From d61255f32a7011e9014e1204471103c719cfd5cb Mon Sep 17 00:00:00 2001 From: Lior Goldberg Date: Sun, 28 Aug 2022 21:52:20 +0300 Subject: [PATCH] Cairo v0.10.0. --- CMakeLists.txt | 4 +- Dockerfile | 5 +- README.md | 4 +- build.sh | 2 +- scripts/requirements-deps.json | 264 +- scripts/requirements.txt | 71 +- src/cmake_utils/CMakeLists.txt | 2 - src/cmake_utils/cmake_rules.cmake | 2 +- src/cmake_utils/gen_pip_cmake.py | 7 +- src/cmake_utils/gen_py_lib.py | 2 +- src/cmake_utils/gen_solidity_env.py | 22 +- src/cmake_utils/gen_venv.py | 8 +- src/cmake_utils/python_rules.cmake | 2 +- src/cmake_utils/solidity_rules.cmake | 12 +- src/demo/amm_demo/amm.cairo | 425 +- .../everest/api/feeder_gateway/CMakeLists.txt | 2 +- .../everest/api/gateway/CMakeLists.txt | 14 +- .../everest/api/gateway/set_config_request.py | 89 + .../everest/business_logic/CMakeLists.txt | 14 +- .../business_logic/internal_transaction.py | 5 +- src/services/everest/business_logic/state.py | 34 +- .../everest/business_logic/state_api.py | 7 + .../everest/definitions/CMakeLists.txt | 2 +- src/services/everest/definitions/fields.py | 5 +- src/services/external_api/CMakeLists.txt | 2 +- src/services/external_api/client.py | 6 +- src/starkware/cairo/CMakeLists.txt | 2 + .../bootloaders/bootloader/bootloader.cairo | 402 +- .../simple_bootloader/execute_task.cairo | 186 +- .../run_simple_bootloader.cairo | 192 +- .../simple_bootloader/simple_bootloader.cairo | 17 +- .../inner_select_builtins.cairo | 98 +- .../builtin_selection/select_builtins.cairo | 22 +- .../select_input_builtins.cairo | 50 +- .../builtin_selection/validate_builtins.cairo | 84 +- .../cairo/cairo_verifier/CMakeLists.txt | 45 + .../layouts/recursive/cairo_verifier.cairo | 206 + .../layouts/recursive/program_hash.json | 3 + .../layouts/recursive/program_hash_test.py | 25 + .../cairo/cairo_verifier/objects.cairo | 8 +- src/starkware/cairo/common/CMakeLists.txt | 29 +- src/starkware/cairo/common/alloc.cairo | 10 +- src/starkware/cairo/common/bitwise.cairo | 176 +- src/starkware/cairo/common/bool.cairo | 6 +- .../cairo/common/cairo_blake2s/CMakeLists.txt | 16 + .../cairo/common/cairo_blake2s/blake2s.cairo | 942 +- .../common/cairo_blake2s/blake2s_test.cairo | 34 +- .../common/cairo_blake2s/packed_blake2s.cairo | 396 +- .../cairo/common/cairo_builtins.cairo | 59 +- .../cairo/common/cairo_function_runner.py | 15 + .../cairo/common/cairo_keccak/keccak.cairo | 870 +- .../common/cairo_keccak/packed_keccak.cairo | 1104 +- .../cairo/common/cairo_secp/bigint.cairo | 198 +- .../cairo/common/cairo_secp/constants.cairo | 43 +- .../cairo/common/cairo_secp/ec.cairo | 392 +- .../cairo/common/cairo_secp/field.cairo | 219 +- .../cairo/common/cairo_secp/signature.cairo | 332 +- src/starkware/cairo/common/default_dict.cairo | 54 +- src/starkware/cairo/common/dict.cairo | 102 +- src/starkware/cairo/common/dict_access.cairo | 20 +- src/starkware/cairo/common/ec.cairo | 386 +- src/starkware/cairo/common/ec_point.cairo | 10 +- src/starkware/cairo/common/find_element.cairo | 136 +- src/starkware/cairo/common/hash.cairo | 34 +- src/starkware/cairo/common/hash_chain.cairo | 64 +- src/starkware/cairo/common/hash_state.cairo | 241 +- src/starkware/cairo/common/invoke.cairo | 38 +- src/starkware/cairo/common/keccak.cairo | 140 +- src/starkware/cairo/common/keccak_state.cairo | 11 + src/starkware/cairo/common/math.cairo | 561 +- src/starkware/cairo/common/math_cmp.cairo | 131 +- src/starkware/cairo/common/memcpy.cairo | 46 +- src/starkware/cairo/common/memset.cairo | 42 +- .../cairo/common/merkle_multi_update.cairo | 171 +- .../cairo/common/merkle_update.cairo | 81 +- src/starkware/cairo/common/patricia.cairo | 686 +- src/starkware/cairo/common/pow.cairo | 82 +- src/starkware/cairo/common/registers.cairo | 44 +- src/starkware/cairo/common/segments.cairo | 18 +- src/starkware/cairo/common/serialize.cairo | 88 +- src/starkware/cairo/common/set.cairo | 84 +- src/starkware/cairo/common/signature.cairo | 91 +- .../cairo/common/small_merkle_tree.cairo | 110 +- src/starkware/cairo/common/squash_dict.cairo | 334 +- src/starkware/cairo/common/uint256.cairo | 763 +- src/starkware/cairo/common/usort.cairo | 90 +- src/starkware/cairo/common/validate_utils.py | 11 + src/starkware/cairo/lang/CMakeLists.txt | 1 + src/starkware/cairo/lang/VERSION | 2 +- .../cairo/lang/builtins/CMakeLists.txt | 26 +- .../cairo/lang/builtins/all_builtins.py | 2 + .../bitwise/bitwise_builtin_runner.py | 3 +- .../cairo/lang/builtins/ec/CMakeLists.txt | 15 + .../lang/builtins/ec/ec_op_builtin_runner.py | 8 +- .../builtins/ec/ec_op_builtin_runner_test.py | 28 +- .../lang/builtins/hash/hash_builtin_runner.py | 3 +- .../builtins/keccak/keccak_builtin_runner.py | 100 + .../lang/builtins/range_check/CMakeLists.txt | 13 + .../range_check_builtin_runner_test.py | 8 +- .../lang/builtins/signature/CMakeLists.txt | 14 + .../signature/signature_builtin_runner.py | 8 +- .../signature_builtin_runner_test.py | 10 +- .../cairo/lang/cairo_cmake_rules.cmake | 2 - .../cairo/lang/compiler/CMakeLists.txt | 17 +- .../cairo/lang/compiler/assembler.py | 2 + .../cairo/lang/compiler/assembler_test.py | 3 + .../cairo/lang/compiler/ast/CMakeLists.txt | 12 + .../cairo/lang/compiler/ast/cairo_types.py | 80 +- .../cairo/lang/compiler/ast/code_elements.py | 185 +- src/starkware/cairo/lang/compiler/ast/expr.py | 125 +- .../cairo/lang/compiler/ast/expr_func_call.py | 7 +- .../lang/compiler/ast/formatting_utils.py | 34 +- .../compiler/ast/formatting_utils_test.py | 36 +- .../cairo/lang/compiler/ast/instructions.py | 2 +- .../cairo/lang/compiler/ast/notes.py | 14 +- .../cairo/lang/compiler/ast/rvalue.py | 33 +- .../cairo/lang/compiler/ast/types.py | 2 +- .../cairo/lang/compiler/ast/visitor.py | 9 +- .../cairo/lang/compiler/ast_objects_test.py | 564 +- src/starkware/cairo/lang/compiler/cairo.ebnf | 52 +- .../cairo/lang/compiler/cairo_compile.py | 11 +- .../cairo/lang/compiler/cairo_compile_test.py | 36 +- .../cairo/lang/compiler/cairo_format.py | 46 +- .../cairo/lang/compiler/debug_info.py | 3 +- .../cairo/lang/compiler/encode_test.py | 2 +- .../filter_unused_identifiers_test.py | 24 +- .../lang/compiler/identifier_definition.py | 29 +- .../compiler/identifier_manager_field_test.py | 3 +- .../cairo/lang/compiler/import_loader_test.py | 32 +- src/starkware/cairo/lang/compiler/injector.py | 7 +- .../cairo/lang/compiler/injector_test.py | 50 +- .../lang/compiler/instruction_builder_test.py | 18 +- .../cairo/lang/compiler/lib/registers.cairo | 31 +- .../lang/compiler/offset_reference_test.py | 2 +- .../cairo/lang/compiler/parser_errors_test.py | 73 +- .../cairo/lang/compiler/parser_test.py | 275 +- .../cairo/lang/compiler/parser_transformer.py | 40 +- .../lang/compiler/preprocessor/CMakeLists.txt | 26 + .../preprocessor/auxiliary_info_collector.py | 30 +- .../preprocessor/bool_expr/CMakeLists.txt | 13 + .../preprocessor/bool_expr/lowering.py | 8 +- .../preprocessor/bool_expr/lowering_test.py | 140 +- .../preprocessor/compound_expressions.py | 48 +- .../preprocessor/compound_expressions_test.py | 298 +- .../compiler/preprocessor/dependency_graph.py | 3 - .../preprocessor/dependency_graph_test.py | 110 +- .../cairo/lang/compiler/preprocessor/flow.py | 5 +- .../preprocessor/identifier_aware_visitor.py | 77 +- .../preprocessor/identifier_collector.py | 31 +- .../preprocessor/identifier_collector_test.py | 49 +- .../compiler/preprocessor/if_labels_test.py | 72 +- .../compiler/preprocessor/local_variables.py | 6 +- .../preprocessor/local_variables_test.py | 270 +- .../compiler/preprocessor/memento_test.py | 46 +- .../compiler/preprocessor/pass_manager.py | 13 +- .../compiler/preprocessor/preprocessor.py | 207 +- .../preprocessor/preprocessor_test.py | 4627 ++++--- .../preprocessor/preprocessor_test_utils.py | 8 +- .../compiler/preprocessor/struct_collector.py | 27 +- .../preprocessor/struct_collector_test.py | 70 +- src/starkware/cairo/lang/compiler/program.py | 44 +- .../cairo/lang/compiler/references.py | 21 +- .../lang/compiler/substitute_identifiers.py | 43 +- .../cairo/lang/compiler/type_casts.py | 4 +- .../cairo/lang/compiler/type_casts_test.py | 18 +- .../cairo/lang/compiler/type_system.py | 14 +- .../lang/compiler/type_system_visitor.py | 43 +- .../lang/compiler/type_system_visitor_test.py | 53 +- .../cairo/lang/compiler/type_utils.py | 2 +- .../cairo/lang/compiler/type_utils_test.py | 34 +- .../cairo/lang/ide/vim/syntax/cairo.vim | 6 +- .../vscode-cairo/language-configuration.json | 2 +- .../cairo/lang/ide/vscode-cairo/package.json | 2 +- .../cairo/lang/ide/vscode-cairo/snippets.json | 14 +- .../syntaxes/cairo.tmLanguage.json | 48 +- src/starkware/cairo/lang/instances.py | 120 + src/starkware/cairo/lang/lang.cmake | 4 +- .../cairo/lang/migrators/CMakeLists.txt | 35 + .../lang/migrators}/__init__.py | 0 .../cairo/lang/migrators/migrator.py | 305 + .../lang/migrators/migrator_grammar.ebnf | 178 + .../cairo/lang/migrators/migrator_test.py | 179 + .../cairo/lang/package_test/main.cairo | 10 +- .../cairo/lang/package_test/run_test.sh | 4 +- .../cairo/lang/scripts/CMakeLists.txt | 2 + src/starkware/cairo/lang/scripts/cairo-format | 2 +- .../cairo/lang/scripts/cairo-migrate | 10 + src/starkware/cairo/lang/setup.py | 2 + .../cairo/lang/tracer/tracer_data_test.py | 22 +- src/starkware/cairo/lang/vm/CMakeLists.txt | 3 +- .../cairo/lang/vm/air_public_input.py | 7 +- src/starkware/cairo/lang/vm/builtin_runner.py | 24 +- src/starkware/cairo/lang/vm/cairo_pie.py | 19 +- src/starkware/cairo/lang/vm/cairo_pie_test.py | 31 +- src/starkware/cairo/lang/vm/cairo_run.py | 30 +- src/starkware/cairo/lang/vm/cairo_runner.py | 13 +- .../cairo/lang/vm/cairo_runner_test.py | 79 +- .../cairo/lang/vm/memory_dict_test.py | 2 + .../cairo/lang/vm/memory_segments_test.py | 18 +- .../lang/vm/output_builtin_runner_test.py | 6 +- .../lang/vm/reconstruct_traceback_test.py | 44 +- src/starkware/cairo/lang/vm/relocatable.py | 6 +- .../cairo/lang/vm/relocatable_fields_test.py | 9 +- src/starkware/cairo/lang/vm/security_test.py | 59 +- src/starkware/cairo/lang/vm/test.cairo | 18 +- .../cairo/lang/vm/trace_entry_test.py | 2 +- .../cairo/lang/vm/virtual_machine_base.py | 32 +- src/starkware/cairo/lang/vm/vm_consts_test.py | 4 +- src/starkware/cairo/lang/vm/vm_core.py | 2 + src/starkware/cairo/lang/vm/vm_test.py | 464 +- .../cairo/sharp/sharp_client_test.py | 10 +- .../cairo/stark_verifier/CMakeLists.txt | 2 + .../stark_verifier}/__init__.py | 0 .../cairo/stark_verifier/air/CMakeLists.txt | 45 + .../cairo/stark_verifier/air/__init__.py | 0 .../cairo/stark_verifier/air/config.cairo | 25 + .../cairo/stark_verifier/air/diluted.cairo | 59 + .../stark_verifier/air/example_proof.json | 4623 +++++++ .../cairo/stark_verifier/air/layout.cairo | 32 + .../stark_verifier/air/layouts/CMakeLists.txt | 21 + .../air/layouts/bitwise/autogenerated.cairo | 1559 +++ .../air/layouts/bitwise/composition.cairo | 136 + .../air/layouts/bitwise/global_values.cairo | 64 + .../layouts/bitwise/periodic_columns.cairo | 1571 +++ .../air/layouts/bitwise/public_verify.cairo | 115 + .../air/layouts/bitwise/verify.cairo | 71 + .../air/layouts/dex/autogenerated.cairo | 1794 +++ .../air/layouts/dex/composition.cairo | 121 + .../air/layouts/dex/global_values.cairo | 54 + .../air/layouts/dex/periodic_columns.cairo | 1571 +++ .../air/layouts/dex/public_verify.cairo | 106 + .../air/layouts/dex/verify.cairo | 73 + .../autogenerated.cairo | 1902 +++ .../perpetual_with_bitwise/composition.cairo | 141 + .../global_values.cairo | 71 + .../periodic_columns.cairo | 1571 +++ .../public_verify.cairo | 124 + .../perpetual_with_bitwise/verify.cairo | 75 + .../air/layouts/recursive/autogenerated.cairo | 11044 ++++++++++++++++ .../air/layouts/recursive/composition.cairo | 150 + .../air/layouts/recursive/global_values.cairo | 62 + .../layouts/recursive/periodic_columns.cairo | 1858 +++ .../air/layouts/recursive/public_verify.cairo | 114 + .../air/layouts/recursive/verify.cairo | 71 + .../cairo/stark_verifier/air/oods.cairo | 103 + .../cairo/stark_verifier/air/params.cairo | 2 + .../cairo/stark_verifier/air/parser.py | 289 + .../stark_verifier/air/public_input.cairo | 157 + .../stark_verifier/air/public_memory.cairo | 49 + .../cairo/stark_verifier/air/stark_test.py | 49 + .../cairo/stark_verifier/air/traces.cairo | 130 + .../cairo/stark_verifier/air/utils.py | 98 + .../cairo/stark_verifier/core/CMakeLists.txt | 52 + .../cairo/stark_verifier/core/__init__.py | 0 .../stark_verifier/core/air_interface.cairo | 110 + .../cairo/stark_verifier/core/channel.cairo | 197 + .../stark_verifier/core/channel_test.cairo | 86 + .../cairo/stark_verifier/core/channel_test.py | 27 + .../cairo/stark_verifier/core/config.cairo | 99 + .../cairo/stark_verifier/core/domains.cairo | 15 + .../stark_verifier/core/fri/CMakeLists.txt | 30 + .../cairo/stark_verifier/core/fri/__init__.py | 0 .../stark_verifier/core/fri/config.cairo | 63 + .../cairo/stark_verifier/core/fri/fri.cairo | 325 + .../stark_verifier/core/fri/fri_formula.cairo | 81 + .../core/fri/fri_formula_test.py | 58 + .../stark_verifier/core/fri/fri_layer.cairo | 175 + .../stark_verifier/core/fri/fri_layer_test.py | 160 + .../cairo/stark_verifier/core/fri/fri_test.py | 71 + .../stark_verifier/core/fri/test_utils.py | 44 + .../stark_verifier/core/merkle_test_data.json | 301 + .../stark_verifier/core/proof_of_work.cairo | 92 + .../stark_verifier/core/proof_of_work_test.py | 58 + .../cairo/stark_verifier/core/queries.cairo | 97 + .../cairo/stark_verifier/core/stark.cairo | 376 + .../core/table_commitment.cairo | 160 + .../core/table_commitment_test.py | 86 + .../cairo/stark_verifier/core/utils.cairo | 32 + .../cairo/stark_verifier/core/utils_test.py | 35 + .../core/vector_commitment.cairo | 164 + .../core/vector_commitment_test.py | 93 + src/starkware/crypto/CMakeLists.txt | 14 +- src/starkware/crypto/__init__.py | 0 src/starkware/crypto/signature/__init__.py | 0 .../signature/fast_pedersen_hash.py | 2 +- .../crypto => }/signature/math_utils.py | 0 .../signature/nothing_up_my_sleeve_gen.py | 0 .../signature/pedersen_params.json | 0 .../crypto => }/signature/signature.py | 0 src/starkware/eth/eth_test_utils.py | 3 + src/starkware/python/CMakeLists.txt | 1 + src/starkware/python/math_utils.py | 45 +- src/starkware/python/math_utils_test.py | 28 + src/starkware/python/utils.py | 144 +- src/starkware/python/utils_test.py | 75 + src/starkware/solidity/CMakeLists.txt | 2 + .../solidity/components/CMakeLists.txt | 24 + .../solidity/components/FactRegistry.sol | 46 + .../solidity/components/GenericGovernance.sol | 42 + .../solidity/components/Governance.sol | 108 + .../solidity/components/GovernanceStorage.sol | 11 + .../components/GovernedFinalizable.sol | 29 + .../components/OnchainDataFactTreeEncoder.sol | 50 + .../solidity/components/Operator.sol | 33 + .../solidity/interfaces/BlockDirectCall.sol | 21 + .../solidity/interfaces/CMakeLists.txt | 28 + .../interfaces/ContractInitializer.sol | 38 + .../interfaces/ExternalInitializer.sol | 8 + .../solidity/interfaces/IFactRegistry.sol | 24 + .../interfaces/IQueryableFactRegistry.sol | 15 + .../solidity/interfaces/Identity.sol | 9 + .../solidity/interfaces/MGovernance.sol | 14 + .../solidity/interfaces/MOperator.sol | 22 + .../solidity/interfaces/ProxySupport.sol | 78 + .../solidity/libraries/Addresses.sol | 42 + .../solidity/libraries/CMakeLists.txt | 6 + src/starkware/solidity/utils.py | 12 +- .../starknet/apps/amm_sample/amm_sample.cairo | 249 +- .../starknet/business_logic/CMakeLists.txt | 79 +- .../business_logic/execution/CMakeLists.txt | 8 +- .../execution/execute_entry_point.py | 159 +- .../execution/execute_entry_point_base.py | 24 +- .../business_logic/execution/gas_usage.py | 16 +- .../business_logic/execution/objects.py | 139 +- .../execution/os_resources.json | 163 +- .../business_logic/execution/os_usage.py | 36 +- .../business_logic/fact_state/CMakeLists.txt | 47 + .../contract_state_objects.py} | 148 +- .../fact_state/patricia_state.py | 90 + .../business_logic/fact_state/state.py | 427 + .../internal_transaction_interface.py | 72 - .../business_logic/state/CMakeLists.txt | 14 +- .../starknet/business_logic/state/state.py | 714 +- .../business_logic/state/state_api.py | 135 + .../business_logic/state/state_api_objects.py | 84 + .../business_logic/transaction/CMakeLists.txt | 80 + .../fee.py} | 66 +- .../objects.py} | 803 +- .../transaction/state_objects.py | 96 + .../starknet/business_logic/utils.py | 234 +- src/starkware/starknet/cli/CMakeLists.txt | 2 + .../reconstruct_starknet_traceback_test.py | 26 +- src/starkware/starknet/cli/starknet_cli.py | 549 +- src/starkware/starknet/common/CMakeLists.txt | 3 +- src/starkware/starknet/common/constants.cairo | 8 + src/starkware/starknet/common/eth_utils.cairo | 20 +- .../starknet/common/eth_utils_test.py | 4 +- src/starkware/starknet/common/messages.cairo | 14 +- src/starkware/starknet/common/storage.cairo | 82 +- src/starkware/starknet/common/syscalls.cairo | 781 +- .../starknet/compiler/CMakeLists.txt | 22 +- src/starkware/starknet/compiler/compile.py | 4 + .../starknet/compiler/compiler.cmake | 18 + .../starknet/compiler/contract_interface.py | 56 +- .../compiler/contract_interface_test.py | 304 +- .../starknet/compiler/data_encoder.py | 67 +- .../starknet/compiler/data_encoder_test.py | 94 +- src/starkware/starknet/compiler/event.py | 34 +- src/starkware/starknet/compiler/event_test.py | 191 +- .../starknet/compiler/external_wrapper.py | 151 +- .../compiler/external_wrapper_test.py | 683 +- .../compiler/starknet_pass_manager.py | 6 +- .../compiler/starknet_preprocessor.py | 3 +- .../compiler/starknet_preprocessor_test.py | 116 +- .../starknet/compiler/storage_var.py | 150 +- .../starknet/compiler/storage_var_test.py | 437 +- src/starkware/starknet/compiler/test_utils.py | 86 +- .../starknet/compiler/validation_utils.py | 84 +- .../compiler/validation_utils_test.py | 102 + src/starkware/starknet/core/os/CMakeLists.txt | 4 +- .../starknet/core/os/block_context.cairo | 68 +- src/starkware/starknet/core/os/builtins.cairo | 92 +- src/starkware/starknet/core/os/class_hash.py | 9 +- .../contract_address/contract_address.cairo | 36 +- .../starknet/core/os/contracts.cairo | 240 +- src/starkware/starknet/core/os/os.cairo | 88 +- .../starknet/core/os/os_config/CMakeLists.txt | 2 + .../core/os/os_config/os_config.cairo | 52 +- .../core/os/os_config/os_config_hash_test.py | 6 +- src/starkware/starknet/core/os/output.cairo | 164 +- .../starknet/core/os/program_hash.json | 2 +- .../starknet/core/os/program_hash_test.py | 5 +- src/starkware/starknet/core/os/state.cairo | 335 +- .../starknet/core/os/syscall_utils.py | 200 +- .../core/os/transaction_hash/CMakeLists.txt | 4 +- .../transaction_hash/transaction_hash.cairo | 48 +- .../os/transaction_hash/transaction_hash.py | 19 +- .../transaction_hash/transaction_hash_test.py | 16 +- .../starknet/core/os/transactions.cairo | 1605 ++- .../core/test_contract/delegate_proxy.cairo | 50 +- .../core/test_contract/dummy_account.cairo | 58 +- .../starknet/core/test_contract/test_utils.py | 2 +- .../starknet/definitions/CMakeLists.txt | 3 + .../starknet/definitions/constants.py | 7 +- .../starknet/definitions/error_codes.py | 17 +- src/starkware/starknet/definitions/fields.py | 49 +- .../starknet/definitions/general_config.py | 28 +- .../starknet/definitions/general_config.yml | 8 +- .../starknet/definitions/transaction_type.py | 7 +- src/starkware/starknet/public/abi.py | 16 +- src/starkware/starknet/public/abi_structs.py | 4 +- .../starknet/security/CMakeLists.txt | 2 + .../security/latest_whitelist_test.py | 6 +- .../starknet/security/secure_hints.py | 22 +- .../starknet/security/secure_hints_test.py | 74 +- .../starknet/security/starknet_common.cairo | 2 + .../starknet/security/whitelists/latest.json | 125 +- .../starknet/services/CMakeLists.txt | 1 + .../starknet/services/api/CMakeLists.txt | 3 +- .../starknet/services/api/contract_class.py | 5 +- .../api/feeder_gateway/CMakeLists.txt | 19 +- .../feeder_gateway/feeder_gateway_client.py | 75 +- .../api/feeder_gateway/request_objects.py | 55 + .../api/feeder_gateway/response_objects.py | 120 +- .../services/api/gateway/CMakeLists.txt | 1 + .../services/api/gateway/transaction.py | 115 +- .../starknet/services/api/messages.py | 11 +- .../starknet/services/utils/CMakeLists.txt | 19 + .../services/utils/sequencer_api_utils.py | 85 + .../starknet/solidity/CMakeLists.txt | 25 +- .../starknet/solidity/IStarknetMessaging.sol | 7 +- .../solidity/IStarknetMessagingEvents.sol | 3 +- src/starkware/starknet/solidity/Output.sol | 165 + src/starkware/starknet/solidity/Starknet.sol | 203 + .../starknet/solidity/StarknetGovernance.sol | 38 + .../starknet/solidity/StarknetMessaging.sol | 29 +- .../starknet/solidity/StarknetOperator.sol | 13 + .../starknet/solidity/StarknetState.sol | 36 + .../starknet/solidity/solidity.cmake | 19 + .../starknet/storage/starknet_storage.py | 7 +- src/starkware/starknet/testing/CMakeLists.txt | 9 +- .../testing/MockStarknetMessaging.sol | 2 +- src/starkware/starknet/testing/contract.py | 58 +- .../starknet/testing/contract_test.py | 41 +- src/starkware/starknet/testing/objects.py | 22 +- src/starkware/starknet/testing/postman.py | 6 +- .../starknet/testing/postman_test.py | 15 +- src/starkware/starknet/testing/starknet.py | 41 +- .../starknet/testing/starknet_test.py | 39 +- src/starkware/starknet/testing/state.py | 160 +- src/starkware/starknet/testing/test.cairo | 136 +- .../testing/test_unwhitelisted_hint.cairo | 6 +- .../third_party/open_zeppelin/Account.cairo | 383 +- .../open_zeppelin/utils/constants.cairo | 30 +- src/starkware/starknet/utils/api_utils.py | 2 +- src/starkware/starknet/wallets/CMakeLists.txt | 2 + src/starkware/starknet/wallets/account.py | 23 +- .../starknet/wallets/open_zeppelin.py | 102 +- src/starkware/starkware_utils/CMakeLists.txt | 2 +- .../starkware_utils/CMakeLists_common.txt | 34 +- .../commitment_tree/binary_fact_tree.py | 5 +- .../binary_fact_tree_da_utils.py | 2 +- .../commitment_tree/calculation.py | 32 +- .../patricia_tree/virtual_calculation_node.py | 4 +- .../virtual_calculation_node_test.py | 5 +- .../commitment_tree/update_tree.py | 10 +- src/starkware/starkware_utils/config_base.py | 2 +- .../starkware_utils/error_handling.py | 71 +- .../starkware_utils/field_validators.py | 17 +- .../marshmallow_dataclass_fields.py | 61 +- .../marshmallow_fields_metadata.py | 87 + .../time/synchronous_executor.py | 2 +- .../starkware_utils/validated_dataclass.py | 47 +- .../starkware_utils/validated_fields.py | 116 +- src/starkware/storage/storage.py | 18 +- src/starkware/storage/storage_test.py | 3 + src/starkware/storage/test_utils.py | 3 + 467 files changed, 55536 insertions(+), 14985 deletions(-) create mode 100644 src/services/everest/api/gateway/set_config_request.py create mode 100644 src/services/everest/business_logic/state_api.py create mode 100644 src/starkware/cairo/cairo_verifier/CMakeLists.txt create mode 100644 src/starkware/cairo/cairo_verifier/layouts/recursive/cairo_verifier.cairo create mode 100644 src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash.json create mode 100644 src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash_test.py create mode 100644 src/starkware/cairo/common/cairo_blake2s/CMakeLists.txt create mode 100644 src/starkware/cairo/common/keccak_state.cairo create mode 100644 src/starkware/cairo/common/validate_utils.py create mode 100644 src/starkware/cairo/lang/builtins/ec/CMakeLists.txt create mode 100644 src/starkware/cairo/lang/builtins/keccak/keccak_builtin_runner.py create mode 100644 src/starkware/cairo/lang/builtins/range_check/CMakeLists.txt create mode 100644 src/starkware/cairo/lang/builtins/signature/CMakeLists.txt create mode 100644 src/starkware/cairo/lang/compiler/ast/CMakeLists.txt create mode 100644 src/starkware/cairo/lang/compiler/preprocessor/CMakeLists.txt create mode 100644 src/starkware/cairo/lang/compiler/preprocessor/bool_expr/CMakeLists.txt create mode 100644 src/starkware/cairo/lang/migrators/CMakeLists.txt rename src/starkware/{crypto/starkware/crypto => cairo/lang/migrators}/__init__.py (100%) create mode 100644 src/starkware/cairo/lang/migrators/migrator.py create mode 100644 src/starkware/cairo/lang/migrators/migrator_grammar.ebnf create mode 100644 src/starkware/cairo/lang/migrators/migrator_test.py create mode 100755 src/starkware/cairo/lang/scripts/cairo-migrate create mode 100644 src/starkware/cairo/stark_verifier/CMakeLists.txt rename src/starkware/{crypto/starkware/crypto/signature => cairo/stark_verifier}/__init__.py (100%) create mode 100644 src/starkware/cairo/stark_verifier/air/CMakeLists.txt create mode 100644 src/starkware/cairo/stark_verifier/air/__init__.py create mode 100644 src/starkware/cairo/stark_verifier/air/config.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/diluted.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/example_proof.json create mode 100644 src/starkware/cairo/stark_verifier/air/layout.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/CMakeLists.txt create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/bitwise/autogenerated.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/bitwise/composition.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/bitwise/global_values.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/bitwise/periodic_columns.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/bitwise/public_verify.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/bitwise/verify.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/dex/autogenerated.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/dex/composition.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/dex/global_values.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/dex/periodic_columns.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/dex/public_verify.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/dex/verify.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/autogenerated.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/composition.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/global_values.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/periodic_columns.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/public_verify.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/verify.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/recursive/autogenerated.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/recursive/composition.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/recursive/global_values.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/recursive/periodic_columns.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/recursive/public_verify.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/layouts/recursive/verify.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/oods.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/params.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/parser.py create mode 100644 src/starkware/cairo/stark_verifier/air/public_input.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/public_memory.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/stark_test.py create mode 100644 src/starkware/cairo/stark_verifier/air/traces.cairo create mode 100644 src/starkware/cairo/stark_verifier/air/utils.py create mode 100644 src/starkware/cairo/stark_verifier/core/CMakeLists.txt create mode 100644 src/starkware/cairo/stark_verifier/core/__init__.py create mode 100644 src/starkware/cairo/stark_verifier/core/air_interface.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/channel.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/channel_test.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/channel_test.py create mode 100644 src/starkware/cairo/stark_verifier/core/config.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/domains.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/fri/CMakeLists.txt create mode 100644 src/starkware/cairo/stark_verifier/core/fri/__init__.py create mode 100644 src/starkware/cairo/stark_verifier/core/fri/config.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/fri/fri.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/fri/fri_formula.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/fri/fri_formula_test.py create mode 100644 src/starkware/cairo/stark_verifier/core/fri/fri_layer.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/fri/fri_layer_test.py create mode 100644 src/starkware/cairo/stark_verifier/core/fri/fri_test.py create mode 100644 src/starkware/cairo/stark_verifier/core/fri/test_utils.py create mode 100644 src/starkware/cairo/stark_verifier/core/merkle_test_data.json create mode 100644 src/starkware/cairo/stark_verifier/core/proof_of_work.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/proof_of_work_test.py create mode 100644 src/starkware/cairo/stark_verifier/core/queries.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/stark.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/table_commitment.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/table_commitment_test.py create mode 100644 src/starkware/cairo/stark_verifier/core/utils.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/utils_test.py create mode 100644 src/starkware/cairo/stark_verifier/core/vector_commitment.cairo create mode 100644 src/starkware/cairo/stark_verifier/core/vector_commitment_test.py create mode 100644 src/starkware/crypto/__init__.py create mode 100644 src/starkware/crypto/signature/__init__.py rename src/starkware/crypto/{starkware/crypto => }/signature/fast_pedersen_hash.py (95%) rename src/starkware/crypto/{starkware/crypto => }/signature/math_utils.py (100%) rename src/starkware/crypto/{starkware/crypto => }/signature/nothing_up_my_sleeve_gen.py (100%) rename src/starkware/crypto/{starkware/crypto => }/signature/pedersen_params.json (100%) rename src/starkware/crypto/{starkware/crypto => }/signature/signature.py (100%) create mode 100644 src/starkware/solidity/components/CMakeLists.txt create mode 100644 src/starkware/solidity/components/FactRegistry.sol create mode 100644 src/starkware/solidity/components/GenericGovernance.sol create mode 100644 src/starkware/solidity/components/Governance.sol create mode 100644 src/starkware/solidity/components/GovernanceStorage.sol create mode 100644 src/starkware/solidity/components/GovernedFinalizable.sol create mode 100644 src/starkware/solidity/components/OnchainDataFactTreeEncoder.sol create mode 100644 src/starkware/solidity/components/Operator.sol create mode 100644 src/starkware/solidity/interfaces/BlockDirectCall.sol create mode 100644 src/starkware/solidity/interfaces/CMakeLists.txt create mode 100644 src/starkware/solidity/interfaces/ContractInitializer.sol create mode 100644 src/starkware/solidity/interfaces/ExternalInitializer.sol create mode 100644 src/starkware/solidity/interfaces/IFactRegistry.sol create mode 100644 src/starkware/solidity/interfaces/IQueryableFactRegistry.sol create mode 100644 src/starkware/solidity/interfaces/Identity.sol create mode 100644 src/starkware/solidity/interfaces/MGovernance.sol create mode 100644 src/starkware/solidity/interfaces/MOperator.sol create mode 100644 src/starkware/solidity/interfaces/ProxySupport.sol create mode 100644 src/starkware/solidity/libraries/Addresses.sol create mode 100644 src/starkware/starknet/business_logic/fact_state/CMakeLists.txt rename src/starkware/starknet/business_logic/{state/objects.py => fact_state/contract_state_objects.py} (61%) create mode 100644 src/starkware/starknet/business_logic/fact_state/patricia_state.py create mode 100644 src/starkware/starknet/business_logic/fact_state/state.py delete mode 100644 src/starkware/starknet/business_logic/internal_transaction_interface.py create mode 100644 src/starkware/starknet/business_logic/state/state_api.py create mode 100644 src/starkware/starknet/business_logic/state/state_api_objects.py create mode 100644 src/starkware/starknet/business_logic/transaction/CMakeLists.txt rename src/starkware/starknet/business_logic/{transaction_fee.py => transaction/fee.py} (57%) rename src/starkware/starknet/business_logic/{internal_transaction.py => transaction/objects.py} (53%) create mode 100644 src/starkware/starknet/business_logic/transaction/state_objects.py create mode 100644 src/starkware/starknet/common/constants.cairo create mode 100644 src/starkware/starknet/compiler/compiler.cmake create mode 100644 src/starkware/starknet/compiler/validation_utils_test.py create mode 100644 src/starkware/starknet/services/api/feeder_gateway/request_objects.py create mode 100644 src/starkware/starknet/services/utils/CMakeLists.txt create mode 100644 src/starkware/starknet/services/utils/sequencer_api_utils.py create mode 100644 src/starkware/starknet/solidity/Output.sol create mode 100644 src/starkware/starknet/solidity/Starknet.sol create mode 100644 src/starkware/starknet/solidity/StarknetGovernance.sol create mode 100644 src/starkware/starknet/solidity/StarknetOperator.sol create mode 100644 src/starkware/starknet/solidity/StarknetState.sol create mode 100644 src/starkware/starknet/solidity/solidity.cmake create mode 100644 src/starkware/starkware_utils/marshmallow_fields_metadata.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c01a40a..42f8f54d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.22) -set (PYTHON_COMMAND python3.7) +set (PYTHON_COMMAND python3.9) project(CairoLang VERSION 0.1.0) include(CTest) @@ -15,8 +15,8 @@ endif() find_program(PYTHON "python3") include("src/cmake_utils/cmake_rules.cmake") +include("src/cmake_utils/solidity_rules.cmake") include("src/starkware/cairo/lang/cairo_cmake_rules.cmake") include("src/starkware/starknet/compiler/starknet_cmake_rules.cmake") -# Repos needs to be first as it defines macros that are needed by src. add_subdirectory(src) diff --git a/Dockerfile b/Dockerfile index 36673778..66c63f97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,7 @@ -FROM ciimage/python:3.7 +FROM ciimage/python:3.9 RUN apt update -RUN apt -y -o Dpkg::Options::="--force-overwrite" install python3.7-dev -RUN apt install -y make libgmp3-dev g++ python3-pip python3.7-venv npm +RUN apt install -y make libgmp3-dev g++ python3-pip python3.9-dev python3.9-venv npm # Installing cmake via apt doesn't bring the most up-to-date version. RUN pip install cmake==3.22 diff --git a/README.md b/README.md index 07803bdc..415ec225 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ We recommend starting from [Setting up the environment](https://cairo-lang.org/d # Installation instructions You should be able to download the python package zip file directly from -[github](https://github.com/starkware-libs/cairo-lang/releases/tag/v0.5.2) +[github](https://github.com/starkware-libs/cairo-lang/releases/tag/v0.10.0) and install it using ``pip``. See [Setting up the environment](https://cairo-lang.org/docs/quickstart.html). @@ -54,7 +54,7 @@ Once the docker image is built, you can fetch the python package zip file using: ```bash > container_id=$(docker create cairo) -> docker cp ${container_id}:/app/cairo-lang-0.9.1.zip . +> docker cp ${container_id}:/app/cairo-lang-0.10.0.zip . > docker rm -v ${container_id} ``` diff --git a/build.sh b/build.sh index 943d71b8..b278d7e6 100755 --- a/build.sh +++ b/build.sh @@ -12,5 +12,5 @@ cp src/starkware/cairo/lang/setup.py ${VENV_SITE_DIR} cp src/starkware/cairo/lang/MANIFEST.in ${VENV_SITE_DIR} cp scripts/requirements-gen.txt ${VENV_SITE_DIR}/requirements.txt cp README.md ${VENV_SITE_DIR} -( cd ${VENV_SITE_DIR}; python3 setup.py sdist --format=zip ) +( cd ${VENV_SITE_DIR}; python3.9 setup.py sdist --format=zip ) cp ${VENV_SITE_DIR}/dist/cairo-lang-$(cat src/starkware/cairo/lang/VERSION).zip . diff --git a/scripts/requirements-deps.json b/scripts/requirements-deps.json index 060c7c86..14b72073 100644 --- a/scripts/requirements-deps.json +++ b/scripts/requirements-deps.json @@ -22,25 +22,19 @@ "required_version": ">=4.0.0a3,<5.0" }, { - "installed_version": "0.13.0", - "key": "asynctest", - "package_name": "asynctest", - "required_version": "==0.13.0" - }, - { - "installed_version": "21.4.0", + "installed_version": "22.1.0", "key": "attrs", "package_name": "attrs", "required_version": ">=17.3.0" }, { - "installed_version": "2.0.11", + "installed_version": "2.1.1", "key": "charset-normalizer", "package_name": "charset-normalizer", "required_version": ">=2.0,<3.0" }, { - "installed_version": "1.3.0", + "installed_version": "1.3.1", "key": "frozenlist", "package_name": "frozenlist", "required_version": ">=1.1.1" @@ -52,13 +46,7 @@ "required_version": ">=4.5,<7.0" }, { - "installed_version": "4.0.1", - "key": "typing-extensions", - "package_name": "typing-extensions", - "required_version": ">=3.7.4" - }, - { - "installed_version": "1.7.2", + "installed_version": "1.8.1", "key": "yarl", "package_name": "yarl", "required_version": ">=1.0,<2.0" @@ -73,7 +61,7 @@ { "dependencies": [ { - "installed_version": "1.3.0", + "installed_version": "1.3.1", "key": "frozenlist", "package_name": "frozenlist", "required_version": ">=1.1.0" @@ -86,14 +74,7 @@ } }, { - "dependencies": [ - { - "installed_version": "4.0.1", - "key": "typing-extensions", - "package_name": "typing-extensions", - "required_version": ">=3.6.5" - } - ], + "dependencies": [], "package": { "installed_version": "4.0.2", "key": "async-timeout", @@ -103,15 +84,7 @@ { "dependencies": [], "package": { - "installed_version": "0.13.0", - "key": "asynctest", - "package_name": "asynctest" - } - }, - { - "dependencies": [], - "package": { - "installed_version": "21.4.0", + "installed_version": "22.1.0", "key": "attrs", "package_name": "attrs" } @@ -127,7 +100,7 @@ { "dependencies": [], "package": { - "installed_version": "1.2.2", + "installed_version": "2.6.0", "key": "bitarray", "package_name": "bitarray" } @@ -135,7 +108,7 @@ { "dependencies": [], "package": { - "installed_version": "5.0.0", + "installed_version": "5.2.0", "key": "cachetools", "package_name": "cachetools" } @@ -143,7 +116,7 @@ { "dependencies": [], "package": { - "installed_version": "2021.10.8", + "installed_version": "2022.6.15", "key": "certifi", "package_name": "certifi" } @@ -151,7 +124,7 @@ { "dependencies": [], "package": { - "installed_version": "2.0.11", + "installed_version": "2.1.1", "key": "charset-normalizer", "package_name": "charset-normalizer" } @@ -159,14 +132,14 @@ { "dependencies": [ { - "installed_version": "0.11.2", + "installed_version": "0.12.0", "key": "toolz", "package_name": "toolz", "required_version": ">=0.8.0" } ], "package": { - "installed_version": "0.11.2", + "installed_version": "0.12.0", "key": "cytoolz", "package_name": "cytoolz" } @@ -181,7 +154,7 @@ } ], "package": { - "installed_version": "0.17.0", + "installed_version": "0.18.0", "key": "ecdsa", "package_name": "ecdsa" } @@ -195,7 +168,7 @@ "required_version": ">=2.0.0,<3.0.0" }, { - "installed_version": "1.10.0", + "installed_version": "1.9.5", "key": "eth-utils", "package_name": "eth-utils", "required_version": ">=1.2.0,<2.0.0" @@ -208,7 +181,7 @@ } ], "package": { - "installed_version": "2.1.1", + "installed_version": "2.2.0", "key": "eth-abi", "package_name": "eth-abi" } @@ -216,13 +189,13 @@ { "dependencies": [ { - "installed_version": "1.2.2", + "installed_version": "2.6.0", "key": "bitarray", "package_name": "bitarray", - "required_version": ">=1.2.1,<1.3.0" + "required_version": ">=1.2.1,<3" }, { - "installed_version": "2.1.1", + "installed_version": "2.2.0", "key": "eth-abi", "package_name": "eth-abi", "required_version": ">=2.0.0b7,<3" @@ -246,13 +219,13 @@ "required_version": ">=0.1.2,<2" }, { - "installed_version": "1.10.0", + "installed_version": "1.9.5", "key": "eth-utils", "package_name": "eth-utils", "required_version": ">=1.3.0,<2" }, { - "installed_version": "0.2.2", + "installed_version": "0.3.0", "key": "hexbytes", "package_name": "hexbytes", "required_version": ">=0.1.0,<1" @@ -265,7 +238,7 @@ } ], "package": { - "installed_version": "0.5.7", + "installed_version": "0.5.9", "key": "eth-account", "package_name": "eth-account" } @@ -273,7 +246,7 @@ { "dependencies": [], "package": { - "installed_version": "0.3.2", + "installed_version": "0.5.0", "key": "eth-hash", "package_name": "eth-hash" } @@ -281,7 +254,7 @@ { "dependencies": [ { - "installed_version": "0.11.2", + "installed_version": "0.12.0", "key": "cytoolz", "package_name": "cytoolz", "required_version": ">=0.9.0,<1.0.0" @@ -293,13 +266,13 @@ "required_version": ">=0.1.0-beta.4,<1.0.0" }, { - "installed_version": "1.10.0", + "installed_version": "1.9.5", "key": "eth-utils", "package_name": "eth-utils", "required_version": ">=1.0.0-beta.1,<2.0.0" }, { - "installed_version": "3.14.1", + "installed_version": "3.15.0", "key": "pycryptodome", "package_name": "pycryptodome", "required_version": ">=3.4.7,<4.0.0" @@ -320,7 +293,7 @@ "required_version": ">=2.2.1,<3.0.0" }, { - "installed_version": "1.10.0", + "installed_version": "1.9.5", "key": "eth-utils", "package_name": "eth-utils", "required_version": ">=1.8.2,<2.0.0" @@ -335,13 +308,13 @@ { "dependencies": [ { - "installed_version": "1.10.0", + "installed_version": "1.9.5", "key": "eth-utils", "package_name": "eth-utils", "required_version": ">=1.0.1,<2" }, { - "installed_version": "0.2.2", + "installed_version": "0.3.0", "key": "hexbytes", "package_name": "hexbytes", "required_version": ">=0.1.0,<1" @@ -370,16 +343,16 @@ { "dependencies": [ { - "installed_version": "0.11.2", + "installed_version": "0.12.0", "key": "cytoolz", "package_name": "cytoolz", "required_version": ">=0.10.1,<1.0.0" }, { - "installed_version": "0.3.2", + "installed_version": "0.5.0", "key": "eth-hash", "package_name": "eth-hash", - "required_version": ">=0.3.1,<0.4.0" + "required_version": ">=0.1.0,<1.0.0" }, { "installed_version": "2.3.0", @@ -389,7 +362,7 @@ } ], "package": { - "installed_version": "1.10.0", + "installed_version": "1.9.5", "key": "eth-utils", "package_name": "eth-utils" } @@ -413,7 +386,7 @@ { "dependencies": [], "package": { - "installed_version": "1.3.0", + "installed_version": "1.3.1", "key": "frozenlist", "package_name": "frozenlist" } @@ -421,7 +394,7 @@ { "dependencies": [], "package": { - "installed_version": "0.2.2", + "installed_version": "0.3.0", "key": "hexbytes", "package_name": "hexbytes" } @@ -434,27 +407,6 @@ "package_name": "idna" } }, - { - "dependencies": [ - { - "installed_version": "4.0.1", - "key": "typing-extensions", - "package_name": "typing-extensions", - "required_version": ">=3.6.4" - }, - { - "installed_version": "3.7.0", - "key": "zipp", - "package_name": "zipp", - "required_version": ">=0.5" - } - ], - "package": { - "installed_version": "4.10.1", - "key": "importlib-metadata", - "package_name": "importlib-metadata" - } - }, { "dependencies": [], "package": { @@ -472,7 +424,7 @@ "required_version": ">=0.0.7" }, { - "installed_version": "2.27.1", + "installed_version": "2.28.1", "key": "requests", "package_name": "requests", "required_version": ">=2.11" @@ -487,17 +439,11 @@ { "dependencies": [ { - "installed_version": "21.4.0", + "installed_version": "22.1.0", "key": "attrs", "package_name": "attrs", "required_version": ">=17.4.0" }, - { - "installed_version": "4.10.1", - "key": "importlib-metadata", - "package_name": "importlib-metadata", - "required_version": null - }, { "installed_version": "0.18.1", "key": "pyrsistent", @@ -505,7 +451,7 @@ "required_version": ">=0.14.0" }, { - "installed_version": "60.5.0", + "installed_version": "63.2.0", "key": "setuptools", "package_name": "setuptools", "required_version": null @@ -534,15 +480,22 @@ { "dependencies": [], "package": { - "installed_version": "1.1.7", + "installed_version": "1.1.8", "key": "lru-dict", "package_name": "lru-dict" } }, { - "dependencies": [], + "dependencies": [ + { + "installed_version": "21.3", + "key": "packaging", + "package_name": "packaging", + "required_version": ">=17.0" + } + ], "package": { - "installed_version": "3.14.1", + "installed_version": "3.17.1", "key": "marshmallow", "package_name": "marshmallow" } @@ -550,20 +503,20 @@ { "dependencies": [ { - "installed_version": "3.14.1", + "installed_version": "3.17.1", "key": "marshmallow", "package_name": "marshmallow", "required_version": ">=3.13.0,<4.0" }, { - "installed_version": "0.7.1", + "installed_version": "0.8.0", "key": "typing-inspect", "package_name": "typing-inspect", "required_version": ">=0.7.1" } ], "package": { - "installed_version": "8.5.3", + "installed_version": "8.5.8", "key": "marshmallow-dataclass", "package_name": "marshmallow-dataclass" } @@ -571,7 +524,7 @@ { "dependencies": [ { - "installed_version": "3.14.1", + "installed_version": "3.17.1", "key": "marshmallow", "package_name": "marshmallow", "required_version": ">=2.0.0" @@ -586,7 +539,7 @@ { "dependencies": [ { - "installed_version": "3.14.1", + "installed_version": "3.17.1", "key": "marshmallow", "package_name": "marshmallow", "required_version": ">=3.0.0,<4.0.0" @@ -666,7 +619,7 @@ { "dependencies": [], "package": { - "installed_version": "1.21.5", + "installed_version": "1.23.2", "key": "numpy", "package_name": "numpy" } @@ -674,7 +627,7 @@ { "dependencies": [ { - "installed_version": "3.0.7", + "installed_version": "3.0.9", "key": "pyparsing", "package_name": "pyparsing", "required_version": ">=2.0.2,!=3.0.5" @@ -704,7 +657,7 @@ { "dependencies": [], "package": { - "installed_version": "21.3.1", + "installed_version": "22.2.2", "key": "pip", "package_name": "pip" } @@ -712,7 +665,7 @@ { "dependencies": [ { - "installed_version": "21.3.1", + "installed_version": "22.2.2", "key": "pip", "package_name": "pip", "required_version": ">=6.0.0" @@ -725,14 +678,7 @@ } }, { - "dependencies": [ - { - "installed_version": "4.10.1", - "key": "importlib-metadata", - "package_name": "importlib-metadata", - "required_version": ">=0.12" - } - ], + "dependencies": [], "package": { "installed_version": "1.0.0", "key": "pluggy", @@ -742,7 +688,7 @@ { "dependencies": [], "package": { - "installed_version": "0.13.1", + "installed_version": "0.14.1", "key": "prometheus-client", "package_name": "prometheus-client" } @@ -750,7 +696,7 @@ { "dependencies": [], "package": { - "installed_version": "3.19.4", + "installed_version": "3.20.1", "key": "protobuf", "package_name": "protobuf" } @@ -766,7 +712,7 @@ { "dependencies": [], "package": { - "installed_version": "3.14.1", + "installed_version": "3.15.0", "key": "pycryptodome", "package_name": "pycryptodome" } @@ -774,7 +720,7 @@ { "dependencies": [], "package": { - "installed_version": "3.0.7", + "installed_version": "3.0.9", "key": "pyparsing", "package_name": "pyparsing" } @@ -790,17 +736,11 @@ { "dependencies": [ { - "installed_version": "21.4.0", + "installed_version": "22.1.0", "key": "attrs", "package_name": "attrs", "required_version": ">=19.2.0" }, - { - "installed_version": "4.10.1", - "key": "importlib-metadata", - "package_name": "importlib-metadata", - "required_version": ">=0.12" - }, { "installed_version": "1.1.1", "key": "iniconfig", @@ -833,7 +773,7 @@ } ], "package": { - "installed_version": "7.0.0", + "installed_version": "7.1.2", "key": "pytest", "package_name": "pytest" } @@ -841,20 +781,14 @@ { "dependencies": [ { - "installed_version": "7.0.0", + "installed_version": "7.1.2", "key": "pytest", "package_name": "pytest", "required_version": ">=6.1.0" - }, - { - "installed_version": "4.0.1", - "key": "typing-extensions", - "package_name": "typing-extensions", - "required_version": ">=3.7.2" } ], "package": { - "installed_version": "0.18.0", + "installed_version": "0.19.0", "key": "pytest-asyncio", "package_name": "pytest-asyncio" } @@ -862,16 +796,16 @@ { "dependencies": [ { - "installed_version": "2021.10.8", + "installed_version": "2022.6.15", "key": "certifi", "package_name": "certifi", "required_version": ">=2017.4.17" }, { - "installed_version": "2.0.11", + "installed_version": "2.1.1", "key": "charset-normalizer", "package_name": "charset-normalizer", - "required_version": "~=2.0.0" + "required_version": ">=2,<3" }, { "installed_version": "3.3", @@ -880,14 +814,14 @@ "required_version": ">=2.5,<4" }, { - "installed_version": "1.26.8", + "installed_version": "1.26.12", "key": "urllib3", "package_name": "urllib3", "required_version": ">=1.21.1,<1.27" } ], "package": { - "installed_version": "2.27.1", + "installed_version": "2.28.1", "key": "requests", "package_name": "requests" } @@ -895,7 +829,7 @@ { "dependencies": [ { - "installed_version": "1.10.0", + "installed_version": "1.9.5", "key": "eth-utils", "package_name": "eth-utils", "required_version": ">=1.0.2,<2" @@ -910,7 +844,7 @@ { "dependencies": [], "package": { - "installed_version": "60.5.0", + "installed_version": "63.2.0", "key": "setuptools", "package_name": "setuptools" } @@ -933,7 +867,7 @@ } ], "package": { - "installed_version": "1.9", + "installed_version": "1.10.1", "key": "sympy", "package_name": "sympy" } @@ -949,7 +883,7 @@ { "dependencies": [], "package": { - "installed_version": "0.11.2", + "installed_version": "0.12.0", "key": "toolz", "package_name": "toolz" } @@ -965,7 +899,7 @@ { "dependencies": [], "package": { - "installed_version": "4.0.1", + "installed_version": "4.3.0", "key": "typing-extensions", "package_name": "typing-extensions" } @@ -979,14 +913,14 @@ "required_version": ">=0.3.0" }, { - "installed_version": "4.0.1", + "installed_version": "4.3.0", "key": "typing-extensions", "package_name": "typing-extensions", "required_version": ">=3.7.4" } ], "package": { - "installed_version": "0.7.1", + "installed_version": "0.8.0", "key": "typing-inspect", "package_name": "typing-inspect" } @@ -994,7 +928,7 @@ { "dependencies": [], "package": { - "installed_version": "1.26.8", + "installed_version": "1.26.12", "key": "urllib3", "package_name": "urllib3" } @@ -1016,19 +950,19 @@ "required_version": ">=3.7.4.post0,<4" }, { - "installed_version": "2.1.1", + "installed_version": "2.2.0", "key": "eth-abi", "package_name": "eth-abi", "required_version": ">=2.0.0b6,<3.0.0" }, { - "installed_version": "0.5.7", + "installed_version": "0.5.9", "key": "eth-account", "package_name": "eth-account", "required_version": ">=0.5.7,<0.6.0" }, { - "installed_version": "0.3.2", + "installed_version": "0.5.0", "key": "eth-hash", "package_name": "eth-hash", "required_version": ">=0.2.0,<1.0.0" @@ -1040,13 +974,13 @@ "required_version": ">=2.0.0,<3.0.0" }, { - "installed_version": "1.10.0", + "installed_version": "1.9.5", "key": "eth-utils", "package_name": "eth-utils", "required_version": ">=1.9.5,<2.0.0" }, { - "installed_version": "0.2.2", + "installed_version": "0.3.0", "key": "hexbytes", "package_name": "hexbytes", "required_version": ">=0.1.0,<1.0.0" @@ -1064,29 +998,23 @@ "required_version": ">=3.2.0,<4.0.0" }, { - "installed_version": "1.1.7", + "installed_version": "1.1.8", "key": "lru-dict", "package_name": "lru-dict", "required_version": ">=1.1.6,<2.0.0" }, { - "installed_version": "3.19.4", + "installed_version": "3.20.1", "key": "protobuf", "package_name": "protobuf", "required_version": ">=3.10.0,<4" }, { - "installed_version": "2.27.1", + "installed_version": "2.28.1", "key": "requests", "package_name": "requests", "required_version": ">=2.16.0,<3.0.0" }, - { - "installed_version": "4.0.1", - "key": "typing-extensions", - "package_name": "typing-extensions", - "required_version": ">=3.7.4.1,<5" - }, { "installed_version": "9.1", "key": "websockets", @@ -1095,7 +1023,7 @@ } ], "package": { - "installed_version": "5.27.0", + "installed_version": "5.28.0", "key": "web3", "package_name": "web3" } @@ -1129,26 +1057,12 @@ "key": "multidict", "package_name": "multidict", "required_version": ">=4.0" - }, - { - "installed_version": "4.0.1", - "key": "typing-extensions", - "package_name": "typing-extensions", - "required_version": ">=3.7.4" } ], "package": { - "installed_version": "1.7.2", + "installed_version": "1.8.1", "key": "yarl", "package_name": "yarl" } - }, - { - "dependencies": [], - "package": { - "installed_version": "3.7.0", - "key": "zipp", - "package_name": "zipp" - } } ] diff --git a/scripts/requirements.txt b/scripts/requirements.txt index 3ffc9835..ce4250a8 100644 --- a/scripts/requirements.txt +++ b/scripts/requirements.txt @@ -1,38 +1,34 @@ -# This file is autogenerated. Do not edit manually. - aiohttp==3.8.1 aiosignal==1.2.0 async-timeout==4.0.2 -asynctest==0.13.0 -attrs==21.4.0 +attrs==22.1.0 base58==2.1.1 -bitarray==1.2.2 -cachetools==5.0.0 -certifi==2021.10.8 -charset-normalizer==2.0.11 -cytoolz==0.11.2 -ecdsa==0.17.0 -eth-abi==2.1.1 -eth-account==0.5.7 -eth-hash[pycryptodome]==0.3.2 +bitarray==2.6.0 +cachetools==5.2.0 +certifi==2022.6.15 +charset-normalizer==2.1.1 +cytoolz==0.12.0 +ecdsa==0.18.0 +eth-abi==2.2.0 +eth-account==0.5.9 +eth-hash[pycryptodome]==0.5.0 eth-keyfile==0.5.1 eth-keys==0.3.4 eth-rlp==0.2.1 eth-typing==2.3.0 -eth-utils==1.10.0 +eth-utils==1.9.5 fastecdsa==2.2.3 frozendict==1.2 -frozenlist==1.3.0 -hexbytes==0.2.2 +frozenlist==1.3.1 +hexbytes==0.3.0 idna==3.3 -importlib-metadata==4.10.1 iniconfig==1.1.1 ipfshttpclient==0.8.0a2 jsonschema==3.2.0 lark-parser==0.12.0 -lru-dict==1.1.7 -marshmallow==3.14.1 -marshmallow-dataclass==8.5.3 +lru-dict==1.1.8 +marshmallow==3.17.1 +marshmallow-dataclass==8.5.8 marshmallow-enum==1.5.1 marshmallow-oneofschema==3.0.1 mpmath==1.2.1 @@ -40,35 +36,34 @@ multiaddr==0.0.9 multidict==6.0.2 mypy-extensions==0.4.3 netaddr==0.8.0 -numpy==1.21.5 +numpy==1.23.2 packaging==21.3 parsimonious==0.8.1 -pip==21.3.1 +pip==22.2.2 pipdeptree==2.2.1 pluggy==1.0.0 -prometheus-client==0.13.1 -protobuf==3.19.4 +prometheus-client==0.14.1 +protobuf==3.20.1 py==1.11.0 -pycryptodome==3.14.1 -pyparsing==3.0.7 +pycryptodome==3.15.0 +pyparsing==3.0.9 pyrsistent==0.18.1 -pytest==7.0.0 -pytest-asyncio==0.18.0 +pytest==7.1.2 +pytest-asyncio==0.19.0 PyYAML==6.0 -requests==2.27.1 +requests==2.28.1 rlp==2.0.1 -setuptools==60.5.0 +setuptools==63.2.0 six==1.16.0 -sympy==1.9 +sympy==1.10.1 tomli==2.0.1 -toolz==0.11.2 +toolz==0.12.0 typeguard==2.13.3 -typing-inspect==0.7.1 -typing_extensions==4.0.1 -urllib3==1.26.8 +typing-inspect==0.8.0 +typing_extensions==4.3.0 +urllib3==1.26.12 varint==1.0.2 -web3==5.27.0 +web3==5.28.0 websockets==9.1 wheel==0.37.1 -yarl==1.7.2 -zipp==3.7.0 +yarl==1.8.1 diff --git a/src/cmake_utils/CMakeLists.txt b/src/cmake_utils/CMakeLists.txt index e8eff168..76a9c43b 100644 --- a/src/cmake_utils/CMakeLists.txt +++ b/src/cmake_utils/CMakeLists.txt @@ -1,8 +1,6 @@ python_lib(gen_solidity_lib FILES gen_solidity_env.py - LIBS - pip_mypy_extensions ) python_venv(gen_solidity_venv diff --git a/src/cmake_utils/cmake_rules.cmake b/src/cmake_utils/cmake_rules.cmake index 5bd02362..58119834 100644 --- a/src/cmake_utils/cmake_rules.cmake +++ b/src/cmake_utils/cmake_rules.cmake @@ -4,6 +4,6 @@ include("${CMAKE_SOURCE_DIR}/src/cmake_utils/python_rules.cmake") include("${CMAKE_SOURCE_DIR}/src/cmake_utils/pip_rules.cmake") include("${CMAKE_SOURCE_DIR}/src/cmake_utils/solidity_rules.cmake") python_get_pip_deps(main_reqs - python3.7:${CMAKE_SOURCE_DIR}/scripts/requirements-deps.json + python3.9:${CMAKE_SOURCE_DIR}/scripts/requirements-deps.json ${ADDITIONAL_PIP_DEPS} ) diff --git a/src/cmake_utils/gen_pip_cmake.py b/src/cmake_utils/gen_pip_cmake.py index b63af667..a9a529f9 100755 --- a/src/cmake_utils/gen_pip_cmake.py +++ b/src/cmake_utils/gen_pip_cmake.py @@ -23,7 +23,7 @@ def main(): nargs="*", required=True, help="Interpreters and dependency output JSON files. " - "Example: python3.7:python_deps.json ...", + "Example: python3.9:python_deps.json ...", ) parser.add_argument("--output", type=str, help="Output cmake file", required=True) args = parser.parse_args() @@ -38,7 +38,7 @@ def main(): with open(dep_file, "r") as fp: for package in json.load(fp): # Extract name of package. - name = package["package"]["key"].replace("-", "_").lower() + name = package["package"]["key"].replace("-", "_").replace(".", "_").lower() # Build a requirement line for current interpreter. req = ( package["package"]["package_name"] @@ -48,7 +48,8 @@ def main(): package_versions[name].append(f'"{interpreter} {req}"') # Append dependency libraries. dep_names = [ - dep["key"].replace("-", "_").lower() for dep in package["dependencies"] + dep["key"].replace("-", "_").replace(".", "_").lower() + for dep in package["dependencies"] ] package_libs[name] += [f"{interpreter}:pip_{name}" for name in dep_names] diff --git a/src/cmake_utils/gen_py_lib.py b/src/cmake_utils/gen_py_lib.py index 269726ea..ee495052 100755 --- a/src/cmake_utils/gen_py_lib.py +++ b/src/cmake_utils/gen_py_lib.py @@ -48,7 +48,7 @@ def main(): ) parser.add_argument("--name", type=str, help="Python library target name", required=True) parser.add_argument( - "--interpreters", type=str, nargs="*", help="Supported interpreters", default=["python3.7"] + "--interpreters", type=str, nargs="*", help="Supported interpreters", default=["python3.9"] ) parser.add_argument("--lib_dir", type=str, nargs="*", help="Library directory", required=True) parser.add_argument( diff --git a/src/cmake_utils/gen_solidity_env.py b/src/cmake_utils/gen_solidity_env.py index 9386fde4..55790bd4 100755 --- a/src/cmake_utils/gen_solidity_env.py +++ b/src/cmake_utils/gen_solidity_env.py @@ -44,11 +44,16 @@ def main(): parser.add_argument( "--info_dir", help="Directory for all libraries info files", type=str, required=True ) + parser.add_argument("--solc_bin", help="Explicit solc binary", type=str, default="solc-0.6.12") + parser.add_argument( + "--optimize_runs", help="Optimize-runs arg to pass into solc", type=int, default=200 + ) + args = parser.parse_args() # Clean directories. shutil.rmtree(args.env_dir, ignore_errors=True) - contracts_dir = os.path.join(args.env_dir, "contracts") + contracts_dir = args.env_dir artifacts_dir = os.path.join(args.env_dir, "artifacts") os.makedirs(contracts_dir) os.makedirs(artifacts_dir) @@ -73,10 +78,10 @@ def main(): # Compile. subprocess.check_call( [ - "solc-0.6.12", + args.solc_bin, "--optimize", "--optimize-runs", - "200", + str(args.optimize_runs), "--combined-json", "abi,bin", "-o", @@ -119,11 +124,20 @@ def extract_artifacts(artifacts_dir, combined_json_filename): if len(val["bin"]) > 0: bytecode = "0x" + val["bin"] + # Support both solc-0.6 & solc-0.8 output format. + # In solc-0.6 the abi is a list in a json string, + # whereas in 0.8 it's a plain json. + try: + abi = json.loads(val["abi"]) + except TypeError: + abi = val["abi"] + artifact = { "contractName": name, - "abi": json.loads(val["abi"]), + "abi": abi, "bytecode": bytecode, } + destination_filename = os.path.join(artifacts_dir, f"{name}.json") with open(destination_filename, "w") as fp: json.dump(artifact, fp, indent=4) diff --git a/src/cmake_utils/gen_venv.py b/src/cmake_utils/gen_venv.py index 3a680641..8503ff41 100755 --- a/src/cmake_utils/gen_venv.py +++ b/src/cmake_utils/gen_venv.py @@ -69,10 +69,10 @@ def fill_init_files(site_dir): def get_pth_dir(python: str, venv_dir: str): - if python == "python3.7": - return os.path.join(venv_dir, "lib/python3.7/site-packages") - elif python == "pypy3": - pth_dir = os.path.join(venv_dir, "site-packages") + if python == "python3.9": + return os.path.join(venv_dir, "lib/python3.9/site-packages") + elif python == "pypy3.9": + pth_dir = os.path.join(venv_dir, "lib/pypy3.9/site-packages") os.makedirs(pth_dir, exist_ok=True) return pth_dir else: diff --git a/src/cmake_utils/python_rules.cmake b/src/cmake_utils/python_rules.cmake index 1ec73f40..d4283faf 100644 --- a/src/cmake_utils/python_rules.cmake +++ b/src/cmake_utils/python_rules.cmake @@ -123,7 +123,7 @@ function(python_lib LIB) endfunction() # Creates a virtual environment target. -# Usage: python_venv(venv_name PYTHON python3.7 LIBS lib0 lib1 ...) +# Usage: python_venv(venv_name PYTHON ${PYTHON_COMMAND} LIBS lib0 lib1 ...) # Target properties: # VENV_PYTHON: Full path to the vritual environment python executable. # STAMP_FILE: when this file is generated, the virtual environment is ready to use. diff --git a/src/cmake_utils/solidity_rules.cmake b/src/cmake_utils/solidity_rules.cmake index 9efac99a..33f2c9da 100644 --- a/src/cmake_utils/solidity_rules.cmake +++ b/src/cmake_utils/solidity_rules.cmake @@ -1,13 +1,21 @@ set(GEN_SOLIDITY_ENV_EXE ${CMAKE_BINARY_DIR}/src/cmake_utils/gen_solidity_exe CACHE INTERNAL "") +set(DEFAULT_SOLC "solc-0.6.12") +set(DEFAULT_RUNS "200") # Creates a solidity environment target. # Usage: solidity_env(venv_name LIBS lib0 lib1 ...) function(solidity_env ENV_NAME) # Parse arguments. set(options) - set(oneValueArgs) + set(oneValueArgs SOLC_BIN OPTIMIZE_RUNS) set(multiValueArgs CONTRACTS LIBS) cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if (NOT ARGS_SOLC_BIN) + set(ARGS_SOLC_BIN ${DEFAULT_SOLC}) + endif() + if (NOT ARGS_OPTIMIZE_RUNS) + set(ARGS_OPTIMIZE_RUNS ${DEFAULT_RUNS}) + endif() # A directory with symlinks to files of other libraries. set(ENV_DIR ${CMAKE_CURRENT_BINARY_DIR}/${ENV_NAME}) @@ -23,6 +31,8 @@ function(solidity_env ENV_NAME) OUTPUT ${ENV_INFO_FILE} COMMAND ${GEN_SOLIDITY_ENV_EXE} --name ${ENV_NAME} + --solc_bin ${ARGS_SOLC_BIN} + --optimize_runs ${ARGS_OPTIMIZE_RUNS} --libs ${ARGS_LIBS} --env_dir ${ENV_DIR} --info_dir ${PY_LIB_INFO_GLOBAL_DIR} diff --git a/src/demo/amm_demo/amm.cairo b/src/demo/amm_demo/amm.cairo index 51562e00..ec84cfd1 100644 --- a/src/demo/amm_demo/amm.cairo +++ b/src/demo/amm_demo/amm.cairo @@ -8,117 +8,117 @@ from starkware.cairo.common.math import assert_nn_le, unsigned_div_rem from starkware.cairo.common.registers import get_fp_and_pc from starkware.cairo.common.small_merkle_tree import small_merkle_tree_update -struct Account: - member public_key : felt - member token_a_balance : felt - member token_b_balance : felt -end - -# The maximum amount of each token that belongs to the AMM. -const MAX_BALANCE = 2 ** 64 - 1 - -struct AmmState: - # A dictionary that tracks the accounts' state. - member account_dict_start : DictAccess* - member account_dict_end : DictAccess* - # The amount of the tokens currently in the AMM. - # Must be in the range [0, MAX_BALANCE]. - member token_a_balance : felt - member token_b_balance : felt -end - -func modify_account{range_check_ptr}(state : AmmState, account_id, diff_a, diff_b) -> ( - state : AmmState, key : felt -): - alloc_locals - - # Define a reference to state.account_dict_end so that we - # can use it as an implicit argument to the dict functions. - let account_dict_end = state.account_dict_end - - # Retrieve the pointer to the current state of the account. - let (local old_account : Account*) = dict_read{dict_ptr=account_dict_end}(key=account_id) - - # Compute the new account values. +struct Account { + public_key: felt, + token_a_balance: felt, + token_b_balance: felt, +} + +// The maximum amount of each token that belongs to the AMM. +const MAX_BALANCE = 2 ** 64 - 1; + +struct AmmState { + // A dictionary that tracks the accounts' state. + account_dict_start: DictAccess*, + account_dict_end: DictAccess*, + // The amount of the tokens currently in the AMM. + // Must be in the range [0, MAX_BALANCE]. + token_a_balance: felt, + token_b_balance: felt, +} + +func modify_account{range_check_ptr}(state: AmmState, account_id, diff_a, diff_b) -> ( + state: AmmState, key: felt +) { + alloc_locals; + + // Define a reference to state.account_dict_end so that we + // can use it as an implicit argument to the dict functions. + let account_dict_end = state.account_dict_end; + + // Retrieve the pointer to the current state of the account. + let (local old_account: Account*) = dict_read{dict_ptr=account_dict_end}(key=account_id); + + // Compute the new account values. tempvar new_token_a_balance = ( - old_account.token_a_balance + diff_a) + old_account.token_a_balance + diff_a); tempvar new_token_b_balance = ( - old_account.token_b_balance + diff_b) - - # Verify that the new balances are positive. - assert_nn_le(new_token_a_balance, MAX_BALANCE) - assert_nn_le(new_token_b_balance, MAX_BALANCE) - - # Create a new Account instance. - local new_account : Account - assert new_account.public_key = old_account.public_key - assert new_account.token_a_balance = new_token_a_balance - assert new_account.token_b_balance = new_token_b_balance - - # Perform the account update. - # Note that dict_write() will update the 'account_dict_end' - # reference. - let (__fp__, _) = get_fp_and_pc() - dict_write{dict_ptr=account_dict_end}(key=account_id, new_value=cast(&new_account, felt)) - - # Construct and return the new state with the updated - # 'account_dict_end'. - local new_state : AmmState + old_account.token_b_balance + diff_b); + + // Verify that the new balances are positive. + assert_nn_le(new_token_a_balance, MAX_BALANCE); + assert_nn_le(new_token_b_balance, MAX_BALANCE); + + // Create a new Account instance. + local new_account: Account; + assert new_account.public_key = old_account.public_key; + assert new_account.token_a_balance = new_token_a_balance; + assert new_account.token_b_balance = new_token_b_balance; + + // Perform the account update. + // Note that dict_write() will update the 'account_dict_end' + // reference. + let (__fp__, _) = get_fp_and_pc(); + dict_write{dict_ptr=account_dict_end}(key=account_id, new_value=cast(&new_account, felt)); + + // Construct and return the new state with the updated + // 'account_dict_end'. + local new_state: AmmState; assert new_state.account_dict_start = ( - state.account_dict_start) - assert new_state.account_dict_end = account_dict_end - assert new_state.token_a_balance = state.token_a_balance - assert new_state.token_b_balance = state.token_b_balance + state.account_dict_start); + assert new_state.account_dict_end = account_dict_end; + assert new_state.token_a_balance = state.token_a_balance; + assert new_state.token_b_balance = state.token_b_balance; - return (state=new_state, key=old_account.public_key) -end + return (state=new_state, key=old_account.public_key); +} -# Represents a swap transaction between a user and the AMM. -struct SwapTransaction: - member account_id : felt - member token_a_amount : felt -end +// Represents a swap transaction between a user and the AMM. +struct SwapTransaction { + account_id: felt, + token_a_amount: felt, +} -func swap{range_check_ptr}(state : AmmState, transaction : SwapTransaction*) -> (state : AmmState): - alloc_locals +func swap{range_check_ptr}(state: AmmState, transaction: SwapTransaction*) -> (state: AmmState) { + alloc_locals; - tempvar a = transaction.token_a_amount - tempvar x = state.token_a_balance - tempvar y = state.token_b_balance + tempvar a = transaction.token_a_amount; + tempvar x = state.token_a_balance; + tempvar y = state.token_b_balance; - # Check that a is in range. - assert_nn_le(a, MAX_BALANCE) + // Check that a is in range. + assert_nn_le(a, MAX_BALANCE); - # Compute the amount of token_b the user will get: - # b = (y * a) / (x + a). - let (b, _) = unsigned_div_rem(y * a, x + a) - # Make sure that b is also in range. - assert_nn_le(b, MAX_BALANCE) + // Compute the amount of token_b the user will get: + // b = (y * a) / (x + a). + let (b, _) = unsigned_div_rem(y * a, x + a); + // Make sure that b is also in range. + assert_nn_le(b, MAX_BALANCE); - # Update the user's account. + // Update the user's account. let (state, key) = modify_account( state=state, account_id=transaction.account_id, diff_a=-a, diff_b=b - ) - - # Here you should verify the user has signed on a message - # specifying that they would like to sell 'a' tokens of - # type token_a. You should use the public key returned by - # modify_account(). - - # Compute the new balances of the AMM and make sure they - # are in range. - tempvar new_x = x + a - tempvar new_y = y - b - assert_nn_le(new_x, MAX_BALANCE) - assert_nn_le(new_y, MAX_BALANCE) - - # Update the state. - local new_state : AmmState + ); + + // Here you should verify the user has signed on a message + // specifying that they would like to sell 'a' tokens of + // type token_a. You should use the public key returned by + // modify_account(). + + // Compute the new balances of the AMM and make sure they + // are in range. + tempvar new_x = x + a; + tempvar new_y = y - b; + assert_nn_le(new_x, MAX_BALANCE); + assert_nn_le(new_y, MAX_BALANCE); + + // Update the state. + local new_state: AmmState; assert new_state.account_dict_start = ( - state.account_dict_start) - assert new_state.account_dict_end = state.account_dict_end - assert new_state.token_a_balance = new_x - assert new_state.token_b_balance = new_y + state.account_dict_start); + assert new_state.account_dict_end = state.account_dict_end; + assert new_state.token_a_balance = new_x; + assert new_state.token_b_balance = new_y; %{ # Print the transaction values using a hint, for @@ -129,76 +129,77 @@ func swap{range_check_ptr}(state : AmmState, transaction : SwapTransaction*) -> f'received {ids.b} tokens of type token_b.') %} - return (state=new_state) -end + return (state=new_state); +} func transaction_loop{range_check_ptr}( - state : AmmState, transactions : SwapTransaction**, n_transactions -) -> (state : AmmState): - if n_transactions == 0: - return (state=state) - end + state: AmmState, transactions: SwapTransaction**, n_transactions +) -> (state: AmmState) { + if (n_transactions == 0) { + return (state=state); + } - let first_transaction : SwapTransaction* = [transactions] - let (state) = swap(state=state, transaction=first_transaction) + let first_transaction: SwapTransaction* = [transactions]; + let (state) = swap(state=state, transaction=first_transaction); return transaction_loop( state=state, transactions=transactions + 1, n_transactions=n_transactions - 1 - ) -end - -# Returns a hash committing to the account's state using the -# following formula: -# H(H(public_key, token_a_balance), token_b_balance). -# where H is the Pedersen hash function. -func hash_account{pedersen_ptr : HashBuiltin*}(account : Account*) -> (res : felt): - let res = account.public_key - let (res) = hash2{hash_ptr=pedersen_ptr}(res, account.token_a_balance) - let (res) = hash2{hash_ptr=pedersen_ptr}(res, account.token_b_balance) - return (res=res) -end - -# For each entry in the input dict (represented by dict_start -# and dict_end) write an entry to the output dict (represented by -# hash_dict_start and hash_dict_end) after applying hash_account -# on prev_value and new_value and keeping the same key. -func hash_dict_values{pedersen_ptr : HashBuiltin*}( - dict_start : DictAccess*, dict_end : DictAccess*, hash_dict_start : DictAccess* -) -> (hash_dict_end : DictAccess*): - if dict_start == dict_end: - return (hash_dict_end=hash_dict_start) - end - - # Compute the hash of the account before and after the - # change. - let (prev_hash) = hash_account(account=cast(dict_start.prev_value, Account*)) - let (new_hash) = hash_account(account=cast(dict_start.new_value, Account*)) - - # Add an entry to the output dict. + ); +} + +// Returns a hash committing to the account's state using the +// following formula: +// H(H(public_key, token_a_balance), token_b_balance). +// where H is the Pedersen hash function. +func hash_account{pedersen_ptr: HashBuiltin*}(account: Account*) -> (res: felt) { + let res = account.public_key; + let (res) = hash2{hash_ptr=pedersen_ptr}(res, account.token_a_balance); + let (res) = hash2{hash_ptr=pedersen_ptr}(res, account.token_b_balance); + return (res=res); +} + +// For each entry in the input dict (represented by dict_start +// and dict_end) write an entry to the output dict (represented +// by hash_dict_start and hash_dict_end) after applying +// hash_account on prev_value and new_value and keeping the same +// key. +func hash_dict_values{pedersen_ptr: HashBuiltin*}( + dict_start: DictAccess*, dict_end: DictAccess*, hash_dict_start: DictAccess* +) -> (hash_dict_end: DictAccess*) { + if (dict_start == dict_end) { + return (hash_dict_end=hash_dict_start); + } + + // Compute the hash of the account before and after the + // change. + let (prev_hash) = hash_account(account=cast(dict_start.prev_value, Account*)); + let (new_hash) = hash_account(account=cast(dict_start.new_value, Account*)); + + // Add an entry to the output dict. dict_update{dict_ptr=hash_dict_start}( key=dict_start.key, prev_value=prev_hash, new_value=new_hash - ) + ); return hash_dict_values( dict_start=dict_start + DictAccess.SIZE, dict_end=dict_end, hash_dict_start=hash_dict_start - ) -end + ); +} -const LOG_N_ACCOUNTS = 10 +const LOG_N_ACCOUNTS = 10; -# Computes the Merkle roots before and after the batch. -# Hint argument: initial_account_dict should be a dictionary -# from account_id to an address in memory of the Account struct. -func compute_merkle_roots{pedersen_ptr : HashBuiltin*, range_check_ptr}(state : AmmState) -> ( - root_before : felt, root_after : felt -): - alloc_locals +// Computes the Merkle roots before and after the batch. +// Hint argument: initial_account_dict should be a dictionary +// from account_id to an address in memory of the Account struct. +func compute_merkle_roots{pedersen_ptr: HashBuiltin*, range_check_ptr}(state: AmmState) -> ( + root_before: felt, root_after: felt +) { + alloc_locals; - # Squash the account dictionary. + // Squash the account dictionary. let (squashed_dict_start, squashed_dict_end) = dict_squash( dict_accesses_start=state.account_dict_start, dict_accesses_end=state.account_dict_end - ) + ); - # Hash the dict values. + // Hash the dict values. %{ from starkware.crypto.signature.signature import pedersen_hash @@ -214,23 +215,23 @@ func compute_merkle_roots{pedersen_ptr : HashBuiltin*, range_check_ptr}(state : pedersen_hash(public_key, token_a_balance), token_b_balance) %} - let (local hash_dict_start : DictAccess*) = dict_new() + let (local hash_dict_start: DictAccess*) = dict_new(); let (hash_dict_end) = hash_dict_values( dict_start=squashed_dict_start, dict_end=squashed_dict_end, hash_dict_start=hash_dict_start - ) + ); - # Compute the two Merkle roots. + // Compute the two Merkle roots. let (root_before, root_after) = small_merkle_tree_update{hash_ptr=pedersen_ptr}( squashed_dict_start=hash_dict_start, squashed_dict_end=hash_dict_end, height=LOG_N_ACCOUNTS - ) + ); - return (root_before=root_before, root_after=root_after) -end + return (root_before=root_before, root_after=root_after); +} -func get_transactions() -> (transactions : SwapTransaction**, n_transactions : felt): - alloc_locals - local transactions : SwapTransaction** - local n_transactions : felt +func get_transactions() -> (transactions: SwapTransaction**, n_transactions: felt) { + alloc_locals; + local transactions: SwapTransaction**; + local n_transactions: felt; %{ transactions = [ [ @@ -242,11 +243,11 @@ func get_transactions() -> (transactions : SwapTransaction**, n_transactions : f ids.transactions = segments.gen_arg(transactions) ids.n_transactions = len(transactions) %} - return (transactions=transactions, n_transactions=n_transactions) -end + return (transactions=transactions, n_transactions=n_transactions); +} -func get_account_dict() -> (account_dict : DictAccess*): - alloc_locals +func get_account_dict() -> (account_dict: DictAccess*) { + alloc_locals; %{ account = program_input['accounts'] initial_dict = { @@ -258,35 +259,35 @@ func get_account_dict() -> (account_dict : DictAccess*): for account_id_str, info in account.items() } - # Save a copy initial account dict for + # Save a copy of initial_dict for # compute_merkle_roots. initial_account_dict = dict(initial_dict) %} - # Initialize the account dictionary. - let (account_dict) = dict_new() - return (account_dict=account_dict) -end - -# The output of the AMM program. -struct AmmBatchOutput: - # The balances of the AMM before applying the batch. - member token_a_before : felt - member token_b_before : felt - # The balances of the AMM after applying the batch. - member token_a_after : felt - member token_b_after : felt - # The account Merkle roots before and after applying - # the batch. - member account_root_before : felt - member account_root_after : felt -end - -func main{output_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(): - alloc_locals - - # Create the initial state. - local state : AmmState + // Initialize the account dictionary. + let (account_dict) = dict_new(); + return (account_dict=account_dict); +} + +// The output of the AMM program. +struct AmmBatchOutput { + // The balances of the AMM before applying the batch. + token_a_before: felt, + token_b_before: felt, + // The balances of the AMM after applying the batch. + token_a_after: felt, + token_b_after: felt, + // The account Merkle roots before and after applying + // the batch. + account_root_before: felt, + account_root_after: felt, +} + +func main{output_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + alloc_locals; + + // Create the initial state. + local state: AmmState; %{ # Initialize the balances using a hint. # Later we will output them to the output struct, @@ -298,31 +299,31 @@ func main{output_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(): program_input['token_b_balance'] %} - let (account_dict) = get_account_dict() - assert state.account_dict_start = account_dict - assert state.account_dict_end = account_dict + let (account_dict) = get_account_dict(); + assert state.account_dict_start = account_dict; + assert state.account_dict_end = account_dict; - # Output the AMM's balances before applying the batch. - let output = cast(output_ptr, AmmBatchOutput*) - let output_ptr = output_ptr + AmmBatchOutput.SIZE + // Output the AMM's balances before applying the batch. + let output = cast(output_ptr, AmmBatchOutput*); + let output_ptr = output_ptr + AmmBatchOutput.SIZE; - assert output.token_a_before = state.token_a_balance - assert output.token_b_before = state.token_b_balance + assert output.token_a_before = state.token_a_balance; + assert output.token_b_before = state.token_b_balance; - # Execute the transactions. - let (transactions, n_transactions) = get_transactions() - let (state : AmmState) = transaction_loop( + // Execute the transactions. + let (transactions, n_transactions) = get_transactions(); + let (state: AmmState) = transaction_loop( state=state, transactions=transactions, n_transactions=n_transactions - ) + ); - # Output the AMM's balances after applying the batch. - assert output.token_a_after = state.token_a_balance - assert output.token_b_after = state.token_b_balance + // Output the AMM's balances after applying the batch. + assert output.token_a_after = state.token_a_balance; + assert output.token_b_after = state.token_b_balance; - # Write the Merkle roots to the output. - let (root_before, root_after) = compute_merkle_roots(state=state) - assert output.account_root_before = root_before - assert output.account_root_after = root_after + // Write the Merkle roots to the output. + let (root_before, root_after) = compute_merkle_roots(state=state); + assert output.account_root_before = root_before; + assert output.account_root_after = root_after; - return () -end + return (); +} diff --git a/src/services/everest/api/feeder_gateway/CMakeLists.txt b/src/services/everest/api/feeder_gateway/CMakeLists.txt index e6ee4a2f..30548c75 100644 --- a/src/services/everest/api/feeder_gateway/CMakeLists.txt +++ b/src/services/everest/api/feeder_gateway/CMakeLists.txt @@ -15,6 +15,6 @@ python_lib(everest_feeder_gateway_response_objects_lib response_objects.py LIBS - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib pip_marshmallow ) diff --git a/src/services/everest/api/gateway/CMakeLists.txt b/src/services/everest/api/gateway/CMakeLists.txt index 8317abe3..e55824cd 100644 --- a/src/services/everest/api/gateway/CMakeLists.txt +++ b/src/services/everest/api/gateway/CMakeLists.txt @@ -12,11 +12,23 @@ python_lib(everest_transaction_lib transaction.py LIBS - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib pip_marshmallow_enum pip_marshmallow_oneofschema ) +python_lib(everest_config_request_lib + PREFIX services/everest/api/gateway + + FILES + set_config_request.py + + LIBS + starkware_dataclasses_field_utils_lib + starkware_dataclasses_utils_lib + starkware_error_handling_lib +) + python_lib(everest_gateway_client_lib PREFIX services/everest/api/gateway diff --git a/src/services/everest/api/gateway/set_config_request.py b/src/services/everest/api/gateway/set_config_request.py new file mode 100644 index 00000000..b260075e --- /dev/null +++ b/src/services/everest/api/gateway/set_config_request.py @@ -0,0 +1,89 @@ +from dataclasses import field +from typing import Optional + +import marshmallow.fields as mfields +import marshmallow_dataclass + +from starkware.starkware_utils.error_handling import StarkErrorCode, stark_assert +from starkware.starkware_utils.field_validators import validate_alternative_endpoint +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata +from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass + + +@marshmallow_dataclass.dataclass +class AlternativeEndpointSettingRequest(ValidatedMarshmallowDataclass): + """ + This request is sent when the endpoint that receives the alternative transaction request + is changed. + The client should provide one of the following options: + - Bearer token + - Certificates: server certificate and client certificate + + :param url: The URL address of the endpoint. + :type url: str + :param bearer_token: The Bearer token. + :type bearer_token: Optional[str] + :param server_certificate: The server certificate. + :type server_certificate: Optional[str] + :param client_certificate: The client certificate. + :type client_certificate: Optional[str] + :param client_key: The client private key. + :type client_key: Optional[str] + """ + + url: str = field( + metadata=additional_metadata( + marshmallow_field=mfields.String(validate=validate_alternative_endpoint), + ) + ) + bearer_token: Optional[str] = field( + metadata=additional_metadata( + marshmallow_field=mfields.String(allow_none=True), description="Bearer token" + ), + default=None, + ) + server_certificate: Optional[str] = field( + metadata=additional_metadata( + marshmallow_field=mfields.String(allow_none=True), description="Server certificates" + ), + default=None, + ) + client_certificate: Optional[str] = field( + metadata=additional_metadata( + marshmallow_field=mfields.String(allow_none=True), description="Client certificates" + ), + default=None, + ) + client_key: Optional[str] = field( + metadata=additional_metadata( + marshmallow_field=mfields.String(allow_none=True), description="Client private key" + ), + default=None, + ) + + def __post_init__(self): + super().__post_init__() + self._validate_set_config() + + def _validate_set_config(self) -> None: + """ + Verifies at one of the two is given: Bearer token or certificates. + If Bearer token is given -> certificates should be None. + If certificates are given -> Bearer token should be None. + """ + if self.bearer_token is None: + stark_assert( + (self.client_certificate is not None) + and (self.server_certificate is not None) + and (self.client_key is not None), + code=StarkErrorCode.SCHEMA_VALIDATION_ERROR, + message=f"Neither bearer token nor certificates is provided correctly.", + ) + else: + stark_assert( + (self.client_certificate is None) + and (self.server_certificate is None) + and (self.client_key is None), + code=StarkErrorCode.SCHEMA_VALIDATION_ERROR, + message=f"Endpoint should not provide both bearer token and certificates.", + ) diff --git a/src/services/everest/business_logic/CMakeLists.txt b/src/services/everest/business_logic/CMakeLists.txt index f9e86cbd..e4f7d523 100644 --- a/src/services/everest/business_logic/CMakeLists.txt +++ b/src/services/everest/business_logic/CMakeLists.txt @@ -1,3 +1,10 @@ +python_lib(everest_business_logic_state_api_lib + PREFIX services/everest/business_logic + + FILES + state_api.py +) + python_lib(everest_business_logic_lib PREFIX services/everest/business_logic @@ -5,8 +12,9 @@ python_lib(everest_business_logic_lib state.py LIBS + everest_business_logic_state_api_lib starkware_config_utils_lib - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib starkware_python_utils_lib starkware_storage_lib starkware_utils_lib @@ -20,9 +28,11 @@ python_lib(everest_internal_transaction_lib LIBS everest_business_logic_lib + everest_business_logic_state_api_lib everest_transaction_lib starkware_config_utils_lib starkware_dataclasses_utils_lib + starkware_one_of_schema_utils_lib pip_marshmallow_dataclass ) @@ -33,7 +43,7 @@ python_lib(everest_transaction_execution_objects_lib transaction_execution_objects.py LIBS - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib pip_marshmallow pip_marshmallow_dataclass ) diff --git a/src/services/everest/business_logic/internal_transaction.py b/src/services/everest/business_logic/internal_transaction.py index ec374da1..057246b4 100644 --- a/src/services/everest/business_logic/internal_transaction.py +++ b/src/services/everest/business_logic/internal_transaction.py @@ -6,7 +6,8 @@ import marshmallow_dataclass from services.everest.api.gateway.transaction import EverestTransaction -from services.everest.business_logic.state import CarriedStateBase, StateSelectorBase +from services.everest.business_logic.state import StateSelectorBase +from services.everest.business_logic.state_api import StateProxy from starkware.starkware_utils.config_base import Config from starkware.starkware_utils.one_of_schema_tracker import SubclassSchemaTracker from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass @@ -35,7 +36,7 @@ class EverestInternalStateTransaction(SubclassSchemaTracker): @abstractmethod async def apply_state_updates( - self, state: CarriedStateBase, general_config: Config + self, state: StateProxy, general_config: Config ) -> Optional[EverestTransactionExecutionInfo]: """ Applies the transaction on the state in an atomic manner. diff --git a/src/services/everest/business_logic/state.py b/src/services/everest/business_logic/state.py index da6359fa..2277c5db 100644 --- a/src/services/everest/business_logic/state.py +++ b/src/services/everest/business_logic/state.py @@ -1,7 +1,9 @@ import contextlib +import functools from abc import ABC, abstractmethod -from typing import Iterator, Optional, Type, TypeVar +from typing import Iterable, Iterator, Optional, Type, TypeVar +from services.everest.business_logic.state_api import StateProxy from starkware.python.object_utils import generic_object_repr from starkware.starkware_utils.commitment_tree.binary_fact_tree import BinaryFactDict from starkware.starkware_utils.config_base import Config @@ -14,6 +16,7 @@ TStateSelector = TypeVar("TStateSelector", bound="StateSelectorBase") TCarriedState = TypeVar("TCarriedState", bound="CarriedStateBase") TSharedState = TypeVar("TSharedState", bound="SharedStateBase") +TStateDiff = TypeVar("TStateDiff", bound="EverestStateDiff") TGeneralConfig = TypeVar("TGeneralConfig", bound=Config) @@ -49,7 +52,7 @@ def __le__(self: TStateSelector, other: TStateSelector) -> bool: pass -class CarriedStateBase(ABC): +class CarriedStateBase(StateProxy): """ A class representing a sub-state of the total state (SharedState). It is carried and maintained by the Batcher, as each pending transaction is applied to it @@ -201,3 +204,30 @@ async def apply_state_updates( facts: Optional[BinaryFactDict] = None, ) -> TSharedState: pass + + +class EverestStateDiff(ValidatedMarshmallowDataclass): + """ + Represents uncommitted changes to a state. + """ + + @abstractmethod + def squash(self: TStateDiff, other: TStateDiff) -> TStateDiff: + """ + Creates a state diff. object by applying the given object on self. + """ + + @abstractmethod + async def commit( + self, ffc: FactFetchingContext, previous_state: SharedStateBase + ) -> SharedStateBase: + """ + Returns a new state after applying the changes onto the given state. + """ + + @classmethod + def squash_many(cls: Type[TStateDiff], state_diffs: Iterable[TStateDiff]) -> TStateDiff: + """ + Creates a state diff. object with the given changes applied in chronological order. + """ + return functools.reduce(lambda x, y: x.squash(other=y), state_diffs) diff --git a/src/services/everest/business_logic/state_api.py b/src/services/everest/business_logic/state_api.py new file mode 100644 index 00000000..813edbec --- /dev/null +++ b/src/services/everest/business_logic/state_api.py @@ -0,0 +1,7 @@ +from abc import ABC + + +class StateProxy(ABC): + """ + A proxy to the state, exposing the sufficient functionallity to run a transaction. + """ diff --git a/src/services/everest/definitions/CMakeLists.txt b/src/services/everest/definitions/CMakeLists.txt index 95139736..c7006447 100644 --- a/src/services/everest/definitions/CMakeLists.txt +++ b/src/services/everest/definitions/CMakeLists.txt @@ -7,7 +7,7 @@ python_lib(everest_definitions_lib LIBS starkware_crypto_lib - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib starkware_error_handling_lib pip_marshmallow pip_web3 diff --git a/src/services/everest/definitions/fields.py b/src/services/everest/definitions/fields.py index 64bb471b..cf728b87 100644 --- a/src/services/everest/definitions/fields.py +++ b/src/services/everest/definitions/fields.py @@ -4,6 +4,7 @@ from typing import Any, ClassVar, Dict, List, Optional import marshmallow.fields as mfields +import marshmallow.utils from eth_typing import ChecksumAddress from web3 import Web3 @@ -55,7 +56,9 @@ def format_invalid_value_error_message(self, value: str, name: Optional[str] = N ) # Serialization. - def get_marshmallow_field(self, required: bool, load_default: Any) -> mfields.Field: + def get_marshmallow_field( + self, required: bool = True, load_default: Any = marshmallow.utils.missing + ) -> mfields.Field: return mfields.String(required=required, load_default=load_default) def convert_valid_to_checksum(self, value: str) -> ChecksumAddress: diff --git a/src/services/external_api/CMakeLists.txt b/src/services/external_api/CMakeLists.txt index d0ee9d0e..def57705 100644 --- a/src/services/external_api/CMakeLists.txt +++ b/src/services/external_api/CMakeLists.txt @@ -15,7 +15,7 @@ python_lib(services_external_api_lib LIBS services_external_api_utils_lib - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib starkware_python_utils_lib pip_aiohttp ${SERVICES_EXTERNAL_API_LIB_ADDITIONAL_LIBS} diff --git a/src/services/external_api/client.py b/src/services/external_api/client.py index 1e53234c..d9626edc 100644 --- a/src/services/external_api/client.py +++ b/src/services/external_api/client.py @@ -61,7 +61,6 @@ def __init__( url: str, certificates_path: Optional[str] = None, retry_config: Optional[RetryConfig] = None, - validate_server_crt: bool = True, ): self.url = url self.ssl_context: Optional[ssl.SSLContext] = None @@ -82,10 +81,7 @@ def __init__( ) # Enforce usage of server certificate authentication. - if validate_server_crt: - self.ssl_context.load_verify_locations( - os.path.join(certificates_path, "server.crt") - ) + self.ssl_context.load_verify_locations(os.path.join(certificates_path, "server.crt")) def __repr__(self) -> str: return generic_object_repr(obj=self) diff --git a/src/starkware/cairo/CMakeLists.txt b/src/starkware/cairo/CMakeLists.txt index 3681cef9..a65a1366 100644 --- a/src/starkware/cairo/CMakeLists.txt +++ b/src/starkware/cairo/CMakeLists.txt @@ -1,4 +1,6 @@ add_subdirectory(bootloaders) +add_subdirectory(cairo_verifier) add_subdirectory(common) add_subdirectory(lang) add_subdirectory(sharp) +add_subdirectory(stark_verifier) diff --git a/src/starkware/cairo/bootloaders/bootloader/bootloader.cairo b/src/starkware/cairo/bootloaders/bootloader/bootloader.cairo index 41bb20cd..9d4ee851 100644 --- a/src/starkware/cairo/bootloaders/bootloader/bootloader.cairo +++ b/src/starkware/cairo/bootloaders/bootloader/bootloader.cairo @@ -1,4 +1,4 @@ -%builtins output pedersen range_check ecdsa bitwise ec_op +%builtins output pedersen range_check ecdsa bitwise ec_op keccak from starkware.cairo.bootloaders.simple_bootloader.run_simple_bootloader import ( run_simple_bootloader, @@ -9,34 +9,35 @@ from starkware.cairo.common.find_element import find_element from starkware.cairo.common.hash_state import hash_felts from starkware.cairo.common.memcpy import memcpy -struct BootloaderConfig: - # The hash of the simple bootloader program. - member simple_bootloader_program_hash : felt - # The hashes of the supported (Cairo) programs that verify a STARK proof for the Cairo machine. - member supported_cairo_verifier_program_hashes_len : felt - member supported_cairo_verifier_program_hashes : felt* -end - -struct TaskOutputHeader: - member size : felt - member program_hash : felt -end - -# Runs the simple bootloader on tasks and unpacks them to the output. -# -# Hint arguments: -# program_input - Contains the inputs for the bootloader. +struct BootloaderConfig { + // The hash of the simple bootloader program. + simple_bootloader_program_hash: felt, + // The hashes of the supported (Cairo) programs that verify a STARK proof for the Cairo machine. + supported_cairo_verifier_program_hashes_len: felt, + supported_cairo_verifier_program_hashes: felt*, +} + +struct TaskOutputHeader { + size: felt, + program_hash: felt, +} + +// Runs the simple bootloader on tasks and unpacks them to the output. +// +// Hint arguments: +// program_input - Contains the inputs for the bootloader. func main{ - output_ptr : felt*, - pedersen_ptr : HashBuiltin*, + output_ptr: felt*, + pedersen_ptr: HashBuiltin*, range_check_ptr, ecdsa_ptr, bitwise_ptr, ec_op_ptr, -}(): - ap += SIZEOF_LOCALS + keccak_ptr, +}() { + ap += SIZEOF_LOCALS; - local simple_bootloader_output_start : felt* + local simple_bootloader_output_start: felt*; %{ from starkware.cairo.bootloaders.bootloader.objects import BootloaderInput bootloader_input = BootloaderInput.Schema().load(program_input) @@ -49,25 +50,26 @@ func main{ output_builtin.new_state(base=ids.simple_bootloader_output_start) %} - # Save segment's start. - let simple_bootloader_output_ptr : felt* = simple_bootloader_output_start + // Save segment's start. + let simple_bootloader_output_ptr: felt* = simple_bootloader_output_start; - # Call the simple bootloader program to execute direct subtasks. Simple bootloader input is - # contained in the bootloader input. + // Call the simple bootloader program to execute direct subtasks. Simple bootloader input is + // contained in the bootloader input. %{ simple_bootloader_input = bootloader_input %} - run_simple_bootloader{output_ptr=simple_bootloader_output_ptr}() - local range_check_ptr = range_check_ptr - local ecdsa_ptr = ecdsa_ptr - local bitwise_ptr = bitwise_ptr - local ec_op_ptr = ec_op_ptr - local simple_bootloader_output_end : felt* = simple_bootloader_output_ptr + run_simple_bootloader{output_ptr=simple_bootloader_output_ptr}(); + local range_check_ptr = range_check_ptr; + local ecdsa_ptr = ecdsa_ptr; + local bitwise_ptr = bitwise_ptr; + local ec_op_ptr = ec_op_ptr; + local keccak_ptr = keccak_ptr; + local simple_bootloader_output_end: felt* = simple_bootloader_output_ptr; %{ # Restore the bootloader's output builtin state. output_builtin.set_state(output_builtin_state) %} - local bootloader_config : BootloaderConfig* + local bootloader_config: BootloaderConfig*; %{ from starkware.cairo.bootloaders.bootloader.objects import BootloaderConfig bootloader_config: BootloaderConfig = bootloader_input.bootloader_config @@ -81,35 +83,35 @@ func main{ ) %} - # The bootloader config appears at the beginning of the output. - serialize_bootloader_config(bootloader_config=bootloader_config) + // The bootloader config appears at the beginning of the output. + serialize_bootloader_config(bootloader_config=bootloader_config); - # Increment output_ptr to save place for n_total_tasks. - local output_n_total_tasks_ptr : felt* = output_ptr - let output_ptr = output_ptr + 1 + // Increment output_ptr to save place for n_total_tasks. + local output_n_total_tasks_ptr: felt* = output_ptr; + let output_ptr = output_ptr + 1; %{ output_start = ids.output_ptr %} - let simple_bootloader_output_ptr = simple_bootloader_output_start + let simple_bootloader_output_ptr = simple_bootloader_output_start; - # Skip n_subtasks in the simple bootloader output. - let n_subtasks = [simple_bootloader_output_ptr] - let simple_bootloader_output_ptr = simple_bootloader_output_ptr + 1 + // Skip n_subtasks in the simple bootloader output. + let n_subtasks = [simple_bootloader_output_ptr]; + let simple_bootloader_output_ptr = simple_bootloader_output_ptr + 1; - # Parse outputs recursively and write it to the output builtin. - let n_total_tasks : felt = 0 + // Parse outputs recursively and write it to the output builtin. + let n_total_tasks: felt = 0; %{ packed_outputs = bootloader_input.packed_outputs %} - with simple_bootloader_output_ptr, n_total_tasks: + with simple_bootloader_output_ptr, n_total_tasks { parse_tasks{subtasks_output=simple_bootloader_output_ptr}( bootloader_config=bootloader_config, n_subtasks=n_subtasks - ) - end + ); + } - # Assert that parse_tasks used the entire output of the simple bootloader. - let parse_tasks_end = simple_bootloader_output_ptr - assert simple_bootloader_output_end = parse_tasks_end + // Assert that parse_tasks used the entire output of the simple bootloader. + let parse_tasks_end = simple_bootloader_output_ptr; + assert simple_bootloader_output_end = parse_tasks_end; - # Output the total number of tasks. - assert [output_n_total_tasks_ptr] = n_total_tasks + // Output the total number of tasks. + assert [output_n_total_tasks_ptr] = n_total_tasks; %{ from typing import List @@ -140,36 +142,36 @@ func main{ fact_topologies=plain_fact_topologies, ) %} - return () -end - -# Unpacks composite packed outputs recursively and writes each task's plain output to the output -# builtin. -# -# Arguments: -# n_subtasks - Number of direct subtasks to unfold. -# bootloader_config. -# -# Hint arguments: -# packed_outputs - PackedOutput object that stores the task tree structure. -# -# Implicit arguments: -# n_total_tasks - Number of PlainPackedOutput that were unpacked. This function increments this -# value for each unpacked output. -# subtasks_output - Contains direct subtasks outputs which is used for unpacking. This is an input -# to this function and is returned for validation purposes. + return (); +} + +// Unpacks composite packed outputs recursively and writes each task's plain output to the output +// builtin. +// +// Arguments: +// n_subtasks - Number of direct subtasks to unfold. +// bootloader_config. +// +// Hint arguments: +// packed_outputs - PackedOutput object that stores the task tree structure. +// +// Implicit arguments: +// n_total_tasks - Number of PlainPackedOutput that were unpacked. This function increments this +// value for each unpacked output. +// subtasks_output - Contains direct subtasks outputs which is used for unpacking. This is an input +// to this function and is returned for validation purposes. func parse_tasks{ - output_ptr : felt*, - pedersen_ptr : HashBuiltin*, + output_ptr: felt*, + pedersen_ptr: HashBuiltin*, range_check_ptr, - n_total_tasks : felt, - subtasks_output : felt*, -}(bootloader_config : BootloaderConfig*, n_subtasks : felt): - if n_subtasks == 0: - return () - end + n_total_tasks: felt, + subtasks_output: felt*, +}(bootloader_config: BootloaderConfig*, n_subtasks: felt) { + if (n_subtasks == 0) { + return (); + } - ap += SIZEOF_LOCALS + ap += SIZEOF_LOCALS; %{ from starkware.cairo.bootloaders.bootloader.objects import PackedOutput @@ -187,160 +189,160 @@ func parse_tasks{ ) %} - if nondet %{ isinstance(packed_output, PlainPackedOutput) %} != 0: - # Handle plain packed task. - unpack_plain_packed_task{task_output=subtasks_output}(bootloader_config=bootloader_config) - else: - # Handle composite packed task. + if (nondet %{ isinstance(packed_output, PlainPackedOutput) %} != 0) { + // Handle plain packed task. + unpack_plain_packed_task{task_output=subtasks_output}(bootloader_config=bootloader_config); + } else { + // Handle composite packed task. %{ assert isinstance(packed_output, CompositePackedOutput) %} unpack_composite_packed_task{task_output=subtasks_output}( bootloader_config=bootloader_config - ) - end + ); + } %{ vm_exit_scope() %} - # Call recursively for handling the other tasks. - return parse_tasks(bootloader_config=bootloader_config, n_subtasks=n_subtasks - 1) -end + // Call recursively for handling the other tasks. + return parse_tasks(bootloader_config=bootloader_config, n_subtasks=n_subtasks - 1); +} -# Serializes the bootloader config. -# -# Arguments: -# bootloader_config - A pointer to the bootloader config. -func serialize_bootloader_config{output_ptr : felt*, pedersen_ptr : HashBuiltin*}( - bootloader_config : BootloaderConfig* -): - assert [output_ptr] = bootloader_config.simple_bootloader_program_hash +// Serializes the bootloader config. +// +// Arguments: +// bootloader_config - A pointer to the bootloader config. +func serialize_bootloader_config{output_ptr: felt*, pedersen_ptr: HashBuiltin*}( + bootloader_config: BootloaderConfig* +) { + assert [output_ptr] = bootloader_config.simple_bootloader_program_hash; - # Compute the hash of the supported Cairo verifiers. + // Compute the hash of the supported Cairo verifiers. let (supported_cairo_verifiers_hash) = hash_felts{hash_ptr=pedersen_ptr}( data=bootloader_config.supported_cairo_verifier_program_hashes, length=bootloader_config.supported_cairo_verifier_program_hashes_len, - ) - - assert [output_ptr + 1] = supported_cairo_verifiers_hash - let output_ptr = output_ptr + 2 - return () -end - -# Parses the task header. -# -# Implicit arguments: -# task_output - A pointer to the output of the plain packed task. Assumes that task_output is of -# the following format: (task_header, output). -func parse_task_header{task_output : felt*}() -> (task_header : TaskOutputHeader*): - let task_header = cast(task_output, TaskOutputHeader*) - let task_output = task_output + TaskOutputHeader.SIZE - return (task_header=task_header) -end - -# Unpacks a composite packed task output. -# -# Arguments: -# bootloader_config. -# -# Implicit arguments: -# task_output - A pointer to the output of the composite packed task. task_output should be of the -# following format: -# (output_len, cairo_verifier_program_hash, simple_bootloader_program_hash, output_hash). -# n_total_tasks - Number of PlainPackedOutput that were unpacked. -# -# Hint arguments: -# packed_output - CompositePackedOutput object which uses for unpacking the task. + ); + + assert [output_ptr + 1] = supported_cairo_verifiers_hash; + let output_ptr = output_ptr + 2; + return (); +} + +// Parses the task header. +// +// Implicit arguments: +// task_output - A pointer to the output of the plain packed task. Assumes that task_output is of +// the following format: (task_header, output). +func parse_task_header{task_output: felt*}() -> (task_header: TaskOutputHeader*) { + let task_header = cast(task_output, TaskOutputHeader*); + let task_output = task_output + TaskOutputHeader.SIZE; + return (task_header=task_header); +} + +// Unpacks a composite packed task output. +// +// Arguments: +// bootloader_config. +// +// Implicit arguments: +// task_output - A pointer to the output of the composite packed task. task_output should be of the +// following format: +// (output_len, cairo_verifier_program_hash, simple_bootloader_program_hash, output_hash). +// n_total_tasks - Number of PlainPackedOutput that were unpacked. +// +// Hint arguments: +// packed_output - CompositePackedOutput object which uses for unpacking the task. func unpack_composite_packed_task{ - output_ptr : felt*, - pedersen_ptr : HashBuiltin*, + output_ptr: felt*, + pedersen_ptr: HashBuiltin*, range_check_ptr, - n_total_tasks : felt, - task_output : felt*, -}(bootloader_config : BootloaderConfig*): - ap += SIZEOF_LOCALS - - # Guess the pre-image of subtasks_output_hash (subtasks_output_hash appears in task_output). - local nested_subtasks_output : felt* - local nested_subtasks_output_len + n_total_tasks: felt, + task_output: felt*, +}(bootloader_config: BootloaderConfig*) { + ap += SIZEOF_LOCALS; + + // Guess the pre-image of subtasks_output_hash (subtasks_output_hash appears in task_output). + local nested_subtasks_output: felt*; + local nested_subtasks_output_len; %{ data = packed_output.elements_for_hash() ids.nested_subtasks_output_len = len(data) ids.nested_subtasks_output = segments.gen_arg(data) %} - # Compute the hash of nested_subtasks_output. + // Compute the hash of nested_subtasks_output. let (subtasks_output_hash) = hash_felts{hash_ptr=pedersen_ptr}( data=nested_subtasks_output, length=nested_subtasks_output_len - ) + ); - # Verify task output header. - let (task_header : TaskOutputHeader*) = parse_task_header() - assert task_header.size = TaskOutputHeader.SIZE + CairoVerifierOutput.SIZE + // Verify task output header. + let (task_header: TaskOutputHeader*) = parse_task_header(); + assert task_header.size = TaskOutputHeader.SIZE + CairoVerifierOutput.SIZE; - # Make sure the program hash is one of the supported verifier program hashes. + // Make sure the program hash is one of the supported verifier program hashes. find_element( array_ptr=bootloader_config.supported_cairo_verifier_program_hashes, elm_size=1, n_elms=bootloader_config.supported_cairo_verifier_program_hashes_len, key=task_header.program_hash, - ) + ); - # Verify task output. + // Verify task output. assert [cast(task_output, CairoVerifierOutput*)] = CairoVerifierOutput( program_hash=bootloader_config.simple_bootloader_program_hash, - output_hash=subtasks_output_hash) - local task_output : felt* = task_output + CairoVerifierOutput.SIZE + output_hash=subtasks_output_hash); + local task_output: felt* = task_output + CairoVerifierOutput.SIZE; - # Call recursively to parse the composite task's subtasks. - local nested_subtasks_output_start : felt* = nested_subtasks_output - let n_subtasks = [nested_subtasks_output] - let nested_subtasks_output = nested_subtasks_output + 1 + // Call recursively to parse the composite task's subtasks. + local nested_subtasks_output_start: felt* = nested_subtasks_output; + let n_subtasks = [nested_subtasks_output]; + let nested_subtasks_output = nested_subtasks_output + 1; %{ packed_outputs = packed_output.subtasks %} - with nested_subtasks_output: + with nested_subtasks_output { parse_tasks{subtasks_output=nested_subtasks_output}( bootloader_config=bootloader_config, n_subtasks=n_subtasks - ) - end - - # Assert that the entire subtask output was used. - assert nested_subtasks_output = nested_subtasks_output_start + nested_subtasks_output_len - return () -end - -# Unpacks a plain packed task output to the output builtin. -# -# Arguments: -# bootloader_config. -# -# Implicit arguments: -# task_output - A pointer to the output of the plain packed task. Assumes that task_output is of -# the following format: (output_len, cairo_verifier_program_hash, *output). -# n_total_tasks - Number of PlainPackedOutput that were unpacked. This function increments this -# value by 1. + ); + } + + // Assert that the entire subtask output was used. + assert nested_subtasks_output = nested_subtasks_output_start + nested_subtasks_output_len; + return (); +} + +// Unpacks a plain packed task output to the output builtin. +// +// Arguments: +// bootloader_config. +// +// Implicit arguments: +// task_output - A pointer to the output of the plain packed task. Assumes that task_output is of +// the following format: (output_len, cairo_verifier_program_hash, *output). +// n_total_tasks - Number of PlainPackedOutput that were unpacked. This function increments this +// value by 1. func unpack_plain_packed_task{ - output_ptr : felt*, - pedersen_ptr : HashBuiltin*, + output_ptr: felt*, + pedersen_ptr: HashBuiltin*, range_check_ptr, - n_total_tasks : felt, - task_output : felt*, -}(bootloader_config : BootloaderConfig*): - ap += SIZEOF_LOCALS - - # Parse task output header. - let (task_header : TaskOutputHeader*) = parse_task_header() - local task_output : felt* = task_output - - # Copy the simple bootloader output header to the bootloader output. - assert [cast(output_ptr, TaskOutputHeader*)] = [task_header] - - # Increment output pointer. - let output_ptr = output_ptr + TaskOutputHeader.SIZE - - # Copy the program output to the bootloader output. - local output_size = task_header.size - TaskOutputHeader.SIZE - memcpy(dst=output_ptr, src=task_output, len=output_size) - - # Increment pointers. - let output_ptr = output_ptr + output_size - let task_output = task_output + output_size - let n_total_tasks = n_total_tasks + 1 - return () -end + n_total_tasks: felt, + task_output: felt*, +}(bootloader_config: BootloaderConfig*) { + ap += SIZEOF_LOCALS; + + // Parse task output header. + let (task_header: TaskOutputHeader*) = parse_task_header(); + local task_output: felt* = task_output; + + // Copy the simple bootloader output header to the bootloader output. + assert [cast(output_ptr, TaskOutputHeader*)] = [task_header]; + + // Increment output pointer. + let output_ptr = output_ptr + TaskOutputHeader.SIZE; + + // Copy the program output to the bootloader output. + local output_size = task_header.size - TaskOutputHeader.SIZE; + memcpy(dst=output_ptr, src=task_output, len=output_size); + + // Increment pointers. + let output_ptr = output_ptr + output_size; + let task_output = task_output + output_size; + let n_total_tasks = n_total_tasks + 1; + return (); +} diff --git a/src/starkware/cairo/bootloaders/simple_bootloader/execute_task.cairo b/src/starkware/cairo/bootloaders/simple_bootloader/execute_task.cairo index 0fecdee0..cdccaf56 100644 --- a/src/starkware/cairo/bootloaders/simple_bootloader/execute_task.cairo +++ b/src/starkware/cairo/bootloaders/simple_bootloader/execute_task.cairo @@ -5,57 +5,58 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.hash_chain import hash_chain from starkware.cairo.common.registers import get_ap, get_fp_and_pc -const BOOTLOADER_VERSION = 0 - -# Use an empty struct to encode an arbitrary-length array. -struct BuiltinList: -end - -struct ProgramHeader: - # The data length field specifies the length of the data (i.e., program header + program) - # and guarantees unique decoding of the program hash. - member data_length : felt - member bootloader_version : felt - member program_main : felt - member n_builtins : felt - # 'builtin_list' is a continuous memory segment containing the ASCII encoding of the (ordered) - # builtins used by the program. - member builtin_list : BuiltinList -end - -struct BuiltinData: - member output : felt - member pedersen : felt - member range_check : felt - member ecdsa : felt - member bitwise : felt - member ec_op : felt -end - -# Executes a single task. -# The task is passed in the 'task' hint variable. -# Outputs of the task are prefixed by: -# a. Output size (including this prefix) -# b. hash_chain(ProgramHeader || task.program.data) where ProgramHeader is defined below. -# The function returns a pointer to the updated builtin pointers after executing the task. -func execute_task{builtin_ptrs : BuiltinData*, self_range_check_ptr}( - builtin_encodings : BuiltinData*, builtin_instance_sizes : BuiltinData* -): - # Allocate memory for local variables. - alloc_locals - - # Get the value of fp. - let (local __fp__, _) = get_fp_and_pc() - - # Pointer to the program data (which starts with ProgramHeader). - local program_data_ptr : felt* +const BOOTLOADER_VERSION = 0; + +// Use an empty struct to encode an arbitrary-length array. +struct BuiltinList { +} + +struct ProgramHeader { + // The data length field specifies the length of the data (i.e., program header + program) + // and guarantees unique decoding of the program hash. + data_length: felt, + bootloader_version: felt, + program_main: felt, + n_builtins: felt, + // 'builtin_list' is a continuous memory segment containing the ASCII encoding of the (ordered) + // builtins used by the program. + builtin_list: BuiltinList, +} + +struct BuiltinData { + output: felt, + pedersen: felt, + range_check: felt, + ecdsa: felt, + bitwise: felt, + ec_op: felt, + keccak: felt, +} + +// Executes a single task. +// The task is passed in the 'task' hint variable. +// Outputs of the task are prefixed by: +// a. Output size (including this prefix) +// b. hash_chain(ProgramHeader || task.program.data) where ProgramHeader is defined below. +// The function returns a pointer to the updated builtin pointers after executing the task. +func execute_task{builtin_ptrs: BuiltinData*, self_range_check_ptr}( + builtin_encodings: BuiltinData*, builtin_instance_sizes: BuiltinData* +) { + // Allocate memory for local variables. + alloc_locals; + + // Get the value of fp. + let (local __fp__, _) = get_fp_and_pc(); + + // Pointer to the program data (which starts with ProgramHeader). + local program_data_ptr: felt*; %{ ids.program_data_ptr = program_data_base = segments.add() %} - # The struct of input builtin pointers pointed by the given builtin_ptrs. - let input_builtin_ptrs : BuiltinData* = builtin_ptrs - local output_ptr = input_builtin_ptrs.output + // The struct of input builtin pointers pointed by the given builtin_ptrs. + let input_builtin_ptrs: BuiltinData* = builtin_ptrs; + local output_ptr = input_builtin_ptrs.output; - let program_header = cast(program_data_ptr, ProgramHeader*) + let program_header = cast(program_data_ptr, ProgramHeader*); %{ from starkware.cairo.bootloaders.simple_bootloader.utils import load_program @@ -66,14 +67,14 @@ func execute_task{builtin_ptrs : BuiltinData*, self_range_check_ptr}( segments.finalize(program_data_base.segment_index, program_data_size) %} - # Verify that the bootloader version is compatible with the bootloader. - assert program_header.bootloader_version = BOOTLOADER_VERSION + // Verify that the bootloader version is compatible with the bootloader. + assert program_header.bootloader_version = BOOTLOADER_VERSION; - # Call hash_chain, to verify the program hash. - let pedersen_ptr = cast(input_builtin_ptrs.pedersen, HashBuiltin*) - let (hash) = hash_chain{hash_ptr=pedersen_ptr}(data_ptr=program_data_ptr) - # Write hash_chain result to output_ptr + 1. - assert [output_ptr + 1] = hash + // Call hash_chain, to verify the program hash. + let pedersen_ptr = cast(input_builtin_ptrs.pedersen, HashBuiltin*); + let (hash) = hash_chain{hash_ptr=pedersen_ptr}(data_ptr=program_data_ptr); + // Write hash_chain result to output_ptr + 1. + assert [output_ptr + 1] = hash; %{ # Validate hash. from starkware.cairo.bootloaders.hash_program import compute_program_hash_chain @@ -82,35 +83,36 @@ func execute_task{builtin_ptrs : BuiltinData*, self_range_check_ptr}( 'Computed hash does not match input.' %} - # Set the program entry point, so the bootloader can later run the program. - local builtin_list : felt* = &program_header.builtin_list - local n_builtins = program_header.n_builtins - tempvar program_address = builtin_list + n_builtins + // Set the program entry point, so the bootloader can later run the program. + local builtin_list: felt* = &program_header.builtin_list; + local n_builtins = program_header.n_builtins; + tempvar program_address = builtin_list + n_builtins; %{ # Sanity check. assert ids.program_address == program_address %} - tempvar program_main = program_header.program_main - # The address in memory where the main function of the task is loaded. - local program_entry_point : felt* = program_address + program_main + tempvar program_main = program_header.program_main; + // The address in memory where the main function of the task is loaded. + local program_entry_point: felt* = program_address + program_main; - # Fill in all builtin pointers which may be used by the task. - # Skip the 2 slots prefix that we add to the task output. - local pre_execution_builtin_ptrs : BuiltinData = BuiltinData( + // Fill in all builtin pointers which may be used by the task. + // Skip the 2 slots prefix that we add to the task output. + local pre_execution_builtin_ptrs: BuiltinData = BuiltinData( output=output_ptr + 2, pedersen=cast(pedersen_ptr, felt), range_check=input_builtin_ptrs.range_check, ecdsa=input_builtin_ptrs.ecdsa, bitwise=input_builtin_ptrs.bitwise, - ec_op=input_builtin_ptrs.ec_op) + ec_op=input_builtin_ptrs.ec_op, + keccak=input_builtin_ptrs.keccak); - # Call select_input_builtins to get the relevant input builtin pointers for the task. + // Call select_input_builtins to get the relevant input builtin pointers for the task. select_input_builtins( all_encodings=builtin_encodings, all_ptrs=&pre_execution_builtin_ptrs, selected_encodings=builtin_list, n_selected_builtins=n_builtins, - ) + ); call_task: %{ @@ -137,7 +139,7 @@ func execute_task{builtin_ptrs : BuiltinData*, self_range_check_ptr}( load_cairo_pie( task=task.cairo_pie, memory=memory, segments=segments, program_address=program_address, execution_segment_address= ap - n_builtins, - ecdsa_builtin=ecdsa_builtin, ret_fp=fp, ret_pc=ret_pc) + builtin_runners=builtin_runners, ret_fp=fp, ret_pc=ret_pc) else: raise NotImplementedError(f'Unexpected task type: {type(task).__name__}.') @@ -148,8 +150,8 @@ func execute_task{builtin_ptrs : BuiltinData*, self_range_check_ptr}( vm_enter_scope(new_task_locals) %} - # Call the inner program's main() function. - call abs program_entry_point + // Call the inner program's main() function. + call abs program_entry_point; ret_pc_label: %{ @@ -157,16 +159,16 @@ func execute_task{builtin_ptrs : BuiltinData*, self_range_check_ptr}( # Note that bootloader_input will only be available in the next hint. %} - # Note that used_builtins_addr cannot be set in a hint because doing so will allow a malicious - # prover to lie about the outputs of a valid program. - let (ap_val) = get_ap() - local used_builtins_addr : felt* = cast(ap_val - n_builtins, felt*) + // Note that used_builtins_addr cannot be set in a hint because doing so will allow a malicious + // prover to lie about the outputs of a valid program. + let (ap_val) = get_ap(); + local used_builtins_addr: felt* = cast(ap_val - n_builtins, felt*); - # Call inner_select_builtins to validate that the values of the builtin pointers for the next - # task are updated according to the task return builtin pointers. + // Call inner_select_builtins to validate that the values of the builtin pointers for the next + // task are updated according to the task return builtin pointers. - # Allocate a struct containing all builtin pointers just after the program returns. - local return_builtin_ptrs : BuiltinData + // Allocate a struct containing all builtin pointers just after the program returns. + local return_builtin_ptrs: BuiltinData; %{ from starkware.cairo.bootloaders.simple_bootloader.utils import write_return_builtins @@ -185,25 +187,25 @@ func execute_task{builtin_ptrs : BuiltinData*, self_range_check_ptr}( selected_encodings=builtin_list, selected_ptrs=used_builtins_addr, n_builtins=BuiltinData.SIZE, - ) + ); %{ vm_exit_scope() %} - # Assert that the correct number of builtins was selected. - # Note that builtin_list is a pointer to the list containing the selected encodings. - assert n_builtins = select_builtins_ret.selected_encodings_end - builtin_list + // Assert that the correct number of builtins was selected. + // Note that builtin_list is a pointer to the list containing the selected encodings. + assert n_builtins = select_builtins_ret.selected_encodings_end - builtin_list; - # Call validate_builtins to validate that the builtin pointers have advanced correctly. + // Call validate_builtins to validate that the builtin pointers have advanced correctly. validate_builtins{range_check_ptr=self_range_check_ptr}( prev_builtin_ptrs=&pre_execution_builtin_ptrs, new_builtin_ptrs=&return_builtin_ptrs, builtin_instance_sizes=builtin_instance_sizes, n_builtins=BuiltinData.SIZE, - ) + ); - # Verify that [output_ptr] = return_builtin_ptrs.output - output_ptr. - # Output size should be 2 + the number of output slots that were consumed by the task. - local output_size = return_builtin_ptrs.output - output_ptr - assert [output_ptr] = output_size + // Verify that [output_ptr] = return_builtin_ptrs.output - output_ptr. + // Output size should be 2 + the number of output slots that were consumed by the task. + local output_size = return_builtin_ptrs.output - output_ptr; + assert [output_ptr] = output_size; %{ from starkware.cairo.bootloaders.simple_bootloader.utils import get_task_fact_topology @@ -219,6 +221,6 @@ func execute_task{builtin_ptrs : BuiltinData*, self_range_check_ptr}( )) %} - let builtin_ptrs = &return_builtin_ptrs - return () -end + let builtin_ptrs = &return_builtin_ptrs; + return (); +} diff --git a/src/starkware/cairo/bootloaders/simple_bootloader/run_simple_bootloader.cairo b/src/starkware/cairo/bootloaders/simple_bootloader/run_simple_bootloader.cairo index 5f685f84..b220df46 100644 --- a/src/starkware/cairo/bootloaders/simple_bootloader/run_simple_bootloader.cairo +++ b/src/starkware/cairo/bootloaders/simple_bootloader/run_simple_bootloader.cairo @@ -2,24 +2,25 @@ from starkware.cairo.bootloaders.simple_bootloader.execute_task import BuiltinDa from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.registers import get_fp_and_pc -# Loads the programs and executes them. -# -# Hint Arguments: -# simple_bootloader_input - contains the tasks to execute. -# -# Returns: -# Updated builtin pointers after executing all programs. -# fact_topologies - that corresponds to the tasks (hint variable). +// Loads the programs and executes them. +// +// Hint Arguments: +// simple_bootloader_input - contains the tasks to execute. +// +// Returns: +// Updated builtin pointers after executing all programs. +// fact_topologies - that corresponds to the tasks (hint variable). func run_simple_bootloader{ - output_ptr : felt*, - pedersen_ptr : HashBuiltin*, + output_ptr: felt*, + pedersen_ptr: HashBuiltin*, range_check_ptr, ecdsa_ptr, bitwise_ptr, ec_op_ptr, -}(): - alloc_locals - local task_range_check_ptr + keccak_ptr, +}() { + alloc_locals; + local task_range_check_ptr; %{ n_tasks = len(simple_bootloader_input.tasks) @@ -29,102 +30,113 @@ func run_simple_bootloader{ # this is validated later in this function. ids.task_range_check_ptr = ids.range_check_ptr + ids.BuiltinData.SIZE * n_tasks - # A list of fact_tooplogies that instruct how to generate the fact from the program output + # A list of fact_toplogies that instruct how to generate the fact from the program output # for each task. fact_topologies = [] %} - let n_tasks = [output_ptr] - let output_ptr = output_ptr + 1 + let n_tasks = [output_ptr]; + let output_ptr = output_ptr + 1; - # A struct containing the pointer to each builtin. - local builtin_ptrs_before : BuiltinData = BuiltinData( + // A struct containing the pointer to each builtin. + local builtin_ptrs_before: BuiltinData = BuiltinData( output=cast(output_ptr, felt), pedersen=cast(pedersen_ptr, felt), range_check=task_range_check_ptr, ecdsa=ecdsa_ptr, bitwise=bitwise_ptr, - ec_op=ec_op_ptr) + ec_op=ec_op_ptr, + keccak=keccak_ptr); - # A struct containing the encoding of each builtin. - local builtin_encodings : BuiltinData = BuiltinData( + // A struct containing the encoding of each builtin. + local builtin_encodings: BuiltinData = BuiltinData( output='output', pedersen='pedersen', range_check='range_check', ecdsa='ecdsa', bitwise='bitwise', - ec_op='ec_op') + ec_op='ec_op', + keccak='keccak'); - local builtin_instance_sizes : BuiltinData = BuiltinData( - output=1, pedersen=3, range_check=1, ecdsa=2, bitwise=5, ec_op=7) + local builtin_instance_sizes: BuiltinData = BuiltinData( + output=1, pedersen=3, range_check=1, ecdsa=2, bitwise=5, ec_op=7, keccak=16); - # Call execute_tasks. - let (__fp__, _) = get_fp_and_pc() + // Call execute_tasks. + let (__fp__, _) = get_fp_and_pc(); %{ tasks = simple_bootloader_input.tasks %} - let builtin_ptrs = &builtin_ptrs_before - let self_range_check_ptr = range_check_ptr - with builtin_ptrs, self_range_check_ptr: + let builtin_ptrs = &builtin_ptrs_before; + let self_range_check_ptr = range_check_ptr; + with builtin_ptrs, self_range_check_ptr { execute_tasks( builtin_encodings=&builtin_encodings, builtin_instance_sizes=&builtin_instance_sizes, n_tasks=n_tasks, - ) - end - - # Verify that the task range checks appear after the self range checks of execute_task. - assert self_range_check_ptr = task_range_check_ptr - - # Return the updated builtin pointers. - local builtin_ptrs : BuiltinData* = builtin_ptrs - let output_ptr = cast(builtin_ptrs.output, felt*) - let pedersen_ptr = cast(builtin_ptrs.pedersen, HashBuiltin*) - let range_check_ptr = builtin_ptrs.range_check - let ecdsa_ptr = builtin_ptrs.ecdsa - let bitwise_ptr = builtin_ptrs.bitwise - let ec_op_ptr = builtin_ptrs.ec_op - - # Verify that range_check has indeed advanced. - let additional_range_checks = range_check_ptr - self_range_check_ptr - verify_non_negative(num=additional_range_checks, n_bits=64) - - return () -end - -# Verifies that a field element is in the range [0, 2^n_bits), without relying on the range_check -# builtin. -func verify_non_negative(num : felt, n_bits : felt): - if n_bits == 0: - assert num = 0 - return () - end - - tempvar num_div2 = nondet %{ ids.num // 2 %} - tempvar bit = num - (num_div2 + num_div2) - # Check that bit is 0 or 1. - assert bit = bit * bit - return verify_non_negative(num=num_div2, n_bits=n_bits - 1) -end - -# Executes the last n_tasks from simple_bootloader_input.tasks. -# -# Arguments: -# builtin_encodings - String encodings of the builtins. -# builtin_instance_sizes - Mapping to builtin sizes. -# n_tasks - The number of tasks to execute. -# -# Implicit arguments: -# builtin_ptrs - Pointer to the builtin pointers before/after executing the tasks. -# self_range_check_ptr - range_check pointer (used for validating the builtins). -# -# Hint arguments: -# tasks - A list of tasks to execute. -func execute_tasks{builtin_ptrs : BuiltinData*, self_range_check_ptr}( - builtin_encodings : BuiltinData*, builtin_instance_sizes : BuiltinData*, n_tasks -): - if n_tasks == 0: - return () - end + ); + } + + // Verify that the task range checks appear after the self range checks of execute_task. + assert self_range_check_ptr = task_range_check_ptr; + + // Return the updated builtin pointers. + local builtin_ptrs: BuiltinData* = builtin_ptrs; + let output_ptr = cast(builtin_ptrs.output, felt*); + let pedersen_ptr = cast(builtin_ptrs.pedersen, HashBuiltin*); + let range_check_ptr = builtin_ptrs.range_check; + let ecdsa_ptr = builtin_ptrs.ecdsa; + let bitwise_ptr = builtin_ptrs.bitwise; + let ec_op_ptr = builtin_ptrs.ec_op; + let keccak_ptr = builtin_ptrs.keccak; + + // 'execute_tasks' runs untrusted code and uses the range_check builtin to verify that + // the builtin pointers were advanced correctly by said code. + // Since range_check itself is used for the verification, we cannot assume that the verification + // above is sound unless we know that the self range checks that were used during verification + // are indeed valid (that is, within the segment of the range_check builtin). + // Following the Cairo calling convention, we can guarantee the validity of the self range + // checks by making sure that range_check_ptr >= self_range_check_ptr. + // The following check validates that the inequality above holds without using the range check + // builtin. + let additional_range_checks = range_check_ptr - self_range_check_ptr; + verify_non_negative(num=additional_range_checks, n_bits=64); + + return (); +} + +// Verifies that a field element is in the range [0, 2^n_bits), without relying on the range_check +// builtin. +func verify_non_negative(num: felt, n_bits: felt) { + if (n_bits == 0) { + assert num = 0; + return (); + } + + tempvar num_div2 = nondet %{ ids.num // 2 %}; + tempvar bit = num - (num_div2 + num_div2); + // Check that bit is 0 or 1. + assert bit = bit * bit; + return verify_non_negative(num=num_div2, n_bits=n_bits - 1); +} + +// Executes the last n_tasks from simple_bootloader_input.tasks. +// +// Arguments: +// builtin_encodings - String encodings of the builtins. +// builtin_instance_sizes - Mapping to builtin sizes. +// n_tasks - The number of tasks to execute. +// +// Implicit arguments: +// builtin_ptrs - Pointer to the builtin pointers before/after executing the tasks. +// self_range_check_ptr - range_check pointer (used for validating the builtins). +// +// Hint arguments: +// tasks - A list of tasks to execute. +func execute_tasks{builtin_ptrs: BuiltinData*, self_range_check_ptr}( + builtin_encodings: BuiltinData*, builtin_instance_sizes: BuiltinData*, n_tasks +) { + if (n_tasks == 0) { + return (); + } %{ from starkware.cairo.bootloaders.simple_bootloader.objects import Task @@ -133,12 +145,14 @@ func execute_tasks{builtin_ptrs : BuiltinData*, self_range_check_ptr}( task_id = len(simple_bootloader_input.tasks) - ids.n_tasks task = simple_bootloader_input.tasks[task_id].load_task() %} - # Call execute_task to execute the current task. - execute_task(builtin_encodings=builtin_encodings, builtin_instance_sizes=builtin_instance_sizes) + // Call execute_task to execute the current task. + execute_task( + builtin_encodings=builtin_encodings, builtin_instance_sizes=builtin_instance_sizes + ); return execute_tasks( builtin_encodings=builtin_encodings, builtin_instance_sizes=builtin_instance_sizes, n_tasks=n_tasks - 1, - ) -end + ); +} diff --git a/src/starkware/cairo/bootloaders/simple_bootloader/simple_bootloader.cairo b/src/starkware/cairo/bootloaders/simple_bootloader/simple_bootloader.cairo index 386c682c..6f727425 100644 --- a/src/starkware/cairo/bootloaders/simple_bootloader/simple_bootloader.cairo +++ b/src/starkware/cairo/bootloaders/simple_bootloader/simple_bootloader.cairo @@ -1,4 +1,4 @@ -%builtins output pedersen range_check ecdsa bitwise ec_op +%builtins output pedersen range_check ecdsa bitwise ec_op keccak from starkware.cairo.bootloaders.simple_bootloader.run_simple_bootloader import ( run_simple_bootloader, @@ -7,20 +7,21 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.registers import get_fp_and_pc func main{ - output_ptr : felt*, - pedersen_ptr : HashBuiltin*, + output_ptr: felt*, + pedersen_ptr: HashBuiltin*, range_check_ptr, ecdsa_ptr, bitwise_ptr, ec_op_ptr, -}(): + keccak_ptr, +}() { %{ from starkware.cairo.bootloaders.simple_bootloader.objects import SimpleBootloaderInput simple_bootloader_input = SimpleBootloaderInput.Schema().load(program_input) %} - # Execute tasks. - run_simple_bootloader() + // Execute tasks. + run_simple_bootloader(); %{ # Dump fact topologies to a json file. @@ -45,5 +46,5 @@ func main{ fact_topologies=fact_topologies, ) %} - return () -end + return (); +} diff --git a/src/starkware/cairo/builtin_selection/inner_select_builtins.cairo b/src/starkware/cairo/builtin_selection/inner_select_builtins.cairo index 06d16e5a..38615799 100644 --- a/src/starkware/cairo/builtin_selection/inner_select_builtins.cairo +++ b/src/starkware/cairo/builtin_selection/inner_select_builtins.cairo @@ -1,40 +1,40 @@ -# An helper function to extract selected_ptrs from all_ptrs according to the builtin encodings -# that appear in the selected_encodings list. -# The caller needs to pass n_selected_builtins as a hint. -# Returns a pointer to the next memory slot after the selected_encodings list, see "Assumptions". -# -# For example, given the following setup: -# - all_encodings points to ["output", "pedersen", "range-check"]. -# - selected_encodings points to ["output", "range-check"] -# - all_ptrs points to [output_ptr, pedersen_ptr, range_check_ptr] -# - The caller asserts that the return value is selected_encodings + n_selected_builtins(2). -# The function will check that selected_encodings points to [output_ptr, range_check_ptr]. -# -# n_builtins is the length of the list of *all pointers*. -# Assumptions: -# * The caller has to check that n_selected_builtins = selected_encodings_end - selected_encodings. -# * All lists are sorted according to the order of builtins input in Cairo programs. -# * len(selected_encodings) <= len(all_encodings) == len(all_ptrs). +// An helper function to extract selected_ptrs from all_ptrs according to the builtin encodings +// that appear in the selected_encodings list. +// The caller needs to pass n_selected_builtins as a hint. +// Returns a pointer to the next memory slot after the selected_encodings list, see "Assumptions". +// +// For example, given the following setup: +// - all_encodings points to ["output", "pedersen", "range-check"]. +// - selected_encodings points to ["output", "range-check"] +// - all_ptrs points to [output_ptr, pedersen_ptr, range_check_ptr] +// - The caller asserts that the return value is selected_encodings + n_selected_builtins(2). +// The function will check that selected_encodings points to [output_ptr, range_check_ptr]. +// +// n_builtins is the length of the list of *all pointers*. +// Assumptions: +// * The caller has to check that n_selected_builtins = selected_encodings_end - selected_encodings. +// * All lists are sorted according to the order of builtins input in Cairo programs. +// * len(selected_encodings) <= len(all_encodings) == len(all_ptrs). func inner_select_builtins( - all_encodings : felt*, - all_ptrs : felt*, - selected_encodings : felt*, - selected_ptrs : felt*, + all_encodings: felt*, + all_ptrs: felt*, + selected_encodings: felt*, + selected_ptrs: felt*, n_builtins, -) -> (selected_encodings_end : felt*): - # Number of memory cells used when n_builtins = 0. - const FUNC_MEMORY_NO_BUILTINS = 1 - # Number of memory cells used *in a single iteration* when n_builtins > 0. - const FUNC_MEMORY_WITH_BUILTINS = 10 +) -> (selected_encodings_end: felt*) { + // Number of memory cells used when n_builtins = 0. + const FUNC_MEMORY_NO_BUILTINS = 1; + // Number of memory cells used *in a single iteration* when n_builtins > 0. + const FUNC_MEMORY_WITH_BUILTINS = 10; - if n_builtins == 0: - # Return a pointer to the end of the selected_encodings list. - return (selected_encodings_end=selected_encodings) - end + if (n_builtins == 0) { + // Return a pointer to the end of the selected_encodings list. + return (selected_encodings_end=selected_encodings); + } - alloc_locals - # select_builtin equals 1 if the first builtin should be selected and 0 otherwise. - local select_builtin + alloc_locals; + // select_builtin equals 1 if the first builtin should be selected and 0 otherwise. + local select_builtin; %{ # A builtin should be selected iff its encoding appears in the selected encodings list # and the list wasn't exhausted. @@ -44,28 +44,28 @@ func inner_select_builtins( if ids.select_builtin: n_selected_builtins = n_selected_builtins - 1 %} - # Verify that select_builtin is a bit. - select_builtin = select_builtin * select_builtin + // Verify that select_builtin is a bit. + select_builtin = select_builtin * select_builtin; - local curr_builtin_encoding = [all_encodings] - local curr_builtin_ptr = [all_ptrs] + local curr_builtin_encoding = [all_encodings]; + local curr_builtin_ptr = [all_ptrs]; - if select_builtin != 0: - # Verify that the current builtin is indeed selected, by asserting that its encoding appears - # in the selected encodings list. - curr_builtin_encoding = [selected_encodings] - # Copy the current builtin pointer between selected_ptrs and all_ptrs. - curr_builtin_ptr = [selected_ptrs] - end + if (select_builtin != 0) { + // Verify that the current builtin is indeed selected, by asserting that its encoding + // appears in the selected encodings list. + curr_builtin_encoding = [selected_encodings]; + // Copy the current builtin pointer between selected_ptrs and all_ptrs. + curr_builtin_ptr = [selected_ptrs]; + } - # Advance all list pointers accordingly and continue selection by calling inner_select_builtins - # recursively. - # Lists of selected builtins/encodings should advance only if the current builtin was selected. + // Advance all list pointers accordingly and continue selection by calling inner_select_builtins + // recursively. + // Lists of selected builtins/encodings should advance only if the current builtin was selected. return inner_select_builtins( all_encodings=all_encodings + 1, all_ptrs=all_ptrs + 1, selected_encodings=selected_encodings + select_builtin, selected_ptrs=selected_ptrs + select_builtin, n_builtins=n_builtins - 1, - ) -end + ); +} diff --git a/src/starkware/cairo/builtin_selection/select_builtins.cairo b/src/starkware/cairo/builtin_selection/select_builtins.cairo index aa4af146..299d07b2 100644 --- a/src/starkware/cairo/builtin_selection/select_builtins.cairo +++ b/src/starkware/cairo/builtin_selection/select_builtins.cairo @@ -1,14 +1,14 @@ from starkware.cairo.builtin_selection.inner_select_builtins import inner_select_builtins -# A wrapper for 'inner_select_builtins' function (see its documentation). +// A wrapper for 'inner_select_builtins' function (see its documentation). func select_builtins( n_builtins, - all_encodings : felt*, - all_ptrs : felt*, + all_encodings: felt*, + all_ptrs: felt*, n_selected_builtins, - selected_encodings : felt*, - selected_ptrs : felt*, -): + selected_encodings: felt*, + selected_ptrs: felt*, +) { %{ vm_enter_scope({'n_selected_builtins': ids.n_selected_builtins}) %} let (selected_encodings_end) = inner_select_builtins( all_encodings=all_encodings, @@ -16,10 +16,10 @@ func select_builtins( selected_encodings=selected_encodings, selected_ptrs=selected_ptrs, n_builtins=n_builtins, - ) + ); %{ vm_exit_scope() %} - # Assert that the correct number of builtins was selected. - assert n_selected_builtins = selected_encodings_end - selected_encodings + // Assert that the correct number of builtins was selected. + assert n_selected_builtins = selected_encodings_end - selected_encodings; - return () -end + return (); +} diff --git a/src/starkware/cairo/builtin_selection/select_input_builtins.cairo b/src/starkware/cairo/builtin_selection/select_input_builtins.cairo index 3456d6a3..cb06b0a3 100644 --- a/src/starkware/cairo/builtin_selection/select_input_builtins.cairo +++ b/src/starkware/cairo/builtin_selection/select_input_builtins.cairo @@ -1,28 +1,28 @@ from starkware.cairo.builtin_selection.inner_select_builtins import inner_select_builtins from starkware.cairo.common.registers import get_fp_and_pc -# A wrapper for 'inner_select_builtins' function (see its documentation). -# Returns the selected builtin pointers (e.g., if n_selected_builtins=2, returns two values). -# Note that the function assumes that the total number of builtins is 4, and so the length of -# all_encodings, all_ptrs must be 4. +// A wrapper for 'inner_select_builtins' function (see its documentation). +// Returns the selected builtin pointers (e.g., if n_selected_builtins=2, returns two values). +// Note that the function assumes that the total number of builtins is 4, and so the length of +// all_encodings, all_ptrs must be 4. func select_input_builtins( - all_encodings : felt*, all_ptrs : felt*, selected_encodings : felt*, n_selected_builtins -): - # Total number of optional builtins. - const N_BUILTINS = 6 - # Number of memory cells used, without taking the inner function memory into account. - const FUNC_MEMORY_WITHOUT_INNER_FUNC = 9 - const INNER_FUNC_MEMORY_PER_ITERATION = inner_select_builtins.FUNC_MEMORY_WITH_BUILTINS - const INNER_FUNC_MEMORY_FINAL_ITERATION = inner_select_builtins.FUNC_MEMORY_NO_BUILTINS - # 'inner_select_builtins' has N_BUILTINS iterations, until the final halting one, when called - # with n_builtins = N_BUILTINS. + all_encodings: felt*, all_ptrs: felt*, selected_encodings: felt*, n_selected_builtins +) { + // Total number of optional builtins. + const N_BUILTINS = 7; + // Number of memory cells used, without taking the inner function memory into account. + const FUNC_MEMORY_WITHOUT_INNER_FUNC = 9; + const INNER_FUNC_MEMORY_PER_ITERATION = inner_select_builtins.FUNC_MEMORY_WITH_BUILTINS; + const INNER_FUNC_MEMORY_FINAL_ITERATION = inner_select_builtins.FUNC_MEMORY_NO_BUILTINS; + // 'inner_select_builtins' has N_BUILTINS iterations, until the final halting one, when called + // with n_builtins = N_BUILTINS. const INNER_FUNC_MEMORY = N_BUILTINS * INNER_FUNC_MEMORY_PER_ITERATION + - INNER_FUNC_MEMORY_FINAL_ITERATION - const TOTAL_FUNC_MEMORY = FUNC_MEMORY_WITHOUT_INNER_FUNC + INNER_FUNC_MEMORY + INNER_FUNC_MEMORY_FINAL_ITERATION; + const TOTAL_FUNC_MEMORY = FUNC_MEMORY_WITHOUT_INNER_FUNC + INNER_FUNC_MEMORY; - let frame = call get_fp_and_pc - # The selected builtin pointers are the return values at the end of the function memory. - let selected_ptrs = cast(frame.fp_val + TOTAL_FUNC_MEMORY, felt*) + let frame = call get_fp_and_pc; + // The selected builtin pointers are the return values at the end of the function memory. + let selected_ptrs = cast(frame.fp_val + TOTAL_FUNC_MEMORY, felt*); %{ vm_enter_scope({'n_selected_builtins': ids.n_selected_builtins}) %} let inner_ret = inner_select_builtins( all_encodings=all_encodings, @@ -30,11 +30,11 @@ func select_input_builtins( selected_encodings=selected_encodings, selected_ptrs=selected_ptrs, n_builtins=N_BUILTINS, - ) + ); %{ vm_exit_scope() %} - # Assert that the correct number of builtins was selected. - n_selected_builtins = inner_ret.selected_encodings_end - selected_encodings + // Assert that the correct number of builtins was selected. + n_selected_builtins = inner_ret.selected_encodings_end - selected_encodings; - ap += n_selected_builtins - ret -end + ap += n_selected_builtins; + ret; +} diff --git a/src/starkware/cairo/builtin_selection/validate_builtins.cairo b/src/starkware/cairo/builtin_selection/validate_builtins.cairo index 413286dd..790a5fd3 100644 --- a/src/starkware/cairo/builtin_selection/validate_builtins.cairo +++ b/src/starkware/cairo/builtin_selection/validate_builtins.cairo @@ -1,56 +1,56 @@ -# Validates that the builtin pointer of a single builtin was advanced correctly. -# The inputs are: -# The previous builtin pointer. -# The new builtin pointer. -# The size of the builtin instances. -# The function validates that the difference between the new builtin pointer and the old builtin -# pointer is a positive integer divisible by the given builtin instance size. -# -# The function consumes 1 range check instance starting at range_check_ptr and returns the -# updated range check pointer. +// Validates that the builtin pointer of a single builtin was advanced correctly. +// The inputs are: +// The previous builtin pointer. +// The new builtin pointer. +// The size of the builtin instances. +// The function validates that the difference between the new builtin pointer and the old builtin +// pointer is a positive integer divisible by the given builtin instance size. +// +// The function consumes 1 range check instance starting at range_check_ptr and returns the +// updated range check pointer. func validate_builtin{range_check_ptr}( - prev_builtin_ptr : felt*, new_builtin_ptr : felt*, builtin_instance_size : felt -): - # Check that the difference is positive and divisible by builtin_instance_size by checking that - # 0 <= div_res < RANGE_CHECK_BOUND and diff = div_res * builtin_instance_size. - tempvar diff = new_builtin_ptr - prev_builtin_ptr - tempvar div_res = diff / builtin_instance_size - div_res = [range_check_ptr] - let range_check_ptr = range_check_ptr + 1 - return () -end + prev_builtin_ptr: felt*, new_builtin_ptr: felt*, builtin_instance_size: felt +) { + // Check that the difference is positive and divisible by builtin_instance_size by checking that + // 0 <= div_res < RANGE_CHECK_BOUND and diff = div_res * builtin_instance_size. + tempvar diff = new_builtin_ptr - prev_builtin_ptr; + tempvar div_res = diff / builtin_instance_size; + div_res = [range_check_ptr]; + let range_check_ptr = range_check_ptr + 1; + return (); +} -# Validates that the builtin pointers were advanced correctly. -# -# The inputs are: -# The previous list of builtin pointers. -# The new list of builtin pointers. -# The sizes of the builtin instances. -# The number of builtins. -# -# For each builtin the function validates that the difference between the new builtin pointer and -# the old builtin pointer is a nonnegative integer divisible by the corresponding builtin -# instance size. -# -# The function consumes n_builtins range check instances starting at range_check_ptr and returns the -# updated range check pointer. +// Validates that the builtin pointers were advanced correctly. +// +// The inputs are: +// The previous list of builtin pointers. +// The new list of builtin pointers. +// The sizes of the builtin instances. +// The number of builtins. +// +// For each builtin the function validates that the difference between the new builtin pointer and +// the old builtin pointer is a nonnegative integer divisible by the corresponding builtin +// instance size. +// +// The function consumes n_builtins range check instances starting at range_check_ptr and returns +// the updated range check pointer. func validate_builtins{range_check_ptr}( - prev_builtin_ptrs : felt*, new_builtin_ptrs : felt*, builtin_instance_sizes : felt*, n_builtins -): - if n_builtins == 0: - return () - end + prev_builtin_ptrs: felt*, new_builtin_ptrs: felt*, builtin_instance_sizes: felt*, n_builtins +) { + if (n_builtins == 0) { + return (); + } validate_builtin( prev_builtin_ptr=cast([prev_builtin_ptrs], felt*), new_builtin_ptr=cast([new_builtin_ptrs], felt*), builtin_instance_size=[builtin_instance_sizes], - ) + ); return validate_builtins( prev_builtin_ptrs=prev_builtin_ptrs + 1, new_builtin_ptrs=new_builtin_ptrs + 1, builtin_instance_sizes=builtin_instance_sizes + 1, n_builtins=n_builtins - 1, - ) -end + ); +} diff --git a/src/starkware/cairo/cairo_verifier/CMakeLists.txt b/src/starkware/cairo/cairo_verifier/CMakeLists.txt new file mode 100644 index 00000000..fb3a9265 --- /dev/null +++ b/src/starkware/cairo/cairo_verifier/CMakeLists.txt @@ -0,0 +1,45 @@ +set(PROGRAM_ARTIFACTS) +add_custom_target(cairo_verifier_program_all_layouts) + +function(cairo_verifier_layout LAYOUT_NAME) + cairo_compile(cairo_verifier_program_${LAYOUT_NAME} + cairo_verifier_compiled_${LAYOUT_NAME}.json + layouts/${LAYOUT_NAME}/cairo_verifier.cairo + "--no_debug_info --proof_mode" + ) + set( + PROGRAM_ARTIFACTS + ${PROGRAM_ARTIFACTS} + "${CMAKE_CURRENT_BINARY_DIR}/cairo_verifier_compiled_${LAYOUT_NAME}.json cairo_verifier_compiled_${LAYOUT_NAME}.json" + PARENT_SCOPE + ) + add_dependencies(cairo_verifier_program_all_layouts cairo_verifier_program_${LAYOUT_NAME}) +endfunction() + +cairo_verifier_layout(recursive) + +full_python_test(cairo_verifier_program_hash_recursive_test + PREFIX starkware/cairo/cairo_verifier/ + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/cairo_verifier/ + + FILES + layouts/recursive/program_hash_test.py + layouts/recursive/program_hash.json + + LIBS + cairo_hash_program_lib + program_hash_test_utils_lib + starkware_python_utils_lib + pip_pytest + + ARTIFACTS + "${CMAKE_CURRENT_BINARY_DIR}/cairo_verifier_compiled_recursive.json cairo_verifier_compiled_recursive.json" +) +add_dependencies(cairo_verifier_program_hash_recursive_test_venv cairo_verifier_program_recursive) + +python_exe(generate_cairo_verifier_program_hash_recursive + VENV cairo_verifier_program_hash_recursive_test_venv + MODULE starkware.cairo.cairo_verifier.layouts.recursive.program_hash_test + ARGS "--fix" +) diff --git a/src/starkware/cairo/cairo_verifier/layouts/recursive/cairo_verifier.cairo b/src/starkware/cairo/cairo_verifier/layouts/recursive/cairo_verifier.cairo new file mode 100644 index 00000000..2e9ee742 --- /dev/null +++ b/src/starkware/cairo/cairo_verifier/layouts/recursive/cairo_verifier.cairo @@ -0,0 +1,206 @@ +%builtins output pedersen range_check bitwise + +from starkware.cairo.cairo_verifier.objects import CairoVerifierOutput +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin, HashBuiltin +from starkware.cairo.common.hash_state import hash_felts +from starkware.cairo.common.math import assert_nn_le +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layouts.recursive.public_verify import ( + get_layout_builtins, + segments, +) +from starkware.cairo.stark_verifier.air.layouts.recursive.verify import verify_proof +from starkware.cairo.stark_verifier.air.public_input import PublicInput, SegmentInfo +from starkware.cairo.stark_verifier.air.public_memory import AddrValue +from starkware.cairo.stark_verifier.core.stark import StarkProof + +const SECURITY_BITS = 80; +const MAX_ADDRESS = 2 ** 64 - 1; +const INITIAL_PC = 1; + +// Returns the list of builtins that need to be passed to the verified program. +// The list is zero-terminated. +// +// See verify_stack() for more detail. +func get_program_builtins() -> (n_builtins: felt, builtins: felt*) { + let (builtins_address) = get_label_location(data); + let n_builtins = 7; + assert builtins_address[n_builtins] = 0; + return (n_builtins=n_builtins, builtins=builtins_address); + + data: + dw 'output'; + dw 'pedersen'; + dw 'range_check'; + dw 'ecdsa'; + dw 'bitwise'; + dw 'ec_op'; + dw 'keccak'; + dw 0; +} + +// Verifies a complete Cairo proof of a Cairo program with a "start" section, with a single output +// page. +// Returns the program hash and the output hash. +func verify_cairo_proof{range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*}( + proof: StarkProof* +) -> (program_hash: felt, output_hash: felt) { + alloc_locals; + verify_proof(proof=proof, security_bits=SECURITY_BITS); + return _verify_public_input(public_input=cast(proof.public_input, PublicInput*)); +} + +func _verify_public_input{ + range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin* +}(public_input: PublicInput*) -> (program_hash: felt, output_hash: felt) { + alloc_locals; + local public_segments: SegmentInfo* = public_input.segments; + + local initial_pc = public_segments[segments.PROGRAM].begin_addr; + local final_pc = public_segments[segments.PROGRAM].stop_ptr; + local initial_ap = public_segments[segments.EXECUTION].begin_addr; + let initial_fp = initial_ap; + local final_ap = public_segments[segments.EXECUTION].stop_ptr; + local output_start = public_segments[segments.OUTPUT].begin_addr; + local output_stop = public_segments[segments.OUTPUT].stop_ptr; + + // Sanity checks. + assert_nn_le(initial_ap, MAX_ADDRESS); + assert_nn_le(final_ap, MAX_ADDRESS); + + assert public_input.n_continuous_pages = 0; + + // Program builtins. + let (n_program_builtins, program_builtins) = get_program_builtins(); + let (n_layout_builtins, layout_builtins) = get_layout_builtins(); + + // Verify the public memory. + let memory: AddrValue* = public_input.main_page; + with memory { + // 1. Program segment. + // Check that the program counter starts and ends at the right places. + assert initial_pc = INITIAL_PC; + assert final_pc = INITIAL_PC + 4; + // Extract program. + let (program: felt*) = alloc(); + let program_end_pc = initial_fp - 2; + let program_len = program_end_pc - initial_pc; + extract_range(addr=initial_pc, length=program_len, output=program); + // Check that the program starts with a "start" section as follows: + assert program[0] = 0x40780017fff7fff; // Instruction: ap += N_BUILTINS. + assert program[1] = n_program_builtins; + assert program[2] = 0x1104800180018000; // Instruction: call rel ?. + assert program[4] = 0x10780017fff7fff; // Instruction: jmp rel 0. + assert program[5] = 0x0; + // Program hash. + let (program_hash) = hash_felts{hash_ptr=pedersen_ptr}(data=program, length=program_len); + + // 2. Execution segment. + // 2.1. initial_fp, initial_pc. + // Make sure [initial_fp - 2] = initial_fp. + // This is required for the "safe call" feature (that is, all "call" instructions will + // return, even if the called function is malicious). + // It guarantees that it's not possible to create a cycle in the call stack. + assert memory[0] = AddrValue(address=initial_fp - 2, value=initial_fp); + // Make sure [initial_fp - 1] = 0. + assert memory[1] = AddrValue(address=initial_fp - 1, value=0); + let memory = &memory[2]; + // 2.2 main's arguments and return values. + verify_stack( + start_ap=initial_ap, + segment_addresses=&public_segments[2].begin_addr, + program_builtins=program_builtins, + layout_builtins=layout_builtins, + ); + verify_stack( + start_ap=final_ap - n_program_builtins, + segment_addresses=&public_segments[2].stop_ptr, + program_builtins=program_builtins, + layout_builtins=layout_builtins, + ); + // 3. Output segment. + let (output: felt*) = alloc(); + local output_len = output_stop - output_start; + extract_range(addr=output_start, length=output_len, output=output); + let (output_hash) = hash_felts{hash_ptr=pedersen_ptr}(data=output, length=output_len); + } + + // Make sure main_page_len is correct. + assert memory = &public_input.main_page[public_input.main_page_len]; + + return (program_hash=program_hash, output_hash=output_hash); +} + +// Verifies the initial or the final part of the stack. +// segment_addresses should point to either begin_addr, or stop_ptr for the segment of the first +// builtin, inside a SegmentInfo array (i.e. step SegmentInfo.SIZE). +func verify_stack{memory: AddrValue*}( + start_ap: felt, segment_addresses: felt*, program_builtins: felt*, layout_builtins: felt* +) { + if (program_builtins[0] == 0) { + // Done. + return (); + } + + if (program_builtins[0] != layout_builtins[0]) { + // Skip. + assert memory[0] = AddrValue(address=start_ap, value=0); + let memory = &memory[1]; + return verify_stack( + start_ap=start_ap + 1, + segment_addresses=segment_addresses, + program_builtins=&program_builtins[1], + layout_builtins=layout_builtins, + ); + } else { + // Use. + assert memory[0] = AddrValue(address=start_ap, value=[segment_addresses]); + let memory = &memory[1]; + return verify_stack( + start_ap=start_ap + 1, + segment_addresses=segment_addresses + SegmentInfo.SIZE, + program_builtins=&program_builtins[1], + layout_builtins=&layout_builtins[1], + ); + } +} + +// Extracts a consecutive memory range from the public memory of the Cairo proof. +func extract_range{memory: AddrValue*}(addr: felt, length: felt, output: felt*) { + if (length == 0) { + return (); + } + assert memory.address = addr; + assert output[0] = memory.value; + let memory = &memory[1]; + return extract_range(addr=addr + 1, length=length - 1, output=&output[1]); +} + +// Main function for the Cairo verifier. +// +// Hint arguments: +// program_input - Contains the inputs for the Cairo verifier. +// +// Outputs the program hash and the hash of the output. +func main{ + output_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin* +}() { + alloc_locals; + local proof: StarkProof*; + %{ + from starkware.cairo.stark_verifier.air.parser import parse_proof + ids.proof = segments.gen_arg(parse_proof( + identifiers=ids._context.identifiers, + proof_json=program_input["proof"])) + %} + let (program_hash, output_hash) = verify_cairo_proof(proof); + + // Write program_hash and output_hash to output. + assert [cast(output_ptr, CairoVerifierOutput*)] = CairoVerifierOutput( + program_hash=program_hash, + output_hash=output_hash); + let output_ptr = output_ptr + CairoVerifierOutput.SIZE; + + return (); +} diff --git a/src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash.json b/src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash.json new file mode 100644 index 00000000..007538a2 --- /dev/null +++ b/src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash.json @@ -0,0 +1,3 @@ +{ + "program_hash": "0x66b992b6eacd832abc3dd51ebedeb007b8b68a13941ef4eeaabd9a659294dd0" +} diff --git a/src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash_test.py b/src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash_test.py new file mode 100644 index 00000000..eeabf93d --- /dev/null +++ b/src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash_test.py @@ -0,0 +1,25 @@ +import os + +from starkware.cairo.bootloaders.program_hash_test_utils import ( + program_hash_test_main, + run_generate_hash_test, +) +from starkware.python.utils import get_source_dir_path + +PROGRAM_PATH = os.path.join( + os.path.dirname(__file__), "../../cairo_verifier_compiled_recursive.json" +) +HASH_PATH = get_source_dir_path( + "src/starkware/cairo/cairo_verifier/layouts/recursive/program_hash.json" +) +COMMAND = "generate_cairo_verifier_program_hash_recursive" + + +def test_program_hash(): + run_generate_hash_test( + fix=False, program_path=PROGRAM_PATH, hash_path=HASH_PATH, command=COMMAND + ) + + +if __name__ == "__main__": + program_hash_test_main(program_path=PROGRAM_PATH, hash_path=HASH_PATH, command=COMMAND) diff --git a/src/starkware/cairo/cairo_verifier/objects.cairo b/src/starkware/cairo/cairo_verifier/objects.cairo index eae3195a..5fbb64f6 100644 --- a/src/starkware/cairo/cairo_verifier/objects.cairo +++ b/src/starkware/cairo/cairo_verifier/objects.cairo @@ -1,4 +1,4 @@ -struct CairoVerifierOutput: - member program_hash : felt - member output_hash : felt -end +struct CairoVerifierOutput { + program_hash: felt, + output_hash: felt, +} diff --git a/src/starkware/cairo/common/CMakeLists.txt b/src/starkware/cairo/common/CMakeLists.txt index b1eda072..dd8714e8 100644 --- a/src/starkware/cairo/common/CMakeLists.txt +++ b/src/starkware/cairo/common/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectory(cairo_blake2s) + python_lib(cairo_common_lib PREFIX starkware/cairo/common FILES @@ -32,6 +34,7 @@ python_lib(cairo_common_lib hash.cairo invoke.cairo keccak.cairo + keccak_state.cairo math_cmp.cairo math_utils.py math.cairo @@ -62,35 +65,29 @@ python_lib(cairo_common_lib ${CAIRO_COMMON_LIB_ADDITIONAL_LIBS} ) -python_lib(cairo_function_runner_lib +python_lib(cairo_common_validate_utils_lib PREFIX starkware/cairo/common - FILES - cairo_function_runner.py + validate_utils.py LIBS - cairo_common_lib - cairo_compile_lib cairo_run_builtins_lib cairo_run_lib - cairo_tracer_lib - cairo_vm_crypto_lib cairo_vm_lib ) -full_python_test(cairo_common_test +python_lib(cairo_function_runner_lib PREFIX starkware/cairo/common - PYTHON ${PYTHON_COMMAND} - TESTED_MODULES starkware/cairo/common FILES - cairo_blake2s/blake2s_test.cairo - cairo_blake2s/blake2s_test.py + cairo_function_runner.py LIBS cairo_common_lib - cairo_constants_lib - cairo_function_runner_lib - pip_pytest - pip_pytest_asyncio + cairo_compile_lib + cairo_run_builtins_lib + cairo_run_lib + cairo_tracer_lib + cairo_vm_crypto_lib + cairo_vm_lib ) diff --git a/src/starkware/cairo/common/alloc.cairo b/src/starkware/cairo/common/alloc.cairo index 320e3dd8..89568f6c 100644 --- a/src/starkware/cairo/common/alloc.cairo +++ b/src/starkware/cairo/common/alloc.cairo @@ -1,6 +1,6 @@ -# Allocates a new memory segment. -func alloc() -> (ptr : felt*): +// Allocates a new memory segment. +func alloc() -> (ptr: felt*) { %{ memory[ap] = segments.add() %} - ap += 1 - return (ptr=cast([ap - 1], felt*)) -end + ap += 1; + return (ptr=cast([ap - 1], felt*)); +} diff --git a/src/starkware/cairo/common/bitwise.cairo b/src/starkware/cairo/common/bitwise.cairo index 8cec36a8..98bc89cf 100644 --- a/src/starkware/cairo/common/bitwise.cairo +++ b/src/starkware/cairo/common/bitwise.cairo @@ -1,95 +1,95 @@ from starkware.cairo.common.cairo_builtins import BitwiseBuiltin -const ALL_ONES = 2 ** 251 - 1 +const ALL_ONES = 2 ** 251 - 1; -# Computes the bitwise operations and, xor and or. -# -# Arguments: -# bitwise_ptr - the bitwise builtin pointer. -# x, y - the two field elements to operate on, in this order. Both inputs should be 251-bit -# integers, and are taken as unsigned ints. -# -# Returns: -# x_and_y = x & y (bitwise and). -# x_xor_y = x ^ y (bitwise xor). -# x_or_y = x | y (bitwise or). -func bitwise_operations{bitwise_ptr : BitwiseBuiltin*}(x : felt, y : felt) -> ( - x_and_y : felt, x_xor_y : felt, x_or_y : felt -): - bitwise_ptr.x = x - bitwise_ptr.y = y - let x_and_y = bitwise_ptr.x_and_y - let x_xor_y = bitwise_ptr.x_xor_y - let x_or_y = bitwise_ptr.x_or_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - return (x_and_y=x_and_y, x_xor_y=x_xor_y, x_or_y=x_or_y) -end +// Computes the bitwise operations and, xor and or. +// +// Arguments: +// bitwise_ptr - the bitwise builtin pointer. +// x, y - the two field elements to operate on, in this order. Both inputs should be 251-bit +// integers, and are taken as unsigned ints. +// +// Returns: +// x_and_y = x & y (bitwise and). +// x_xor_y = x ^ y (bitwise xor). +// x_or_y = x | y (bitwise or). +func bitwise_operations{bitwise_ptr: BitwiseBuiltin*}(x: felt, y: felt) -> ( + x_and_y: felt, x_xor_y: felt, x_or_y: felt +) { + bitwise_ptr.x = x; + bitwise_ptr.y = y; + let x_and_y = bitwise_ptr.x_and_y; + let x_xor_y = bitwise_ptr.x_xor_y; + let x_or_y = bitwise_ptr.x_or_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + return (x_and_y=x_and_y, x_xor_y=x_xor_y, x_or_y=x_or_y); +} -# Computes the bitwise and of two inputs. -# -# Arguments: -# bitwise_ptr - the bitwise builtin pointer. -# x, y - the two field elements to operate on, in this order. Both inputs should be 251-bit -# integers, and are taken as unsigned ints. -# -# Returns: -# x_and_y = x & y (bitwise and). -func bitwise_and{bitwise_ptr : BitwiseBuiltin*}(x : felt, y : felt) -> (x_and_y : felt): - bitwise_ptr.x = x - bitwise_ptr.y = y - let x_and_y = bitwise_ptr.x_and_y - let x_xor_y = bitwise_ptr.x_xor_y - let x_or_y = bitwise_ptr.x_or_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - return (x_and_y=x_and_y) -end +// Computes the bitwise and of two inputs. +// +// Arguments: +// bitwise_ptr - the bitwise builtin pointer. +// x, y - the two field elements to operate on, in this order. Both inputs should be 251-bit +// integers, and are taken as unsigned ints. +// +// Returns: +// x_and_y = x & y (bitwise and). +func bitwise_and{bitwise_ptr: BitwiseBuiltin*}(x: felt, y: felt) -> (x_and_y: felt) { + bitwise_ptr.x = x; + bitwise_ptr.y = y; + let x_and_y = bitwise_ptr.x_and_y; + let x_xor_y = bitwise_ptr.x_xor_y; + let x_or_y = bitwise_ptr.x_or_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + return (x_and_y=x_and_y); +} -# Computes the bitwise xor of two inputs. -# -# Arguments: -# bitwise_ptr - the bitwise builtin pointer. -# x, y - the two field elements to operate on, in this order. Both inputs should be 251-bit -# integers, and are taken as unsigned ints. -# -# Returns: -# x_xor_y = x ^ y (bitwise xor). -func bitwise_xor{bitwise_ptr : BitwiseBuiltin*}(x : felt, y : felt) -> (x_xor_y : felt): - bitwise_ptr.x = x - bitwise_ptr.y = y - let x_and_y = bitwise_ptr.x_and_y - let x_xor_y = bitwise_ptr.x_xor_y - let x_or_y = bitwise_ptr.x_or_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - return (x_xor_y=x_xor_y) -end +// Computes the bitwise xor of two inputs. +// +// Arguments: +// bitwise_ptr - the bitwise builtin pointer. +// x, y - the two field elements to operate on, in this order. Both inputs should be 251-bit +// integers, and are taken as unsigned ints. +// +// Returns: +// x_xor_y = x ^ y (bitwise xor). +func bitwise_xor{bitwise_ptr: BitwiseBuiltin*}(x: felt, y: felt) -> (x_xor_y: felt) { + bitwise_ptr.x = x; + bitwise_ptr.y = y; + let x_and_y = bitwise_ptr.x_and_y; + let x_xor_y = bitwise_ptr.x_xor_y; + let x_or_y = bitwise_ptr.x_or_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + return (x_xor_y=x_xor_y); +} -# Computes the bitwise or of two inputs. -# -# Arguments: -# bitwise_ptr - the bitwise builtin pointer. -# x, y - the two field elements to operate on, in this order. Both inputs should be 251-bit -# integers, and are taken as unsigned ints. -# -# Returns: -# x_or_y = x | y (bitwise or). -func bitwise_or{bitwise_ptr : BitwiseBuiltin*}(x : felt, y : felt) -> (x_or_y : felt): - bitwise_ptr.x = x - bitwise_ptr.y = y - let x_and_y = bitwise_ptr.x_and_y - let x_xor_y = bitwise_ptr.x_xor_y - let x_or_y = bitwise_ptr.x_or_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - return (x_or_y=x_or_y) -end +// Computes the bitwise or of two inputs. +// +// Arguments: +// bitwise_ptr - the bitwise builtin pointer. +// x, y - the two field elements to operate on, in this order. Both inputs should be 251-bit +// integers, and are taken as unsigned ints. +// +// Returns: +// x_or_y = x | y (bitwise or). +func bitwise_or{bitwise_ptr: BitwiseBuiltin*}(x: felt, y: felt) -> (x_or_y: felt) { + bitwise_ptr.x = x; + bitwise_ptr.y = y; + let x_and_y = bitwise_ptr.x_and_y; + let x_xor_y = bitwise_ptr.x_xor_y; + let x_or_y = bitwise_ptr.x_or_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + return (x_or_y=x_or_y); +} -# Computes the bitwise not of a single 251-bit integer. -# -# Argument: -# x - the field element to operate on. The input should be a 251-bit -# integer, and is taken as unsigned int. -# -# Returns: -# not_x = ~x (bitwise not). -func bitwise_not(x : felt) -> (not_x : felt): - return (not_x=ALL_ONES - x) -end +// Computes the bitwise not of a single 251-bit integer. +// +// Argument: +// x - the field element to operate on. The input should be a 251-bit +// integer, and is taken as unsigned int. +// +// Returns: +// not_x = ~x (bitwise not). +func bitwise_not(x: felt) -> (not_x: felt) { + return (not_x=ALL_ONES - x); +} diff --git a/src/starkware/cairo/common/bool.cairo b/src/starkware/cairo/common/bool.cairo index 76d9a2a2..c0ae06c2 100644 --- a/src/starkware/cairo/common/bool.cairo +++ b/src/starkware/cairo/common/bool.cairo @@ -1,3 +1,3 @@ -# Represents boolean values in Cairo. -const FALSE = 0 -const TRUE = 1 +// Represents boolean values in Cairo. +const FALSE = 0; +const TRUE = 1; diff --git a/src/starkware/cairo/common/cairo_blake2s/CMakeLists.txt b/src/starkware/cairo/common/cairo_blake2s/CMakeLists.txt new file mode 100644 index 00000000..e2a2a159 --- /dev/null +++ b/src/starkware/cairo/common/cairo_blake2s/CMakeLists.txt @@ -0,0 +1,16 @@ +full_python_test(cairo_blake2s_test + PREFIX starkware/cairo/common/cairo_blake2s + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/common + + FILES + blake2s_test.cairo + blake2s_test.py + + LIBS + cairo_common_lib + cairo_constants_lib + cairo_function_runner_lib + pip_pytest + pip_pytest_asyncio +) diff --git a/src/starkware/cairo/common/cairo_blake2s/blake2s.cairo b/src/starkware/cairo/common/cairo_blake2s/blake2s.cairo index 03d0e314..603e6094 100644 --- a/src/starkware/cairo/common/cairo_blake2s/blake2s.cairo +++ b/src/starkware/cairo/common/cairo_blake2s/blake2s.cairo @@ -1,6 +1,6 @@ -# This module provides a set of functions to compute the blake2s hash function. -# -# This module is similar to the keccak.cairo module. See more info there. +// This module provides a set of functions to compute the blake2s hash function. +// +// This module is similar to the keccak.cairo module. See more info there. from starkware.cairo.common.alloc import alloc from starkware.cairo.common.cairo_blake2s.packed_blake2s import N_PACKED_INSTANCES, blake2s_compress @@ -13,173 +13,173 @@ from starkware.cairo.common.pow import pow from starkware.cairo.common.registers import get_fp_and_pc, get_label_location from starkware.cairo.common.uint256 import Uint256 -const INPUT_BLOCK_FELTS = 16 -const INPUT_BLOCK_BYTES = 64 -const STATE_SIZE_FELTS = 8 -# Each instance consists of 8 words for the input state, 16 words of message, 2 words for t0 and f0, -# and 8 words for the output state. -const INSTANCE_SIZE = STATE_SIZE_FELTS + INPUT_BLOCK_FELTS + 2 + STATE_SIZE_FELTS - -# Computes blake2s of 'input'. -# To use this function, split the input into words of 32 bits (little endian). -# For example, to compute blake2s('Hello world'), use: -# input = [1819043144, 1870078063, 6581362] -# where: -# 1819043144 == int.from_bytes(b'Hell', 'little') -# 1870078063 == int.from_bytes(b'o wo', 'little') -# 6581362 == int.from_bytes(b'rld', 'little') -# -# Returns the hash as a Uint256. -# -# Note: You must call finalize_blake2s() at the end of the program. Otherwise, this function -# is not sound and a malicious prover may return a wrong result. -# Note: the interface of this function may change in the future. -# Note: Each input word is verified to be in the range [0, 2 ** 32) by this function. -func blake2s{range_check_ptr, blake2s_ptr : felt*}(data : felt*, n_bytes : felt) -> (res : Uint256): - let (output) = blake2s_as_words(data=data, n_bytes=n_bytes) - let res_low = output[3] * 2 ** 96 + output[2] * 2 ** 64 + output[1] * 2 ** 32 + output[0] - let res_high = output[7] * 2 ** 96 + output[6] * 2 ** 64 + output[5] * 2 ** 32 + output[4] - return (res=Uint256(low=res_low, high=res_high)) -end - -# Computes blake2s of 'input', and returns the hash in big endian representation. -# See blake2s(). -# Note that the input is still treated as little endian. -func blake2s_bigend{bitwise_ptr : BitwiseBuiltin*, range_check_ptr, blake2s_ptr : felt*}( - data : felt*, n_bytes : felt -) -> (res : Uint256): - let (num) = blake2s(data=data, n_bytes=n_bytes) - - # Reverse byte endianness of 128-bit words. - tempvar value = num.high - assert bitwise_ptr[0].x = value - assert bitwise_ptr[0].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff - tempvar value = value + (2 ** 16 - 1) * bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].x = value - assert bitwise_ptr[1].y = 0x00ffff0000ffff0000ffff0000ffff00 - tempvar value = value + (2 ** 32 - 1) * bitwise_ptr[1].x_and_y - assert bitwise_ptr[2].x = value - assert bitwise_ptr[2].y = 0x00ffffffff00000000ffffffff000000 - tempvar value = value + (2 ** 64 - 1) * bitwise_ptr[2].x_and_y - assert bitwise_ptr[3].x = value - assert bitwise_ptr[3].y = 0x00ffffffffffffffff00000000000000 - tempvar value = value + (2 ** 128 - 1) * bitwise_ptr[3].x_and_y - tempvar high = value / 2 ** (8 + 16 + 32 + 64) - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE - - tempvar value = num.low - assert bitwise_ptr[0].x = value - assert bitwise_ptr[0].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff - tempvar value = value + (2 ** 16 - 1) * bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].x = value - assert bitwise_ptr[1].y = 0x00ffff0000ffff0000ffff0000ffff00 - tempvar value = value + (2 ** 32 - 1) * bitwise_ptr[1].x_and_y - assert bitwise_ptr[2].x = value - assert bitwise_ptr[2].y = 0x00ffffffff00000000ffffffff000000 - tempvar value = value + (2 ** 64 - 1) * bitwise_ptr[2].x_and_y - assert bitwise_ptr[3].x = value - assert bitwise_ptr[3].y = 0x00ffffffffffffffff00000000000000 - tempvar value = value + (2 ** 128 - 1) * bitwise_ptr[3].x_and_y - tempvar low = value / 2 ** (8 + 16 + 32 + 64) - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE - - return (res=Uint256(low=high, high=low)) -end - -# Same as blake2s, but outputs a pointer to 8 32-bit little endian words instead. -func blake2s_as_words{range_check_ptr, blake2s_ptr : felt*}(data : felt*, n_bytes : felt) -> ( - output : felt* -): - # Set the initial state to IV (IV[0] is modified). - assert blake2s_ptr[0] = 0x6B08E647 # IV[0] ^ 0x01010020 (config: no key, 32 bytes output). - assert blake2s_ptr[1] = 0xBB67AE85 - assert blake2s_ptr[2] = 0x3C6EF372 - assert blake2s_ptr[3] = 0xA54FF53A - assert blake2s_ptr[4] = 0x510E527F - assert blake2s_ptr[5] = 0x9B05688C - assert blake2s_ptr[6] = 0x1F83D9AB - assert blake2s_ptr[7] = 0x5BE0CD19 - static_assert STATE_SIZE_FELTS == 8 - let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS - - let (output) = blake2s_inner(data=data, n_bytes=n_bytes, counter=0) - return (output) -end - -# Inner loop for blake2s. blake2s_ptr points to the middle of an instance: after the initial state, -# before the message. -func blake2s_inner{range_check_ptr, blake2s_ptr : felt*}( - data : felt*, n_bytes : felt, counter : felt -) -> (output : felt*): - alloc_locals - let (is_last_block) = is_le(n_bytes, INPUT_BLOCK_BYTES) - if is_last_block != 0: - return blake2s_last_block(data=data, n_bytes=n_bytes, counter=counter) - end - - memcpy(blake2s_ptr, data, INPUT_BLOCK_FELTS) - let blake2s_ptr = blake2s_ptr + INPUT_BLOCK_FELTS - - assert blake2s_ptr[0] = counter + INPUT_BLOCK_BYTES # n_bytes. - assert blake2s_ptr[1] = 0 # Is last byte = False. - let blake2s_ptr = blake2s_ptr + 2 - - # Write output. - let output = blake2s_ptr +const INPUT_BLOCK_FELTS = 16; +const INPUT_BLOCK_BYTES = 64; +const STATE_SIZE_FELTS = 8; +// Each instance consists of 8 words for the input state, 16 words of message, +// 2 words for t0 and f0, and 8 words for the output state. +const INSTANCE_SIZE = STATE_SIZE_FELTS + INPUT_BLOCK_FELTS + 2 + STATE_SIZE_FELTS; + +// Computes blake2s of 'input'. +// To use this function, split the input into words of 32 bits (little endian). +// For example, to compute blake2s('Hello world'), use: +// input = [1819043144, 1870078063, 6581362] +// where: +// 1819043144 == int.from_bytes(b'Hell', 'little') +// 1870078063 == int.from_bytes(b'o wo', 'little') +// 6581362 == int.from_bytes(b'rld', 'little') +// +// Returns the hash as a Uint256. +// +// Note: You must call finalize_blake2s() at the end of the program. Otherwise, this function +// is not sound and a malicious prover may return a wrong result. +// Note: the interface of this function may change in the future. +// Note: Each input word is verified to be in the range [0, 2 ** 32) by this function. +func blake2s{range_check_ptr, blake2s_ptr: felt*}(data: felt*, n_bytes: felt) -> (res: Uint256) { + let (output) = blake2s_as_words(data=data, n_bytes=n_bytes); + let res_low = output[3] * 2 ** 96 + output[2] * 2 ** 64 + output[1] * 2 ** 32 + output[0]; + let res_high = output[7] * 2 ** 96 + output[6] * 2 ** 64 + output[5] * 2 ** 32 + output[4]; + return (res=Uint256(low=res_low, high=res_high)); +} + +// Computes blake2s of 'input', and returns the hash in big endian representation. +// See blake2s(). +// Note that the input is still treated as little endian. +func blake2s_bigend{bitwise_ptr: BitwiseBuiltin*, range_check_ptr, blake2s_ptr: felt*}( + data: felt*, n_bytes: felt +) -> (res: Uint256) { + let (num) = blake2s(data=data, n_bytes=n_bytes); + + // Reverse byte endianness of 128-bit words. + tempvar value = num.high; + assert bitwise_ptr[0].x = value; + assert bitwise_ptr[0].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff; + tempvar value = value + (2 ** 16 - 1) * bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].x = value; + assert bitwise_ptr[1].y = 0x00ffff0000ffff0000ffff0000ffff00; + tempvar value = value + (2 ** 32 - 1) * bitwise_ptr[1].x_and_y; + assert bitwise_ptr[2].x = value; + assert bitwise_ptr[2].y = 0x00ffffffff00000000ffffffff000000; + tempvar value = value + (2 ** 64 - 1) * bitwise_ptr[2].x_and_y; + assert bitwise_ptr[3].x = value; + assert bitwise_ptr[3].y = 0x00ffffffffffffffff00000000000000; + tempvar value = value + (2 ** 128 - 1) * bitwise_ptr[3].x_and_y; + tempvar high = value / 2 ** (8 + 16 + 32 + 64); + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; + + tempvar value = num.low; + assert bitwise_ptr[0].x = value; + assert bitwise_ptr[0].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff; + tempvar value = value + (2 ** 16 - 1) * bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].x = value; + assert bitwise_ptr[1].y = 0x00ffff0000ffff0000ffff0000ffff00; + tempvar value = value + (2 ** 32 - 1) * bitwise_ptr[1].x_and_y; + assert bitwise_ptr[2].x = value; + assert bitwise_ptr[2].y = 0x00ffffffff00000000ffffffff000000; + tempvar value = value + (2 ** 64 - 1) * bitwise_ptr[2].x_and_y; + assert bitwise_ptr[3].x = value; + assert bitwise_ptr[3].y = 0x00ffffffffffffffff00000000000000; + tempvar value = value + (2 ** 128 - 1) * bitwise_ptr[3].x_and_y; + tempvar low = value / 2 ** (8 + 16 + 32 + 64); + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; + + return (res=Uint256(low=high, high=low)); +} + +// Same as blake2s, but outputs a pointer to 8 32-bit little endian words instead. +func blake2s_as_words{range_check_ptr, blake2s_ptr: felt*}(data: felt*, n_bytes: felt) -> ( + output: felt* +) { + // Set the initial state to IV (IV[0] is modified). + assert blake2s_ptr[0] = 0x6B08E647; // IV[0] ^ 0x01010020 (config: no key, 32 bytes output). + assert blake2s_ptr[1] = 0xBB67AE85; + assert blake2s_ptr[2] = 0x3C6EF372; + assert blake2s_ptr[3] = 0xA54FF53A; + assert blake2s_ptr[4] = 0x510E527F; + assert blake2s_ptr[5] = 0x9B05688C; + assert blake2s_ptr[6] = 0x1F83D9AB; + assert blake2s_ptr[7] = 0x5BE0CD19; + static_assert STATE_SIZE_FELTS == 8; + let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS; + + let (output) = blake2s_inner(data=data, n_bytes=n_bytes, counter=0); + return (output=output); +} + +// Inner loop for blake2s. blake2s_ptr points to the middle of an instance: after the initial state, +// before the message. +func blake2s_inner{range_check_ptr, blake2s_ptr: felt*}( + data: felt*, n_bytes: felt, counter: felt +) -> (output: felt*) { + alloc_locals; + let is_last_block = is_le(n_bytes, INPUT_BLOCK_BYTES); + if (is_last_block != 0) { + return blake2s_last_block(data=data, n_bytes=n_bytes, counter=counter); + } + + memcpy(blake2s_ptr, data, INPUT_BLOCK_FELTS); + let blake2s_ptr = blake2s_ptr + INPUT_BLOCK_FELTS; + + assert blake2s_ptr[0] = counter + INPUT_BLOCK_BYTES; // n_bytes. + assert blake2s_ptr[1] = 0; // Is last byte = False. + let blake2s_ptr = blake2s_ptr + 2; + + // Write output. + let output = blake2s_ptr; %{ from starkware.cairo.common.cairo_blake2s.blake2s_utils import compute_blake2s_func compute_blake2s_func(segments=segments, output_ptr=ids.output) %} - let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS + let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS; - # Write the current output to the input state for the next instance. - memcpy(blake2s_ptr, output, STATE_SIZE_FELTS) - let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS + // Write the current output to the input state for the next instance. + memcpy(blake2s_ptr, output, STATE_SIZE_FELTS); + let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS; return blake2s_inner( data=data + INPUT_BLOCK_FELTS, n_bytes=n_bytes - INPUT_BLOCK_BYTES, counter=counter + INPUT_BLOCK_BYTES, - ) -end - -func blake2s_last_block{range_check_ptr, blake2s_ptr : felt*}( - data : felt*, n_bytes : felt, counter : felt -) -> (output : felt*): - alloc_locals - let (n_felts, _) = unsigned_div_rem(n_bytes + 3, 4) - memcpy(blake2s_ptr, data, n_felts) - memset(blake2s_ptr + n_felts, 0, INPUT_BLOCK_FELTS - n_felts) - let blake2s_ptr = blake2s_ptr + INPUT_BLOCK_FELTS - - assert blake2s_ptr[0] = counter + n_bytes # n_bytes. - assert blake2s_ptr[1] = 0xffffffff # Is last byte = True. - let blake2s_ptr = blake2s_ptr + 2 - - # Write output. - let output = blake2s_ptr + ); +} + +func blake2s_last_block{range_check_ptr, blake2s_ptr: felt*}( + data: felt*, n_bytes: felt, counter: felt +) -> (output: felt*) { + alloc_locals; + let (n_felts, _) = unsigned_div_rem(n_bytes + 3, 4); + memcpy(blake2s_ptr, data, n_felts); + memset(blake2s_ptr + n_felts, 0, INPUT_BLOCK_FELTS - n_felts); + let blake2s_ptr = blake2s_ptr + INPUT_BLOCK_FELTS; + + assert blake2s_ptr[0] = counter + n_bytes; // n_bytes. + assert blake2s_ptr[1] = 0xffffffff; // Is last byte = True. + let blake2s_ptr = blake2s_ptr + 2; + + // Write output. + let output = blake2s_ptr; %{ from starkware.cairo.common.cairo_blake2s.blake2s_utils import compute_blake2s_func compute_blake2s_func(segments=segments, output_ptr=ids.output) %} - let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS + let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS; - return (output=output) -end + return (output=output); +} -# Verifies that the results of blake2s() are valid. -func finalize_blake2s{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}( - blake2s_ptr_start : felt*, blake2s_ptr_end : felt* -): - alloc_locals +// Verifies that the results of blake2s() are valid. +func finalize_blake2s{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + blake2s_ptr_start: felt*, blake2s_ptr_end: felt* +) { + alloc_locals; - let (__fp__, _) = get_fp_and_pc() + let (__fp__, _) = get_fp_and_pc(); - let (sigma) = _get_sigma() + let (sigma) = _get_sigma(); - tempvar n = (blake2s_ptr_end - blake2s_ptr_start) / INSTANCE_SIZE - if n == 0: - return () - end + tempvar n = (blake2s_ptr_end - blake2s_ptr_start) / INSTANCE_SIZE; + if (n == 0) { + return (); + } %{ # Add dummy pairs of input and output. @@ -204,202 +204,202 @@ func finalize_blake2s{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}( segments.write_arg(ids.blake2s_ptr_end, padding) %} - # Compute the amount of chunks (rounded up). - let (local n_chunks, _) = unsigned_div_rem(n + N_PACKED_INSTANCES - 1, N_PACKED_INSTANCES) - let blake2s_ptr = blake2s_ptr_start - _finalize_blake2s_inner{blake2s_ptr=blake2s_ptr}(n=n_chunks, sigma=sigma) - return () -end + // Compute the amount of chunks (rounded up). + let (local n_chunks, _) = unsigned_div_rem(n + N_PACKED_INSTANCES - 1, N_PACKED_INSTANCES); + let blake2s_ptr = blake2s_ptr_start; + _finalize_blake2s_inner{blake2s_ptr=blake2s_ptr}(n=n_chunks, sigma=sigma); + return (); +} -func _get_sigma() -> (sigma : felt*): - alloc_locals - let (sigma_address) = get_label_location(data) - return (sigma=cast(sigma_address, felt*)) +func _get_sigma() -> (sigma: felt*) { + alloc_locals; + let (sigma_address) = get_label_location(data); + return (sigma=cast(sigma_address, felt*)); data: - dw 0 - dw 1 - dw 2 - dw 3 - dw 4 - dw 5 - dw 6 - dw 7 - dw 8 - dw 9 - dw 10 - dw 11 - dw 12 - dw 13 - dw 14 - dw 15 - dw 14 - dw 10 - dw 4 - dw 8 - dw 9 - dw 15 - dw 13 - dw 6 - dw 1 - dw 12 - dw 0 - dw 2 - dw 11 - dw 7 - dw 5 - dw 3 - dw 11 - dw 8 - dw 12 - dw 0 - dw 5 - dw 2 - dw 15 - dw 13 - dw 10 - dw 14 - dw 3 - dw 6 - dw 7 - dw 1 - dw 9 - dw 4 - dw 7 - dw 9 - dw 3 - dw 1 - dw 13 - dw 12 - dw 11 - dw 14 - dw 2 - dw 6 - dw 5 - dw 10 - dw 4 - dw 0 - dw 15 - dw 8 - dw 9 - dw 0 - dw 5 - dw 7 - dw 2 - dw 4 - dw 10 - dw 15 - dw 14 - dw 1 - dw 11 - dw 12 - dw 6 - dw 8 - dw 3 - dw 13 - dw 2 - dw 12 - dw 6 - dw 10 - dw 0 - dw 11 - dw 8 - dw 3 - dw 4 - dw 13 - dw 7 - dw 5 - dw 15 - dw 14 - dw 1 - dw 9 - dw 12 - dw 5 - dw 1 - dw 15 - dw 14 - dw 13 - dw 4 - dw 10 - dw 0 - dw 7 - dw 6 - dw 3 - dw 9 - dw 2 - dw 8 - dw 11 - dw 13 - dw 11 - dw 7 - dw 14 - dw 12 - dw 1 - dw 3 - dw 9 - dw 5 - dw 0 - dw 15 - dw 4 - dw 8 - dw 6 - dw 2 - dw 10 - dw 6 - dw 15 - dw 14 - dw 9 - dw 11 - dw 3 - dw 0 - dw 8 - dw 12 - dw 2 - dw 13 - dw 7 - dw 1 - dw 4 - dw 10 - dw 5 - dw 10 - dw 2 - dw 8 - dw 4 - dw 7 - dw 6 - dw 1 - dw 5 - dw 15 - dw 11 - dw 9 - dw 14 - dw 3 - dw 12 - dw 13 - dw 0 -end - -# Handles n chunks of N_PACKED_INSTANCES blake2s instances. -func _finalize_blake2s_inner{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, blake2s_ptr : felt*}( - n : felt, sigma : felt* -): - if n == 0: - return () - end - - alloc_locals - let blake2s_start = blake2s_ptr - - # Load instance data. - let (local data : felt*) = alloc() - _pack_ints(INSTANCE_SIZE, data) - - let input_state : felt* = data - let message : felt* = input_state + STATE_SIZE_FELTS - let t0_and_f0 : felt* = message + INPUT_BLOCK_FELTS - let output_state : felt* = t0_and_f0 + 2 - - # Run blake2s on N_PACKED_INSTANCES instances. + dw 0; + dw 1; + dw 2; + dw 3; + dw 4; + dw 5; + dw 6; + dw 7; + dw 8; + dw 9; + dw 10; + dw 11; + dw 12; + dw 13; + dw 14; + dw 15; + dw 14; + dw 10; + dw 4; + dw 8; + dw 9; + dw 15; + dw 13; + dw 6; + dw 1; + dw 12; + dw 0; + dw 2; + dw 11; + dw 7; + dw 5; + dw 3; + dw 11; + dw 8; + dw 12; + dw 0; + dw 5; + dw 2; + dw 15; + dw 13; + dw 10; + dw 14; + dw 3; + dw 6; + dw 7; + dw 1; + dw 9; + dw 4; + dw 7; + dw 9; + dw 3; + dw 1; + dw 13; + dw 12; + dw 11; + dw 14; + dw 2; + dw 6; + dw 5; + dw 10; + dw 4; + dw 0; + dw 15; + dw 8; + dw 9; + dw 0; + dw 5; + dw 7; + dw 2; + dw 4; + dw 10; + dw 15; + dw 14; + dw 1; + dw 11; + dw 12; + dw 6; + dw 8; + dw 3; + dw 13; + dw 2; + dw 12; + dw 6; + dw 10; + dw 0; + dw 11; + dw 8; + dw 3; + dw 4; + dw 13; + dw 7; + dw 5; + dw 15; + dw 14; + dw 1; + dw 9; + dw 12; + dw 5; + dw 1; + dw 15; + dw 14; + dw 13; + dw 4; + dw 10; + dw 0; + dw 7; + dw 6; + dw 3; + dw 9; + dw 2; + dw 8; + dw 11; + dw 13; + dw 11; + dw 7; + dw 14; + dw 12; + dw 1; + dw 3; + dw 9; + dw 5; + dw 0; + dw 15; + dw 4; + dw 8; + dw 6; + dw 2; + dw 10; + dw 6; + dw 15; + dw 14; + dw 9; + dw 11; + dw 3; + dw 0; + dw 8; + dw 12; + dw 2; + dw 13; + dw 7; + dw 1; + dw 4; + dw 10; + dw 5; + dw 10; + dw 2; + dw 8; + dw 4; + dw 7; + dw 6; + dw 1; + dw 5; + dw 15; + dw 11; + dw 9; + dw 14; + dw 3; + dw 12; + dw 13; + dw 0; +} + +// Handles n chunks of N_PACKED_INSTANCES blake2s instances. +func _finalize_blake2s_inner{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, blake2s_ptr: felt*}( + n: felt, sigma: felt* +) { + if (n == 0) { + return (); + } + + alloc_locals; + let blake2s_start = blake2s_ptr; + + // Load instance data. + let (local data: felt*) = alloc(); + _pack_ints(INSTANCE_SIZE, data); + + let input_state: felt* = data; + let message: felt* = input_state + STATE_SIZE_FELTS; + let t0_and_f0: felt* = message + INPUT_BLOCK_FELTS; + let output_state: felt* = t0_and_f0 + 2; + + // Run blake2s on N_PACKED_INSTANCES instances. blake2s_compress( h=input_state, message=message, @@ -407,103 +407,103 @@ func _finalize_blake2s_inner{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, bla f0=t0_and_f0[1], sigma=sigma, output=output_state, - ) - let blake2s_ptr = blake2s_start + INSTANCE_SIZE * N_PACKED_INSTANCES + ); + let blake2s_ptr = blake2s_start + INSTANCE_SIZE * N_PACKED_INSTANCES; - return _finalize_blake2s_inner(n=n - 1, sigma=sigma) -end + return _finalize_blake2s_inner(n=n - 1, sigma=sigma); +} -# Given N_PACKED_INSTANCES sets of m (32-bit) integers in the blake2s implicit argument, -# where each set starts at offset INSTANCE_SIZE from the previous set, -# computes m packed integers. -# blake2s_ptr is advanced m steps (just after the first set). -func _pack_ints{range_check_ptr, blake2s_ptr : felt*}(m, packed_values : felt*): - static_assert N_PACKED_INSTANCES == 7 - alloc_locals +// Given N_PACKED_INSTANCES sets of m (32-bit) integers in the blake2s implicit argument, +// where each set starts at offset INSTANCE_SIZE from the previous set, +// computes m packed integers. +// blake2s_ptr is advanced m steps (just after the first set). +func _pack_ints{range_check_ptr, blake2s_ptr: felt*}(m, packed_values: felt*) { + static_assert N_PACKED_INSTANCES == 7; + alloc_locals; - local MAX_VALUE = 2 ** 32 - 1 + local MAX_VALUE = 2 ** 32 - 1; - tempvar packed_values = packed_values - tempvar blake2s_ptr = blake2s_ptr - tempvar range_check_ptr = range_check_ptr - tempvar m = m + tempvar packed_values = packed_values; + tempvar blake2s_ptr = blake2s_ptr; + tempvar range_check_ptr = range_check_ptr; + tempvar m = m; loop: - tempvar x0 = blake2s_ptr[0 * INSTANCE_SIZE] - assert [range_check_ptr + 0] = x0 - assert [range_check_ptr + 1] = MAX_VALUE - x0 - tempvar x1 = blake2s_ptr[1 * INSTANCE_SIZE] - assert [range_check_ptr + 2] = x1 - assert [range_check_ptr + 3] = MAX_VALUE - x1 - tempvar x2 = blake2s_ptr[2 * INSTANCE_SIZE] - assert [range_check_ptr + 4] = x2 - assert [range_check_ptr + 5] = MAX_VALUE - x2 - tempvar x3 = blake2s_ptr[3 * INSTANCE_SIZE] - assert [range_check_ptr + 6] = x3 - assert [range_check_ptr + 7] = MAX_VALUE - x3 - tempvar x4 = blake2s_ptr[4 * INSTANCE_SIZE] - assert [range_check_ptr + 8] = x4 - assert [range_check_ptr + 9] = MAX_VALUE - x4 - tempvar x5 = blake2s_ptr[5 * INSTANCE_SIZE] - assert [range_check_ptr + 10] = x5 - assert [range_check_ptr + 11] = MAX_VALUE - x5 - tempvar x6 = blake2s_ptr[6 * INSTANCE_SIZE] - assert [range_check_ptr + 12] = x6 - assert [range_check_ptr + 13] = MAX_VALUE - x6 + tempvar x0 = blake2s_ptr[0 * INSTANCE_SIZE]; + assert [range_check_ptr + 0] = x0; + assert [range_check_ptr + 1] = MAX_VALUE - x0; + tempvar x1 = blake2s_ptr[1 * INSTANCE_SIZE]; + assert [range_check_ptr + 2] = x1; + assert [range_check_ptr + 3] = MAX_VALUE - x1; + tempvar x2 = blake2s_ptr[2 * INSTANCE_SIZE]; + assert [range_check_ptr + 4] = x2; + assert [range_check_ptr + 5] = MAX_VALUE - x2; + tempvar x3 = blake2s_ptr[3 * INSTANCE_SIZE]; + assert [range_check_ptr + 6] = x3; + assert [range_check_ptr + 7] = MAX_VALUE - x3; + tempvar x4 = blake2s_ptr[4 * INSTANCE_SIZE]; + assert [range_check_ptr + 8] = x4; + assert [range_check_ptr + 9] = MAX_VALUE - x4; + tempvar x5 = blake2s_ptr[5 * INSTANCE_SIZE]; + assert [range_check_ptr + 10] = x5; + assert [range_check_ptr + 11] = MAX_VALUE - x5; + tempvar x6 = blake2s_ptr[6 * INSTANCE_SIZE]; + assert [range_check_ptr + 12] = x6; + assert [range_check_ptr + 13] = MAX_VALUE - x6; assert packed_values[0] = x0 + 2 ** 35 * x1 + 2 ** (35 * 2) * x2 + 2 ** (35 * 3) * x3 + - 2 ** (35 * 4) * x4 + 2 ** (35 * 5) * x5 + 2 ** (35 * 6) * x6 + 2 ** (35 * 4) * x4 + 2 ** (35 * 5) * x5 + 2 ** (35 * 6) * x6; - tempvar packed_values = packed_values + 1 - tempvar blake2s_ptr = blake2s_ptr + 1 - tempvar range_check_ptr = range_check_ptr + 14 - tempvar m = m - 1 - jmp loop if m != 0 + tempvar packed_values = packed_values + 1; + tempvar blake2s_ptr = blake2s_ptr + 1; + tempvar range_check_ptr = range_check_ptr + 14; + tempvar m = m - 1; + jmp loop if m != 0; - return () -end + return (); +} -# Helper functions. -# These functions serialize data to a data array to be used with blake2s(). -# They use the property that each data word is verified by blake2s() to be in range [0, 2 ** 32). +// Helper functions. +// These functions serialize data to a data array to be used with blake2s(). +// They use the property that each data word is verified by blake2s() to be in range [0, 2 ** 32). -# Serializes a uint256 number in a blake2s compatible way (little-endian). -func blake2s_add_uint256{data : felt*}(num : Uint256): - let high = num.high - let low = num.low +// Serializes a uint256 number in a blake2s compatible way (little-endian). +func blake2s_add_uint256{data: felt*}(num: Uint256) { + let high = num.high; + let low = num.low; %{ B = 32 MASK = 2 ** 32 - 1 segments.write_arg(ids.data, [(ids.low >> (B * i)) & MASK for i in range(4)]) segments.write_arg(ids.data + 4, [(ids.high >> (B * i)) & MASK for i in range(4)]) %} - assert data[3] * 2 ** 96 + data[2] * 2 ** 64 + data[1] * 2 ** 32 + data[0] = low - assert data[7] * 2 ** 96 + data[6] * 2 ** 64 + data[5] * 2 ** 32 + data[4] = high - let data = data + 8 - return () -end - -# Serializes a uint256 number in a blake2s compatible way (big-endian). -func blake2s_add_uint256_bigend{bitwise_ptr : BitwiseBuiltin*, data : felt*}(num : Uint256): - # Reverse byte endianness of 32-bit chunks. - tempvar value = num.high - assert bitwise_ptr[0].x = value - assert bitwise_ptr[0].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff - tempvar value = value + (2 ** 16 - 1) * bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].x = value - assert bitwise_ptr[1].y = 0x00ffff0000ffff0000ffff0000ffff00 - tempvar value = value + (2 ** 32 - 1) * bitwise_ptr[1].x_and_y - tempvar high = value / 2 ** (8 + 16) - - tempvar value = num.low - assert bitwise_ptr[2].x = value - assert bitwise_ptr[2].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff - tempvar value = value + (2 ** 16 - 1) * bitwise_ptr[2].x_and_y - assert bitwise_ptr[3].x = value - assert bitwise_ptr[3].y = 0x00ffff0000ffff0000ffff0000ffff00 - tempvar value = value + (2 ** 32 - 1) * bitwise_ptr[3].x_and_y - tempvar low = value / 2 ** (8 + 16) - - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE + assert data[3] * 2 ** 96 + data[2] * 2 ** 64 + data[1] * 2 ** 32 + data[0] = low; + assert data[7] * 2 ** 96 + data[6] * 2 ** 64 + data[5] * 2 ** 32 + data[4] = high; + let data = data + 8; + return (); +} + +// Serializes a uint256 number in a blake2s compatible way (big-endian). +func blake2s_add_uint256_bigend{bitwise_ptr: BitwiseBuiltin*, data: felt*}(num: Uint256) { + // Reverse byte endianness of 32-bit chunks. + tempvar value = num.high; + assert bitwise_ptr[0].x = value; + assert bitwise_ptr[0].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff; + tempvar value = value + (2 ** 16 - 1) * bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].x = value; + assert bitwise_ptr[1].y = 0x00ffff0000ffff0000ffff0000ffff00; + tempvar value = value + (2 ** 32 - 1) * bitwise_ptr[1].x_and_y; + tempvar high = value / 2 ** (8 + 16); + + tempvar value = num.low; + assert bitwise_ptr[2].x = value; + assert bitwise_ptr[2].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff; + tempvar value = value + (2 ** 16 - 1) * bitwise_ptr[2].x_and_y; + assert bitwise_ptr[3].x = value; + assert bitwise_ptr[3].y = 0x00ffff0000ffff0000ffff0000ffff00; + tempvar value = value + (2 ** 32 - 1) * bitwise_ptr[3].x_and_y; + tempvar low = value / 2 ** (8 + 16); + + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; %{ B = 32 @@ -512,49 +512,49 @@ func blake2s_add_uint256_bigend{bitwise_ptr : BitwiseBuiltin*, data : felt*}(num segments.write_arg(ids.data + 4, [(ids.low >> (B * (3 - i))) & MASK for i in range(4)]) %} - assert data[0] * 2 ** 96 + data[1] * 2 ** 64 + data[2] * 2 ** 32 + data[3] = high - assert data[4] * 2 ** 96 + data[5] * 2 ** 64 + data[6] * 2 ** 32 + data[7] = low - let data = data + 8 - return () -end - -# Serializes a field element in a blake2s compatible way. -func blake2s_add_felt{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, data : felt*}( - num : felt, bigend : felt -): - let (high, low) = split_felt(num) - if bigend != 0: - blake2s_add_uint256_bigend(Uint256(low=low, high=high)) - return () - else: - blake2s_add_uint256(Uint256(low=low, high=high)) - return () - end -end - -# Serializes multiple field elements in a blake2s compatible way. -# Note: This function does not serialize the number of elements. If desired, this is the caller's -# responsibility. -func blake2s_add_felts{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, data : felt*}( - n_elements : felt, elements : felt*, bigend : felt -) -> (): - if n_elements == 0: - return () - end - blake2s_add_felt(num=elements[0], bigend=bigend) - return blake2s_add_felts(n_elements=n_elements - 1, elements=&elements[1], bigend=bigend) -end - -# Computes the blake2s hash for multiple field elements. -func blake2s_felts{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, blake2s_ptr : felt*}( - n_elements : felt, elements : felt*, bigend : felt -) -> (res : Uint256): - alloc_locals - let (data) = alloc() - let data_start = data - with data: - blake2s_add_felts(n_elements=n_elements, elements=elements, bigend=bigend) - end - let (res) = blake2s(data=data_start, n_bytes=n_elements * 32) - return (res=res) -end + assert data[0] * 2 ** 96 + data[1] * 2 ** 64 + data[2] * 2 ** 32 + data[3] = high; + assert data[4] * 2 ** 96 + data[5] * 2 ** 64 + data[6] * 2 ** 32 + data[7] = low; + let data = data + 8; + return (); +} + +// Serializes a field element in a blake2s compatible way. +func blake2s_add_felt{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, data: felt*}( + num: felt, bigend: felt +) { + let (high, low) = split_felt(num); + if (bigend != 0) { + blake2s_add_uint256_bigend(Uint256(low=low, high=high)); + return (); + } else { + blake2s_add_uint256(Uint256(low=low, high=high)); + return (); + } +} + +// Serializes multiple field elements in a blake2s compatible way. +// Note: This function does not serialize the number of elements. If desired, this is the caller's +// responsibility. +func blake2s_add_felts{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, data: felt*}( + n_elements: felt, elements: felt*, bigend: felt +) -> () { + if (n_elements == 0) { + return (); + } + blake2s_add_felt(num=elements[0], bigend=bigend); + return blake2s_add_felts(n_elements=n_elements - 1, elements=&elements[1], bigend=bigend); +} + +// Computes the blake2s hash for multiple field elements. +func blake2s_felts{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, blake2s_ptr: felt*}( + n_elements: felt, elements: felt*, bigend: felt +) -> (res: Uint256) { + alloc_locals; + let (data) = alloc(); + let data_start = data; + with data { + blake2s_add_felts(n_elements=n_elements, elements=elements, bigend=bigend); + } + let (res) = blake2s(data=data_start, n_bytes=n_elements * 32); + return (res=res); +} diff --git a/src/starkware/cairo/common/cairo_blake2s/blake2s_test.cairo b/src/starkware/cairo/common/cairo_blake2s/blake2s_test.cairo index f4f1bb23..c4983340 100644 --- a/src/starkware/cairo/common/cairo_blake2s/blake2s_test.cairo +++ b/src/starkware/cairo/common/cairo_blake2s/blake2s_test.cairo @@ -14,23 +14,23 @@ from starkware.cairo.common.cairo_blake2s.blake2s import ( ) from starkware.cairo.common.cairo_builtins import BitwiseBuiltin -func run_blake2s{range_check_ptr, blake2s_ptr : felt*}(inputs : felt**, lengths : felt*, n : felt): - if n == 0: - return () - end +func run_blake2s{range_check_ptr, blake2s_ptr: felt*}(inputs: felt**, lengths: felt*, n: felt) { + if (n == 0) { + return (); + } - blake2s(inputs[0], lengths[0]) - return run_blake2s(inputs + 1, lengths + 1, n - 1) -end + blake2s(inputs[0], lengths[0]); + return run_blake2s(inputs + 1, lengths + 1, n - 1); +} -func run_blake2s_and_finalize{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}( - inputs : felt**, lengths : felt*, n : felt -): - alloc_locals - let (local blake2s_ptr_start) = alloc() - let blake2s_ptr = blake2s_ptr_start +func run_blake2s_and_finalize{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + inputs: felt**, lengths: felt*, n: felt +) { + alloc_locals; + let (local blake2s_ptr_start) = alloc(); + let blake2s_ptr = blake2s_ptr_start; - run_blake2s{blake2s_ptr=blake2s_ptr}(inputs, lengths, n) - finalize_blake2s(blake2s_ptr_start=blake2s_ptr_start, blake2s_ptr_end=blake2s_ptr) - return () -end + run_blake2s{blake2s_ptr=blake2s_ptr}(inputs, lengths, n); + finalize_blake2s(blake2s_ptr_start=blake2s_ptr_start, blake2s_ptr_end=blake2s_ptr); + return (); +} diff --git a/src/starkware/cairo/common/cairo_blake2s/packed_blake2s.cairo b/src/starkware/cairo/common/cairo_blake2s/packed_blake2s.cairo index c07bc613..c0e3b7a6 100644 --- a/src/starkware/cairo/common/cairo_blake2s/packed_blake2s.cairo +++ b/src/starkware/cairo/common/cairo_blake2s/packed_blake2s.cairo @@ -2,221 +2,223 @@ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.cairo_builtins import BitwiseBuiltin from starkware.cairo.common.registers import get_fp_and_pc -const N_PACKED_INSTANCES = 7 -const ALL_ONES = 2 ** 251 - 1 +const N_PACKED_INSTANCES = 7; +const ALL_ONES = 2 ** 251 - 1; const SHIFTS = 1 + 2 ** 35 + 2 ** (35 * 2) + 2 ** (35 * 3) + 2 ** (35 * 4) + 2 ** (35 * 5) + - 2 ** (35 * 6) - -func mix{bitwise_ptr : BitwiseBuiltin*}( - a : felt, b : felt, c : felt, d : felt, m0 : felt, m1 : felt -) -> (a : felt, b : felt, c : felt, d : felt): - alloc_locals - - # Defining the following constant as local variables saves some instructions. - local mask32ones = SHIFTS * (2 ** 32 - 1) - - # a = (a + b + m0) % 2**32 - assert bitwise_ptr[0].x = a + b + m0 - assert bitwise_ptr[0].y = mask32ones - tempvar a = bitwise_ptr[0].x_and_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - - # d = right_rot((d ^ a), 16) - assert bitwise_ptr[0].x = a - assert bitwise_ptr[0].y = d - tempvar a_xor_d = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = a_xor_d - assert bitwise_ptr[1].y = SHIFTS * (2 ** 32 - 2 ** 16) - tempvar d = (2 ** (32 - 16)) * a_xor_d + (1 / 2 ** 16 - 2 ** (32 - 16)) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - # c = (c + d) % 2**32 - assert bitwise_ptr[0].x = c + d - assert bitwise_ptr[0].y = mask32ones - tempvar c = bitwise_ptr[0].x_and_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - - # b = right_rot((b ^ c), 12) - assert bitwise_ptr[0].x = b - assert bitwise_ptr[0].y = c - tempvar b_xor_c = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = b_xor_c - assert bitwise_ptr[1].y = SHIFTS * (2 ** 32 - 2 ** 12) - tempvar b = (2 ** (32 - 12)) * b_xor_c + (1 / 2 ** 12 - 2 ** (32 - 12)) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - # a = (a + b + m1) % 2**32 - assert bitwise_ptr[0].x = a + b + m1 - assert bitwise_ptr[0].y = mask32ones - tempvar a = bitwise_ptr[0].x_and_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - - # d = right_rot((d ^ a), 8) - assert bitwise_ptr[0].x = d - assert bitwise_ptr[0].y = a - tempvar d_xor_a = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = d_xor_a - assert bitwise_ptr[1].y = SHIFTS * (2 ** 32 - 2 ** 8) - tempvar d = (2 ** (32 - 8)) * d_xor_a + (1 / 2 ** 8 - 2 ** (32 - 8)) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - # c = (c + d) % 2**32 - assert bitwise_ptr[0].x = c + d - assert bitwise_ptr[0].y = mask32ones - tempvar c = bitwise_ptr[0].x_and_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - - # b = right_rot((b ^ c), 7) - assert bitwise_ptr[0].x = b - assert bitwise_ptr[0].y = c - tempvar b_xor_c = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = b_xor_c - assert bitwise_ptr[1].y = SHIFTS * (2 ** 32 - 2 ** 7) - tempvar b = (2 ** (32 - 7)) * b_xor_c + (1 / 2 ** 7 - 2 ** (32 - 7)) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - return (a, b, c, d) -end - -func blake_round{bitwise_ptr : BitwiseBuiltin*}(state : felt*, message : felt*, sigma : felt*) -> ( - new_state : felt* -): - let state0 = state[0] - let state1 = state[1] - let state2 = state[2] - let state3 = state[3] - let state4 = state[4] - let state5 = state[5] - let state6 = state[6] - let state7 = state[7] - let state8 = state[8] - let state9 = state[9] - let state10 = state[10] - let state11 = state[11] - let state12 = state[12] - let state13 = state[13] - let state14 = state[14] - let state15 = state[15] + 2 ** (35 * 6); + +func mix{bitwise_ptr: BitwiseBuiltin*}(a: felt, b: felt, c: felt, d: felt, m0: felt, m1: felt) -> ( + a: felt, b: felt, c: felt, d: felt +) { + alloc_locals; + + // Defining the following constant as local variables saves some instructions. + local mask32ones = SHIFTS * (2 ** 32 - 1); + + // a = (a + b + m0) % 2**32. + assert bitwise_ptr[0].x = a + b + m0; + assert bitwise_ptr[0].y = mask32ones; + tempvar a = bitwise_ptr[0].x_and_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + + // d = right_rot((d ^ a), 16). + assert bitwise_ptr[0].x = a; + assert bitwise_ptr[0].y = d; + tempvar a_xor_d = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = a_xor_d; + assert bitwise_ptr[1].y = SHIFTS * (2 ** 32 - 2 ** 16); + tempvar d = (2 ** (32 - 16)) * a_xor_d + + (1 / 2 ** 16 - 2 ** (32 - 16)) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + // c = (c + d) % 2**32. + assert bitwise_ptr[0].x = c + d; + assert bitwise_ptr[0].y = mask32ones; + tempvar c = bitwise_ptr[0].x_and_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + + // b = right_rot((b ^ c), 12). + assert bitwise_ptr[0].x = b; + assert bitwise_ptr[0].y = c; + tempvar b_xor_c = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = b_xor_c; + assert bitwise_ptr[1].y = SHIFTS * (2 ** 32 - 2 ** 12); + tempvar b = (2 ** (32 - 12)) * b_xor_c + + (1 / 2 ** 12 - 2 ** (32 - 12)) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + // a = (a + b + m1) % 2**32. + assert bitwise_ptr[0].x = a + b + m1; + assert bitwise_ptr[0].y = mask32ones; + tempvar a = bitwise_ptr[0].x_and_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + + // d = right_rot((d ^ a), 8). + assert bitwise_ptr[0].x = d; + assert bitwise_ptr[0].y = a; + tempvar d_xor_a = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = d_xor_a; + assert bitwise_ptr[1].y = SHIFTS * (2 ** 32 - 2 ** 8); + tempvar d = (2 ** (32 - 8)) * d_xor_a + (1 / 2 ** 8 - 2 ** (32 - 8)) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + // c = (c + d) % 2**32. + assert bitwise_ptr[0].x = c + d; + assert bitwise_ptr[0].y = mask32ones; + tempvar c = bitwise_ptr[0].x_and_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + + // b = right_rot((b ^ c), 7). + assert bitwise_ptr[0].x = b; + assert bitwise_ptr[0].y = c; + tempvar b_xor_c = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = b_xor_c; + assert bitwise_ptr[1].y = SHIFTS * (2 ** 32 - 2 ** 7); + tempvar b = (2 ** (32 - 7)) * b_xor_c + (1 / 2 ** 7 - 2 ** (32 - 7)) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + return (a, b, c, d); +} + +func blake_round{bitwise_ptr: BitwiseBuiltin*}(state: felt*, message: felt*, sigma: felt*) -> ( + new_state: felt* +) { + let state0 = state[0]; + let state1 = state[1]; + let state2 = state[2]; + let state3 = state[3]; + let state4 = state[4]; + let state5 = state[5]; + let state6 = state[6]; + let state7 = state[7]; + let state8 = state[8]; + let state9 = state[9]; + let state10 = state[10]; + let state11 = state[11]; + let state12 = state[12]; + let state13 = state[13]; + let state14 = state[14]; + let state15 = state[15]; let (state0, state4, state8, state12) = mix( state0, state4, state8, state12, message[sigma[0]], message[sigma[1]] - ) + ); let (state1, state5, state9, state13) = mix( state1, state5, state9, state13, message[sigma[2]], message[sigma[3]] - ) + ); let (state2, state6, state10, state14) = mix( state2, state6, state10, state14, message[sigma[4]], message[sigma[5]] - ) + ); let (state3, state7, state11, state15) = mix( state3, state7, state11, state15, message[sigma[6]], message[sigma[7]] - ) + ); let (state0, state5, state10, state15) = mix( state0, state5, state10, state15, message[sigma[8]], message[sigma[9]] - ) + ); let (state1, state6, state11, state12) = mix( state1, state6, state11, state12, message[sigma[10]], message[sigma[11]] - ) + ); let (state2, state7, state8, state13) = mix( state2, state7, state8, state13, message[sigma[12]], message[sigma[13]] - ) + ); let (state3, state4, state9, state14) = mix( state3, state4, state9, state14, message[sigma[14]], message[sigma[15]] - ) - - let (new_state : felt*) = alloc() - assert new_state[0] = state0 - assert new_state[1] = state1 - assert new_state[2] = state2 - assert new_state[3] = state3 - assert new_state[4] = state4 - assert new_state[5] = state5 - assert new_state[6] = state6 - assert new_state[7] = state7 - assert new_state[8] = state8 - assert new_state[9] = state9 - assert new_state[10] = state10 - assert new_state[11] = state11 - assert new_state[12] = state12 - assert new_state[13] = state13 - assert new_state[14] = state14 - assert new_state[15] = state15 - - return (new_state) -end - -# Performs the blake compression function. -# -# h is a list of 8 32-bit words. -# message is a list of 16 32-bit words. -# t1 and f1 are assumed to be 0. -func blake2s_compress{bitwise_ptr : BitwiseBuiltin*}( - h : felt*, message : felt*, t0 : felt, f0 : felt, sigma : felt*, output : felt* -): - alloc_locals - let (__fp__, _) = get_fp_and_pc() - - # Compute state[12]. - assert bitwise_ptr[0].x = 0x510e527f * SHIFTS - assert bitwise_ptr[0].y = t0 - let state12 = bitwise_ptr[0].x_xor_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - - # Compute state[14]. - assert bitwise_ptr[0].x = 0x1f83d9ab * SHIFTS - assert bitwise_ptr[0].y = f0 - let state14 = bitwise_ptr[0].x_xor_y - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE - - local initial_state = h[0] - local initial_state_ = h[1] - local initial_state_ = h[2] - local initial_state_ = h[3] - local initial_state_ = h[4] - local initial_state_ = h[5] - local initial_state_ = h[6] - local initial_state_ = h[7] - local initial_state_ = 0x6a09e667 * SHIFTS - local initial_state_ = 0xbb67ae85 * SHIFTS - local initial_state_ = 0x3c6ef372 * SHIFTS - local initial_state_ = 0xa54ff53a * SHIFTS - local initial_state_ = state12 - local initial_state_ = 0x9b05688c * SHIFTS - local initial_state_ = state14 - local initial_state_ = 0x5be0cd19 * SHIFTS - - let state = &initial_state - - let (state) = blake_round(state, message, sigma + 16 * 0) - let (state) = blake_round(state, message, sigma + 16 * 1) - let (state) = blake_round(state, message, sigma + 16 * 2) - let (state) = blake_round(state, message, sigma + 16 * 3) - let (state) = blake_round(state, message, sigma + 16 * 4) - let (state) = blake_round(state, message, sigma + 16 * 5) - let (state) = blake_round(state, message, sigma + 16 * 6) - let (state) = blake_round(state, message, sigma + 16 * 7) - let (state) = blake_round(state, message, sigma + 16 * 8) - let (state) = blake_round(state, message, sigma + 16 * 9) - - tempvar old_h = h - tempvar last_state = state - tempvar new_h = output - tempvar bitwise_ptr = bitwise_ptr - tempvar n = 8 + ); + + let (new_state: felt*) = alloc(); + assert new_state[0] = state0; + assert new_state[1] = state1; + assert new_state[2] = state2; + assert new_state[3] = state3; + assert new_state[4] = state4; + assert new_state[5] = state5; + assert new_state[6] = state6; + assert new_state[7] = state7; + assert new_state[8] = state8; + assert new_state[9] = state9; + assert new_state[10] = state10; + assert new_state[11] = state11; + assert new_state[12] = state12; + assert new_state[13] = state13; + assert new_state[14] = state14; + assert new_state[15] = state15; + + return (new_state=new_state); +} + +// Performs the blake compression function. +// +// h is a list of 8 32-bit words. +// message is a list of 16 32-bit words. +// t1 and f1 are assumed to be 0. +func blake2s_compress{bitwise_ptr: BitwiseBuiltin*}( + h: felt*, message: felt*, t0: felt, f0: felt, sigma: felt*, output: felt* +) { + alloc_locals; + let (__fp__, _) = get_fp_and_pc(); + + // Compute state[12]. + assert bitwise_ptr[0].x = 0x510e527f * SHIFTS; + assert bitwise_ptr[0].y = t0; + let state12 = bitwise_ptr[0].x_xor_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + + // Compute state[14]. + assert bitwise_ptr[0].x = 0x1f83d9ab * SHIFTS; + assert bitwise_ptr[0].y = f0; + let state14 = bitwise_ptr[0].x_xor_y; + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + + local initial_state = h[0]; + local initial_state_ = h[1]; + local initial_state_ = h[2]; + local initial_state_ = h[3]; + local initial_state_ = h[4]; + local initial_state_ = h[5]; + local initial_state_ = h[6]; + local initial_state_ = h[7]; + local initial_state_ = 0x6a09e667 * SHIFTS; + local initial_state_ = 0xbb67ae85 * SHIFTS; + local initial_state_ = 0x3c6ef372 * SHIFTS; + local initial_state_ = 0xa54ff53a * SHIFTS; + local initial_state_ = state12; + local initial_state_ = 0x9b05688c * SHIFTS; + local initial_state_ = state14; + local initial_state_ = 0x5be0cd19 * SHIFTS; + + let state = &initial_state; + + let (state) = blake_round(state, message, sigma + 16 * 0); + let (state) = blake_round(state, message, sigma + 16 * 1); + let (state) = blake_round(state, message, sigma + 16 * 2); + let (state) = blake_round(state, message, sigma + 16 * 3); + let (state) = blake_round(state, message, sigma + 16 * 4); + let (state) = blake_round(state, message, sigma + 16 * 5); + let (state) = blake_round(state, message, sigma + 16 * 6); + let (state) = blake_round(state, message, sigma + 16 * 7); + let (state) = blake_round(state, message, sigma + 16 * 8); + let (state) = blake_round(state, message, sigma + 16 * 9); + + tempvar old_h = h; + tempvar last_state = state; + tempvar new_h = output; + tempvar bitwise_ptr = bitwise_ptr; + tempvar n = 8; loop: - assert bitwise_ptr[0].x = old_h[0] - assert bitwise_ptr[0].y = last_state[0] - assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].y = last_state[8] - assert new_h[0] = bitwise_ptr[1].x_xor_y - - tempvar old_h = old_h + 1 - tempvar last_state = last_state + 1 - tempvar new_h = new_h + 1 - tempvar bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - tempvar n = n - 1 - jmp loop if n != 0 - - return () -end + assert bitwise_ptr[0].x = old_h[0]; + assert bitwise_ptr[0].y = last_state[0]; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].y = last_state[8]; + assert new_h[0] = bitwise_ptr[1].x_xor_y; + + tempvar old_h = old_h + 1; + tempvar last_state = last_state + 1; + tempvar new_h = new_h + 1; + tempvar bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + tempvar n = n - 1; + jmp loop if n != 0; + + return (); +} diff --git a/src/starkware/cairo/common/cairo_builtins.cairo b/src/starkware/cairo/common/cairo_builtins.cairo index 2ceeb62a..2dce716f 100644 --- a/src/starkware/cairo/common/cairo_builtins.cairo +++ b/src/starkware/cairo/common/cairo_builtins.cairo @@ -1,31 +1,38 @@ from starkware.cairo.common.ec_point import EcPoint +from starkware.cairo.common.keccak_state import KeccakBuiltinState -# Specifies the hash builtin memory structure. -struct HashBuiltin: - member x : felt - member y : felt - member result : felt -end +// Specifies the hash builtin memory structure. +struct HashBuiltin { + x: felt, + y: felt, + result: felt, +} -# Specifies the signature builtin memory structure. -struct SignatureBuiltin: - member pub_key : felt - member message : felt -end +// Specifies the signature builtin memory structure. +struct SignatureBuiltin { + pub_key: felt, + message: felt, +} -# Specifies the bitwise builtin memory structure. -struct BitwiseBuiltin: - member x : felt - member y : felt - member x_and_y : felt - member x_xor_y : felt - member x_or_y : felt -end +// Specifies the bitwise builtin memory structure. +struct BitwiseBuiltin { + x: felt, + y: felt, + x_and_y: felt, + x_xor_y: felt, + x_or_y: felt, +} -# Specifies the EC operation builtin memory structure. -struct EcOpBuiltin: - member p : EcPoint - member q : EcPoint - member m : felt - member r : EcPoint -end +// Specifies the EC operation builtin memory structure. +struct EcOpBuiltin { + p: EcPoint, + q: EcPoint, + m: felt, + r: EcPoint, +} + +// Specifies the Keccak builtin memory structure. +struct KeccakBuiltin { + input: KeccakBuiltinState, + output: KeccakBuiltinState, +} diff --git a/src/starkware/cairo/common/cairo_function_runner.py b/src/starkware/cairo/common/cairo_function_runner.py index d84aa5a5..906396cc 100644 --- a/src/starkware/cairo/common/cairo_function_runner.py +++ b/src/starkware/cairo/common/cairo_function_runner.py @@ -7,6 +7,8 @@ from starkware.cairo.lang.builtins.ec.ec_op_builtin_runner import EcOpBuiltinRunner from starkware.cairo.lang.builtins.ec.instance_def import EcOpInstanceDef from starkware.cairo.lang.builtins.hash.hash_builtin_runner import HashBuiltinRunner +from starkware.cairo.lang.builtins.keccak.instance_def import KeccakInstanceDef +from starkware.cairo.lang.builtins.keccak.keccak_builtin_runner import KeccakBuiltinRunner from starkware.cairo.lang.builtins.range_check.range_check_builtin_runner import ( RangeCheckBuiltinRunner, ) @@ -59,6 +61,15 @@ def __init__(self, *args, **kwargs): ), ) self.builtin_runners["ec_op_builtin"] = ec_op_builtin + keccak_builtin = KeccakBuiltinRunner( + included=True, + instance_def=KeccakInstanceDef( + ratio=1, + state_rep=[200] * 8, + instances_per_component=16, + ), + ) + self.builtin_runners["keccak_builtin"] = keccak_builtin self.initialize_segments() @@ -86,6 +97,10 @@ def bitwise_builtin(self) -> BitwiseBuiltinRunner: def ec_op_builtin(self) -> EcOpBuiltinRunner: return cast(EcOpBuiltinRunner, self.builtin_runners["ec_op_builtin"]) + @property + def keccak_builtin(self) -> KeccakBuiltinRunner: + return cast(KeccakBuiltinRunner, self.builtin_runners["keccak_builtin"]) + def assert_eq(self, arg: MaybeRelocatable, expected_value, apply_modulo: bool = True): """ Asserts that arg is the Cairo representation of expected_value. diff --git a/src/starkware/cairo/common/cairo_keccak/keccak.cairo b/src/starkware/cairo/common/cairo_keccak/keccak.cairo index ec604ece..524b0c65 100644 --- a/src/starkware/cairo/common/cairo_keccak/keccak.cairo +++ b/src/starkware/cairo/common/cairo_keccak/keccak.cairo @@ -1,40 +1,40 @@ -# This module provides a set of functions to compute the (Ethereuem compatible) keccak hash -# function. -# -# In order to use the functions that get the ``keccak_ptr`` implicit argument -# (e.g., ``keccak_uint256s()``, ``keccak()``, ...) you should: -# -# 1. Create a new memory segment using ``alloc()`` and store it in a variable named -# ``keccak_ptr``. -# 2. Create a copy of the pointer, and name it ``keccak_ptr_start``, before using keccak. -# 3. Use the keccak functions with the ``keccak_ptr`` implicit argument -# (either use the ``with`` statement or write ``{keccak_ptr=keccak_ptr}`` explicitly). -# 4. Call ``finalize_keccak()`` (once) at the end of your program/transaction. -# -# For example: -# -# let (keccak_ptr : felt*) = alloc() -# local keccak_ptr_start : felt* = keccak_ptr -# -# with keccak_ptr: -# keccak_uint256s(...) -# keccak_uint256s(...) -# end -# -# finalize_keccak(keccak_ptr_start=keccak_ptr_start, keccak_ptr_end=keccak_ptr) -# -# It's more efficient to reuse the ``keccak_ptr`` segment for all the keccak functions you need, -# and call ``finalize_keccak()`` once, because of an internal batching done inside -# ``finalize_keccak()``. -# -# Failing to call ``finalize_keccak()``, will make the keccak function unsound - the prover will be -# able to choose any value as the keccak's result. -# -# The module also provides a set of helper functions to prepare the input data for keccak, -# such as ``keccak_add_uint256()`` and ``keccak_add_felt()``. To use them, you should allocate -# a new memory segment to variable named ``inputs`` (this value is an implicit argument to those -# functions). Once the input is ready, you should call ``keccak()`` or ``keccak_bigend()``. -# Don't forget to call ``finalize_keccak()`` at the end of the program/transaction. +// This module provides a set of functions to compute the (Ethereuem compatible) keccak hash +// function. +// +// In order to use the functions that get the ``keccak_ptr`` implicit argument +// (e.g., ``keccak_uint256s()``, ``keccak()``, ...) you should: +// +// 1. Create a new memory segment using ``alloc()`` and store it in a variable named +// ``keccak_ptr``. +// 2. Create a copy of the pointer, and name it ``keccak_ptr_start``, before using keccak. +// 3. Use the keccak functions with the ``keccak_ptr`` implicit argument +// (either use the ``with`` statement or write ``{keccak_ptr=keccak_ptr}`` explicitly). +// 4. Call ``finalize_keccak()`` (once) at the end of your program/transaction. +// +// For example: +// +// let (keccak_ptr: felt*) = alloc(); +// local keccak_ptr_start: felt* = keccak_ptr; +// +// with keccak_ptr { +// keccak_uint256s(...); +// keccak_uint256s(...); +// } +// +// finalize_keccak(keccak_ptr_start=keccak_ptr_start, keccak_ptr_end=keccak_ptr); +// +// It's more efficient to reuse the ``keccak_ptr`` segment for all the keccak functions you need, +// and call ``finalize_keccak()`` once, because of an internal batching done inside +// ``finalize_keccak()``. +// +// Failing to call ``finalize_keccak()``, will make the keccak function unsound - the prover will be +// able to choose any value as the keccak's result. +// +// The module also provides a set of helper functions to prepare the input data for keccak, +// such as ``keccak_add_uint256()`` and ``keccak_add_felt()``. To use them, you should allocate +// a new memory segment to variable named ``inputs`` (this value is an implicit argument to those +// functions). Once the input is ready, you should call ``keccak()`` or ``keccak_bigend()``. +// Don't forget to call ``finalize_keccak()`` at the end of the program/transaction. from starkware.cairo.common.alloc import alloc from starkware.cairo.common.bitwise import bitwise_and, bitwise_or, bitwise_xor @@ -53,323 +53,323 @@ from starkware.cairo.common.memset import memset from starkware.cairo.common.pow import pow from starkware.cairo.common.uint256 import Uint256, uint256_reverse_endian -const KECCAK_STATE_SIZE_FELTS = 25 -const KECCAK_FULL_RATE_IN_BYTES = 136 -const KECCAK_FULL_RATE_IN_WORDS = 17 -const KECCAK_CAPACITY_IN_WORDS = 8 -const BYTES_IN_WORD = 8 - -# Computes the keccak hash of multiple uint256 numbers. -func keccak_uint256s{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - n_elements : felt, elements : Uint256* -) -> (res : Uint256): - alloc_locals - - let (inputs) = alloc() - let inputs_start = inputs - - keccak_add_uint256s{inputs=inputs}(n_elements=n_elements, elements=elements, bigend=0) - - return keccak(inputs=inputs_start, n_bytes=n_elements * 32) -end - -# Computes the keccak hash of multiple uint256 numbers (big-endian). -# Note that both the output and the input are in big endian representation. -func keccak_uint256s_bigend{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - n_elements : felt, elements : Uint256* -) -> (res : Uint256): - alloc_locals - - let (inputs) = alloc() - let inputs_start = inputs - - keccak_add_uint256s{inputs=inputs}(n_elements=n_elements, elements=elements, bigend=1) - - return keccak_bigend(inputs=inputs_start, n_bytes=n_elements * 32) -end - -# Computes the keccak hash of multiple field elements. -func keccak_felts{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - n_elements : felt, elements : felt* -) -> (res : Uint256): - alloc_locals - - let (inputs) = alloc() - let inputs_start = inputs - - keccak_add_felts{inputs=inputs}(n_elements=n_elements, elements=elements, bigend=0) - - return keccak(inputs=inputs_start, n_bytes=n_elements * 32) -end - -# Computes the keccak hash of multiple field elements (big-endian). -# Note that both the output and the input are in big endian representation. -func keccak_felts_bigend{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - n_elements : felt, elements : felt* -) -> (res : Uint256): - alloc_locals - - let (inputs) = alloc() - let inputs_start = inputs - - keccak_add_felts{inputs=inputs}(n_elements=n_elements, elements=elements, bigend=1) - - return keccak_bigend(inputs=inputs_start, n_bytes=n_elements * 32) -end - -# Helper functions. -# These functions serialize input to an array of 64-bit little endian words -# to be used with keccak() or keccak_as_words(). -# Note: You must call finalize_keccak() at the end of the program, where the range of the input -# is checked. Otherwise, these functions are not sound. - -# Serializes a uint256 number in a keccak compatible way. -# The argument 'bigend' is either 0 or 1, representing the endianness of the given number. -func keccak_add_uint256{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, inputs : felt*}( - num : Uint256, bigend : felt -): - if bigend != 0: - let (num_reversed) = uint256_reverse_endian(num=num) - tempvar bitwise_ptr = bitwise_ptr - tempvar high = num_reversed.high - tempvar low = num_reversed.low - else: - tempvar bitwise_ptr = bitwise_ptr - tempvar high = num.high - tempvar low = num.low - end +const KECCAK_STATE_SIZE_FELTS = 25; +const KECCAK_FULL_RATE_IN_BYTES = 136; +const KECCAK_FULL_RATE_IN_WORDS = 17; +const KECCAK_CAPACITY_IN_WORDS = 8; +const BYTES_IN_WORD = 8; + +// Computes the keccak hash of multiple uint256 numbers. +func keccak_uint256s{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + n_elements: felt, elements: Uint256* +) -> (res: Uint256) { + alloc_locals; + + let (inputs) = alloc(); + let inputs_start = inputs; + + keccak_add_uint256s{inputs=inputs}(n_elements=n_elements, elements=elements, bigend=0); + + return keccak(inputs=inputs_start, n_bytes=n_elements * 32); +} + +// Computes the keccak hash of multiple uint256 numbers (big-endian). +// Note that both the output and the input are in big endian representation. +func keccak_uint256s_bigend{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + n_elements: felt, elements: Uint256* +) -> (res: Uint256) { + alloc_locals; + + let (inputs) = alloc(); + let inputs_start = inputs; + + keccak_add_uint256s{inputs=inputs}(n_elements=n_elements, elements=elements, bigend=1); + + return keccak_bigend(inputs=inputs_start, n_bytes=n_elements * 32); +} + +// Computes the keccak hash of multiple field elements. +func keccak_felts{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + n_elements: felt, elements: felt* +) -> (res: Uint256) { + alloc_locals; + + let (inputs) = alloc(); + let inputs_start = inputs; + + keccak_add_felts{inputs=inputs}(n_elements=n_elements, elements=elements, bigend=0); + + return keccak(inputs=inputs_start, n_bytes=n_elements * 32); +} + +// Computes the keccak hash of multiple field elements (big-endian). +// Note that both the output and the input are in big endian representation. +func keccak_felts_bigend{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + n_elements: felt, elements: felt* +) -> (res: Uint256) { + alloc_locals; + + let (inputs) = alloc(); + let inputs_start = inputs; + + keccak_add_felts{inputs=inputs}(n_elements=n_elements, elements=elements, bigend=1); + + return keccak_bigend(inputs=inputs_start, n_bytes=n_elements * 32); +} + +// Helper functions. +// These functions serialize input to an array of 64-bit little endian words +// to be used with keccak() or keccak_as_words(). +// Note: You must call finalize_keccak() at the end of the program, where the range of the input +// is checked. Otherwise, these functions are not sound. + +// Serializes a uint256 number in a keccak compatible way. +// The argument 'bigend' is either 0 or 1, representing the endianness of the given number. +func keccak_add_uint256{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, inputs: felt*}( + num: Uint256, bigend: felt +) { + if (bigend != 0) { + let (num_reversed) = uint256_reverse_endian(num=num); + tempvar bitwise_ptr = bitwise_ptr; + tempvar high = num_reversed.high; + tempvar low = num_reversed.low; + } else { + tempvar bitwise_ptr = bitwise_ptr; + tempvar high = num.high; + tempvar low = num.low; + } %{ segments.write_arg(ids.inputs, [ids.low % 2 ** 64, ids.low // 2 ** 64]) segments.write_arg(ids.inputs + 2, [ids.high % 2 ** 64, ids.high // 2 ** 64]) %} - assert inputs[1] * 2 ** 64 + inputs[0] = low - assert inputs[3] * 2 ** 64 + inputs[2] = high - - let inputs = inputs + 4 - return () -end - -# Serializes multiple uint256 numbers in a keccak compatible way. -# The argument 'bigend' is either 0 or 1, representing the endianness of the given numbers. -# Note: This function does not serialize the number of elements. If desired, this is the caller's -# responsibility. -func keccak_add_uint256s{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, inputs : felt*}( - n_elements : felt, elements : Uint256*, bigend : felt -): - if n_elements == 0: - return () - end - - keccak_add_uint256(num=elements[0], bigend=bigend) - return keccak_add_uint256s(n_elements=n_elements - 1, elements=&elements[1], bigend=bigend) -end - -# Serializes a field element in a keccak compatible way. -# The argument 'bigend' is either 0 or 1, representing the endianness of the given element. -func keccak_add_felt{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, inputs : felt*}( - num : felt, bigend : felt -): - let (high, low) = split_felt(value=num) - keccak_add_uint256(num=Uint256(low=low, high=high), bigend=bigend) - - return () -end - -# Serializes multiple field elements in a keccak compatible way. -# The argument 'bigend' is either 0 or 1, representing the endianness of the given elements. -# Note: This function does not serialize the number of elements. If desired, this is the caller's -# responsibility. -func keccak_add_felts{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, inputs : felt*}( - n_elements : felt, elements : felt*, bigend : felt -): - if n_elements == 0: - return () - end - - keccak_add_felt(num=elements[0], bigend=bigend) - return keccak_add_felts(n_elements=n_elements - 1, elements=&elements[1], bigend=bigend) -end - -# Computes the keccak of 'input'. -# To use this function, split the input into words of 64 bits (little endian). -# For example, to compute keccak('Hello world!'), use: -# inputs = [8031924123371070792, 560229490] -# where: -# 8031924123371070792 == int.from_bytes(b'Hello wo', 'little') -# 560229490 == int.from_bytes(b'rld!', 'little') -# -# Returns the hash as a Uint256. -# -# Note: You must call finalize_keccak() at the end of the program. Otherwise, this function -# is not sound and a malicious prover may return a wrong result. -func keccak{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - inputs : felt*, n_bytes : felt -) -> (res : Uint256): - let (output) = keccak_as_words(inputs=inputs, n_bytes=n_bytes) - - let res_low = output[1] * 2 ** 64 + output[0] - let res_high = output[3] * 2 ** 64 + output[2] - - return (res=Uint256(low=res_low, high=res_high)) -end - -# Same as keccak, but outputs the hash in big endian representation. -# Note that the input is still treated as little endian. -func keccak_bigend{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - inputs : felt*, n_bytes : felt -) -> (res : Uint256): - let (hash) = keccak(inputs=inputs, n_bytes=n_bytes) - let (res) = uint256_reverse_endian(num=hash) - return (res=res) -end - -# Same as keccak, but outputs a pointer to 4 64-bit little endian words instead. -func keccak_as_words{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - inputs : felt*, n_bytes : felt -) -> (output : felt*): - alloc_locals - - let (local state) = alloc() - memset(dst=state, value=0, n=KECCAK_STATE_SIZE_FELTS) - - return _keccak(inputs=inputs, n_bytes=n_bytes, state=state) -end - -# Prepares a block for the block permutation: adds padding (of the form 100...001, see the -# _padding function) and capacity (8 64-bits words of zeros) to the input, xors the result -# with the previous block permutation's output, and writes it to keccak_ptr. -# -# This function is called for every block that is sent to the _block_permutation -# function. Each time it is called with a chunk of the input of at -# most 17 64-bit words. That is, with n_bytes <= 136. When it is called with exactly 136 -# bytes, no padding is added. Only the last block is padded. -# -# Arguments: -# inputs - chunk of the input, in little endian. -# n_bytes - the length of inputs in bytes. Must be in the range [0, 136]. -# state - the output of the previous block permutation that contains 25 64-bits words. -func _prepare_block{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - inputs : felt*, n_bytes : felt, state : felt* -): - alloc_locals - - let inputs_start = inputs - _copy_inputs{inputs=inputs, n_bytes=n_bytes, state=state}() - # n_words_written is the number of words written to keccak_ptr. - let n_words_written = inputs - inputs_start - - tempvar padding_len = (KECCAK_FULL_RATE_IN_WORDS - n_words_written) - local input_word - if n_bytes == 0: - input_word = 0 - else: - input_word = inputs[0] - end - - _padding(input_word=input_word, n_bytes=n_bytes, state=state, padding_len=padding_len) - let state = state + padding_len - - # Since the capacity part consists of zeros, we simply copy the state. - memcpy(dst=keccak_ptr, src=state, len=KECCAK_CAPACITY_IN_WORDS) - let keccak_ptr = keccak_ptr + KECCAK_CAPACITY_IN_WORDS - - return () -end - -# Xors full words from the input with the corresponding words from the output of the -# previous block permutation, and writes the restult to keccak_ptr. + assert inputs[1] * 2 ** 64 + inputs[0] = low; + assert inputs[3] * 2 ** 64 + inputs[2] = high; + + let inputs = inputs + 4; + return (); +} + +// Serializes multiple uint256 numbers in a keccak compatible way. +// The argument 'bigend' is either 0 or 1, representing the endianness of the given numbers. +// Note: This function does not serialize the number of elements. If desired, this is the caller's +// responsibility. +func keccak_add_uint256s{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, inputs: felt*}( + n_elements: felt, elements: Uint256*, bigend: felt +) { + if (n_elements == 0) { + return (); + } + + keccak_add_uint256(num=elements[0], bigend=bigend); + return keccak_add_uint256s(n_elements=n_elements - 1, elements=&elements[1], bigend=bigend); +} + +// Serializes a field element in a keccak compatible way. +// The argument 'bigend' is either 0 or 1, representing the endianness of the given element. +func keccak_add_felt{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, inputs: felt*}( + num: felt, bigend: felt +) { + let (high, low) = split_felt(value=num); + keccak_add_uint256(num=Uint256(low=low, high=high), bigend=bigend); + + return (); +} + +// Serializes multiple field elements in a keccak compatible way. +// The argument 'bigend' is either 0 or 1, representing the endianness of the given elements. +// Note: This function does not serialize the number of elements. If desired, this is the caller's +// responsibility. +func keccak_add_felts{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, inputs: felt*}( + n_elements: felt, elements: felt*, bigend: felt +) { + if (n_elements == 0) { + return (); + } + + keccak_add_felt(num=elements[0], bigend=bigend); + return keccak_add_felts(n_elements=n_elements - 1, elements=&elements[1], bigend=bigend); +} + +// Computes the keccak of 'input'. +// To use this function, split the input into words of 64 bits (little endian). +// For example, to compute keccak('Hello world!'), use: +// inputs = [8031924123371070792, 560229490] +// where: +// 8031924123371070792 == int.from_bytes(b'Hello wo', 'little') +// 560229490 == int.from_bytes(b'rld!', 'little') +// +// Returns the hash as a Uint256. +// +// Note: You must call finalize_keccak() at the end of the program. Otherwise, this function +// is not sound and a malicious prover may return a wrong result. +func keccak{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + inputs: felt*, n_bytes: felt +) -> (res: Uint256) { + let (output) = keccak_as_words(inputs=inputs, n_bytes=n_bytes); + + let res_low = output[1] * 2 ** 64 + output[0]; + let res_high = output[3] * 2 ** 64 + output[2]; + + return (res=Uint256(low=res_low, high=res_high)); +} + +// Same as keccak, but outputs the hash in big endian representation. +// Note that the input is still treated as little endian. +func keccak_bigend{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + inputs: felt*, n_bytes: felt +) -> (res: Uint256) { + let (hash) = keccak(inputs=inputs, n_bytes=n_bytes); + let (res) = uint256_reverse_endian(num=hash); + return (res=res); +} + +// Same as keccak, but outputs a pointer to 4 64-bit little endian words instead. +func keccak_as_words{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + inputs: felt*, n_bytes: felt +) -> (output: felt*) { + alloc_locals; + + let (local state) = alloc(); + memset(dst=state, value=0, n=KECCAK_STATE_SIZE_FELTS); + + return _keccak(inputs=inputs, n_bytes=n_bytes, state=state); +} + +// Prepares a block for the block permutation: adds padding (of the form 100...001, see the +// _padding function) and capacity (8 64-bits words of zeros) to the input, xors the result +// with the previous block permutation's output, and writes it to keccak_ptr. +// +// This function is called for every block that is sent to the _block_permutation +// function. Each time it is called with a chunk of the input of at +// most 17 64-bit words. That is, with n_bytes <= 136. When it is called with exactly 136 +// bytes, no padding is added. Only the last block is padded. +// +// Arguments: +// inputs - chunk of the input, in little endian. +// n_bytes - the length of inputs in bytes. Must be in the range [0, 136]. +// state - the output of the previous block permutation that contains 25 64-bits words. +func _prepare_block{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + inputs: felt*, n_bytes: felt, state: felt* +) { + alloc_locals; + + let inputs_start = inputs; + _copy_inputs{inputs=inputs, n_bytes=n_bytes, state=state}(); + // n_words_written is the number of words written to keccak_ptr. + let n_words_written = inputs - inputs_start; + + tempvar padding_len = (KECCAK_FULL_RATE_IN_WORDS - n_words_written); + local input_word; + if (n_bytes == 0) { + input_word = 0; + } else { + input_word = inputs[0]; + } + + _padding(input_word=input_word, n_bytes=n_bytes, state=state, padding_len=padding_len); + let state = state + padding_len; + + // Since the capacity part consists of zeros, we simply copy the state. + memcpy(dst=keccak_ptr, src=state, len=KECCAK_CAPACITY_IN_WORDS); + let keccak_ptr = keccak_ptr + KECCAK_CAPACITY_IN_WORDS; + + return (); +} + +// Xors full words from the input with the corresponding words from the output of the +// previous block permutation, and writes the restult to keccak_ptr. func _copy_inputs{ range_check_ptr, - bitwise_ptr : BitwiseBuiltin*, - keccak_ptr : felt*, - inputs : felt*, - n_bytes : felt, - state : felt*, -}(): - if nondet %{ ids.n_bytes < ids.BYTES_IN_WORD %} != 0: - assert_nn_le(n_bytes, BYTES_IN_WORD - 1) - return () - end - - let (next_word) = bitwise_xor(inputs[0], state[0]) - assert keccak_ptr[0] = next_word - - let inputs = &inputs[1] - let state = &state[1] - let keccak_ptr = &keccak_ptr[1] - let n_bytes = n_bytes - BYTES_IN_WORD - - return _copy_inputs() -end - -# Adds padding of the form 100...001 to the last bytes of the input, to a total of -# padding_len words, xors the result with the output of the last block permutation, -# from the corresponding offset, and writes it to keccak_ptr. -# -# Arguments: -# input_word - the last word of the input to keccak (given in little endian) -# if it has less than 8 bytes, otherwise 0. -# n_bytes - the number of bytes in input_word. Must be in the range [0, 8). -# state - the output of the last block permutation, from the word that corresponds -# to the input_word. (i.e., if input_word is the i-th word in the current block, -# then state points to the i-th word of the last block permutation's output). -# padding_len - the length of the required padding (in words). Must be in the range [0, 17]. -func _padding{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - input_word : felt, n_bytes : felt, state : felt*, padding_len : felt -): - if padding_len == 0: - return () - end - - let (first_one) = pow(256, n_bytes) - # The beginning of the padding with the last bytes of the input and the first 1. - let input_word_with_initial_padding = input_word + first_one - - if padding_len == 1: - let both_ones = 2 ** 63 + input_word_with_initial_padding - let (word) = bitwise_xor(both_ones, state[0]) - - assert keccak_ptr[0] = word - let keccak_ptr = &keccak_ptr[1] - - return () - end + bitwise_ptr: BitwiseBuiltin*, + keccak_ptr: felt*, + inputs: felt*, + n_bytes: felt, + state: felt*, +}() { + if (nondet %{ ids.n_bytes < ids.BYTES_IN_WORD %} != 0) { + assert_nn_le(n_bytes, BYTES_IN_WORD - 1); + return (); + } + + let (next_word) = bitwise_xor(inputs[0], state[0]); + assert keccak_ptr[0] = next_word; + + let inputs = &inputs[1]; + let state = &state[1]; + let keccak_ptr = &keccak_ptr[1]; + let n_bytes = n_bytes - BYTES_IN_WORD; + + return _copy_inputs(); +} + +// Adds padding of the form 100...001 to the last bytes of the input, to a total of +// padding_len words, xors the result with the output of the last block permutation, +// from the corresponding offset, and writes it to keccak_ptr. +// +// Arguments: +// input_word - the last word of the input to keccak (given in little endian) +// if it has less than 8 bytes, otherwise 0. +// n_bytes - the number of bytes in input_word. Must be in the range [0, 8). +// state - the output of the last block permutation, from the word that corresponds +// to the input_word. (i.e., if input_word is the i-th word in the current block, +// then state points to the i-th word of the last block permutation's output). +// padding_len - the length of the required padding (in words). Must be in the range [0, 17]. +func _padding{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + input_word: felt, n_bytes: felt, state: felt*, padding_len: felt +) { + if (padding_len == 0) { + return (); + } + + let (first_one) = pow(256, n_bytes); + // The beginning of the padding with the last bytes of the input and the first 1. + let input_word_with_initial_padding = input_word + first_one; + + if (padding_len == 1) { + let both_ones = 2 ** 63 + input_word_with_initial_padding; + let (word) = bitwise_xor(both_ones, state[0]); + + assert keccak_ptr[0] = word; + let keccak_ptr = &keccak_ptr[1]; + + return (); + } return _long_padding( input_word_with_initial_padding=input_word_with_initial_padding, state=state, padding_len=padding_len, - ) -end - -# Padding of more than 1 word. -func _long_padding{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - input_word_with_initial_padding : felt, state : felt*, padding_len : felt -): - alloc_locals - - # First word. - let (first_one) = bitwise_xor(input_word_with_initial_padding, state[0]) - assert keccak_ptr[0] = first_one - let keccak_ptr = &keccak_ptr[1] - let state = state + 1 - - # The padding of the inner words is zero, so we should simply copy them. - memcpy(dst=keccak_ptr, src=state, len=padding_len - 2) - let keccak_ptr = keccak_ptr + padding_len - 2 - let state = state + padding_len - 2 - - # Last word. - let (second_one) = bitwise_xor(2 ** 63, state[0]) - assert keccak_ptr[0] = second_one - let keccak_ptr = &keccak_ptr[1] - - return () -end - -func _block_permutation{keccak_ptr : felt*}(): + ); +} + +// Padding of more than 1 word. +func _long_padding{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + input_word_with_initial_padding: felt, state: felt*, padding_len: felt +) { + alloc_locals; + + // First word. + let (first_one) = bitwise_xor(input_word_with_initial_padding, state[0]); + assert keccak_ptr[0] = first_one; + let keccak_ptr = &keccak_ptr[1]; + let state = state + 1; + + // The padding of the inner words is zero, so we should simply copy them. + memcpy(dst=keccak_ptr, src=state, len=padding_len - 2); + let keccak_ptr = keccak_ptr + padding_len - 2; + let state = state + padding_len - 2; + + // Last word. + let (second_one) = bitwise_xor(2 ** 63, state[0]); + assert keccak_ptr[0] = second_one; + let keccak_ptr = &keccak_ptr[1]; + + return (); +} + +func _block_permutation{keccak_ptr: felt*}() { %{ from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) @@ -379,44 +379,44 @@ func _block_permutation{keccak_ptr : felt*}(): ids.keccak_ptr - _keccak_state_size_felts, _keccak_state_size_felts)) segments.write_arg(ids.keccak_ptr, output_values) %} - let keccak_ptr = keccak_ptr + KECCAK_STATE_SIZE_FELTS + let keccak_ptr = keccak_ptr + KECCAK_STATE_SIZE_FELTS; - return () -end + return (); +} -func _keccak{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - inputs : felt*, n_bytes : felt, state : felt* -) -> (output : felt*): - if nondet %{ ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES %} != 0: - _prepare_block(inputs=inputs, n_bytes=KECCAK_FULL_RATE_IN_BYTES, state=state) - _block_permutation() +func _keccak{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + inputs: felt*, n_bytes: felt, state: felt* +) -> (output: felt*) { + if (nondet %{ ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES %} != 0) { + _prepare_block(inputs=inputs, n_bytes=KECCAK_FULL_RATE_IN_BYTES, state=state); + _block_permutation(); return _keccak( inputs=inputs + KECCAK_FULL_RATE_IN_WORDS, n_bytes=n_bytes - KECCAK_FULL_RATE_IN_BYTES, state=keccak_ptr - KECCAK_STATE_SIZE_FELTS, - ) - end + ); + } - assert_nn_le(n_bytes, KECCAK_FULL_RATE_IN_BYTES - 1) + assert_nn_le(n_bytes, KECCAK_FULL_RATE_IN_BYTES - 1); - _prepare_block(inputs=inputs, n_bytes=n_bytes, state=state) - _block_permutation() + _prepare_block(inputs=inputs, n_bytes=n_bytes, state=state); + _block_permutation(); - return (keccak_ptr - KECCAK_STATE_SIZE_FELTS) -end + return (output=keccak_ptr - KECCAK_STATE_SIZE_FELTS); +} -# Verifies that the results of keccak() are valid. For optimization, this can be called only once -# after all the keccak calculations are completed. -func finalize_keccak{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}( - keccak_ptr_start : felt*, keccak_ptr_end : felt* -): - alloc_locals +// Verifies that the results of keccak() are valid. For optimization, this can be called only once +// after all the keccak calculations are completed. +func finalize_keccak{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + keccak_ptr_start: felt*, keccak_ptr_end: felt* +) { + alloc_locals; - tempvar n = (keccak_ptr_end - keccak_ptr_start) / (2 * KECCAK_STATE_SIZE_FELTS) - if n == 0: - return () - end + tempvar n = (keccak_ptr_end - keccak_ptr_start) / (2 * KECCAK_STATE_SIZE_FELTS); + if (n == 0) { + return (); + } %{ # Add dummy pairs of input and output. @@ -429,82 +429,82 @@ func finalize_keccak{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}( segments.write_arg(ids.keccak_ptr_end, padding) %} - # Compute the amount of blocks (rounded up). - let (local q, r) = unsigned_div_rem(n + BLOCK_SIZE - 1, BLOCK_SIZE) - _finalize_keccak_inner(keccak_ptr_start, n=q) - return () -end + // Compute the amount of blocks (rounded up). + let (local q, r) = unsigned_div_rem(n + BLOCK_SIZE - 1, BLOCK_SIZE); + _finalize_keccak_inner(keccak_ptr_start, n=q); + return (); +} -# Handles n blocks of BLOCK_SIZE keccak instances. -func _finalize_keccak_inner{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}( - keccak_ptr : felt*, n : felt -): - if n == 0: - return () - end +// Handles n blocks of BLOCK_SIZE keccak instances. +func _finalize_keccak_inner{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + keccak_ptr: felt*, n: felt +) { + if (n == 0) { + return (); + } - ap += SIZEOF_LOCALS + ap += SIZEOF_LOCALS; - local MAX_VALUE = 2 ** 64 - 1 + local MAX_VALUE = 2 ** 64 - 1; - let keccak_ptr_start = keccak_ptr + let keccak_ptr_start = keccak_ptr; - let (local inputs_start : felt*) = alloc() + let (local inputs_start: felt*) = alloc(); - # Handle inputs. + // Handle inputs. - tempvar inputs = inputs_start - tempvar keccak_ptr = keccak_ptr - tempvar range_check_ptr = range_check_ptr - tempvar m = 25 + tempvar inputs = inputs_start; + tempvar keccak_ptr = keccak_ptr; + tempvar range_check_ptr = range_check_ptr; + tempvar m = 25; input_loop: - tempvar x0 = keccak_ptr[0] - assert [range_check_ptr] = x0 - assert [range_check_ptr + 1] = MAX_VALUE - x0 - tempvar x1 = keccak_ptr[50] - assert [range_check_ptr + 2] = x1 - assert [range_check_ptr + 3] = MAX_VALUE - x1 - tempvar x2 = keccak_ptr[100] - assert [range_check_ptr + 4] = x2 - assert [range_check_ptr + 5] = MAX_VALUE - x2 - assert inputs[0] = x0 + 2 ** 64 * x1 + 2 ** 128 * x2 - - tempvar inputs = inputs + 1 - tempvar keccak_ptr = keccak_ptr + 1 - tempvar range_check_ptr = range_check_ptr + 6 - tempvar m = m - 1 - jmp input_loop if m != 0 - - # Run keccak on the 3 instances. - - let (outputs) = packed_keccak_func(inputs_start) - local bitwise_ptr : BitwiseBuiltin* = bitwise_ptr - - # Handle outputs. - - tempvar outputs = outputs - tempvar keccak_ptr = keccak_ptr - tempvar range_check_ptr = range_check_ptr - tempvar m = 25 + tempvar x0 = keccak_ptr[0]; + assert [range_check_ptr] = x0; + assert [range_check_ptr + 1] = MAX_VALUE - x0; + tempvar x1 = keccak_ptr[50]; + assert [range_check_ptr + 2] = x1; + assert [range_check_ptr + 3] = MAX_VALUE - x1; + tempvar x2 = keccak_ptr[100]; + assert [range_check_ptr + 4] = x2; + assert [range_check_ptr + 5] = MAX_VALUE - x2; + assert inputs[0] = x0 + 2 ** 64 * x1 + 2 ** 128 * x2; + + tempvar inputs = inputs + 1; + tempvar keccak_ptr = keccak_ptr + 1; + tempvar range_check_ptr = range_check_ptr + 6; + tempvar m = m - 1; + jmp input_loop if m != 0; + + // Run keccak on the 3 instances. + + let (outputs) = packed_keccak_func(inputs_start); + local bitwise_ptr: BitwiseBuiltin* = bitwise_ptr; + + // Handle outputs. + + tempvar outputs = outputs; + tempvar keccak_ptr = keccak_ptr; + tempvar range_check_ptr = range_check_ptr; + tempvar m = 25; output_loop: - tempvar x0 = keccak_ptr[0] - assert [range_check_ptr] = x0 - assert [range_check_ptr + 1] = MAX_VALUE - x0 - tempvar x1 = keccak_ptr[50] - assert [range_check_ptr + 2] = x1 - assert [range_check_ptr + 3] = MAX_VALUE - x1 - tempvar x2 = keccak_ptr[100] - assert [range_check_ptr + 4] = x2 - assert [range_check_ptr + 5] = MAX_VALUE - x2 - assert outputs[0] = x0 + 2 ** 64 * x1 + 2 ** 128 * x2 - - tempvar outputs = outputs + 1 - tempvar keccak_ptr = keccak_ptr + 1 - tempvar range_check_ptr = range_check_ptr + 6 - tempvar m = m - 1 - jmp output_loop if m != 0 - - return _finalize_keccak_inner(keccak_ptr=keccak_ptr_start + 150, n=n - 1) -end + tempvar x0 = keccak_ptr[0]; + assert [range_check_ptr] = x0; + assert [range_check_ptr + 1] = MAX_VALUE - x0; + tempvar x1 = keccak_ptr[50]; + assert [range_check_ptr + 2] = x1; + assert [range_check_ptr + 3] = MAX_VALUE - x1; + tempvar x2 = keccak_ptr[100]; + assert [range_check_ptr + 4] = x2; + assert [range_check_ptr + 5] = MAX_VALUE - x2; + assert outputs[0] = x0 + 2 ** 64 * x1 + 2 ** 128 * x2; + + tempvar outputs = outputs + 1; + tempvar keccak_ptr = keccak_ptr + 1; + tempvar range_check_ptr = range_check_ptr + 6; + tempvar m = m - 1; + jmp output_loop if m != 0; + + return _finalize_keccak_inner(keccak_ptr=keccak_ptr_start + 150, n=n - 1); +} diff --git a/src/starkware/cairo/common/cairo_keccak/packed_keccak.cairo b/src/starkware/cairo/common/cairo_keccak/packed_keccak.cairo index ae6bd384..aa9aadfa 100644 --- a/src/starkware/cairo/common/cairo_keccak/packed_keccak.cairo +++ b/src/starkware/cairo/common/cairo_keccak/packed_keccak.cairo @@ -2,555 +2,555 @@ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.cairo_builtins import BitwiseBuiltin from starkware.cairo.common.registers import get_fp_and_pc -const ALL_ONES = 2 ** 251 - 1 -const BLOCK_SIZE = 3 -const SHIFTS = 1 + 2 ** 64 + 2 ** 128 - -func keccak_round{bitwise_ptr : BitwiseBuiltin*}(values : felt*, rc : felt) -> (values_b : felt*): - ap += SIZEOF_LOCALS - - ############################################################################################## - # Compute: c[x] = a[0][x] ^ a[1][x] ^ a[2][x] ^ a[3][x] ^ a[4][x]. # - ############################################################################################## - - let values_start = values - - assert bitwise_ptr[0].x = values[0] - assert bitwise_ptr[0].y = values[5] - assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].y = values[10] - assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y - assert bitwise_ptr[2].y = values[15] - assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y - assert bitwise_ptr[3].y = values[20] - tempvar c0 = bitwise_ptr[3].x_xor_y - let values = values + 1 - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[0] - assert bitwise_ptr[0].y = values[5] - assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].y = values[10] - assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y - assert bitwise_ptr[2].y = values[15] - assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y - assert bitwise_ptr[3].y = values[20] - tempvar c1 = bitwise_ptr[3].x_xor_y - let values = values + 1 - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[0] - assert bitwise_ptr[0].y = values[5] - assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].y = values[10] - assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y - assert bitwise_ptr[2].y = values[15] - assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y - assert bitwise_ptr[3].y = values[20] - tempvar c2 = bitwise_ptr[3].x_xor_y - let values = values + 1 - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[0] - assert bitwise_ptr[0].y = values[5] - assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].y = values[10] - assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y - assert bitwise_ptr[2].y = values[15] - assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y - assert bitwise_ptr[3].y = values[20] - tempvar c3 = bitwise_ptr[3].x_xor_y - let values = values + 1 - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[0] - assert bitwise_ptr[0].y = values[5] - assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].y = values[10] - assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y - assert bitwise_ptr[2].y = values[15] - assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y - assert bitwise_ptr[3].y = values[20] - tempvar c4 = bitwise_ptr[3].x_xor_y - let values = values + 1 - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE - - ############################################################################################## - # Compute: d[x] = c[(x - 1) % 5] ^ rot_left(c[(x + 1) % 5], 1). # - ############################################################################################## - - # Saving constants as local variables is more efficient in some instructions. - local mask = 0x800000000000000080000000000000008000000000000000 - - let x = c1 - let y = c4 - assert bitwise_ptr[0].x = x - assert bitwise_ptr[0].y = mask - tempvar x0 = bitwise_ptr[0].x_and_y - let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0 - assert bitwise_ptr[1].x = rotx - assert bitwise_ptr[1].y = y - tempvar d0 = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - let x = c2 - let y = c0 - assert bitwise_ptr[0].x = x - assert bitwise_ptr[0].y = mask - tempvar x0 = bitwise_ptr[0].x_and_y - let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0 - assert bitwise_ptr[1].x = rotx - assert bitwise_ptr[1].y = y - tempvar d1 = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - let x = c3 - let y = c1 - assert bitwise_ptr[0].x = x - assert bitwise_ptr[0].y = mask - tempvar x0 = bitwise_ptr[0].x_and_y - let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0 - assert bitwise_ptr[1].x = rotx - assert bitwise_ptr[1].y = y - tempvar d2 = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - let x = c4 - let y = c2 - assert bitwise_ptr[0].x = x - assert bitwise_ptr[0].y = mask - tempvar x0 = bitwise_ptr[0].x_and_y - let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0 - assert bitwise_ptr[1].x = rotx - assert bitwise_ptr[1].y = y - tempvar d3 = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - let x = c0 - let y = c3 - assert bitwise_ptr[0].x = x - assert bitwise_ptr[0].y = mask - tempvar x0 = bitwise_ptr[0].x_and_y - let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0 - assert bitwise_ptr[1].x = rotx - assert bitwise_ptr[1].y = y - tempvar d4 = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - ############################################################################################## - # Compute: b[(2 * x + 3 * y) % 5][y] = rot_left([a[y][x] ^ d[x], OFFSETS[x][y]) # - ############################################################################################## - - let values = values_start - - assert bitwise_ptr[0].x = values[0] - assert bitwise_ptr[0].y = d0 - tempvar b0 = bitwise_ptr[0].x_xor_y - let bitwise_ptr = bitwise_ptr + 1 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[5] - assert bitwise_ptr[0].y = d0 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffffffff0000000fffffffff0000000fffffffff0000000 - tempvar b16 = 2 ** 36 * x + (1 / 2 ** 28 - 2 ** 36) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[10] - assert bitwise_ptr[0].y = d0 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xe000000000000000e000000000000000e000000000000000 - tempvar b7 = 2 ** 3 * x + (1 / 2 ** 61 - 2 ** 3) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[15] - assert bitwise_ptr[0].y = d0 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xffffffffff800000ffffffffff800000ffffffffff800000 - tempvar b23 = 2 ** 41 * x + (1 / 2 ** 23 - 2 ** 41) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[20] - assert bitwise_ptr[0].y = d0 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xffffc00000000000ffffc00000000000ffffc00000000000 - tempvar b14 = 2 ** 18 * x + (1 / 2 ** 46 - 2 ** 18) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[1] - assert bitwise_ptr[0].y = d1 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0x800000000000000080000000000000008000000000000000 - tempvar b10 = 2 ** 1 * x + (1 / 2 ** 63 - 2 ** 1) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[6] - assert bitwise_ptr[0].y = d1 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffffffffff00000fffffffffff00000fffffffffff00000 - tempvar b1 = 2 ** 44 * x + (1 / 2 ** 20 - 2 ** 44) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[11] - assert bitwise_ptr[0].y = d1 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xffc0000000000000ffc0000000000000ffc0000000000000 - tempvar b17 = 2 ** 10 * x + (1 / 2 ** 54 - 2 ** 10) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[16] - assert bitwise_ptr[0].y = d1 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffffffffff80000fffffffffff80000fffffffffff80000 - tempvar b8 = 2 ** 45 * x + (1 / 2 ** 19 - 2 ** 45) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[21] - assert bitwise_ptr[0].y = d1 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xc000000000000000c000000000000000c000000000000000 - tempvar b24 = 2 ** 2 * x + (1 / 2 ** 62 - 2 ** 2) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[2] - assert bitwise_ptr[0].y = d2 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffffffffffffffcfffffffffffffffcfffffffffffffffc - tempvar b20 = 2 ** 62 * x + (1 / 2 ** 2 - 2 ** 62) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[7] - assert bitwise_ptr[0].y = d2 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfc00000000000000fc00000000000000fc00000000000000 - tempvar b11 = 2 ** 6 * x + (1 / 2 ** 58 - 2 ** 6) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[12] - assert bitwise_ptr[0].y = d2 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xffffffffffe00000ffffffffffe00000ffffffffffe00000 - tempvar b2 = 2 ** 43 * x + (1 / 2 ** 21 - 2 ** 43) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[17] - assert bitwise_ptr[0].y = d2 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffe000000000000fffe000000000000fffe000000000000 - tempvar b18 = 2 ** 15 * x + (1 / 2 ** 49 - 2 ** 15) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[22] - assert bitwise_ptr[0].y = d2 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffffffffffffff8fffffffffffffff8fffffffffffffff8 - tempvar b9 = 2 ** 61 * x + (1 / 2 ** 3 - 2 ** 61) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[3] - assert bitwise_ptr[0].y = d3 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffffff000000000fffffff000000000fffffff000000000 - tempvar b5 = 2 ** 28 * x + (1 / 2 ** 36 - 2 ** 28) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[8] - assert bitwise_ptr[0].y = d3 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffffffffffffe00fffffffffffffe00fffffffffffffe00 - tempvar b21 = 2 ** 55 * x + (1 / 2 ** 9 - 2 ** 55) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[13] - assert bitwise_ptr[0].y = d3 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xffffff8000000000ffffff8000000000ffffff8000000000 - tempvar b12 = 2 ** 25 * x + (1 / 2 ** 39 - 2 ** 25) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[18] - assert bitwise_ptr[0].y = d3 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffff80000000000fffff80000000000fffff80000000000 - tempvar b3 = 2 ** 21 * x + (1 / 2 ** 43 - 2 ** 21) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[23] - assert bitwise_ptr[0].y = d3 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xffffffffffffff00ffffffffffffff00ffffffffffffff00 - tempvar b19 = 2 ** 56 * x + (1 / 2 ** 8 - 2 ** 56) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[4] - assert bitwise_ptr[0].y = d4 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xffffffe000000000ffffffe000000000ffffffe000000000 - tempvar b15 = 2 ** 27 * x + (1 / 2 ** 37 - 2 ** 27) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[9] - assert bitwise_ptr[0].y = d4 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffff00000000000fffff00000000000fffff00000000000 - tempvar b6 = 2 ** 20 * x + (1 / 2 ** 44 - 2 ** 20) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[14] - assert bitwise_ptr[0].y = d4 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffffffffe000000fffffffffe000000fffffffffe000000 - tempvar b22 = 2 ** 39 * x + (1 / 2 ** 25 - 2 ** 39) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[19] - assert bitwise_ptr[0].y = d4 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xff00000000000000ff00000000000000ff00000000000000 - tempvar b13 = 2 ** 8 * x + (1 / 2 ** 56 - 2 ** 8) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = values[24] - assert bitwise_ptr[0].y = d4 - tempvar x = bitwise_ptr[0].x_xor_y - assert bitwise_ptr[1].x = x - assert bitwise_ptr[1].y = 0xfffc000000000000fffc000000000000fffc000000000000 - tempvar b4 = 2 ** 14 * x + (1 / 2 ** 50 - 2 ** 14) * bitwise_ptr[1].x_and_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - ############################################################################################## - # Compute: a[y][x] = [[a[y][x] ^ ((~a[y][(x + 1) % 5]) & a[y][(x + 2) % 5]) # - ############################################################################################## - - let (local output : felt*) = alloc() - - assert bitwise_ptr[0].x = ALL_ONES - b1 - assert bitwise_ptr[0].y = b2 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b0 - assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y - assert bitwise_ptr[2].y = rc - assert output[0] = bitwise_ptr[2].x_xor_y - let bitwise_ptr = bitwise_ptr + 3 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b6 - assert bitwise_ptr[0].y = b7 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b5 - assert output[5] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b11 - assert bitwise_ptr[0].y = b12 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b10 - assert output[10] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b16 - assert bitwise_ptr[0].y = b17 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b15 - assert output[15] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b21 - assert bitwise_ptr[0].y = b22 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b20 - assert output[20] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b2 - assert bitwise_ptr[0].y = b3 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b1 - assert output[1] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b7 - assert bitwise_ptr[0].y = b8 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b6 - assert output[6] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b12 - assert bitwise_ptr[0].y = b13 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b11 - assert output[11] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b17 - assert bitwise_ptr[0].y = b18 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b16 - assert output[16] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b22 - assert bitwise_ptr[0].y = b23 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b21 - assert output[21] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b3 - assert bitwise_ptr[0].y = b4 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b2 - assert output[2] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b8 - assert bitwise_ptr[0].y = b9 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b7 - assert output[7] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b13 - assert bitwise_ptr[0].y = b14 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b12 - assert output[12] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b18 - assert bitwise_ptr[0].y = b19 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b17 - assert output[17] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b23 - assert bitwise_ptr[0].y = b24 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b22 - assert output[22] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b4 - assert bitwise_ptr[0].y = b0 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b3 - assert output[3] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b9 - assert bitwise_ptr[0].y = b5 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b8 - assert output[8] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b14 - assert bitwise_ptr[0].y = b10 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b13 - assert output[13] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b19 - assert bitwise_ptr[0].y = b15 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b18 - assert output[18] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b24 - assert bitwise_ptr[0].y = b20 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b23 - assert output[23] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b0 - assert bitwise_ptr[0].y = b1 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b4 - assert output[4] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b5 - assert bitwise_ptr[0].y = b6 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b9 - assert output[9] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b10 - assert bitwise_ptr[0].y = b11 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b14 - assert output[14] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b15 - assert bitwise_ptr[0].y = b16 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b19 - assert output[19] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - assert bitwise_ptr[0].x = ALL_ONES - b20 - assert bitwise_ptr[0].y = b21 - assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y - assert bitwise_ptr[1].y = b24 - assert output[24] = bitwise_ptr[1].x_xor_y - let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE - - return (output) -end - -func packed_keccak_func{bitwise_ptr : BitwiseBuiltin*}(values : felt*) -> (values : felt*): - let (values) = keccak_round(values, 0x0000000000000001 * SHIFTS) - let (values) = keccak_round(values, 0x0000000000008082 * SHIFTS) - let (values) = keccak_round(values, 0x800000000000808A * SHIFTS) - let (values) = keccak_round(values, 0x8000000080008000 * SHIFTS) - let (values) = keccak_round(values, 0x000000000000808B * SHIFTS) - let (values) = keccak_round(values, 0x0000000080000001 * SHIFTS) - let (values) = keccak_round(values, 0x8000000080008081 * SHIFTS) - let (values) = keccak_round(values, 0x8000000000008009 * SHIFTS) - let (values) = keccak_round(values, 0x000000000000008A * SHIFTS) - let (values) = keccak_round(values, 0x0000000000000088 * SHIFTS) - let (values) = keccak_round(values, 0x0000000080008009 * SHIFTS) - let (values) = keccak_round(values, 0x000000008000000A * SHIFTS) - let (values) = keccak_round(values, 0x000000008000808B * SHIFTS) - let (values) = keccak_round(values, 0x800000000000008B * SHIFTS) - let (values) = keccak_round(values, 0x8000000000008089 * SHIFTS) - let (values) = keccak_round(values, 0x8000000000008003 * SHIFTS) - let (values) = keccak_round(values, 0x8000000000008002 * SHIFTS) - let (values) = keccak_round(values, 0x8000000000000080 * SHIFTS) - let (values) = keccak_round(values, 0x000000000000800A * SHIFTS) - let (values) = keccak_round(values, 0x800000008000000A * SHIFTS) - let (values) = keccak_round(values, 0x8000000080008081 * SHIFTS) - let (values) = keccak_round(values, 0x8000000000008080 * SHIFTS) - let (values) = keccak_round(values, 0x0000000080000001 * SHIFTS) - let (values) = keccak_round(values, 0x8000000080008008 * SHIFTS) - - return (values) -end +const ALL_ONES = 2 ** 251 - 1; +const BLOCK_SIZE = 3; +const SHIFTS = 1 + 2 ** 64 + 2 ** 128; + +func keccak_round{bitwise_ptr: BitwiseBuiltin*}(values: felt*, rc: felt) -> (values_b: felt*) { + ap += SIZEOF_LOCALS; + + // ***************************************************************************************. + // Compute: c[x] = a[0][x] ^ a[1][x] ^ a[2][x] ^ a[3][x] ^ a[4][x]. . + // ***************************************************************************************. + + let values_start = values; + + assert bitwise_ptr[0].x = values[0]; + assert bitwise_ptr[0].y = values[5]; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].y = values[10]; + assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y; + assert bitwise_ptr[2].y = values[15]; + assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y; + assert bitwise_ptr[3].y = values[20]; + tempvar c0 = bitwise_ptr[3].x_xor_y; + let values = values + 1; + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[0]; + assert bitwise_ptr[0].y = values[5]; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].y = values[10]; + assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y; + assert bitwise_ptr[2].y = values[15]; + assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y; + assert bitwise_ptr[3].y = values[20]; + tempvar c1 = bitwise_ptr[3].x_xor_y; + let values = values + 1; + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[0]; + assert bitwise_ptr[0].y = values[5]; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].y = values[10]; + assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y; + assert bitwise_ptr[2].y = values[15]; + assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y; + assert bitwise_ptr[3].y = values[20]; + tempvar c2 = bitwise_ptr[3].x_xor_y; + let values = values + 1; + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[0]; + assert bitwise_ptr[0].y = values[5]; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].y = values[10]; + assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y; + assert bitwise_ptr[2].y = values[15]; + assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y; + assert bitwise_ptr[3].y = values[20]; + tempvar c3 = bitwise_ptr[3].x_xor_y; + let values = values + 1; + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[0]; + assert bitwise_ptr[0].y = values[5]; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].y = values[10]; + assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y; + assert bitwise_ptr[2].y = values[15]; + assert bitwise_ptr[3].x = bitwise_ptr[2].x_xor_y; + assert bitwise_ptr[3].y = values[20]; + tempvar c4 = bitwise_ptr[3].x_xor_y; + let values = values + 1; + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; + + // ***************************************************************************************. + // Compute: d[x] = c[(x - 1) % 5] ^ rot_left(c[(x + 1) % 5], 1). . + // ***************************************************************************************. + + // Saving constants as local variables is more efficient in some instructions. + local mask = 0x800000000000000080000000000000008000000000000000; + + let x = c1; + let y = c4; + assert bitwise_ptr[0].x = x; + assert bitwise_ptr[0].y = mask; + tempvar x0 = bitwise_ptr[0].x_and_y; + let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0; + assert bitwise_ptr[1].x = rotx; + assert bitwise_ptr[1].y = y; + tempvar d0 = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + let x = c2; + let y = c0; + assert bitwise_ptr[0].x = x; + assert bitwise_ptr[0].y = mask; + tempvar x0 = bitwise_ptr[0].x_and_y; + let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0; + assert bitwise_ptr[1].x = rotx; + assert bitwise_ptr[1].y = y; + tempvar d1 = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + let x = c3; + let y = c1; + assert bitwise_ptr[0].x = x; + assert bitwise_ptr[0].y = mask; + tempvar x0 = bitwise_ptr[0].x_and_y; + let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0; + assert bitwise_ptr[1].x = rotx; + assert bitwise_ptr[1].y = y; + tempvar d2 = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + let x = c4; + let y = c2; + assert bitwise_ptr[0].x = x; + assert bitwise_ptr[0].y = mask; + tempvar x0 = bitwise_ptr[0].x_and_y; + let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0; + assert bitwise_ptr[1].x = rotx; + assert bitwise_ptr[1].y = y; + tempvar d3 = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + let x = c0; + let y = c3; + assert bitwise_ptr[0].x = x; + assert bitwise_ptr[0].y = mask; + tempvar x0 = bitwise_ptr[0].x_and_y; + let rotx = 2 * x + (1 / 2 ** 63 - 2) * x0; + assert bitwise_ptr[1].x = rotx; + assert bitwise_ptr[1].y = y; + tempvar d4 = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + // ***************************************************************************************. + // Compute: b[(2 * x + 3 * y) % 5][y] = rot_left([a[y][x] ^ d[x], OFFSETS[x][y]) . + // ***************************************************************************************. + + let values = values_start; + + assert bitwise_ptr[0].x = values[0]; + assert bitwise_ptr[0].y = d0; + tempvar b0 = bitwise_ptr[0].x_xor_y; + let bitwise_ptr = bitwise_ptr + 1 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[5]; + assert bitwise_ptr[0].y = d0; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffffffff0000000fffffffff0000000fffffffff0000000; + tempvar b16 = 2 ** 36 * x + (1 / 2 ** 28 - 2 ** 36) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[10]; + assert bitwise_ptr[0].y = d0; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xe000000000000000e000000000000000e000000000000000; + tempvar b7 = 2 ** 3 * x + (1 / 2 ** 61 - 2 ** 3) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[15]; + assert bitwise_ptr[0].y = d0; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xffffffffff800000ffffffffff800000ffffffffff800000; + tempvar b23 = 2 ** 41 * x + (1 / 2 ** 23 - 2 ** 41) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[20]; + assert bitwise_ptr[0].y = d0; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xffffc00000000000ffffc00000000000ffffc00000000000; + tempvar b14 = 2 ** 18 * x + (1 / 2 ** 46 - 2 ** 18) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[1]; + assert bitwise_ptr[0].y = d1; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0x800000000000000080000000000000008000000000000000; + tempvar b10 = 2 ** 1 * x + (1 / 2 ** 63 - 2 ** 1) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[6]; + assert bitwise_ptr[0].y = d1; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffffffffff00000fffffffffff00000fffffffffff00000; + tempvar b1 = 2 ** 44 * x + (1 / 2 ** 20 - 2 ** 44) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[11]; + assert bitwise_ptr[0].y = d1; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xffc0000000000000ffc0000000000000ffc0000000000000; + tempvar b17 = 2 ** 10 * x + (1 / 2 ** 54 - 2 ** 10) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[16]; + assert bitwise_ptr[0].y = d1; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffffffffff80000fffffffffff80000fffffffffff80000; + tempvar b8 = 2 ** 45 * x + (1 / 2 ** 19 - 2 ** 45) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[21]; + assert bitwise_ptr[0].y = d1; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xc000000000000000c000000000000000c000000000000000; + tempvar b24 = 2 ** 2 * x + (1 / 2 ** 62 - 2 ** 2) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[2]; + assert bitwise_ptr[0].y = d2; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffffffffffffffcfffffffffffffffcfffffffffffffffc; + tempvar b20 = 2 ** 62 * x + (1 / 2 ** 2 - 2 ** 62) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[7]; + assert bitwise_ptr[0].y = d2; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfc00000000000000fc00000000000000fc00000000000000; + tempvar b11 = 2 ** 6 * x + (1 / 2 ** 58 - 2 ** 6) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[12]; + assert bitwise_ptr[0].y = d2; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xffffffffffe00000ffffffffffe00000ffffffffffe00000; + tempvar b2 = 2 ** 43 * x + (1 / 2 ** 21 - 2 ** 43) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[17]; + assert bitwise_ptr[0].y = d2; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffe000000000000fffe000000000000fffe000000000000; + tempvar b18 = 2 ** 15 * x + (1 / 2 ** 49 - 2 ** 15) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[22]; + assert bitwise_ptr[0].y = d2; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffffffffffffff8fffffffffffffff8fffffffffffffff8; + tempvar b9 = 2 ** 61 * x + (1 / 2 ** 3 - 2 ** 61) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[3]; + assert bitwise_ptr[0].y = d3; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffffff000000000fffffff000000000fffffff000000000; + tempvar b5 = 2 ** 28 * x + (1 / 2 ** 36 - 2 ** 28) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[8]; + assert bitwise_ptr[0].y = d3; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffffffffffffe00fffffffffffffe00fffffffffffffe00; + tempvar b21 = 2 ** 55 * x + (1 / 2 ** 9 - 2 ** 55) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[13]; + assert bitwise_ptr[0].y = d3; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xffffff8000000000ffffff8000000000ffffff8000000000; + tempvar b12 = 2 ** 25 * x + (1 / 2 ** 39 - 2 ** 25) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[18]; + assert bitwise_ptr[0].y = d3; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffff80000000000fffff80000000000fffff80000000000; + tempvar b3 = 2 ** 21 * x + (1 / 2 ** 43 - 2 ** 21) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[23]; + assert bitwise_ptr[0].y = d3; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xffffffffffffff00ffffffffffffff00ffffffffffffff00; + tempvar b19 = 2 ** 56 * x + (1 / 2 ** 8 - 2 ** 56) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[4]; + assert bitwise_ptr[0].y = d4; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xffffffe000000000ffffffe000000000ffffffe000000000; + tempvar b15 = 2 ** 27 * x + (1 / 2 ** 37 - 2 ** 27) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[9]; + assert bitwise_ptr[0].y = d4; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffff00000000000fffff00000000000fffff00000000000; + tempvar b6 = 2 ** 20 * x + (1 / 2 ** 44 - 2 ** 20) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[14]; + assert bitwise_ptr[0].y = d4; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffffffffe000000fffffffffe000000fffffffffe000000; + tempvar b22 = 2 ** 39 * x + (1 / 2 ** 25 - 2 ** 39) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[19]; + assert bitwise_ptr[0].y = d4; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xff00000000000000ff00000000000000ff00000000000000; + tempvar b13 = 2 ** 8 * x + (1 / 2 ** 56 - 2 ** 8) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = values[24]; + assert bitwise_ptr[0].y = d4; + tempvar x = bitwise_ptr[0].x_xor_y; + assert bitwise_ptr[1].x = x; + assert bitwise_ptr[1].y = 0xfffc000000000000fffc000000000000fffc000000000000; + tempvar b4 = 2 ** 14 * x + (1 / 2 ** 50 - 2 ** 14) * bitwise_ptr[1].x_and_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + // ***************************************************************************************. + // Compute: a[y][x] = [[a[y][x] ^ ((~a[y][(x + 1) % 5]) & a[y][(x + 2) % 5]) . + // ***************************************************************************************. + + let (local output: felt*) = alloc(); + + assert bitwise_ptr[0].x = ALL_ONES - b1; + assert bitwise_ptr[0].y = b2; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b0; + assert bitwise_ptr[2].x = bitwise_ptr[1].x_xor_y; + assert bitwise_ptr[2].y = rc; + assert output[0] = bitwise_ptr[2].x_xor_y; + let bitwise_ptr = bitwise_ptr + 3 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b6; + assert bitwise_ptr[0].y = b7; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b5; + assert output[5] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b11; + assert bitwise_ptr[0].y = b12; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b10; + assert output[10] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b16; + assert bitwise_ptr[0].y = b17; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b15; + assert output[15] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b21; + assert bitwise_ptr[0].y = b22; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b20; + assert output[20] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b2; + assert bitwise_ptr[0].y = b3; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b1; + assert output[1] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b7; + assert bitwise_ptr[0].y = b8; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b6; + assert output[6] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b12; + assert bitwise_ptr[0].y = b13; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b11; + assert output[11] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b17; + assert bitwise_ptr[0].y = b18; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b16; + assert output[16] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b22; + assert bitwise_ptr[0].y = b23; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b21; + assert output[21] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b3; + assert bitwise_ptr[0].y = b4; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b2; + assert output[2] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b8; + assert bitwise_ptr[0].y = b9; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b7; + assert output[7] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b13; + assert bitwise_ptr[0].y = b14; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b12; + assert output[12] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b18; + assert bitwise_ptr[0].y = b19; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b17; + assert output[17] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b23; + assert bitwise_ptr[0].y = b24; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b22; + assert output[22] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b4; + assert bitwise_ptr[0].y = b0; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b3; + assert output[3] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b9; + assert bitwise_ptr[0].y = b5; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b8; + assert output[8] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b14; + assert bitwise_ptr[0].y = b10; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b13; + assert output[13] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b19; + assert bitwise_ptr[0].y = b15; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b18; + assert output[18] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b24; + assert bitwise_ptr[0].y = b20; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b23; + assert output[23] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b0; + assert bitwise_ptr[0].y = b1; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b4; + assert output[4] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b5; + assert bitwise_ptr[0].y = b6; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b9; + assert output[9] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b10; + assert bitwise_ptr[0].y = b11; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b14; + assert output[14] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b15; + assert bitwise_ptr[0].y = b16; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b19; + assert output[19] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + assert bitwise_ptr[0].x = ALL_ONES - b20; + assert bitwise_ptr[0].y = b21; + assert bitwise_ptr[1].x = bitwise_ptr[0].x_and_y; + assert bitwise_ptr[1].y = b24; + assert output[24] = bitwise_ptr[1].x_xor_y; + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + + return (values_b=output); +} + +func packed_keccak_func{bitwise_ptr: BitwiseBuiltin*}(values: felt*) -> (values: felt*) { + let (values) = keccak_round(values, 0x0000000000000001 * SHIFTS); + let (values) = keccak_round(values, 0x0000000000008082 * SHIFTS); + let (values) = keccak_round(values, 0x800000000000808A * SHIFTS); + let (values) = keccak_round(values, 0x8000000080008000 * SHIFTS); + let (values) = keccak_round(values, 0x000000000000808B * SHIFTS); + let (values) = keccak_round(values, 0x0000000080000001 * SHIFTS); + let (values) = keccak_round(values, 0x8000000080008081 * SHIFTS); + let (values) = keccak_round(values, 0x8000000000008009 * SHIFTS); + let (values) = keccak_round(values, 0x000000000000008A * SHIFTS); + let (values) = keccak_round(values, 0x0000000000000088 * SHIFTS); + let (values) = keccak_round(values, 0x0000000080008009 * SHIFTS); + let (values) = keccak_round(values, 0x000000008000000A * SHIFTS); + let (values) = keccak_round(values, 0x000000008000808B * SHIFTS); + let (values) = keccak_round(values, 0x800000000000008B * SHIFTS); + let (values) = keccak_round(values, 0x8000000000008089 * SHIFTS); + let (values) = keccak_round(values, 0x8000000000008003 * SHIFTS); + let (values) = keccak_round(values, 0x8000000000008002 * SHIFTS); + let (values) = keccak_round(values, 0x8000000000000080 * SHIFTS); + let (values) = keccak_round(values, 0x000000000000800A * SHIFTS); + let (values) = keccak_round(values, 0x800000008000000A * SHIFTS); + let (values) = keccak_round(values, 0x8000000080008081 * SHIFTS); + let (values) = keccak_round(values, 0x8000000000008080 * SHIFTS); + let (values) = keccak_round(values, 0x0000000080000001 * SHIFTS); + let (values) = keccak_round(values, 0x8000000080008008 * SHIFTS); + + return (values=values); +} diff --git a/src/starkware/cairo/common/cairo_secp/bigint.cairo b/src/starkware/cairo/common/cairo_secp/bigint.cairo index af0ac1a3..603575c4 100644 --- a/src/starkware/cairo/common/cairo_secp/bigint.cairo +++ b/src/starkware/cairo/common/cairo_secp/bigint.cairo @@ -3,45 +3,45 @@ from starkware.cairo.common.math import assert_nn, assert_nn_le, unsigned_div_re from starkware.cairo.common.math_cmp import RC_BOUND from starkware.cairo.common.uint256 import Uint256 -# Represents a big integer defined by: -# d0 + BASE * d1 + BASE**2 * d2. -# Note that the limbs (d_i) are NOT restricted to the range [0, BASE) and in particular they -# can be negative. -# In most cases this is used to represent a secp256k1 field element. -struct UnreducedBigInt3: - member d0 : felt - member d1 : felt - member d2 : felt -end +// Represents a big integer defined by: +// d0 + BASE * d1 + BASE**2 * d2. +// Note that the limbs (d_i) are NOT restricted to the range [0, BASE) and in particular they +// can be negative. +// In most cases this is used to represent a secp256k1 field element. +struct UnreducedBigInt3 { + d0: felt, + d1: felt, + d2: felt, +} -# Same as UnreducedBigInt3, except that d0, d1 and d2 must be in the range [0, 3 * BASE). -# In most cases this is used to represent a secp256k1 field element. -struct BigInt3: - member d0 : felt - member d1 : felt - member d2 : felt -end +// Same as UnreducedBigInt3, except that d0, d1 and d2 must be in the range [0, 3 * BASE). +// In most cases this is used to represent a secp256k1 field element. +struct BigInt3 { + d0: felt, + d1: felt, + d2: felt, +} -# Represents a big integer defined by: -# sum_i(BASE**i * d_i). -# Note that the limbs (d_i) are NOT restricted to the range [0, BASE) and in particular they -# can be negative. -struct UnreducedBigInt5: - member d0 : felt - member d1 : felt - member d2 : felt - member d3 : felt - member d4 : felt -end +// Represents a big integer defined by: +// sum_i(BASE**i * d_i). +// Note that the limbs (d_i) are NOT restricted to the range [0, BASE) and in particular they +// can be negative. +struct UnreducedBigInt5 { + d0: felt, + d1: felt, + d2: felt, + d3: felt, + d4: felt, +} -# Computes the multiplication of two big integers, given in BigInt3 representation. -# -# Arguments: -# x, y - the two BigInt3 to operate on. -# -# Returns: -# x * y in an UnreducedBigInt5 representation. -func bigint_mul(x : BigInt3, y : BigInt3) -> (res : UnreducedBigInt5): +// Computes the multiplication of two big integers, given in BigInt3 representation. +// +// Arguments: +// x, y - the two BigInt3 to operate on. +// +// Returns: +// x * y in an UnreducedBigInt5 representation. +func bigint_mul(x: BigInt3, y: BigInt3) -> (res: UnreducedBigInt5) { return ( UnreducedBigInt5( d0=x.d0 * y.d0, @@ -49,77 +49,77 @@ func bigint_mul(x : BigInt3, y : BigInt3) -> (res : UnreducedBigInt5): d2=x.d0 * y.d2 + x.d1 * y.d1 + x.d2 * y.d0, d3=x.d1 * y.d2 + x.d2 * y.d1, d4=x.d2 * y.d2), - ) -end + ); +} -# Returns a BigInt3 instance whose value is controlled by a prover hint. -# -# Soundness guarantee: each limb is in the range [0, 3 * BASE). -# Completeness guarantee (honest prover): the value is in reduced form and in particular, -# each limb is in the range [0, BASE). -# -# Implicit arguments: -# range_check_ptr - range check builtin pointer. -# -# Hint arguments: value. -func nondet_bigint3{range_check_ptr}() -> (res : BigInt3): - # The result should be at the end of the stack after the function returns. - let res : BigInt3 = [cast(ap + 5, BigInt3*)] +// Returns a BigInt3 instance whose value is controlled by a prover hint. +// +// Soundness guarantee: each limb is in the range [0, 3 * BASE). +// Completeness guarantee (honest prover): the value is in reduced form and in particular, +// each limb is in the range [0, BASE). +// +// Implicit arguments: +// range_check_ptr - range check builtin pointer. +// +// Hint arguments: value. +func nondet_bigint3{range_check_ptr}() -> (res: BigInt3) { + // The result should be at the end of the stack after the function returns. + let res: BigInt3 = [cast(ap + 5, BigInt3*)]; %{ from starkware.cairo.common.cairo_secp.secp_utils import split segments.write_arg(ids.res.address_, split(value)) %} - # The maximal possible sum of the limbs, assuming each of them is in the range [0, BASE). - const MAX_SUM = 3 * (BASE - 1) - assert [range_check_ptr] = MAX_SUM - (res.d0 + res.d1 + res.d2) + // The maximal possible sum of the limbs, assuming each of them is in the range [0, BASE). + const MAX_SUM = 3 * (BASE - 1); + assert [range_check_ptr] = MAX_SUM - (res.d0 + res.d1 + res.d2); - # Prepare the result at the end of the stack. - tempvar range_check_ptr = range_check_ptr + 4 - [range_check_ptr - 3] = res.d0; ap++ - [range_check_ptr - 2] = res.d1; ap++ - [range_check_ptr - 1] = res.d2; ap++ - static_assert &res + BigInt3.SIZE == ap - return (res=res) -end + // Prepare the result at the end of the stack. + tempvar range_check_ptr = range_check_ptr + 4; + [range_check_ptr - 3] = res.d0, ap++; + [range_check_ptr - 2] = res.d1, ap++; + [range_check_ptr - 1] = res.d2, ap++; + static_assert &res + BigInt3.SIZE == ap; + return (res=res); +} -# Converts a BigInt3 instance into a Uint256. -# -# Assumptions: -# * The limbs of x are in the range [0, BASE * 3). -# * x is in the range [0, 2 ** 256). -# * PRIME is at least 174 bits. -# Implicit arguments: -# range_check_ptr - range check builtin pointer. -func bigint_to_uint256{range_check_ptr}(x : BigInt3) -> (res : Uint256): - let low = [range_check_ptr] - let high = [range_check_ptr + 1] - let range_check_ptr = range_check_ptr + 2 +// Converts a BigInt3 instance into a Uint256. +// +// Assumptions: +// * The limbs of x are in the range [0, BASE * 3). +// * x is in the range [0, 2 ** 256). +// * PRIME is at least 174 bits. +// Implicit arguments: +// range_check_ptr - range check builtin pointer. +func bigint_to_uint256{range_check_ptr}(x: BigInt3) -> (res: Uint256) { + let low = [range_check_ptr]; + let high = [range_check_ptr + 1]; + let range_check_ptr = range_check_ptr + 2; %{ ids.low = (ids.x.d0 + ids.x.d1 * ids.BASE) & ((1 << 128) - 1) %} - # Because PRIME is at least 174 bits, the numerator doesn't overflow. - tempvar a = ((x.d0 + x.d1 * BASE) - low) / RC_BOUND - const D2_SHIFT = BASE * BASE / RC_BOUND - const A_BOUND = 4 * D2_SHIFT - # We'll check that the division in `a` doesn't cause an overflow. This means that the 128 LSB - # of (x.d0 + x.d1 * BASE) and low are identical, which ensures that low is correct. - assert_nn_le(a, A_BOUND - 1) - # high * RC_BOUND = a * RC_BOUND + x.d2 * BASE ** 2 = - # = x.d0 + x.d1 * BASE + x.d2 * BASE ** 2 - low = num - low. - with_attr error_message("x out of range"): - assert high = a + x.d2 * D2_SHIFT - end + // Because PRIME is at least 174 bits, the numerator doesn't overflow. + tempvar a = ((x.d0 + x.d1 * BASE) - low) / RC_BOUND; + const D2_SHIFT = BASE * BASE / RC_BOUND; + const A_BOUND = 4 * D2_SHIFT; + // We'll check that the division in `a` doesn't cause an overflow. This means that the 128 LSB + // of (x.d0 + x.d1 * BASE) and low are identical, which ensures that low is correct. + assert_nn_le(a, A_BOUND - 1); + // high * RC_BOUND = a * RC_BOUND + x.d2 * BASE ** 2 = + // = x.d0 + x.d1 * BASE + x.d2 * BASE ** 2 - low = num - low. + with_attr error_message("x out of range") { + assert high = a + x.d2 * D2_SHIFT; + } - return (res=Uint256(low=low, high=high)) -end + return (res=Uint256(low=low, high=high)); +} -# Converts a Uint256 instance into a BigInt3. -# Assuming x is a valid Uint256 (its two limbs are below 2 ** 128), the resulting number will have -# limbs in the range [0, BASE). -func uint256_to_bigint{range_check_ptr}(x : Uint256) -> (res : BigInt3): - const D1_HIGH_BOUND = BASE ** 2 / RC_BOUND - const D1_LOW_BOUND = RC_BOUND / BASE - let (d1_low, d0) = unsigned_div_rem(x.low, BASE) - let (d2, d1_high) = unsigned_div_rem(x.high, D1_HIGH_BOUND) - let d1 = d1_high * D1_LOW_BOUND + d1_low - return (BigInt3(d0=d0, d1=d1, d2=d2)) -end +// Converts a Uint256 instance into a BigInt3. +// Assuming x is a valid Uint256 (its two limbs are below 2 ** 128), the resulting number will have +// limbs in the range [0, BASE). +func uint256_to_bigint{range_check_ptr}(x: Uint256) -> (res: BigInt3) { + const D1_HIGH_BOUND = BASE ** 2 / RC_BOUND; + const D1_LOW_BOUND = RC_BOUND / BASE; + let (d1_low, d0) = unsigned_div_rem(x.low, BASE); + let (d2, d1_high) = unsigned_div_rem(x.high, D1_HIGH_BOUND); + let d1 = d1_high * D1_LOW_BOUND + d1_low; + return (res=BigInt3(d0=d0, d1=d1, d2=d2)); +} diff --git a/src/starkware/cairo/common/cairo_secp/constants.cairo b/src/starkware/cairo/common/cairo_secp/constants.cairo index 113f9cc5..7316c852 100644 --- a/src/starkware/cairo/common/cairo_secp/constants.cairo +++ b/src/starkware/cairo/common/cairo_secp/constants.cairo @@ -1,21 +1,28 @@ -# Basic definitions for the secp256k1 elliptic curve. -# The curve is given by the equation: -# y^2 = x^3 + 7 -# over the field Z/p for -# p = secp256k1_prime = 2 ** 256 - (2 ** 32 + 2 ** 9 + 2 ** 8 + 2 ** 7 + 2 ** 6 + 2 ** 4 + 1). -# The size of the curve is -# n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 (prime). +// Basic definitions for the secp256k1 elliptic curve. +// The curve is given by the equation: +// y^2 = x^3 + 7 +// over the field Z/p for +// p = secp256k1_prime = 2 ** 256 - (2 ** 32 + 2 ** 9 + 2 ** 8 + 2 ** 7 + 2 ** 6 + 2 ** 4 + 1). +// The size of the curve is +// n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 (prime). -# SECP_REM is defined by the equation: -# secp256k1_prime = 2 ** 256 - SECP_REM. -const SECP_REM = 2 ** 32 + 2 ** 9 + 2 ** 8 + 2 ** 7 + 2 ** 6 + 2 ** 4 + 1 +// SECP_REM is defined by the equation: +// secp256k1_prime = 2 ** 256 - SECP_REM. +const SECP_REM = 2 ** 32 + 2 ** 9 + 2 ** 8 + 2 ** 7 + 2 ** 6 + 2 ** 4 + 1; -# The following constants represent the size of the secp256k1 curve: -# n = N0 + BASE * N1 + BASE**2 * N2. -const BASE = 2 ** 86 -const N0 = 0x8a03bbfd25e8cd0364141 -const N1 = 0x3ffffffffffaeabb739abd -const N2 = 0xfffffffffffffffffffff +const BASE = 2 ** 86; -# BETA is the free term in the curve equation. -const BETA = 7 +// The following constants represent the size of the secp256k1 field: +// p = P0 + BASE * P1 + BASE**2 * P2. +const P0 = 0x3ffffffffffffefffffc2f; +const P1 = 0x3fffffffffffffffffffff; +const P2 = 0xfffffffffffffffffffff; + +// The following constants represent the size of the secp256k1 curve: +// n = N0 + BASE * N1 + BASE**2 * N2. +const N0 = 0x8a03bbfd25e8cd0364141; +const N1 = 0x3ffffffffffaeabb739abd; +const N2 = 0xfffffffffffffffffffff; + +// BETA is the free term in the curve equation. +const BETA = 7; diff --git a/src/starkware/cairo/common/cairo_secp/ec.cairo b/src/starkware/cairo/common/cairo_secp/ec.cairo index 5c0a5c5e..9c7cd58b 100644 --- a/src/starkware/cairo/common/cairo_secp/ec.cairo +++ b/src/starkware/cairo/common/cairo_secp/ec.cairo @@ -6,23 +6,23 @@ from starkware.cairo.common.cairo_secp.field import ( verify_zero, ) -# Represents a point on the secp256k1 elliptic curve. -# The zero point is represented as a point with x = 0 (there is no point on the curve with a zero -# x value). -struct EcPoint: - member x : BigInt3 - member y : BigInt3 -end - -# Computes the negation of a point on the elliptic curve, which is a point with the same x value and -# the negation of the y value. If the point is the zero point, returns the zero point. -# -# Arguments: -# point - The point to operate on. -# -# Returns: -# point - The negation of the given point. -func ec_negate{range_check_ptr}(point : EcPoint) -> (point : EcPoint): +// Represents a point on the secp256k1 elliptic curve. +// The zero point is represented as a point with x = 0 (there is no point on the curve with a zero +// x value). +struct EcPoint { + x: BigInt3, + y: BigInt3, +} + +// Computes the negation of a point on the elliptic curve, which is a point with the same x value +// and the negation of the y value. If the point is the zero point, returns the zero point. +// +// Arguments: +// point - The point to operate on. +// +// Returns: +// point - The negation of the given point. +func ec_negate{range_check_ptr}(point: EcPoint) -> (point: EcPoint) { %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack @@ -30,30 +30,30 @@ func ec_negate{range_check_ptr}(point : EcPoint) -> (point : EcPoint): # The modulo operation in python always returns a nonnegative number. value = (-y) % SECP_P %} - let (minus_y) = nondet_bigint3() + let (minus_y) = nondet_bigint3(); verify_zero( UnreducedBigInt3( d0=minus_y.d0 + point.y.d0, d1=minus_y.d1 + point.y.d1, d2=minus_y.d2 + point.y.d2), - ) - - return (point=EcPoint(x=point.x, y=minus_y)) -end - -# Computes the slope of the elliptic curve at a given point. -# The slope is used to compute point + point. -# -# Arguments: -# point - the point to operate on. -# -# Returns: -# slope - the slope of the curve at point, in BigInt3 representation. -# -# Assumption: point != 0. -func compute_doubling_slope{range_check_ptr}(point : EcPoint) -> (slope : BigInt3): - # Note that y cannot be zero: assume that it is, then point = -point, so 2 * point = 0, which - # contradicts the fact that the size of the curve is odd. + ); + + return (point=EcPoint(x=point.x, y=minus_y)); +} + +// Computes the slope of the elliptic curve at a given point. +// The slope is used to compute point + point. +// +// Arguments: +// point - the point to operate on. +// +// Returns: +// slope - the slope of the curve at point, in BigInt3 representation. +// +// Assumption: point != 0. +func compute_doubling_slope{range_check_ptr}(point: EcPoint) -> (slope: BigInt3) { + // Note that y cannot be zero: assume that it is, then point = -point, so 2 * point = 0, which + // contradicts the fact that the size of the curve is odd. %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack from starkware.python.math_utils import ec_double_slope @@ -63,34 +63,34 @@ func compute_doubling_slope{range_check_ptr}(point : EcPoint) -> (slope : BigInt y = pack(ids.point.y, PRIME) value = slope = ec_double_slope(point=(x, y), alpha=0, p=SECP_P) %} - let (slope : BigInt3) = nondet_bigint3() + let (slope: BigInt3) = nondet_bigint3(); - let (x_sqr : UnreducedBigInt3) = unreduced_sqr(point.x) - let (slope_y : UnreducedBigInt3) = unreduced_mul(slope, point.y) + let (x_sqr: UnreducedBigInt3) = unreduced_sqr(point.x); + let (slope_y: UnreducedBigInt3) = unreduced_mul(slope, point.y); verify_zero( UnreducedBigInt3( d0=3 * x_sqr.d0 - 2 * slope_y.d0, d1=3 * x_sqr.d1 - 2 * slope_y.d1, d2=3 * x_sqr.d2 - 2 * slope_y.d2), - ) - - return (slope=slope) -end - -# Computes the slope of the line connecting the two given points. -# The slope is used to compute point0 + point1. -# -# Arguments: -# point0, point1 - the points to operate on. -# -# Returns: -# slope - the slope of the line connecting point0 and point1, in BigInt3 representation. -# -# Assumptions: -# * point0.x != point1.x (mod secp256k1_prime). -# * point0, point1 != 0. -func compute_slope{range_check_ptr}(point0 : EcPoint, point1 : EcPoint) -> (slope : BigInt3): + ); + + return (slope=slope); +} + +// Computes the slope of the line connecting the two given points. +// The slope is used to compute point0 + point1. +// +// Arguments: +// point0, point1 - the points to operate on. +// +// Returns: +// slope - the slope of the line connecting point0 and point1, in BigInt3 representation. +// +// Assumptions: +// * point0.x != point1.x (mod secp256k1_prime). +// * point0, point1 != 0. +func compute_slope{range_check_ptr}(point0: EcPoint, point1: EcPoint) -> (slope: BigInt3) { %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack from starkware.python.math_utils import line_slope @@ -102,42 +102,42 @@ func compute_slope{range_check_ptr}(point0 : EcPoint, point1 : EcPoint) -> (slop y1 = pack(ids.point1.y, PRIME) value = slope = line_slope(point1=(x0, y0), point2=(x1, y1), p=SECP_P) %} - let (slope) = nondet_bigint3() + let (slope) = nondet_bigint3(); let x_diff = BigInt3( d0=point0.x.d0 - point1.x.d0, d1=point0.x.d1 - point1.x.d1, d2=point0.x.d2 - point1.x.d2 - ) - let (x_diff_slope : UnreducedBigInt3) = unreduced_mul(x_diff, slope) + ); + let (x_diff_slope: UnreducedBigInt3) = unreduced_mul(x_diff, slope); verify_zero( UnreducedBigInt3( d0=x_diff_slope.d0 - point0.y.d0 + point1.y.d0, d1=x_diff_slope.d1 - point0.y.d1 + point1.y.d1, d2=x_diff_slope.d2 - point0.y.d2 + point1.y.d2), - ) - - return (slope) -end - -# Computes the addition of a given point to itself. -# -# Arguments: -# point - the point to operate on. -# -# Returns: -# res - a point representing point + point. -func ec_double{range_check_ptr}(point : EcPoint) -> (res : EcPoint): - # The zero point. - if point.x.d0 == 0: - if point.x.d1 == 0: - if point.x.d2 == 0: - return (point) - end - end - end - - let (slope : BigInt3) = compute_doubling_slope(point) - let (slope_sqr : UnreducedBigInt3) = unreduced_sqr(slope) + ); + + return (slope=slope); +} + +// Computes the addition of a given point to itself. +// +// Arguments: +// point - the point to operate on. +// +// Returns: +// res - a point representing point + point. +func ec_double{range_check_ptr}(point: EcPoint) -> (res: EcPoint) { + // The zero point. + if (point.x.d0 == 0) { + if (point.x.d1 == 0) { + if (point.x.d2 == 0) { + return (res=point); + } + } + } + + let (slope: BigInt3) = compute_doubling_slope(point); + let (slope_sqr: UnreducedBigInt3) = unreduced_sqr(slope); %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack @@ -148,64 +148,64 @@ func ec_double{range_check_ptr}(point : EcPoint) -> (res : EcPoint): value = new_x = (pow(slope, 2, SECP_P) - 2 * x) % SECP_P %} - let (new_x : BigInt3) = nondet_bigint3() + let (new_x: BigInt3) = nondet_bigint3(); %{ value = new_y = (slope * (x - new_x) - y) % SECP_P %} - let (new_y : BigInt3) = nondet_bigint3() + let (new_y: BigInt3) = nondet_bigint3(); verify_zero( UnreducedBigInt3( d0=slope_sqr.d0 - new_x.d0 - 2 * point.x.d0, d1=slope_sqr.d1 - new_x.d1 - 2 * point.x.d1, d2=slope_sqr.d2 - new_x.d2 - 2 * point.x.d2), - ) + ); - let (x_diff_slope : UnreducedBigInt3) = unreduced_mul( + let (x_diff_slope: UnreducedBigInt3) = unreduced_mul( BigInt3(d0=point.x.d0 - new_x.d0, d1=point.x.d1 - new_x.d1, d2=point.x.d2 - new_x.d2), slope - ) + ); verify_zero( UnreducedBigInt3( d0=x_diff_slope.d0 - point.y.d0 - new_y.d0, d1=x_diff_slope.d1 - point.y.d1 - new_y.d1, d2=x_diff_slope.d2 - point.y.d2 - new_y.d2), - ) - - return (res=EcPoint(new_x, new_y)) -end - -# Computes the addition of two given points. -# -# Arguments: -# point0, point1 - the points to operate on. -# -# Returns: -# res - the sum of the two points (point0 + point1). -# -# Assumption: point0.x != point1.x (however, point0 = point1 = 0 is allowed). -# Note that this means that the function cannot be used if point0 = point1 != 0 -# (use ec_double() in this case) or point0 = -point1 != 0 (the result is 0 in this case). -func fast_ec_add{range_check_ptr}(point0 : EcPoint, point1 : EcPoint) -> (res : EcPoint): - # Check whether point0 is the zero point. - if point0.x.d0 == 0: - if point0.x.d1 == 0: - if point0.x.d2 == 0: - return (point1) - end - end - end - - # Check whether point1 is the zero point. - if point1.x.d0 == 0: - if point1.x.d1 == 0: - if point1.x.d2 == 0: - return (point0) - end - end - end - - let (slope : BigInt3) = compute_slope(point0, point1) - let (slope_sqr : UnreducedBigInt3) = unreduced_sqr(slope) + ); + + return (res=EcPoint(new_x, new_y)); +} + +// Computes the addition of two given points. +// +// Arguments: +// point0, point1 - the points to operate on. +// +// Returns: +// res - the sum of the two points (point0 + point1). +// +// Assumption: point0.x != point1.x (however, point0 = point1 = 0 is allowed). +// Note that this means that the function cannot be used if point0 = point1 != 0 +// (use ec_double() in this case) or point0 = -point1 != 0 (the result is 0 in this case). +func fast_ec_add{range_check_ptr}(point0: EcPoint, point1: EcPoint) -> (res: EcPoint) { + // Check whether point0 is the zero point. + if (point0.x.d0 == 0) { + if (point0.x.d1 == 0) { + if (point0.x.d2 == 0) { + return (res=point1); + } + } + } + + // Check whether point1 is the zero point. + if (point1.x.d0 == 0) { + if (point1.x.d1 == 0) { + if (point1.x.d2 == 0) { + return (res=point0); + } + } + } + + let (slope: BigInt3) = compute_slope(point0, point1); + let (slope_sqr: UnreducedBigInt3) = unreduced_sqr(slope); %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack @@ -217,100 +217,100 @@ func fast_ec_add{range_check_ptr}(point0 : EcPoint, point1 : EcPoint) -> (res : value = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P %} - let (new_x : BigInt3) = nondet_bigint3() + let (new_x: BigInt3) = nondet_bigint3(); %{ value = new_y = (slope * (x0 - new_x) - y0) % SECP_P %} - let (new_y : BigInt3) = nondet_bigint3() + let (new_y: BigInt3) = nondet_bigint3(); verify_zero( UnreducedBigInt3( d0=slope_sqr.d0 - new_x.d0 - point0.x.d0 - point1.x.d0, d1=slope_sqr.d1 - new_x.d1 - point0.x.d1 - point1.x.d1, d2=slope_sqr.d2 - new_x.d2 - point0.x.d2 - point1.x.d2), - ) + ); - let (x_diff_slope : UnreducedBigInt3) = unreduced_mul( + let (x_diff_slope: UnreducedBigInt3) = unreduced_mul( BigInt3(d0=point0.x.d0 - new_x.d0, d1=point0.x.d1 - new_x.d1, d2=point0.x.d2 - new_x.d2), slope, - ) + ); verify_zero( UnreducedBigInt3( d0=x_diff_slope.d0 - point0.y.d0 - new_y.d0, d1=x_diff_slope.d1 - point0.y.d1 - new_y.d1, d2=x_diff_slope.d2 - point0.y.d2 - new_y.d2), - ) + ); - return (EcPoint(new_x, new_y)) -end + return (res=EcPoint(new_x, new_y)); +} -# Same as fast_ec_add, except that the cases point0 = +/-point1 are supported. -func ec_add{range_check_ptr}(point0 : EcPoint, point1 : EcPoint) -> (res : EcPoint): +// Same as fast_ec_add, except that the cases point0 = +/-point1 are supported. +func ec_add{range_check_ptr}(point0: EcPoint, point1: EcPoint) -> (res: EcPoint) { let x_diff = BigInt3( d0=point0.x.d0 - point1.x.d0, d1=point0.x.d1 - point1.x.d1, d2=point0.x.d2 - point1.x.d2 - ) - let (same_x : felt) = is_zero(x_diff) - if same_x == 0: - # point0.x != point1.x so we can use fast_ec_add. - return fast_ec_add(point0, point1) - end - - # We have point0.x = point1.x. This implies point0.y = +/-point1.y. - # Check whether point0.y = -point1.y. + ); + let (same_x: felt) = is_zero(x_diff); + if (same_x == 0) { + // point0.x != point1.x so we can use fast_ec_add. + return fast_ec_add(point0, point1); + } + + // We have point0.x = point1.x. This implies point0.y = +/-point1.y. + // Check whether point0.y = -point1.y. let y_sum = BigInt3( d0=point0.y.d0 + point1.y.d0, d1=point0.y.d1 + point1.y.d1, d2=point0.y.d2 + point1.y.d2 - ) - let (opposite_y : felt) = is_zero(y_sum) - if opposite_y != 0: - # point0.y = -point1.y. - # Note that the case point0 = point1 = 0 falls into this branch as well. - let ZERO_POINT = EcPoint(BigInt3(0, 0, 0), BigInt3(0, 0, 0)) - return (ZERO_POINT) - else: - # point0.y = point1.y. - return ec_double(point0) - end -end - -# Given a scalar, an integer m in the range [0, 250), and a point on the elliptic curve, point, -# verifies that 0 <= scalar < 2**m and returns (2**m * point, scalar * point). -func ec_mul_inner{range_check_ptr}(point : EcPoint, scalar : felt, m : felt) -> ( - pow2 : EcPoint, res : EcPoint -): - if m == 0: - with_attr error_message("Too large scalar"): - scalar = 0 - end - let ZERO_POINT = EcPoint(BigInt3(0, 0, 0), BigInt3(0, 0, 0)) - return (pow2=point, res=ZERO_POINT) - end - - alloc_locals - let (double_point : EcPoint) = ec_double(point) + ); + let (opposite_y: felt) = is_zero(y_sum); + if (opposite_y != 0) { + // point0.y = -point1.y. + // Note that the case point0 = point1 = 0 falls into this branch as well. + let ZERO_POINT = EcPoint(BigInt3(0, 0, 0), BigInt3(0, 0, 0)); + return (res=ZERO_POINT); + } else { + // point0.y = point1.y. + return ec_double(point0); + } +} + +// Given a scalar, an integer m in the range [0, 250), and a point on the elliptic curve, point, +// verifies that 0 <= scalar < 2**m and returns (2**m * point, scalar * point). +func ec_mul_inner{range_check_ptr}(point: EcPoint, scalar: felt, m: felt) -> ( + pow2: EcPoint, res: EcPoint +) { + if (m == 0) { + with_attr error_message("Too large scalar") { + scalar = 0; + } + let ZERO_POINT = EcPoint(BigInt3(0, 0, 0), BigInt3(0, 0, 0)); + return (pow2=point, res=ZERO_POINT); + } + + alloc_locals; + let (double_point: EcPoint) = ec_double(point); %{ memory[ap] = (ids.scalar % PRIME) % 2 %} - jmp odd if [ap] != 0; ap++ - return ec_mul_inner(point=double_point, scalar=scalar / 2, m=m - 1) + jmp odd if [ap] != 0, ap++; + return ec_mul_inner(point=double_point, scalar=scalar / 2, m=m - 1); odd: - let (local inner_pow2 : EcPoint, inner_res : EcPoint) = ec_mul_inner( + let (local inner_pow2: EcPoint, inner_res: EcPoint) = ec_mul_inner( point=double_point, scalar=(scalar - 1) / 2, m=m - 1 - ) - # Here inner_res = (scalar - 1) / 2 * double_point = (scalar - 1) * point. - # Assume point != 0 and that inner_res = +/-point. We obtain (scalar - 1) * point = +/-point => - # scalar - 1 = +/-1 (mod N) => scalar = 0 or 2 (mod N). - # By induction, we know that (scalar - 1) / 2 must be in the range [0, 2**(m-1)), - # so scalar is an odd number in the range [0, 2**m), and we get a contradiction. - let (res : EcPoint) = fast_ec_add(point0=point, point1=inner_res) - return (pow2=inner_pow2, res=res) -end - -# Given a point and a 256-bit scalar, returns scalar * point. -func ec_mul{range_check_ptr}(point : EcPoint, scalar : BigInt3) -> (res : EcPoint): - alloc_locals - let (pow2_0 : EcPoint, local res0 : EcPoint) = ec_mul_inner(point, scalar.d0, 86) - let (pow2_1 : EcPoint, local res1 : EcPoint) = ec_mul_inner(pow2_0, scalar.d1, 86) - let (_, local res2 : EcPoint) = ec_mul_inner(pow2_1, scalar.d2, 84) - let (res : EcPoint) = ec_add(res0, res1) - let (res : EcPoint) = ec_add(res, res2) - return (res) -end + ); + // Here inner_res = (scalar - 1) / 2 * double_point = (scalar - 1) * point. + // Assume point != 0 and that inner_res = +/-point. We obtain (scalar - 1) * point = +/-point => + // scalar - 1 = +/-1 (mod N) => scalar = 0 or 2 (mod N). + // By induction, we know that (scalar - 1) / 2 must be in the range [0, 2**(m-1)), + // so scalar is an odd number in the range [0, 2**m), and we get a contradiction. + let (res: EcPoint) = fast_ec_add(point0=point, point1=inner_res); + return (pow2=inner_pow2, res=res); +} + +// Given a point and a 256-bit scalar, returns scalar * point. +func ec_mul{range_check_ptr}(point: EcPoint, scalar: BigInt3) -> (res: EcPoint) { + alloc_locals; + let (pow2_0: EcPoint, local res0: EcPoint) = ec_mul_inner(point, scalar.d0, 86); + let (pow2_1: EcPoint, local res1: EcPoint) = ec_mul_inner(pow2_0, scalar.d1, 86); + let (_, local res2: EcPoint) = ec_mul_inner(pow2_1, scalar.d2, 84); + let (res: EcPoint) = ec_add(res0, res1); + let (res: EcPoint) = ec_add(res, res2); + return (res=res); +} diff --git a/src/starkware/cairo/common/cairo_secp/field.cairo b/src/starkware/cairo/common/cairo_secp/field.cairo index 4b9cb956..64a9758b 100644 --- a/src/starkware/cairo/common/cairo_secp/field.cairo +++ b/src/starkware/cairo/common/cairo_secp/field.cairo @@ -1,58 +1,59 @@ from starkware.cairo.common.cairo_secp.bigint import BigInt3, UnreducedBigInt3, nondet_bigint3 -from starkware.cairo.common.cairo_secp.constants import BASE, SECP_REM - -# Computes the multiplication of two big integers, given in BigInt3 representation, modulo the -# secp256k1 prime. -# -# Arguments: -# x, y - the two BigInt3 to operate on. -# -# Returns: -# x * y in an UnreducedBigInt3 representation (the returned limbs may be above 3 * BASE). -# -# If each of the input limbs is in the range (-x, x), the result's limbs are guaranteed to be -# in the range (-x**2 * (2 ** 35.01), x**2 * (2 ** 35.01)) since log(8 * SECP_REM + 1) < 35.01. -# -# This means that if unreduced_mul is called on the result of nondet_bigint3, or the difference -# between two such results, we have: -# Soundness guarantee: the limbs are in the range (-2**210.18, 2**210.18). -# Completeness guarantee: the limbs are in the range (-2**207.01, 2**207.01). -func unreduced_mul(a : BigInt3, b : BigInt3) -> (res_low : UnreducedBigInt3): - # The result of the product is: - # sum_{i, j} a.d_i * b.d_j * BASE**(i + j) - # Since we are computing it mod secp256k1_prime, we replace the term - # a.d_i * b.d_j * BASE**(i + j) - # where i + j >= 3 with - # a.d_i * b.d_j * BASE**(i + j - 3) * 4 * SECP_REM - # since BASE ** 3 = 4 * SECP_REM (mod secp256k1_prime). +from starkware.cairo.common.cairo_secp.constants import BASE, P0, P1, P2, SECP_REM +from starkware.cairo.common.math import assert_nn_le + +// Computes the multiplication of two big integers, given in BigInt3 representation, modulo the +// secp256k1 prime. +// +// Arguments: +// x, y - the two BigInt3 to operate on. +// +// Returns: +// x * y in an UnreducedBigInt3 representation (the returned limbs may be above 3 * BASE). +// +// If each of the input limbs is in the range (-x, x), the result's limbs are guaranteed to be +// in the range (-x**2 * (2 ** 35.01), x**2 * (2 ** 35.01)) since log(8 * SECP_REM + 1) < 35.01. +// +// This means that if unreduced_mul is called on the result of nondet_bigint3, or the difference +// between two such results, we have: +// Soundness guarantee: the limbs are in the range (-2**210.18, 2**210.18). +// Completeness guarantee: the limbs are in the range (-2**207.01, 2**207.01). +func unreduced_mul(a: BigInt3, b: BigInt3) -> (res_low: UnreducedBigInt3) { + // The result of the product is: + // sum_{i, j} a.d_i * b.d_j * BASE**(i + j) + // Since we are computing it mod secp256k1_prime, we replace the term + // a.d_i * b.d_j * BASE**(i + j) + // where i + j >= 3 with + // a.d_i * b.d_j * BASE**(i + j - 3) * 4 * SECP_REM + // since BASE ** 3 = 4 * SECP_REM (mod secp256k1_prime). return ( UnreducedBigInt3( d0=a.d0 * b.d0 + (a.d1 * b.d2 + a.d2 * b.d1) * (4 * SECP_REM), d1=a.d0 * b.d1 + a.d1 * b.d0 + (a.d2 * b.d2) * (4 * SECP_REM), d2=a.d0 * b.d2 + a.d1 * b.d1 + a.d2 * b.d0), - ) -end - -# Computes the square of a big integer, given in BigInt3 representation, modulo the -# secp256k1 prime. -# -# Has the same guarantees as in unreduced_mul(a, a). -func unreduced_sqr(a : BigInt3) -> (res_low : UnreducedBigInt3): - tempvar twice_d0 = a.d0 * 2 + ); +} + +// Computes the square of a big integer, given in BigInt3 representation, modulo the +// secp256k1 prime. +// +// Has the same guarantees as in unreduced_mul(a, a). +func unreduced_sqr(a: BigInt3) -> (res_low: UnreducedBigInt3) { + tempvar twice_d0 = a.d0 * 2; return ( UnreducedBigInt3( d0=a.d0 * a.d0 + (a.d1 * a.d2) * (2 * 4 * SECP_REM), d1=twice_d0 * a.d1 + (a.d2 * a.d2) * (4 * SECP_REM), d2=twice_d0 * a.d2 + a.d1 * a.d1), - ) -end - -# Verifies that the given unreduced value is equal to zero modulo the secp256k1 prime. -# -# Completeness assumption: val's limbs are in the range (-2**210.99, 2**210.99). -# Soundness assumption: val's limbs are in the range (-2**250, 2**250). -func verify_zero{range_check_ptr}(val : UnreducedBigInt3): - let q = [ap] + ); +} + +// Verifies that the given unreduced value is equal to zero modulo the secp256k1 prime. +// +// Completeness assumption: val's limbs are in the range (-2**210.99, 2**210.99). +// Soundness assumption: val's limbs are in the range (-2**250, 2**250). +func verify_zero{range_check_ptr}(val: UnreducedBigInt3) { + let q = [ap]; %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack @@ -60,50 +61,50 @@ func verify_zero{range_check_ptr}(val : UnreducedBigInt3): assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}." ids.q = q % PRIME %} - let q_biased = [ap + 1] - q_biased = q + 2 ** 127; ap++ - [range_check_ptr] = q_biased; ap++ - # This implies that q is in the range [-2**127, 2**127). - - tempvar r1 = (val.d0 + q * SECP_REM) / BASE - assert [range_check_ptr + 1] = r1 + 2 ** 127 - # This implies that r1 is in the range [-2**127, 2**127). - # Therefore, r1 * BASE is in the range [-2**213, 2**213). - # By the soundness assumption, val.d0 is in the range (-2**250, 2**250). - # This implies that r1 * BASE = val.d0 + q * SECP_REM (as integers). - - tempvar r2 = (val.d1 + r1) / BASE - assert [range_check_ptr + 2] = r2 + 2 ** 127 - # Similarly, this implies that r2 * BASE = val.d1 + r1 (as integers). - # Therefore, r2 * BASE**2 = val.d1 * BASE + r1 * BASE. - - assert val.d2 = q * (BASE / 4) - r2 - # Similarly, this implies that q * BASE / 4 = val.d2 + r2 (as integers). - # Therefore, - # q * BASE**3 / 4 = val.d2 * BASE**2 + r2 * BASE ** 2 = - # val.d2 * BASE**2 + val.d1 * BASE + r1 * BASE = - # val.d2 * BASE**2 + val.d1 * BASE + val.d0 + q * SECP_REM = - # val + q * SECP_REM. - # Hence, val = q * (BASE**3 / 4 - SECP_REM) = q * (2**256 - SECP_REM) = q * secp256k1_prime. - - let range_check_ptr = range_check_ptr + 3 - return () -end - -# Returns 1 if x == 0 (mod secp256k1_prime), and 0 otherwise. -# -# Completeness assumption: x's limbs are in the range (-BASE, 2*BASE). -# Soundness assumption: x's limbs are in the range (-2**107.49, 2**107.49). -func is_zero{range_check_ptr}(x : BigInt3) -> (res : felt): + let q_biased = [ap + 1]; + q_biased = q + 2 ** 127, ap++; + [range_check_ptr] = q_biased, ap++; + // This implies that q is in the range [-2**127, 2**127). + + tempvar r1 = (val.d0 + q * SECP_REM) / BASE; + assert [range_check_ptr + 1] = r1 + 2 ** 127; + // This implies that r1 is in the range [-2**127, 2**127). + // Therefore, r1 * BASE is in the range [-2**213, 2**213). + // By the soundness assumption, val.d0 is in the range (-2**250, 2**250). + // This implies that r1 * BASE = val.d0 + q * SECP_REM (as integers). + + tempvar r2 = (val.d1 + r1) / BASE; + assert [range_check_ptr + 2] = r2 + 2 ** 127; + // Similarly, this implies that r2 * BASE = val.d1 + r1 (as integers). + // Therefore, r2 * BASE**2 = val.d1 * BASE + r1 * BASE. + + assert val.d2 = q * (BASE / 4) - r2; + // Similarly, this implies that q * BASE / 4 = val.d2 + r2 (as integers). + // Therefore, + // q * BASE**3 / 4 = val.d2 * BASE**2 + r2 * BASE ** 2 = + // val.d2 * BASE**2 + val.d1 * BASE + r1 * BASE = + // val.d2 * BASE**2 + val.d1 * BASE + val.d0 + q * SECP_REM = + // val + q * SECP_REM. + // Hence, val = q * (BASE**3 / 4 - SECP_REM) = q * (2**256 - SECP_REM) = q * secp256k1_prime. + + let range_check_ptr = range_check_ptr + 3; + return (); +} + +// Returns 1 if x == 0 (mod secp256k1_prime), and 0 otherwise. +// +// Completeness assumption: x's limbs are in the range (-BASE, 2*BASE). +// Soundness assumption: x's limbs are in the range (-2**107.49, 2**107.49). +func is_zero{range_check_ptr}(x: BigInt3) -> (res: felt) { %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack x = pack(ids.x, PRIME) % SECP_P %} - if nondet %{ x == 0 %} != 0: - verify_zero(UnreducedBigInt3(d0=x.d0, d1=x.d1, d2=x.d2)) - return (res=1) - end + if (nondet %{ x == 0 %} != 0) { + verify_zero(UnreducedBigInt3(d0=x.d0, d1=x.d1, d2=x.d2)); + return (res=1); + } %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P @@ -111,35 +112,53 @@ func is_zero{range_check_ptr}(x : BigInt3) -> (res : felt): value = x_inv = div_mod(1, x, SECP_P) %} - let (x_inv) = nondet_bigint3() - let (x_x_inv) = unreduced_mul(x, x_inv) + let (x_inv) = nondet_bigint3(); + let (x_x_inv) = unreduced_mul(x, x_inv); - # Check that x * x_inv = 1 to verify that x != 0. + // Check that x * x_inv = 1 to verify that x != 0. verify_zero(UnreducedBigInt3( d0=x_x_inv.d0 - 1, d1=x_x_inv.d1, - d2=x_x_inv.d2)) - return (res=0) -end - -# Receives an unreduced number, and returns a number that is equal to the original number mod SECP_P -# and in reduced form (meaning every limb is in the range [0, BASE)). -# -# Completeness assumption: x's limbs are in the range (-2**210.99, 2**210.99). -# Soundness assumption: x's limbs are in the range (-2**249.99, 2**249.99). -func reduce{range_check_ptr}(x : UnreducedBigInt3) -> (reduced_x : BigInt3): + d2=x_x_inv.d2)); + return (res=0); +} + +// Receives an unreduced number, and returns a number that is equal to the original number mod +// SECP_P and in reduced form (meaning every limb is in the range [0, BASE)). +// +// Completeness assumption: x's limbs are in the range (-2**210.99, 2**210.99). +// Soundness assumption: x's limbs are in the range (-2**249.99, 2**249.99). +func reduce{range_check_ptr}(x: UnreducedBigInt3) -> (reduced_x: BigInt3) { %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack value = pack(ids.x, PRIME) % SECP_P %} - let (reduced_x : BigInt3) = nondet_bigint3() + let (reduced_x: BigInt3) = nondet_bigint3(); verify_zero( UnreducedBigInt3( d0=x.d0 - reduced_x.d0, d1=x.d1 - reduced_x.d1, d2=x.d2 - reduced_x.d2), - ) - return (reduced_x=reduced_x) -end + ); + return (reduced_x=reduced_x); +} + +// Verifies that val is in the range [0, p) (where p is secp256k1 prime) and that the limbs of +// val are in the range [0, BASE). This guarantees unique representation. +func validate_reduced_field_element{range_check_ptr}(val: BigInt3) { + assert_nn_le(val.d2, P2); + assert_nn_le(val.d1, BASE - 1); + assert_nn_le(val.d0, BASE - 1); + + if (val.d2 == P2) { + if (val.d1 == P1) { + assert_nn_le(val.d0, P0 - 1); + return (); + } + assert_nn_le(val.d1, P1 - 1); + return (); + } + return (); +} diff --git a/src/starkware/cairo/common/cairo_secp/signature.cairo b/src/starkware/cairo/common/cairo_secp/signature.cairo index 4d91b309..aeb40d4d 100644 --- a/src/starkware/cairo/common/cairo_secp/signature.cairo +++ b/src/starkware/cairo/common/cairo_secp/signature.cairo @@ -16,6 +16,7 @@ from starkware.cairo.common.cairo_secp.field import ( reduce, unreduced_mul, unreduced_sqr, + validate_reduced_field_element, verify_zero, ) from starkware.cairo.common.math import assert_nn, assert_nn_le, assert_not_zero, unsigned_div_rem @@ -23,25 +24,29 @@ from starkware.cairo.common.math_cmp import RC_BOUND from starkware.cairo.common.uint256 import Uint256 @known_ap_change -func get_generator_point() -> (point : EcPoint): - # generator_point = ( - # 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, - # 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 - # ) +func get_generator_point() -> (point: EcPoint) { + // generator_point = ( + // 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, + // 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 + // ). return ( point=EcPoint( BigInt3(0xe28d959f2815b16f81798, 0xa573a1c2c1c0a6ff36cb7, 0x79be667ef9dcbbac55a06), BigInt3(0x554199c47d08ffb10d4b8, 0x2ff0384422a3f45ed1229a, 0x483ada7726a3c4655da4f)), - ) -end - -# Computes a * b^(-1) modulo the size of the elliptic curve (N). -# -# Prover assumptions: -# * All the limbs of a are in the range (-2 ** 210.99, 2 ** 210.99). -# * All the limbs of b are in the range (-2 ** 124.99, 2 ** 124.99). -# * b is in the range [0, 2 ** 256). -func div_mod_n{range_check_ptr}(a : BigInt3, b : BigInt3) -> (res : BigInt3): + ); +} + +// Computes a * b^(-1) modulo the size of the elliptic curve (N). +// +// Prover assumptions: +// * All the limbs of a are in the range (-2 ** 210.99, 2 ** 210.99). +// * All the limbs of b are in the range (-2 ** 124.99, 2 ** 124.99). +// * b is in the range [0, 2 ** 256). +// +// Soundness assumptions: +// * The limbs of a are in the range (-2 ** 249, 2 ** 249). +// * The limbs of b are in the range (-2 ** 159.83, 2 ** 159.83). +func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { %{ from starkware.cairo.common.cairo_secp.secp_utils import N, pack from starkware.python.math_utils import div_mod, safe_div @@ -50,91 +55,95 @@ func div_mod_n{range_check_ptr}(a : BigInt3, b : BigInt3) -> (res : BigInt3): b = pack(ids.b, PRIME) value = res = div_mod(a, b, N) %} - let (res) = nondet_bigint3() + let (res) = nondet_bigint3(); %{ value = k = safe_div(res * b - a, N) %} - let (k) = nondet_bigint3() + let (k) = nondet_bigint3(); - let (res_b) = bigint_mul(res, b) - let n = BigInt3(N0, N1, N2) - let (k_n) = bigint_mul(k, n) + let (res_b) = bigint_mul(res, b); + let n = BigInt3(N0, N1, N2); + let (k_n) = bigint_mul(k, n); - # We should now have res_b = k_n + a. Since the numbers are in unreduced form, - # we should handle the carry. + // We should now have res_b = k_n + a. Since the numbers are in unreduced form, + // we should handle the carry. - tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE - assert [range_check_ptr + 0] = carry1 + 2 ** 127 + tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE; + assert [range_check_ptr + 0] = carry1 + 2 ** 127; - tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE - assert [range_check_ptr + 1] = carry2 + 2 ** 127 + tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE; + assert [range_check_ptr + 1] = carry2 + 2 ** 127; - tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE - assert [range_check_ptr + 2] = carry3 + 2 ** 127 + tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE; + assert [range_check_ptr + 2] = carry3 + 2 ** 127; - tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE - assert [range_check_ptr + 3] = carry4 + 2 ** 127 + tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE; + assert [range_check_ptr + 3] = carry4 + 2 ** 127; - assert res_b.d4 - k_n.d4 + carry4 = 0 + assert res_b.d4 - k_n.d4 + carry4 = 0; - let range_check_ptr = range_check_ptr + 4 + let range_check_ptr = range_check_ptr + 4; - return (res=res) -end + return (res=res); +} -# Verifies that val is in the range [1, N) and that the limbs of val are in the range [0, BASE). -func validate_signature_entry{range_check_ptr}(val : BigInt3): - assert_nn_le(val.d2, N2) - assert_nn_le(val.d1, BASE - 1) - assert_nn_le(val.d0, BASE - 1) +// Verifies that val is in the range [1, N) and that the limbs of val are in the range [0, BASE). +func validate_signature_entry{range_check_ptr}(val: BigInt3) { + assert_nn_le(val.d2, N2); + assert_nn_le(val.d1, BASE - 1); + assert_nn_le(val.d0, BASE - 1); - if val.d2 == N2: - if val.d1 == N1: - assert_nn_le(val.d0, N0 - 1) - return () - end - assert_nn_le(val.d1, N1 - 1) - return () - end + if (val.d2 == N2) { + if (val.d1 == N1) { + assert_nn_le(val.d0, N0 - 1); + return (); + } + assert_nn_le(val.d1, N1 - 1); + return (); + } - # Check that val > 0. - if val.d2 == 0: - if val.d1 == 0: - assert_not_zero(val.d0) - return () - end - end - return () -end + // Check that val > 0. + if (val.d2 == 0) { + if (val.d1 == 0) { + assert_not_zero(val.d0); + return (); + } + } + return (); +} -# Converts a public key point to the corresponding Ethereum address. +// Converts a public key point to the corresponding Ethereum address. func public_key_point_to_eth_address{ - range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt* -}(public_key_point : EcPoint) -> (eth_address : felt): - alloc_locals - let (local elements : Uint256*) = alloc() - let (x_uint256 : Uint256) = bigint_to_uint256(public_key_point.x) - assert elements[0] = x_uint256 - let (y_uint256 : Uint256) = bigint_to_uint256(public_key_point.y) - assert elements[1] = y_uint256 - let (point_hash : Uint256) = keccak_uint256s_bigend(n_elements=2, elements=elements) - - # The Ethereum address is the 20 least significant bytes of the keccak of the public key. - let (high_high, high_low) = unsigned_div_rem(point_hash.high, 2 ** 32) - return (eth_address=point_hash.low + RC_BOUND * high_low) -end - -# Returns a point on the secp256k1 curve with the given x coordinate. Chooses the y that has the -# same parity as v (there are two y values that correspond to x, with different parities). -# Also verifies that v is in the range [0, 2 ** 128). -# Prover assumption: -# x is the x coordinate of some nonzero point on the curve. -func get_point_from_x{range_check_ptr}(x : BigInt3, v : felt) -> (point : EcPoint): - with_attr error_message("Out of range v {v}."): - assert_nn(v) - end - let (x_square : UnreducedBigInt3) = unreduced_sqr(x) - let (x_square_reduced : BigInt3) = reduce(x_square) - let (x_cube : UnreducedBigInt3) = unreduced_mul(x, x_square_reduced) + range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt* +}(public_key_point: EcPoint) -> (eth_address: felt) { + alloc_locals; + let (local elements: Uint256*) = alloc(); + let (x_uint256: Uint256) = bigint_to_uint256(public_key_point.x); + assert elements[0] = x_uint256; + let (y_uint256: Uint256) = bigint_to_uint256(public_key_point.y); + assert elements[1] = y_uint256; + let (point_hash: Uint256) = keccak_uint256s_bigend(n_elements=2, elements=elements); + + // The Ethereum address is the 20 least significant bytes of the keccak of the public key. + let (high_high, high_low) = unsigned_div_rem(point_hash.high, 2 ** 32); + return (eth_address=point_hash.low + RC_BOUND * high_low); +} + +// Returns a point on the secp256k1 curve with the given x coordinate. Chooses the y that has the +// same parity as v (there are two y values that correspond to x, with different parities). +// Also verifies that v is in the range [0, 2 ** 128). +// Prover assumptions: +// * x is the x coordinate of some nonzero point on the curve. +// * The limbs of x are in the range (-2**87.99, 2**87.99). +// Soundness assumptions: +// * The limbs of x are in the range (-2**106.99, 2**106.99). +func get_point_from_x{range_check_ptr}(x: BigInt3, v: felt) -> (point: EcPoint) { + alloc_locals; + with_attr error_message("Out of range v {v}.") { + assert_nn(v); + } + let (x_square: UnreducedBigInt3) = unreduced_sqr(x); + let (x_square_reduced: BigInt3) = reduce(x_square); + let (x_cube: UnreducedBigInt3) = unreduced_mul(x, x_square_reduced); %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack @@ -149,92 +158,93 @@ func get_point_from_x{range_check_ptr}(x : BigInt3, v : felt) -> (point : EcPoin else: value = (-y) % SECP_P %} - let (y : BigInt3) = nondet_bigint3() + let (local y: BigInt3) = nondet_bigint3(); + validate_reduced_field_element(y); - # Check that y has same parity as v. - assert_nn((y.d0 + v) / 2) + // Check that y has same parity as v. + assert_nn((y.d0 + v) / 2); - let (y_square : UnreducedBigInt3) = unreduced_sqr(y) - # Check that y_square = x_cube + BETA. + let (y_square: UnreducedBigInt3) = unreduced_sqr(y); + // Check that y_square = x_cube + BETA. verify_zero( UnreducedBigInt3( d0=x_cube.d0 + BETA - y_square.d0, d1=x_cube.d1 - y_square.d1, d2=x_cube.d2 - y_square.d2, ), - ) - - return (point=EcPoint(x, y)) -end - -# Receives a signature and the signed message hash. -# Returns the public key associated with the signer, represented as a point on the curve. -# Note: -# Some places use the values 27 and 28 instead of 0 and 1 for v. In that case, a subtraction by 27 -# returns a v that can be used by this function. -# Prover assumptions: -# * r is the x coordinate of some nonzero point on the curve. -# * All the limbs of s and msg_hash are in the range (-2 ** 210.99, 2 ** 210.99). -# * All the limbs of r are in the range (-2 ** 124.99, 2 ** 124.99). -func recover_public_key{range_check_ptr}( - msg_hash : BigInt3, r : BigInt3, s : BigInt3, v : felt -) -> (public_key_point : EcPoint): - alloc_locals - let (local r_point : EcPoint) = get_point_from_x(x=r, v=v) - let (generator_point : EcPoint) = get_generator_point() - # The result is given by - # -(msg_hash / r) * gen + (s / r) * r_point - # where the division by r is modulo N. - - let (u1 : BigInt3) = div_mod_n(msg_hash, r) - let (u2 : BigInt3) = div_mod_n(s, r) - - let (point1) = ec_mul(generator_point, u1) - # We prefer negating the point over negating the scalar because negating mod SECP_P is - # computationally easier than mod N. - let (minus_point1) = ec_negate(point1) - - let (point2) = ec_mul(r_point, u2) - - let (public_key_point) = ec_add(minus_point1, point2) - return (public_key_point=public_key_point) -end - -# Verifies a Secp256k1 ECDSA signature. -# Also verifies that r and s are in the range (0, N), that their limbs are in the range -# [0, BASE), and that v is in the range [0, 2 ** 128). -# Receives a keccak_ptr for computing keccak. finalize_keccak should be called by the function's -# caller after all the keccak calculations are done. -# Assumptions: -# * All the limbs of msg_hash are in the range [0, 3 * BASE). -func verify_eth_signature{range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt*}( - msg_hash : BigInt3, r : BigInt3, s : BigInt3, v : felt, eth_address : felt -): - alloc_locals - - with_attr error_message("Signature out of range."): - validate_signature_entry(r) - validate_signature_entry(s) - end - - with_attr error_message("Invalid signature."): - let (public_key_point : EcPoint) = recover_public_key(msg_hash=msg_hash, r=r, s=s, v=v) + ); + + return (point=EcPoint(x, y)); +} + +// Receives a signature and the signed message hash. +// Returns the public key associated with the signer, represented as a point on the curve. +// Note: +// Some places use the values 27 and 28 instead of 0 and 1 for v. +// In that case, a subtraction by 27 returns a v that can be used by this function. +// Prover assumptions: +// * r is the x coordinate of some nonzero point on the curve. +// * All the limbs of s and msg_hash are in the range (-2 ** 210.99, 2 ** 210.99). +// * All the limbs of r are in the range (-2 ** 124.99, 2 ** 124.99). +func recover_public_key{range_check_ptr}(msg_hash: BigInt3, r: BigInt3, s: BigInt3, v: felt) -> ( + public_key_point: EcPoint +) { + alloc_locals; + let (local r_point: EcPoint) = get_point_from_x(x=r, v=v); + let (generator_point: EcPoint) = get_generator_point(); + // The result is given by + // -(msg_hash / r) * gen + (s / r) * r_point + // where the division by r is modulo N. + + let (u1: BigInt3) = div_mod_n(msg_hash, r); + let (u2: BigInt3) = div_mod_n(s, r); + + let (point1) = ec_mul(generator_point, u1); + // We prefer negating the point over negating the scalar because negating mod SECP_P is + // computationally easier than mod N. + let (minus_point1) = ec_negate(point1); + + let (point2) = ec_mul(r_point, u2); + + let (public_key_point) = ec_add(minus_point1, point2); + return (public_key_point=public_key_point); +} + +// Verifies a Secp256k1 ECDSA signature. +// Also verifies that r and s are in the range (0, N), that their limbs are in the range +// [0, BASE), and that v is in the range [0, 2 ** 128). +// Receives a keccak_ptr for computing keccak. finalize_keccak should be called by the function's +// caller after all the keccak calculations are done. +// Assumptions: +// * All the limbs of msg_hash are in the range [0, 3 * BASE). +func verify_eth_signature{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + msg_hash: BigInt3, r: BigInt3, s: BigInt3, v: felt, eth_address: felt +) { + alloc_locals; + + with_attr error_message("Signature out of range.") { + validate_signature_entry(r); + validate_signature_entry(s); + } + + with_attr error_message("Invalid signature.") { + let (public_key_point: EcPoint) = recover_public_key(msg_hash=msg_hash, r=r, s=s, v=v); let (calculated_eth_address) = public_key_point_to_eth_address( public_key_point=public_key_point - ) - assert eth_address = calculated_eth_address - end - return () -end - -# Same as verify_eth_signature, except that msg_hash, r and s are Uint256. -func verify_eth_signature_uint256{ - range_check_ptr, bitwise_ptr : BitwiseBuiltin*, keccak_ptr : felt* -}(msg_hash : Uint256, r : Uint256, s : Uint256, v : felt, eth_address : felt): - let (msg_hash_bigint : BigInt3) = uint256_to_bigint(msg_hash) - let (r_bigint : BigInt3) = uint256_to_bigint(r) - let (s_bigint : BigInt3) = uint256_to_bigint(s) + ); + assert eth_address = calculated_eth_address; + } + return (); +} + +// Same as verify_eth_signature, except that msg_hash, r and s are Uint256. +func verify_eth_signature_uint256{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( + msg_hash: Uint256, r: Uint256, s: Uint256, v: felt, eth_address: felt +) { + let (msg_hash_bigint: BigInt3) = uint256_to_bigint(msg_hash); + let (r_bigint: BigInt3) = uint256_to_bigint(r); + let (s_bigint: BigInt3) = uint256_to_bigint(s); return verify_eth_signature( msg_hash=msg_hash_bigint, r=r_bigint, s=s_bigint, v=v, eth_address=eth_address - ) -end + ); +} diff --git a/src/starkware/cairo/common/default_dict.cairo b/src/starkware/cairo/common/default_dict.cairo index 0a73712c..a8d2c7f2 100644 --- a/src/starkware/cairo/common/default_dict.cairo +++ b/src/starkware/cairo/common/default_dict.cairo @@ -1,11 +1,11 @@ from starkware.cairo.common.dict import dict_squash from starkware.cairo.common.dict_access import DictAccess -# Creates a new dictionary, with a default value. -# -# NOTE: you MUST call default_dict_finalize() (with the same default_value) to properly destruct -# the dictionary. Otherwise, the initial values of the dictionary are not guaranteed to be 'value'. -func default_dict_new(default_value : felt) -> (res : DictAccess*): +// Creates a new dictionary, with a default value. +// +// NOTE: you MUST call default_dict_finalize() (with the same default_value) to properly destruct +// the dictionary. Otherwise, the initial values of the dictionary are not guaranteed to be 'value'. +func default_dict_new(default_value: felt) -> (res: DictAccess*) { %{ if '__dict_manager' not in globals(): from starkware.cairo.common.dict import DictManager @@ -13,41 +13,41 @@ func default_dict_new(default_value : felt) -> (res : DictAccess*): memory[ap] = __dict_manager.new_default_dict(segments, ids.default_value) %} - ap += 1 - return (res=cast([ap - 1], DictAccess*)) -end + ap += 1; + return (res=cast([ap - 1], DictAccess*)); +} -# Finalizes the given default dictionary, and makes sure the initial values of the dictionary -# were indeed 'default_value'. -# Returns the squashed dictionary. +// Finalizes the given default dictionary, and makes sure the initial values of the dictionary +// were indeed 'default_value'. +// Returns the squashed dictionary. func default_dict_finalize{range_check_ptr}( - dict_accesses_start : DictAccess*, dict_accesses_end : DictAccess*, default_value : felt -) -> (squashed_dict_start : DictAccess*, squashed_dict_end : DictAccess*): - alloc_locals + dict_accesses_start: DictAccess*, dict_accesses_end: DictAccess*, default_value: felt +) -> (squashed_dict_start: DictAccess*, squashed_dict_end: DictAccess*) { + alloc_locals; let (local squashed_dict_start, local squashed_dict_end) = dict_squash( dict_accesses_start, dict_accesses_end - ) - local range_check_ptr = range_check_ptr + ); + local range_check_ptr = range_check_ptr; default_dict_finalize_inner( dict_accesses_start=squashed_dict_start, n_accesses=(squashed_dict_end - squashed_dict_start) / DictAccess.SIZE, default_value=default_value, - ) - return (squashed_dict_start=squashed_dict_start, squashed_dict_end=squashed_dict_end) -end + ); + return (squashed_dict_start=squashed_dict_start, squashed_dict_end=squashed_dict_end); +} func default_dict_finalize_inner( - dict_accesses_start : DictAccess*, n_accesses : felt, default_value : felt -): - if n_accesses == 0: - return () - end + dict_accesses_start: DictAccess*, n_accesses: felt, default_value: felt +) { + if (n_accesses == 0) { + return (); + } - assert dict_accesses_start.prev_value = default_value + assert dict_accesses_start.prev_value = default_value; return default_dict_finalize_inner( dict_accesses_start + DictAccess.SIZE, n_accesses=n_accesses - 1, default_value=default_value, - ) -end + ); +} diff --git a/src/starkware/cairo/common/dict.cairo b/src/starkware/cairo/common/dict.cairo index 3c3dcb8b..a15b2f3d 100644 --- a/src/starkware/cairo/common/dict.cairo +++ b/src/starkware/cairo/common/dict.cairo @@ -1,11 +1,11 @@ from starkware.cairo.common.dict_access import DictAccess from starkware.cairo.common.squash_dict import squash_dict -# Creates a new dict. -# -# Hint argument: -# initial_dict - A python dict containing the initial values of the new dict. -func dict_new() -> (res : DictAccess*): +// Creates a new dict. +// +// Hint argument: +// initial_dict - A python dict containing the initial values of the new dict. +func dict_new() -> (res: DictAccess*) { %{ if '__dict_manager' not in globals(): from starkware.cairo.common.dict import DictManager @@ -14,45 +14,45 @@ func dict_new() -> (res : DictAccess*): memory[ap] = __dict_manager.new_dict(segments, initial_dict) del initial_dict %} - ap += 1 - return (res=cast([ap - 1], DictAccess*)) -end + ap += 1; + return (res=cast([ap - 1], DictAccess*)); +} -# Reads a value from the dictionary and returns the result. -func dict_read{dict_ptr : DictAccess*}(key : felt) -> (value : felt): - alloc_locals - local value +// Reads a value from the dictionary and returns the result. +func dict_read{dict_ptr: DictAccess*}(key: felt) -> (value: felt) { + alloc_locals; + local value; %{ dict_tracker = __dict_manager.get_tracker(ids.dict_ptr) dict_tracker.current_ptr += ids.DictAccess.SIZE ids.value = dict_tracker.data[ids.key] %} - dict_ptr.key = key - dict_ptr.prev_value = value - dict_ptr.new_value = value - let dict_ptr = dict_ptr + DictAccess.SIZE - return (value=value) -end + dict_ptr.key = key; + dict_ptr.prev_value = value; + dict_ptr.new_value = value; + let dict_ptr = dict_ptr + DictAccess.SIZE; + return (value=value); +} -# Writes a value to the dictionary, overriding the existing value. -func dict_write{dict_ptr : DictAccess*}(key : felt, new_value : felt): +// Writes a value to the dictionary, overriding the existing value. +func dict_write{dict_ptr: DictAccess*}(key: felt, new_value: felt) { %{ dict_tracker = __dict_manager.get_tracker(ids.dict_ptr) dict_tracker.current_ptr += ids.DictAccess.SIZE ids.dict_ptr.prev_value = dict_tracker.data[ids.key] dict_tracker.data[ids.key] = ids.new_value %} - dict_ptr.key = key - dict_ptr.new_value = new_value - let dict_ptr = dict_ptr + DictAccess.SIZE - return () -end + dict_ptr.key = key; + dict_ptr.new_value = new_value; + let dict_ptr = dict_ptr + DictAccess.SIZE; + return (); +} -# Updates a value in a dict. prev_value must be specified. A standalone read with no write should be -# performed by writing the same value. -# It is possible to get prev_value from __dict_manager using the hint: -# %{ ids.val = __dict_manager.get_dict(ids.dict_ptr)[ids.key] %} -func dict_update{dict_ptr : DictAccess*}(key : felt, prev_value : felt, new_value : felt): +// Updates a value in a dict. prev_value must be specified. A standalone read with no write should +// be performed by writing the same value. +// It is possible to get prev_value from __dict_manager using the hint: +// %{ ids.val = __dict_manager.get_dict(ids.dict_ptr)[ids.key] %} +func dict_update{dict_ptr: DictAccess*}(key: felt, prev_value: felt, new_value: felt) { %{ # Verify dict pointer and prev value. dict_tracker = __dict_manager.get_tracker(ids.dict_ptr) @@ -64,25 +64,25 @@ func dict_update{dict_ptr : DictAccess*}(key : felt, prev_value : felt, new_valu dict_tracker.data[ids.key] = ids.new_value dict_tracker.current_ptr += ids.DictAccess.SIZE %} - dict_ptr.key = key - dict_ptr.prev_value = prev_value - dict_ptr.new_value = new_value - let dict_ptr = dict_ptr + DictAccess.SIZE - return () -end + dict_ptr.key = key; + dict_ptr.prev_value = prev_value; + dict_ptr.new_value = new_value; + let dict_ptr = dict_ptr + DictAccess.SIZE; + return (); +} -# Returns a new dictionary with one DictAccess instance per key -# (value before and value after) which summarizes all the changes to that key. -# -# Example: -# Input: {(key1, 0, 2), (key1, 2, 7), (key2, 4, 1), (key1, 7, 5), (key2, 1, 2)} -# Output: {(key1, 0, 5), (key2, 4, 2)} -# -# This is a wrapper of squash_dict for dictionaries created by dict_new(). +// Returns a new dictionary with one DictAccess instance per key +// (value before and value after) which summarizes all the changes to that key. +// +// Example: +// Input: {(key1, 0, 2), (key1, 2, 7), (key2, 4, 1), (key1, 7, 5), (key2, 1, 2)} +// Output: {(key1, 0, 5), (key2, 4, 2)} +// +// This is a wrapper of squash_dict for dictionaries created by dict_new(). func dict_squash{range_check_ptr}( - dict_accesses_start : DictAccess*, dict_accesses_end : DictAccess* -) -> (squashed_dict_start : DictAccess*, squashed_dict_end : DictAccess*): - alloc_locals + dict_accesses_start: DictAccess*, dict_accesses_end: DictAccess* +) -> (squashed_dict_start: DictAccess*, squashed_dict_end: DictAccess*) { + alloc_locals; %{ # Prepare arguments for dict_new. In particular, the same dictionary values should be copied @@ -94,19 +94,19 @@ func dict_squash{range_check_ptr}( 'initial_dict': dict(__dict_manager.get_dict(ids.dict_accesses_end)), }) %} - let (local squashed_dict_start) = dict_new() + let (local squashed_dict_start) = dict_new(); %{ vm_exit_scope() %} let (squashed_dict_end) = squash_dict( dict_accesses=dict_accesses_start, dict_accesses_end=dict_accesses_end, squashed_dict=squashed_dict_start, - ) + ); %{ # Update the DictTracker's current_ptr to point to the end of the squashed dict. __dict_manager.get_tracker(ids.squashed_dict_start).current_ptr = \ ids.squashed_dict_end.address_ %} - return (squashed_dict_start=squashed_dict_start, squashed_dict_end=squashed_dict_end) -end + return (squashed_dict_start=squashed_dict_start, squashed_dict_end=squashed_dict_end); +} diff --git a/src/starkware/cairo/common/dict_access.cairo b/src/starkware/cairo/common/dict_access.cairo index b1625804..c04f461e 100644 --- a/src/starkware/cairo/common/dict_access.cairo +++ b/src/starkware/cairo/common/dict_access.cairo @@ -1,10 +1,10 @@ -# Represents an access (read, write or modify) to the dictionary. The dictionary is represented as a -# chronological list of such accesses. The "current" value of a key is the new_value of the last -# access with that key. -# In a valid dictionary, the prev_value of each access is equal to the new_value of the previous -# access to the same key. -struct DictAccess: - member key : felt - member prev_value : felt - member new_value : felt -end +// Represents an access (read, write or modify) to the dictionary. The dictionary is represented as +// a chronological list of such accesses. The "current" value of a key is the new_value of the last +// access with that key. +// In a valid dictionary, the prev_value of each access is equal to the new_value of the previous +// access to the same key. +struct DictAccess { + key: felt, + prev_value: felt, + new_value: felt, +} diff --git a/src/starkware/cairo/common/ec.cairo b/src/starkware/cairo/common/ec.cairo index d2eedf52..02a587a1 100644 --- a/src/starkware/cairo/common/ec.cairo +++ b/src/starkware/cairo/common/ec.cairo @@ -1,115 +1,135 @@ -# Functions for various actions on the STARK curve: -# y^2 = x^3 + alpha * x + beta -# where alpha = 1 and beta = 0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89. -# The point at infinity is represented as (0, 0). +// Functions for various actions on the STARK curve: +// y^2 = x^3 + alpha * x + beta +// where alpha = 1 and beta = 0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89. +// The point at infinity is represented as (0, 0). from starkware.cairo.common.cairo_builtins import EcOpBuiltin from starkware.cairo.common.ec_point import EcPoint +from starkware.cairo.common.math import is_quad_residue -const CURVE_ALPHA = 1 -const CURVE_BETA = 0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89 - -# Asserts that an EC point is on the STARK curve. -# -# Arguments: -# p - an EC point. -func assert_on_curve(p : EcPoint): - # Because the curve order is odd, there is no point (except (0, 0), which represents the point - # at infinity) with y = 0. - if p.y == 0: - assert p.x = 0 - return () - end - tempvar rhs = (p.x * p.x + CURVE_ALPHA) * p.x + CURVE_BETA - assert p.y * p.y = rhs - return () -end - -# Doubles a point (computes p + p) on the elliptic curve. -# -# Arguments: -# p - an EC point. -# -# Returns: -# r = p + p. -# -# Assumptions: -# p is a valid point on the curve. -func ec_double(p : EcPoint) -> (r : EcPoint): - # (0, 0), which represents the point at infinity, is the only point with y = 0. - if p.y == 0: - return (r=p) - end - tempvar slope = (3 * p.x * p.x + CURVE_ALPHA) / (2 * p.y) - tempvar r_x = slope * slope - p.x - p.x - return (r=EcPoint(x=r_x, y=slope * (p.x - r_x) - p.y)) -end - -# Adds two points on the EC. -# -# Arguments: -# p - an EC point. -# q - an EC point. -# -# Returns: -# r = p + q. -# -# Assumptions: -# p and q are valid points on the curve. -func ec_add(p : EcPoint, q : EcPoint) -> (r : EcPoint): - # (0, 0), which represents the point at infinity, is the only point with y = 0. - if p.y == 0: - return (r=q) - end - if q.y == 0: - return (r=p) - end - if p.x == q.x: - if p.y == q.y: - return ec_double(p) - end - # In this case, because p and q are on the curve, p.y = -q.y. - return (r=EcPoint(x=0, y=0)) - end - tempvar slope = (p.y - q.y) / (p.x - q.x) - tempvar r_x = slope * slope - p.x - q.x - return (r=EcPoint(x=r_x, y=slope * (p.x - r_x) - p.y)) -end - -# Computes p + m * q on the elliptic curve. -# Because the EC operation builtin cannot handle inputs where additions of points with the same x -# coordinate arise during the computation, this function adds and subtracts a nondeterministic -# point s to the computation, so that regardless of input, the probability that such additions -# arise will become negligibly small. -# The precise computation is therefore: -# ((p + s) + m * q) - s -# so that the inputs to the builtin itself are (p + s), m, and q. -# -# Arguments: -# ec_op_ptr - the ec_op builtin pointer. -# p - an EC point. -# m - the multiplication coefficient of Q. -# q - an EC point. -# -# Returns: -# r = p + m * q. -# -# Assumptions: -# p and q are valid points on the curve. -func ec_op{ec_op_ptr : EcOpBuiltin*}(p : EcPoint, m : felt, q : EcPoint) -> (r : EcPoint): - alloc_locals - - # (0, 0), which represents the point at infinity, is the only point with y = 0. - if q.y == 0: - return (r=p) - end - - local s : EcPoint +namespace StarkCurve { + const ALPHA = 1; + const BETA = 0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89; + const ORDER = 0x800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f; + const GEN_X = 0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca; + const GEN_Y = 0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f; +} + +// Asserts that an EC point is on the STARK curve. +// +// Arguments: +// p - an EC point. +func assert_on_curve(p: EcPoint) { + // Because the curve order is odd, there is no point (except (0, 0), which represents the point + // at infinity) with y = 0. + if (p.y == 0) { + assert p.x = 0; + return (); + } + tempvar rhs = (p.x * p.x + StarkCurve.ALPHA) * p.x + StarkCurve.BETA; + assert p.y * p.y = rhs; + return (); +} + +// Doubles a point (computes p + p) on the elliptic curve. +// +// Arguments: +// p - an EC point. +// +// Returns: +// r = p + p. +// +// Assumptions: +// p is a valid point on the curve. +func ec_double(p: EcPoint) -> (r: EcPoint) { + // (0, 0), which represents the point at infinity, is the only point with y = 0. + if (p.y == 0) { + return (r=p); + } + tempvar slope = (3 * p.x * p.x + StarkCurve.ALPHA) / (2 * p.y); + tempvar r_x = slope * slope - p.x - p.x; + return (r=EcPoint(x=r_x, y=slope * (p.x - r_x) - p.y)); +} + +// Adds two points on the EC. +// +// Arguments: +// p - an EC point. +// q - an EC point. +// +// Returns: +// r = p + q. +// +// Assumptions: +// p and q are valid points on the curve. +func ec_add(p: EcPoint, q: EcPoint) -> (r: EcPoint) { + // (0, 0), which represents the point at infinity, is the only point with y = 0. + if (p.y == 0) { + return (r=q); + } + if (q.y == 0) { + return (r=p); + } + if (p.x == q.x) { + if (p.y == q.y) { + return ec_double(p); + } + // In this case, because p and q are on the curve, p.y = -q.y. + return (r=EcPoint(x=0, y=0)); + } + tempvar slope = (p.y - q.y) / (p.x - q.x); + tempvar r_x = slope * slope - p.x - q.x; + return (r=EcPoint(x=r_x, y=slope * (p.x - r_x) - p.y)); +} + +// Subtracts a point from another on the EC. +// +// Arguments: +// p - an EC point. +// q - an EC point. +// +// Returns: +// r = p - q. +// +// Assumptions: +// p and q are valid points on the curve. +func ec_sub(p: EcPoint, q: EcPoint) -> (r: EcPoint) { + return ec_add(p=p, q=EcPoint(x=q.x, y=-q.y)); +} + +// Computes p + m * q on the elliptic curve. +// Because the EC operation builtin cannot handle inputs where additions of points with the same x +// coordinate arise during the computation, this function adds and subtracts a nondeterministic +// point s to the computation, so that regardless of input, the probability that such additions +// arise will become negligibly small. +// The precise computation is therefore: +// ((p + s) + m * q) - s +// so that the inputs to the builtin itself are (p + s), m, and q. +// +// Arguments: +// ec_op_ptr - the ec_op builtin pointer. +// p - an EC point. +// m - the multiplication coefficient of Q. +// q - an EC point. +// +// Returns: +// r = p + m * q. +// +// Assumptions: +// p and q are valid points on the curve. +func ec_op{ec_op_ptr: EcOpBuiltin*}(p: EcPoint, m: felt, q: EcPoint) -> (r: EcPoint) { + alloc_locals; + + // (0, 0), which represents the point at infinity, is the only point with y = 0. + if (q.y == 0) { + return (r=p); + } + + local s: EcPoint; %{ from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME from starkware.python.math_utils import random_ec_point - def to_bytes(n): - return n.to_bytes(256, "little") + from starkware.python.utils import to_bytes # Define a seed for random_ec_point that's dependent on all the input, so that: # (1) The added point s is deterministic. @@ -117,12 +137,150 @@ func ec_op{ec_op_ptr : EcOpBuiltin*}(p : EcPoint, m : felt, q : EcPoint) -> (r : seed = b"".join(map(to_bytes, [ids.p.x, ids.p.y, ids.m, ids.q.x, ids.q.y])) ids.s.x, ids.s.y = random_ec_point(FIELD_PRIME, ALPHA, BETA, seed) %} - let p_plus_s : EcPoint = ec_add(p, s) - - assert ec_op_ptr.p = p_plus_s - assert ec_op_ptr.m = m - assert ec_op_ptr.q = q - let r : EcPoint = ec_add(ec_op_ptr.r, EcPoint(x=s.x, y=-s.y)) - let ec_op_ptr = ec_op_ptr + EcOpBuiltin.SIZE - return (r=r) -end + let p_plus_s: EcPoint = ec_add(p, s); + + assert ec_op_ptr.p = p_plus_s; + assert ec_op_ptr.m = m; + assert ec_op_ptr.q = q; + let r: EcPoint = ec_add(ec_op_ptr.r, EcPoint(x=s.x, y=-s.y)); + let ec_op_ptr = ec_op_ptr + EcOpBuiltin.SIZE; + return (r=r); +} + +// Computes m * p on the elliptic curve. +// +// Arguments: +// ec_op_ptr - the ec_op builtin pointer. +// m - the multiplication coefficient of p. +// p - an EC point. +// +// Returns: +// r = m * p. +// +// Assumptions: +// p is a valid point on the curve. +func ec_mul{ec_op_ptr: EcOpBuiltin*}(m: felt, p: EcPoint) -> (r: EcPoint) { + return ec_op(p=EcPoint(x=0, y=0), m=m, q=p); +} + +// Computes p + m[0] * q[0] + m[1] * q[1] + ... m[len - 1] * q[len - 1] on the elliptic curve. +// Because the EC operation builtin cannot handle inputs where additions of points with the same x +// coordinate arise during the computation, this function adds and removes a nondeterministic +// point s to the computation, so that regardless of input, the probability that such additions +// arise will become negligibly small. +// The precise computation is therefore: +// ((p + s) + m[0] * q[0] + m[1] + q[1] + ... + m[len - 1] * q[len - 1]) - s. +// +// Arguments: +// ec_op_ptr - the ec_op builtin pointer. +// p - an EC point. +// m - an array of multiplication coefficients. +// q - an array of EC points. +// len - the number of points in q. +// +// Returns: +// r = p + m[0] * q[0] + m[1] * q[1] + ... + m[len - 1] * q[len - 1]. +// Assumptions: +// * All given EC points are on the STARK curve. +// * len <= 1000. +func chained_ec_op{ec_op_ptr: EcOpBuiltin*}(p: EcPoint, m: felt*, q: EcPoint*, len: felt) -> ( + r: EcPoint +) { + alloc_locals; + local s: EcPoint; + %{ + from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME + from starkware.python.math_utils import random_ec_point + from starkware.python.utils import to_bytes + + n_elms = ids.len + assert isinstance(n_elms, int) and n_elms >= 0, \ + f'Invalid value for len. Got: {n_elms}.' + if '__chained_ec_op_max_len' in globals(): + assert n_elms <= __chained_ec_op_max_len, \ + f'chained_ec_op() can only be used with len<={__chained_ec_op_max_len}. ' \ + f'Got: n_elms={n_elms}.' + + # Define a seed for random_ec_point that's dependent on all the input, so that: + # (1) The added point s is deterministic. + # (2) It's hard to choose inputs for which the builtin will fail. + seed = b"".join( + map( + to_bytes, + [ + ids.p.x, + ids.p.y, + *memory.get_range(ids.m, n_elms), + *memory.get_range(ids.q.address_, 2 * n_elms), + ], + ) + ) + ids.s.x, ids.s.y = random_ec_point(FIELD_PRIME, ALPHA, BETA, seed) + %} + let p_plus_s: EcPoint = ec_add(p, s); + let r_plus_s: EcPoint = _chained_ec_op_inner(p=p_plus_s, m=m, q=q, len=len); + let r: EcPoint = ec_add(r_plus_s, EcPoint(x=s.x, y=-s.y)); + return (r=r); +} + +func _chained_ec_op_inner{ec_op_ptr: EcOpBuiltin*}( + p: EcPoint, m: felt*, q: EcPoint*, len: felt +) -> (r: EcPoint) { + if (len == 0) { + return (r=p); + } + // (0, 0), representing the point at infinity, is the only point for which y = 0. + if (q.y == 0) { + return _chained_ec_op_inner(p=p, m=&m[1], q=&q[1], len=len - 1); + } + assert ec_op_ptr.p = p; + assert ec_op_ptr.m = m[0]; + assert ec_op_ptr.q = q[0]; + let r = ec_op_ptr.r; + let ec_op_ptr = &ec_op_ptr[1]; + return _chained_ec_op_inner(p=r, m=&m[1], q=&q[1], len=len - 1); +} + +// Recovers the y coordinate of a point on the EC. +// +// Arguments: +// x - the x coordinate of an EC point. +// +// Returns: +// p - one of the two EC points with the given x coordinate (x, y). +// +// Assumptions: +// There exists y such that (x, y) is on the curve. Otherwise the function's hint will throw a +// python exception. +// +// Note: +// This function will fail on x = 0 because there is no such point on the curve. The point at +// infinity is represented as (0, 0), but this is just a representation, not actual coordinates. +func recover_y(x: felt) -> (p: EcPoint) { + alloc_locals; + local p: EcPoint; + %{ + from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME + from starkware.python.math_utils import recover_y + ids.p.x = ids.x + # This raises an exception if `x` is not on the curve. + ids.p.y = recover_y(ids.x, ALPHA, BETA, FIELD_PRIME) + %} + assert p.x = x; + assert_on_curve(p); + return (p=p); +} + +// Checks if `x` represents the x coordinate of a point on the curve. +// +// Arguments: +// x - a field element. +// +// Returns: +// res - TRUE if `x` represents the x coordinate of a point on the curve, FALSE otherwise. +// Note: +// Returns FALSE on x = 0 because there is no such point on the curve. The point at +// infinity is represented as (0, 0), but this is just a representation, not actual coordinates. +func is_x_on_curve(x: felt) -> felt { + return is_quad_residue(x=x * x * x + StarkCurve.ALPHA * x + StarkCurve.BETA); +} diff --git a/src/starkware/cairo/common/ec_point.cairo b/src/starkware/cairo/common/ec_point.cairo index ff812fd4..40be277c 100644 --- a/src/starkware/cairo/common/ec_point.cairo +++ b/src/starkware/cairo/common/ec_point.cairo @@ -1,5 +1,5 @@ -# Represents a point on an elliptic curve. -struct EcPoint: - member x : felt - member y : felt -end +// Represents a point on an elliptic curve. +struct EcPoint { + x: felt, + y: felt, +} diff --git a/src/starkware/cairo/common/find_element.cairo b/src/starkware/cairo/common/find_element.cairo index 4185ee17..c7cf8852 100644 --- a/src/starkware/cairo/common/find_element.cairo +++ b/src/starkware/cairo/common/find_element.cairo @@ -1,31 +1,31 @@ from starkware.cairo.common.math import assert_le, assert_le_felt, assert_nn_le -const FIND_ELEMENT_RANGE_CHECK_USAGE = 2 +const FIND_ELEMENT_RANGE_CHECK_USAGE = 2; -# Finds an element in the array whose first field is key and returns a pointer -# to this element. -# Since cairo is nondeterministic this is an O(1) operation. -# Note however that if the array has multiple elements with said key the function may return any -# of those elements. -# -# Arguments: -# array_ptr - pointer to an array. -# elm_size - size of an element in the array. -# n_elms - number of element in the array. -# key - key to look for. -# -# Implicit arguments: -# range_check_ptr - range check builtin pointer. -# -# Returns: -# elm_ptr - pointer to an element in the array satisfying [ptr] = key. -# -# Optional hint variables: -# __find_element_index - the index that should be returned. If not specified, the function will -# return the first index that has the key. -func find_element{range_check_ptr}(array_ptr : felt*, elm_size, n_elms, key) -> (elm_ptr : felt*): - alloc_locals - local index +// Finds an element in the array whose first field is key and returns a pointer +// to this element. +// Since cairo is nondeterministic this is an O(1) operation. +// Note however that if the array has multiple elements with said key the function may return any +// of those elements. +// +// Arguments: +// array_ptr - pointer to an array. +// elm_size - size of an element in the array. +// n_elms - number of element in the array. +// key - key to look for. +// +// Implicit arguments: +// range_check_ptr - range check builtin pointer. +// +// Returns: +// elm_ptr - pointer to an element in the array satisfying [ptr] = key. +// +// Optional hint variables: +// __find_element_index - the index that should be returned. If not specified, the function will +// return the first index that has the key. +func find_element{range_check_ptr}(array_ptr: felt*, elm_size, n_elms, key) -> (elm_ptr: felt*) { + alloc_locals; + local index; %{ array_ptr = ids.array_ptr elm_size = ids.elm_size @@ -58,21 +58,21 @@ func find_element{range_check_ptr}(array_ptr : felt*, elm_size, n_elms, key) -> raise ValueError(f'Key {key} was not found.') %} - assert_nn_le(a=index, b=n_elms - 1) - tempvar elm_ptr = array_ptr + elm_size * index - assert [elm_ptr] = key - return (elm_ptr=elm_ptr) -end + assert_nn_le(a=index, b=n_elms - 1); + tempvar elm_ptr = array_ptr + elm_size * index; + assert [elm_ptr] = key; + return (elm_ptr=elm_ptr); +} -# Given an array sorted by its first field, returns the pointer to the first element in the array -# whose first field is at least key. If no such item exists, returns a pointer to the end of the -# array. -# Prover assumption: all the keys (the first field in each item) are in [0, RANGE_CHECK_BOUND). -func search_sorted_lower{range_check_ptr}(array_ptr : felt*, elm_size, n_elms, key) -> ( - elm_ptr : felt* -): - alloc_locals - local index +// Given an array sorted by its first field, returns the pointer to the first element in the array +// whose first field is at least key. If no such item exists, returns a pointer to the end of the +// array. +// Prover assumption: all the keys (the first field in each item) are in [0, RANGE_CHECK_BOUND). +func search_sorted_lower{range_check_ptr}(array_ptr: felt*, elm_size, n_elms, key) -> ( + elm_ptr: felt* +) { + alloc_locals; + local index; %{ array_ptr = ids.array_ptr elm_size = ids.elm_size @@ -95,38 +95,38 @@ func search_sorted_lower{range_check_ptr}(array_ptr : felt*, elm_size, n_elms, k ids.index = n_elms %} - assert_nn_le(a=index, b=n_elms) - local elm_ptr : felt* = array_ptr + elm_size * index + assert_nn_le(a=index, b=n_elms); + local elm_ptr: felt* = array_ptr + elm_size * index; - if index != n_elms: - assert_le_felt(a=key, b=[elm_ptr]) - else: - tempvar range_check_ptr = range_check_ptr - end + if (index != n_elms) { + assert_le_felt(a=key, b=[elm_ptr]); + } else { + tempvar range_check_ptr = range_check_ptr; + } - if index != 0: - assert_le_felt(a=[elm_ptr - elm_size] + 1, b=key) - end + if (index != 0) { + assert_le_felt(a=[elm_ptr - elm_size] + 1, b=key); + } - return (elm_ptr=elm_ptr) -end + return (elm_ptr=elm_ptr); +} -# Given an array sorted by its first field, returns the pointer to the first element in the array -# whose first field is exactly key. If no such item exists, returns an undefined pointer, -# and success=0. -# Prover assumption: all the keys (the first field in each item) are in [0, RANGE_CHECK_BOUND). -func search_sorted{range_check_ptr}(array_ptr : felt*, elm_size, n_elms, key) -> ( - elm_ptr : felt*, success : felt -): +// Given an array sorted by its first field, returns the pointer to the first element in the array +// whose first field is exactly key. If no such item exists, returns an undefined pointer, +// and success=0. +// Prover assumption: all the keys (the first field in each item) are in [0, RANGE_CHECK_BOUND). +func search_sorted{range_check_ptr}(array_ptr: felt*, elm_size, n_elms, key) -> ( + elm_ptr: felt*, success: felt +) { let (elm_ptr) = search_sorted_lower( array_ptr=array_ptr, elm_size=elm_size, n_elms=n_elms, key=key - ) - tempvar array_end = array_ptr + elm_size * n_elms - if elm_ptr == array_end: - return (elm_ptr=array_ptr, success=0) - end - if [elm_ptr] != key: - return (elm_ptr=array_ptr, success=0) - end - return (elm_ptr=elm_ptr, success=1) -end + ); + tempvar array_end = array_ptr + elm_size * n_elms; + if (elm_ptr == array_end) { + return (elm_ptr=array_ptr, success=0); + } + if ([elm_ptr] != key) { + return (elm_ptr=array_ptr, success=0); + } + return (elm_ptr=elm_ptr, success=1); +} diff --git a/src/starkware/cairo/common/hash.cairo b/src/starkware/cairo/common/hash.cairo index 47483b88..75a08c5a 100644 --- a/src/starkware/cairo/common/hash.cairo +++ b/src/starkware/cairo/common/hash.cairo @@ -1,19 +1,19 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin -# Computes the hash of two given field elements. -# The hash function is defined by the hash_ptr used. -# For example, pass the pedersen builtin pointer to compute Pedersen hash. -# -# Arguments: -# hash_ptr - the hash builtin pointer. -# x, y - the two field elements to be hashed, in this order. -# -# Returns: -# result - the field element result of the hash. -func hash2{hash_ptr : HashBuiltin*}(x, y) -> (result : felt): - hash_ptr.x = x - hash_ptr.y = y - let result = hash_ptr.result - let hash_ptr = hash_ptr + HashBuiltin.SIZE - return (result=result) -end +// Computes the hash of two given field elements. +// The hash function is defined by the hash_ptr used. +// For example, pass the pedersen builtin pointer to compute Pedersen hash. +// +// Arguments: +// hash_ptr - the hash builtin pointer. +// x, y - the two field elements to be hashed, in this order. +// +// Returns: +// result - the field element result of the hash. +func hash2{hash_ptr: HashBuiltin*}(x, y) -> (result: felt) { + hash_ptr.x = x; + hash_ptr.y = y; + let result = hash_ptr.result; + let hash_ptr = hash_ptr + HashBuiltin.SIZE; + return (result=result); +} diff --git a/src/starkware/cairo/common/hash_chain.cairo b/src/starkware/cairo/common/hash_chain.cairo index b2901a1f..34ab6e1d 100644 --- a/src/starkware/cairo/common/hash_chain.cairo +++ b/src/starkware/cairo/common/hash_chain.cairo @@ -1,47 +1,47 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin -# Computes a hash chain of a sequence whose length is given at [data_ptr] and the data starts at -# data_ptr + 1. The hash is calculated backwards (from the highest memory address to the lowest). -# For example, for the 3-element sequence [x, y, z] the hash is: -# h(3, h(x, h(y, z))) -# If data_length = 0, the function does not return (takes more than field prime steps). -func hash_chain{hash_ptr : HashBuiltin*}(data_ptr : felt*) -> (hash : felt): - struct LoopLocals: - member data_ptr : felt* - member hash_ptr : HashBuiltin* - member cur_hash : felt - end - - tempvar data_length = [data_ptr] - tempvar data_ptr_end = data_ptr + data_length - # Prepare the loop_frame for the first iteration of the hash_loop. +// Computes a hash chain of a sequence whose length is given at [data_ptr] and the data starts at +// data_ptr + 1. The hash is calculated backwards (from the highest memory address to the lowest). +// For example, for the 3-element sequence [x, y, z] the hash is: +// h(3, h(x, h(y, z))) +// If data_length = 0, the function does not return (takes more than field prime steps). +func hash_chain{hash_ptr: HashBuiltin*}(data_ptr: felt*) -> (hash: felt) { + struct LoopLocals { + data_ptr: felt*, + hash_ptr: HashBuiltin*, + cur_hash: felt, + } + + tempvar data_length = [data_ptr]; + tempvar data_ptr_end = data_ptr + data_length; + // Prepare the loop_frame for the first iteration of the hash_loop. tempvar loop_frame = LoopLocals( data_ptr=data_ptr_end, hash_ptr=hash_ptr, - cur_hash=[data_ptr_end]) + cur_hash=[data_ptr_end]); hash_loop: - let curr_frame = cast(ap - LoopLocals.SIZE, LoopLocals*) - let current_hash : HashBuiltin* = curr_frame.hash_ptr + let curr_frame = cast(ap - LoopLocals.SIZE, LoopLocals*); + let current_hash: HashBuiltin* = curr_frame.hash_ptr; - tempvar new_data = [curr_frame.data_ptr - 1] + tempvar new_data = [curr_frame.data_ptr - 1]; - let n_elements_to_hash = [ap] - # Assign current_hash inputs and allocate space for n_elements_to_hash. - current_hash.x = new_data; ap++ - current_hash.y = curr_frame.cur_hash + let n_elements_to_hash = [ap]; + // Assign current_hash inputs and allocate space for n_elements_to_hash. + current_hash.x = new_data, ap++; + current_hash.y = curr_frame.cur_hash; - # Set the frame for the next loop iteration (going backwards). + // Set the frame for the next loop iteration (going backwards). tempvar next_frame = LoopLocals( data_ptr=curr_frame.data_ptr - 1, hash_ptr=curr_frame.hash_ptr + HashBuiltin.SIZE, - cur_hash=current_hash.result) + cur_hash=current_hash.result); - # Update n_elements_to_hash and loop accordingly. Note that the hash is calculated backwards. - n_elements_to_hash = next_frame.data_ptr - data_ptr - jmp hash_loop if n_elements_to_hash != 0 + // Update n_elements_to_hash and loop accordingly. Note that the hash is calculated backwards. + n_elements_to_hash = next_frame.data_ptr - data_ptr; + jmp hash_loop if n_elements_to_hash != 0; - # Set the hash_ptr implicit argument and return the result. - let hash_ptr = next_frame.hash_ptr - return (hash=next_frame.cur_hash) -end + // Set the hash_ptr implicit argument and return the result. + let hash_ptr = next_frame.hash_ptr; + return (hash=next_frame.cur_hash); +} diff --git a/src/starkware/cairo/common/hash_state.cairo b/src/starkware/cairo/common/hash_state.cairo index 86f7a1f4..66eb9aa8 100644 --- a/src/starkware/cairo/common/hash_state.cairo +++ b/src/starkware/cairo/common/hash_state.cairo @@ -2,128 +2,129 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.hash import hash2 from starkware.cairo.common.registers import get_fp_and_pc -# Stores the hash of a sequence of items. New items can be added to the hash state using hash_update -# and hash_update_single. The final hash of the entire sequence, including the sequence length, can -# be extracted using hash_finalize. -# For example, the hash of the sequence (x, y, z) is h(h(h(h(0, x), y), z), 3). -# In particular, the hash of zero items is h(0, 0). -struct HashState: - member current_hash : felt - member n_words : felt -end - -# Initializes a new HashState with no items and returns it. -func hash_init() -> (hash_state_ptr : HashState*): - alloc_locals - let (__fp__, _) = get_fp_and_pc() - local hash_state : HashState - hash_state.current_hash = 0 - hash_state.n_words = 0 - return (hash_state_ptr=&hash_state) -end - -# Adds each item in an array of items to the HashState. -# Returns a new HashState with the hash of the items of the input HashState and the array of items. -# The array is represented by a pointer and a length. -func hash_update{hash_ptr : HashBuiltin*}( - hash_state_ptr : HashState*, data_ptr : felt*, data_length -) -> (new_hash_state_ptr : HashState*): - alloc_locals +// Stores the hash of a sequence of items. New items can be added to the hash state using +// hash_update and hash_update_single. +// The final hash of the entire sequence, including the sequence length, +// can be extracted using hash_finalize. +// For example, the hash of the sequence (x, y, z) is h(h(h(h(0, x), y), z), 3). +// In particular, the hash of zero items is h(0, 0). +struct HashState { + current_hash: felt, + n_words: felt, +} + +// Initializes a new HashState with no items and returns it. +func hash_init() -> (hash_state_ptr: HashState*) { + alloc_locals; + let (__fp__, _) = get_fp_and_pc(); + local hash_state: HashState; + hash_state.current_hash = 0; + hash_state.n_words = 0; + return (hash_state_ptr=&hash_state); +} + +// Adds each item in an array of items to the HashState. +// Returns a new HashState with the hash of the items of the input HashState and the array of items. +// The array is represented by a pointer and a length. +func hash_update{hash_ptr: HashBuiltin*}( + hash_state_ptr: HashState*, data_ptr: felt*, data_length +) -> (new_hash_state_ptr: HashState*) { + alloc_locals; let (hash) = hash_update_inner( data_ptr=data_ptr, data_length=data_length, hash=hash_state_ptr.current_hash - ) - let (__fp__, _) = get_fp_and_pc() - local new_hash_state : HashState - new_hash_state.current_hash = hash - assert new_hash_state.n_words = hash_state_ptr.n_words + data_length - return (new_hash_state_ptr=&new_hash_state) -end - -# Adds a single item to the HashState. -# Returns a new HashState with the hash of the items of the input HashState and the item. -func hash_update_single{hash_ptr : HashBuiltin*}(hash_state_ptr : HashState*, item) -> ( - new_hash_state_ptr : HashState* -): - alloc_locals - let (hash) = hash2(x=hash_state_ptr.current_hash, y=item) - let (__fp__, _) = get_fp_and_pc() - local new_hash_state : HashState - new_hash_state.current_hash = hash - assert new_hash_state.n_words = hash_state_ptr.n_words + 1 - return (new_hash_state_ptr=&new_hash_state) -end - -# Computes the hash of the input data and then calls hash_update_single to add the hash -# of the data to 'hash_state' as a single felt. See details in the documentation of HashState. -func hash_update_with_hashchain{hash_ptr : HashBuiltin*}( - hash_state_ptr : HashState*, data_ptr : felt*, data_length : felt -) -> (new_hash_state_ptr : HashState*): - # Hash data. - let (hash : felt) = hash_felts(data=data_ptr, length=data_length) - - # Update 'hash_state' with the hash of the data. - return hash_update_single(hash_state_ptr=hash_state_ptr, item=hash) -end - -# Returns the hash result of the HashState. -func hash_finalize{hash_ptr : HashBuiltin*}(hash_state_ptr : HashState*) -> (hash : felt): - let (hash) = hash2(x=hash_state_ptr.current_hash, y=hash_state_ptr.n_words) - return (hash=hash) -end - -# A helper function for 'hash_update', see its documentation. -# Computes the hash of an array of items, not including its length. -# The hash is: hash(...hash(hash(data[0], data[1]), data[2])..., data[n-1]). -func hash_update_inner{hash_ptr : HashBuiltin*}( - data_ptr : felt*, data_length : felt, hash : felt -) -> (hash : felt): - if data_length == 0: - return (hash=hash) - end - - # Compute 'data_last_ptr' before entering the loop. - alloc_locals - local data_last_ptr : felt* = data_ptr + data_length - 1 - struct LoopLocals: - member data_ptr : felt* - member hash_ptr : HashBuiltin* - member cur_hash : felt - end - - # Set up first iteration locals. - let first_locals : LoopLocals* = cast(ap, LoopLocals*) - first_locals.data_ptr = data_ptr; ap++ - first_locals.hash_ptr = hash_ptr; ap++ - first_locals.cur_hash = hash; ap++ - - # Do{. + ); + let (__fp__, _) = get_fp_and_pc(); + local new_hash_state: HashState; + new_hash_state.current_hash = hash; + assert new_hash_state.n_words = hash_state_ptr.n_words + data_length; + return (new_hash_state_ptr=&new_hash_state); +} + +// Adds a single item to the HashState. +// Returns a new HashState with the hash of the items of the input HashState and the item. +func hash_update_single{hash_ptr: HashBuiltin*}(hash_state_ptr: HashState*, item) -> ( + new_hash_state_ptr: HashState* +) { + alloc_locals; + let (hash) = hash2(x=hash_state_ptr.current_hash, y=item); + let (__fp__, _) = get_fp_and_pc(); + local new_hash_state: HashState; + new_hash_state.current_hash = hash; + assert new_hash_state.n_words = hash_state_ptr.n_words + 1; + return (new_hash_state_ptr=&new_hash_state); +} + +// Computes the hash of the input data and then calls hash_update_single to add the hash +// of the data to 'hash_state' as a single felt. See details in the documentation of HashState. +func hash_update_with_hashchain{hash_ptr: HashBuiltin*}( + hash_state_ptr: HashState*, data_ptr: felt*, data_length: felt +) -> (new_hash_state_ptr: HashState*) { + // Hash data. + let (hash: felt) = hash_felts(data=data_ptr, length=data_length); + + // Update 'hash_state' with the hash of the data. + return hash_update_single(hash_state_ptr=hash_state_ptr, item=hash); +} + +// Returns the hash result of the HashState. +func hash_finalize{hash_ptr: HashBuiltin*}(hash_state_ptr: HashState*) -> (hash: felt) { + let (hash) = hash2(x=hash_state_ptr.current_hash, y=hash_state_ptr.n_words); + return (hash=hash); +} + +// A helper function for 'hash_update', see its documentation. +// Computes the hash of an array of items, not including its length. +// The hash is: hash(...hash(hash(data[0], data[1]), data[2])..., data[n-1]). +func hash_update_inner{hash_ptr: HashBuiltin*}(data_ptr: felt*, data_length: felt, hash: felt) -> ( + hash: felt +) { + if (data_length == 0) { + return (hash=hash); + } + + // Compute 'data_last_ptr' before entering the loop. + alloc_locals; + local data_last_ptr: felt* = data_ptr + data_length - 1; + struct LoopLocals { + data_ptr: felt*, + hash_ptr: HashBuiltin*, + cur_hash: felt, + } + + // Set up first iteration locals. + let first_locals: LoopLocals* = cast(ap, LoopLocals*); + first_locals.data_ptr = data_ptr, ap++; + first_locals.hash_ptr = hash_ptr, ap++; + first_locals.cur_hash = hash, ap++; + + // Do{. hash_loop: - let prev_locals : LoopLocals* = cast(ap - LoopLocals.SIZE, LoopLocals*) - tempvar n_remaining_elements = data_last_ptr - prev_locals.data_ptr - - # Compute hash(cur_hash, [data_ptr]). - prev_locals.hash_ptr.x = prev_locals.cur_hash - assert prev_locals.hash_ptr.y = [prev_locals.data_ptr] # Allocates one memory cell. - - # Set up next iteration locals. - let next_locals : LoopLocals* = cast(ap, LoopLocals*) - next_locals.data_ptr = prev_locals.data_ptr + 1; ap++ - next_locals.hash_ptr = prev_locals.hash_ptr + HashBuiltin.SIZE; ap++ - next_locals.cur_hash = prev_locals.hash_ptr.result; ap++ - - # } while(n_remaining_elements != 0). - jmp hash_loop if n_remaining_elements != 0 - - # Return values from final iteration. - let final_locals : LoopLocals* = cast(ap - LoopLocals.SIZE, LoopLocals*) - let hash_ptr = final_locals.hash_ptr - return (hash=final_locals.cur_hash) -end - -func hash_felts{hash_ptr : HashBuiltin*}(data : felt*, length : felt) -> (hash : felt): - let (hash_state_ptr : HashState*) = hash_init() + let prev_locals: LoopLocals* = cast(ap - LoopLocals.SIZE, LoopLocals*); + tempvar n_remaining_elements = data_last_ptr - prev_locals.data_ptr; + + // Compute hash(cur_hash, [data_ptr]). + prev_locals.hash_ptr.x = prev_locals.cur_hash; + assert prev_locals.hash_ptr.y = [prev_locals.data_ptr]; // Allocates one memory cell. + + // Set up next iteration locals. + let next_locals: LoopLocals* = cast(ap, LoopLocals*); + next_locals.data_ptr = prev_locals.data_ptr + 1, ap++; + next_locals.hash_ptr = prev_locals.hash_ptr + HashBuiltin.SIZE, ap++; + next_locals.cur_hash = prev_locals.hash_ptr.result, ap++; + + // } while(n_remaining_elements != 0). + jmp hash_loop if n_remaining_elements != 0; + + // Return values from final iteration. + let final_locals: LoopLocals* = cast(ap - LoopLocals.SIZE, LoopLocals*); + let hash_ptr = final_locals.hash_ptr; + return (hash=final_locals.cur_hash); +} + +func hash_felts{hash_ptr: HashBuiltin*}(data: felt*, length: felt) -> (hash: felt) { + let (hash_state_ptr: HashState*) = hash_init(); let (hash_state_ptr) = hash_update( hash_state_ptr=hash_state_ptr, data_ptr=data, data_length=length - ) - return hash_finalize(hash_state_ptr=hash_state_ptr) -end + ); + return hash_finalize(hash_state_ptr=hash_state_ptr); +} diff --git a/src/starkware/cairo/common/invoke.cairo b/src/starkware/cairo/common/invoke.cairo index f82ba42c..61a92b73 100644 --- a/src/starkware/cairo/common/invoke.cairo +++ b/src/starkware/cairo/common/invoke.cairo @@ -1,21 +1,21 @@ -# Calls func_ptr(args[0], args[1], ..., args[n_args - 1]) and forwards its return value. -# In order to convert a label to pc and use it as a value for the func_ptr argument, -# use get_label_location(). -func invoke(func_ptr : felt*, n_args : felt, args : felt*): - invoke_prepare_args(args_end=args + n_args, n_args=n_args) - call abs func_ptr - ret -end +// Calls func_ptr(args[0], args[1], ..., args[n_args - 1]) and forwards its return value. +// In order to convert a label to pc and use it as a value for the func_ptr argument, +// use get_label_location(). +func invoke(func_ptr: felt*, n_args: felt, args: felt*) { + invoke_prepare_args(args_end=args + n_args, n_args=n_args); + call abs func_ptr; + ret; +} -# Helper function for invoke(). -# Copies the memory range [args_end - n_args, args_end) to the memory range -# [final_ap - n_args, final_ap) where final_ap is the value of ap when the function returns. -func invoke_prepare_args(args_end : felt*, n_args : felt): - if n_args == 0: - return () - end +// Helper function for invoke(). +// Copies the memory range [args_end - n_args, args_end) to the memory range +// [final_ap - n_args, final_ap) where final_ap is the value of ap when the function returns. +func invoke_prepare_args(args_end: felt*, n_args: felt) { + if (n_args == 0) { + return (); + } - invoke_prepare_args(args_end=args_end - 1, n_args=n_args - 1) - [ap] = [args_end - 1]; ap++ - return () -end + invoke_prepare_args(args_end=args_end - 1, n_args=n_args - 1); + [ap] = [args_end - 1], ap++; + return (); +} diff --git a/src/starkware/cairo/common/keccak.cairo b/src/starkware/cairo/common/keccak.cairo index c1cd3337..f38c443f 100644 --- a/src/starkware/cairo/common/keccak.cairo +++ b/src/starkware/cairo/common/keccak.cairo @@ -2,17 +2,17 @@ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.math import split_felt, unsigned_div_rem from starkware.cairo.common.uint256 import Uint256 -# Computes the keccak hash. -# This function is unsafe (not sound): there is no validity enforcement that the result is indeed -# keccak, but an honest prover will compute the keccak. -# Args: -# data - an array of words representing the input data. Each word in the array is 16 bytes of the -# input data, except the last word, which may be less. -# length - the number of bytes in the input. -func unsafe_keccak(data : felt*, length : felt) -> (low : felt, high : felt): - alloc_locals - local low - local high +// Computes the keccak hash. +// This function is unsafe (not sound): there is no validity enforcement that the result is indeed +// keccak, but an honest prover will compute the keccak. +// Args: +// data - an array of words representing the input data. Each word in the array is 16 bytes of the +// input data, except the last word, which may be less. +// length - the number of bytes in the input. +func unsafe_keccak(data: felt*, length: felt) -> (low: felt, high: felt) { + alloc_locals; + local low; + local high; %{ from eth_hash.auto import keccak @@ -34,50 +34,50 @@ func unsafe_keccak(data : felt*, length : felt) -> (low : felt, high : felt): ids.high = int.from_bytes(hashed[:16], 'big') ids.low = int.from_bytes(hashed[16:32], 'big') %} - return (low=low, high=high) -end + return (low=low, high=high); +} -struct KeccakState: - member start_ptr : felt* - member end_ptr : felt* -end +struct KeccakState { + start_ptr: felt*, + end_ptr: felt*, +} -func unsafe_keccak_init() -> (res : KeccakState): - let (ptr) = alloc() - return (res=KeccakState(ptr, ptr)) -end +func unsafe_keccak_init() -> (res: KeccakState) { + let (ptr) = alloc(); + return (res=KeccakState(ptr, ptr)); +} -func unsafe_keccak_add_felt{keccak_state : KeccakState, range_check_ptr}(num : felt) -> (): - let (high, low) = split_felt(num) - keccak_state.end_ptr[0] = high - keccak_state.end_ptr[1] = low - let keccak_state = KeccakState(keccak_state.start_ptr, keccak_state.end_ptr + 2) - return () -end +func unsafe_keccak_add_felt{keccak_state: KeccakState, range_check_ptr}(num: felt) -> () { + let (high, low) = split_felt(num); + keccak_state.end_ptr[0] = high; + keccak_state.end_ptr[1] = low; + let keccak_state = KeccakState(keccak_state.start_ptr, keccak_state.end_ptr + 2); + return (); +} -func unsafe_keccak_add_uint256{keccak_state : KeccakState, range_check_ptr}(num : Uint256) -> (): - keccak_state.end_ptr[0] = num.high - keccak_state.end_ptr[1] = num.low - let keccak_state = KeccakState(keccak_state.start_ptr, keccak_state.end_ptr + 2) - return () -end +func unsafe_keccak_add_uint256{keccak_state: KeccakState, range_check_ptr}(num: Uint256) -> () { + keccak_state.end_ptr[0] = num.high; + keccak_state.end_ptr[1] = num.low; + let keccak_state = KeccakState(keccak_state.start_ptr, keccak_state.end_ptr + 2); + return (); +} -func unsafe_keccak_add_felts{keccak_state : KeccakState, range_check_ptr}( - n_elements : felt, elements : felt* -) -> (): - if n_elements == 0: - return () - end - unsafe_keccak_add_felt([elements]) - return unsafe_keccak_add_felts(n_elements=n_elements - 1, elements=elements + 1) -end +func unsafe_keccak_add_felts{keccak_state: KeccakState, range_check_ptr}( + n_elements: felt, elements: felt* +) -> () { + if (n_elements == 0) { + return (); + } + unsafe_keccak_add_felt([elements]); + return unsafe_keccak_add_felts(n_elements=n_elements - 1, elements=elements + 1); +} -# This function is unsafe (not sound): there is no validity enforcement that the result is indeed -# keccak, but an honest prover will compute the keccak. -func unsafe_keccak_finalize(keccak_state : KeccakState) -> (res : Uint256): - alloc_locals - local low - local high +// This function is unsafe (not sound): there is no validity enforcement that the result is indeed +// keccak, but an honest prover will compute the keccak. +func unsafe_keccak_finalize(keccak_state: KeccakState) -> (res: Uint256) { + alloc_locals; + local low; + local high; %{ from eth_hash.auto import keccak keccak_input = bytearray() @@ -88,27 +88,27 @@ func unsafe_keccak_finalize(keccak_state : KeccakState) -> (res : Uint256): ids.high = int.from_bytes(hashed[:16], 'big') ids.low = int.from_bytes(hashed[16:32], 'big') %} - return (res=Uint256(low=low, high=high)) -end + return (res=Uint256(low=low, high=high)); +} -func keccak_felts{range_check_ptr}(n_elements : felt, elements : felt*) -> (res : Uint256): - let (keccak_state) = unsafe_keccak_init() - unsafe_keccak_add_felts{keccak_state=keccak_state}(n_elements=n_elements, elements=elements) - let (res) = unsafe_keccak_finalize(keccak_state=keccak_state) - return (res=res) -end +func keccak_felts{range_check_ptr}(n_elements: felt, elements: felt*) -> (res: Uint256) { + let (keccak_state) = unsafe_keccak_init(); + unsafe_keccak_add_felts{keccak_state=keccak_state}(n_elements=n_elements, elements=elements); + let (res) = unsafe_keccak_finalize(keccak_state=keccak_state); + return (res=res); +} -# A 160 msb truncated version of keccak, where each value is assumed to also be a truncated -# hash: -# keccak(x << 96, y << 96) >> 96 -func truncated_keccak2{range_check_ptr}(x : felt, y : felt) -> (res : felt): - let (state) = unsafe_keccak_init() +// A 160 msb truncated version of keccak, where each value is assumed to also be a truncated +// hash: +// keccak(x << 96, y << 96) >> 96. +func truncated_keccak2{range_check_ptr}(x: felt, y: felt) -> (res: felt) { + let (state) = unsafe_keccak_init(); - let (xhigh, xlow) = unsigned_div_rem(x, 2 ** 32) - let (yhigh, ylow) = unsigned_div_rem(y, 2 ** 32) - unsafe_keccak_add_uint256{keccak_state=state}(num=Uint256(low=xlow * 2 ** 96, high=xhigh)) - unsafe_keccak_add_uint256{keccak_state=state}(num=Uint256(low=ylow * 2 ** 96, high=yhigh)) - let (hash) = unsafe_keccak_finalize(keccak_state=state) - let (low_h, low_l) = unsigned_div_rem(hash.low, 2 ** 96) - return (res=hash.high * 2 ** 32 + low_h) -end + let (xhigh, xlow) = unsigned_div_rem(x, 2 ** 32); + let (yhigh, ylow) = unsigned_div_rem(y, 2 ** 32); + unsafe_keccak_add_uint256{keccak_state=state}(num=Uint256(low=xlow * 2 ** 96, high=xhigh)); + unsafe_keccak_add_uint256{keccak_state=state}(num=Uint256(low=ylow * 2 ** 96, high=yhigh)); + let (hash) = unsafe_keccak_finalize(keccak_state=state); + let (low_h, low_l) = unsigned_div_rem(hash.low, 2 ** 96); + return (res=hash.high * 2 ** 32 + low_h); +} diff --git a/src/starkware/cairo/common/keccak_state.cairo b/src/starkware/cairo/common/keccak_state.cairo new file mode 100644 index 00000000..4e8f9d79 --- /dev/null +++ b/src/starkware/cairo/common/keccak_state.cairo @@ -0,0 +1,11 @@ +// Represents 1600 bits of a Keccak state (8 felts each containing 200 bits). +struct KeccakBuiltinState { + s0: felt, + s1: felt, + s2: felt, + s3: felt, + s4: felt, + s5: felt, + s6: felt, + s7: felt, +} diff --git a/src/starkware/cairo/common/math.cairo b/src/starkware/cairo/common/math.cairo index 8003694b..5fb68bbd 100644 --- a/src/starkware/cairo/common/math.cairo +++ b/src/starkware/cairo/common/math.cairo @@ -1,22 +1,24 @@ -# Inline functions with no locals. +from starkware.cairo.common.bool import FALSE, TRUE -# Verifies that value != 0. The proof will fail otherwise. -func assert_not_zero(value): +// Inline functions with no locals. + +// Verifies that value != 0. The proof will fail otherwise. +func assert_not_zero(value) { %{ from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.value) assert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.' %} - if value == 0: - # If value == 0, add an unsatisfiable requirement. - value = 1 - end + if (value == 0) { + // If value == 0, add an unsatisfiable requirement. + value = 1; + } - return () -end + return (); +} -# Verifies that a != b. The proof will fail otherwise. -func assert_not_equal(a, b): +// Verifies that a != b. The proof will fail otherwise. +func assert_not_equal(a, b) { %{ from starkware.cairo.lang.vm.relocatable import RelocatableValue both_ints = isinstance(ids.a, int) and isinstance(ids.b, int) @@ -27,70 +29,70 @@ func assert_not_equal(a, b): f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.' assert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.' %} - if a == b: - # If a == b, add an unsatisfiable requirement. - a = a + 1 - end + if (a == b) { + // If a == b, add an unsatisfiable requirement. + a = a + 1; + } - return () -end + return (); +} -# Verifies that a >= 0 (or more precisely 0 <= a < RANGE_CHECK_BOUND). -func assert_nn{range_check_ptr}(a): +// Verifies that a >= 0 (or more precisely 0 <= a < RANGE_CHECK_BOUND). +func assert_nn{range_check_ptr}(a) { %{ from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.a) assert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.' %} - a = [range_check_ptr] - let range_check_ptr = range_check_ptr + 1 - return () -end - -# Verifies that a <= b (or more precisely 0 <= b - a < RANGE_CHECK_BOUND). -func assert_le{range_check_ptr}(a, b): - assert_nn(b - a) - return () -end - -# Verifies that a <= b - 1 (or more precisely 0 <= b - 1 - a < RANGE_CHECK_BOUND). -func assert_lt{range_check_ptr}(a, b): - assert_le(a, b - 1) - return () -end - -# Verifies that 0 <= a <= b. -# -# Prover assumption: b < RANGE_CHECK_BOUND. -# -# This function is still sound without the prover assumptions. In that case, it is guaranteed -# that a < RANGE_CHECK_BOUND and b < 2 * RANGE_CHECK_BOUND. -func assert_nn_le{range_check_ptr}(a, b): - assert_nn(a) - assert_le(a, b) - return () -end - -# Asserts that value is in the range [lower, upper). -# Or more precisely: -# (0 <= value - lower < RANGE_CHECK_BOUND) and (0 <= upper - 1 - value < RANGE_CHECK_BOUND). -# -# Prover assumption: 0 <= upper - lower <= RANGE_CHECK_BOUND. -func assert_in_range{range_check_ptr}(value, lower, upper): - assert_le(lower, value) - assert_le(value, upper - 1) - return () -end - -# Asserts that 'value' is in the range [0, 2**250). + a = [range_check_ptr]; + let range_check_ptr = range_check_ptr + 1; + return (); +} + +// Verifies that a <= b (or more precisely 0 <= b - a < RANGE_CHECK_BOUND). +func assert_le{range_check_ptr}(a, b) { + assert_nn(b - a); + return (); +} + +// Verifies that a <= b - 1 (or more precisely 0 <= b - 1 - a < RANGE_CHECK_BOUND). +func assert_lt{range_check_ptr}(a, b) { + assert_le(a, b - 1); + return (); +} + +// Verifies that 0 <= a <= b. +// +// Prover assumption: b < RANGE_CHECK_BOUND. +// +// This function is still sound without the prover assumptions. In that case, it is guaranteed +// that a < RANGE_CHECK_BOUND and b < 2 * RANGE_CHECK_BOUND. +func assert_nn_le{range_check_ptr}(a, b) { + assert_nn(a); + assert_le(a, b); + return (); +} + +// Asserts that value is in the range [lower, upper). +// Or more precisely: +// (0 <= value - lower < RANGE_CHECK_BOUND) and (0 <= upper - 1 - value < RANGE_CHECK_BOUND). +// +// Prover assumption: 0 <= upper - lower <= RANGE_CHECK_BOUND. +func assert_in_range{range_check_ptr}(value, lower, upper) { + assert_le(lower, value); + assert_le(value, upper - 1); + return (); +} + +// Asserts that 'value' is in the range [0, 2**250). @known_ap_change -func assert_250_bit{range_check_ptr}(value): - const UPPER_BOUND = 2 ** 250 - const SHIFT = 2 ** 128 - const HIGH_BOUND = UPPER_BOUND / SHIFT +func assert_250_bit{range_check_ptr}(value) { + const UPPER_BOUND = 2 ** 250; + const SHIFT = 2 ** 128; + const HIGH_BOUND = UPPER_BOUND / SHIFT; - let low = [range_check_ptr] - let high = [range_check_ptr + 1] + let low = [range_check_ptr]; + let high = [range_check_ptr + 1]; %{ from starkware.cairo.common.math_utils import as_int @@ -103,31 +105,31 @@ func assert_250_bit{range_check_ptr}(value): ids.high, ids.low = divmod(ids.value, ids.SHIFT) %} - assert [range_check_ptr + 2] = HIGH_BOUND - 1 - high + assert [range_check_ptr + 2] = HIGH_BOUND - 1 - high; - # The assert below guarantees that - # value = high * SHIFT + low <= (HIGH_BOUND - 1) * SHIFT + 2**128 - 1 = - # HIGH_BOUND * SHIFT - SHIFT + SHIFT - 1 = 2**250 - 1. - assert value = high * SHIFT + low + // The assert below guarantees that + // value = high * SHIFT + low <= (HIGH_BOUND - 1) * SHIFT + 2**128 - 1 = + // HIGH_BOUND * SHIFT - SHIFT + SHIFT - 1 = 2**250 - 1. + assert value = high * SHIFT + low; - let range_check_ptr = range_check_ptr + 3 - return () -end + let range_check_ptr = range_check_ptr + 3; + return (); +} -# Splits the unsigned integer lift of a field element into the higher 128 bit and lower 128 bit. -# The unsigned integer lift is the unique integer in the range [0, PRIME) that represents the field -# element. -# For example, if value=17 * 2^128 + 8, then high=17 and low=8. +// Splits the unsigned integer lift of a field element into the higher 128 bit and lower 128 bit. +// The unsigned integer lift is the unique integer in the range [0, PRIME) that represents the field +// element. +// For example, if value=17 * 2^128 + 8, then high=17 and low=8. @known_ap_change -func split_felt{range_check_ptr}(value) -> (high : felt, low : felt): - # Note: the following code works because PRIME - 1 is divisible by 2**128. - const MAX_HIGH = (-1) / 2 ** 128 - const MAX_LOW = 0 +func split_felt{range_check_ptr}(value) -> (high: felt, low: felt) { + // Note: the following code works because PRIME - 1 is divisible by 2**128. + const MAX_HIGH = (-1) / 2 ** 128; + const MAX_LOW = 0; - # Guess the low and high parts of the integer. - let low = [range_check_ptr] - let high = [range_check_ptr + 1] - let range_check_ptr = range_check_ptr + 2 + // Guess the low and high parts of the integer. + let low = [range_check_ptr]; + let high = [range_check_ptr + 1]; + let range_check_ptr = range_check_ptr + 2; %{ from starkware.cairo.common.math_utils import assert_integer @@ -137,23 +139,31 @@ func split_felt{range_check_ptr}(value) -> (high : felt, low : felt): ids.low = ids.value & ((1 << 128) - 1) ids.high = ids.value >> 128 %} - assert value = high * (2 ** 128) + low - if high == MAX_HIGH: - assert_le(low, MAX_LOW) - else: - assert_le(high, MAX_HIGH - 1) - end - return (high=high, low=low) -end - -# Asserts that the unsigned integer lift (as a number in the range [0, PRIME)) of a is lower than -# or equal to that of b. -# See split_felt() for more details. + assert value = high * (2 ** 128) + low; + if (high == MAX_HIGH) { + assert_le(low, MAX_LOW); + } else { + assert_le(high, MAX_HIGH - 1); + } + return (high=high, low=low); +} + +// Asserts that the unsigned integer lift (as a number in the range [0, PRIME)) of a is lower than +// or equal to that of b. @known_ap_change -func assert_le_felt{range_check_ptr}(a, b): - alloc_locals - local small_inputs +func assert_le_felt{range_check_ptr}(a, b) { + // ceil(PRIME / 3 / 2 ** 128). + const PRIME_OVER_3_HIGH = 0x2aaaaaaaaaaaab05555555555555556; + // ceil(PRIME / 2 / 2 ** 128). + const PRIME_OVER_2_HIGH = 0x4000000000000088000000000000001; + // The numbers [0, a, b, PRIME - 1] should be ordered. To prove that, we show that two of the + // 3 arcs {0 -> a, a -> b, b -> PRIME - 1} are small: + // One is less than PRIME / 3 + 2 ** 129. + // Another is less than PRIME / 2 + 2 ** 129. + // Since the sum of the lengths of these two arcs is less than PRIME, there is no wrap-around. %{ + import itertools + from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.a) assert_integer(ids.b) @@ -161,30 +171,56 @@ func assert_le_felt{range_check_ptr}(a, b): b = ids.b % PRIME assert a <= b, f'a = {a} is not less than or equal to b = {b}.' - ids.small_inputs = int( - a < range_check_builtin.bound and (b - a) < range_check_builtin.bound) + # Find an arc less than PRIME / 3, and another less than PRIME / 2. + lengths_and_indices = [(a, 0), (b - a, 1), (PRIME - 1 - b, 2)] + lengths_and_indices.sort() + assert lengths_and_indices[0][0] <= PRIME // 3 and lengths_and_indices[1][0] <= PRIME // 2 + excluded = lengths_and_indices[2][1] + + memory[ids.range_check_ptr + 1], memory[ids.range_check_ptr + 0] = ( + divmod(lengths_and_indices[0][0], ids.PRIME_OVER_3_HIGH)) + memory[ids.range_check_ptr + 3], memory[ids.range_check_ptr + 2] = ( + divmod(lengths_and_indices[1][0], ids.PRIME_OVER_2_HIGH)) %} - if small_inputs != 0: - assert_nn_le(a, b) - ap += 33 - return () - end - - let (local a_high, local a_low) = split_felt(a) - let (b_high, b_low) = split_felt(b) - - if a_high == b_high: - assert_le(a_low, b_low) - return () - end - assert_le(a_high, b_high) - return () -end - -# Asserts that the unsigned integer lift (as a number in the range [0, PRIME)) of a is lower than -# that of b. + // Guess two arc lengths. + tempvar arc_short = [range_check_ptr] + [range_check_ptr + 1] * PRIME_OVER_3_HIGH; + tempvar arc_long = [range_check_ptr + 2] + [range_check_ptr + 3] * PRIME_OVER_2_HIGH; + let range_check_ptr = range_check_ptr + 4; + + // First, choose which arc to exclude from {0 -> a, a -> b, b -> PRIME - 1}. + // Then, to compare the set of two arc lengths, compare their sum and product. + let arc_sum = arc_short + arc_long; + let arc_prod = arc_short * arc_long; + + // Exclude "0 -> a". + %{ memory[ap] = 1 if excluded != 0 else 0 %} + jmp skip_exclude_a if [ap] != 0, ap++; + assert arc_sum = (-1) - a; + assert arc_prod = (a - b) * (1 + b); + return (); + + // Exclude "a -> b". + skip_exclude_a: + %{ memory[ap] = 1 if excluded != 1 else 0 %} + jmp skip_exclude_b_minus_a if [ap] != 0, ap++; + tempvar m1mb = (-1) - b; + assert arc_sum = a + m1mb; + assert arc_prod = a * m1mb; + return (); + + // Exclude "b -> PRIME - 1". + skip_exclude_b_minus_a: + %{ assert excluded == 2 %} + assert arc_sum = b; + assert arc_prod = a * (b - a); + ap += 2; + return (); +} + +// Asserts that the unsigned integer lift (as a number in the range [0, PRIME)) of a is lower than +// that of b. @known_ap_change -func assert_lt_felt{range_check_ptr}(a, b): +func assert_lt_felt{range_check_ptr}(a, b) { %{ from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.a) @@ -192,76 +228,76 @@ func assert_lt_felt{range_check_ptr}(a, b): assert (ids.a % PRIME) < (ids.b % PRIME), \ f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.' %} - alloc_locals - let (local a_high, local a_low) = split_felt(a) - let (b_high, b_low) = split_felt(b) - - if a_high == b_high: - assert_lt(a_low, b_low) - return () - end - assert_lt(a_high, b_high) - return () -end - -# Returns the absolute value of value. -# Prover asumption: -rc_bound < value < rc_bound. -func abs_value{range_check_ptr}(value) -> (abs_value : felt): - tempvar is_positive : felt + if (a == b) { + // If a == b, add an unsatisfiable requirement. + a = a + 1; + } + assert_le_felt(a, b); + return (); +} + +// Returns the absolute value of value. +// Prover asumption: -rc_bound < value < rc_bound. +@known_ap_change +func abs_value{range_check_ptr}(value) -> felt { + tempvar is_positive: felt; %{ from starkware.cairo.common.math_utils import is_positive ids.is_positive = 1 if is_positive( value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0 %} - if is_positive == 0: - tempvar new_range_check_ptr = range_check_ptr + 1 - tempvar abs_value = value * (-1) - [range_check_ptr] = abs_value - let range_check_ptr = new_range_check_ptr - return (abs_value=abs_value) - else: - [range_check_ptr] = value - let range_check_ptr = range_check_ptr + 1 - return (abs_value=value) - end -end - -# Returns the sign of value: -1, 0 or 1. -# Prover asumption: -rc_bound < value < rc_bound. -func sign{range_check_ptr}(value) -> (sign : felt): - if value == 0: - return (sign=0) - end - - tempvar is_positive : felt + if (is_positive == 0) { + tempvar new_range_check_ptr = range_check_ptr + 1; + tempvar abs_value = value * (-1); + [range_check_ptr] = abs_value; + let range_check_ptr = new_range_check_ptr; + return abs_value; + } else { + [range_check_ptr] = value; + let range_check_ptr = range_check_ptr + 1; + return value; + } +} + +// Returns the sign of value: -1, 0 or 1. +// Prover asumption: -rc_bound < value < rc_bound. +@known_ap_change +func sign{range_check_ptr}(value) -> felt { + if (value == 0) { + ap += 2; + return 0; + } + + tempvar is_positive: felt; %{ from starkware.cairo.common.math_utils import is_positive ids.is_positive = 1 if is_positive( value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0 %} - if is_positive == 0: - assert [range_check_ptr] = value * (-1) - let range_check_ptr = range_check_ptr + 1 - return (sign=-1) - else: - [range_check_ptr] = value - let range_check_ptr = range_check_ptr + 1 - return (sign=1) - end -end - -# Returns q and r such that: -# 0 <= q < rc_bound, 0 <= r < div and value = q * div + r. -# -# Assumption: 0 < div <= PRIME / rc_bound. -# Prover assumption: value / div < rc_bound. -# -# The value of div is restricted to make sure there is no overflow. -# q * div + r < (q + 1) * div <= rc_bound * (PRIME / rc_bound) = PRIME. -func unsigned_div_rem{range_check_ptr}(value, div) -> (q : felt, r : felt): - let r = [range_check_ptr] - let q = [range_check_ptr + 1] - let range_check_ptr = range_check_ptr + 2 + if (is_positive == 0) { + assert [range_check_ptr] = value * (-1); + let range_check_ptr = range_check_ptr + 1; + return -1; + } else { + ap += 1; + [range_check_ptr] = value; + let range_check_ptr = range_check_ptr + 1; + return 1; + } +} + +// Returns q and r such that: +// 0 <= q < rc_bound, 0 <= r < div and value = q * div + r. +// +// Assumption: 0 < div <= PRIME / rc_bound. +// Prover assumption: value / div < rc_bound. +// +// The value of div is restricted to make sure there is no overflow. +// q * div + r < (q + 1) * div <= rc_bound * (PRIME / rc_bound) = PRIME. +func unsigned_div_rem{range_check_ptr}(value, div) -> (q: felt, r: felt) { + let r = [range_check_ptr]; + let q = [range_check_ptr + 1]; + let range_check_ptr = range_check_ptr + 2; %{ from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.div) @@ -269,27 +305,27 @@ func unsigned_div_rem{range_check_ptr}(value, div) -> (q : felt, r : felt): f'div={hex(ids.div)} is out of the valid range.' ids.q, ids.r = divmod(ids.value, ids.div) %} - assert_le(r, div - 1) - - assert value = q * div + r - return (q, r) -end - -# Returns q and r such that. -bound <= q < bound, 0 <= r < div and value = q * div + r. -# value < PRIME / 2 is considered positive and value > PRIME / 2 is considered negative. -# -# Assumptions: -# 0 < div <= PRIME / (rc_bound) -# bound <= rc_bound / 2. -# Prover assumption: -bound <= value / div < bound. -# -# The values of div and bound are restricted to make sure there is no overflow. -# q * div + r < (q + 1) * div <= rc_bound / 2 * (PRIME / rc_bound) -# q * div + r >= q * div >= -rc_bound / 2 * (PRIME / rc_bound) -func signed_div_rem{range_check_ptr}(value, div, bound) -> (q : felt, r : felt): - let r = [range_check_ptr] - let biased_q = [range_check_ptr + 1] # == q + bound. - let range_check_ptr = range_check_ptr + 2 + assert_le(r, div - 1); + + assert value = q * div + r; + return (q, r); +} + +// Returns q and r such that. -bound <= q < bound, 0 <= r < div and value = q * div + r. +// value < PRIME / 2 is considered positive and value > PRIME / 2 is considered negative. +// +// Assumptions: +// 0 < div <= PRIME / (rc_bound) +// bound <= rc_bound / 2. +// Prover assumption: -bound <= value / div < bound. +// +// The values of div and bound are restricted to make sure there is no overflow. +// q * div + r < (q + 1) * div <= rc_bound / 2 * (PRIME / rc_bound) +// q * div + r >= q * div >= -rc_bound / 2 * (PRIME / rc_bound). +func signed_div_rem{range_check_ptr}(value, div, bound) -> (q: felt, r: felt) { + let r = [range_check_ptr]; + let biased_q = [range_check_ptr + 1]; // == q + bound. + let range_check_ptr = range_check_ptr + 2; %{ from starkware.cairo.common.math_utils import as_int, assert_integer @@ -309,46 +345,47 @@ func signed_div_rem{range_check_ptr}(value, div, bound) -> (q : felt, r : felt): ids.biased_q = q + ids.bound %} - let q = biased_q - bound - assert value = q * div + r - assert_le(r, div - 1) - assert_le(biased_q, 2 * bound - 1) - return (q, r) -end - -# Splits the given (unsigned) value into n "limbs", where each limb is in the range [0, bound), -# as follows: -# value = x[0] + x[1] * base + x[2] * base**2 + ... + x[n - 1] * base**(n - 1). -# bound must be less than the range check bound (2**128). -# Note that bound may be smaller than base, in which case the function will fail if there is a -# limb which is >= bound. -# Assumptions: -# 1 < bound <= base -# base**n < field characteristic. -func split_int{range_check_ptr}(value, n, base, bound, output : felt*): - if n == 0: + let q = biased_q - bound; + assert value = q * div + r; + assert_le(r, div - 1); + assert_le(biased_q, 2 * bound - 1); + return (q, r); +} + +// Splits the given (unsigned) value into n "limbs", where each limb is in the range [0, bound), +// as follows: +// value = x[0] + x[1] * base + x[2] * base**2 + ... + x[n - 1] * base**(n - 1). +// bound must be less than the range check bound (2**128). +// Note that bound may be smaller than base, in which case the function will fail if there is a +// limb which is >= bound. +// Assumptions: +// 1 < bound <= base +// base**n < field characteristic. +func split_int{range_check_ptr}(value, n, base, bound, output: felt*) { + if (n == 0) { %{ assert ids.value == 0, 'split_int(): value is out of range.' %} - assert value = 0 - return () - end + assert value = 0; + return (); + } %{ memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base assert res < ids.bound, f'split_int(): Limb {res} is out of range.' %} - tempvar low_part = [output] - assert_nn_le(low_part, bound - 1) + tempvar low_part = [output]; + assert_nn_le(low_part, bound - 1); return split_int( value=(value - low_part) / base, n=n - 1, base=base, bound=bound, output=output + 1 - ) -end + ); +} -# Returns the floor value of the square root of the given value. -# Assumptions: 0 <= value < 2**250. -func sqrt{range_check_ptr}(value) -> (res : felt): - alloc_locals - local root : felt +// Returns the floor value of the square root of the given value. +// Assumptions: 0 <= value < 2**250. +@known_ap_change +func sqrt{range_check_ptr}(value) -> felt { + alloc_locals; + local root: felt; %{ from starkware.python.math_utils import isqrt @@ -358,21 +395,51 @@ func sqrt{range_check_ptr}(value) -> (res : felt): ids.root = isqrt(value) %} - assert_nn_le(root, 2 ** 125 - 1) - tempvar root_plus_one = root + 1 - assert_in_range(value, root * root, root_plus_one * root_plus_one) + assert_nn_le(root, 2 ** 125 - 1); + tempvar root_plus_one = root + 1; + assert_in_range(value, root * root, root_plus_one * root_plus_one); - return (res=root) -end + return root; +} -# Computes the evaluation of a polynomial on the given point. -func horner_eval(n_coefficients : felt, coefficients : felt*, point : felt) -> (res : felt): - if n_coefficients == 0: - return (res=0) - end +// Computes the evaluation of a polynomial on the given point. +func horner_eval(n_coefficients: felt, coefficients: felt*, point: felt) -> (res: felt) { + if (n_coefficients == 0) { + return (res=0); + } let (n_minus_one_res) = horner_eval( n_coefficients=n_coefficients - 1, coefficients=&coefficients[1], point=point - ) - return (res=n_minus_one_res * point + [coefficients]) -end + ); + return (res=n_minus_one_res * point + coefficients[0]); +} + +// Returns TRUE if `x` is a quadratic residue modulo the STARK prime. Returns FALSE otherwise. +// Returns TRUE on 0. +@known_ap_change +func is_quad_residue(x: felt) -> felt { + alloc_locals; + local y; + %{ + from starkware.crypto.signature.signature import FIELD_PRIME + from starkware.python.math_utils import div_mod, is_quad_residue, sqrt + + x = ids.x + if is_quad_residue(x, FIELD_PRIME): + ids.y = sqrt(x, FIELD_PRIME) + else: + ids.y = sqrt(div_mod(x, 3, FIELD_PRIME), FIELD_PRIME) + %} + // Relies on the fact that 3 is not a quadratic residue modulo the prime, so for every field + // element x, either: + // * x is a quadratic residue and there exists y such that y^2 = x. + // * x is not a quadratic residue and there exists y such that 3 * y^2 = x. + tempvar y_squared = y * y; + if (y_squared == x) { + ap += 1; + return TRUE; + } else { + assert 3 * y_squared = x; + return FALSE; + } +} diff --git a/src/starkware/cairo/common/math_cmp.cairo b/src/starkware/cairo/common/math_cmp.cairo index ed03348d..e903e05a 100644 --- a/src/starkware/cairo/common/math_cmp.cairo +++ b/src/starkware/cairo/common/math_cmp.cairo @@ -1,78 +1,89 @@ from starkware.cairo.common.math import assert_le_felt, assert_lt_felt -const RC_BOUND = 2 ** 128 +const RC_BOUND = 2 ** 128; -# Returns 1 if value != 0. Returns 0 otherwise. -func is_not_zero(value) -> (res : felt): - if value == 0: - return (res=0) - end +// Returns 1 if value != 0. Returns 0 otherwise. +@known_ap_change +func is_not_zero(value) -> felt { + if (value == 0) { + return 0; + } - return (res=1) -end + return 1; +} -# Returns 1 if a >= 0 (or more precisely 0 <= a < RANGE_CHECK_BOUND). -# Returns 0 otherwise. -func is_nn{range_check_ptr}(a) -> (res : felt): +// Returns 1 if a >= 0 (or more precisely 0 <= a < RANGE_CHECK_BOUND). +// Returns 0 otherwise. +@known_ap_change +func is_nn{range_check_ptr}(a) -> felt { %{ memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1 %} - jmp out_of_range if [ap] != 0; ap++ - [range_check_ptr] = a - let range_check_ptr = range_check_ptr + 1 - return (res=1) + jmp out_of_range if [ap] != 0, ap++; + [range_check_ptr] = a; + ap += 20; + let range_check_ptr = range_check_ptr + 1; + return 1; out_of_range: %{ memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1 %} - jmp need_felt_comparison if [ap] != 0; ap++ - assert [range_check_ptr] = (-a) - 1 - let range_check_ptr = range_check_ptr + 1 - return (res=0) + jmp need_felt_comparison if [ap] != 0, ap++; + assert [range_check_ptr] = (-a) - 1; + ap += 17; + let range_check_ptr = range_check_ptr + 1; + return 0; need_felt_comparison: - assert_le_felt(RC_BOUND, a) - return (res=0) -end + assert_le_felt(RC_BOUND, a); + return 0; +} -# Returns 1 if a <= b (or more precisely 0 <= b - a < RANGE_CHECK_BOUND). -# Returns 0 otherwise. -func is_le{range_check_ptr}(a, b) -> (res : felt): - return is_nn(b - a) -end +// Returns 1 if a <= b (or more precisely 0 <= b - a < RANGE_CHECK_BOUND). +// Returns 0 otherwise. +@known_ap_change +func is_le{range_check_ptr}(a, b) -> felt { + return is_nn(b - a); +} -# Returns 1 if 0 <= a <= b < RANGE_CHECK_BOUND. -# Returns 0 otherwise. -# -# Assumption: b < RANGE_CHECK_BOUND. -func is_nn_le{range_check_ptr}(a, b) -> (res : felt): - let (res) = is_nn(a) - if res == 0: - return (res=res) - end - return is_le(a, b) -end +// Returns 1 if 0 <= a <= b < RANGE_CHECK_BOUND. +// Returns 0 otherwise. +// +// Assumption: b < RANGE_CHECK_BOUND. +@known_ap_change +func is_nn_le{range_check_ptr}(a, b) -> felt { + let res = is_nn(a); + if (res == 0) { + ap += 25; + return res; + } + return is_nn(b - a); +} -# Returns 1 if value is in the range [lower, upper). -# Returns 0 otherwise. -# Assumptions: -# upper - lower <= RANGE_CHECK_BOUND -func is_in_range{range_check_ptr}(value, lower, upper) -> (res : felt): - let (res) = is_le(lower, value) - if res == 0: - return (res=res) - end - return is_le(value, upper - 1) -end +// Returns 1 if value is in the range [lower, upper). +// Returns 0 otherwise. +// Assumptions: +// upper - lower <= RANGE_CHECK_BOUND. +@known_ap_change +func is_in_range{range_check_ptr}(value, lower, upper) -> felt { + let res = is_le(lower, value); + if (res == 0) { + ap += 26; + return res; + } + return is_nn(upper - 1 - value); +} -# Checks if the unsigned integer lift (as a number in the range [0, PRIME)) of a is lower than -# or equal to that of b. -# See split_felt() for more details. -# Returns 1 if true, 0 otherwise. -func is_le_felt{range_check_ptr}(a, b) -> (res : felt): +// Checks if the unsigned integer lift (as a number in the range [0, PRIME)) of a is lower than +// or equal to that of b. +// See split_felt() for more details. +// Returns 1 if true, 0 otherwise. +@known_ap_change +func is_le_felt{range_check_ptr}(a, b) -> felt { %{ memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1 %} - jmp not_le if [ap] != 0; ap++ - assert_le_felt(a, b) - return (res=1) + jmp not_le if [ap] != 0, ap++; + ap += 6; + assert_le_felt(a, b); + return 1; not_le: - assert_lt_felt(b, a) - return (res=0) -end + assert_lt_felt(b, a); + return 0; +} diff --git a/src/starkware/cairo/common/memcpy.cairo b/src/starkware/cairo/common/memcpy.cairo index cbf73e7d..9d6c5775 100644 --- a/src/starkware/cairo/common/memcpy.cairo +++ b/src/starkware/cairo/common/memcpy.cairo @@ -1,35 +1,35 @@ -# Copies len field elements from src to dst. -func memcpy(dst : felt*, src : felt*, len): - struct LoopFrame: - member dst : felt* - member src : felt* - end +// Copies len field elements from src to dst. +func memcpy(dst: felt*, src: felt*, len) { + struct LoopFrame { + dst: felt*, + src: felt*, + } - if len == 0: - return () - end + if (len == 0) { + return (); + } %{ vm_enter_scope({'n': ids.len}) %} - tempvar frame = LoopFrame(dst=dst, src=src) + tempvar frame = LoopFrame(dst=dst, src=src); loop: - let frame = [cast(ap - LoopFrame.SIZE, LoopFrame*)] - assert [frame.dst] = [frame.src] + let frame = [cast(ap - LoopFrame.SIZE, LoopFrame*)]; + assert [frame.dst] = [frame.src]; - let continue_copying = [ap] - # Reserve space for continue_copying. - let next_frame = cast(ap + 1, LoopFrame*) - next_frame.dst = frame.dst + 1; ap++ - next_frame.src = frame.src + 1; ap++ + let continue_copying = [ap]; + // Reserve space for continue_copying. + let next_frame = cast(ap + 1, LoopFrame*); + next_frame.dst = frame.dst + 1, ap++; + next_frame.src = frame.src + 1, ap++; %{ n -= 1 ids.continue_copying = 1 if n > 0 else 0 %} - static_assert next_frame + LoopFrame.SIZE == ap + 1 - jmp loop if continue_copying != 0; ap++ - # Assert that the loop executed len times. - len = cast(next_frame.src, felt) - cast(src, felt) + static_assert next_frame + LoopFrame.SIZE == ap + 1; + jmp loop if continue_copying != 0, ap++; + // Assert that the loop executed len times. + len = cast(next_frame.src, felt) - cast(src, felt); %{ vm_exit_scope() %} - return () -end + return (); +} diff --git a/src/starkware/cairo/common/memset.cairo b/src/starkware/cairo/common/memset.cairo index de97c0b2..c5a0193e 100644 --- a/src/starkware/cairo/common/memset.cairo +++ b/src/starkware/cairo/common/memset.cairo @@ -1,33 +1,33 @@ -# Writes value into [dst + 0], ..., [dst + n - 1]. -func memset(dst : felt*, value : felt, n): - struct LoopFrame: - member dst : felt* - end +// Writes value into [dst + 0], ..., [dst + n - 1]. +func memset(dst: felt*, value: felt, n) { + struct LoopFrame { + dst: felt*, + } - if n == 0: - return () - end + if (n == 0) { + return (); + } %{ vm_enter_scope({'n': ids.n}) %} - tempvar frame = LoopFrame(dst=dst) + tempvar frame = LoopFrame(dst=dst); loop: - let frame = [cast(ap - LoopFrame.SIZE, LoopFrame*)] - assert [frame.dst] = value + let frame = [cast(ap - LoopFrame.SIZE, LoopFrame*)]; + assert [frame.dst] = value; - let continue_loop = [ap] - # Reserve space for continue_loop. - let next_frame = cast(ap + 1, LoopFrame*) - next_frame.dst = frame.dst + 1; ap++ + let continue_loop = [ap]; + // Reserve space for continue_loop. + let next_frame = cast(ap + 1, LoopFrame*); + next_frame.dst = frame.dst + 1, ap++; %{ n -= 1 ids.continue_loop = 1 if n > 0 else 0 %} - static_assert next_frame + LoopFrame.SIZE == ap + 1 - jmp loop if continue_loop != 0; ap++ - # Assert that the loop executed n times. - n = cast(next_frame.dst, felt) - cast(dst, felt) + static_assert next_frame + LoopFrame.SIZE == ap + 1; + jmp loop if continue_loop != 0, ap++; + // Assert that the loop executed n times. + n = cast(next_frame.dst, felt) - cast(dst, felt); %{ vm_exit_scope() %} - return () -end + return (); +} diff --git a/src/starkware/cairo/common/merkle_multi_update.cairo b/src/starkware/cairo/common/merkle_multi_update.cairo index d2b622f9..b782a3c5 100644 --- a/src/starkware/cairo/common/merkle_multi_update.cairo +++ b/src/starkware/cairo/common/merkle_multi_update.cairo @@ -1,37 +1,38 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.dict_access import DictAccess -# Performs an efficient update of multiple leaves in a Merkle tree. -# -# Arguments: -# update_ptr - a list of DictAccess instances sorted by key (e.g., the result of squash_dict). -# height - the height of the merkle tree. -# prev_root - the value of the root before the update. -# new_root - the value of the root after the update. -# -# Hint arguments: -# preimage - a dictionary from the hash value of a merkle node to the pair of children values. -# -# Implicit arguments: -# hash_ptr - hash builtin pointer. -# -# Assumptions: The keys in the update_ptr list are unique and sorted. -# Guarantees: All the keys in the update_ptr list are < 2**height. -# -# Pseudocode: -# def diff(prev, new, height): -# if height == 0: return [(prev,new)] -# if prev.left==new.left: return diff(prev.right, new.right, height - 1) -# if prev.right==new.right: return diff(prev.left, new.left, height - 1) -# return diff(prev.left, new.left, height - 1) + \ -# diff(prev.right, new.right, height - 1) -func merkle_multi_update{hash_ptr : HashBuiltin*}( - update_ptr : DictAccess*, n_updates, height, prev_root, new_root -): - if n_updates == 0: - prev_root = new_root - return () - end +// Performs an efficient update of multiple leaves in a Merkle tree. +// +// Arguments: +// update_ptr - a list of DictAccess instances sorted by key (e.g., the result of squash_dict). +// height - the height of the merkle tree. +// prev_root - the value of the root before the update. +// new_root - the value of the root after the update. +// +// Hint arguments: +// preimage - a dictionary from the hash value of a merkle node to the pair of children values. +// +// Implicit arguments: +// hash_ptr - hash builtin pointer. +// +// Assumptions: The keys in the update_ptr list are unique and sorted. +// Guarantees: All the keys in the update_ptr list are < 2**height. +// +// Pseudocode: +// def diff(prev, new, height): +// if height == 0: return [(prev,new)] +// if prev.left==new.left: return diff(prev.right, new.right, height - 1) +// if prev.right==new.right: return diff(prev.left, new.left, height - 1) +// return diff(prev.left, new.left, height - 1) + \ +// diff(prev.right, new.right, height - 1) +// . +func merkle_multi_update{hash_ptr: HashBuiltin*}( + update_ptr: DictAccess*, n_updates, height, prev_root, new_root +) { + if (n_updates == 0) { + prev_root = new_root; + return (); + } %{ from starkware.python.merkle_tree import build_update_tree @@ -54,21 +55,21 @@ func merkle_multi_update{hash_ptr : HashBuiltin*}( __merkle_multi_update_skip_validation_runner) ) %} - let orig_update_ptr = update_ptr - with update_ptr: - merkle_multi_update_inner(height=height, prev_root=prev_root, new_root=new_root, index=0) - end - assert update_ptr = orig_update_ptr + n_updates * DictAccess.SIZE + let orig_update_ptr = update_ptr; + with update_ptr { + merkle_multi_update_inner(height=height, prev_root=prev_root, new_root=new_root, index=0); + } + assert update_ptr = orig_update_ptr + n_updates * DictAccess.SIZE; %{ vm_exit_scope() %} - return () -end + return (); +} -# Helper function for merkle_multi_update(). -func merkle_multi_update_inner{hash_ptr : HashBuiltin*, update_ptr : DictAccess*}( +// Helper function for merkle_multi_update(). +func merkle_multi_update_inner{hash_ptr: HashBuiltin*, update_ptr: DictAccess*}( height, prev_root, new_root, index -): - let hash0 : HashBuiltin* = hash_ptr - let hash1 : HashBuiltin* = hash_ptr + HashBuiltin.SIZE +) { + let hash0: HashBuiltin* = hash_ptr; + let hash1: HashBuiltin* = hash_ptr + HashBuiltin.SIZE; %{ if ids.height == 0: assert node == ids.new_root, f'Expected node {ids.new_root}. Got {node}.' @@ -97,17 +98,17 @@ func merkle_multi_update_inner{hash_ptr : HashBuiltin*, update_ptr : DictAccess* memory[ap] = int(case != 'right') %} - jmp not_right if [ap] != 0; ap++ + jmp not_right if [ap] != 0, ap++; update_right: - let hash_ptr = hash_ptr + 2 * HashBuiltin.SIZE - assert hash0.result = prev_root - assert hash1.result = new_root + let hash_ptr = hash_ptr + 2 * HashBuiltin.SIZE; + assert hash0.result = prev_root; + assert hash1.result = new_root; - # Make sure the same authentication path is used. - assert hash0.x = hash1.x + // Make sure the same authentication path is used. + assert hash0.x = hash1.x; - # Call merkle_multi_update_inner recursively. + // Call merkle_multi_update_inner recursively. %{ vm_enter_scope(dict( node=right_child, preimage=preimage, @@ -118,23 +119,23 @@ func merkle_multi_update_inner{hash_ptr : HashBuiltin*, update_ptr : DictAccess* merkle_multi_update_inner( height=height - 1, prev_root=hash0.y, new_root=hash1.y, index=index * 2 + 1 - ) + ); %{ vm_exit_scope() %} - return () + return (); not_right: %{ memory[ap] = int(case != 'left') %} - jmp not_left if [ap] != 0; ap++ + jmp not_left if [ap] != 0, ap++; update_left: - let hash_ptr = hash_ptr + 2 * HashBuiltin.SIZE - assert hash0.result = prev_root - assert hash1.result = new_root + let hash_ptr = hash_ptr + 2 * HashBuiltin.SIZE; + assert hash0.result = prev_root; + assert hash1.result = new_root; - # Make sure the same authentication path is used. - assert hash0.y = hash1.y + // Make sure the same authentication path is used. + assert hash0.y = hash1.y; - # Call merkle_multi_update_inner recursively. + // Call merkle_multi_update_inner recursively. %{ vm_enter_scope(dict( node=left_child, preimage=preimage, @@ -144,40 +145,40 @@ func merkle_multi_update_inner{hash_ptr : HashBuiltin*, update_ptr : DictAccess* %} merkle_multi_update_inner( height=height - 1, prev_root=hash0.x, new_root=hash1.x, index=index * 2 - ) + ); %{ vm_exit_scope() %} - return () + return (); not_left: - jmp update_both if height != 0 + jmp update_both if height != 0; update_leaf: - # Note: height may underflow, but in order to reach 0 (which is verified here), we will need - # more steps than the field characteristic. The assumption is that it is not feasible. + // Note: height may underflow, but in order to reach 0 (which is verified here), we will need + // more steps than the field characteristic. The assumption is that it is not feasible. - # Write the update. + // Write the update. %{ assert case == 'leaf' %} - index = update_ptr.key - assert update_ptr.prev_value = prev_root - assert update_ptr.new_value = new_root - let update_ptr = update_ptr + DictAccess.SIZE + index = update_ptr.key; + assert update_ptr.prev_value = prev_root; + assert update_ptr.new_value = new_root; + let update_ptr = update_ptr + DictAccess.SIZE; - # Return values. - return () + // Return values. + return (); update_both: - # When the function starts we have fp=ap. - # The two nondeterministic jumps, write to [fp] and [fp + 1] and advance ap by 2. - # Thus, the next free memory cell is [fp + 2] and we need to increment ap by 1. - let local_left_index = [fp + 2] + // When the function starts we have fp=ap. + // The two nondeterministic jumps, write to [fp] and [fp + 1] and advance ap by 2. + // Thus, the next free memory cell is [fp + 2] and we need to increment ap by 1. + let local_left_index = [fp + 2]; %{ assert case == 'both' %} - local_left_index = index * 2; ap++ + local_left_index = index * 2, ap++; - let hash_ptr = hash_ptr + 2 * HashBuiltin.SIZE - assert hash0.result = prev_root - assert hash1.result = new_root + let hash_ptr = hash_ptr + 2 * HashBuiltin.SIZE; + assert hash0.result = prev_root; + assert hash1.result = new_root; - # Update left. + // Update left. %{ vm_enter_scope(dict( node=left_child, preimage=preimage, @@ -187,10 +188,10 @@ func merkle_multi_update_inner{hash_ptr : HashBuiltin*, update_ptr : DictAccess* %} merkle_multi_update_inner( height=height - 1, prev_root=hash0.x, new_root=hash1.x, index=local_left_index - ) + ); %{ vm_exit_scope() %} - # Update right. + // Update right. %{ vm_enter_scope(dict( node=right_child, preimage=preimage, @@ -200,7 +201,7 @@ func merkle_multi_update_inner{hash_ptr : HashBuiltin*, update_ptr : DictAccess* %} merkle_multi_update_inner( height=height - 1, prev_root=hash0.y, new_root=hash1.y, index=local_left_index + 1 - ) + ); %{ vm_exit_scope() %} - return () -end + return (); +} diff --git a/src/starkware/cairo/common/merkle_update.cairo b/src/starkware/cairo/common/merkle_update.cairo index 1e46603c..6c8256b3 100644 --- a/src/starkware/cairo/common/merkle_update.cairo +++ b/src/starkware/cairo/common/merkle_update.cairo @@ -1,31 +1,31 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin -# Performs an update for a single leaf (index) in a Merkle tree (where 0 <= index < 2^height). -# Updates the leaf from prev_leaf to new_leaf, and returns the previous and new roots of the -# Merkle tree resulting from the change. -# In particular, given a secret authentication path (of the siblings of the nodes in the path from -# the root to the leaf), this function computes the roots twice - once with prev_leaf and once with -# new_leaf, where the verifier is guaranteed that the same authentication path is used. -func merkle_update{hash_ptr : HashBuiltin*}(height, prev_leaf, new_leaf, index) -> ( - prev_root : felt, new_root : felt -): - if height == 0: - # Assert that index is 0. - index = 0 - # Return the two leaves and the Pedersen pointer. +// Performs an update for a single leaf (index) in a Merkle tree (where 0 <= index < 2^height). +// Updates the leaf from prev_leaf to new_leaf, and returns the previous and new roots of the +// Merkle tree resulting from the change. +// In particular, given a secret authentication path (of the siblings of the nodes in the path from +// the root to the leaf), this function computes the roots twice - once with prev_leaf and once with +// new_leaf, where the verifier is guaranteed that the same authentication path is used. +func merkle_update{hash_ptr: HashBuiltin*}(height, prev_leaf, new_leaf, index) -> ( + prev_root: felt, new_root: felt +) { + if (height == 0) { + // Assert that index is 0. + index = 0; + // Return the two leaves and the Pedersen pointer. %{ # Check that auth_path had the right number of elements. assert len(auth_path) == 0, 'Got too many values in auth_path.' %} - return (prev_root=prev_leaf, new_root=new_leaf) - end + return (prev_root=prev_leaf, new_root=new_leaf); + } - let prev_node_hash = hash_ptr - let new_node_hash = hash_ptr + HashBuiltin.SIZE - let hash_ptr = hash_ptr + 2 * HashBuiltin.SIZE + let prev_node_hash = hash_ptr; + let new_node_hash = hash_ptr + HashBuiltin.SIZE; + let hash_ptr = hash_ptr + 2 * HashBuiltin.SIZE; %{ memory[ap] = ids.index % 2 %} - jmp update_right if [ap] != 0; ap++ + jmp update_right if [ap] != 0, ap++; update_left: %{ @@ -34,26 +34,27 @@ func merkle_update{hash_ptr : HashBuiltin*}(height, prev_leaf, new_leaf, index) ids.prev_node_hash.y = sibling ids.new_node_hash.y = sibling %} - prev_leaf = prev_node_hash.x - new_leaf = new_node_hash.x + prev_leaf = prev_node_hash.x; + new_leaf = new_node_hash.x; - # Make sure the same authentication path is used. - let right_sibling = ap - [right_sibling] = prev_node_hash.y - [right_sibling] = new_node_hash.y; ap++ + // Make sure the same authentication path is used. + let right_sibling = ap; + [right_sibling] = prev_node_hash.y; + [right_sibling] = new_node_hash.y, ap++; - # Call merkle_update recursively. + // Call merkle_update recursively. - # Index must be even. - # We can show by induction that index is in the range [0, 2 ** height) (We know that when height - # is 0 index must be 0). If index was odd, then index / 2 is larger than PRIME / 2 which - # contradicts the fact that index / 2 is in the range [0, 2 ** (height - 1)). + // Index must be even. + // We can show by induction that index is in the range [0, 2 ** height) + // (We know that when height is 0 index must be 0). + // If index was odd, then index / 2 is larger than PRIME / 2 which + // contradicts the fact that index / 2 is in the range [0, 2 ** (height - 1)). return merkle_update( height=height - 1, prev_leaf=prev_node_hash.result, new_leaf=new_node_hash.result, index=index / 2, - ) + ); update_right: %{ @@ -62,19 +63,19 @@ func merkle_update{hash_ptr : HashBuiltin*}(height, prev_leaf, new_leaf, index) ids.prev_node_hash.x = sibling ids.new_node_hash.x = sibling %} - prev_leaf = prev_node_hash.y - new_leaf = new_node_hash.y + prev_leaf = prev_node_hash.y; + new_leaf = new_node_hash.y; - # Make sure the same authentication path is used. - let left_sibling = ap - [left_sibling] = prev_node_hash.x - [left_sibling] = new_node_hash.x; ap++ + // Make sure the same authentication path is used. + let left_sibling = ap; + [left_sibling] = prev_node_hash.x; + [left_sibling] = new_node_hash.x, ap++; - # Similarly to the description above, index must be odd at this point. + // Similarly to the description above, index must be odd at this point. return merkle_update( height=height - 1, prev_leaf=prev_node_hash.result, new_leaf=new_node_hash.result, index=(index - 1) / 2, - ) -end + ); +} diff --git a/src/starkware/cairo/common/patricia.cairo b/src/starkware/cairo/common/patricia.cairo index bf6ac904..7bc581e4 100644 --- a/src/starkware/cairo/common/patricia.cairo +++ b/src/starkware/cairo/common/patricia.cairo @@ -11,36 +11,36 @@ from starkware.cairo.common.math import ( assert_not_zero, ) -# Maximum length of an edge. -const MAX_LENGTH = 251 - -# A struct of globals that are passed throughout the algorithm. -struct ParticiaGlobals: - # An array of size MAX_LENGTH, where pow2[i] = 2**i. - member pow2 : felt* - # Offset of the relevant value field in DictAccess. - # 1 if the previous tree is traversed and 2 if the new tree is traversed. - member access_offset : felt -end - -# Represents an edge node: a subtree with a path, s.t. all leaves not under that path are 0. -struct NodeEdge: - member length : felt - member path : felt - member bottom : felt -end - -# Holds the constants needed for Patricia updates. -struct PatriciaUpdateConstants: - member globals_pow2 : felt* -end - -# Given an edge node hash, opens the hash using the preimage hint, and returns a NodeEdge object. -func open_edge{hash_ptr : HashBuiltin*, range_check_ptr}( - globals : ParticiaGlobals*, node : felt -) -> (edge : NodeEdge*): - alloc_locals - local edge : NodeEdge* +// Maximum length of an edge. +const MAX_LENGTH = 251; + +// A struct of globals that are passed throughout the algorithm. +struct ParticiaGlobals { + // An array of size MAX_LENGTH, where pow2[i] = 2**i. + pow2: felt*, + // Offset of the relevant value field in DictAccess. + // 1 if the previous tree is traversed and 2 if the new tree is traversed. + access_offset: felt, +} + +// Represents an edge node: a subtree with a path, s.t. all leaves not under that path are 0. +struct NodeEdge { + length: felt, + path: felt, + bottom: felt, +} + +// Holds the constants needed for Patricia updates. +struct PatriciaUpdateConstants { + globals_pow2: felt*, +} + +// Given an edge node hash, opens the hash using the preimage hint, and returns a NodeEdge object. +func open_edge{hash_ptr: HashBuiltin*, range_check_ptr}(globals: ParticiaGlobals*, node: felt) -> ( + edge: NodeEdge* +) { + alloc_locals; + local edge: NodeEdge*; %{ ids.edge = segments.add() @@ -52,217 +52,217 @@ func open_edge{hash_ptr : HashBuiltin*, range_check_ptr}( __patricia_skip_validation_runner.verified_addresses.add( ids.hash_ptr + ids.HashBuiltin.result) %} - # Validity checks. - assert_in_range(edge.length, 1, MAX_LENGTH + 1) - assert_lt_felt(edge.path, globals.pow2[edge.length]) - # Note: we do not explicitly verify that bottom_hash is binary or leaf here, since it will be - # verified later in the algorithm if necessary. - assert hash_ptr.x = edge.bottom - assert hash_ptr.y = edge.path - assert node = hash_ptr.result + edge.length - let hash_ptr = hash_ptr + HashBuiltin.SIZE - return (edge=edge) -end - -# Traversal: -# See patricia_utils.py for details about the node representation. -# The patricia updates algorithm is composed of 2 traversals: on the previous and the new trees. -# Each traversal outputs: -# 1. update_ptr - Sorted list of leaf indices and values of the traversal. -# 2. siblings - An encoding of the list of untraversed siblings of the nodes we traversed: -# For every node in the underlying merkle tree (in-order), if we only traverse one of its -# children, the other child will be encoded in this list. -# The encoding is as follows: -# * A value of 0 means a 0-sibling - empty subtree. -# * A value of n, for 2 <= n <= MAX_LENGTH means n non leaf 0-siblings. -# * Otherwise, the value is the sibling value. -# It may be a hash (which we assume to be > MAX_LENGTH) for an inner node or a value -# (any felt) for a leaf sibling. -# If the tree traversals output the same leaf indices, and the same siblings, it is guaranteed -# that all the non traversed leaves have the same value. -# All traversal functions do at least one leaf update in the given subtree. -# -# Args: -# * height - The height of the subtree rooted at this node. -# * path - The path from the root to this node. -# -# Hint args: -# * node - The current traversal node update tree. See build_update_tree() for more info. -# * descent_map - A map from for all the nodes on which we should descend. See get_descents() -# in patricia_utils.py. -# * common_args - Contains itself and other relevant hint variables in the context of a traversal. - -# Traverses an empty subtree. -func traverse_empty{update_ptr : DictAccess*, range_check_ptr, siblings : felt*}( - globals : ParticiaGlobals*, height : felt, path : felt -): - if height == 0: - assert update_ptr.key = path - let value = [cast(update_ptr, felt*) + globals.access_offset] - assert value = 0 - let update_ptr = update_ptr + DictAccess.SIZE - return () - end - - # Decide non deterministically if we should traverse both children or just one. - # This is more efficient that trying to determine it from update_ptr. + // Validity checks. + assert_in_range(edge.length, 1, MAX_LENGTH + 1); + assert_lt_felt(edge.path, globals.pow2[edge.length]); + // Note: we do not explicitly verify that bottom_hash is binary or leaf here, since it will be + // verified later in the algorithm if necessary. + assert hash_ptr.x = edge.bottom; + assert hash_ptr.y = edge.path; + assert node = hash_ptr.result + edge.length; + let hash_ptr = hash_ptr + HashBuiltin.SIZE; + return (edge=edge); +} + +// Traversal: +// See patricia_utils.py for details about the node representation. +// The patricia updates algorithm is composed of 2 traversals: on the previous and the new trees. +// Each traversal outputs: +// 1. update_ptr - Sorted list of leaf indices and values of the traversal. +// 2. siblings - An encoding of the list of untraversed siblings of the nodes we traversed: +// For every node in the underlying merkle tree (in-order), if we only traverse one of its +// children, the other child will be encoded in this list. +// The encoding is as follows: +// * A value of 0 means a 0-sibling - empty subtree. +// * A value of n, for 2 <= n <= MAX_LENGTH means n non leaf 0-siblings. +// * Otherwise, the value is the sibling value. +// It may be a hash (which we assume to be > MAX_LENGTH) for an inner node or a value +// (any felt) for a leaf sibling. +// If the tree traversals output the same leaf indices, and the same siblings, it is guaranteed +// that all the non traversed leaves have the same value. +// All traversal functions do at least one leaf update in the given subtree. +// +// Args: +// * height - The height of the subtree rooted at this node. +// * path - The path from the root to this node. +// +// Hint args: +// * node - The current traversal node update tree. See build_update_tree() for more info. +// * descent_map - A map from for all the nodes on which we should descend. See get_descents() +// in patricia_utils.py. +// * common_args - Contains itself and other relevant hint variables in the context of a traversal. + +// Traverses an empty subtree. +func traverse_empty{update_ptr: DictAccess*, range_check_ptr, siblings: felt*}( + globals: ParticiaGlobals*, height: felt, path: felt +) { + if (height == 0) { + assert update_ptr.key = path; + let value = [cast(update_ptr, felt*) + globals.access_offset]; + assert value = 0; + let update_ptr = update_ptr + DictAccess.SIZE; + return (); + } + + // Decide non deterministically if we should traverse both children or just one. + // This is more efficient that trying to determine it from update_ptr. %{ from starkware.python.merkle_tree import decode_node left_child, right_child, case = decode_node(node) memory[ap] = 1 if case != 'both' else 0 %} - jmp skip_both if [ap] != 0; ap++ + jmp skip_both if [ap] != 0, ap++; - # Traverse both children. + // Traverse both children. %{ vm_enter_scope(dict(node=left_child, **common_args)) %} - traverse_empty(globals=globals, height=height - 1, path=path * 2) + traverse_empty(globals=globals, height=height - 1, path=path * 2); %{ vm_exit_scope() %} %{ vm_enter_scope(dict(node=right_child, **common_args)) %} - traverse_empty(globals=globals, height=height - 1, path=path * 2 + 1) + traverse_empty(globals=globals, height=height - 1, path=path * 2 + 1); %{ vm_exit_scope() %} - return () + return (); skip_both: %{ descend = descent_map.get((ids.height, ids.path)) memory[ap] = 0 if descend is None else 1 %} - jmp skip_single if [ap] != 0; ap++ + jmp skip_single if [ap] != 0, ap++; - # Single. - let child_bit = [ap] + // Single. + let child_bit = [ap]; %{ ids.child_bit = 0 if case == 'left' else 1 new_node = left_child if case == 'left' else right_child vm_enter_scope(dict(node=new_node, **common_args)) %} - child_bit = child_bit * child_bit; ap++ - assert [siblings] = 0 - let siblings = siblings + 1 - traverse_empty(globals=globals, height=height - 1, path=path * 2 + child_bit) + child_bit = child_bit * child_bit, ap++; + assert [siblings] = 0; + let siblings = siblings + 1; + traverse_empty(globals=globals, height=height - 1, path=path * 2 + child_bit); %{ vm_exit_scope() %} - return () + return (); skip_single: - # Descend. - tempvar word + // Descend. + tempvar word; %{ memory[ids.siblings], ids.word = descend %} - tempvar length = [siblings] - let siblings = siblings + 1 + tempvar length = [siblings]; + let siblings = siblings + 1; - assert_in_range(length, 2, height + 1) - tempvar length_pow2 = globals.pow2[length] - assert_lt_felt(word, length_pow2) + assert_in_range(length, 2, height + 1); + tempvar length_pow2 = globals.pow2[length]; + assert_lt_felt(word, length_pow2); %{ new_node = node for i in range(ids.length - 1, -1, -1): new_node = new_node[(ids.word >> i) & 1] vm_enter_scope(dict(node=new_node, **common_args)) %} - traverse_empty(globals=globals, height=height - length, path=path * length_pow2 + word) + traverse_empty(globals=globals, height=height - length, path=path * length_pow2 + word); %{ vm_exit_scope() %} - return () -end + return (); +} -# Traverses a subtree rooted at the given NodeEdge. +// Traverses a subtree rooted at the given NodeEdge. func traverse_edge{ - hash_ptr : HashBuiltin*, range_check_ptr, update_ptr : DictAccess*, siblings : felt* -}(globals : ParticiaGlobals*, height : felt, path : felt, edge : NodeEdge): - if edge.length == 0: - return traverse_binary_or_leaf(globals=globals, height=height, path=path, node=edge.bottom) - end + hash_ptr: HashBuiltin*, range_check_ptr, update_ptr: DictAccess*, siblings: felt* +}(globals: ParticiaGlobals*, height: felt, path: felt, edge: NodeEdge) { + if (edge.length == 0) { + return traverse_binary_or_leaf(globals=globals, height=height, path=path, node=edge.bottom); + } - alloc_locals + alloc_locals; %{ descend = descent_map.get((ids.height, ids.path)) memory[ap] = 0 if descend is None else 1 %} - jmp descend if [ap] != 0; ap++ + jmp descend if [ap] != 0, ap++; - # Extract one bit from the edge. edge.length is guaranteed to be >= 1. - local new_length = edge.length - 1 - local bound = globals.pow2[new_length] - local bit + // Extract one bit from the edge. edge.length is guaranteed to be >= 1. + local new_length = edge.length - 1; + local bound = globals.pow2[new_length]; + local bit; %{ ids.bit = (ids.edge.path >> ids.new_length) & 1 %} - bit * bit = bit - local new_path = edge.path - bit * bound - assert_lt_felt(new_path, bound) - local new_edge : NodeEdge = NodeEdge(length=new_length, path=new_path, bottom=edge.bottom) + bit * bit = bit; + local new_path = edge.path - bit * bound; + assert_lt_felt(new_path, bound); + local new_edge: NodeEdge = NodeEdge(length=new_length, path=new_path, bottom=edge.bottom); - # Decide case. + // Decide case. %{ from starkware.python.merkle_tree import decode_node left_child, right_child, case = decode_node(node) memory[ap] = int(case != 'both') %} - jmp skip_both if [ap] != 0; ap++ + jmp skip_both if [ap] != 0, ap++; - # Traverse both children. - if bit == 0: + // Traverse both children. + if (bit == 0) { %{ vm_enter_scope(dict(node=left_child, **common_args)) %} - traverse_edge(globals=globals, height=height - 1, path=path * 2, edge=new_edge) + traverse_edge(globals=globals, height=height - 1, path=path * 2, edge=new_edge); %{ vm_exit_scope() %} - local hash_ptr : HashBuiltin* = hash_ptr + local hash_ptr: HashBuiltin* = hash_ptr; %{ vm_enter_scope(dict(node=right_child, **common_args)) %} - traverse_empty(globals=globals, height=height - 1, path=path * 2 + 1) + traverse_empty(globals=globals, height=height - 1, path=path * 2 + 1); %{ vm_exit_scope() %} - return () - else: + return (); + } else { %{ vm_enter_scope(dict(node=left_child, **common_args)) %} - traverse_empty(globals=globals, height=height - 1, path=path * 2) + traverse_empty(globals=globals, height=height - 1, path=path * 2); %{ vm_exit_scope() %} - ap += 0 + ap += 0; %{ vm_enter_scope(dict(node=right_child, **common_args)) %} - traverse_edge(globals=globals, height=height - 1, path=path * 2 + 1, edge=new_edge) + traverse_edge(globals=globals, height=height - 1, path=path * 2 + 1, edge=new_edge); %{ vm_exit_scope() %} - return () - end + return (); + } skip_both: %{ memory[ap] = int(case == 'right') ^ ids.bit %} - jmp skip_non_empty_child if [ap] != 0; ap++ + jmp skip_non_empty_child if [ap] != 0, ap++; - # Traverse the non-empty child. - assert [siblings] = 0 - let siblings = siblings + 1 + // Traverse the non-empty child. + assert [siblings] = 0; + let siblings = siblings + 1; %{ new_node = left_child if ids.bit == 0 else right_child vm_enter_scope(dict(node=new_node, **common_args)) %} - traverse_edge(globals=globals, height=height - 1, path=path * 2 + bit, edge=new_edge) + traverse_edge(globals=globals, height=height - 1, path=path * 2 + bit, edge=new_edge); %{ vm_exit_scope() %} - return () + return (); skip_non_empty_child: - # Traverse the empty child. - local range_check_ptr = range_check_ptr - local new_hash_ptr : HashBuiltin* + // Traverse the empty child. + local range_check_ptr = range_check_ptr; + local new_hash_ptr: HashBuiltin*; - # Reserve a spot for the sibling. It is more efficient to compute it after the recursive - # traversal. - let current_sibling = siblings - let siblings = siblings + 1 + // Reserve a spot for the sibling. It is more efficient to compute it after the recursive + // traversal. + let current_sibling = siblings; + let siblings = siblings + 1; - # Traverse empty side. + // Traverse empty side. %{ new_node = left_child if ids.bit == 1 else right_child vm_enter_scope(dict(node=new_node, **common_args)) %} - traverse_empty(globals=globals, height=height - 1, path=path * 2 + 1 - bit) + traverse_empty(globals=globals, height=height - 1, path=path * 2 + 1 - bit); %{ vm_exit_scope() %} - if edge.length == 1: - # In this case, the sibling is the bottom of our edge. - # Make sure edge.bottom is binary or leaf. - assert [current_sibling] = edge.bottom - if height != 1: - # This check should only be done on the new tree. - if globals.access_offset == 2: - hash_ptr.result = edge.bottom + if (edge.length == 1) { + // In this case, the sibling is the bottom of our edge. + // Make sure edge.bottom is binary or leaf. + assert [current_sibling] = edge.bottom; + if (height != 1) { + // This check should only be done on the new tree. + if (globals.access_offset == 2) { + hash_ptr.result = edge.bottom; %{ ids.hash_ptr.x, ids.hash_ptr.y = preimage[ids.edge.bottom] if __patricia_skip_validation_runner: @@ -271,38 +271,38 @@ func traverse_edge{ __patricia_skip_validation_runner.verified_addresses.add( ids.hash_ptr + ids.HashBuiltin.result) %} - let hash_ptr = hash_ptr + HashBuiltin.SIZE - return () - else: - return () - end - end - return () - end - - # This is the case where we split an edge. - let (hash) = hash2(edge.bottom, new_edge.path) - assert [current_sibling] = hash + new_edge.length - return () - - # Descend. + let hash_ptr = hash_ptr + HashBuiltin.SIZE; + return (); + } else { + return (); + } + } + return (); + } + + // This is the case where we split an edge. + let (hash) = hash2(edge.bottom, new_edge.path); + assert [current_sibling] = hash + new_edge.length; + return (); + + // Descend. descend: - local length - local word + local length; + local word; %{ ids.length, ids.word = descend %} - assert [siblings] = length - let siblings = siblings + 1 - - # Check that the descend is valid. - assert_in_range(length, 2, edge.length + 1) - tempvar length_pow2 = globals.pow2[length] - tempvar new_length = edge.length - length - tempvar new_length_pow2 = globals.pow2[new_length] - tempvar new_path = edge.path - word * new_length_pow2 - assert_lt_felt(word, length_pow2) - assert_lt_felt(new_path, new_length_pow2) - - let new_edge : NodeEdge = NodeEdge(length=new_length, path=new_path, bottom=edge.bottom) + assert [siblings] = length; + let siblings = siblings + 1; + + // Check that the descend is valid. + assert_in_range(length, 2, edge.length + 1); + tempvar length_pow2 = globals.pow2[length]; + tempvar new_length = edge.length - length; + tempvar new_length_pow2 = globals.pow2[new_length]; + tempvar new_path = edge.path - word * new_length_pow2; + assert_lt_felt(word, length_pow2); + assert_lt_felt(new_path, new_length_pow2); + + let new_edge: NodeEdge = NodeEdge(length=new_length, path=new_path, bottom=edge.bottom); %{ new_node = node for i in range(ids.length - 1, -1, -1): @@ -311,32 +311,32 @@ func traverse_edge{ %} traverse_edge( globals=globals, height=height - length, path=path * length_pow2 + word, edge=new_edge - ) + ); %{ vm_exit_scope() %} - return () -end + return (); +} -# Traverses a subtree rooted at the given binary or leaf node with given hash/value. +// Traverses a subtree rooted at the given binary or leaf node with given hash/value. func traverse_binary_or_leaf{ - hash_ptr : HashBuiltin*, range_check_ptr, update_ptr : DictAccess*, siblings : felt* -}(globals : ParticiaGlobals*, height : felt, path : felt, node : felt): - if height == 0: - # Leaf. - assert update_ptr.key = path - tempvar value = [cast(update_ptr, felt*) + globals.access_offset] - assert value = node - assert_not_zero(value) - let update_ptr = update_ptr + DictAccess.SIZE - return () - end - - alloc_locals - - # Binary. - let current_hash = hash_ptr - let hash_ptr = hash_ptr + HashBuiltin.SIZE - assert current_hash.result = node + hash_ptr: HashBuiltin*, range_check_ptr, update_ptr: DictAccess*, siblings: felt* +}(globals: ParticiaGlobals*, height: felt, path: felt, node: felt) { + if (height == 0) { + // Leaf. + assert update_ptr.key = path; + tempvar value = [cast(update_ptr, felt*) + globals.access_offset]; + assert value = node; + assert_not_zero(value); + let update_ptr = update_ptr + DictAccess.SIZE; + return (); + } + + alloc_locals; + + // Binary. + let current_hash = hash_ptr; + let hash_ptr = hash_ptr + HashBuiltin.SIZE; + assert current_hash.result = node; %{ from starkware.python.merkle_tree import decode_node @@ -356,106 +356,108 @@ func traverse_binary_or_leaf{ memory[ap] = int(case != 'both') %} - jmp skip_both if [ap] != 0; ap++ + jmp skip_both if [ap] != 0, ap++; - # Traverse both children. + // Traverse both children. %{ vm_enter_scope(dict(node=left_child, **common_args)) %} - traverse_non_empty(globals=globals, height=height - 1, path=path * 2, node=current_hash.x) + traverse_non_empty(globals=globals, height=height - 1, path=path * 2, node=current_hash.x); %{ vm_exit_scope() %} - tempvar left_child = path * 2 + tempvar left_child = path * 2; %{ vm_enter_scope(dict(node=right_child, **common_args)) %} - traverse_non_empty(globals=globals, height=height - 1, path=left_child + 1, node=current_hash.y) + traverse_non_empty( + globals=globals, height=height - 1, path=left_child + 1, node=current_hash.y + ); %{ vm_exit_scope() %} - return () + return (); skip_both: %{ memory[ap] = int(case != 'left') %} - jmp skip_left if [ap] != 0; ap++ + jmp skip_left if [ap] != 0, ap++; - # Left. - tempvar sib = current_hash.y - assert_not_zero(sib) - assert [siblings] = sib - let siblings = siblings + 1 + // Left. + tempvar sib = current_hash.y; + assert_not_zero(sib); + assert [siblings] = sib; + let siblings = siblings + 1; %{ vm_enter_scope(dict(node=left_child, **common_args)) %} - traverse_non_empty(globals=globals, height=height - 1, path=path * 2, node=current_hash.x) + traverse_non_empty(globals=globals, height=height - 1, path=path * 2, node=current_hash.x); %{ vm_exit_scope() %} - return () + return (); skip_left: %{ assert case == 'right' %} - # Right. - tempvar sib = current_hash.x - assert_not_zero(sib) - assert [siblings] = sib - let siblings = siblings + 1 + // Right. + tempvar sib = current_hash.x; + assert_not_zero(sib); + assert [siblings] = sib; + let siblings = siblings + 1; %{ vm_enter_scope(dict(node=right_child, **common_args)) %} - traverse_non_empty(globals=globals, height=height - 1, path=path * 2 + 1, node=current_hash.y) + traverse_non_empty(globals=globals, height=height - 1, path=path * 2 + 1, node=current_hash.y); %{ vm_exit_scope() %} - return () -end + return (); +} -# Traverses some of the leaves in the subtree rooted at node. +// Traverses some of the leaves in the subtree rooted at node. func traverse_node{ - hash_ptr : HashBuiltin*, range_check_ptr, update_ptr : DictAccess*, siblings : felt* -}(globals : ParticiaGlobals*, height : felt, path : felt, node : felt): - if node == 0: - # Empty: - traverse_empty(globals=globals, height=height, path=path) - return () - end - - return traverse_non_empty(globals=globals, height=height, path=path, node=node) -end - -# Same as traverse_node, but disallows empty nodes. + hash_ptr: HashBuiltin*, range_check_ptr, update_ptr: DictAccess*, siblings: felt* +}(globals: ParticiaGlobals*, height: felt, path: felt, node: felt) { + if (node == 0) { + // Empty: + traverse_empty(globals=globals, height=height, path=path); + return (); + } + + return traverse_non_empty(globals=globals, height=height, path=path, node=node); +} + +// Same as traverse_node, but disallows empty nodes. func traverse_non_empty{ - hash_ptr : HashBuiltin*, range_check_ptr, update_ptr : DictAccess*, siblings : felt* -}(globals : ParticiaGlobals*, height : felt, path : felt, node : felt): + hash_ptr: HashBuiltin*, range_check_ptr, update_ptr: DictAccess*, siblings: felt* +}(globals: ParticiaGlobals*, height: felt, path: felt, node: felt) { %{ memory[ap] = 1 if ids.height == 0 or len(preimage[ids.node]) == 2 else 0 %} - jmp binary if [ap] != 0; ap++ - # Edge. - let (edge) = open_edge(globals=globals, node=node) - traverse_edge(globals=globals, height=height, path=path, edge=[edge]) - return () + jmp binary if [ap] != 0, ap++; + // Edge. + let (edge) = open_edge(globals=globals, node=node); + traverse_edge(globals=globals, height=height, path=path, edge=[edge]); + return (); - # Binary. + // Binary. binary: - return traverse_binary_or_leaf(globals=globals, height=height, path=path, node=node) -end - -# Computes a power of 2 array. In other words, writes the sequence 1, 2, 4, 8, ... to the given -# pointer (with the given length). -func compute_pow2_array(pow2_ptr : felt*, cur : felt, n : felt): - if n == 0: - return () - end - assert [pow2_ptr] = cur - return compute_pow2_array(pow2_ptr=pow2_ptr + 1, cur=cur * 2, n=n - 1) -end - -# Performs an efficient update of multiple leaves in a Patricia Merkle tree. -# -# Arguments: -# update_ptr - a list of DictAccess instances sorted by key (e.g., the result of squash_dict). -# height - the height of the merkle tree. -# prev_root - the value of the root before the update. -# new_root - the value of the root after the update. -# -# Hint arguments: -# preimage - a dictionary from the hash value of a Patricia node to either -# 1. a pair of children values, for binary nodes. -# 2. a triplet of (length, path, bottom), for edge nodes. -# -# Implicit arguments: -# hash_ptr - hash builtin pointer. -# -# Assumptions: The keys in the update_ptr list are unique and sorted. -# Guarantees: All the keys in the update_ptr list are < 2**height. -func patricia_update{hash_ptr : HashBuiltin*, range_check_ptr}( - update_ptr : DictAccess*, n_updates : felt, height : felt, prev_root : felt, new_root : felt -): - let (patricia_update_constants : PatriciaUpdateConstants*) = patricia_update_constants_new() + return traverse_binary_or_leaf(globals=globals, height=height, path=path, node=node); +} + +// Computes a power of 2 array. In other words, writes the sequence 1, 2, 4, 8, ... to the given +// pointer (with the given length). +func compute_pow2_array(pow2_ptr: felt*, cur: felt, n: felt) { + if (n == 0) { + return (); + } + assert [pow2_ptr] = cur; + return compute_pow2_array(pow2_ptr=pow2_ptr + 1, cur=cur * 2, n=n - 1); +} + +// Performs an efficient update of multiple leaves in a Patricia Merkle tree. +// +// Arguments: +// update_ptr - a list of DictAccess instances sorted by key (e.g., the result of squash_dict). +// height - the height of the merkle tree. +// prev_root - the value of the root before the update. +// new_root - the value of the root after the update. +// +// Hint arguments: +// preimage - a dictionary from the hash value of a Patricia node to either +// 1. a pair of children values, for binary nodes. +// 2. a triplet of (length, path, bottom), for edge nodes. +// +// Implicit arguments: +// hash_ptr - hash builtin pointer. +// +// Assumptions: The keys in the update_ptr list are unique and sorted. +// Guarantees: All the keys in the update_ptr list are < 2**height. +func patricia_update{hash_ptr: HashBuiltin*, range_check_ptr}( + update_ptr: DictAccess*, n_updates: felt, height: felt, prev_root: felt, new_root: felt +) { + let (patricia_update_constants: PatriciaUpdateConstants*) = patricia_update_constants_new(); patricia_update_using_update_constants( patricia_update_constants=patricia_update_constants, update_ptr=update_ptr, @@ -463,31 +465,31 @@ func patricia_update{hash_ptr : HashBuiltin*, range_check_ptr}( height=height, prev_root=prev_root, new_root=new_root, - ) - - return () -end - -func patricia_update_constants_new() -> (patricia_update_constants : PatriciaUpdateConstants*): - # Compute power-of-2 array for patricia updates. - alloc_locals - let (local globals_pow2 : felt*) = alloc() - compute_pow2_array(pow2_ptr=globals_pow2, cur=1, n=MAX_LENGTH + 1) - return (patricia_update_constants=new PatriciaUpdateConstants(globals_pow2=globals_pow2)) -end - -func patricia_update_using_update_constants{hash_ptr : HashBuiltin*, range_check_ptr}( - patricia_update_constants : PatriciaUpdateConstants*, - update_ptr : DictAccess*, - n_updates : felt, - height : felt, - prev_root : felt, - new_root : felt, -): - if n_updates == 0: - prev_root = new_root - return () - end + ); + + return (); +} + +func patricia_update_constants_new() -> (patricia_update_constants: PatriciaUpdateConstants*) { + // Compute power-of-2 array for patricia updates. + alloc_locals; + let (local globals_pow2: felt*) = alloc(); + compute_pow2_array(pow2_ptr=globals_pow2, cur=1, n=MAX_LENGTH + 1); + return (patricia_update_constants=new PatriciaUpdateConstants(globals_pow2=globals_pow2)); +} + +func patricia_update_using_update_constants{hash_ptr: HashBuiltin*, range_check_ptr}( + patricia_update_constants: PatriciaUpdateConstants*, + update_ptr: DictAccess*, + n_updates: felt, + height: felt, + prev_root: felt, + new_root: felt, +) { + if (n_updates == 0) { + prev_root = new_root; + return (); + } %{ from starkware.cairo.common.patricia_utils import canonic, patricia_guess_descents @@ -516,39 +518,39 @@ func patricia_update_using_update_constants{hash_ptr : HashBuiltin*, range_check __patricia_skip_validation_runner=__patricia_skip_validation_runner) common_args['common_args'] = common_args %} - alloc_locals - local update_end : DictAccess* = update_ptr + n_updates * DictAccess.SIZE - - # Traverse prev tree. - let (local siblings) = alloc() - let original_update_ptr = update_ptr - let original_siblings = siblings - let (local globals_prev : ParticiaGlobals*) = alloc() + alloc_locals; + local update_end: DictAccess* = update_ptr + n_updates * DictAccess.SIZE; + + // Traverse prev tree. + let (local siblings) = alloc(); + let original_update_ptr = update_ptr; + let original_siblings = siblings; + let (local globals_prev: ParticiaGlobals*) = alloc(); assert [globals_prev] = ParticiaGlobals( - pow2=patricia_update_constants.globals_pow2, access_offset=DictAccess.prev_value) + pow2=patricia_update_constants.globals_pow2, access_offset=DictAccess.prev_value); - assert_le(height, MAX_LENGTH) + assert_le(height, MAX_LENGTH); %{ vm_enter_scope(dict(node=node, **common_args)) %} - with update_ptr, siblings: - traverse_node(globals=globals_prev, height=height, path=0, node=prev_root) - end + with update_ptr, siblings { + traverse_node(globals=globals_prev, height=height, path=0, node=prev_root); + } %{ vm_exit_scope() %} - assert update_ptr = update_end - local siblings_end : felt* = siblings + assert update_ptr = update_end; + local siblings_end: felt* = siblings; - # Traverse new tree. - let update_ptr = original_update_ptr - let siblings = original_siblings - let (local globals_new : ParticiaGlobals*) = alloc() + // Traverse new tree. + let update_ptr = original_update_ptr; + let siblings = original_siblings; + let (local globals_new: ParticiaGlobals*) = alloc(); assert [globals_new] = ParticiaGlobals( - pow2=patricia_update_constants.globals_pow2, access_offset=DictAccess.new_value) + pow2=patricia_update_constants.globals_pow2, access_offset=DictAccess.new_value); %{ vm_enter_scope(dict(node=node, **common_args)) %} - with update_ptr, siblings: - traverse_node(globals=globals_new, height=height, path=0, node=new_root) - end + with update_ptr, siblings { + traverse_node(globals=globals_new, height=height, path=0, node=new_root); + } %{ vm_exit_scope() %} - assert update_ptr = update_end - assert siblings = siblings_end - return () -end + assert update_ptr = update_end; + assert siblings = siblings_end; + return (); +} diff --git a/src/starkware/cairo/common/pow.cairo b/src/starkware/cairo/common/pow.cairo index 95c5692e..f73929ad 100644 --- a/src/starkware/cairo/common/pow.cairo +++ b/src/starkware/cairo/common/pow.cairo @@ -1,51 +1,51 @@ from starkware.cairo.common.math import assert_le from starkware.cairo.common.registers import get_ap, get_fp_and_pc -# Returns base ** exp, for 0 <= exp < 2**251. -func pow{range_check_ptr}(base, exp) -> (res : felt): - struct LoopLocals: - member bit : felt - member temp0 : felt - - member res : felt - member base : felt - member exp : felt - end - - if exp == 0: - return (1) - end - - let initial_locs : LoopLocals* = cast(fp - 2, LoopLocals*) - initial_locs.res = 1; ap++ - initial_locs.base = base; ap++ - initial_locs.exp = exp; ap++ +// Returns base ** exp, for 0 <= exp < 2**251. +func pow{range_check_ptr}(base, exp) -> (res: felt) { + struct LoopLocals { + bit: felt, + temp0: felt, + + res: felt, + base: felt, + exp: felt, + } + + if (exp == 0) { + return (res=1); + } + + let initial_locs: LoopLocals* = cast(fp - 2, LoopLocals*); + initial_locs.res = 1, ap++; + initial_locs.base = base, ap++; + initial_locs.exp = exp, ap++; loop: - let prev_locs : LoopLocals* = cast(ap - LoopLocals.SIZE, LoopLocals*) - let locs : LoopLocals* = cast(ap, LoopLocals*) - locs.base = prev_locs.base * prev_locs.base; ap++ + let prev_locs: LoopLocals* = cast(ap - LoopLocals.SIZE, LoopLocals*); + let locs: LoopLocals* = cast(ap, LoopLocals*); + locs.base = prev_locs.base * prev_locs.base, ap++; %{ ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1 %} - jmp odd if locs.bit != 0; ap++ + jmp odd if locs.bit != 0, ap++; even: - locs.exp = prev_locs.exp / 2; ap++ - locs.res = prev_locs.res; ap++ - # exp cannot be 0 here. - static_assert ap + 1 == locs + LoopLocals.SIZE - jmp loop; ap++ + locs.exp = prev_locs.exp / 2, ap++; + locs.res = prev_locs.res, ap++; + // exp cannot be 0 here. + static_assert ap + 1 == locs + LoopLocals.SIZE; + jmp loop, ap++; odd: - locs.temp0 = prev_locs.exp - 1 - locs.exp = locs.temp0 / 2; ap++ - locs.res = prev_locs.res * prev_locs.base; ap++ - static_assert ap + 1 == locs + LoopLocals.SIZE - jmp loop if locs.exp != 0; ap++ - - # Cap the number of steps. - let (__ap__) = get_ap() - let (__fp__, _) = get_fp_and_pc() - let n_steps = (__ap__ - cast(initial_locs, felt*)) / LoopLocals.SIZE - 1 - assert_le(n_steps, 251) - return (res=locs.res) -end + locs.temp0 = prev_locs.exp - 1; + locs.exp = locs.temp0 / 2, ap++; + locs.res = prev_locs.res * prev_locs.base, ap++; + static_assert ap + 1 == locs + LoopLocals.SIZE; + jmp loop if locs.exp != 0, ap++; + + // Cap the number of steps. + let (__ap__) = get_ap(); + let (__fp__, _) = get_fp_and_pc(); + let n_steps = (__ap__ - cast(initial_locs, felt*)) / LoopLocals.SIZE - 1; + assert_le(n_steps, 251); + return (res=locs.res); +} diff --git a/src/starkware/cairo/common/registers.cairo b/src/starkware/cairo/common/registers.cairo index dff2fef5..bdf8e7bd 100644 --- a/src/starkware/cairo/common/registers.cairo +++ b/src/starkware/cairo/common/registers.cairo @@ -1,26 +1,26 @@ from starkware.cairo.lang.compiler.lib.registers import get_ap, get_fp_and_pc -# Takes the value of a label (relative to program base) and returns the actual runtime address of -# that label in the memory. -# -# Example usage: -# -# func do_callback(...): -# ... -# end -# -# func do_thing_then_callback(callback): -# ... -# call abs callback -# end -# -# func main(): -# let (callback_address) = get_label_location(do_callback) -# do_thing_then_callback(callback=callback_address) -# end -func get_label_location(label_value : codeoffset) -> (res : felt*): - let (_, pc_val) = get_fp_and_pc() +// Takes the value of a label (relative to program base) and returns the actual runtime address of +// that label in the memory. +// +// Usage example: +// +// func do_callback(...) { +// ... +// } +// +// func do_thing_then_callback(callback) { +// ... +// call abs callback; +// } +// +// func main() { +// let (callback_address) = get_label_location(do_callback); +// do_thing_then_callback(callback=callback_address); +// } +func get_label_location(label_value: codeoffset) -> (res: felt*) { + let (_, pc_val) = get_fp_and_pc(); ret_pc_label: - return (res=pc_val + (label_value - ret_pc_label)) -end + return (res=pc_val + (label_value - ret_pc_label)); +} diff --git a/src/starkware/cairo/common/segments.cairo b/src/starkware/cairo/common/segments.cairo index 4a042abc..cc5abc02 100644 --- a/src/starkware/cairo/common/segments.cairo +++ b/src/starkware/cairo/common/segments.cairo @@ -1,11 +1,11 @@ -# Relocates src_ptr to dest_ptr. -# 'src_ptr' must point to the start of a temporary segment. -# -# See add_relocation_rule() in src/starkware/cairo/lang/vm/memory_dict.py for more details. -func relocate_segment(src_ptr : felt*, dest_ptr : felt*): +// Relocates src_ptr to dest_ptr. +// 'src_ptr' must point to the start of a temporary segment. +// +// See add_relocation_rule() in src/starkware/cairo/lang/vm/memory_dict.py for more details. +func relocate_segment(src_ptr: felt*, dest_ptr: felt*) { %{ memory.add_relocation_rule(src_ptr=ids.src_ptr, dest_ptr=ids.dest_ptr) %} - # Add a verifier side assert that src_ptr and dest_ptr are indeed equal. - assert src_ptr = dest_ptr - return () -end + // Add a verifier side assert that src_ptr and dest_ptr are indeed equal. + assert src_ptr = dest_ptr; + return (); +} diff --git a/src/starkware/cairo/common/serialize.cairo b/src/starkware/cairo/common/serialize.cairo index 1f070f61..6d4e3700 100644 --- a/src/starkware/cairo/common/serialize.cairo +++ b/src/starkware/cairo/common/serialize.cairo @@ -1,58 +1,58 @@ -# Appends a single word to the output pointer, and returns the pointer to the next output cell. -func serialize_word{output_ptr : felt*}(word): - assert [output_ptr] = word - let output_ptr = output_ptr + 1 - return () -end +// Appends a single word to the output pointer, and returns the pointer to the next output cell. +func serialize_word{output_ptr: felt*}(word) { + assert [output_ptr] = word; + let output_ptr = output_ptr + 1; + return (); +} -# Array right fold: computes the following: -# callback(callback(... callback(value, a[n-1]) ..., a[1]), a[0]) -# Arguments: -# value - the initial value. -# array - a pointer to an array. -# elm_size - the size of an element in the array. -# n_elms - the number of elements in the array. -# callback - a function pointer to the callback. Expected signature: (felt, T*) -> felt. -# -# Use starkware.cairo.common.registers.get_label_location() to convert a function label to -# a callback value. -func array_rfold(value, array : felt*, n_elms, elm_size, callback : felt*) -> (res : felt): - if n_elms == 0: - return (value) - end +// Array right fold: computes the following: +// callback(callback(... callback(value, a[n-1]) ..., a[1]), a[0]) +// Arguments: +// value - the initial value. +// array - a pointer to an array. +// elm_size - the size of an element in the array. +// n_elms - the number of elements in the array. +// callback - a function pointer to the callback. Expected signature: (felt, T*) -> felt. +// +// Use starkware.cairo.common.registers.get_label_location() to convert a function label to +// a callback value. +func array_rfold(value, array: felt*, n_elms, elm_size, callback: felt*) -> (res: felt) { + if (n_elms == 0) { + return (res=value); + } - [ap] = value; ap++ - [ap] = array; ap++ - call abs callback - # [ap - 1] holds the return value of callback. + [ap] = value, ap++; + [ap] = array, ap++; + call abs callback; + // [ap - 1] holds the return value of callback. return array_rfold( value=[ap - 1], array=array + elm_size, n_elms=n_elms - 1, elm_size=elm_size, callback=callback, - ) -end + ); +} -# Serializes an array of objects to output_ptr, and returns the pointer to the next output cell. -# The format is: len(array) || callback(a[0]) || ... || callback(a[n-1]) . -# Arguments: -# output_ptr - the pointer to serialize to. -# array - a pointer to an array. -# elm_size - the size of an element in the array. -# n_elms - the number of elements in the array. -# callback - a function pointer to the serialize function of a single element. -# Expected signature: (felt, T*) -> felt. -# Use starkware.cairo.common.registers.get_label_location() to convert a function label to -# a callback value. -func serialize_array{output_ptr : felt*}(array : felt*, n_elms, elm_size, callback : felt*): - serialize_word(n_elms) - let (output_ptr : felt*) = array_rfold( +// Serializes an array of objects to output_ptr, and returns the pointer to the next output cell. +// The format is: len(array) || callback(a[0]) || ... || callback(a[n-1]) . +// Arguments: +// output_ptr - the pointer to serialize to. +// array - a pointer to an array. +// elm_size - the size of an element in the array. +// n_elms - the number of elements in the array. +// callback - a function pointer to the serialize function of a single element. +// Expected signature: (felt, T*) -> felt. +// Use starkware.cairo.common.registers.get_label_location() to convert a function label to +// a callback value. +func serialize_array{output_ptr: felt*}(array: felt*, n_elms, elm_size, callback: felt*) { + serialize_word(n_elms); + let (output_ptr: felt*) = array_rfold( value=cast(output_ptr, felt), array=array, n_elms=n_elms, elm_size=elm_size, callback=callback, - ) - return () -end + ); + return (); +} diff --git a/src/starkware/cairo/common/set.cairo b/src/starkware/cairo/common/set.cairo index 49b4883a..b04a90e4 100644 --- a/src/starkware/cairo/common/set.cairo +++ b/src/starkware/cairo/common/set.cairo @@ -1,36 +1,36 @@ from starkware.cairo.common.math import assert_nn_le from starkware.cairo.common.memcpy import memcpy -const SET_ADD_RANGE_CHECK_USAGE_ON_DUPLICATE = 2 -const SET_ADD_RANGE_CHECK_USAGE_ON_NO_DUPLICATE = 0 +const SET_ADD_RANGE_CHECK_USAGE_ON_DUPLICATE = 2; +const SET_ADD_RANGE_CHECK_USAGE_ON_NO_DUPLICATE = 0; -# Given an array of elements and an element, does one of two things: -# 1. Adds the element to the array. -# 2. Verifies that the element is in the array (all of the fields of the element are equal to all of -# the fields of one of the array's elements). -# -# Note that this function does not ensure that the elements of the resulted array are distinct -# (from soundness perspective). In other words, from the verifier's perspective, an element may be -# added even if it already existed. (On the other hand, from the prover perspective an element won't -# be added if it already exists). -# This function is usually used in order to avoid long arrays where it doesn't matter if an element -# exists more than once in the array. -# -# Arguments: -# set_ptr - pointer to an array. -# elm_size - size of an element in the array. -# elm_ptr - pointer to an element (of size elm_size) to add to the set. -# -# Implicit arguments: -# range_check_ptr - range check builtin pointer. -# set_end_ptr - pointer to the end of the array. -# -# Assumptions: -# elm_size != 0. -func set_add{range_check_ptr, set_end_ptr : felt*}(set_ptr : felt*, elm_size, elm_ptr : felt*): - alloc_locals - local is_elm_in_set - local index +// Given an array of elements and an element, does one of two things: +// 1. Adds the element to the array. +// 2. Verifies that the element is in the array (all of the fields of the element are equal to all +// of the fields of one of the array's elements). +// +// Note that this function does not ensure that the elements of the resulted array are distinct +// (from soundness perspective). In other words, from the verifier's perspective, an element may be +// added even if it already existed. (On the other hand, from the prover perspective an element +// won't be added if it already exists). +// This function is usually used in order to avoid long arrays where it doesn't matter if an element +// exists more than once in the array. +// +// Arguments: +// set_ptr - pointer to an array. +// elm_size - size of an element in the array. +// elm_ptr - pointer to an element (of size elm_size) to add to the set. +// +// Implicit arguments: +// range_check_ptr - range check builtin pointer. +// set_end_ptr - pointer to the end of the array. +// +// Assumptions: +// elm_size != 0. +func set_add{range_check_ptr, set_end_ptr: felt*}(set_ptr: felt*, elm_size, elm_ptr: felt*) { + alloc_locals; + local is_elm_in_set; + local index; %{ assert ids.elm_size > 0 assert ids.set_ptr <= ids.set_end_ptr @@ -43,16 +43,16 @@ func set_add{range_check_ptr, set_end_ptr : felt*}(set_ptr : felt*, elm_size, el else: ids.is_elm_in_set = 0 %} - if is_elm_in_set != 0: - local located_elm_ptr : felt* = set_ptr + elm_size * index - # Using memcpy for equality assertion. - memcpy(dst=located_elm_ptr, src=elm_ptr, len=elm_size) - tempvar n_elms = (cast(set_end_ptr, felt) - cast(set_ptr, felt)) / elm_size - assert_nn_le(index, n_elms - 1) - return () - else: - memcpy(dst=set_end_ptr, src=elm_ptr, len=elm_size) - let set_end_ptr : felt* = set_end_ptr + elm_size - return () - end -end + if (is_elm_in_set != 0) { + local located_elm_ptr: felt* = set_ptr + elm_size * index; + // Using memcpy for equality assertion. + memcpy(dst=located_elm_ptr, src=elm_ptr, len=elm_size); + tempvar n_elms = (cast(set_end_ptr, felt) - cast(set_ptr, felt)) / elm_size; + assert_nn_le(index, n_elms - 1); + return (); + } else { + memcpy(dst=set_end_ptr, src=elm_ptr, len=elm_size); + let set_end_ptr: felt* = set_end_ptr + elm_size; + return (); + } +} diff --git a/src/starkware/cairo/common/signature.cairo b/src/starkware/cairo/common/signature.cairo index 8547c64d..8ffc3bca 100644 --- a/src/starkware/cairo/common/signature.cairo +++ b/src/starkware/cairo/common/signature.cairo @@ -1,16 +1,83 @@ -from starkware.cairo.common.cairo_builtins import SignatureBuiltin +from starkware.cairo.common.bool import FALSE, TRUE +from starkware.cairo.common.cairo_builtins import EcOpBuiltin, SignatureBuiltin +from starkware.cairo.common.ec import StarkCurve, ec_add, ec_mul, ec_sub, is_x_on_curve, recover_y +from starkware.cairo.common.ec_point import EcPoint -# Verifies that the prover knows a signature of the given public_key on the given message. -# -# Prover assumption: (signature_r, signature_s) is a valid signature for the given public_key -# on the given message. -func verify_ecdsa_signature{ecdsa_ptr : SignatureBuiltin*}( +// Verifies that the prover knows a signature of the given public_key on the given message. +// +// Prover assumption: (signature_r, signature_s) is a valid signature for the given public_key +// on the given message. +func verify_ecdsa_signature{ecdsa_ptr: SignatureBuiltin*}( message, public_key, signature_r, signature_s -): +) { %{ ecdsa_builtin.add_signature(ids.ecdsa_ptr.address_, (ids.signature_r, ids.signature_s)) %} - assert ecdsa_ptr.message = message - assert ecdsa_ptr.pub_key = public_key + assert ecdsa_ptr.message = message; + assert ecdsa_ptr.pub_key = public_key; - let ecdsa_ptr = ecdsa_ptr + SignatureBuiltin.SIZE - return () -end + let ecdsa_ptr = ecdsa_ptr + SignatureBuiltin.SIZE; + return (); +} + +// Checks if (signature_r, signature_s) is a valid signature for the given public_key +// on the given message. +// +// Arguments: +// message - the signed message. +// public_key - the public key corresponding to the key with which the message was signed. +// signature_r - the r component of the ECDSA signature. +// signature_s - the s component of the ECDSA signature. +// +// Returns: +// res - TRUE if the signature is valid, FALSE otherwise. +func check_ecdsa_signature{ec_op_ptr: EcOpBuiltin*}( + message, public_key, signature_r, signature_s +) -> (res: felt) { + alloc_locals; + // Check that s != 0 (mod StarkCurve.ORDER). + if (signature_s == 0) { + return (res=FALSE); + } + if (signature_s == StarkCurve.ORDER) { + return (res=FALSE); + } + if (signature_r == StarkCurve.ORDER) { + return (res=FALSE); + } + + // Check that the public key is the x coordinate of a point on the curve. + let on_curve: felt = is_x_on_curve(public_key); + if (on_curve == FALSE) { + return (res=FALSE); + } + // Check that r is the x coordinate of a point on the curve. + // Note that this ensures that r != 0. + let on_curve: felt = is_x_on_curve(signature_r); + if (on_curve == FALSE) { + return (res=FALSE); + } + + // To verify ECDSA, obtain: + // zG = z * G, where z is the message and G is a generator of the EC. + // rQ = r * Q, where Q.x = public_key. + // sR = s * R, where R.x = r. + // and check that: + // zG +/- rQ = +/- sR, or more efficiently that: + // (zG +/- rQ).x = sR.x. + let (zG: EcPoint) = ec_mul(m=message, p=EcPoint(x=StarkCurve.GEN_X, y=StarkCurve.GEN_Y)); + let (public_key_point: EcPoint) = recover_y(public_key); + let (rQ: EcPoint) = ec_mul(signature_r, public_key_point); + let (signature_r_point: EcPoint) = recover_y(signature_r); + let (sR: EcPoint) = ec_mul(signature_s, signature_r_point); + + let (candidate: EcPoint) = ec_add(zG, rQ); + if (candidate.x == sR.x) { + return (res=TRUE); + } + + let (candidate: EcPoint) = ec_sub(zG, rQ); + if (candidate.x == sR.x) { + return (res=TRUE); + } + + return (res=FALSE); +} diff --git a/src/starkware/cairo/common/small_merkle_tree.cairo b/src/starkware/cairo/common/small_merkle_tree.cairo index d03b2ea6..fd7f79b8 100644 --- a/src/starkware/cairo/common/small_merkle_tree.cairo +++ b/src/starkware/cairo/common/small_merkle_tree.cairo @@ -2,58 +2,58 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.dict import DictAccess from starkware.cairo.common.merkle_multi_update import merkle_multi_update -# Performs an efficient update of multiple leaves in a Merkle tree, based on the given squashed -# dict, assuming the merkle tree is small enough to be loaded to the memory. -# -# This function computes the Merkle authentication paths internally and -# does not require any hint arguments, therefore it's usually easier to use. -# The input dict must be created using the higher-level dict functions (see dict.cairo), which add -# information about all the non-default leaves in the hints (not just the leaves that were changed). -# -# Usage example: -# %{ initial_dict = {1: 2, 3: 4, 5: 6} %} -# let (dict_ptr_start) = dict_new() -# let dict_ptr = dict_ptr_start -# let (dict_ptr) = dict_update(dict_ptr=dict_ptr, key=1, prev_value=2, new_value=20) -# let (range_check_ptr, squashed_dict_start, squashed_dict_end) = dict_squash( -# range_check_ptr=range_check_ptr, -# dict_accesses_start=dict_ptr_start, -# dict_accesses_end=dict_ptr) -# const HEIGHT = 3 -# let (prev_root, new_root) = small_merkle_tree_update( -# squashed_dict_start, squashed_dict_end, HEIGHT) -# -# In this example prev_root is the Merkle root of [0, 2, 0, 4, 0, 6, 0, 0], and new_root -# is the Merkle root of [0, 20, 0, 4, 0, 6, 0, 0]. -# Note that from the point of view of the verifier, all it knows is that leaf 1 changed from 2 to -# 20 -- it doesn't know anything about the other leaves (except that they haven't changed). -# -# Arguments: -# squashed_dict, squashed_dict_end - a list of DictAccess instances sorted by key -# (e.g., the result of dict_squash). -# height - the height of the merkle tree. -# -# Implicit arguments: -# hash_ptr - hash builtin pointer. -# -# Returns: -# prev_root - the value of the root before the update. -# new_root - the value of the root after the update. -# -# Assumptions: The keys in the squashed_dict are unique and sorted. -# -# Prover assumptions: -# * squashed_dict was created using the higher-level API dict_squash() (rather than squash_dict()). -# * This function can be used for (relatively) small Merkle trees whose leaves can be loaded -# to the memory. -func small_merkle_tree_update{hash_ptr : HashBuiltin*}( - squashed_dict_start : DictAccess*, squashed_dict_end : DictAccess*, height : felt -) -> (prev_root : felt, new_root : felt): +// Performs an efficient update of multiple leaves in a Merkle tree, based on the given squashed +// dict, assuming the merkle tree is small enough to be loaded to the memory. +// +// This function computes the Merkle authentication paths internally and +// does not require any hint arguments, therefore it's usually easier to use. +// The input dict must be created using the higher-level dict functions (see dict.cairo), which add +// information about all the non-default leaves in the hints (not just the leaves that were +// changed). +// +// Usage example: +// %{ initial_dict = {1: 2, 3: 4, 5: 6} %} +// let (dict_ptr_start) = dict_new(); +// let dict_ptr = dict_ptr_start; +// dict_update{dict_ptr=dict_ptr}(key=1, prev_value=2, new_value=20); +// let (squashed_dict_start, squashed_dict_end) = dict_squash( +// dict_accesses_start=dict_ptr_start, +// dict_accesses_end=dict_ptr); +// const HEIGHT = 3; +// let (prev_root, new_root) = small_merkle_tree_update( +// squashed_dict_start, squashed_dict_end, HEIGHT); +// +// In this example prev_root is the Merkle root of [0, 2, 0, 4, 0, 6, 0, 0], and new_root +// is the Merkle root of [0, 20, 0, 4, 0, 6, 0, 0]. +// Note that from the point of view of the verifier, all it knows is that leaf 1 changed from 2 to +// 20 -- it doesn't know anything about the other leaves (except that they haven't changed). +// +// Arguments: +// squashed_dict, squashed_dict_end - a list of DictAccess instances sorted by key +// (e.g., the result of dict_squash). +// height - the height of the merkle tree. +// +// Implicit arguments: +// hash_ptr - hash builtin pointer. +// +// Returns: +// prev_root - the value of the root before the update. +// new_root - the value of the root after the update. +// +// Assumptions: The keys in the squashed_dict are unique and sorted. +// +// Prover assumptions: +// * squashed_dict was created using the higher-level API dict_squash() (rather than squash_dict()). +// * This function can be used for (relatively) small Merkle trees whose leaves can be loaded +// to the memory. +func small_merkle_tree_update{hash_ptr: HashBuiltin*}( + squashed_dict_start: DictAccess*, squashed_dict_end: DictAccess*, height: felt +) -> (prev_root: felt, new_root: felt) { %{ vm_enter_scope({'__dict_manager': __dict_manager}) %} - alloc_locals - # Allocate memory cells for the roots. - local prev_root - local new_root + alloc_locals; + // Allocate memory cells for the roots. + local prev_root; + local new_root; %{ # Compute the roots and the preimage dictionary. from starkware.cairo.common.small_merkle_tree import get_preimage_dictionary @@ -89,14 +89,14 @@ func small_merkle_tree_update{hash_ptr : HashBuiltin*}( default_leaf=0) %} - # Call merkle_multi_update() to verify the two roots. + // Call merkle_multi_update() to verify the two roots. merkle_multi_update( update_ptr=squashed_dict_start, n_updates=(squashed_dict_end - squashed_dict_start) / DictAccess.SIZE, height=height, prev_root=prev_root, new_root=new_root, - ) + ); %{ vm_exit_scope() %} - return (prev_root=prev_root, new_root=new_root) -end + return (prev_root=prev_root, new_root=new_root); +} diff --git a/src/starkware/cairo/common/squash_dict.cairo b/src/starkware/cairo/common/squash_dict.cairo index 3e3424ee..358fe120 100644 --- a/src/starkware/cairo/common/squash_dict.cairo +++ b/src/starkware/cairo/common/squash_dict.cairo @@ -1,41 +1,41 @@ from starkware.cairo.common.dict_access import DictAccess from starkware.cairo.common.math import assert_lt_felt -# Verifies that dict_accesses lists valid chronological accesses (and updates) -# to a mutable dictionary and outputs a squashed dict with one DictAccess instance per key -# (value before and value after) which summarizes all the changes to that key. -# -# Example: -# Input: {(key1, 0, 2), (key1, 2, 7), (key2, 4, 1), (key1, 7, 5), (key2, 1, 2)} -# Output: {(key1, 0, 5), (key2, 4, 2)} -# -# Arguments: -# dict_accesses - a pointer to the beginning of an array of DictAccess instances. The format of each -# entry is a triplet (key, prev_value, new_value). -# dict_accesses_end - a pointer to the end of said array. -# squashed_dict - a pointer to an output array, which will be filled with -# DictAccess instances sorted by key with the first and last value for each key. -# -# Returns: -# squashed_dict - end pointer to squashed_dict. -# -# Implicit arguments: -# range_check_ptr - range check builtin pointer. +// Verifies that dict_accesses lists valid chronological accesses (and updates) +// to a mutable dictionary and outputs a squashed dict with one DictAccess instance per key +// (value before and value after) which summarizes all the changes to that key. +// +// Example: +// Input: {(key1, 0, 2), (key1, 2, 7), (key2, 4, 1), (key1, 7, 5), (key2, 1, 2)} +// Output: {(key1, 0, 5), (key2, 4, 2)} +// +// Arguments: +// dict_accesses - a pointer to the beginning of an array of DictAccess instances. The format of +// each entry is a triplet (key, prev_value, new_value). +// dict_accesses_end - a pointer to the end of said array. +// squashed_dict - a pointer to an output array, which will be filled with +// DictAccess instances sorted by key with the first and last value for each key. +// +// Returns: +// squashed_dict - end pointer to squashed_dict. +// +// Implicit arguments: +// range_check_ptr - range check builtin pointer. func squash_dict{range_check_ptr}( - dict_accesses : DictAccess*, dict_accesses_end : DictAccess*, squashed_dict : DictAccess* -) -> (squashed_dict : DictAccess*): - alloc_locals + dict_accesses: DictAccess*, dict_accesses_end: DictAccess*, squashed_dict: DictAccess* +) -> (squashed_dict: DictAccess*) { + alloc_locals; %{ vm_enter_scope() %} - local ptr_diff = dict_accesses_end - dict_accesses + local ptr_diff = dict_accesses_end - dict_accesses; - if ptr_diff == 0: - # Access array is empty, nothing to check. + if (ptr_diff == 0) { + // Access array is empty, nothing to check. %{ vm_exit_scope() %} - return (squashed_dict=squashed_dict) - end - local first_key - local big_keys - tempvar n_accesses = ptr_diff / DictAccess.SIZE + return (squashed_dict=squashed_dict); + } + local first_key; + local big_keys; + tempvar n_accesses = ptr_diff / DictAccess.SIZE; %{ dict_access_size = ids.DictAccess.SIZE address = ids.dict_accesses.address_ @@ -58,13 +58,13 @@ func squash_dict{range_check_ptr}( ids.first_key = key = keys.pop() %} - # Call inner. - if big_keys != 0: - tempvar range_check_ptr = range_check_ptr - else: - assert first_key = [range_check_ptr] - tempvar range_check_ptr = range_check_ptr + 1 - end + // Call inner. + if (big_keys != 0) { + tempvar range_check_ptr = range_check_ptr; + } else { + assert first_key = [range_check_ptr]; + tempvar range_check_ptr = range_check_ptr + 1; + } let (range_check_ptr, squashed_dict) = squash_dict_inner( range_check_ptr=range_check_ptr, dict_accesses=dict_accesses, @@ -73,173 +73,173 @@ func squash_dict{range_check_ptr}( remaining_accesses=n_accesses, squashed_dict=squashed_dict, big_keys=big_keys, - ) + ); %{ vm_exit_scope() %} - return (squashed_dict=squashed_dict) -end - -# Inner tail-recursive function for squash_dict. -# -# Arguments: -# range_check_ptr - range check builtin pointer. -# dict_accesses - a pointer to the beginning of an array of DictAccess instances. -# dict_accesses_end_minus1 - a pointer to the end of said array, minus 1. -# key - current DictAccess key to check. -# remaining_accesses - remaining number of accesses that need to be accounted for. Starts with -# the total number of entries in dict_accesses array, and slowly decreases until it reaches 0. -# squashed_dict - a pointer to an output array, which will be filled with -# DictAccess instances sorted by key with the first and last value for each key. -# -# Hints: -# keys - a descending list of the keys for which we have accesses. Destroyed in the process. -# access_indices - A map from key to a descending list of indices in the dict_accesses array that -# access this key. Destroyed in the process. -# -# Returns: -# range_check_ptr - updated range check builtin pointer. -# squashed_dict - end pointer to squashed_dict. + return (squashed_dict=squashed_dict); +} + +// Inner tail-recursive function for squash_dict. +// +// Arguments: +// range_check_ptr - range check builtin pointer. +// dict_accesses - a pointer to the beginning of an array of DictAccess instances. +// dict_accesses_end_minus1 - a pointer to the end of said array, minus 1. +// key - current DictAccess key to check. +// remaining_accesses - remaining number of accesses that need to be accounted for. Starts with +// the total number of entries in dict_accesses array, and slowly decreases until it reaches 0. +// squashed_dict - a pointer to an output array, which will be filled with +// DictAccess instances sorted by key with the first and last value for each key. +// +// Hints: +// keys - a descending list of the keys for which we have accesses. Destroyed in the process. +// access_indices - A map from key to a descending list of indices in the dict_accesses array that +// access this key. Destroyed in the process. +// +// Returns: +// range_check_ptr - updated range check builtin pointer. +// squashed_dict - end pointer to squashed_dict. func squash_dict_inner( range_check_ptr, - dict_accesses : DictAccess*, - dict_accesses_end_minus1 : felt*, + dict_accesses: DictAccess*, + dict_accesses_end_minus1: felt*, key, remaining_accesses, - squashed_dict : DictAccess*, + squashed_dict: DictAccess*, big_keys, -) -> (range_check_ptr : felt, squashed_dict : DictAccess*): - alloc_locals - - let dict_diff : DictAccess* = squashed_dict - - # Loop to verify chronological accesses to the key. - # These values are not needed from previous iteration. - struct LoopTemps: - member index_delta_minus1 : felt - member index_delta : felt - member ptr_delta : felt - member should_continue : felt - end - # These values are needed from previous iteration. - struct LoopLocals: - member value : felt - member access_ptr : DictAccess* - member range_check_ptr : felt - end - - # Prepare first iteration. +) -> (range_check_ptr: felt, squashed_dict: DictAccess*) { + alloc_locals; + + let dict_diff: DictAccess* = squashed_dict; + + // Loop to verify chronological accesses to the key. + // These values are not needed from previous iteration. + struct LoopTemps { + index_delta_minus1: felt, + index_delta: felt, + ptr_delta: felt, + should_continue: felt, + } + // These values are needed from previous iteration. + struct LoopLocals { + value: felt, + access_ptr: DictAccess*, + range_check_ptr: felt, + } + + // Prepare first iteration. %{ current_access_indices = sorted(access_indices[key])[::-1] current_access_index = current_access_indices.pop() memory[ids.range_check_ptr] = current_access_index %} - # Check that first access_index >= 0. - tempvar current_access_index = [range_check_ptr] - tempvar ptr_delta = current_access_index * DictAccess.SIZE - - let first_loop_locals = cast(ap, LoopLocals*) - first_loop_locals.access_ptr = dict_accesses + ptr_delta; ap++ - let first_access : DictAccess* = first_loop_locals.access_ptr - first_loop_locals.value = first_access.new_value; ap++ - first_loop_locals.range_check_ptr = range_check_ptr + 1; ap++ - - # Verify first key. - key = first_access.key - - # Write key and first value to dict_diff. - key = dict_diff.key - # Use a local variable, instead of a tempvar, to avoid increasing ap. - local first_value = first_access.prev_value - assert first_value = dict_diff.prev_value - - # Skip loop nondeterministically if necessary. - # The verifier doesn't care if the loop is skipped or not. The only thing it checks is that - # the function iterated over remaining_accesses accesses in total - # with ascending keys and ascending indices for the same key. - # This guarantees that all the entries were visited exactly once. - local should_skip_loop + // Check that first access_index >= 0. + tempvar current_access_index = [range_check_ptr]; + tempvar ptr_delta = current_access_index * DictAccess.SIZE; + + let first_loop_locals = cast(ap, LoopLocals*); + first_loop_locals.access_ptr = dict_accesses + ptr_delta, ap++; + let first_access: DictAccess* = first_loop_locals.access_ptr; + first_loop_locals.value = first_access.new_value, ap++; + first_loop_locals.range_check_ptr = range_check_ptr + 1, ap++; + + // Verify first key. + key = first_access.key; + + // Write key and first value to dict_diff. + key = dict_diff.key; + // Use a local variable, instead of a tempvar, to avoid increasing ap. + local first_value = first_access.prev_value; + assert first_value = dict_diff.prev_value; + + // Skip loop nondeterministically if necessary. + // The verifier doesn't care if the loop is skipped or not. The only thing it checks is that + // the function iterated over remaining_accesses accesses in total + // with ascending keys and ascending indices for the same key. + // This guarantees that all the entries were visited exactly once. + local should_skip_loop; %{ ids.should_skip_loop = 0 if current_access_indices else 1 %} - jmp skip_loop if should_skip_loop != 0 + jmp skip_loop if should_skip_loop != 0; loop: - # Define references to access the values from the previous iteration, - # the temporary variables and the values for the current iteration. - let prev_loop_locals = cast(ap - LoopLocals.SIZE, LoopLocals*) - let loop_temps = cast(ap, LoopTemps*) - let loop_locals = cast(ap + LoopTemps.SIZE, LoopLocals*) + // Define references to access the values from the previous iteration, + // the temporary variables and the values for the current iteration. + let prev_loop_locals = cast(ap - LoopLocals.SIZE, LoopLocals*); + let loop_temps = cast(ap, LoopTemps*); + let loop_locals = cast(ap + LoopTemps.SIZE, LoopLocals*); - # Check access_index. + // Check access_index. %{ new_access_index = current_access_indices.pop() ids.loop_temps.index_delta_minus1 = new_access_index - current_access_index - 1 current_access_index = new_access_index %} - # Check that new access_index > prev access_index. - loop_temps.index_delta_minus1 = [prev_loop_locals.range_check_ptr]; ap++ - loop_temps.index_delta = loop_temps.index_delta_minus1 + 1; ap++ - loop_temps.ptr_delta = loop_temps.index_delta * DictAccess.SIZE; ap++ - loop_locals.access_ptr = prev_loop_locals.access_ptr + loop_temps.ptr_delta; ap++ + // Check that new access_index > prev access_index. + loop_temps.index_delta_minus1 = [prev_loop_locals.range_check_ptr], ap++; + loop_temps.index_delta = loop_temps.index_delta_minus1 + 1, ap++; + loop_temps.ptr_delta = loop_temps.index_delta * DictAccess.SIZE, ap++; + loop_locals.access_ptr = prev_loop_locals.access_ptr + loop_temps.ptr_delta, ap++; - # Check valid transition. - let access : DictAccess* = loop_locals.access_ptr - prev_loop_locals.value = access.prev_value - loop_locals.value = access.new_value; ap++ + // Check valid transition. + let access: DictAccess* = loop_locals.access_ptr; + prev_loop_locals.value = access.prev_value; + loop_locals.value = access.new_value, ap++; - # Verify key. - key = access.key + // Verify key. + key = access.key; - # Next range_check_ptr. - loop_locals.range_check_ptr = prev_loop_locals.range_check_ptr + 1; ap++ + // Next range_check_ptr. + loop_locals.range_check_ptr = prev_loop_locals.range_check_ptr + 1, ap++; - # The verifier doesn't care how many loop iterations are executed. See comment above. + // The verifier doesn't care how many loop iterations are executed. See comment above. %{ ids.loop_temps.should_continue = 1 if current_access_indices else 0 %} - jmp loop if loop_temps.should_continue != 0; ap++ + jmp loop if loop_temps.should_continue != 0, ap++; skip_loop: - let last_loop_locals = cast(ap - LoopLocals.SIZE, LoopLocals*) + let last_loop_locals = cast(ap - LoopLocals.SIZE, LoopLocals*); - # Check if address is out of bounds. + // Check if address is out of bounds. %{ assert len(current_access_indices) == 0 %} - [ap] = dict_accesses_end_minus1 - cast(last_loop_locals.access_ptr, felt) - [ap] = [last_loop_locals.range_check_ptr]; ap++ - # Calculating the number of used accesses from the number of range check usages for efficiency. - tempvar n_used_accesses = last_loop_locals.range_check_ptr - range_check_ptr + [ap] = dict_accesses_end_minus1 - cast(last_loop_locals.access_ptr, felt); + [ap] = [last_loop_locals.range_check_ptr], ap++; + // Calculating the number of used accesses from the number of range check usages for efficiency. + tempvar n_used_accesses = last_loop_locals.range_check_ptr - range_check_ptr; %{ assert ids.n_used_accesses == len(access_indices[key]) %} - # Write last value to dict_diff. - last_loop_locals.value = dict_diff.new_value + // Write last value to dict_diff. + last_loop_locals.value = dict_diff.new_value; - let range_check_ptr = last_loop_locals.range_check_ptr + 1 - tempvar remaining_accesses = remaining_accesses - n_used_accesses + let range_check_ptr = last_loop_locals.range_check_ptr + 1; + tempvar remaining_accesses = remaining_accesses - n_used_accesses; - # Exit recursion when done. - if remaining_accesses == 0: + // Exit recursion when done. + if (remaining_accesses == 0) { %{ assert len(keys) == 0 %} - return (range_check_ptr=range_check_ptr, squashed_dict=squashed_dict + DictAccess.SIZE) - end + return (range_check_ptr=range_check_ptr, squashed_dict=squashed_dict + DictAccess.SIZE); + } - # ap points to the address of the beginning of the next access in the list. - let next_key = [ap] - ap += 1 - # Guess next_key and check that next_key > key. + // ap points to the address of the beginning of the next access in the list. + let next_key = [ap]; + ap += 1; + // Guess next_key and check that next_key > key. %{ assert len(keys) > 0, 'No keys left but remaining_accesses > 0.' ids.next_key = key = keys.pop() %} - if big_keys != 0: - assert_lt_felt{range_check_ptr=range_check_ptr}(a=key, b=next_key) - tempvar dict_accesses = dict_accesses - tempvar dict_accesses_end_minus1 = dict_accesses_end_minus1 - tempvar next_key = next_key - tempvar remaining_accesses = remaining_accesses - else: - assert [range_check_ptr] = next_key - (key + 1) - tempvar range_check_ptr = range_check_ptr + 1 - tempvar dict_accesses = dict_accesses - tempvar dict_accesses_end_minus1 = dict_accesses_end_minus1 - tempvar next_key = next_key - tempvar remaining_accesses = remaining_accesses - end + if (big_keys != 0) { + assert_lt_felt{range_check_ptr=range_check_ptr}(a=key, b=next_key); + tempvar dict_accesses = dict_accesses; + tempvar dict_accesses_end_minus1 = dict_accesses_end_minus1; + tempvar next_key = next_key; + tempvar remaining_accesses = remaining_accesses; + } else { + assert [range_check_ptr] = next_key - (key + 1); + tempvar range_check_ptr = range_check_ptr + 1; + tempvar dict_accesses = dict_accesses; + tempvar dict_accesses_end_minus1 = dict_accesses_end_minus1; + tempvar next_key = next_key; + tempvar remaining_accesses = remaining_accesses; + } return squash_dict_inner( range_check_ptr=range_check_ptr, @@ -249,5 +249,5 @@ func squash_dict_inner( remaining_accesses=remaining_accesses, squashed_dict=squashed_dict + DictAccess.SIZE, big_keys=big_keys, - ) -end + ); +} diff --git a/src/starkware/cairo/common/uint256.cairo b/src/starkware/cairo/common/uint256.cairo index eca0e114..8599cb89 100644 --- a/src/starkware/cairo/common/uint256.cairo +++ b/src/starkware/cairo/common/uint256.cairo @@ -5,34 +5,34 @@ from starkware.cairo.common.math_cmp import is_le from starkware.cairo.common.pow import pow from starkware.cairo.common.registers import get_ap, get_fp_and_pc -# Represents an integer in the range [0, 2^256). -struct Uint256: - # The low 128 bits of the value. - member low : felt - # The high 128 bits of the value. - member high : felt -end - -const SHIFT = 2 ** 128 -const ALL_ONES = 2 ** 128 - 1 -const HALF_SHIFT = 2 ** 64 - -# Verifies that the given integer is valid. -func uint256_check{range_check_ptr}(a : Uint256): - [range_check_ptr] = a.low - [range_check_ptr + 1] = a.high - let range_check_ptr = range_check_ptr + 2 - return () -end - -# Arithmetics. - -# Adds two integers. Returns the result as a 256-bit integer and the (1-bit) carry. -func uint256_add{range_check_ptr}(a : Uint256, b : Uint256) -> (res : Uint256, carry : felt): - alloc_locals - local res : Uint256 - local carry_low : felt - local carry_high : felt +// Represents an integer in the range [0, 2^256). +struct Uint256 { + // The low 128 bits of the value. + low: felt, + // The high 128 bits of the value. + high: felt, +} + +const SHIFT = 2 ** 128; +const ALL_ONES = 2 ** 128 - 1; +const HALF_SHIFT = 2 ** 64; + +// Verifies that the given integer is valid. +func uint256_check{range_check_ptr}(a: Uint256) { + [range_check_ptr] = a.low; + [range_check_ptr + 1] = a.high; + let range_check_ptr = range_check_ptr + 2; + return (); +} + +// Arithmetics. + +// Adds two integers. Returns the result as a 256-bit integer and the (1-bit) carry. +func uint256_add{range_check_ptr}(a: Uint256, b: Uint256) -> (res: Uint256, carry: felt) { + alloc_locals; + local res: Uint256; + local carry_low: felt; + local carry_high: felt; %{ sum_low = ids.a.low + ids.b.low ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 @@ -40,60 +40,61 @@ func uint256_add{range_check_ptr}(a : Uint256, b : Uint256) -> (res : Uint256, c ids.carry_high = 1 if sum_high >= ids.SHIFT else 0 %} - assert carry_low * carry_low = carry_low - assert carry_high * carry_high = carry_high + assert carry_low * carry_low = carry_low; + assert carry_high * carry_high = carry_high; - assert res.low = a.low + b.low - carry_low * SHIFT - assert res.high = a.high + b.high + carry_low - carry_high * SHIFT - uint256_check(res) + assert res.low = a.low + b.low - carry_low * SHIFT; + assert res.high = a.high + b.high + carry_low - carry_high * SHIFT; + uint256_check(res); - return (res, carry_high) -end + return (res, carry_high); +} -# Splits a field element in the range [0, 2^192) to its low 64-bit and high 128-bit parts. -func split_64{range_check_ptr}(a : felt) -> (low : felt, high : felt): - alloc_locals - local low : felt - local high : felt +// Splits a field element in the range [0, 2^192) to its low 64-bit and high 128-bit parts. +// Soundness guarantee: a is in the range [0, 2^192). +func split_64{range_check_ptr}(a: felt) -> (low: felt, high: felt) { + alloc_locals; + local low: felt; + local high: felt; %{ ids.low = ids.a & ((1<<64) - 1) ids.high = ids.a >> 64 %} - assert a = low + high * HALF_SHIFT - assert [range_check_ptr + 0] = low - assert [range_check_ptr + 1] = HALF_SHIFT - 1 - low - assert [range_check_ptr + 2] = high - let range_check_ptr = range_check_ptr + 3 - return (low, high) -end - -# Multiplies two integers. Returns the result as two 256-bit integers (low and high parts). -func uint256_mul{range_check_ptr}(a : Uint256, b : Uint256) -> (low : Uint256, high : Uint256): - alloc_locals - let (a0, a1) = split_64(a.low) - let (a2, a3) = split_64(a.high) - let (b0, b1) = split_64(b.low) - let (b2, b3) = split_64(b.high) - - let (res0, carry) = split_64(a0 * b0) - let (res1, carry) = split_64(a1 * b0 + a0 * b1 + carry) - let (res2, carry) = split_64(a2 * b0 + a1 * b1 + a0 * b2 + carry) - let (res3, carry) = split_64(a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3 + carry) - let (res4, carry) = split_64(a3 * b1 + a2 * b2 + a1 * b3 + carry) - let (res5, carry) = split_64(a3 * b2 + a2 * b3 + carry) - let (res6, carry) = split_64(a3 * b3 + carry) + assert a = low + high * HALF_SHIFT; + assert [range_check_ptr + 0] = low; + assert [range_check_ptr + 1] = HALF_SHIFT - 1 - low; + assert [range_check_ptr + 2] = high; + let range_check_ptr = range_check_ptr + 3; + return (low, high); +} + +// Multiplies two integers. Returns the result as two 256-bit integers (low and high parts). +func uint256_mul{range_check_ptr}(a: Uint256, b: Uint256) -> (low: Uint256, high: Uint256) { + alloc_locals; + let (a0, a1) = split_64(a.low); + let (a2, a3) = split_64(a.high); + let (b0, b1) = split_64(b.low); + let (b2, b3) = split_64(b.high); + + let (res0, carry) = split_64(a0 * b0); + let (res1, carry) = split_64(a1 * b0 + a0 * b1 + carry); + let (res2, carry) = split_64(a2 * b0 + a1 * b1 + a0 * b2 + carry); + let (res3, carry) = split_64(a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3 + carry); + let (res4, carry) = split_64(a3 * b1 + a2 * b2 + a1 * b3 + carry); + let (res5, carry) = split_64(a3 * b2 + a2 * b3 + carry); + let (res6, carry) = split_64(a3 * b3 + carry); return ( low=Uint256(low=res0 + HALF_SHIFT * res1, high=res2 + HALF_SHIFT * res3), high=Uint256(low=res4 + HALF_SHIFT * res5, high=res6 + HALF_SHIFT * carry), - ) -end + ); +} -# Returns the floor value of the square root of a uint256 integer. -func uint256_sqrt{range_check_ptr}(n : Uint256) -> (res : Uint256): - alloc_locals - local root : Uint256 +// Returns the floor value of the square root of a uint256 integer. +func uint256_sqrt{range_check_ptr}(n: Uint256) -> (res: Uint256) { + alloc_locals; + local root: Uint256; %{ from starkware.python.math_utils import isqrt @@ -104,98 +105,99 @@ func uint256_sqrt{range_check_ptr}(n : Uint256) -> (res : Uint256): ids.root.high = 0 %} - # Verify that 0 <= root < 2**128. - assert root.high = 0 - [range_check_ptr] = root.low - let range_check_ptr = range_check_ptr + 1 - - # Verify that n >= root**2. - let (root_squared, carry) = uint256_mul(root, root) - assert carry = Uint256(0, 0) - let (check_lower_bound) = uint256_le(root_squared, n) - assert check_lower_bound = 1 - - # Verify that n <= (root+1)**2 - 1. - # In the case where root = 2**128 - 1, we will have next_root_squared=0, since - # (root+1)**2 = 2**256. Therefore next_root_squared - 1 = 2**256 - 1, as desired. - let (next_root, add_carry) = uint256_add(root, Uint256(1, 0)) - assert add_carry = 0 - let (next_root_squared, _) = uint256_mul(next_root, next_root) - let (next_root_squared_minus_one) = uint256_sub(next_root_squared, Uint256(1, 0)) - let (check_upper_bound) = uint256_le(n, next_root_squared_minus_one) - assert check_upper_bound = 1 - - return (res=root) -end - -# Returns 1 if the first unsigned integer is less than the second unsigned integer. -func uint256_lt{range_check_ptr}(a : Uint256, b : Uint256) -> (res : felt): - if a.high == b.high: - return is_le(a.low + 1, b.low) - end - return is_le(a.high + 1, b.high) -end - -# Returns 1 if the first signed integer is less than the second signed integer. -func uint256_signed_lt{range_check_ptr}(a : Uint256, b : Uint256) -> (res : felt): - let (a, _) = uint256_add(a, cast((low=0, high=2 ** 127), Uint256)) - let (b, _) = uint256_add(b, cast((low=0, high=2 ** 127), Uint256)) - return uint256_lt(a, b) -end - -# Returns 1 if the first unsigned integer is less than or equal to the second unsigned integer. -func uint256_le{range_check_ptr}(a : Uint256, b : Uint256) -> (res : felt): - let (not_le) = uint256_lt(a=b, b=a) - return (1 - not_le) -end - -# Returns 1 if the first signed integer is less than or equal to the second signed integer. -func uint256_signed_le{range_check_ptr}(a : Uint256, b : Uint256) -> (res : felt): - let (not_le) = uint256_signed_lt(a=b, b=a) - return (1 - not_le) -end - -# Returns 1 if the signed integer is nonnegative. + // Verify that 0 <= root < 2**128. + assert root.high = 0; + [range_check_ptr] = root.low; + let range_check_ptr = range_check_ptr + 1; + + // Verify that n >= root**2. + let (root_squared, carry) = uint256_mul(root, root); + assert carry = Uint256(0, 0); + let (check_lower_bound) = uint256_le(root_squared, n); + assert check_lower_bound = 1; + + // Verify that n <= (root+1)**2 - 1. + // In the case where root = 2**128 - 1, we will have next_root_squared=0. + // Since (root+1)**2 = 2**256. Therefore next_root_squared - 1 = 2**256 - 1, as desired. + let (next_root, add_carry) = uint256_add(root, Uint256(1, 0)); + assert add_carry = 0; + let (next_root_squared, _) = uint256_mul(next_root, next_root); + let (next_root_squared_minus_one) = uint256_sub(next_root_squared, Uint256(1, 0)); + let (check_upper_bound) = uint256_le(n, next_root_squared_minus_one); + assert check_upper_bound = 1; + + return (res=root); +} + +// Returns 1 if the first unsigned integer is less than the second unsigned integer. +func uint256_lt{range_check_ptr}(a: Uint256, b: Uint256) -> (res: felt) { + if (a.high == b.high) { + return (is_le(a.low + 1, b.low),); + } + return (is_le(a.high + 1, b.high),); +} + +// Returns 1 if the first signed integer is less than the second signed integer. +func uint256_signed_lt{range_check_ptr}(a: Uint256, b: Uint256) -> (res: felt) { + let (a, _) = uint256_add(a, cast((low=0, high=2 ** 127), Uint256)); + let (b, _) = uint256_add(b, cast((low=0, high=2 ** 127), Uint256)); + return uint256_lt(a, b); +} + +// Returns 1 if the first unsigned integer is less than or equal to the second unsigned integer. +func uint256_le{range_check_ptr}(a: Uint256, b: Uint256) -> (res: felt) { + let (not_le) = uint256_lt(a=b, b=a); + return (res=1 - not_le); +} + +// Returns 1 if the first signed integer is less than or equal to the second signed integer. +func uint256_signed_le{range_check_ptr}(a: Uint256, b: Uint256) -> (res: felt) { + let (not_le) = uint256_signed_lt(a=b, b=a); + return (res=1 - not_le); +} + +// Returns 1 if the signed integer is nonnegative. @known_ap_change -func uint256_signed_nn{range_check_ptr}(a : Uint256) -> (res : felt): +func uint256_signed_nn{range_check_ptr}(a: Uint256) -> (res: felt) { %{ memory[ap] = 1 if 0 <= (ids.a.high % PRIME) < 2 ** 127 else 0 %} - jmp non_negative if [ap] != 0; ap++ + jmp non_negative if [ap] != 0, ap++; - assert [range_check_ptr] = a.high - 2 ** 127 - let range_check_ptr = range_check_ptr + 1 - return (res=0) + assert [range_check_ptr] = a.high - 2 ** 127; + let range_check_ptr = range_check_ptr + 1; + return (res=0); non_negative: - assert [range_check_ptr] = a.high + 2 ** 127 - let range_check_ptr = range_check_ptr + 1 - return (res=1) -end - -# Returns 1 if the first signed integer is less than or equal to the second signed integer -# and is greater than or equal to zero. -func uint256_signed_nn_le{range_check_ptr}(a : Uint256, b : Uint256) -> (res : felt): - let (is_le) = uint256_signed_le(a=a, b=b) - if is_le == 0: - return (res=0) - end - let (is_nn) = uint256_signed_nn(a=a) - return (res=is_nn) -end - -# Unsigned integer division between two integers. Returns the quotient and the remainder. -# Conforms to EVM specifications: division by 0 yields 0. -func uint256_unsigned_div_rem{range_check_ptr}(a : Uint256, div : Uint256) -> ( - quotient : Uint256, remainder : Uint256 -): - alloc_locals - local quotient : Uint256 - local remainder : Uint256 - - # If div == 0, return (0, 0). - if div.low + div.high == 0: - return (quotient=Uint256(0, 0), remainder=Uint256(0, 0)) - end - + assert [range_check_ptr] = a.high + 2 ** 127; + let range_check_ptr = range_check_ptr + 1; + return (res=1); +} + +// Returns 1 if the first signed integer is less than or equal to the second signed integer +// and is greater than or equal to zero. +func uint256_signed_nn_le{range_check_ptr}(a: Uint256, b: Uint256) -> (res: felt) { + let (is_le) = uint256_signed_le(a=a, b=b); + if (is_le == 0) { + return (res=0); + } + let (is_nn) = uint256_signed_nn(a=a); + return (res=is_nn); +} + +// Unsigned integer division between two integers. Returns the quotient and the remainder. +// Conforms to EVM specifications: division by 0 yields 0. +func uint256_unsigned_div_rem{range_check_ptr}(a: Uint256, div: Uint256) -> ( + quotient: Uint256, remainder: Uint256 +) { + alloc_locals; + + // If div == 0, return (0, 0). + if (div.low + div.high == 0) { + return (quotient=Uint256(0, 0), remainder=Uint256(0, 0)); + } + + // Guess the quotient and the remainder. + local quotient: Uint256; + local remainder: Uint256; %{ a = (ids.a.high << 128) + ids.a.low div = (ids.div.high << 128) + ids.div.low @@ -206,215 +208,240 @@ func uint256_unsigned_div_rem{range_check_ptr}(a : Uint256, div : Uint256) -> ( ids.remainder.low = remainder & ((1 << 128) - 1) ids.remainder.high = remainder >> 128 %} - let (res_mul, carry) = uint256_mul(quotient, div) - assert carry = Uint256(0, 0) - - let (check_val, add_carry) = uint256_add(res_mul, remainder) - assert check_val = a - assert add_carry = 0 - - let (is_valid) = uint256_lt(remainder, div) - assert is_valid = 1 - return (quotient=quotient, remainder=remainder) -end - -# Returns the bitwise NOT of an integer. -func uint256_not{range_check_ptr}(a : Uint256) -> (res : Uint256): - return (Uint256(low=ALL_ONES - a.low, high=ALL_ONES - a.high)) -end - -# Returns the negation of an integer. -# Note that the negation of -2**255 is -2**255. -func uint256_neg{range_check_ptr}(a : Uint256) -> (res : Uint256): - let (not_num) = uint256_not(a) - let (res, _) = uint256_add(not_num, Uint256(low=1, high=0)) - return (res) -end - -# Conditionally negates an integer. -func uint256_cond_neg{range_check_ptr}(a : Uint256, should_neg) -> (res : Uint256): - if should_neg != 0: - return uint256_neg(a) - else: - return (res=a) - end -end - -# Signed integer division between two integers. Returns the quotient and the remainder. -# Conforms to EVM specifications. -# See ethereum yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf, page 29). -# Note that the remainder may be negative if one of the inputs is negative and that -# (-2**255) / (-1) = -2**255 because 2*255 is out of range. -func uint256_signed_div_rem{range_check_ptr}(a : Uint256, div : Uint256) -> ( - quot : Uint256, rem : Uint256 -): - alloc_locals - - # When div=-1, simply return -a. - if div.low == SHIFT - 1: - if div.high == SHIFT - 1: - let (quot) = uint256_neg(a) - return (quot, cast((0, 0), Uint256)) - end - end - - # Take the absolute value of a. - let (local a_sign) = is_le(2 ** 127, a.high) - local range_check_ptr = range_check_ptr - let (local a) = uint256_cond_neg(a, should_neg=a_sign) - - # Take the absolute value of div. - let (local div_sign) = is_le(2 ** 127, div.high) - local range_check_ptr = range_check_ptr - let (div) = uint256_cond_neg(div, should_neg=div_sign) - - # Unsigned division. - let (local quot, local rem) = uint256_unsigned_div_rem(a, div) - local range_check_ptr = range_check_ptr - - # Fix the remainder according to the sign of a. - let (rem) = uint256_cond_neg(rem, should_neg=a_sign) - - # Fix the quotient according to the signs of a and div. - if a_sign == div_sign: - return (quot=quot, rem=rem) - end - let (local quot_neg) = uint256_neg(quot) - - return (quot=quot_neg, rem=rem) -end - -# Subtracts two integers. Returns the result as a 256-bit integer. -func uint256_sub{range_check_ptr}(a : Uint256, b : Uint256) -> (res : Uint256): - let (b_neg) = uint256_neg(b) - let (res, _) = uint256_add(a, b_neg) - return (res) -end - -# Bitwise. - -# Return true if both integers are equal. -func uint256_eq{range_check_ptr}(a : Uint256, b : Uint256) -> (res : felt): - if a.high != b.high: - return (0) - end - if a.low != b.low: - return (0) - end - return (1) -end - -# Computes the bitwise XOR of 2 uint256 integers. -func uint256_xor{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}(a : Uint256, b : Uint256) -> ( - res : Uint256 -): - let (low) = bitwise_xor(a.low, b.low) - let (high) = bitwise_xor(a.high, b.high) - return (Uint256(low, high)) -end - -# Computes the bitwise AND of 2 uint256 integers. -func uint256_and{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}(a : Uint256, b : Uint256) -> ( - res : Uint256 -): - let (low) = bitwise_and(a.low, b.low) - let (high) = bitwise_and(a.high, b.high) - return (Uint256(low, high)) -end - -# Computes the bitwise OR of 2 uint256 integers. -func uint256_or{range_check_ptr, bitwise_ptr : BitwiseBuiltin*}(a : Uint256, b : Uint256) -> ( - res : Uint256 -): - let (low) = bitwise_or(a.low, b.low) - let (high) = bitwise_or(a.high, b.high) - return (Uint256(low, high)) -end - -# Computes 2**exp % 2**256 as a uint256 integer. -func uint256_pow2{range_check_ptr}(exp : Uint256) -> (res : Uint256): - # If exp >= 256, the result will be zero modulo 2**256. - let (res) = uint256_lt(exp, Uint256(256, 0)) - if res == 0: - return (Uint256(0, 0)) - end - - let (res) = is_le(exp.low, 127) - if res != 0: - let (x) = pow(2, exp.low) - return (Uint256(x, 0)) - else: - let (x) = pow(2, exp.low - 128) - return (Uint256(0, x)) - end -end - -# Computes the logical left shift of a uint256 integer. -func uint256_shl{range_check_ptr}(a : Uint256, b : Uint256) -> (res : Uint256): - let (c) = uint256_pow2(b) - let (res, _) = uint256_mul(a, c) - return (res) -end - -# Computes the logical right shift of a uint256 integer. -func uint256_shr{range_check_ptr}(a : Uint256, b : Uint256) -> (res : Uint256): - let (c) = uint256_pow2(b) - let (res, _) = uint256_unsigned_div_rem(a, c) - return (res) -end - -# Reverses byte endianness of a 128-bit word. -# -# The algorithm works in steps. Generally speaking, on the i-th step, -# we switch between every two consecutive sequences of 2 ** i bytes. -# To illustrate how it works, here are the steps when running -# on a 64-bit word = [b0, b1, b2, b3, b4, b5, b6, b7] (3 steps instead of 4): -# -# step 1: -# [b0, b1, b2, b3, b4, b5, b6, b7] - -# [b0, 0,  b2, 0,  b4, 0,  b6, 0 ] + -# [0,  0,  b0, 0,  b2, 0,  b4, 0, b6] = -# [0,  b1, b0, b3, b2, b5, b4, b7, b6] -# -# step 2: -# [0, b1, b0, b3, b2, b5, b4, b7, b6] - -# [0, b1, b0, 0,  0,  b5, b4, 0,  0 ] + -# [0, 0,  0,  0,  0,  b1, b0, 0,  0,  b5, b4] = -# [0, 0,  0,  b3, b2, b1, b0, b7, b6, b5, b4] -# -# step 3: -# [0, 0, 0, b3, b2, b1, b0, b7, b6, b5, b4] - -# [0, 0, 0, b3, b2, b1, b0, 0,  0,  0,  0 ] + -# [0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0, b3, b2, b1, b0] = -# [0, 0, 0, 0,  0,  0,  0,  b7, b6, b5, b4, b3, b2, b1, b0] -# -# Next, we divide by 2 ** (8 + 16 + 32) and get [b7, b6, b5, b4, b3, b2, b1, b0]. -func word_reverse_endian{bitwise_ptr : BitwiseBuiltin*}(word : felt) -> (res : felt): - # Step 1. - assert bitwise_ptr[0].x = word - assert bitwise_ptr[0].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff - tempvar word = word + (2 ** 16 - 1) * bitwise_ptr[0].x_and_y - # Step 2. - assert bitwise_ptr[1].x = word - assert bitwise_ptr[1].y = 0x00ffff0000ffff0000ffff0000ffff00 - tempvar word = word + (2 ** 32 - 1) * bitwise_ptr[1].x_and_y - # Step 3. - assert bitwise_ptr[2].x = word - assert bitwise_ptr[2].y = 0x00ffffffff00000000ffffffff000000 - tempvar word = word + (2 ** 64 - 1) * bitwise_ptr[2].x_and_y - # Step 4. - assert bitwise_ptr[3].x = word - assert bitwise_ptr[3].y = 0x00ffffffffffffffff00000000000000 - tempvar word = word + (2 ** 128 - 1) * bitwise_ptr[3].x_and_y - - let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE - return (res=word / 2 ** (8 + 16 + 32 + 64)) -end - -# Reverses byte endianness of a uint256 integer. -func uint256_reverse_endian{bitwise_ptr : BitwiseBuiltin*}(num : Uint256) -> (res : Uint256): - let (high) = word_reverse_endian(num.high) - let (low) = word_reverse_endian(num.low) - - return (res=Uint256(low=high, high=low)) -end + uint256_check(quotient); + uint256_check(remainder); + let (res_mul, carry) = uint256_mul(quotient, div); + assert carry = Uint256(0, 0); + + let (check_val, add_carry) = uint256_add(res_mul, remainder); + assert check_val = a; + assert add_carry = 0; + + let (is_valid) = uint256_lt(remainder, div); + assert is_valid = 1; + return (quotient=quotient, remainder=remainder); +} + +// Returns the bitwise NOT of an integer. +func uint256_not{range_check_ptr}(a: Uint256) -> (res: Uint256) { + return (res=Uint256(low=ALL_ONES - a.low, high=ALL_ONES - a.high)); +} + +// Returns the negation of an integer. +// Note that the negation of -2**255 is -2**255. +func uint256_neg{range_check_ptr}(a: Uint256) -> (res: Uint256) { + let (not_num) = uint256_not(a); + let (res, _) = uint256_add(not_num, Uint256(low=1, high=0)); + return (res=res); +} + +// Conditionally negates an integer. +func uint256_cond_neg{range_check_ptr}(a: Uint256, should_neg) -> (res: Uint256) { + if (should_neg != 0) { + return uint256_neg(a); + } else { + return (res=a); + } +} + +// Signed integer division between two integers. Returns the quotient and the remainder. +// Conforms to EVM specifications. +// See ethereum yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf, page 29). +// Note that the remainder may be negative if one of the inputs is negative and that +// (-2**255) / (-1) = -2**255 because 2*255 is out of range. +func uint256_signed_div_rem{range_check_ptr}(a: Uint256, div: Uint256) -> ( + quot: Uint256, rem: Uint256 +) { + alloc_locals; + + // When div=-1, simply return -a. + if (div.low == SHIFT - 1 and div.high == SHIFT - 1) { + let (quot) = uint256_neg(a); + return (quot, cast((0, 0), Uint256)); + } + + // Take the absolute value of a. + local a_sign = is_le(2 ** 127, a.high); + local range_check_ptr = range_check_ptr; + let (local a) = uint256_cond_neg(a, should_neg=a_sign); + + // Take the absolute value of div. + local div_sign = is_le(2 ** 127, div.high); + local range_check_ptr = range_check_ptr; + let (div) = uint256_cond_neg(div, should_neg=div_sign); + + // Unsigned division. + let (local quot, local rem) = uint256_unsigned_div_rem(a, div); + local range_check_ptr = range_check_ptr; + + // Fix the remainder according to the sign of a. + let (rem) = uint256_cond_neg(rem, should_neg=a_sign); + + // Fix the quotient according to the signs of a and div. + if (a_sign == div_sign) { + return (quot=quot, rem=rem); + } + let (local quot_neg) = uint256_neg(quot); + + return (quot=quot_neg, rem=rem); +} + +// Subtracts two integers. Returns the result as a 256-bit integer. +func uint256_sub{range_check_ptr}(a: Uint256, b: Uint256) -> (res: Uint256) { + let (b_neg) = uint256_neg(b); + let (res, _) = uint256_add(a, b_neg); + return (res=res); +} + +// Bitwise. + +// Return true if both integers are equal. +func uint256_eq{range_check_ptr}(a: Uint256, b: Uint256) -> (res: felt) { + if (a.high != b.high) { + return (res=0); + } + if (a.low != b.low) { + return (res=0); + } + return (res=1); +} + +// Computes the bitwise XOR of 2 uint256 integers. +func uint256_xor{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(a: Uint256, b: Uint256) -> ( + res: Uint256 +) { + let (low) = bitwise_xor(a.low, b.low); + let (high) = bitwise_xor(a.high, b.high); + return (res=Uint256(low, high)); +} + +// Computes the bitwise AND of 2 uint256 integers. +func uint256_and{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(a: Uint256, b: Uint256) -> ( + res: Uint256 +) { + let (low) = bitwise_and(a.low, b.low); + let (high) = bitwise_and(a.high, b.high); + return (res=Uint256(low, high)); +} + +// Computes the bitwise OR of 2 uint256 integers. +func uint256_or{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(a: Uint256, b: Uint256) -> ( + res: Uint256 +) { + let (low) = bitwise_or(a.low, b.low); + let (high) = bitwise_or(a.high, b.high); + return (res=Uint256(low, high)); +} + +// Computes 2**exp % 2**256 as a uint256 integer. +func uint256_pow2{range_check_ptr}(exp: Uint256) -> (res: Uint256) { + // If exp >= 256, the result will be zero modulo 2**256. + let (res) = uint256_lt(exp, Uint256(256, 0)); + if (res == 0) { + return (res=Uint256(0, 0)); + } + + if (is_le(exp.low, 127) != 0) { + let (x) = pow(2, exp.low); + return (res=Uint256(x, 0)); + } else { + let (x) = pow(2, exp.low - 128); + return (res=Uint256(0, x)); + } +} + +// Computes the logical left shift of a uint256 integer. +func uint256_shl{range_check_ptr}(a: Uint256, b: Uint256) -> (res: Uint256) { + let (c) = uint256_pow2(b); + let (res, _) = uint256_mul(a, c); + return (res=res); +} + +// Computes the logical right shift of a uint256 integer. +func uint256_shr{range_check_ptr}(a: Uint256, b: Uint256) -> (res: Uint256) { + let (c) = uint256_pow2(b); + let (res, _) = uint256_unsigned_div_rem(a, c); + return (res=res); +} + +// Reverses byte endianness of a 128-bit word. +// +// The algorithm works in steps. Generally speaking, on the i-th step, +// we switch between every two consecutive sequences of 2 ** i bytes. +// To illustrate how it works, here are the steps when running +// on a 64-bit word = [b0, b1, b2, b3, b4, b5, b6, b7] (3 steps instead of 4): +// +// step 1: +// [b0, b1, b2, b3, b4, b5, b6, b7] - +// [b0, 0,  b2, 0,  b4, 0,  b6, 0 ] + +// [0,  0,  b0, 0,  b2, 0,  b4, 0, b6] = +// [0,  b1, b0, b3, b2, b5, b4, b7, b6] +// +// step 2: +// [0, b1, b0, b3, b2, b5, b4, b7, b6] - +// [0, b1, b0, 0,  0,  b5, b4, 0,  0 ] + +// [0, 0,  0,  0,  0,  b1, b0, 0,  0,  b5, b4] = +// [0, 0,  0,  b3, b2, b1, b0, b7, b6, b5, b4] +// +// step 3: +// [0, 0, 0, b3, b2, b1, b0, b7, b6, b5, b4] - +// [0, 0, 0, b3, b2, b1, b0, 0,  0,  0,  0 ] + +// [0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0, b3, b2, b1, b0] = +// [0, 0, 0, 0,  0,  0,  0,  b7, b6, b5, b4, b3, b2, b1, b0] +// +// Next, we divide by 2 ** (8 + 16 + 32) and get [b7, b6, b5, b4, b3, b2, b1, b0]. +func word_reverse_endian{bitwise_ptr: BitwiseBuiltin*}(word: felt) -> (res: felt) { + // Step 1. + assert bitwise_ptr[0].x = word; + assert bitwise_ptr[0].y = 0x00ff00ff00ff00ff00ff00ff00ff00ff; + tempvar word = word + (2 ** 16 - 1) * bitwise_ptr[0].x_and_y; + // Step 2. + assert bitwise_ptr[1].x = word; + assert bitwise_ptr[1].y = 0x00ffff0000ffff0000ffff0000ffff00; + tempvar word = word + (2 ** 32 - 1) * bitwise_ptr[1].x_and_y; + // Step 3. + assert bitwise_ptr[2].x = word; + assert bitwise_ptr[2].y = 0x00ffffffff00000000ffffffff000000; + tempvar word = word + (2 ** 64 - 1) * bitwise_ptr[2].x_and_y; + // Step 4. + assert bitwise_ptr[3].x = word; + assert bitwise_ptr[3].y = 0x00ffffffffffffffff00000000000000; + tempvar word = word + (2 ** 128 - 1) * bitwise_ptr[3].x_and_y; + + let bitwise_ptr = bitwise_ptr + 4 * BitwiseBuiltin.SIZE; + return (res=word / 2 ** (8 + 16 + 32 + 64)); +} + +// Reverses byte endianness of a uint256 integer. +func uint256_reverse_endian{bitwise_ptr: BitwiseBuiltin*}(num: Uint256) -> (res: Uint256) { + let (high) = word_reverse_endian(num.high); + let (low) = word_reverse_endian(num.low); + + return (res=Uint256(low=high, high=low)); +} + +// Assertions: + +func assert_uint256_eq{range_check_ptr}(a: Uint256, b: Uint256) { + let (res) = uint256_eq(a, b); + with_attr error_message("assert_uint256_eq failed") { + assert res = 1; + } + return (); +} + +func assert_uint256_lt{range_check_ptr}(a: Uint256, b: Uint256) { + let (res) = uint256_lt(a, b); + with_attr error_message("assert_uint256_lt failed") { + assert res = 1; + } + return (); +} + +func assert_uint256_le{range_check_ptr}(a: Uint256, b: Uint256) { + let (res) = uint256_le(a, b); + with_attr error_message("assert_uint256_le failed") { + assert res = 1; + } + return (); +} diff --git a/src/starkware/cairo/common/usort.cairo b/src/starkware/cairo/common/usort.cairo index 73be4d27..1ed24878 100644 --- a/src/starkware/cairo/common/usort.cairo +++ b/src/starkware/cairo/common/usort.cairo @@ -1,17 +1,17 @@ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.math import assert_lt, assert_nn -# Sorts an array of field elements and removes duplicates. -# Returns the sorted array and an array of multiplicities. -# multiplicities[i] is the number of times that output[i] appeared in input. -# Completeness assumption: All numbers are in [0, RANGE_CHECK_BOUND). -func usort{range_check_ptr}(input_len : felt, input : felt*) -> ( - output_len : felt, output : felt*, multiplicities : felt* -): - alloc_locals - local output_len - local output : felt* - local multiplicities : felt* +// Sorts an array of field elements and removes duplicates. +// Returns the sorted array and an array of multiplicities. +// multiplicities[i] is the number of times that output[i] appeared in input. +// Completeness assumption: All numbers are in [0, RANGE_CHECK_BOUND). +func usort{range_check_ptr}(input_len: felt, input: felt*) -> ( + output_len: felt, output: felt*, multiplicities: felt* +) { + alloc_locals; + local output_len; + local output: felt*; + local multiplicities: felt*; %{ vm_enter_scope(dict(__usort_max_size = globals().get('__usort_max_size'))) %} %{ from collections import defaultdict @@ -35,37 +35,37 @@ func usort{range_check_ptr}(input_len : felt, input : felt*) -> ( ids.multiplicities = segments.gen_arg([len(positions_dict[k]) for k in output]) %} - let output_start = output + let output_start = output; verify_usort{output=output}( input_len=input_len, input=input, total_visited=0, multiplicities=multiplicities, prev=-1 - ) + ); %{ vm_exit_scope() %} - return (output_len=output - output_start, output=output_start, multiplicities=multiplicities) -end + return (output_len=output - output_start, output=output_start, multiplicities=multiplicities); +} -# Verifies that usort of input is (output, multiplicities). See usort(). -func verify_usort{range_check_ptr, output : felt*}( - input_len : felt, input : felt*, total_visited : felt, multiplicities : felt*, prev : felt -): - alloc_locals +// Verifies that usort of input is (output, multiplicities). See usort(). +func verify_usort{range_check_ptr, output: felt*}( + input_len: felt, input: felt*, total_visited: felt, multiplicities: felt*, prev: felt +) { + alloc_locals; - if total_visited == input_len: - return () - end + if (total_visited == input_len) { + return (); + } - local value = [output] - let output = &output[1] - assert_lt(prev, value) + local value = [output]; + let output = &output[1]; + assert_lt(prev, value); - local multiplicity = [multiplicities] - assert_nn(multiplicity - 1) + local multiplicity = [multiplicities]; + assert_nn(multiplicity - 1); %{ last_pos = 0 positions = positions_dict[ids.value][::-1] %} - verify_multiplicity(multiplicity=multiplicity, input_len=input_len, input=input, value=value) + verify_multiplicity(multiplicity=multiplicity, input_len=input_len, input=input, value=value); return verify_usort( input_len=input_len, @@ -73,33 +73,33 @@ func verify_usort{range_check_ptr, output : felt*}( total_visited=total_visited + multiplicity, multiplicities=&multiplicities[1], prev=value, - ) -end + ); +} -# Verifies that value appears at least multiplicity times in input. +// Verifies that value appears at least multiplicity times in input. func verify_multiplicity{range_check_ptr}( - multiplicity : felt, input_len : felt, input : felt*, value : felt -): - if multiplicity == 0: + multiplicity: felt, input_len: felt, input: felt*, value: felt +) { + if (multiplicity == 0) { %{ assert len(positions) == 0 %} - assert_nn(input_len) - return () - end + assert_nn(input_len); + return (); + } - alloc_locals - # Skip to the next appearance. - local next_item_index + alloc_locals; + // Skip to the next appearance. + local next_item_index; %{ current_pos = positions.pop() ids.next_item_index = current_pos - last_pos last_pos = current_pos + 1 %} - assert_nn(next_item_index) - assert input[next_item_index] = value + assert_nn(next_item_index); + assert input[next_item_index] = value; return verify_multiplicity( multiplicity=multiplicity - 1, input_len=input_len - next_item_index - 1, input=&input[next_item_index + 1], value=value, - ) -end + ); +} diff --git a/src/starkware/cairo/common/validate_utils.py b/src/starkware/cairo/common/validate_utils.py new file mode 100644 index 00000000..368fcba4 --- /dev/null +++ b/src/starkware/cairo/common/validate_utils.py @@ -0,0 +1,11 @@ +from starkware.cairo.lang.vm.builtin_runner import SimpleBuiltinRunner +from starkware.cairo.lang.vm.relocatable import RelocatableValue + + +def validate_builtin_usage(builtin_runner: SimpleBuiltinRunner, end_ptr: RelocatableValue): + assert builtin_runner.base is not None + usage = end_ptr - builtin_runner.base + assert usage % builtin_runner.cells_per_instance == 0, ( + f"usage = {usage} is not a multiple of cells_per_instance = " + f"{builtin_runner.cells_per_instance}." + ) diff --git a/src/starkware/cairo/lang/CMakeLists.txt b/src/starkware/cairo/lang/CMakeLists.txt index c5a76d78..fa88e88d 100644 --- a/src/starkware/cairo/lang/CMakeLists.txt +++ b/src/starkware/cairo/lang/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(builtins) add_subdirectory(compiler) +add_subdirectory(migrators) add_subdirectory(scripts) add_subdirectory(tracer) add_subdirectory(vm) diff --git a/src/starkware/cairo/lang/VERSION b/src/starkware/cairo/lang/VERSION index f374f666..78bc1abd 100644 --- a/src/starkware/cairo/lang/VERSION +++ b/src/starkware/cairo/lang/VERSION @@ -1 +1 @@ -0.9.1 +0.10.0 diff --git a/src/starkware/cairo/lang/builtins/CMakeLists.txt b/src/starkware/cairo/lang/builtins/CMakeLists.txt index 92738f1e..5d9e1836 100644 --- a/src/starkware/cairo/lang/builtins/CMakeLists.txt +++ b/src/starkware/cairo/lang/builtins/CMakeLists.txt @@ -1,3 +1,7 @@ +add_subdirectory(ec) +add_subdirectory(range_check) +add_subdirectory(signature) + python_lib(cairo_run_builtins_lib PREFIX starkware/cairo/lang/builtins @@ -9,6 +13,7 @@ python_lib(cairo_run_builtins_lib ec/instance_def.py hash/hash_builtin_runner.py hash/instance_def.py + keccak/keccak_builtin_runner.py keccak/instance_def.py range_check/instance_def.py range_check/range_check_builtin_runner.py @@ -16,6 +21,7 @@ python_lib(cairo_run_builtins_lib signature/signature_builtin_runner.py LIBS + cairo_common_lib cairo_relocatable_lib cairo_vm_lib starkware_python_utils_lib @@ -30,23 +36,3 @@ python_lib(cairo_run_builtins_test_utils_lib cairo_compile_lib cairo_run_lib ) - -full_python_test(cairo_run_builtins_test - PREFIX starkware/cairo/lang/builtins - PYTHON ${PYTHON_COMMAND} - TESTED_MODULES starkware/cairo/lang/builtins - - FILES - ec/ec_op_builtin_runner_test.py - range_check/range_check_builtin_runner_test.py - signature/signature_builtin_runner_test.py - - LIBS - cairo_common_lib - cairo_compile_lib - cairo_run_lib - cairo_run_builtins_lib - cairo_run_builtins_test_utils_lib - starkware_python_test_utils_lib - pip_pytest -) diff --git a/src/starkware/cairo/lang/builtins/all_builtins.py b/src/starkware/cairo/lang/builtins/all_builtins.py index 4da019f1..0b38fb33 100644 --- a/src/starkware/cairo/lang/builtins/all_builtins.py +++ b/src/starkware/cairo/lang/builtins/all_builtins.py @@ -11,6 +11,7 @@ ECDSA_BUILTIN = "ecdsa" BITWISE_BUILTIN = "bitwise" EC_OP_BUILTIN = "ec_op" +KECCAK_BUILTIN = "keccak" BUILTIN_NAME_SUFFIX = "_builtin" @@ -53,5 +54,6 @@ def with_suffix(self): ECDSA_BUILTIN, BITWISE_BUILTIN, EC_OP_BUILTIN, + KECCAK_BUILTIN, ] ) diff --git a/src/starkware/cairo/lang/builtins/bitwise/bitwise_builtin_runner.py b/src/starkware/cairo/lang/builtins/bitwise/bitwise_builtin_runner.py index 4bb5b521..02127abd 100644 --- a/src/starkware/cairo/lang/builtins/bitwise/bitwise_builtin_runner.py +++ b/src/starkware/cairo/lang/builtins/bitwise/bitwise_builtin_runner.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any, Dict from starkware.cairo.lang.builtins.bitwise.instance_def import ( CELLS_PER_BITWISE, @@ -18,7 +18,6 @@ def __init__(self, included: bool, bitwise_builtin: BitwiseInstanceDef): cells_per_instance=CELLS_PER_BITWISE, n_input_cells=INPUT_CELLS_PER_BITWISE, ) - self.stop_ptr: Optional[RelocatableValue] = None self.bitwise_builtin: BitwiseInstanceDef = bitwise_builtin def add_auto_deduction_rules(self, runner): diff --git a/src/starkware/cairo/lang/builtins/ec/CMakeLists.txt b/src/starkware/cairo/lang/builtins/ec/CMakeLists.txt new file mode 100644 index 00000000..2d990c23 --- /dev/null +++ b/src/starkware/cairo/lang/builtins/ec/CMakeLists.txt @@ -0,0 +1,15 @@ +full_python_test(cairo_run_builtins_ec_op_test + PREFIX starkware/cairo/lang/builtins/ec + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/lang/builtins/ec + + FILES + ec_op_builtin_runner_test.py + + LIBS + cairo_run_builtins_test_utils_lib + cairo_vm_lib + starkware_crypto_lib + starkware_python_utils_lib + pip_pytest +) diff --git a/src/starkware/cairo/lang/builtins/ec/ec_op_builtin_runner.py b/src/starkware/cairo/lang/builtins/ec/ec_op_builtin_runner.py index 0cf969e6..48051961 100644 --- a/src/starkware/cairo/lang/builtins/ec/ec_op_builtin_runner.py +++ b/src/starkware/cairo/lang/builtins/ec/ec_op_builtin_runner.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Tuple, Union +from typing import Any, Dict, Tuple, Union from starkware.cairo.lang.builtins.ec.instance_def import ( CELLS_PER_EC_OP, @@ -42,12 +42,13 @@ def ec_op_impl( """ doubled_point = (q_x, q_y) partial_sum = (p_x, p_y) + orig_m = m for _ in range(height): assert (doubled_point[0] - partial_sum[0]) % prime != 0, ( "Cannot apply EC operation: computation reached two points with the same x coordinate." "\nAttempting to compute P + m * Q where:\n" f"P = {(p_x, p_y)}\n" - f"m = {m}\n" + f"m = {orig_m}\n" f"Q = {(q_x, q_y)}." ) if m & 1 != 0: @@ -68,7 +69,6 @@ def __init__(self, included: bool, ec_op_builtin: EcOpInstanceDef): cells_per_instance=CELLS_PER_EC_OP, n_input_cells=INPUT_CELLS_PER_EC_OP, ) - self.stop_ptr: Optional[RelocatableValue] = None self.ec_op_builtin: EcOpInstanceDef = ec_op_builtin def add_auto_deduction_rules(self, runner): @@ -106,7 +106,7 @@ def rule(vm, addr): ec_point_x, ec_point_y = [memory[instance + i] for i in pair] assert point_on_curve( ec_point_x, ec_point_y, ALPHA, BETA, FIELD_PRIME - ), f"{self.name} builtin: point {pair} is not on the curve." + ), f"{self.name} builtin: point ({ec_point_x}, {ec_point_y}) is not on the curve." res = ec_op_impl( # type: ignore *[memory[instance + i] for i in range(INPUT_CELLS_PER_EC_OP)], diff --git a/src/starkware/cairo/lang/builtins/ec/ec_op_builtin_runner_test.py b/src/starkware/cairo/lang/builtins/ec/ec_op_builtin_runner_test.py index 7883f4e5..8ea24904 100644 --- a/src/starkware/cairo/lang/builtins/ec/ec_op_builtin_runner_test.py +++ b/src/starkware/cairo/lang/builtins/ec/ec_op_builtin_runner_test.py @@ -18,20 +18,20 @@ def test_validation_rules(): from starkware.cairo.common.cairo_builtins import EcOpBuiltin from starkware.cairo.common.ec_point import EcPoint -func main{{ec_op_ptr: EcOpBuiltin*}}(): - assert ec_op_ptr.p.x = {p[0]} - assert ec_op_ptr.p.y = {p[1]} - assert ec_op_ptr.q.x = {q[0]} - assert ec_op_ptr.q.y = {q[1]} - assert ec_op_ptr.m = {m} - with_attr error_message("Wrong result"): - tempvar r = ec_op_ptr.r - assert r.x = {r[0]} - assert r.y = {r[1]} - end - let ec_op_ptr = ec_op_ptr + 7 - return () -end +func main{{ec_op_ptr: EcOpBuiltin*}}() {{ + assert ec_op_ptr.p.x = {p[0]}; + assert ec_op_ptr.p.y = {p[1]}; + assert ec_op_ptr.q.x = {q[0]}; + assert ec_op_ptr.q.y = {q[1]}; + assert ec_op_ptr.m = {m}; + with_attr error_message("Wrong result") {{ + tempvar r = ec_op_ptr.r; + assert r.x = {r[0]}; + assert r.y = {r[1]}; + }} + let ec_op_ptr = ec_op_ptr + 7; + return (); +}} """ # A valid computation. diff --git a/src/starkware/cairo/lang/builtins/hash/hash_builtin_runner.py b/src/starkware/cairo/lang/builtins/hash/hash_builtin_runner.py index 8988359f..37337b79 100644 --- a/src/starkware/cairo/lang/builtins/hash/hash_builtin_runner.py +++ b/src/starkware/cairo/lang/builtins/hash/hash_builtin_runner.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Set +from typing import Any, Dict, Set from starkware.cairo.lang.builtins.hash.instance_def import CELLS_PER_HASH, INPUT_CELLS_PER_HASH from starkware.cairo.lang.vm.builtin_runner import BuiltinVerifier, SimpleBuiltinRunner @@ -16,7 +16,6 @@ def __init__(self, name: str, included: bool, ratio: int, hash_func): n_input_cells=INPUT_CELLS_PER_HASH, ) self.hash_func = hash_func - self.stop_ptr: Optional[RelocatableValue] = None self.verified_addresses: Set[MaybeRelocatable] = set() def add_auto_deduction_rules(self, runner): diff --git a/src/starkware/cairo/lang/builtins/keccak/keccak_builtin_runner.py b/src/starkware/cairo/lang/builtins/keccak/keccak_builtin_runner.py new file mode 100644 index 00000000..07071305 --- /dev/null +++ b/src/starkware/cairo/lang/builtins/keccak/keccak_builtin_runner.py @@ -0,0 +1,100 @@ +from typing import Any, Dict, Set + +from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_f +from starkware.cairo.lang.builtins.keccak.instance_def import KeccakInstanceDef +from starkware.cairo.lang.vm.builtin_runner import SimpleBuiltinRunner +from starkware.cairo.lang.vm.relocatable import MaybeRelocatable, RelocatableValue +from starkware.python.math_utils import safe_div +from starkware.python.utils import from_bytes, safe_zip, to_bytes + + +class KeccakBuiltinRunner(SimpleBuiltinRunner): + def __init__(self, included: bool, instance_def: KeccakInstanceDef): + super().__init__( + name="keccak", + included=included, + ratio=None if instance_def is None else instance_def.ratio, + instances_per_component=instance_def.instances_per_component, + cells_per_instance=instance_def.cells_per_builtin, + n_input_cells=safe_div(instance_def.cells_per_builtin, 2), + ) + self.instance_def: KeccakInstanceDef = instance_def + self.verified_addresses: Set[MaybeRelocatable] = set() + + def is_input_cell(self, index: int) -> bool: + return index < self.n_input_cells + + def add_auto_deduction_rules(self, runner): + def rule(vm, addr, verified_addresses): + memory = vm.run_context.memory + index = addr.offset % self.cells_per_instance + if self.is_input_cell(index): + return + first_input_addr = addr - index + if first_input_addr in verified_addresses: + return + if not all(first_input_addr + i in memory for i in range(self.n_input_cells)): + return + + for i, bits in enumerate(self.instance_def.state_rep): + value = memory[first_input_addr + i] + assert vm.is_integer_value(value), ( + f"{self.name} builtin: Expected integer at address {first_input_addr + i}. " + + f"Got: {value}." + ) + assert 0 <= value < 2**bits, ( + f"{self.name} builtin: Expected integer at address {first_input_addr + i} " + + f"to be smaller than 2^{bits}. Got: {value}." + ) + input_felts = [memory[first_input_addr + i] for i in range(self.n_input_cells)] + output_bytes = keccak_f( + b"".join( + to_bytes(value, safe_div(bits, 8), "little") + for value, bits in safe_zip(input_felts, self.instance_def.state_rep) + ) + ) + start_index = 0 + for i, bits in enumerate(self.instance_def.state_rep): + end_index = start_index + safe_div(bits, 8) + memory[first_input_addr + self.n_input_cells + i] = from_bytes( + output_bytes[start_index:end_index], byte_order="little" + ) + start_index = end_index + return memory[addr] + + runner.vm.add_auto_deduction_rule(self.base.segment_index, rule, self.verified_addresses) + + def air_private_input(self, runner) -> Dict[str, Any]: + assert self.base is not None, "Uninitialized self.base." + res: Dict[int, Any] = {} + for addr, val in runner.vm_memory.items(): + if ( + not isinstance(addr, RelocatableValue) + or addr.segment_index != self.base.segment_index + ): + continue + idx, state_index = divmod(addr.offset, self.cells_per_instance) + if not self.is_input_cell(state_index): + continue + + assert isinstance(val, int) + res.setdefault(idx, {"index": idx})[f"input_s{state_index}"] = hex(val) + + for index, item in res.items(): + for i in range(self.n_input_cells): + assert f"input_s{i}" in item, f"Missing input #{i} of {self.name} instance {index}." + + return {self.name: sorted(res.values(), key=lambda item: item["index"])} + + def get_used_diluted_check_units(self, diluted_spacing: int, diluted_n_bits: int) -> int: + # The diluted cells are: + # state - 25 rounds times 1600 elements. + # parity - 24 rounds times 1600/5 elements times 3 auxiliaries. + # after_theta_rho_pi - 24 rounds times 1600 elements. + # theta_aux - 24 rounds times 1600 elements. + # chi_iota_aux - 24 rounds times 1600 elements times 2 auxiliaries. + # In total 25 * 1600 + 24 * 320 * 3 + 24 * 1600 + 24 * 1600 + 24 * 1600 * 2 = 216640. + # But we actually allocate 4 virtual columns, of dimensions 64 * 1024, in which we embed the + # real cells, and we don't free the unused ones. + # So the real number is 4 * 64 * 1024 = 262144. + return safe_div(2**18, diluted_n_bits) diff --git a/src/starkware/cairo/lang/builtins/range_check/CMakeLists.txt b/src/starkware/cairo/lang/builtins/range_check/CMakeLists.txt new file mode 100644 index 00000000..e70d104b --- /dev/null +++ b/src/starkware/cairo/lang/builtins/range_check/CMakeLists.txt @@ -0,0 +1,13 @@ +full_python_test(cairo_run_builtins_range_check_test + PREFIX starkware/cairo/lang/builtins/range_check + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/lang/builtins/range_check + + FILES + range_check_builtin_runner_test.py + + LIBS + cairo_run_builtins_test_utils_lib + cairo_vm_lib + pip_pytest +) diff --git a/src/starkware/cairo/lang/builtins/range_check/range_check_builtin_runner_test.py b/src/starkware/cairo/lang/builtins/range_check/range_check_builtin_runner_test.py index 6cfbf33e..ccbdc29e 100644 --- a/src/starkware/cairo/lang/builtins/range_check/range_check_builtin_runner_test.py +++ b/src/starkware/cairo/lang/builtins/range_check/range_check_builtin_runner_test.py @@ -8,10 +8,10 @@ def test_validation_rules(): CODE_FORMAT = """ %builtins range_check -func main(range_check_ptr) -> (range_check_ptr): - assert [range_check_ptr] = {value} - return (range_check_ptr=range_check_ptr + 1) -end +func main(range_check_ptr: felt) -> (range_check_ptr: felt) {{ + assert [range_check_ptr] = {value}; + return (range_check_ptr=range_check_ptr + 1); +}} """ # Test valid values. diff --git a/src/starkware/cairo/lang/builtins/signature/CMakeLists.txt b/src/starkware/cairo/lang/builtins/signature/CMakeLists.txt new file mode 100644 index 00000000..e3b02e92 --- /dev/null +++ b/src/starkware/cairo/lang/builtins/signature/CMakeLists.txt @@ -0,0 +1,14 @@ +full_python_test(cairo_run_builtins_signature_test + PREFIX starkware/cairo/lang/builtins/signature + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/lang/builtins/signature + + FILES + signature_builtin_runner_test.py + + LIBS + cairo_run_builtins_test_utils_lib + cairo_vm_lib + starkware_python_test_utils_lib + pip_pytest +) diff --git a/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner.py b/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner.py index 51f0b4fc..090c1ee2 100644 --- a/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner.py +++ b/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner.py @@ -105,7 +105,13 @@ def get_additional_data(self): def extend_additional_data(self, data, relocate_callback, data_is_trusted=True): for addr, signature in data: - self.signatures[relocate_callback(RelocatableValue.from_tuple(addr))] = signature + relocated_addr = relocate_callback(RelocatableValue.from_tuple(addr)) + assert relocated_addr.segment_index == self.base.segment_index, ( + f"Error while loading {self.name} builtin additional data: " + "Signature hint must point to the signature builtin segment. " + f"Found: {addr} (after relocation: {relocated_addr})." + ) + self.signatures[relocated_addr] = signature class SignatureBuiltinVerifier(BuiltinVerifier): diff --git a/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner_test.py b/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner_test.py index 016c2bb4..324c3d93 100644 --- a/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner_test.py +++ b/src/starkware/cairo/lang/builtins/signature/signature_builtin_runner_test.py @@ -33,8 +33,8 @@ class SignatureExample: SIG_PTR = "ecdsa_ptr" formats = SimpleNamespace( hint_code_format="%{{ ecdsa_builtin.add_signature({addr}, {signature}) %}}", - pubkey_code_format=f"assert [{SIG_PTR} + SignatureBuiltin.pub_key] = {{pubkey}}", - msg_code_format=f"assert [{SIG_PTR} + SignatureBuiltin.message] = {{msg}}", + pubkey_code_format=f"assert [{SIG_PTR} + SignatureBuiltin.pub_key] = {{pubkey}};", + msg_code_format=f"assert [{SIG_PTR} + SignatureBuiltin.message] = {{msg}};", ) # The address is used inside a hint. @@ -96,12 +96,12 @@ def get_test_cases(self): %builtins ecdsa from starkware.cairo.common.cairo_builtins import SignatureBuiltin -func main(ecdsa_ptr : felt) -> (ecdsa_ptr : felt): +func main(ecdsa_ptr: felt) -> (ecdsa_ptr: felt) {{ {hint} {write_pubkey} {write_msg} - return(ecdsa_ptr=ecdsa_ptr + SignatureBuiltin.SIZE) -end + return (ecdsa_ptr=ecdsa_ptr + SignatureBuiltin.SIZE); +}} """ test = SignatureTest() diff --git a/src/starkware/cairo/lang/cairo_cmake_rules.cmake b/src/starkware/cairo/lang/cairo_cmake_rules.cmake index 734af49e..7ac1a295 100644 --- a/src/starkware/cairo/lang/cairo_cmake_rules.cmake +++ b/src/starkware/cairo/lang/cairo_cmake_rules.cmake @@ -2,8 +2,6 @@ # See cairo_compile for usage example. function(cairo_compile_base TARGET_NAME COMPILER_EXE COMPILED_PROGRAM_NAME SOURCE_FILE COMPILE_FLAGS) - set(COMPILED_PROGRAM "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_compiled.json") - # Choose a file name for the Cairo dependencies of the compiled file. set(COMPILE_DEPENDENCY_FILE "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_compile_dependencies.cmake") diff --git a/src/starkware/cairo/lang/compiler/CMakeLists.txt b/src/starkware/cairo/lang/compiler/CMakeLists.txt index c84498ab..ea09cd6d 100644 --- a/src/starkware/cairo/lang/compiler/CMakeLists.txt +++ b/src/starkware/cairo/lang/compiler/CMakeLists.txt @@ -1,3 +1,6 @@ +add_subdirectory(ast) +add_subdirectory(preprocessor) + python_lib(cairo_compile_lib PREFIX starkware/cairo/lang/compiler FILES @@ -131,7 +134,6 @@ full_python_test(cairo_compile_test FILES assembler_test.py ast_objects_test.py - ast/formatting_utils_test.py cairo_compile_test.py conftest.py debug_info_test.py @@ -153,19 +155,6 @@ full_python_test(cairo_compile_test parser_errors_test.py parser_test_utils.py parser_test.py - preprocessor/bool_expr/lowering_test.py - preprocessor/compound_expressions_test.py - preprocessor/conftest.py - preprocessor/dependency_graph_test.py - preprocessor/flow_test.py - preprocessor/identifier_aware_visitor_test.py - preprocessor/identifier_collector_test.py - preprocessor/if_labels_test.py - preprocessor/local_variables_test.py - preprocessor/memento_test.py - preprocessor/preprocessor_test.py - preprocessor/reg_tracking_test.py - preprocessor/struct_collector_test.py proxy_identifier_manager_test.py references_test.py resolve_search_result_test.py diff --git a/src/starkware/cairo/lang/compiler/assembler.py b/src/starkware/cairo/lang/compiler/assembler.py index 808e23c2..d8e87918 100644 --- a/src/starkware/cairo/lang/compiler/assembler.py +++ b/src/starkware/cairo/lang/compiler/assembler.py @@ -8,6 +8,7 @@ from starkware.cairo.lang.compiler.program import CairoHint, Program from starkware.cairo.lang.compiler.scoped_name import ScopedName from starkware.cairo.lang.compiler.unique_name_provider import UniqueNameProvider +from starkware.cairo.lang.version import __version__ def assemble( @@ -80,4 +81,5 @@ def assemble( builtins=preprocessed_program.builtins, reference_manager=preprocessed_program.reference_manager, debug_info=debug_info, + compiler_version=__version__, ) diff --git a/src/starkware/cairo/lang/compiler/assembler_test.py b/src/starkware/cairo/lang/compiler/assembler_test.py index 1b26b08a..6e962a8a 100644 --- a/src/starkware/cairo/lang/compiler/assembler_test.py +++ b/src/starkware/cairo/lang/compiler/assembler_test.py @@ -27,6 +27,7 @@ def test_main_scope(): main_scope=ScopedName.from_string("a"), identifiers=identifiers, reference_manager=reference_manager, + compiler_version=None, ) # Check accessible identifiers. @@ -65,6 +66,7 @@ def test_program_start_property(): main_scope=main_scope, identifiers=identifiers, reference_manager=reference_manager, + compiler_version=None, ) assert program.start == 3 @@ -77,5 +79,6 @@ def test_program_start_property(): main_scope=main_scope, identifiers=IdentifierManager(), reference_manager=reference_manager, + compiler_version=None, ) assert program.start == 0 diff --git a/src/starkware/cairo/lang/compiler/ast/CMakeLists.txt b/src/starkware/cairo/lang/compiler/ast/CMakeLists.txt new file mode 100644 index 00000000..eeb89511 --- /dev/null +++ b/src/starkware/cairo/lang/compiler/ast/CMakeLists.txt @@ -0,0 +1,12 @@ +full_python_test(cairo_compile_formatting_utils_test + PREFIX starkware/cairo/lang/compiler/ast + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/lang/compiler/ast + + FILES + formatting_utils_test.py + + LIBS + cairo_compile_lib + pip_pytest +) diff --git a/src/starkware/cairo/lang/compiler/ast/cairo_types.py b/src/starkware/cairo/lang/compiler/ast/cairo_types.py index 35efa80d..0b6fdbcf 100644 --- a/src/starkware/cairo/lang/compiler/ast/cairo_types.py +++ b/src/starkware/cairo/lang/compiler/ast/cairo_types.py @@ -1,5 +1,7 @@ import dataclasses from abc import abstractmethod +from contextlib import contextmanager +from contextvars import ContextVar from enum import Enum, auto from typing import List, Optional, Sequence @@ -14,6 +16,25 @@ from starkware.cairo.lang.compiler.error_handling import Location from starkware.cairo.lang.compiler.scoped_name import ScopedName +add_backward_compatibility_space_ctx_var: ContextVar[int] = ContextVar( + "add_backward_compatibility_space", default=False +) + + +@contextmanager +def add_backward_compatibility_space(value: bool): + """ + Adds space before the colon when formatting named tuple types. + This should be used for backward compatibility in the contract hash computation in versions + before 0.10.0. + For example, use "(a : felt)" instead of "(a: felt)". + """ + token = add_backward_compatibility_space_ctx_var.set(value) + try: + yield + finally: + add_backward_compatibility_space_ctx_var.reset(token) + class CairoType(AstNode): location: Optional[Location] @@ -71,23 +92,46 @@ def get_children(self) -> Sequence[Optional[AstNode]]: return [self.pointee] +@dataclasses.dataclass +class TypeIdentifier(CairoType): + """ + Represents a name of an unresolved type. + This type can be resolved to TypeStruct or TypeDefinition. + """ + + name: ScopedName + location: Optional[Location] = LocationField + + def to_particle(self) -> Particle: + return SingleParticle(text=str(self.name)) + + def get_children(self) -> Sequence[Optional[AstNode]]: + return [] + + @dataclasses.dataclass class TypeStruct(CairoType): scope: ScopedName - # Indicates whether scope refers to the fully resolved name. - is_fully_resolved: bool location: Optional[Location] = LocationField def to_particle(self) -> Particle: return SingleParticle(text=str(self.scope)) - @property - def resolved_scope(self): - """ - Verifies that is_fully_resolved=True and returns scope. - """ - assert self.is_fully_resolved, "Type is expected to be fully resolved at this point." - return self.scope + def get_children(self) -> Sequence[Optional[AstNode]]: + return [] + + +@dataclasses.dataclass +class TypeFunction(CairoType): + """ + Represents a type of a function. + """ + + scope: ScopedName + location: Optional[Location] = LocationField + + def to_particle(self) -> Particle: + return SingleParticle(text=str(self.scope)) def get_children(self) -> Sequence[Optional[AstNode]]: return [] @@ -97,14 +141,14 @@ def get_children(self) -> Sequence[Optional[AstNode]]: class TypeTuple(CairoType): """ Represents a type of a named or unnamed tuple. - For example, "(felt, felt*)" or "(a : felt, b : felt*)". + For example, "(felt, felt*)" or "(a: felt, b: felt*)". """ @dataclasses.dataclass class Item(AstNode): """ Represents a possibly named type item of a TypeTuple. - For example: "felt" or "a : felt". + For example: "felt" or "a: felt". """ name: Optional[str] @@ -114,7 +158,10 @@ class Item(AstNode): def to_particle(self) -> Particle: particle = self.typ.to_particle() if self.name is not None: - particle.add_prefix(f"{self.name} : ") + backward_compatibility_space = ( + " " if add_backward_compatibility_space_ctx_var.get() else "" + ) + particle.add_prefix(f"{self.name}{backward_compatibility_space}: ") return particle def get_children(self) -> Sequence[Optional[AstNode]]: @@ -137,7 +184,10 @@ def get_particles(self) -> List[Particle]: return [member.to_particle() for member in self.members] def to_particle(self) -> Particle: - return SeparatedParticleList(elements=self.get_particles(), start="(", end=")") + has_trailing_comma = len(self.members) == 1 and self.members[0].name is None + return SeparatedParticleList( + elements=self.get_particles(), start="(", end=")", trailing_separator=has_trailing_comma + ) def get_children(self) -> Sequence[Optional[AstNode]]: return self.members @@ -181,7 +231,7 @@ class CastType(Enum): FORCED = 0 # When an explicit cast occurs using 'cast(*, *)'. EXPLICIT = auto() - # When unpacking occurs (e.g., 'let (x : T) = foo()'). + # When unpacking occurs (e.g., 'let (x: T) = foo();'). UNPACKING = auto() - # When a variable is initialized (e.g., 'tempvar x : T = 5'). + # When a variable is initialized (e.g., 'tempvar x: T = 5;'). ASSIGN = auto() diff --git a/src/starkware/cairo/lang/compiler/ast/code_elements.py b/src/starkware/cairo/lang/compiler/ast/code_elements.py index 393e4863..20ad1236 100644 --- a/src/starkware/cairo/lang/compiler/ast/code_elements.py +++ b/src/starkware/cairo/lang/compiler/ast/code_elements.py @@ -6,12 +6,7 @@ from starkware.cairo.lang.compiler.ast.arguments import IdentifierList from starkware.cairo.lang.compiler.ast.bool_expr import BoolExpr from starkware.cairo.lang.compiler.ast.cairo_types import CairoType -from starkware.cairo.lang.compiler.ast.expr import ( - ExprAssignment, - Expression, - ExprHint, - ExprIdentifier, -) +from starkware.cairo.lang.compiler.ast.expr import Expression, ExprHint, ExprIdentifier, ExprTuple from starkware.cairo.lang.compiler.ast.formatting_utils import ( INDENTATION, LocationField, @@ -47,7 +42,7 @@ def get_particles(self): return [self.instruction.format()] def format(self, allowed_line_length): - return self.instruction.format() + return self.instruction.format() + ";" def get_children(self) -> Sequence[Optional[AstNode]]: return [self.instruction] @@ -59,7 +54,7 @@ class CodeElementConst(CodeElement): expr: Expression def format(self, allowed_line_length): - return f"const {self.identifier.format()} = {self.expr.format()}" + return f"const {self.identifier.format()} = {self.expr.format()};" def get_children(self) -> Sequence[Optional[AstNode]]: return [self.identifier, self.expr] @@ -71,7 +66,7 @@ class CodeElementMember(CodeElement): def format(self, allowed_line_length): particle = self.typed_identifier.to_particle() - particle.add_prefix("member ") + particle.add_suffix(",") return particles_in_lines( particles=particle, config=ParticleFormattingConfig( @@ -91,7 +86,7 @@ class CodeElementReference(CodeElement): def format(self, allowed_line_length): particle = self.typed_identifier.to_particle() particle.add_prefix("let ") - particle.add_suffix(f" = {self.expr.format()}") + particle.add_suffix(f" = {self.expr.format()};") return particles_in_lines( particles=particle, config=ParticleFormattingConfig( @@ -107,7 +102,7 @@ def get_children(self) -> Sequence[Optional[AstNode]]: class CodeElementLocalVariable(CodeElement): """ Represents a statement of the form: - local x [: expr_type] = [expr] + local x [: expr_type] = [expr]; Both the expr_type and the initialization expr are optional. """ @@ -121,6 +116,7 @@ def format(self, allowed_line_length): particle.add_prefix("local ") if self.expr is not None: particle.add_suffix(f" = {self.expr.format()}") + particle.add_suffix(";") return particles_in_lines( particles=particle, config=ParticleFormattingConfig( @@ -136,7 +132,7 @@ def get_children(self) -> Sequence[Optional[AstNode]]: class CodeElementTemporaryVariable(CodeElement): """ Represents a statement of the form: - tempvar x = expr. + tempvar x = expr; """ typed_identifier: TypedIdentifier @@ -148,6 +144,7 @@ def format(self, allowed_line_length): particle.add_prefix("tempvar ") if self.expr is not None: particle.add_suffix(f" = {self.expr.format()}") + particle.add_suffix(";") return particles_in_lines( particles=particle, config=ParticleFormattingConfig( @@ -172,7 +169,7 @@ class CodeElementCompoundAssertEq(CodeElement): location: Optional[Location] = LocationField def format(self, allowed_line_length): - return f"assert {self.a.format()} = {self.b.format()}" + return f"assert {self.a.format()} = {self.b.format()};" def get_children(self) -> Sequence[Optional[AstNode]]: return [self.a, self.b] @@ -185,7 +182,7 @@ class CodeElementStaticAssert(CodeElement): location: Optional[Location] = LocationField def format(self, allowed_line_length): - return f"static_assert {self.a.format()} == {self.b.format()}" + return f"static_assert {self.a.format()} == {self.b.format()};" def get_children(self) -> Sequence[Optional[AstNode]]: return [self.a, self.b] @@ -195,44 +192,57 @@ def get_children(self) -> Sequence[Optional[AstNode]]: class CodeElementReturn(CodeElement): """ Represents a statement of the form: - return ([ident=]expr, ...). + return expr; """ - exprs: List[ExprAssignment] + expr: Expression location: Optional[Location] = LocationField def format(self, allowed_line_length): - expr_codes = [x.format() for x in self.exprs] + if isinstance(self.expr, ExprTuple): + self.expr.members.assert_no_comments() + args = self.expr.members.args + expr_codes = [arg.format() for arg in args] + + trailing_comma = self.expr.members.has_trailing_comma and len(args) > 0 + + return particles_in_lines( + particles=ParticleList( + elements=[ + "return (", + SeparatedParticleList( + elements=expr_codes, end=");", trailing_separator=trailing_comma + ), + ] + ), + config=ParticleFormattingConfig( + allowed_line_length=allowed_line_length, + line_indent=INDENTATION, + one_per_line=True, + ), + ) - return particles_in_lines( - particles=ParticleList( - elements=[ - "return (", - SeparatedParticleList(elements=expr_codes, end=")"), - ] - ), - config=ParticleFormattingConfig( - allowed_line_length=allowed_line_length, line_indent=INDENTATION, one_per_line=True - ), - ) + return "return " + self.expr.format() + ";" def get_children(self) -> Sequence[Optional[AstNode]]: - return self.exprs + return [self.expr] @dataclasses.dataclass class CodeElementTailCall(CodeElement): """ Represents a statement of the form: - return func_ident([ident=]expr, ...). + return func_ident([ident=]expr, ...); """ func_call: RvalueFuncCall location: Optional[Location] = LocationField def get_particles(self): - particales = self.func_call.get_particles() - return ["return " + particales[0]] + particales[1:] + particles = self.func_call.get_particles() + particles[0].add_prefix("return ") + particles[-1].add_suffix(";") + return particles def format(self, allowed_line_length): return particles_in_lines( @@ -250,7 +260,7 @@ def get_children(self) -> Sequence[Optional[AstNode]]: class CodeElementFuncCall(CodeElement): """ Represents a statement of the form: - func_ident([ident=]expr, ...). + func_ident([ident=]expr, ...); """ func_call: RvalueFuncCall @@ -259,7 +269,7 @@ def get_particles(self): return self.func_call.get_particles() def format(self, allowed_line_length): - return self.func_call.format(allowed_line_length) + return self.func_call.format_ex(allowed_line_length, semicolon=True) def get_children(self) -> Sequence[Optional[AstNode]]: return [self.func_call] @@ -269,9 +279,9 @@ def get_children(self) -> Sequence[Optional[AstNode]]: class CodeElementReturnValueReference(CodeElement): """ Represents one of the references below. - let x [: type] = func(...) - let x [: type] = call func - let x [: type] = call rel 5 + let x [: type] = func(...); + let x [: type] = call func; + let x [: type] = call rel 5; where: 'x [: type]' is the 'typed_identifier' 'func(...)' is the 'func_call'. @@ -286,8 +296,11 @@ def format(self, allowed_line_length): first_particle.add_prefix("let ") first_particle.add_suffix(f" = {call_particles[0]}") + particles = ParticleList(elements=[first_particle] + call_particles[1:]) + particles.add_suffix(";") + return particles_in_lines( - particles=ParticleList(elements=[first_particle] + call_particles[1:]), + particles=particles, config=ParticleFormattingConfig( allowed_line_length=allowed_line_length, line_indent=INDENTATION, one_per_line=True ), @@ -301,7 +314,7 @@ def get_children(self) -> Sequence[Optional[AstNode]]: class CodeElementUnpackBinding(CodeElement): """ Represents return value unpacking statement of the form: - let (a, b, c) = func(...) + let (a, b, c) = func(...); where: '(a, b, c)' is the 'unpacking_list' 'func(...)' is the 'rvalue'. @@ -311,16 +324,21 @@ class CodeElementUnpackBinding(CodeElement): rvalue: Rvalue def format(self, allowed_line_length): - particles = self.rvalue.get_particles() + rvalue_particles = self.rvalue.get_particles() + rvalue_particles[0].add_prefix(") = ") + unpacking_list_particles: List[Particle] = [ + SeparatedParticleList( + elements=self.unpacking_list.get_particles(), + start="let (", + end=str(rvalue_particles[0]), + ) + ] - end_particle = ") = " + particles[0] - unpacking_list_particles = SeparatedParticleList( - elements=self.unpacking_list.get_particles(), end=end_particle - ) - particles = ["let (", unpacking_list_particles] + particles[1:] + particles = ParticleList(elements=unpacking_list_particles + rvalue_particles[1:]) + particles.add_suffix(";") return particles_in_lines( - particles=ParticleList(elements=particles), + particles=particles, config=ParticleFormattingConfig( allowed_line_length=allowed_line_length, line_indent=INDENTATION, one_per_line=True ), @@ -374,7 +392,7 @@ class CommentedCodeElement(AstNode): def format(self, allowed_line_length): elm_str = self.code_elm.format(allowed_line_length=allowed_line_length) - comment_str = f"#{self.comment}" if self.comment is not None else "" + comment_str = f"//{self.comment}" if self.comment is not None else "" separator = " " if elm_str != "" and comment_str != "" else "" return elm_str + separator + comment_str.rstrip() @@ -465,9 +483,9 @@ class CodeElementFunction(CodeElement): """ Represents either a 'func', 'namespace' or 'struct' statement. For example: - func foo(x, y) -> (z : felt, w : felt): - return (z=x, w=y) - end + func foo(x, y) -> (z: felt, w: felt) { + return (z=x, w=y); + } """ # The type of the code element. Either 'func', 'namespace' or 'struct'. @@ -475,7 +493,7 @@ class CodeElementFunction(CodeElement): identifier: ExprIdentifier arguments: IdentifierList implicit_arguments: Optional[IdentifierList] - returns: Optional[IdentifierList] + returns: Optional[CairoType] code_block: CodeBlock decorators: List[ExprIdentifier] additional_attributes: Dict[str, Any] = dataclasses.field(default_factory=dict) @@ -493,7 +511,7 @@ def format(self, allowed_line_length): code = indent(code, INDENTATION) particles: List[Union[Particle, str]] if self.element_type in ["struct", "namespace"]: - particles = [f"{self.element_type} {self.name}:"] + particles = [f"{self.element_type} {self.name} {{"] else: if self.implicit_arguments is not None: first_particle_suffix = "{" @@ -506,19 +524,32 @@ def format(self, allowed_line_length): first_particle_suffix = "(" implicit_args_particles = [] - if self.returns is not None: - particles = [ - f"{self.element_type} {self.name}{first_particle_suffix}", - *implicit_args_particles, - SeparatedParticleList(elements=self.arguments.get_particles(), end=") -> ("), - SeparatedParticleList(elements=self.returns.get_particles(), end="):"), - ] + args_particle = SeparatedParticleList(elements=self.arguments.get_particles()) + if self.returns is None: + args_particle.add_suffix(") {") + return_particles = [] else: - particles = [ - f"{self.element_type} {self.name}{first_particle_suffix}", - *implicit_args_particles, - SeparatedParticleList(elements=self.arguments.get_particles(), end="):"), - ] + return_particle = self.returns.to_particle() + return_particle.add_suffix(" {") + args_suffix = ") -> " + if isinstance(return_particle, SeparatedParticleList): + args_suffix += return_particle.start + return_particle.start = "" + return_particles = [return_particle] + else: + # If return_particle is not a SeparatedParticleList we add the entire + # particle to args_suffix. + # This is needed to avoid a line break between the '->' and the return type. + args_suffix += str(return_particle) + return_particles = [] + args_particle.add_suffix(args_suffix) + + particles = [ + f"{self.element_type} {self.name}{first_particle_suffix}", + *implicit_args_particles, + args_particle, + *return_particles, + ] decorators = "".join(f"@{decorator.format()}\n" for decorator in self.decorators) header = particles_in_lines( @@ -529,7 +560,7 @@ def format(self, allowed_line_length): double_indentation=True, ), ) - return f"{decorators}{header}\n{code}end" + return f"{decorators}{header}\n{code}}}" def get_children(self) -> Sequence[Optional[AstNode]]: return [ @@ -545,9 +576,9 @@ def get_children(self) -> Sequence[Optional[AstNode]]: class CodeElementTypeDef(CodeElement): """ Represents a statement of the form: - using new_type_name = old_type + using new_type_name = old_type; For example, - using Point = (x : felt, y : felt) + using Point = (x: felt, y: felt); """ identifier: ExprIdentifier @@ -555,7 +586,7 @@ class CodeElementTypeDef(CodeElement): location: Optional[Location] = LocationField def format(self, allowed_line_length): - return f"using {self.identifier.format()} = {self.cairo_type.format()}" + return f"using {self.identifier.format()} = {self.cairo_type.format()};" @property def name(self) -> str: @@ -581,9 +612,9 @@ def format(self, allowed_line_length): if len(self.attribute_value) == 0: # Attribute has no value. - return f"with_attr {self.attribute_name.format()}:\n{inner_code}end" + return f"with_attr {self.attribute_name.format()} {{\n{inner_code}}}" - len_without_value = len(f"with_attr {self.attribute_name.format()}():") + len_without_value = len(f"with_attr {self.attribute_name.format()}() {{") if ( len(self.attribute_value) == 1 and len_without_value + len(self.attribute_value[0]) <= allowed_line_length @@ -591,7 +622,7 @@ def format(self, allowed_line_length): attribute_value = self.attribute_value[0] else: attribute_value = "\n" + indent("\n".join(self.attribute_value), 2 * INDENTATION) - return f"with_attr {self.attribute_name.format()}({attribute_value}):\n{inner_code}end" + return f"with_attr {self.attribute_name.format()}({attribute_value}) {{\n{inner_code}}}" def get_children(self) -> Sequence[Optional[AstNode]]: return [self.attribute_name, self.code_block] @@ -609,7 +640,7 @@ def format(self, allowed_line_length): identifier_list_str = ", ".join(identifier.format() for identifier in self.identifiers) inner_code = self.code_block.format(allowed_line_length=allowed_line_length - INDENTATION) inner_code = indent(inner_code, INDENTATION) - return f"with {identifier_list_str}:\n{inner_code}end" + return f"with {identifier_list_str} {{\n{inner_code}}}" def get_children(self) -> Sequence[Optional[AstNode]]: return [*self.identifiers, self.code_block] @@ -626,8 +657,8 @@ class CodeElementIf(CodeElement): def format(self, allowed_line_length): cond_particle = self.condition.to_particle() - cond_particle.add_prefix("if ") - cond_particle.add_suffix(":") + cond_particle.add_prefix("if (") + cond_particle.add_suffix(") {") code = particles_in_lines( particles=cond_particle, config=ParticleFormattingConfig( @@ -640,13 +671,13 @@ def format(self, allowed_line_length): main_code = indent(main_code, INDENTATION) code += f"\n{main_code}" if self.else_code_block is not None: - code += f"else:" + code += "} else {" else_code = self.else_code_block.format( allowed_line_length=allowed_line_length - INDENTATION ) else_code = indent(else_code, INDENTATION) code += f"\n{else_code}" - code += "end" + code += "}" return code def get_children(self) -> Sequence[Optional[AstNode]]: @@ -738,7 +769,7 @@ class CodeElementAllocLocals(CodeElement): location: Optional[Location] = LocationField def format(self, allowed_line_length): - return "alloc_locals" + return "alloc_locals;" def get_children(self) -> Sequence[Optional[AstNode]]: return [] diff --git a/src/starkware/cairo/lang/compiler/ast/expr.py b/src/starkware/cairo/lang/compiler/ast/expr.py index c5196e20..e375cf2d 100644 --- a/src/starkware/cairo/lang/compiler/ast/expr.py +++ b/src/starkware/cairo/lang/compiler/ast/expr.py @@ -7,13 +7,21 @@ import marshmallow from starkware.cairo.lang.compiler.ast.cairo_types import CairoType, CastType -from starkware.cairo.lang.compiler.ast.formatting_utils import INDENTATION, LocationField +from starkware.cairo.lang.compiler.ast.formatting_utils import ( + INDENTATION, + LocationField, + Particle, + ParticleList, + SeparatedParticleList, + SingleParticle, +) from starkware.cairo.lang.compiler.ast.node import AstNode from starkware.cairo.lang.compiler.ast.notes import Notes, NotesField from starkware.cairo.lang.compiler.error_handling import Location from starkware.cairo.lang.compiler.instruction import Register from starkware.python.expression_string import ExpressionString from starkware.python.utils import indent, safe_zip +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata class Expression(AstNode): @@ -34,6 +42,12 @@ def to_expr_str(self) -> ExpressionString: insertion of parentheses (where required). """ + @abstractmethod + def get_particles(self) -> List[Particle]: + """ + Returns a list of particles representing the expression, for formatting purposes. + """ + @dataclasses.dataclass class ExprConst(Expression): @@ -44,16 +58,25 @@ class ExprConst(Expression): default=None, hash=False, compare=False, - metadata=dict(marshmallow_field=marshmallow.fields.Field(load_only=True, dump_only=True)), + metadata=additional_metadata( + marshmallow_field=marshmallow.fields.Field(load_only=True, dump_only=True) + ), ) location: Optional[Location] = LocationField + def absolute_val_format(self) -> str: + return str(abs(self.val)) if self.format_str is None else self.format_str + def to_expr_str(self): - abs_format = str(abs(self.val)) if self.format_str is None else self.format_str + abs_format = self.absolute_val_format() if self.val >= 0: return ExpressionString.highest(abs_format) return -ExpressionString.highest(abs_format) + def get_particles(self) -> List[Particle]: + abs_format = self.absolute_val_format() + return [SingleParticle(text=abs_format if self.val >= 0 else f"-{abs_format}")] + def get_children(self) -> Sequence[Optional[AstNode]]: return [] @@ -99,6 +122,9 @@ def to_str(self): def to_expr_str(self): return ExpressionString.highest(f"nondet {self.to_str()}") + def get_particles(self) -> List[Particle]: + return [SingleParticle(text=f"nondet {self.to_str()}")] + def get_children(self) -> Sequence[Optional[AstNode]]: return [] @@ -111,6 +137,9 @@ class ExprIdentifier(Expression): def to_expr_str(self): return ExpressionString.highest(self.name) + def get_particles(self) -> List[Particle]: + return [SingleParticle(text=self.name)] + def get_children(self) -> Sequence[Optional[AstNode]]: return [] @@ -185,6 +214,9 @@ class ExprReg(Expression): def to_expr_str(self): return ExpressionString.highest(self.reg.name.lower()) + def get_particles(self) -> List[Particle]: + return [SingleParticle(text=self.reg.name.lower())] + def get_children(self) -> Sequence[Optional[AstNode]]: return [] @@ -214,6 +246,13 @@ def to_expr_str(self): else: raise NotImplementedError(f"Unexpected operator '{self.op}'") + def get_particles(self) -> List[Particle]: + self.notes.assert_no_comments() + + a_particles = self.a.get_particles() + a_particles[-1].add_suffix(f" {self.op} ") + return a_particles + self.b.get_particles() + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.a, self.b] @@ -233,6 +272,13 @@ def to_expr_str(self): b = b.prepend("\n") return a.double_star_pow(b) + def get_particles(self) -> List[Particle]: + self.notes.assert_no_comments() + + a_particles = self.a.get_particles() + a_particles[-1].add_suffix(f" ** ") + return a_particles + self.b.get_particles() + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.a, self.b] @@ -249,6 +295,11 @@ class ExprAddressOf(Expression): def to_expr_str(self): return self.expr.to_expr_str().address_of() + def get_particles(self) -> List[Particle]: + particles = self.expr.get_particles() + particles[0].add_prefix("&") + return particles + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.expr] @@ -261,6 +312,11 @@ class ExprNeg(Expression): def to_expr_str(self): return -self.val.to_expr_str() + def get_particles(self) -> List[Particle]: + particles = self.val.get_particles() + particles[0].add_prefix("-") + return particles + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.val] @@ -274,6 +330,17 @@ class ExprParentheses(Expression): def to_expr_str(self): return ExpressionString.highest(f"({self.notes.format()}{str(self.val.to_expr_str())})") + def get_particles(self) -> List[Particle]: + self.notes.assert_no_comments() + return [ + SeparatedParticleList( + elements=self.val.get_particles(), + start="(", + end=")", + separator="", + ) + ] + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.val] @@ -293,6 +360,14 @@ def to_expr_str(self): notes = "" if self.notes.empty else "\n" return ExpressionString.highest(f"[{notes}{str(self.addr.to_expr_str())}]") + def get_particles(self) -> List[Particle]: + self.notes.assert_no_comments() + return [ + SeparatedParticleList( + elements=self.addr.get_particles(), start="[", end="]", separator="" + ) + ] + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.addr] @@ -316,6 +391,17 @@ def to_expr_str(self): f"{self.expr.to_expr_str():HIGHEST}[{notes}{str(self.offset.to_expr_str())}]" ) + def get_particles(self) -> List[Particle]: + self.notes.assert_no_comments() + + expr_particles = self.expr.get_particles() + expr_particles[-1].add_suffix("[") + offset_particle = SeparatedParticleList( + elements=self.offset.get_particles(), start="", end="]", separator="" + ) + + return expr_particles + [offset_particle] + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.expr, self.offset] @@ -336,6 +422,13 @@ def to_expr_str(self): f"{self.expr.to_expr_str():HIGHEST}.{str(self.member.to_expr_str())}" ) + def get_particles(self) -> List[Particle]: + expr_particles = self.expr.get_particles() + member_str = "".join(str(particle) for particle in self.member.get_particles()) + expr_particles[-1].add_suffix(f".{member_str}") + + return expr_particles + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.expr, self.member] @@ -361,6 +454,17 @@ def to_expr_str(self): f"cast({notes}{str(self.expr.to_expr_str())}, {self.dest_type.format()})" ) + def get_particles(self) -> List[Particle]: + expr_particles = self.expr.get_particles() + type_particle = self.dest_type.to_particle() + return [ + SeparatedParticleList( + elements=[ParticleList(elements=expr_particles), type_particle], + start="cast(", + end=")", + ) + ] + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.expr, self.dest_type] @@ -374,6 +478,13 @@ def to_expr_str(self): code = self.members.format() return ExpressionString.highest(f"({code})") + def get_particles(self) -> List[Particle]: + return [ + SeparatedParticleList( + elements=[x.format() for x in self.members.args], start="(", end=")" + ) + ] + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.members] @@ -392,6 +503,9 @@ class ExprFutureLabel(Expression): def to_expr_str(self): return self.identifier.to_expr_str() + def get_particles(self) -> List[Particle]: + return self.identifier.get_particles() + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.identifier] @@ -412,5 +526,10 @@ class ExprNewOperator(Expression): def to_expr_str(self): return self.expr.to_expr_str().operator_new() + def get_particles(self) -> List[Particle]: + particles = self.expr.get_particles() + particles[0].add_prefix("new ") + return particles + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.expr] diff --git a/src/starkware/cairo/lang/compiler/ast/expr_func_call.py b/src/starkware/cairo/lang/compiler/ast/expr_func_call.py index c353f283..045465b8 100644 --- a/src/starkware/cairo/lang/compiler/ast/expr_func_call.py +++ b/src/starkware/cairo/lang/compiler/ast/expr_func_call.py @@ -1,8 +1,8 @@ import dataclasses -from typing import Optional, Sequence +from typing import List, Optional, Sequence from starkware.cairo.lang.compiler.ast.expr import Expression -from starkware.cairo.lang.compiler.ast.formatting_utils import LocationField +from starkware.cairo.lang.compiler.ast.formatting_utils import LocationField, Particle from starkware.cairo.lang.compiler.ast.node import AstNode from starkware.cairo.lang.compiler.ast.rvalue import RvalueFuncCall from starkware.cairo.lang.compiler.error_handling import Location @@ -21,5 +21,8 @@ class ExprFuncCall(Expression): def to_expr_str(self): return ExpressionString.highest(self.rvalue.format_for_expr()) + def get_particles(self) -> List[Particle]: + return self.rvalue.get_particles() + def get_children(self) -> Sequence[Optional[AstNode]]: return [self.rvalue] diff --git a/src/starkware/cairo/lang/compiler/ast/formatting_utils.py b/src/starkware/cairo/lang/compiler/ast/formatting_utils.py index 77f14d36..c37af63a 100644 --- a/src/starkware/cairo/lang/compiler/ast/formatting_utils.py +++ b/src/starkware/cairo/lang/compiler/ast/formatting_utils.py @@ -12,13 +12,16 @@ import marshmallow from starkware.cairo.lang.compiler.error_handling import LocationError +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata INDENTATION = 4 LocationField = field( default=None, hash=False, compare=False, - metadata=dict(marshmallow_field=marshmallow.fields.Field(load_only=True, dump_only=True)), + metadata=additional_metadata( + marshmallow_field=marshmallow.fields.Field(load_only=True, dump_only=True) + ), ) max_line_length_ctx_var: ContextVar[int] = ContextVar("max_line_length", default=100) one_item_per_line_ctx_var: ContextVar[bool] = ContextVar("one_item_per_line", default=True) @@ -177,6 +180,12 @@ def add_suffix(self, suffix: str): The suffix is glued to the particle (not splittable). """ + @abstractmethod + def pop_prefix(self) -> str: + """ + Removes and returns the particle prefix. + """ + @abstractmethod def add_to_builder(self, builder: ParticleLineBuilder, suffix: str = ""): """ @@ -205,6 +214,11 @@ def add_prefix(self, prefix: str): def add_suffix(self, suffix: str): self.text += suffix + def pop_prefix(self) -> str: + prefix = self.text + self.text = "" + return prefix + def add_to_builder(self, builder: ParticleLineBuilder, suffix: str = ""): builder.add_to_line(f"{self.text}{suffix}") @@ -237,6 +251,11 @@ def add_suffix(self, suffix: str): assert len(self.elements) > 0 self.elements[-1].add_suffix(suffix) + def pop_prefix(self) -> str: + if len(self.elements) == 0: + return "" + return self.elements[0].pop_prefix() + def add_to_builder(self, builder: ParticleLineBuilder, suffix: str = ""): for i, particle in enumerate(self.elements): particle.add_to_builder( @@ -281,6 +300,11 @@ def add_prefix(self, prefix: str): def add_suffix(self, suffix: str): self.end += suffix + def pop_prefix(self) -> str: + prefix = self.start + self.start = "" + return prefix + def elements_to_string(self) -> str: """ Returns a concatenation of the strings in self.elements, separated with self.separator. @@ -328,7 +352,7 @@ def add_elements_one_per_line(self, builder: ParticleLineBuilder, suffix: str): a, b, c, - ): + ) { """ # If the entire list fits in a new line, add it. # Else, add each element of the list in a separate line. @@ -360,10 +384,10 @@ def add_elements_indent_new_lines( x, y, z) -> ( a, b, - c): + c) { With a longer line length we will get the lists on the same line: - func f(x, y, z) -> (a, b, c): + func f(x, y, z) -> (a, b, c) { """ # If the entire list fits in the current line, add it. elements_string = f"{self.elements_to_string()}{self.end}{suffix}" @@ -414,7 +438,7 @@ def particles_in_lines(particles: Particle, config: ParticleFormattingConfig) -> ParticleList(elements=[ 'func f(', SeparatedParticleList(elements=['x', 'y', 'z'], end=') -> ('), - SeparatedParticleList(elements=['a', 'b', 'c'], end='):')]), + SeparatedParticleList(elements=['a', 'b', 'c'], end=') {')]), 12, 4) """ diff --git a/src/starkware/cairo/lang/compiler/ast/formatting_utils_test.py b/src/starkware/cairo/lang/compiler/ast/formatting_utils_test.py index 55cb8806..bb504c1a 100644 --- a/src/starkware/cairo/lang/compiler/ast/formatting_utils_test.py +++ b/src/starkware/cairo/lang/compiler/ast/formatting_utils_test.py @@ -240,27 +240,27 @@ def test_nested_particle_lists(): "felt", SeparatedParticleList(elements=["felt, felt"], start="(", end=")"), ], - start="d : (", + start="d: (", end=")", ) return_val_e = SeparatedParticleList( - elements=["f : felt", "g : felt"], - start="e : (", + elements=["f: felt", "g: felt"], + start="e: (", end=")", ) return_val_h = SeparatedParticleList( elements=["felt", "felt", "felt", "felt"], - start="h : (", + start="h: (", end=")", ) return_val_b = SeparatedParticleList( elements=[ - "c : felt", + "c: felt", return_val_d, return_val_e, return_val_h, ], - start="b : (", + start="b: (", end=")", ) particles = ParticleList( @@ -269,7 +269,7 @@ def test_nested_particle_lists(): SeparatedParticleList(elements=["x", "y", "z"], end=") -> ("), SeparatedParticleList( elements=[ - "a : felt", + "a: felt", return_val_b, ], end="):", @@ -278,21 +278,21 @@ def test_nested_particle_lists(): ) expected = """\ func f(x, y, z) -> ( - a : felt, - b : (c : felt, - d : (felt, (felt, felt)), - e : (f : felt, g : felt), - h : (felt, felt, felt, + a: felt, + b: (c: felt, + d: (felt, (felt, felt)), + e: (f: felt, g: felt), + h: (felt, felt, felt, felt))):\ """ expected_one_per_line = """\ func f(x, y, z) -> ( - a : felt, - b : ( - c : felt, - d : (felt, (felt, felt)), - e : (f : felt, g : felt), - h : ( + a: felt, + b: ( + c: felt, + d: (felt, (felt, felt)), + e: (f: felt, g: felt), + h: ( felt, felt, felt, felt ), ), diff --git a/src/starkware/cairo/lang/compiler/ast/instructions.py b/src/starkware/cairo/lang/compiler/ast/instructions.py index c6e05e33..53de81af 100644 --- a/src/starkware/cairo/lang/compiler/ast/instructions.py +++ b/src/starkware/cairo/lang/compiler/ast/instructions.py @@ -186,7 +186,7 @@ class InstructionAst(AstNode): location: Optional[Location] = LocationField def format(self): - return self.body.format() + ("; ap++" if self.inc_ap else "") + return self.body.format() + (", ap++" if self.inc_ap else "") def get_children(self) -> Sequence[Optional[AstNode]]: return [self.body] diff --git a/src/starkware/cairo/lang/compiler/ast/notes.py b/src/starkware/cairo/lang/compiler/ast/notes.py index b189b9dd..e5892655 100644 --- a/src/starkware/cairo/lang/compiler/ast/notes.py +++ b/src/starkware/cairo/lang/compiler/ast/notes.py @@ -16,8 +16,8 @@ class Notes(AstNode): For example, in the following code the first comment is represented by a note and the second is represented in the CommentedCodeElement: - assert a = b + # Hello. - c + d # World. + assert a = b + // Hello. + c + d // World. """ # The comments of the note. If empty, the value of starts_new_line is ignored. @@ -62,11 +62,15 @@ def format(self): elif len(self.comments) > 0: code += " " for comment in self.comments: - assert comment.startswith("#") - comment_body = comment[1:].strip() + if comment.startswith("//"): + comment_body = comment[2:].strip() + elif comment.startswith("#"): + comment_body = comment[1:].strip() + else: + raise Exception("Internal error: comment prefix not found.") if comment_body != "": comment_body = " " + comment_body - code += f"#{comment_body}\n" + code += f"//{comment_body}\n" return code def get_children(self) -> Sequence[Optional[AstNode]]: diff --git a/src/starkware/cairo/lang/compiler/ast/rvalue.py b/src/starkware/cairo/lang/compiler/ast/rvalue.py index 63ba5737..12199bd7 100644 --- a/src/starkware/cairo/lang/compiler/ast/rvalue.py +++ b/src/starkware/cairo/lang/compiler/ast/rvalue.py @@ -1,14 +1,16 @@ import dataclasses from abc import abstractmethod -from typing import Optional, Sequence +from typing import List, Optional, Sequence from starkware.cairo.lang.compiler.ast.expr import ArgList, Expression, ExprIdentifier from starkware.cairo.lang.compiler.ast.formatting_utils import ( INDENTATION, LocationField, + Particle, ParticleFormattingConfig, ParticleList, SeparatedParticleList, + SingleParticle, particles_in_lines, ) from starkware.cairo.lang.compiler.ast.instructions import CallInstruction @@ -33,7 +35,7 @@ def location(self): """ @abstractmethod - def get_particles(self): + def get_particles(self) -> List[Particle]: """ Returns a list of particles that can be used to convert the Rvalue to a multiline string. """ @@ -57,8 +59,8 @@ class RvalueExpr(Rvalue): def location(self): return self.expr.location - def get_particles(self): - return [self.expr.format()] + def get_particles(self) -> List[Particle]: + return [SingleParticle(text=self.expr.format())] def format(self): return self.expr.format() @@ -89,8 +91,8 @@ class RvalueCallInst(RvalueCall): def location(self): return self.call_inst.location - def get_particles(self): - return [self.call_inst.format()] + def get_particles(self) -> List[Particle]: + return [SingleParticle(text=self.call_inst.format())] def format(self): return self.call_inst.format() @@ -116,20 +118,21 @@ def assert_no_comments(self): if self.implicit_arguments is not None: self.implicit_arguments.assert_no_comments() - def get_particles(self): + def get_particles(self) -> List[Particle]: self.assert_no_comments() - particles = [self.func_ident.format()] + particles = self.func_ident.get_particles() if self.implicit_arguments is not None: - particles[-1] += "{" + particles[-1].add_suffix("{") particles.append( SeparatedParticleList( - elements=[x.format() for x in self.implicit_arguments.args], end="}(" + elements=[x.format() for x in self.implicit_arguments.args], + end="}(", ) ) else: - particles[-1] += "(" + particles[-1].add_suffix("(") particles.append( SeparatedParticleList(elements=[x.format() for x in self.arguments.args], end=")") @@ -137,9 +140,15 @@ def get_particles(self): return particles def format(self, allowed_line_length): + return self.format_ex(allowed_line_length=allowed_line_length, semicolon=False) + + def format_ex(self, allowed_line_length, semicolon: bool): self.assert_no_comments() + particles = ParticleList(elements=self.get_particles()) + if semicolon: + particles.add_suffix(";") return particles_in_lines( - particles=ParticleList(elements=self.get_particles()), + particles=particles, config=ParticleFormattingConfig( allowed_line_length=allowed_line_length, line_indent=INDENTATION, one_per_line=True ), diff --git a/src/starkware/cairo/lang/compiler/ast/types.py b/src/starkware/cairo/lang/compiler/ast/types.py index b9a1cb73..cf5afde3 100644 --- a/src/starkware/cairo/lang/compiler/ast/types.py +++ b/src/starkware/cairo/lang/compiler/ast/types.py @@ -41,7 +41,7 @@ def to_particle(self) -> Particle: return SingleParticle(text=modifier_str + self.identifier.format()) else: particle = self.expr_type.to_particle() - particle.add_prefix(modifier_str + self.identifier.format() + " : ") + particle.add_prefix(modifier_str + self.identifier.format() + ": ") return particle def format(self): diff --git a/src/starkware/cairo/lang/compiler/ast/visitor.py b/src/starkware/cairo/lang/compiler/ast/visitor.py index 7365a1b6..58f57625 100644 --- a/src/starkware/cairo/lang/compiler/ast/visitor.py +++ b/src/starkware/cairo/lang/compiler/ast/visitor.py @@ -27,8 +27,10 @@ class Visitor: Base visitor class for visiting code elements in the Cairo AST. """ - def __init__(self): - self.accessible_scopes: List[ScopedName] = [] + def __init__(self, accessible_scopes: Optional[List[ScopedName]] = None): + self.accessible_scopes: List[ScopedName] = ( + [] if accessible_scopes is None else accessible_scopes.copy() + ) self.parents: List[Optional[AstNode]] = [] self.file_lang: Optional[str] = None @@ -39,6 +41,9 @@ def visit(self, obj): """ return getattr(self, f"visit_{type(obj).__name__}", self._visit_default)(obj) + def visit_CairoFile(self, elm: CairoFile): + return CairoFile(code_block=self.visit(elm.code_block)) + def visit_CodeElementFunction(self, elm: CodeElementFunction): if elm.element_type == "struct": return elm diff --git a/src/starkware/cairo/lang/compiler/ast_objects_test.py b/src/starkware/cairo/lang/compiler/ast_objects_test.py index 0dc0b4fa..7f6480f4 100644 --- a/src/starkware/cairo/lang/compiler/ast_objects_test.py +++ b/src/starkware/cairo/lang/compiler/ast_objects_test.py @@ -66,10 +66,10 @@ def test_format_parentheses(): def test_format_parentheses_notes(): before = """\ -( # Comment. +( // Comment. a + b)""" after = """\ -( # Comment. +( // Comment. a + b)""" assert parse_expr(before).format() == after @@ -83,33 +83,33 @@ def test_format_parentheses_notes(): before = """\ ( - # Comment. + // Comment. a + b)""" after = """\ ( - # Comment. + // Comment. a + b)""" assert parse_expr(before).format() == after before = """\ -(# Comment. - # - # x. - # y. +(// Comment. + // + // x. + // y. a + b)""" after = """\ -( # Comment. - # - # x. - # y. +( // Comment. + // + // x. + // y. a + b)""" assert parse_expr(before).format() == after def test_format_func_call_notes(): before = """\ -foo(x = 12 # Comment. -)""" +foo(x = 12 // Comment. +);""" with pytest.raises(FormattingError, match="Comments inside expressions are not supported"): parse_code_element(before).format(allowed_line_length=100) @@ -129,103 +129,108 @@ def test_negative_numbers(): def test_file_format(): before = """ -ap+=[ fp ] +ap+=[ fp ] ; %lang starknet -[ap + -1] = [fp] * 3 +[ap + -1] = [fp] * 3; const x=y + f(a=g( - z) ,# test - b=0) - member x:T.S - let x= ap-y + z - let y:a.b.c= x + z) ,// test + b=0); + struct A{ + + x:T.S , + } + let x= ap-y + z; + let y:a.b.c= x; label : -[ap] = [fp]; ap ++ -tempvar x=y*z+w -tempvar q : felt - alloc_locals -local z :T*=x -assert x*z+x= y+y -static_assert ap + (3 + 7 )+ ap ==fp -let()=foo() +[ap] = [fp], ap ++; +tempvar x=y*z+w; +tempvar q : felt; + alloc_locals; +local z :T*=x; +assert x*z+x= y+y; +static_assert ap + (3 + 7 )+ ap ==fp; +let()=foo(); return (1,[fp], - [ap +3],) - fibonacci (a = 3 , b=[fp +1]) -[ap - 1] = [fp]# This is a comment. - #This is another comment. + [ap +3],); + fibonacci (a = 3 , b=[fp +1]); +[ap - 1] = [fp];// This is a comment. + //This is another comment. label2: - jmp rel 17 if [ap+3]!= 0 -[fp] = [fp] * [fp] -with_attr no_value_attribute: -[ap] = [fp]; ap++ -end + jmp rel 17 if [ap+3]!= 0; +[fp] = [fp] * [fp]; +with_attr no_value_attribute { +[ap] = [fp], ap++; +} with_attr single_line_attribute ( "A single line value" - ) : - [ap] = [fp]; ap++ -end + ) { + [ap] = [fp], ap++; +} with_attr long_value_attribute( - "A single line with_attr expression that is too long and does not fit into a single line"): - [ap] = [fp]; ap++ -end + "A single line with_attr expression that is too long and does not fit into a single line") { + [ap] = [fp], ap++; +} with_attr error_message ( "Attribute value " "with" " multiple" "\\n" -"lines" ) : - [ap] = [fp]; ap++ -end""" +"lines" ) { + [ap] = [fp], ap++; +}""" after = """\ -ap += [fp] +ap += [fp]; %lang starknet -[ap + (-1)] = [fp] * 3 +[ap + (-1)] = [fp] * 3; const x = y + f(a=g( - z), # test - b=0) -member x : T.S -let x = ap - y + z -let y : a.b.c = x + z), // test + b=0); +struct A { + x: T.S, +} +let x = ap - y + z; +let y: a.b.c = x; label: -[ap] = [fp]; ap++ -tempvar x = y * z + w -tempvar q : felt -alloc_locals -local z : T* = x -assert x * z + x = y + y -static_assert ap + (3 + 7) + ap == fp -let () = foo() -return (1, [fp], [ap + 3]) -fibonacci(a=3, b=[fp + 1]) -[ap - 1] = [fp] # This is a comment. - -# This is another comment. +[ap] = [fp], ap++; +tempvar x = y * z + w; +tempvar q: felt; +alloc_locals; +local z: T* = x; +assert x * z + x = y + y; +static_assert ap + (3 + 7) + ap == fp; +let () = foo(); +return (1, [fp], [ap + 3],); +fibonacci(a=3, b=[fp + 1]); +[ap - 1] = [fp]; // This is a comment. + +// This is another comment. label2: -jmp rel 17 if [ap + 3] != 0 -[fp] = [fp] * [fp] -with_attr no_value_attribute: - [ap] = [fp]; ap++ -end -with_attr single_line_attribute("A single line value"): - [ap] = [fp]; ap++ -end +jmp rel 17 if [ap + 3] != 0; +[fp] = [fp] * [fp]; +with_attr no_value_attribute { + [ap] = [fp], ap++; +} +with_attr single_line_attribute("A single line value") { + [ap] = [fp], ap++; +} with_attr long_value_attribute( - "A single line with_attr expression that is too long and does not fit into a single line"): - [ap] = [fp]; ap++ -end + "A single line with_attr expression that is too long and does not fit into a single line") { + [ap] = [fp], ap++; +} with_attr error_message( "Attribute value " "with" " multiple" "\\n" - "lines"): - [ap] = [fp]; ap++ -end + "lines") { + [ap] = [fp], ap++; +} """ assert parse_file(before).format() == after @@ -233,83 +238,83 @@ def test_file_format(): def test_file_format_comments(): before = """ -# First line. -[ap] = [ap] +// First line. +[ap] = [ap]; -# Separator comment. +// Separator comment. -[ap] = [ap] -[ap] = [ap] +[ap] = [ap]; +[ap] = [ap]; -# Comment before label. +// Comment before label. label : -[ap] = [ap] # Inline. - #This is another - # comment before label. -label2:#Inline (label). +[ap] = [ap]; // Inline. + //This is another + // comment before label. +label2://Inline (label). -[ap] = [ap] +[ap] = [ap]; label3: -[ap] = [ap] -# End of file comment.""" +[ap] = [ap]; +// End of file comment.""" after = """\ -# First line. -[ap] = [ap] +// First line. +[ap] = [ap]; -# Separator comment. +// Separator comment. -[ap] = [ap] -[ap] = [ap] +[ap] = [ap]; +[ap] = [ap]; -# Comment before label. +// Comment before label. label: -[ap] = [ap] # Inline. +[ap] = [ap]; // Inline. -# This is another -# comment before label. -label2: # Inline (label). -[ap] = [ap] +// This is another +// comment before label. +label2: // Inline (label). +[ap] = [ap]; label3: -[ap] = [ap] -# End of file comment. +[ap] = [ap]; +// End of file comment. """ assert parse_file(before).format() == after def test_file_format_comment_spaces(): before = """ -# First line. -#{spaces} -# Second line.{spaces} -#Fourth line. -# Third line. -[ap] = [ap] # inline comment. -# First line. -# Second line. - -# First line. -# Second line. -[ap] = [ap] #{spaces} +// First line. +//{spaces} +// Second line.{spaces} +//Fourth line. +// Third line. +[ap] = [ap]; // inline comment. +// First line. +// Second line. + +// First line. +// Second line. +[ap] = [ap]; //{spaces} """.format( spaces=" " ) after = """\ -# First line. -# -# Second line. -# Fourth line. -# Third line. -[ap] = [ap] # inline comment. -# First line. -# Second line. - -# First line. -# Second line. -[ap] = [ap] # +// First line. +// +// Second line. +// Fourth line. +// Third line. +[ap] = [ap]; // inline comment. +// First line. +// Second line. + +// First line. +// Second line. +[ap] = [ap]; // """ assert parse_file(before).format() == after @@ -320,20 +325,20 @@ def test_file_format_hint(): %{ x = y "[ fp ]"#Python comment is not auto-formatted - %}#Cairo Comment + %}//Cairo Comment %{ - %} # Empty hint. + %} // Empty hint. """ after = """\ label: %{ x = y "[ fp ]"#Python comment is not auto-formatted -%} # Cairo Comment +%} // Cairo Comment %{ -%} # Empty hint. +%} // Empty hint. """ assert parse_file(before).format() == after @@ -344,96 +349,99 @@ def test_file_format_hints_indent(): hint1 hint2 %} -[fp] = [fp] -func f(): +[fp] = [fp]; +func f() { %{ if a: b %} -[fp] = [fp] -end +[fp] = [fp]; +} """ after = """\ %{ hint1 hint2 %} -[fp] = [fp] -func f(): +[fp] = [fp]; +func f() { %{ if a: b %} - [fp] = [fp] -end + [fp] = [fp]; +} """ assert parse_file(before).format() == after def test_parse_struct(): before = """\ -struct MyStruct: -x = 5 - y=3 - end # Comment. +struct MyStruct{ +x,// Comment1. + + + y : felt** , + } // Comment2. """ after = """\ -struct MyStruct: - x = 5 - y = 3 -end # Comment. +struct MyStruct { + x, // Comment1. + + y: felt**, +} // Comment2. """ assert parse_file(before).format() == after def test_parse_namespace(): before = """\ -namespace MyNamespace: -x = 5 - y=3 - end # Comment. +namespace MyNamespace { +x = 5; + y=3; + } // Comment. -namespace MyNamespace2: - end +namespace MyNamespace2 { + } """ after = """\ -namespace MyNamespace: - x = 5 - y = 3 -end # Comment. +namespace MyNamespace { + x = 5; + y = 3; +} // Comment. -namespace MyNamespace2: -end +namespace MyNamespace2 { +} """ assert parse_file(before).format() == after def test_parse_func(): before = """\ -[ap] = 1; ap++ +[ap] = 1, ap++; -func fib(): +func fib() { - [ap] = 2; ap++ - ap += 3 - ret + [ap] = 2, ap++; + ap += 3; + ret; - end # Comment. + } // Comment. - call fib + call fib; """ after = """\ -[ap] = 1; ap++ +[ap] = 1, ap++; -func fib(): - [ap] = 2; ap++ - ap += 3 - ret -end # Comment. +func fib() { + [ap] = 2, ap++; + ap += 3; + ret; +} // Comment. -call fib +call fib; """ assert parse_file(before).format() == after @@ -441,9 +449,9 @@ def test_parse_func(): def test_func_arg_splitting(): before = """\ func myfunc{x, y, z, w, foo_bar}(a, b, c, foo, bar, - variable_name_which_is_way_too_long_but_has_to_be_supported, g): - ret -end + variable_name_which_is_way_too_long_but_has_to_be_supported, g) { + ret; +} """ after = """\ func myfunc{ @@ -452,9 +460,9 @@ def test_func_arg_splitting(): a, b, c, foo, bar, variable_name_which_is_way_too_long_but_has_to_be_supported, - g): - ret -end + g) { + ret; +} """ with set_one_item_per_line(False): assert parse_file(before).format(allowed_line_length=25) == after @@ -463,7 +471,7 @@ def test_func_arg_splitting(): def test_return_splitting(): before = """\ return (a, b, c, foo, bar, - variable_name_which_is_way_too_long_but_has_to_be_supported, g) + variable_name_which_is_way_too_long_but_has_to_be_supported, g); """ after = """\ return ( @@ -473,7 +481,7 @@ def test_return_splitting(): foo, bar, variable_name_which_is_way_too_long_but_has_to_be_supported, - g) + g); """ with set_one_item_per_line(False): assert parse_file(before).format(allowed_line_length=20) == after @@ -483,9 +491,9 @@ def test_func_arg_ret_splitting(): before = """\ func myfunc(a, b, c, foo, bar, variable_name_which_is_way_too_long_but_has_to_be_supported, g) - -> (x, y, z, a_return_arg_which_is_also_waaaaaaay_too_long, w): - ret -end + -> (x, y, z, a_return_arg_which_is_also_waaaaaaay_too_long, w) { + ret; +} """ after = """\ func myfunc( @@ -495,43 +503,43 @@ def test_func_arg_ret_splitting(): g) -> ( x, y, z, a_return_arg_which_is_also_waaaaaaay_too_long, - w): - ret -end + w) { + ret; +} """ with set_one_item_per_line(False): assert parse_file(before).format(allowed_line_length=25) == after before = """\ func myfunc(a, b, c, foo, bar, variable_name_which_is_way_too_long_but_has_to_be_supported, g) -> - (x, y, z): - ret -end + (x, y, z) { + ret; +} """ after = """\ func myfunc( a, b, c, foo, bar, variable_name_which_is_way_too_long_but_has_to_be_supported, - g) -> (x, y, z): - ret -end + g) -> (x, y, z) { + ret; +} """ with set_one_item_per_line(False): assert parse_file(before).format(allowed_line_length=25) == after before = """\ -func myfunc(ab, cd, ef) -> (x, y, z, a_return_arg_which_is_also_waaaaaaay_too_long, w): - ret -end +func myfunc(ab, cd, ef) -> (x, y, z, a_return_arg_which_is_also_waaaaaaay_too_long, w) { + ret; +} """ after = """\ func myfunc( ab, cd, ef) -> ( x, y, z, a_return_arg_which_is_also_waaaaaaay_too_long, - w): - ret -end + w) { + ret; +} """ with set_one_item_per_line(False): assert parse_file(before).format(allowed_line_length=25) == after @@ -539,31 +547,31 @@ def test_func_arg_ret_splitting(): def test_func_one_per_line_splitting(): before = """\ -func myfunc{x, y}(a, b): - ret -end +func myfunc{x, y}(a, b) { + ret; +} """ with set_one_item_per_line(True): assert parse_file(before).format(allowed_line_length=25) == before before = """\ -func myfunc{x: felt*, y: felt*}(a, b, c, d): - ret -end +func myfunc{x: felt*, y: felt*}(a, b, c, d) { + ret; +} """ after = """\ func myfunc{ - x : felt*, y : felt* -}(a, b, c, d): - ret -end + x: felt*, y: felt* +}(a, b, c, d) { + ret; +} """ with set_one_item_per_line(True): assert parse_file(before).format(allowed_line_length=25) == after before = """\ func myfunc{long_imp_arg1, long_imp_arg2,long_imp_arg3}( - very_long_arg1, very_long_arg2): - ret -end + very_long_arg1, very_long_arg2) { + ret; +} """ after = """\ func myfunc{ @@ -573,32 +581,32 @@ def test_func_one_per_line_splitting(): }( very_long_arg1, very_long_arg2, -): - ret -end +) { + ret; +} """ with set_one_item_per_line(True): assert parse_file(before).format(allowed_line_length=25) == after before = """\ -func myfunc{}(a, variable_name_which_is_way_too_long_but_has_to_be_supported): - ret -end +func myfunc{}(a, variable_name_which_is_way_too_long_but_has_to_be_supported) { + ret; +} """ after = """\ func myfunc{}( a, variable_name_which_is_way_too_long_but_has_to_be_supported, -): - ret -end +) { + ret; +} """ with set_one_item_per_line(True): assert parse_file(before).format(allowed_line_length=25) == after before = """\ func myfunc(ab, cd, ef) -> ( - long_return_arg1, long_return_arg2): - ret -end + long_return_arg1, long_return_arg2) { + ret; +} """ after = """\ func myfunc( @@ -606,9 +614,9 @@ def test_func_one_per_line_splitting(): ) -> ( long_return_arg1, long_return_arg2, -): - ret -end +) { + ret; +} """ with set_one_item_per_line(True): assert parse_file(before).format(allowed_line_length=25) == after @@ -617,7 +625,7 @@ def test_func_one_per_line_splitting(): def test_return_one_per_line_splitting(): before = """\ return (a, b, c, foo, bar, - variable_name_which_is_way_too_long_but_has_to_be_supported, g) + variable_name_which_is_way_too_long_but_has_to_be_supported, g); """ after = """\ return ( @@ -628,7 +636,7 @@ def test_return_one_per_line_splitting(): bar, variable_name_which_is_way_too_long_but_has_to_be_supported, g, -) +); """ with set_one_item_per_line(True): assert parse_file(before).format(allowed_line_length=25) == after @@ -636,26 +644,26 @@ def test_return_one_per_line_splitting(): def test_func_call_one_per_line_splitting(): before = """\ -let (a, b, c) = foo(long_arg1, long_arg2, long_arg3) +let (a, b, c) = foo(long_arg1, long_arg2, long_arg3); """ after = """\ let (a, b, c) = foo( long_arg1, long_arg2, long_arg3, -) +); """ with set_one_item_per_line(True): assert parse_file(before).format(allowed_line_length=25) == after before = """\ -return foo(long_arg1, long_arg2, long_arg3) +return foo(long_arg1, long_arg2, long_arg3); """ after = """\ return foo( long_arg1, long_arg2, long_arg3, -) +); """ with set_one_item_per_line(True): assert parse_file(before).format(allowed_line_length=25) == after @@ -679,45 +687,45 @@ def test_import_one_per_line_splitting(): def test_directives(): code = """\ -[ap] = [ap] -# Comment. -%builtins ab cd ef # Comment. +[ap] = [ap]; +// Comment. +%builtins ab cd ef // Comment. -[fp] = [fp] +[fp] = [fp]; """ assert parse_file(code).format() == code def test_if(): code = """\ -if (a + 1) / b == [fp]: - [ap] = [ap] -end +if ((a + 1) / b == [fp]) { + [ap] = [ap]; +} """ assert parse_file(code).format() == code code = """\ -if (a + 1) / b != 5: - [ap] = [ap] -else: - [ap] = [ap] -end +if ((a + 1) / b != 5) { + [ap] = [ap]; +} else { + [ap] = [ap]; +} """ assert parse_file(code).format() == code def test_with(): code = """\ -with a , b as c,d : - [ap] = [ap] -end +with a , b as c,d { + [ap] = [ap]; + } """ assert ( parse_file(code).format() == """\ -with a, b as c, d: - [ap] = [ap] -end +with a, b as c, d { + [ap] = [ap]; +} """ ) @@ -725,10 +733,10 @@ def test_with(): def test_with_attr(): code = """\ with_attr attribute_name ("Comments" - # within attribute value - " are not supported") : - [ap] = [fp]; ap++ -end""" + // within attribute value + " are not supported") { + [ap] = [fp], ap++; +}""" with pytest.raises(FormattingError, match="Comments inside expressions are not supported"): parse_code_element(code).format(allowed_line_length=100) @@ -745,35 +753,37 @@ def test_100_chars_long_import(): def test_tuples(): code = """\ -local x : ( - a : felt, - b : (c : felt, - d : (felt, (felt, felt)), - e : (f : felt, g : felt), - h : (felt, felt, felt))) +local x: ( + a: felt, + b: (c: felt, + d: felt, + e: (felt, (felt, felt)), + f: (g: felt, h: felt), + i: (felt, felt, felt))); """ with set_one_item_per_line(True): assert ( parse_file(code).format() == """\ -local x : ( - a : felt, - b : (c : felt, d : (felt, (felt, felt)), e : (f : felt, g : felt), h : (felt, felt, felt)), -) +local x: ( + a: felt, + b: (c: felt, d: felt, e: (felt, (felt, felt)), f: (g: felt, h: felt), i: (felt, felt, felt)), +); """ ) assert ( parse_file(code).format(allowed_line_length=50) == """\ -local x : ( - a : felt, - b : ( - c : felt, - d : (felt, (felt, felt)), - e : (f : felt, g : felt), - h : (felt, felt, felt), +local x: ( + a: felt, + b: ( + c: felt, + d: felt, + e: (felt, (felt, felt)), + f: (g: felt, h: felt), + i: (felt, felt, felt), ), -) +); """ ) diff --git a/src/starkware/cairo/lang/compiler/cairo.ebnf b/src/starkware/cairo/lang/compiler/cairo.ebnf index b39b28d1..ce3d1d29 100644 --- a/src/starkware/cairo/lang/compiler/cairo.ebnf +++ b/src/starkware/cairo/lang/compiler/cairo.ebnf @@ -100,7 +100,7 @@ call_instruction: "call" "rel" expr -> inst_call_rel | "ap" "+=" expr -> inst_add_ap | "dw" expr -> inst_data_word instruction: instruction_body -> instruction_noap - | instruction_body ";" "ap" _DBL_PLUS -> instruction_ap + | instruction_body "," "ap" _DBL_PLUS -> instruction_ap function_call: identifier ("{" arg_list "}")? "(" arg_list ")" @@ -123,53 +123,59 @@ _import_body: aliased_identifier ("," aliased_identifier)* _import: "from" identifier "import" _import_body // Function/Namespace/Struct definition. -_returns: _ARROW _NEWLINE* "(" identifier_list ")" +_returns: _ARROW _NEWLINE* type _arguments: "(" identifier_list ")" implicit_arguments: ("{" identifier_list "}")? -_funcdecl: "func" identifier_def implicit_arguments _arguments _NEWLINE* _returns? ":" -_func: decorator_list _funcdecl _NEWLINE code_block "end" -_if: "if" bool_expr ":" _NEWLINE code_block ("else" ":" _NEWLINE code_block)? "end" +_funcdecl: "func" identifier_def implicit_arguments _arguments _NEWLINE* _returns? "{" +_func: decorator_list _funcdecl _NEWLINE code_block "}" +_if: "if" "(" bool_expr ")" "{" _NEWLINE code_block ("}" "else" "{" _NEWLINE code_block)? "}" -!_some_namespace: "struct" | "namespace" -_struct: decorator_list _some_namespace identifier_def ":"_NEWLINE code_block "end" +_struct: decorator_list "struct" identifier_def "{" _NEWLINE struct_code_block "}" +_namespace: decorator_list "namespace" identifier_def "{" _NEWLINE code_block "}" -_with_statement: "with" (aliased_identifier ",")* aliased_identifier ":" _NEWLINE code_block "end" +_with_statement: "with" (aliased_identifier ",")* aliased_identifier "{" _NEWLINE code_block "}" _attr_val: "(" notes (STRING notes)* ")" -_with_attr_statement: "with_attr" identifier_def _attr_val? ":" _NEWLINE code_block "end" +_with_attr_statement: "with_attr" identifier_def _attr_val? "{" _NEWLINE code_block "}" // Cairo file. _NEWLINE: "\n" -COMMENT: /#.*/ +COMMENT: /\/\/.*/ // Note: code_element_label is using identifier instead of identifier_def, in order to make the // parser LALR-friendly. -code_element: instruction -> code_element_instruction - | "const" identifier_def "=" expr -> code_element_const - | "member" typed_identifier -> code_element_member - | "let" _ref_binding "=" rvalue -> code_element_reference - | "local" typed_identifier ("=" expr)? -> code_element_local_var - | "tempvar" typed_identifier ("=" expr)? -> code_element_temp_var - | "assert" expr "=" expr -> code_element_compound_assert_eq - | "static_assert" expr _DBL_EQ expr -> code_element_static_assert - | "return" "(" arg_list ")" -> code_element_return - | "return" function_call -> code_element_tail_call +code_element: instruction ";" -> code_element_instruction + | "const" identifier_def "=" expr ";" -> code_element_const + | "let" _ref_binding "=" rvalue ";" -> code_element_reference + | "local" typed_identifier ("=" expr)? ";" -> code_element_local_var + | "tempvar" typed_identifier ("=" expr)? ";" -> code_element_temp_var + | "assert" expr "=" expr ";" -> code_element_compound_assert_eq + | "static_assert" expr _DBL_EQ expr ";" -> code_element_static_assert + | "return" expr ";" -> code_element_return | _if -> code_element_if - | function_call -> code_element_func_call + | function_call ";" -> code_element_func_call | identifier ":" -> code_element_label | _func -> code_element_function | _struct -> code_element_struct - | "using" identifier_def "=" type -> code_element_typedef + | _namespace -> code_element_namespace + | "using" identifier_def "=" type ";" -> code_element_typedef | _with_attr_statement -> code_element_with_attr | _with_statement -> code_element_with | HINT -> code_element_hint | directive -> code_element_directive | _import -> code_element_import - | "alloc_locals" -> code_element_alloc_locals + | "alloc_locals" ";" -> code_element_alloc_locals | -> code_element_empty_line commented_code_element: code_element [COMMENT] code_block: (commented_code_element _NEWLINE)* +// A version of code_block for structs. This allows any combination of empty lines, comments and +// struct members. +struct_code_element: typed_identifier "," -> code_element_member + | -> code_element_empty_line +struct_commented_code_element: struct_code_element [COMMENT] -> commented_code_element +struct_code_block: (struct_commented_code_element _NEWLINE)* -> code_block + cairo_file: code_block // Notes (comments inside parentheses). diff --git a/src/starkware/cairo/lang/compiler/cairo_compile.py b/src/starkware/cairo/lang/compiler/cairo_compile.py index ff2ba89a..17934633 100644 --- a/src/starkware/cairo/lang/compiler/cairo_compile.py +++ b/src/starkware/cairo/lang/compiler/cairo_compile.py @@ -57,7 +57,7 @@ def cairo_compile_add_common_args(parser: argparse.ArgumentParser): "--no_debug_info", dest="debug_info", action="store_false", - help="Include debug information.", + help="Don't include debug information in the compiled file.", ) parser.add_argument( "--debug_info_with_source", @@ -139,6 +139,7 @@ def cairo_compile_common( ) # Print a new line at the end. print(file=out) + out.flush() return preprocessed finally: @@ -312,7 +313,7 @@ def check_main_args(program: Program): assert isinstance(return_type_def.cairo_type, TypeTuple) member_names = [] for member in return_type_def.cairo_type.members: - assert member.name is not None, "Unexpected unnamed return value." + assert member.name is not None, "The return values of main() must be named." member_names.append(member.name) main_returns = implicit_args + member_names except IdentifierError: @@ -331,11 +332,11 @@ def get_start_code(): """ return """\ __start__: -ap += main.Args.SIZE + main.ImplicitArgs.SIZE -call main +ap += main.Args.SIZE + main.ImplicitArgs.SIZE; +call main; __end__: -jmp rel 0 +jmp rel 0; """ diff --git a/src/starkware/cairo/lang/compiler/cairo_compile_test.py b/src/starkware/cairo/lang/compiler/cairo_compile_test.py index 925756a4..81abde46 100644 --- a/src/starkware/cairo/lang/compiler/cairo_compile_test.py +++ b/src/starkware/cairo/lang/compiler/cairo_compile_test.py @@ -21,9 +21,9 @@ def test_main_args_match_builtins(): code=""" %builtins output range_check -func main(output_ptr : felt*) -> (output_ptr : felt*): - return (output_ptr=output_ptr + 1) -end +func main(output_ptr: felt*) -> (output_ptr: felt*) { + return (output_ptr=output_ptr + 1); +} """, prime=PRIME, ) @@ -35,10 +35,11 @@ def test_main_args_match_builtins(): code=""" %builtins output range_check -func main(range_check_ptr : felt*, output_ptr : felt*) -> ( - range_check_ptr : felt*, output_ptr : felt*): - return (range_check_ptr=range_check_ptr + 1, output_ptr=output_ptr + 1) -end +func main(range_check_ptr: felt*, output_ptr: felt*) -> ( + range_check_ptr: felt*, output_ptr: felt* +) { + return (range_check_ptr=range_check_ptr + 1, output_ptr=output_ptr + 1); +} """, prime=PRIME, ) @@ -58,9 +59,24 @@ def test_main_return_match_builtins(): code=""" %builtins output range_check -func main(output_ptr : felt*, range_check_ptr : felt*) -> (output_ptr : felt*): - return (output_ptr=output_ptr + 1) -end +func main(output_ptr: felt*, range_check_ptr: felt*) -> (output_ptr: felt*) { + return (output_ptr=output_ptr + 1); +} +""", + prime=PRIME, + ) + + +def test_main_unnamed_return(): + expected_error_msg = "The return values of main() must be named." + with pytest.raises(AssertionError, match=re.escape(expected_error_msg)): + compile_cairo( + code=""" +%builtins output range_check + +func main(output_ptr: felt*, range_check_ptr: felt*) -> (felt*,) { + ret; +} """, prime=PRIME, ) diff --git a/src/starkware/cairo/lang/compiler/cairo_format.py b/src/starkware/cairo/lang/compiler/cairo_format.py index df9d2dff..89128e3e 100644 --- a/src/starkware/cairo/lang/compiler/cairo_format.py +++ b/src/starkware/cairo/lang/compiler/cairo_format.py @@ -1,18 +1,20 @@ import argparse import sys -from typing import Callable +from typing import Callable, Optional from starkware.cairo.lang.compiler.ast.formatting_utils import set_one_item_per_line from starkware.cairo.lang.compiler.ast.module import CairoFile from starkware.cairo.lang.compiler.parser import parse_file from starkware.cairo.lang.version import __version__ +ParserCallback = Callable[[str, str], CairoFile] -def cairo_format_common(cairo_parser: Callable[[str, str], CairoFile], description: str): - parser = argparse.ArgumentParser(description=description) - parser.add_argument("-v", "--version", action="version", version=f"%(prog)s {__version__}") - parser.add_argument("files", metavar="file", type=str, nargs="+", help="File names") - parser.add_argument( + +def cairo_format_arg_parser(description: str) -> argparse.ArgumentParser: + arg_parser = argparse.ArgumentParser(description=description) + arg_parser.add_argument("-v", "--version", action="version", version=f"%(prog)s {__version__}") + arg_parser.add_argument("files", metavar="file", type=str, nargs="+", help="File names") + arg_parser.add_argument( "--one_item_per_line", action="store_true", default=True, @@ -21,18 +23,24 @@ def cairo_format_common(cairo_parser: Callable[[str, str], CairoFile], descripti "if the list doesn't fit into a single line." ), ) - parser.add_argument( + arg_parser.add_argument( "--no_one_item_per_line", dest="one_item_per_line", action="store_false", help="Don't use one per line formatting (see --one_item_per_line).", ) - action = parser.add_mutually_exclusive_group(required=False) + action = arg_parser.add_mutually_exclusive_group(required=False) action.add_argument("-i", dest="inplace", action="store_true", help="Edit files inplace.") action.add_argument("-c", dest="check", action="store_true", help="Check files' formats.") - args = parser.parse_args() + return arg_parser + +def cairo_format_common( + args: argparse.Namespace, + cairo_parser: ParserCallback, + validate_parser: Optional[ParserCallback] = None, +): return_code = 0 with set_one_item_per_line(args.one_item_per_line): @@ -44,7 +52,18 @@ def cairo_format_common(cairo_parser: Callable[[str, str], CairoFile], descripti old_content = open(path).read() filename = path try: - new_content = cairo_parser(old_content, filename).format() + ast = cairo_parser(old_content, filename) + new_content = ast.format() + + if validate_parser is not None: + # If validate_parser is given, re-parse the result and make sure it returns + # the same AST. + validated_content = validate_parser(new_content, filename).format() + assert new_content == validated_content, ( + "Error: Formatting validation failed.\n" + f"Before validation:\n{new_content}\n\n\n" + f"After validation:\n{validated_content}" + ) except Exception as exc: print(exc, file=sys.stderr) return 2 @@ -64,11 +83,10 @@ def cairo_format_common(cairo_parser: Callable[[str, str], CairoFile], descripti def main(): - cairo_parser = lambda code, filename: parse_file(code=code, filename=filename) + arg_parser = cairo_format_arg_parser(description="A tool to automatically format Cairo code.") + args = arg_parser.parse_args() - return cairo_format_common( - cairo_parser=cairo_parser, description="A tool to automatically format Cairo code." - ) + return cairo_format_common(args=args, cairo_parser=parse_file) if __name__ == "__main__": diff --git a/src/starkware/cairo/lang/compiler/debug_info.py b/src/starkware/cairo/lang/compiler/debug_info.py index 9983eb90..d7456a19 100644 --- a/src/starkware/cairo/lang/compiler/debug_info.py +++ b/src/starkware/cairo/lang/compiler/debug_info.py @@ -8,6 +8,7 @@ from starkware.cairo.lang.compiler.error_handling import Location from starkware.cairo.lang.compiler.preprocessor.flow import FlowTrackingDataActual from starkware.cairo.lang.compiler.scoped_name import ScopedName, ScopedNameAsStr +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass @@ -23,7 +24,7 @@ class InstructionLocation: inst: Location hints: List[Optional[HintLocation]] accessible_scopes: List[ScopedName] = field( - metadata=dict(marshmallow_field=mfields.List(ScopedNameAsStr)) + metadata=additional_metadata(marshmallow_field=mfields.List(ScopedNameAsStr)) ) # flow_tracking_data may be removed when filtering unnecessary identifiers is enabled. diff --git a/src/starkware/cairo/lang/compiler/encode_test.py b/src/starkware/cairo/lang/compiler/encode_test.py index f1791f4b..ea4608a7 100644 --- a/src/starkware/cairo/lang/compiler/encode_test.py +++ b/src/starkware/cairo/lang/compiler/encode_test.py @@ -32,7 +32,7 @@ def test_assert_eq(): fp_update=Instruction.FpUpdate.REGULAR, opcode=Instruction.Opcode.ASSERT_EQ, ) - assert build_instruction(parse_instruction("[ap] = 1; ap++")) == instruction + assert build_instruction(parse_instruction("[ap] = 1, ap++")) == instruction assert encode_instruction(instruction, prime=PRIME) == encoded assert decode_instruction(*encoded) == instruction diff --git a/src/starkware/cairo/lang/compiler/filter_unused_identifiers_test.py b/src/starkware/cairo/lang/compiler/filter_unused_identifiers_test.py index e157816f..a4716662 100644 --- a/src/starkware/cairo/lang/compiler/filter_unused_identifiers_test.py +++ b/src/starkware/cairo/lang/compiler/filter_unused_identifiers_test.py @@ -23,21 +23,21 @@ def test_filter_unused_identifiers(): program = compile_cairo( code=""" -func main(): - alloc_locals - local a - local b +func main() { + alloc_locals; + local a; + local b; - local x - tempvar x + local x; + tempvar x; %{ ids.x = 5 %} - tempvar y + tempvar y; - with_attr error_message("Error. b={b}"): - [ap] = 1 - end - return () -end + with_attr error_message("Error. b={b}") { + [ap] = 1; + } + return (); +} """, prime=PRIME, ) diff --git a/src/starkware/cairo/lang/compiler/identifier_definition.py b/src/starkware/cairo/lang/compiler/identifier_definition.py index bc51d2ac..f52688b3 100644 --- a/src/starkware/cairo/lang/compiler/identifier_definition.py +++ b/src/starkware/cairo/lang/compiler/identifier_definition.py @@ -1,7 +1,7 @@ import dataclasses from abc import ABC, abstractmethod from dataclasses import field -from typing import ClassVar, Dict, List, Optional, Type +from typing import ClassVar, Dict, List, Optional, Type, TypeVar import marshmallow import marshmallow_dataclass @@ -15,6 +15,9 @@ from starkware.cairo.lang.compiler.preprocessor.flow import FlowTrackingData, ReferenceManager from starkware.cairo.lang.compiler.references import Reference from starkware.cairo.lang.compiler.scoped_name import ScopedName, ScopedNameAsStr +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata + +TIdentifierDefinition = TypeVar("TIdentifierDefinition", bound="IdentifierDefinition") class DefinitionError(Exception): @@ -43,7 +46,9 @@ class AliasDefinition(IdentifierDefinition): TYPE: ClassVar[str] = "alias" Schema: ClassVar[Type[marshmallow.Schema]] = marshmallow.Schema - destination: ScopedName = field(metadata=dict(marshmallow_field=ScopedNameAsStr())) + destination: ScopedName = field( + metadata=additional_metadata(marshmallow_field=ScopedNameAsStr()) + ) @marshmallow_dataclass.dataclass @@ -60,7 +65,9 @@ class MemberDefinition(IdentifierDefinition): Schema: ClassVar[Type[marshmallow.Schema]] = marshmallow.Schema offset: int - cairo_type: CairoType = field(metadata=dict(marshmallow_field=CairoTypeAsStr(required=True))) + cairo_type: CairoType = field( + metadata=additional_metadata(marshmallow_field=CairoTypeAsStr(required=True)) + ) location: Optional[Location] = LocationField @@ -70,15 +77,15 @@ class StructDefinition(IdentifierDefinition): """ Represents a struct definition. - struct MyStruct: + struct MyStruct { ... - end + } """ TYPE: ClassVar[str] = "struct" Schema: ClassVar[Type[marshmallow.Schema]] = marshmallow.Schema - full_name: ScopedName = field(metadata=dict(marshmallow_field=ScopedNameAsStr())) + full_name: ScopedName = field(metadata=additional_metadata(marshmallow_field=ScopedNameAsStr())) # members sorted by member offset, note the sort_members post_load function. members: Dict[str, MemberDefinition] @@ -105,7 +112,9 @@ class TypeDefinition(IdentifierDefinition): TYPE: ClassVar[str] = "type_definition" Schema: ClassVar[Type[marshmallow.Schema]] = marshmallow.Schema - cairo_type: CairoType = field(metadata=dict(marshmallow_field=CairoTypeAsStr(required=True))) + cairo_type: CairoType = field( + metadata=additional_metadata(marshmallow_field=CairoTypeAsStr(required=True)) + ) location: Optional[Location] = LocationField @@ -136,8 +145,10 @@ class ReferenceDefinition(IdentifierDefinition): TYPE: ClassVar[str] = "reference" Schema: ClassVar[Type[marshmallow.Schema]] = marshmallow.Schema - full_name: ScopedName = field(metadata=dict(marshmallow_field=ScopedNameAsStr())) - cairo_type: CairoType = field(metadata=dict(marshmallow_field=CairoTypeAsStr(required=True))) + full_name: ScopedName = field(metadata=additional_metadata(marshmallow_field=ScopedNameAsStr())) + cairo_type: CairoType = field( + metadata=additional_metadata(marshmallow_field=CairoTypeAsStr(required=True)) + ) references: List[Reference] def eval( diff --git a/src/starkware/cairo/lang/compiler/identifier_manager_field_test.py b/src/starkware/cairo/lang/compiler/identifier_manager_field_test.py index bc103cf2..9cefc87b 100644 --- a/src/starkware/cairo/lang/compiler/identifier_manager_field_test.py +++ b/src/starkware/cairo/lang/compiler/identifier_manager_field_test.py @@ -6,6 +6,7 @@ from starkware.cairo.lang.compiler.identifier_manager import IdentifierManager from starkware.cairo.lang.compiler.identifier_manager_field import IdentifierManagerField from starkware.cairo.lang.compiler.scoped_name import ScopedName +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata scope = ScopedName.from_string @@ -14,7 +15,7 @@ def test_identifier_manager_field_serialization(): @marshmallow_dataclass.dataclass class Foo: identifiers: IdentifierManager = field( - metadata=dict(marshmallow_field=IdentifierManagerField()) + metadata=additional_metadata(marshmallow_field=IdentifierManagerField()) ) Schema = marshmallow_dataclass.class_schema(Foo) diff --git a/src/starkware/cairo/lang/compiler/import_loader_test.py b/src/starkware/cairo/lang/compiler/import_loader_test.py index c842fb8e..6d76bd1e 100644 --- a/src/starkware/cairo/lang/compiler/import_loader_test.py +++ b/src/starkware/cairo/lang/compiler/import_loader_test.py @@ -18,16 +18,16 @@ def test_get_imports(): code = """ from a import b -ap += [fp] + 2; ap++ +ap += [fp] + 2, ap++; from b.c.d.e import f as g my_label: -call that +call that; from vim import ide -# from vs.code import ide -func foo(): - from pytest import cairo_stack_test as ci -end +// from vs.code import ide +func foo() { + from pytest import cairo_stack_test as ci +} """ ast = parse_file(code) collector = DirectDependenciesCollector() @@ -83,8 +83,8 @@ def test_shallow_tree_graph(): from a import aa from b import bb """, - "a": "[ap] = 1", - "b": "[ap] = 2", + "a": "[ap] = 1;", + "b": "[ap] = 2;", } expected_res = {name: parse_file(code) for name, code in files.items()} @@ -94,7 +94,7 @@ def test_shallow_tree_graph(): def test_long_path_grph(): files = {f"a{i}": f"from a{i+1} import b" for i in range(10)} - files["a9"] = "[ap] = 0" + files["a9"] = "[ap] = 0;" expected_res = {name: parse_file(code) for name, code in files.items()} assert collect_imports("a0", read_file_from_dict(files)) == expected_res @@ -114,8 +114,8 @@ def test_dag(): from common.first import some1 from common.second import some2 """, - "common.first": "[ap] = 1", - "common.second": "[ap] = 2", + "common.first": "[ap] = 1;", + "common.second": "[ap] = 2;", } expected_res = {name: parse_file(code) for name, code in files.items()} @@ -210,14 +210,14 @@ def test_lang_directive(): """, "d_lang": """ %lang lang -const x = 0 +const x = 0; """, "d_no_lang": """ -const x = 0 +const x = 0; """, "e": """ -%lang lang # First line. -%lang lang # Second line. +%lang lang // First line. +%lang lang // Second line. """, } @@ -249,7 +249,7 @@ def test_lang_directive(): "e", """ e:?:?: Found two %lang directives -%lang lang # Second line. +%lang lang // Second line. ^********^ """, ) diff --git a/src/starkware/cairo/lang/compiler/injector.py b/src/starkware/cairo/lang/compiler/injector.py index c9aa6c30..a3430328 100644 --- a/src/starkware/cairo/lang/compiler/injector.py +++ b/src/starkware/cairo/lang/compiler/injector.py @@ -9,6 +9,10 @@ from starkware.cairo.lang.compiler.ast.visitor import Visitor +class InjectionError(Exception): + pass + + class InjectVisitor(Visitor): """ A visitor that injects code elements after other code elements, comparing by the python object @@ -53,5 +57,6 @@ def inject_code_elements( """ visitor = InjectVisitor(injections=injections) res = visitor.visit(ast) - assert len(visitor.injections) == 0, f"Some injections were unsuccessful: {visitor.injections}." + if len(visitor.injections) != 0: + raise InjectionError(f"Some injections were unsuccessful: {visitor.injections}.") return res diff --git a/src/starkware/cairo/lang/compiler/injector_test.py b/src/starkware/cairo/lang/compiler/injector_test.py index 73be0f6c..d3f9c9cc 100644 --- a/src/starkware/cairo/lang/compiler/injector_test.py +++ b/src/starkware/cairo/lang/compiler/injector_test.py @@ -13,29 +13,29 @@ def test_injector(): block: CodeBlock = parse( filename="", code="""\ -let (x, local y) = f() -let z = 1 -if 1 != 0: - tempvar z = 0 -end -local x = 1 -func foo(): - tempvar y = 0 -end +let (x, local y) = f(); +let z = 1; +if (1 != 0) { + tempvar z = 0; +} +local x = 1; +func foo() { + tempvar y = 0; +} """, code_type="code_block", expected_type=CodeBlock, ) injected0 = parse( filename="", - code="const a = 0\n", + code="const a = 0;\n", code_type="code_block", expected_type=CodeBlock, ).code_elements[0] injected1 = parse( filename="", - code="const b = 1\n", + code="const b = 1;\n", code_type="code_block", expected_type=CodeBlock, ).code_elements[0] @@ -65,19 +65,19 @@ def test_injector(): assert ( block.format(allowed_line_length=100) == """\ -let (x, local y) = f() -const a = 0 -const b = 1 -let z = 1 -if 1 != 0: - tempvar z = 0 - const b = 1 -end -const a = 0 -local x = 1 -func foo(): - tempvar y = 0 - const a = 0 -end +let (x, local y) = f(); +const a = 0; +const b = 1; +let z = 1; +if (1 != 0) { + tempvar z = 0; + const b = 1; +} +const a = 0; +local x = 1; +func foo() { + tempvar y = 0; + const a = 0; +} """ ) diff --git a/src/starkware/cairo/lang/compiler/instruction_builder_test.py b/src/starkware/cairo/lang/compiler/instruction_builder_test.py index 9038807b..7d1c3ba1 100644 --- a/src/starkware/cairo/lang/compiler/instruction_builder_test.py +++ b/src/starkware/cairo/lang/compiler/instruction_builder_test.py @@ -17,7 +17,7 @@ def parse_and_build(inst: str) -> BytecodeElement: def test_assert_eq(): - assert parse_and_build("[ap] = [fp]; ap++") == Instruction( + assert parse_and_build("[ap] = [fp], ap++") == Instruction( off0=0, off1=-1, off2=0, @@ -63,8 +63,8 @@ def test_assert_eq(): def test_assert_eq_reversed(): assert parse_and_build("5 = [fp + 1]") == parse_and_build("[fp + 1] = 5") - assert parse_and_build("[[ap + 2] + 3] = [fp + 1]; ap++") == parse_and_build( - "[fp + 1] = [[ap + 2] + 3]; ap++" + assert parse_and_build("[[ap + 2] + 3] = [fp + 1], ap++") == parse_and_build( + "[fp + 1] = [[ap + 2] + 3], ap++" ) assert parse_and_build("[ap] + [fp] = [fp + 1]") == parse_and_build("[fp + 1] = [ap] + [fp]") @@ -145,7 +145,7 @@ def test_assert_eq_double_dereference(): fp_update=Instruction.FpUpdate.REGULAR, opcode=Instruction.Opcode.ASSERT_EQ, ) - assert parse_and_build("[ap + 2] = [[ap - 4] + 7]; ap++") == Instruction( + assert parse_and_build("[ap + 2] = [[ap - 4] + 7], ap++") == Instruction( off0=2, off1=-4, off2=7, @@ -320,7 +320,7 @@ def test_jump_instruction(): fp_update=Instruction.FpUpdate.REGULAR, opcode=Instruction.Opcode.NOP, ) - assert parse_and_build("jmp abs 123; ap++") == Instruction( + assert parse_and_build("jmp abs 123, ap++") == Instruction( off0=-1, off1=-1, off2=1, @@ -379,7 +379,7 @@ def test_jnz_instruction(): fp_update=Instruction.FpUpdate.REGULAR, opcode=Instruction.Opcode.NOP, ) - assert parse_and_build("jmp rel 123 if [ap] != 0; ap++") == Instruction( + assert parse_and_build("jmp rel 123 if [ap] != 0, ap++") == Instruction( off0=0, off1=-1, off2=1, @@ -496,7 +496,7 @@ def test_call_instruction_failures(): ) verify_exception( """\ -call rel 5; ap++ +call rel 5, ap++ ^**************^ ap++ may not be used with the call opcode. """ @@ -523,7 +523,7 @@ def test_ret_instruction(): def test_ret_instruction_failures(): verify_exception( """\ -ret; ap++ +ret, ap++ ^*******^ ap++ may not be used with the ret opcode. """ @@ -578,7 +578,7 @@ def test_addap_instruction(): def test_addap_instruction_failures(): verify_exception( """\ -ap += 5; ap++ +ap += 5, ap++ ^***********^ ap++ may not be used with the addap opcode. """ diff --git a/src/starkware/cairo/lang/compiler/lib/registers.cairo b/src/starkware/cairo/lang/compiler/lib/registers.cairo index e5ece113..29d0d98e 100644 --- a/src/starkware/cairo/lang/compiler/lib/registers.cairo +++ b/src/starkware/cairo/lang/compiler/lib/registers.cairo @@ -1,17 +1,18 @@ -# Returns the contents of the fp and pc registers of the calling function. -# The pc register's value is the address of the instruction that follows directly after the -# invocation of get_fp_and_pc(). -func get_fp_and_pc() -> (fp_val : felt*, pc_val : felt*): - # The call instruction itself already places the old fp and the return pc at [ap - 2], [ap - 1]. - return (fp_val=cast([ap - 2], felt*), pc_val=cast([ap - 1], felt*)) -end +// Returns the contents of the fp and pc registers of the calling function. +// The pc register's value is the address of the instruction that follows directly after the +// invocation of get_fp_and_pc(). +func get_fp_and_pc() -> (fp_val: felt*, pc_val: felt*) { + // The call instruction itself already places the old fp and the return pc at + // [ap - 2], [ap - 1]. + return (fp_val=cast([ap - 2], felt*), pc_val=cast([ap - 1], felt*)); +} -# Returns the content of the ap register just before this function was invoked. +// Returns the content of the ap register just before this function was invoked. @known_ap_change -func get_ap() -> (ap_val : felt*): - # Once get_ap() is invoked, fp points to ap + 2 (since the call instruction placed the old fp - # and pc in memory, advancing ap accordingly). - # Hence, the desired ap value is fp - 2. - let (fp_val, pc_val) = get_fp_and_pc() - return (ap_val=fp_val - 2) -end +func get_ap() -> (ap_val: felt*) { + // Once get_ap() is invoked, fp points to ap + 2 (since the call instruction placed the old fp + // and pc in memory, advancing ap accordingly). + // Hence, the desired ap value is fp - 2. + let (fp_val, pc_val) = get_fp_and_pc(); + return (ap_val=fp_val - 2); +} diff --git a/src/starkware/cairo/lang/compiler/offset_reference_test.py b/src/starkware/cairo/lang/compiler/offset_reference_test.py index a905a3fd..9b75198e 100644 --- a/src/starkware/cairo/lang/compiler/offset_reference_test.py +++ b/src/starkware/cairo/lang/compiler/offset_reference_test.py @@ -15,7 +15,7 @@ def test_offset_reference_definition_typed_members(): - t = TypeStruct(scope=scope("T"), is_fully_resolved=True) + t = TypeStruct(scope=scope("T")) t_star = TypePointer(pointee=t) reference_manager = ReferenceManager() diff --git a/src/starkware/cairo/lang/compiler/parser_errors_test.py b/src/starkware/cairo/lang/compiler/parser_errors_test.py index 7d42b0aa..568d63ab 100644 --- a/src/starkware/cairo/lang/compiler/parser_errors_test.py +++ b/src/starkware/cairo/lang/compiler/parser_errors_test.py @@ -38,8 +38,8 @@ def test_unexpected_token(): foo = bar test """, """ -file:?:?: Unexpected token Token('IDENTIFIER', 'test'). Expected one of: "(", ".", ";", "[", "{", \ -operator. +file:?:?: Unexpected token Token('IDENTIFIER', 'test'). Expected one of: "(", ",", ".", ";", "[", \ +"{", operator. foo = bar test ^**^ """, @@ -79,7 +79,7 @@ def test_unexpected_token(): [ap] = x& + y """, """ -file:?:?: Unexpected token Token('AMPERSAND', '&'). Expected one of: "(", ".", ";", "[", "{", \ +file:?:?: Unexpected token Token('AMPERSAND', '&'). Expected one of: "(", ",", ".", ";", "[", "{", \ operator. [ap] = x& + y ^ @@ -117,22 +117,22 @@ def test_unexpected_token(): ) verify_exception( """ -if x y +if (x y """, """ file:?:?: Unexpected token Token('IDENTIFIER', 'y'). Expected one of: "!=", "(", ".", "==", "[", \ "{", operator. -if x y - ^ +if (x y + ^ """, ) verify_exception( """ -x = y; ap-- +x = y, ap-- """, """ file:?:?: Unexpected token Token('MINUS', '-'). Expected: "++". -x = y; ap-- +x = y, ap-- ^ """, ) @@ -141,7 +141,7 @@ def test_unexpected_token(): func foo()* """, """ -file:?:?: Unexpected token Token('STAR', '*'). Expected one of: "->", ":". +file:?:?: Unexpected token Token('STAR', '*'). Expected one of: "->", "{". func foo()* ^ """, @@ -165,14 +165,14 @@ def test_parser_error(): # Unexpected EOF - missing 'end'. verify_exception( """ -func f(): -const a = 5 +func f() { +const a = 5; """, """ file:?:?: Unexpected end of input. Expected one of: "%builtins", "%lang", "@", "alloc_locals", \ -"assert", "call", "const", "dw", "end", "from", ... -const a = 5 - ^ +"assert", "call", "const", "dw", "from", "func", ... +const a = 5; + ^ """, ) @@ -237,12 +237,12 @@ def test_new_operator_error(): def test_modifier_in_tuple(): verify_exception( """ -let a : (b : local felt) = 5 +let a : (b : local felt) = 5; """, """ file:?:?: Unexpected token Token('LOCAL', 'local'). Expected one of: \ "(", "codeoffset", "felt", identifier. -let a : (b : local felt) = 5 +let a : (b : local felt) = 5; ^***^ """, ) @@ -251,14 +251,45 @@ def test_modifier_in_tuple(): def test_if_with_parenthesized_condition(): verify_exception( """ -if (a == 0 and b == 1): - let x = 0 -end +if ((a == 0 and b == 1)) { + let x = 0; +} """, """ file:?:?: Unexpected token Token(\'_DBL_EQ\', \'==\'). Expected one of: "(", ")", ",", ".", "=", \ "[", "{", operator. -if (a == 0 and b == 1): - ^^ +if ((a == 0 and b == 1)) { + ^^ """, ) + + +def test_modifier_in_return_type(): + verify_exception( + """ +func f(x) -> (local y) { + ret; +} +""", + """ +file:?:?: Unexpected token Token('LOCAL', 'local'). \ +Expected one of: "(", ")", ",", "codeoffset", "felt", identifier. +func f(x) -> (local y) { + ^***^ +""", + ) + + +def test_bad_struct(): + verify_exception( + """ +struct T { + return (); +} +""", + """ +file:?:?: Unexpected token Token('RETURN', 'return'). Expected one of: "local", "}", identifier. + return (); + ^****^ +""", + ) diff --git a/src/starkware/cairo/lang/compiler/parser_test.py b/src/starkware/cairo/lang/compiler/parser_test.py index c0976ae8..e3a2ab03 100644 --- a/src/starkware/cairo/lang/compiler/parser_test.py +++ b/src/starkware/cairo/lang/compiler/parser_test.py @@ -15,7 +15,9 @@ CodeElementIf, CodeElementImport, CodeElementReference, + CodeElementReturn, CodeElementReturnValueReference, + CodeElementTailCall, ) from starkware.cairo.lang.compiler.ast.expr import ( ExprConst, @@ -27,6 +29,7 @@ ExprParentheses, ExprReg, ExprSubscript, + ExprTuple, ) from starkware.cairo.lang.compiler.ast.formatting_utils import FormattingError from starkware.cairo.lang.compiler.ast.instructions import ( @@ -110,18 +113,18 @@ def test_short_string(): ) verify_exception( - """let x = '0123456789012345678901234567890123456789'""", + """let x = '0123456789012345678901234567890123456789';""", """ file:?:?: Short string (e.g., 'abc') length must be at most 31. -let x = '0123456789012345678901234567890123456789' +let x = '0123456789012345678901234567890123456789'; ^****************************************^ """, ) verify_exception( - """let x = '\u1234'""", + """let x = '\u1234';""", """ file:?:?: Expected an ascii string. Found: '\u1234'. -let x = '\u1234' +let x = '\u1234'; ^*^ """, ) @@ -139,7 +142,7 @@ def test_types(): def test_type_tuple(): typ = parse_type("(felt)") assert typ == TypeTuple.unnamed([TypeFelt()]) - assert typ.format() == "(felt)" + assert typ.format() == "(felt,)" assert parse_type("( felt, felt* , (felt, T.S,)* )").format() == "(felt, felt*, (felt, T.S)*)" @@ -148,17 +151,17 @@ def test_type_named_tuple(): assert isinstance(typ, TypeTuple) assert typ.members[0].name == "a" assert typ.members[1].name == "b" - assert typ.format() == "(a : felt, b : felt)" + assert typ.format() == "(a: felt, b: felt)" assert ( parse_type("( a:(felt, felt*) , b:(c:felt,)* )").format() - == "(a : (felt, felt*), b : (c : felt)*)" + == "(a: (felt, felt*), b: (c: felt)*)" ) # With new lines. - assert parse_type("(\n a:felt\n\n, \n b: felt \n )").format() == "(a : felt, b : felt)" + assert parse_type("(\n a:felt\n\n, \n b: felt \n )").format() == "(a: felt, b: felt)" # With comments (parsing, but no auto-formatting). - typ2 = parse_type("( # This is a comment.\na:felt\n\n, \n b: felt \n )") + typ2 = parse_type("( // This is a comment.\na:felt\n\n, \n b: felt \n )") assert typ2 == typ with pytest.raises( FormattingError, @@ -167,24 +170,24 @@ def test_type_named_tuple(): typ2.format() # Partially named tuple types can be parsed, but they won't pass the other compilation stages. - assert parse_type("( felt , a:felt, )").format() == "(felt, a : felt)" + assert parse_type("( felt , a:felt, )").format() == "(felt, a: felt)" def test_type_named_tuple_failure(): verify_exception( - "local x : (a* : felt)", + "local x: (a*: felt)", """ file:?:?: Unexpected token Token('COLON', ':'). Expected one of: ")", "*", ",". -local x : (a* : felt) - ^ +local x: (a*: felt) + ^ """, ) verify_exception( - "local x : (a.b : felt)", + "local x: (a.b: felt);", """ file:?:?: Unexpected '.' in name. -local x : (a.b : felt) - ^*^ +local x: (a.b: felt); + ^*^ """, ) @@ -217,10 +220,10 @@ def test_identifier_and_dot(): def test_typed_identifier(): typed_identifier = parse(None, "t : felt*", "typed_identifier", TypedIdentifier) - assert typed_identifier.format() == "t : felt*" + assert typed_identifier.format() == "t: felt*" typed_identifier = parse(None, "local t : felt", "typed_identifier", TypedIdentifier) - assert typed_identifier.format() == "local t : felt" + assert typed_identifier.format() == "local t: felt" def test_add_expr(): @@ -322,34 +325,34 @@ def test_tuple_expr(): assert parse_expr("( 1 , a = ap, )").format() == "(1, a=ap,)" verify_exception( - "let x = (,)", + "let x = (,);", """ file:?:?: Unexpected comma. -let x = (,) +let x = (,); ^ """, ) verify_exception( - "let x = (a, ,)", + "let x = (a, ,);", """ file:?:?: Unexpected comma. -let x = (a, ,) +let x = (a, ,); ^ """, ) verify_exception( - "let x = ((a)(b))", + "let x = ((a)(b));", """ file:?:?: Unexpected token Token('LPAR', '('). Expected one of: ")", ",", ".", "[", operator. -let x = ((a)(b)) +let x = ((a)(b)); ^ """, ) verify_exception( - "let x = ((a)\n(b))", + "let x = ((a)\n(b));", """ file:?:?: Expected a comma before this expression. -(b)) +(b)); ^*^ """, ) @@ -359,27 +362,27 @@ def test_tuple_expr_with_notes(): assert ( parse_expr( """\ -( 1 , # a. - ( # c. - ) #b. +( 1 , // a. + ( // c. + ) //b. , (fp,[3]))""" ).format() == """\ -(1, # a. - ( # c. - ), # b. +(1, // a. + ( // c. + ), // b. (fp, [3]))""" ) assert ( parse_expr( """\ -( 1 # b. - , # a. +( 1 // b. + , // a. )""" ).format() == """\ -(1, # b. - # a. +(1, // b. + // a. )""" ) @@ -411,19 +414,19 @@ def test_offsets(): def test_instruction(): # AssertEq. - expr = parse_instruction("[ap] = [fp]; ap++") + expr = parse_instruction("[ap] = [fp], ap++") assert expr == InstructionAst( body=AssertEqInstruction( a=ExprDeref(addr=ExprReg(reg=Register.AP)), b=ExprDeref(addr=ExprReg(reg=Register.FP)) ), inc_ap=True, ) - assert expr.format() == "[ap] = [fp]; ap++" + assert expr.format() == "[ap] = [fp], ap++" assert parse_instruction("[ap+5] = [fp]+[ap] - 5").format() == "[ap + 5] = [fp] + [ap] - 5" - assert parse_instruction("[ap+5]+3= [fp]*7;ap ++ ").format() == "[ap + 5] + 3 = [fp] * 7; ap++" + assert parse_instruction("[ap+5]+3= [fp]*7,ap ++ ").format() == "[ap + 5] + 3 = [fp] * 7, ap++" # Jump. - expr = parse_instruction("jmp rel [ap] + x; ap++") + expr = parse_instruction("jmp rel [ap] + x, ap++") assert expr == InstructionAst( body=JumpInstruction( val=ExprOperator( @@ -433,7 +436,7 @@ def test_instruction(): ), inc_ap=True, ) - assert expr.format() == "jmp rel [ap] + x; ap++" + assert expr.format() == "jmp rel [ap] + x, ap++" assert parse_instruction(" jmp abs[ap]+x").format() == "jmp abs [ap] + x" # Make sure the following are not OK. with pytest.raises(ParserError): @@ -469,8 +472,8 @@ def test_instruction(): ) assert expr.format() == "jmp rel [ap] + x if [fp + 3] != 0" assert ( - parse_instruction(" jmp rel 17 if[fp]!=0;ap++").format() - == "jmp rel 17 if [fp] != 0; ap++" + parse_instruction(" jmp rel 17 if[fp]!=0,ap++").format() + == "jmp rel 17 if [fp] != 0, ap++" ) # Make sure the following are not OK. with pytest.raises(ParserError): @@ -509,7 +512,7 @@ def test_instruction(): inc_ap=False, ) assert expr.format() == "call abs [fp] + x" - assert parse_instruction("call abs 17;ap++").format() == "call abs 17; ap++" + assert parse_instruction("call abs 17,ap++").format() == "call abs 17, ap++" # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction("call abs") @@ -528,7 +531,7 @@ def test_instruction(): inc_ap=False, ) assert expr.format() == "call rel [ap] + x" - assert parse_instruction("call rel 17;ap++").format() == "call rel 17; ap++" + assert parse_instruction("call rel 17,ap++").format() == "call rel 17, ap++" # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction("call rel") @@ -541,7 +544,7 @@ def test_instruction(): body=CallLabelInstruction(label=ExprIdentifier(name="label")), inc_ap=False ) assert expr.format() == "call label" - assert parse_instruction("call label ;ap++").format() == "call label; ap++" + assert parse_instruction("call label ,ap++").format() == "call label, ap++" # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction("call [fp]") @@ -565,7 +568,7 @@ def test_instruction(): ) assert expr.format() == "ap += [fp] + 2" assert parse_instruction("ap +=[ fp]+ 2").format() == "ap += [fp] + 2" - assert parse_instruction("ap +=[ fp]+ 2;ap ++").format() == "ap += [fp] + 2; ap++" + assert parse_instruction("ap +=[ fp]+ 2,ap ++").format() == "ap += [fp] + 2, ap++" # Data word. assert parse_instruction("dw 0x123").format() == "dw 0x123" @@ -650,17 +653,17 @@ def test_import(): def test_return_value_reference(): - res = parse_code_element("let z=call x") - assert res.format(allowed_line_length=100) == "let z = call x" + res = parse_code_element("let z=call x;") + assert res.format(allowed_line_length=100) == "let z = call x;" - res = parse_code_element("let z:y.z=call x") - assert res.format(allowed_line_length=100) == "let z : y.z = call x" + res = parse_code_element("let z:y.z=call x;") + assert res.format(allowed_line_length=100) == "let z: y.z = call x;" - res = parse_code_element("let z:y.z=call rel x") - assert res.format(allowed_line_length=100) == "let z : y.z = call rel x" + res = parse_code_element("let z:y.z=call rel x;") + assert res.format(allowed_line_length=100) == "let z: y.z = call rel x;" res = parse_code_element( - "let very_long_prefix = foo(a=1, b= 1, very_long_arg_1=1, very_long_arg_2 =1)" + "let very_long_prefix = foo(a=1, b= 1, very_long_arg_1=1, very_long_arg_2 =1);" ) assert ( res.format(allowed_line_length=40) @@ -670,21 +673,21 @@ def test_return_value_reference(): b=1, very_long_arg_1=1, very_long_arg_2=1, -)""" +);""" ) res = parse_code_element( - "let (very_long_prefix ,b,c: T) = foo(a=1, b= 1, very_long_arg_1=1, very_long_arg_2 =1)" + "let (very_long_prefix ,b,c: T) = foo(a=1, b= 1, very_long_arg_1=1, very_long_arg_2 =1);" ) assert ( res.format(allowed_line_length=40) == """\ -let (very_long_prefix, b, c : T) = foo( +let (very_long_prefix, b, c: T) = foo( a=1, b=1, very_long_arg_1=1, very_long_arg_2=1, -)""" +);""" ) with pytest.raises(ParserError): @@ -697,50 +700,93 @@ def test_return_value_reference(): with pytest.raises(ParserError): # 'ap++' cannot be used in the return value reference syntax. - parse_expr("let z = call x; ap++") + parse_expr("let z = call x, ap++") def test_new_operator(): expr = parse_expr("new Struct(a = 1, b= 2 )") assert expr.format() == "new Struct(a=1, b=2)" - res = parse_code_element("new ( a = 1, b= 2 ) + 5 = 17 + new 7 + 2") - assert res.format(allowed_line_length=100) == "(new (a=1, b=2)) + 5 = 17 + (new 7) + 2" + res = parse_code_element("new ( a = 1, b= 2 ) + 5 = 17 + new 7 + 2;") + assert res.format(allowed_line_length=100) == "(new (a=1, b=2)) + 5 = 17 + (new 7) + 2;" def test_return(): - res = parse_code_element("return( 1, \na= 2 )") - assert res.format(allowed_line_length=100) == "return (1, a=2)" + res = parse_code_element("return( 1, \na= 2 );") + assert res.format(allowed_line_length=100) == "return (1, a=2);" + + +def test_empty_return(): + res = parse_code_element("return( ) ;") + assert res.format(allowed_line_length=100) == "return ();" + + +def test_code_element_return(): + res = parse_code_element("return (res );") + assert res.format(allowed_line_length=100) == "return (res);" + assert isinstance(res, CodeElementReturn) + assert isinstance(res.expr, ExprParentheses) + + res = parse_code_element("return (res,);") + assert res.format(allowed_line_length=100) == "return (res,);" + assert isinstance(res, CodeElementReturn) + assert isinstance(res.expr, ExprTuple) + + res = parse_code_element("return res * 5;") + assert res.format(allowed_line_length=100) == "return res * 5;" + assert isinstance(res, CodeElementReturn) + assert isinstance(res.expr, ExprOperator) + + code = """\ +return ( + res=Point( + x=points[0].x + points[1].x, + y=points[0].y + points[1].y), +);""" + + res = parse_code_element(code) + assert res.format(allowed_line_length=40) == code def test_func_call(): - res = parse_code_element("fibonacci( 1, \na= 2 )") - assert res.format(allowed_line_length=100) == "fibonacci(1, a=2)" + res = parse_code_element("fibonacci( 1, \na= 2 );") + assert res.format(allowed_line_length=100) == "fibonacci(1, a=2);" - res = parse_code_element("fibonacci {a=b,c = d}( 1, \na= 2 )") - assert res.format(allowed_line_length=100) == "fibonacci{a=b, c=d}(1, a=2)" - assert res.format(allowed_line_length=20) == "fibonacci{a=b, c=d}(\n 1, a=2\n)" - assert res.format(allowed_line_length=15) == "fibonacci{\n a=b, c=d\n}(1, a=2)" + res = parse_code_element("fibonacci {a=b,c = d}( 1, \na= 2 );") + assert res.format(allowed_line_length=100) == "fibonacci{a=b, c=d}(1, a=2);" + assert res.format(allowed_line_length=20) == "fibonacci{a=b, c=d}(\n 1, a=2\n);" + assert res.format(allowed_line_length=15) == "fibonacci{\n a=b, c=d\n}(1, a=2);" def test_tail_call(): - res = parse_code_element("return fibonacci( 1, \na= 2 )") - assert res.format(allowed_line_length=100) == "return fibonacci(1, a=2)" + res = parse_code_element("return fibonacci( 1, \na= 2 );") + assert isinstance(res, CodeElementTailCall) + assert res.format(allowed_line_length=100) == "return fibonacci(1, a=2);" + + res = parse_code_element("return (fibonacci( 1, \na= 2 ));") + assert isinstance(res, CodeElementReturn) + assert isinstance(res.expr, ExprParentheses) + assert ( + res.format(allowed_line_length=100) + == """\ +return (fibonacci(1, + a=2));""" + ) def test_func_with_args(): def def_func(args_str): return f"""\ -func myfunc{args_str}: - [ap] = 4 -end""" +func myfunc{args_str} {{ + [ap] = 4; +}}""" - def test_format(args_str_wrong, args_str_right=""): + def test_format(args_str_wrong, args_str_right="", allowed_line_length=100): assert parse_code_element(def_func(args_str_wrong)).format( - allowed_line_length=100 + allowed_line_length=allowed_line_length ) == def_func(args_str_right) - test_format(" ( x : T, y : S, z ) ", "(x : T, y : S, z)") + test_format(" ( x : T, y : S, z ) ", "(x: T, y: S, z)") test_format("(x,y,z)", "(x, y, z)") test_format("(x,y,z,)", "(x, y, z)") test_format("(x,\ny,\nz)", "(x, y, z)") @@ -755,6 +801,11 @@ def test_format(args_str_wrong, args_str_right=""): # Implicit arguments. test_format("{x,y\n\n}(z,w)->()", "{x, y}(z, w) -> ()") + # Test that we don't split the line between the '->' and the return type. + args_str = "{a}(z, w) -> felt" + splitting_line_length = len(def_func(args_str).splitlines()[0]) - 2 + test_format(args_str, "{a}(\n z, w\n) -> felt", allowed_line_length=splitting_line_length) + with pytest.raises(ParserError): test_format("") @@ -771,7 +822,7 @@ def test_format(args_str_wrong, args_str_right=""): test_format("(x,y,z,,)") with pytest.raises(FormattingError): - test_format("(x #comment\n,y,z)->()") + test_format("(x //comment\n,y,z)->()") def test_decoractor(): @@ -779,9 +830,9 @@ def test_decoractor(): @hello @world -@external func myfunc(): - return () -end""" +@external func myfunc() { + return (); +}""" assert ( parse_code_element(code=code).format(allowed_line_length=100) @@ -789,9 +840,9 @@ def test_decoractor(): @hello @world @external -func myfunc(): - return () -end""" +func myfunc() { + return (); +}""" ) @@ -799,9 +850,9 @@ def test_decoractor_errors(): verify_exception( """ @hello world -func myfunc(): - return() -end +func myfunc() { + return (); +} """, """ file:?:?: Unexpected token Token('IDENTIFIER', \'world\'). Expected one of: "@", "func", \ @@ -814,9 +865,9 @@ def test_decoractor_errors(): verify_exception( """ @hello-world -func myfunc(): - return() -end +func myfunc() { + return (); +} """, """ file:?:?: Unexpected token Token('MINUS', \'-\'). Expected one of: "@", "func", "namespace", \ @@ -828,26 +879,26 @@ def test_decoractor_errors(): def test_reference_type_annotation(): - res = parse_code_element("let s : T * = ap") - assert res.format(allowed_line_length=100) == "let s : T* = ap" + res = parse_code_element("let s : T * = ap;") + assert res.format(allowed_line_length=100) == "let s: T* = ap;" with pytest.raises(ParserError): - parse_expr("local x : = 0") + parse_expr("local x : = 0;") def test_addressof(): - res = parse_code_element("static_assert & s.SIZE == ap ") - assert res.format(allowed_line_length=100) == "static_assert &s.SIZE == ap" + res = parse_code_element("static_assert & s.SIZE == ap ; ") + assert res.format(allowed_line_length=100) == "static_assert &s.SIZE == ap;" def test_func_expr(): - res = parse_code_element("let x = f()") + res = parse_code_element("let x = f();") assert isinstance(res, CodeElementReturnValueReference) - assert res.format(allowed_line_length=100) == "let x = f()" + assert res.format(allowed_line_length=100) == "let x = f();" - res = parse_code_element("let x = (f())") + res = parse_code_element("let x = (f());") assert isinstance(res, CodeElementReference) - assert res.format(allowed_line_length=100) == "let x = (f())" + assert res.format(allowed_line_length=100) == "let x = (f());" def test_parent_location(): @@ -856,7 +907,7 @@ def test_parent_location(): parent_location = (location, "An error ocurred while processing:") code_element = parse_code_element( - "let x = 3 + 4", parser_context=ParserContext(parent_location=parent_location) + "let x = 3 + 4;", parser_context=ParserContext(parent_location=parent_location) ) assert isinstance(code_element, CodeElementReference) location = code_element.expr.location @@ -868,7 +919,7 @@ def test_parent_location(): 1 + 2 ^***^ :1:9: Error -let x = 3 + 4 +let x = 3 + 4; ^***^\ """ ) @@ -876,7 +927,7 @@ def test_parent_location(): def test_locations(): code_with_marks = """\ - [ap ] = [ fp + 2]; ap ++ + [ap ] = [ fp + 2], ap ++ ^***********************^ ^***************^ ^***^ @@ -924,9 +975,9 @@ def test_pointer(): def test_if_and(): code = """\ -if a == 0 and b == 0: - alloc_locals -end\ +if (a == 0 and b == 0) { + alloc_locals; +}\ """ ret = parse_code_element(code) assert isinstance(ret, CodeElementIf) @@ -947,9 +998,9 @@ def test_if_and(): def test_if_and_is_left_to_right_associative(): code = """\ -if a == 0 and b == 0 and c == 0: - alloc_locals -end\ +if (a == 0 and b == 0 and c == 0) { + alloc_locals; +}\ """ ret = parse_code_element(code) assert isinstance(ret, CodeElementIf) @@ -977,10 +1028,10 @@ def test_if_and_is_left_to_right_associative(): def test_if_multiline_and(): code = """\ -if a == 0 and b == 0 and c == 0 and - d == 0 and e == 0: - alloc_locals -end\ +if (a == 0 and b == 0 and c == 0 and + d == 0 and e == 0) { + alloc_locals; +}\ """ ret = parse_code_element(code) assert ret.format(allowed_line_length=40) == code diff --git a/src/starkware/cairo/lang/compiler/parser_transformer.py b/src/starkware/cairo/lang/compiler/parser_transformer.py index fc729e15..6a16ac25 100644 --- a/src/starkware/cairo/lang/compiler/parser_transformer.py +++ b/src/starkware/cairo/lang/compiler/parser_transformer.py @@ -12,6 +12,7 @@ CairoType, TypeCodeoffset, TypeFelt, + TypeIdentifier, TypePointer, TypeStruct, TypeTuple, @@ -210,9 +211,15 @@ def type_codeoffset(self, value, meta): def type_struct(self, value): assert len(value) == 1 and isinstance(value[0], ExprIdentifier) - return TypeStruct( - scope=ScopedName.from_string(value[0].name), - is_fully_resolved=self.parser_context.resolved_types, + if self.parser_context.resolved_types: + # If parser_context.resolved_types is True, assume that the type is a struct. + return TypeStruct( + scope=ScopedName.from_string(value[0].name), + location=value[0].location, + ) + + return TypeIdentifier( + name=ScopedName.from_string(value[0].name), location=value[0].location, ) @@ -592,12 +599,11 @@ def code_element_static_assert(self, value, meta): @v_args(meta=True) def code_element_return(self, value, meta): - (arglist,) = value - return CodeElementReturn(exprs=arglist.args, location=self.meta2loc(meta)) + (expr,) = value + if isinstance(expr, ExprFuncCall): + return CodeElementTailCall(func_call=expr.rvalue, location=self.meta2loc(meta)) - @v_args(meta=True) - def code_element_tail_call(self, value, meta): - return CodeElementTailCall(func_call=value[0], location=self.meta2loc(meta)) + return CodeElementReturn(expr=expr, location=self.meta2loc(meta)) def code_element_func_call(self, value): return CodeElementFuncCall(func_call=value[0]) @@ -622,7 +628,7 @@ def code_element_empty_line(self, value): @v_args(meta=True) def commented_code_element(self, value, meta): - comment = value[1][1:] if len(value) == 2 else None + comment = value[1][2:] if len(value) == 2 else None return CommentedCodeElement( code_elm=value[0], comment=comment, location=self.meta2loc(meta) ) @@ -675,9 +681,21 @@ def code_element_function(self, value): ) def code_element_struct(self, value): - decorators, element_type, identifier, code_block = value + decorators, identifier, code_block = value + return CodeElementFunction( + element_type="struct", + identifier=identifier, + arguments=IdentifierList(identifiers=[], notes=[]), + implicit_arguments=None, + returns=None, + code_block=code_block, + decorators=decorators, + ) + + def code_element_namespace(self, value): + decorators, identifier, code_block = value return CodeElementFunction( - element_type=element_type.value, + element_type="namespace", identifier=identifier, arguments=IdentifierList(identifiers=[], notes=[]), implicit_arguments=None, diff --git a/src/starkware/cairo/lang/compiler/preprocessor/CMakeLists.txt b/src/starkware/cairo/lang/compiler/preprocessor/CMakeLists.txt new file mode 100644 index 00000000..cca6166a --- /dev/null +++ b/src/starkware/cairo/lang/compiler/preprocessor/CMakeLists.txt @@ -0,0 +1,26 @@ +add_subdirectory(bool_expr) + +full_python_test(cairo_compile_preprocessor_test + PREFIX starkware/cairo/lang/compiler/preprocessor + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/lang/compiler/preprocessor + + FILES + compound_expressions_test.py + conftest.py + dependency_graph_test.py + flow_test.py + identifier_aware_visitor_test.py + identifier_collector_test.py + if_labels_test.py + local_variables_test.py + memento_test.py + preprocessor_test.py + reg_tracking_test.py + struct_collector_test.py + + LIBS + cairo_compile_lib + cairo_compile_test_utils_lib + pip_pytest +) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/auxiliary_info_collector.py b/src/starkware/cairo/lang/compiler/preprocessor/auxiliary_info_collector.py index c88f3de2..30a3aaac 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/auxiliary_info_collector.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/auxiliary_info_collector.py @@ -1,9 +1,12 @@ from abc import ABC, abstractmethod from typing import List, Optional -from starkware.cairo.lang.compiler.ast.expr import ExprAssignment, Expression +from starkware.cairo.lang.compiler.ast.cairo_types import CairoType +from starkware.cairo.lang.compiler.ast.expr import Expression +from starkware.cairo.lang.compiler.ast.types import TypedIdentifier from starkware.cairo.lang.compiler.error_handling import Location from starkware.cairo.lang.compiler.identifier_definition import StructDefinition +from starkware.cairo.lang.compiler.preprocessor.reg_tracking import RegChange from starkware.cairo.lang.compiler.scoped_name import ScopedName @@ -26,11 +29,13 @@ def start_function_info( start_pc: int, implicit_args_struct: StructDefinition, args_struct: StructDefinition, + ret_names: List[str], + ret_types: List[CairoType], ): pass @abstractmethod - def finish_function_info(self, end_pc: int): + def finish_function_info(self, end_pc: int, total_ap_change: RegChange): pass @abstractmethod @@ -38,7 +43,7 @@ def add_assert_eq(self, lhs: Expression, rhs: Expression): pass @abstractmethod - def start_compound_assert_eq(self, lhs: Expression, rhs: Expression): + def start_compound_assert_eq(self, lhs: Expression, rhs: Expression, resolved_type: CairoType): pass @abstractmethod @@ -46,17 +51,26 @@ def finish_compound_assert_eq(self): pass @abstractmethod - def add_reference(self, name: ScopedName, expr: Expression, identifier_loc: Optional[Location]): + def add_reference( + self, + identifier: TypedIdentifier, + resolved_type: CairoType, + expr: Expression, + identifier_loc: Optional[Location], + ): pass @abstractmethod def start_temp_var( - self, name: ScopedName, expr: Expression, identifier_loc: Optional[Location] + self, + identifier: TypedIdentifier, + expr: Expression, + identifier_loc: Optional[Location], ): pass @abstractmethod - def finish_temp_var(self): + def finish_temp_var(self, resolve_type: CairoType): pass @abstractmethod @@ -84,7 +98,7 @@ def start_return(self): pass @abstractmethod - def finish_return(self, exprs: List[ExprAssignment]): + def finish_return(self, exprs: List[Expression]): pass @abstractmethod @@ -114,5 +128,5 @@ def add_add_ap(self, expr: Expression): pass @abstractmethod - def add_const(self, name: ScopedName, val: int): + def add_const(self, name: ScopedName, expr: Expression, val: int): pass diff --git a/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/CMakeLists.txt b/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/CMakeLists.txt new file mode 100644 index 00000000..1141a2e9 --- /dev/null +++ b/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/CMakeLists.txt @@ -0,0 +1,13 @@ +full_python_test(cairo_compile_preprocessor_bool_expr_test + PREFIX starkware/cairo/lang/compiler/preprocessor/bool_expr + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/lang/compiler/preprocessor/bool_expr + + FILES + lowering_test.py + + LIBS + cairo_compile_lib + + cairo_compile_test_utils_lib +) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/lowering.py b/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/lowering.py index 43bb576d..8647b51a 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/lowering.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/lowering.py @@ -29,7 +29,9 @@ def _visit_default(self, elm): def visit_CodeElementIf(self, elm: CodeElementIf) -> CodeElementIf: if isinstance(elm.condition, BoolEqExpr): - return elm + # Call visit_CodeElementIf directly instead of using visit() to avoid infinite + # recursion. + return super().visit_CodeElementIf(elm) if elm.else_code_block is not None: raise BoolExprLoweringError( @@ -38,7 +40,9 @@ def visit_CodeElementIf(self, elm: CodeElementIf) -> CodeElementIf: ) return _lower_conjunction_chain( - lhs=elm.condition, main_code_block=elm.main_code_block, location=elm.location + lhs=elm.condition, + main_code_block=self.visit(elm.main_code_block), + location=elm.location, ) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/lowering_test.py b/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/lowering_test.py index 19bdccf5..2750de65 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/lowering_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/bool_expr/lowering_test.py @@ -6,60 +6,98 @@ def test_lowers_single_and_without_else(): code = """ -func main(): - let a = 10 - let b = 12 - if a == 10 and b == 12: - let x = a + b - end - ret -end +func main() { + let a = 10; + let b = 12; + if (a == 10 and b == 12) { + let x = a + b; + } + ret; +} """ assert ( lower_and_format(code) == """\ -func main(): - let a = 10 - let b = 12 - if a == 10: - if b == 12: - let x = a + b - end - end - ret -end +func main() { + let a = 10; + let b = 12; + if (a == 10) { + if (b == 12) { + let x = a + b; + } + } + ret; +} +""" + ) + + +def test_lowers_nested_ifs(): + code = """ +func main() -> (res: felt) { + if (1 == 2 and 3 == 4) { + if (5 == 6) { + if (7 == 8 and 9 == 10) { + return (res=1); + } + return (res=2); + } + return (res=3); + } + return (res=4); +} +""" + assert ( + lower_and_format(code) + == """\ +func main() -> (res: felt) { + if (1 == 2) { + if (3 == 4) { + if (5 == 6) { + if (7 == 8) { + if (9 == 10) { + return (res=1); + } + } + return (res=2); + } + return (res=3); + } + } + return (res=4); +} """ ) def test_lowers_nested_and_without_else(): code = """ -func main(): - let a = 10 - let b = 12 - let c = 14 - if a == 10 and b == 12 and c == 14: - let x = a + b + c - end - ret -end +func main() { + let a = 10; + let b = 12; + let c = 14; + if (a == 10 and b == 12 and c == 14) { + let x = a + b + c; + } + ret; +} """ assert ( lower_and_format(code) == """\ -func main(): - let a = 10 - let b = 12 - let c = 14 - if a == 10: - if b == 12: - if c == 14: - let x = a + b + c - end - end - end - ret -end +func main() { + let a = 10; + let b = 12; + let c = 14; + if (a == 10) { + if (b == 12) { + if (c == 14) { + let x = a + b + c; + } + } + } + ret; +} """ ) @@ -67,20 +105,20 @@ def test_lowers_nested_and_without_else(): def test_else_is_not_supported(): verify_exception( """ -func main(): - let a = 10 - let b = 12 - if a == 10 and b == 12: - let x = a + b - else: - let x = a - b - end - ret -end +func main() { + let a = 10; + let b = 12; + if (a == 10 and b == 12) { + let x = a + b; + } else { + let x = a - b; + } + ret; +} """, """ file:?:?: Else blocks are not supported with boolean logic expressions yet. - if a == 10 and b == 12: + if (a == 10 and b == 12) { ^^ """, ) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/compound_expressions.py b/src/starkware/cairo/lang/compiler/preprocessor/compound_expressions.py index c75da62b..60b3e2e6 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/compound_expressions.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/compound_expressions.py @@ -1,3 +1,4 @@ +import dataclasses from abc import ABC, abstractmethod from enum import Enum, auto from typing import List, Optional, Union @@ -5,9 +6,11 @@ from starkware.cairo.lang.compiler.ast.cairo_types import TypeFelt from starkware.cairo.lang.compiler.ast.code_elements import ( CodeElement, + CodeElementFuncCall, CodeElementTemporaryVariable, ) from starkware.cairo.lang.compiler.ast.expr import ( + ArgList, ExprConst, ExprDeref, Expression, @@ -19,6 +22,7 @@ ExprOperator, ExprReg, ) +from starkware.cairo.lang.compiler.ast.expr_func_call import ExprFuncCall from starkware.cairo.lang.compiler.ast.types import TypedIdentifier from starkware.cairo.lang.compiler.error_handling import Location from starkware.cairo.lang.compiler.expression_simplifier import ExpressionSimplifier @@ -30,7 +34,7 @@ ) from starkware.cairo.lang.compiler.preprocessor.flow import RegTrackingData from starkware.cairo.lang.compiler.preprocessor.preprocessor_error import PreprocessorError -from starkware.cairo.lang.compiler.references import translate_ap +from starkware.cairo.lang.compiler.references import ApDeductionError, translate_ap class SimplicityLevel(Enum): @@ -199,6 +203,48 @@ def rewrite_ExprNewOperator(self, expr: ExprNewOperator, sim: SimplicityLevel): ), "The CompoundExpressionVisitor expects ExprNewOperator expressions to be untyped." return self.wrap(expr) + def translate_arg_list(self, arg_list: ArgList) -> ArgList: + """ + Applies translate_ap() to all the arguments in 'arg_list'. + """ + return dataclasses.replace( + arg_list, + args=[ + dataclasses.replace(arg, expr=self.translate_ap(arg.expr)) for arg in arg_list.args + ], + ) + + def rewrite_ExprFuncCall(self, expr: ExprFuncCall, sim: SimplicityLevel): + # Arguments with AP based expression need to be rewritten. + # The implicit arguments here are only allowed to be identifiers so there is no + # need to translate them. + func_call = dataclasses.replace( + expr.rvalue, arguments=self.translate_arg_list(expr.rvalue.arguments) + ) + + self.context.visit(CodeElementFuncCall(func_call=func_call)) + location = expr.location + try: + # Note that [ap - 1] is with respect to the current ap so we need to call untranslate_ap + # to return an untranslated expression (that is, with respect to the initial ap). + return self.untranslate_ap( + expr=ExprDeref( + addr=ExprOperator( + a=ExprReg(reg=Register.AP, location=location), + op="+", + b=ExprConst(val=-1, location=location), + location=location, + ), + location=location, + ) + ) + except ApDeductionError: + raise PreprocessorError( + "Only functions with known ap change may be used in an expression. " + f"Consider calling '{func_call.func_ident.name}' in a separate line.", + location=expr.location, + ) + def wrap(self, expr: Expression) -> ExprIdentifier: identifier = ExprIdentifier(name=self.context.new_tempvar_name(), location=expr.location) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/compound_expressions_test.py b/src/starkware/cairo/lang/compiler/preprocessor/compound_expressions_test.py index ee356443..fc4327ea 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/compound_expressions_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/compound_expressions_test.py @@ -56,8 +56,8 @@ def get_ap_tracking(self) -> RegTrackingData: "5", "5", "5", - "tempvar x0 : felt = 5; x0", - "tempvar x0 : felt = 5; x0", + "tempvar x0: felt = 5; x0", + "tempvar x0: felt = 5; x0", ], [ "[ap + 5]", @@ -69,44 +69,44 @@ def get_ap_tracking(self) -> RegTrackingData: [ "[ap + 5] + 3", "[ap + 5] + 3", - "tempvar x0 : felt = [ap - 0 + 5] + 3; x0", + "tempvar x0: felt = [ap - 0 + 5] + 3; x0", "[ap + 5] + 3", - "tempvar x0 : felt = [ap - 0 + 5] + 3; x0", + "tempvar x0: felt = [ap - 0 + 5] + 3; x0", ], [ "3 + [ap + 5]", - "tempvar x0 : felt = 3; x0 + [ap + 5]", - "tempvar x0 : felt = 3; tempvar x1 : felt = x0 + [ap - 1 + 5]; x1", - "tempvar x0 : felt = 3; tempvar x1 : felt = x0 + [ap - 1 + 5]; x1", - "tempvar x0 : felt = 3; tempvar x1 : felt = x0 + [ap - 1 + 5]; x1", + "tempvar x0: felt = 3; x0 + [ap + 5]", + "tempvar x0: felt = 3; tempvar x1: felt = x0 + [ap - 1 + 5]; x1", + "tempvar x0: felt = 3; tempvar x1: felt = x0 + [ap - 1 + 5]; x1", + "tempvar x0: felt = 3; tempvar x1: felt = x0 + [ap - 1 + 5]; x1", ], [ "[[ap + 5]]", "[[ap + 5]]", - "tempvar x0 : felt = [[ap - 0 + 5]]; x0", - "tempvar x0 : felt = [[ap - 0 + 5]]; x0", - "tempvar x0 : felt = [[ap - 0 + 5]]; x0", + "tempvar x0: felt = [[ap - 0 + 5]]; x0", + "tempvar x0: felt = [[ap - 0 + 5]]; x0", + "tempvar x0: felt = [[ap - 0 + 5]]; x0", ], [ "[[[ap + 5]]]", - "tempvar x0 : felt = [[ap - 0 + 5]]; [x0]", - "tempvar x0 : felt = [[ap - 0 + 5]]; tempvar x1 : felt = [x0]; x1", - "tempvar x0 : felt = [[ap - 0 + 5]]; tempvar x1 : felt = [x0]; x1", - "tempvar x0 : felt = [[ap - 0 + 5]]; tempvar x1 : felt = [x0]; x1", + "tempvar x0: felt = [[ap - 0 + 5]]; [x0]", + "tempvar x0: felt = [[ap - 0 + 5]]; tempvar x1: felt = [x0]; x1", + "tempvar x0: felt = [[ap - 0 + 5]]; tempvar x1: felt = [x0]; x1", + "tempvar x0: felt = [[ap - 0 + 5]]; tempvar x1: felt = [x0]; x1", ], [ "[3]", - "tempvar x0 : felt = 3; [x0]", - "tempvar x0 : felt = 3; tempvar x1 : felt = [x0]; x1", - "tempvar x0 : felt = 3; tempvar x1 : felt = [x0]; x1", - "tempvar x0 : felt = 3; tempvar x1 : felt = [x0]; x1", + "tempvar x0: felt = 3; [x0]", + "tempvar x0: felt = 3; tempvar x1: felt = [x0]; x1", + "tempvar x0: felt = 3; tempvar x1: felt = [x0]; x1", + "tempvar x0: felt = 3; tempvar x1: felt = [x0]; x1", ], [ "-[ap + 3]", "[ap + 3] * (-1)", - "tempvar x0 : felt = [ap - 0 + 3] * (-1); x0", - "tempvar x0 : felt = [ap - 0 + 3] * (-1); x0", - "tempvar x0 : felt = [ap - 0 + 3] * (-1); x0", + "tempvar x0: felt = [ap - 0 + 3] * (-1); x0", + "tempvar x0: felt = [ap - 0 + 3] * (-1); x0", + "tempvar x0: felt = [ap - 0 + 3] * (-1); x0", ], ], ) @@ -129,7 +129,7 @@ def test_compound_expression_visitor( res = visitor.rewrite(expr, sim) assert ( "".join( - code_element.format(allowed_line_length=100) + "; " + code_element.format(allowed_line_length=100) + " " for code_element in context.code_elements ) + res.format() @@ -150,13 +150,13 @@ def test_compound_expression_visitor_long(): for code_element in context.code_elements ) == """\ -tempvar x0 : felt = [ap - 0 + 200] * (-1) -tempvar x1 : felt = x0 / [ap - 1 + 300] -tempvar x2 : felt = [x1] -tempvar x3 : felt = [x2] -tempvar x4 : felt = [fp] * x3 -tempvar x5 : felt = [ap - 5 + 100] - x4 -tempvar x6 : felt = [ap - 6] * [ap - 6] +tempvar x0: felt = [ap - 0 + 200] * (-1); +tempvar x1: felt = x0 / [ap - 1 + 300]; +tempvar x2: felt = [x1]; +tempvar x3: felt = [x2]; +tempvar x4: felt = [fp] * x3; +tempvar x5: felt = [ap - 5 + 100] - x4; +tempvar x6: felt = [ap - 6] * [ap - 6]; """ ) assert res.format() == "x5 + x6" @@ -172,12 +172,12 @@ def test_compound_expression_visitor_inverses(): for code_element in context.code_elements ) == """\ -tempvar x0 : felt = 2 -tempvar x1 : felt = 1 -tempvar x2 : felt = x1 / [ap - 2] -tempvar x3 : felt = x0 - x2 -tempvar x4 : felt = [ap - 4] / 3 -tempvar x5 : felt = x3 + x4 +tempvar x0: felt = 2; +tempvar x1: felt = 1; +tempvar x2: felt = x1 / [ap - 2]; +tempvar x3: felt = x0 - x2; +tempvar x4: felt = [ap - 4] / 3; +tempvar x5: felt = x3 + x4; """ ) assert res.format() == "x5" @@ -213,8 +213,8 @@ def test_process_compound_expressions(): for code_element in context.code_elements ) == """\ -tempvar x0 : felt = [ap - 0 - 1] * [ap - 0 - 1] -tempvar x1 : felt = [ap - 1 - 2] * [ap - 1 - 2] +tempvar x0: felt = [ap - 0 - 1] * [ap - 0 - 1]; +tempvar x1: felt = [ap - 1 - 2] * [ap - 1 - 2]; """ ) assert [x.format() for x in res] == [ @@ -228,54 +228,54 @@ def test_process_compound_expressions(): def test_compound_expressions(): code = """\ -assert [ap] = [ap + 1] * [ap + 2] -assert 5 = [[ap - 1]] -assert [[ap - 1]] = 5 -assert [ap - 2] = [[ap - 1] - 5] -assert [ap - 2] = [[ap - 1] + 999999] -assert [[ap + 5 + 5]] = [ap - 1] -assert [ap - 1] = [[[ap + 5 + 5]]] -assert [[ap - 1]] = [[ap - 2]] - -tempvar __fp__ = 100 -assert [fp] = fp + [fp + [fp]] - -let __fp__ = [ap - 1] + [ap - 1] -assert [fp] = fp + fp +assert [ap] = [ap + 1] * [ap + 2]; +assert 5 = [[ap - 1]]; +assert [[ap - 1]] = 5; +assert [ap - 2] = [[ap - 1] - 5]; +assert [ap - 2] = [[ap - 1] + 999999]; +assert [[ap + 5 + 5]] = [ap - 1]; +assert [ap - 1] = [[[ap + 5 + 5]]]; +assert [[ap - 1]] = [[ap - 2]]; + +tempvar __fp__ = 100; +assert [fp] = fp + [fp + [fp]]; + +let __fp__ = [ap - 1] + [ap - 1]; +assert [fp] = fp + fp; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = [ap + 1] * [ap + 2] +[ap] = [ap + 1] * [ap + 2]; -[ap] = [[ap + (-1)]]; ap++ -5 = [ap + (-1)] +[ap] = [[ap + (-1)]], ap++; +5 = [ap + (-1)]; -[ap] = 5; ap++ -[[ap + (-2)]] = [ap + (-1)] +[ap] = 5, ap++; +[[ap + (-2)]] = [ap + (-1)]; -[ap + (-2)] = [[ap + (-1)] + (-5)] +[ap + (-2)] = [[ap + (-1)] + (-5)]; -[ap] = [ap + (-1)] + 999999; ap++ -[ap + (-3)] = [[ap + (-1)]] +[ap] = [ap + (-1)] + 999999, ap++; +[ap + (-3)] = [[ap + (-1)]]; -[[ap + 10]] = [ap + (-1)] +[[ap + 10]] = [ap + (-1)]; -[ap] = [[ap + 10]]; ap++ -[ap + (-2)] = [[ap + (-1)]] +[ap] = [[ap + 10]], ap++; +[ap + (-2)] = [[ap + (-1)]]; -[ap] = [[ap + (-2)]]; ap++ -[[ap + (-2)]] = [ap + (-1)] +[ap] = [[ap + (-2)]], ap++; +[[ap + (-2)]] = [ap + (-1)]; -[ap] = 100; ap++ -[ap] = [ap + (-1)] + [fp]; ap++ -[ap] = [[ap + (-1)]]; ap++ -[fp] = [ap + (-3)] + [ap + (-1)] +[ap] = 100, ap++; +[ap] = [ap + (-1)] + [fp], ap++; +[ap] = [[ap + (-1)]], ap++; +[fp] = [ap + (-3)] + [ap + (-1)]; -[ap] = [ap + (-1)] + [ap + (-1)]; ap++ -[ap] = [ap + (-2)] + [ap + (-2)]; ap++ -[fp] = [ap + (-2)] + [ap + (-1)] +[ap] = [ap + (-1)] + [ap + (-1)], ap++; +[ap] = [ap + (-2)] + [ap + (-2)], ap++; +[fp] = [ap + (-2)] + [ap + (-1)]; """.replace( "\n\n", "\n" ) @@ -284,53 +284,53 @@ def test_compound_expressions(): def test_compound_expressions_long(): code = """\ -let x = [[ap - 1]] -let y = [fp] -let z = [ap + 100] -assert x + y * z + x / (-x - (y - z)) = x * x +let x = [[ap - 1]]; +let y = [fp]; +let z = [ap + 100]; +assert x + y * z + x / ((-x) - (y - z)) = x * x; """ program = preprocess_str(code=code, prime=PRIME) expected_result = """\ -[ap] = [[ap + (-1)]]; ap++ # Compute x. -[ap] = [fp] * [ap + 99]; ap++ # Compute y * z. -[ap] = [ap + (-2)] + [ap + (-1)]; ap++ # Compute x + y * z. -[ap] = [[ap + (-4)]]; ap++ # Compute x. -[ap] = [[ap + (-5)]]; ap++ # Compute x. -[ap] = [ap + (-1)] * (-1); ap++ # Compute -x. -[ap] = [fp] - [ap + 94]; ap++ # Compute y - z -[ap] = [ap + (-2)] - [ap + (-1)]; ap++ # Compute -x - (y - z). -[ap] = [ap + (-5)] / [ap + (-1)]; ap++ # Compute x / (-x - (y - z)). -[ap] = [[ap + (-10)]]; ap++ # Compute x. -[ap] = [[ap + (-11)]]; ap++ # Compute x. -[ap] = [ap + (-2)] * [ap + (-1)]; ap++ # Compute x * x. -[ap + (-10)] + [ap + (-4)] = [ap + (-1)] # Assert x + y * z + x / (-x - (y - z)) = x * x. +[ap] = [[ap + (-1)]], ap++; // Compute x. +[ap] = [fp] * [ap + 99], ap++; // Compute y * z. +[ap] = [ap + (-2)] + [ap + (-1)], ap++; // Compute x + y * z. +[ap] = [[ap + (-4)]], ap++; // Compute x. +[ap] = [[ap + (-5)]], ap++; // Compute x. +[ap] = [ap + (-1)] * (-1), ap++; // Compute -x. +[ap] = [fp] - [ap + 94], ap++; // Compute y - z +[ap] = [ap + (-2)] - [ap + (-1)], ap++; // Compute -x - (y - z). +[ap] = [ap + (-5)] / [ap + (-1)], ap++; // Compute x / (-x - (y - z)). +[ap] = [[ap + (-10)]], ap++; // Compute x. +[ap] = [[ap + (-11)]], ap++; // Compute x. +[ap] = [ap + (-2)] * [ap + (-1)], ap++; // Compute x * x. +[ap + (-10)] + [ap + (-4)] = [ap + (-1)]; // Assert x + y * z + x / (-x - (y - z)) = x * x. """ assert program.format() == strip_comments_and_linebreaks(expected_result) def test_compound_expressions_tempvars(): code = """\ -tempvar x = [ap - 1] * [ap - 1] + [ap - 1] * [ap - 2] -tempvar y = x + x -tempvar z = 5 + nondet %{ val %} * 15 + nondet %{ 1 %} +tempvar x = [ap - 1] * [ap - 1] + [ap - 1] * [ap - 2]; +tempvar y = x + x; +tempvar z = 5 + nondet %{ val %} * 15 + nondet %{ 1 %}; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = [ap + (-1)] * [ap + (-1)]; ap++ -[ap] = [ap + (-2)] * [ap + (-3)]; ap++ -[ap] = [ap + (-2)] + [ap + (-1)]; ap++ +[ap] = [ap + (-1)] * [ap + (-1)], ap++; +[ap] = [ap + (-2)] * [ap + (-3)], ap++; +[ap] = [ap + (-2)] + [ap + (-1)], ap++; -[ap] = [ap + (-1)] + [ap + (-1)]; ap++ +[ap] = [ap + (-1)] + [ap + (-1)], ap++; %{ memory[ap] = to_felt_or_relocatable(val) %} -ap += 1 -[ap] = [ap + (-1)] * 15; ap++ -[ap] = [ap + (-1)] + 5; ap++ +ap += 1; +[ap] = [ap + (-1)] * 15, ap++; +[ap] = [ap + (-1)] + 5, ap++; %{ memory[ap] = to_felt_or_relocatable(1) %} -ap += 1 -[ap] = [ap + (-2)] + [ap + (-1)]; ap++ +ap += 1; +[ap] = [ap + (-2)] + [ap + (-1)], ap++; """.replace( "\n\n", "\n" ) @@ -339,56 +339,56 @@ def test_compound_expressions_tempvars(): def test_compound_expressions_localvar(): code = """\ -func f(): - alloc_locals - local x - local y = x * x + [ap - 1] * [ap - 2] - local z = y + y - ret -end +func f() { + alloc_locals; + local x; + local y = x * x + [ap - 1] * [ap - 2]; + local z = y + y; + ret; +} """ program = preprocess_str(code=code, prime=PRIME) expected_result = """\ -ap += 3 +ap += 3; -[ap] = [fp] * [fp]; ap++ # x * x. -[ap] = [ap + (-2)] * [ap + (-3)]; ap++ # [ap - 1] * [ap - 2]. -[fp + 1] = [ap + (-2)] + [ap + (-1)] # x * x + [ap - 1] * [ap - 2]. +[ap] = [fp] * [fp], ap++; // x * x. +[ap] = [ap + (-2)] * [ap + (-3)], ap++; // [ap - 1] * [ap - 2]. +[fp + 1] = [ap + (-2)] + [ap + (-1)]; // x * x + [ap - 1] * [ap - 2]. -[fp + 2] = [fp + 1] + [fp + 1] # y + y. +[fp + 2] = [fp + 1] + [fp + 1]; // y + y. -ret +ret; """ assert program.format() == strip_comments_and_linebreaks(expected_result) def test_compound_expressions_args(): code = """\ -func foo(a, b, c, d) -> (x : felt, y : felt): - return (a + b, c * c + d) -end +func foo(a, b, c, d) -> (x: felt, y: felt) { + return (a + b, c * c + d); +} -tempvar x = 5 -foo(x + x, x + x * x, x, 3 * x + x * x) +tempvar x = 5; +foo(x + x, x + x * x, x, 3 * x + x * x); """ program = preprocess_str(code=code, prime=PRIME) expected_result = """\ -[ap] = [fp + (-4)] * [fp + (-4)]; ap++ # Compute c * c. -[ap] = [fp + (-6)] + [fp + (-5)]; ap++ # Push a + b. -[ap] = [ap + (-2)] + [fp + (-3)]; ap++ # Push c * c + d. -ret - -[ap] = 5; ap++ - -[ap] = [ap + (-1)] * [ap + (-1)]; ap++ # Compute x * x. -[ap] = 3; ap++ -[ap] = [ap + (-1)] * [ap + (-3)]; ap++ # Compute 3 * x. -[ap] = [ap + (-4)] * [ap + (-4)]; ap++ # Compute x * x. -[ap] = [ap + (-5)] + [ap + (-5)]; ap++ # Push x + x. -[ap] = [ap + (-6)] + [ap + (-5)]; ap++ # Push x + x * x. -[ap] = [ap + (-7)]; ap++ # Push x. -[ap] = [ap + (-5)] + [ap + (-4)]; ap++ # Push 3 * x + x * x. -call rel -15 +[ap] = [fp + (-4)] * [fp + (-4)], ap++; // Compute c * c. +[ap] = [fp + (-6)] + [fp + (-5)], ap++; // Push a + b. +[ap] = [ap + (-2)] + [fp + (-3)], ap++; // Push c * c + d. +ret; + +[ap] = 5, ap++; + +[ap] = [ap + (-1)] * [ap + (-1)], ap++; // Compute x * x. +[ap] = 3, ap++; +[ap] = [ap + (-1)] * [ap + (-3)], ap++; // Compute 3 * x. +[ap] = [ap + (-4)] * [ap + (-4)], ap++; // Compute x * x. +[ap] = [ap + (-5)] + [ap + (-5)], ap++; // Push x + x. +[ap] = [ap + (-6)] + [ap + (-5)], ap++; // Push x + x * x. +[ap] = [ap + (-7)], ap++; // Push x. +[ap] = [ap + (-5)] + [ap + (-4)], ap++; // Push 3 * x + x * x. +call rel -15; """ assert program.format() == strip_comments_and_linebreaks(expected_result) @@ -396,54 +396,54 @@ def test_compound_expressions_args(): def test_compound_expressions_failures(): verify_exception( """\ -assert [ap + [ap]] = [ap] +assert [ap + [ap]] = [ap]; """, """ file:?:?: ap may only be used in an expression of the form [ap + ]. -assert [ap + [ap]] = [ap] +assert [ap + [ap]] = [ap]; ^^ """, ) verify_exception( """\ -assert [[ap]] = ap +assert [[ap]] = ap; """, """ file:?:?: ap may only be used in an expression of the form [ap + ]. -assert [[ap]] = ap +assert [[ap]] = ap; ^^ """, ) verify_exception( """\ -assert [[fp]] = fp +assert [[fp]] = fp; """, """ file:?:?: Using the value of fp directly, requires defining a variable named __fp__. -assert [[fp]] = fp +assert [[fp]] = fp; ^^ """, ) verify_exception( """\ -assert [ap] = [ap + 32768] # Offset is out of bounds. +assert [ap] = [ap + 32768]; // Offset is out of bounds. """, """ file:?:?: ap may only be used in an expression of the form [ap + ]. -assert [ap] = [ap + 32768] # Offset is out of bounds. +assert [ap] = [ap + 32768]; // Offset is out of bounds. ^^ """, ) verify_exception( """\ -struct T: - member a : felt -end -assert 7 = cast(7, T*) +struct T { + a: felt, +} +assert 7 = cast(7, T*); """, """ file:?:?: Cannot compare 'felt' and 'test_scope.T*'. -assert 7 = cast(7, T*) -^********************^ +assert 7 = cast(7, T*); +^*********************^ """, ) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/dependency_graph.py b/src/starkware/cairo/lang/compiler/preprocessor/dependency_graph.py index 6f61758a..3a97a528 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/dependency_graph.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/dependency_graph.py @@ -63,9 +63,6 @@ def add_identifier( if self.current_function is not None: self.visited_identifiers.setdefault(self.current_function, []).append(canonical_name) - def visit_CodeElementMember(self, elm): - pass - def visit_ExprDot(self, expr: ExprDot): # We override the default visitor, since we must not visit expr.member. self.visit(expr.expr) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/dependency_graph_test.py b/src/starkware/cairo/lang/compiler/preprocessor/dependency_graph_test.py index 523a96a4..bfbdba1e 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/dependency_graph_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/dependency_graph_test.py @@ -36,71 +36,71 @@ def _extract_dependency_graph(codes: Dict[str, str]) -> DependencyGraphVisitor: def test_dependency_graph(): modules = { "module": """ -func func0() -> (res): - return (res=0) -end -func func1(): - return () -end -func func2(): - return () -end -func func3(): - return () -end +func func0() -> (res: felt) { + return (res=0); +} +func func1() { + return (); +} +func func2() { + return (); +} +func func3() { + return (); +} """, "__main__": """ from module import func1 as func1_alias -func foo(): - struct S: - member x : S* - member y : S* - end +func foo() { + struct S { + x: S*, + y: S*, + } - struct T: - member x : S* - end + struct T { + x: S*, + } - # Importing creates a dependency even if not used. + // Importing creates a dependency even if not used. from module import func0 as func0_alias, func2 - tempvar _tempvar = [ap] - const _const = [ap] - local _local = [ap] - let _reference = [fp] + 2 + tempvar _tempvar = [ap]; + const _const = [ap]; + local _local = [ap]; + let _reference = [fp] + 2; _label: - let _typed_reference : W = ns.myfunc(1, 2, 3) -end - -namespace ns: - func myfunc(): - myfunc() - func1_alias() - end - - call bar # This line will be ignored since it's outside of any function. -end - -struct W: - member x : felt -end - -func bar(): - const a = foo.S.x + 1 - jmp bar if foo.S.y * 2 != 0 - let w : W* = 0 - let w_x = w.x - foo.func0_alias() -end - -func main(): - jmp foo._label - call bar -end - -call bar # This line will be ignored since it's outside of any function. + let _typed_reference: W = ns.myfunc(1, 2, 3); +} + +namespace ns { + func myfunc() { + myfunc(); + func1_alias(); + } + + call bar; // This line will be ignored since it's outside of any function. +} + +struct W { + x: felt, +} + +func bar() { + const a = foo.S.x + 1; + jmp bar if foo.S.y * 2 != 0; + let w: W* = 0; + let w_x = w.x; + foo.func0_alias(); +} + +func main() { + jmp foo._label; + call bar; +} + +call bar; // This line will be ignored since it's outside of any function. """, "": """ from module import func2 diff --git a/src/starkware/cairo/lang/compiler/preprocessor/flow.py b/src/starkware/cairo/lang/compiler/preprocessor/flow.py index d9fcf468..87dccfee 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/flow.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/flow.py @@ -22,6 +22,7 @@ ) from starkware.cairo.lang.compiler.references import ApDeductionError, FlowTrackingError, Reference from starkware.cairo.lang.compiler.scoped_name import ScopedName, ScopedNameAsStr +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata class LostReferenceError(FlowTrackingError): @@ -132,7 +133,7 @@ class FlowTrackingDataActual(FlowTrackingData): ap_tracking: RegTrackingData # Mapping from full reference name to the Reference instance. reference_ids: Dict[ScopedName, int] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=mfields.Dict(keys=ScopedNameAsStr, values=mfields.Integer()) ), default_factory=dict, @@ -316,7 +317,7 @@ def get_ap_tracking(self) -> RegTrackingData: def add_flow_to_label(self, label_name: ScopedName, ap_change: RegChangeLike): """ Registers a flow from current location to a label, with some ap_change. - For example, after 'jmp label1 if [ap] != 0; ap++', we have a flow to label1 with ap_change + For example, after 'jmp label1 if [ap] != 0, ap++', we have a flow to label1 with ap_change of 1. """ ap_change = RegChange.from_expr(ap_change) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/identifier_aware_visitor.py b/src/starkware/cairo/lang/compiler/preprocessor/identifier_aware_visitor.py index 165205f4..dd7417e6 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/identifier_aware_visitor.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/identifier_aware_visitor.py @@ -5,15 +5,19 @@ CairoType, TypeCodeoffset, TypeFelt, + TypeFunction, + TypeIdentifier, TypePointer, TypeStruct, TypeTuple, ) from starkware.cairo.lang.compiler.ast.code_elements import CodeElementFunction +from starkware.cairo.lang.compiler.ast.rvalue import RvalueFuncCall from starkware.cairo.lang.compiler.ast.visitor import Visitor from starkware.cairo.lang.compiler.error_handling import Location from starkware.cairo.lang.compiler.identifier_definition import ( DefinitionError, + FunctionDefinition, FutureIdentifierDefinition, IdentifierDefinition, StructDefinition, @@ -23,7 +27,6 @@ from starkware.cairo.lang.compiler.identifier_utils import get_struct_definition from starkware.cairo.lang.compiler.preprocessor.preprocessor_error import PreprocessorError from starkware.cairo.lang.compiler.scoped_name import ScopedName -from starkware.python.utils import as_non_optional class IdentifierAwareVisitor(Visitor): @@ -35,8 +38,9 @@ def __init__( self, identifiers: Optional[IdentifierManager] = None, identifier_locations: Dict[ScopedName, Location] = None, + accessible_scopes: Optional[List[ScopedName]] = None, ): - super().__init__() + super().__init__(accessible_scopes=accessible_scopes) if identifiers is None: identifiers = IdentifierManager() if identifier_locations is None: @@ -143,7 +147,7 @@ def get_type_definition( def get_type_or_struct_definition_members( self, name: ScopedName, location: Optional[Location] - ) -> List[Tuple[str, CairoType]]: + ) -> List[Tuple[Optional[str], CairoType]]: """ Returns the members of the type definition (assuming it's a named tuple) or struct definition. @@ -153,10 +157,14 @@ def get_type_or_struct_definition_members( ) if isinstance(definition, TypeDefinition): - assert isinstance(definition.cairo_type, TypeTuple) + if not isinstance(definition.cairo_type, TypeTuple): + raise PreprocessorError( + "Only tuple types are currently supported.", + location=location, + ) return [ - (as_non_optional(member.name), self.resolve_type(member.typ)) + (member.name, self.resolve_type(member.typ)) for member in definition.cairo_type.members ] elif isinstance(definition, StructDefinition): @@ -189,9 +197,9 @@ def verify_possibly_future_struct( (FutureDefinition). For example when parsing: - struct S: - member a : S* - end + struct S { + a: S*, + } We have to lookup S before S is defined in the identifier manager. scoped_name and location are used if there is an error. @@ -211,19 +219,20 @@ def resolve_type(self, cairo_type: CairoType) -> CairoType: """ Resolves a CairoType instance to fully qualified name. """ - if isinstance(cairo_type, (TypeFelt, TypeCodeoffset)): + if isinstance(cairo_type, (TypeFelt, TypeCodeoffset, TypeStruct)): return cairo_type elif isinstance(cairo_type, TypePointer): return dataclasses.replace(cairo_type, pointee=self.resolve_type(cairo_type.pointee)) - elif isinstance(cairo_type, TypeStruct): - if cairo_type.is_fully_resolved: - return cairo_type + elif isinstance(cairo_type, TypeIdentifier): try: - result = self.identifiers.search(self.accessible_scopes, cairo_type.scope) + result = self.identifiers.search(self.accessible_scopes, cairo_type.name) result.assert_fully_parsed() if isinstance(result.identifier_definition, TypeDefinition): return self.resolve_type(result.identifier_definition.cairo_type) + if isinstance(result.identifier_definition, FunctionDefinition): + return TypeFunction(scope=result.get_canonical_name()) + if ( isinstance(result.identifier_definition, FutureIdentifierDefinition) and result.identifier_definition.identifier_type is TypeDefinition @@ -234,14 +243,13 @@ def resolve_type(self, cairo_type: CairoType) -> CairoType: self.verify_possibly_future_struct( identifier_definition=result.identifier_definition, - scoped_name=cairo_type.scope, + scoped_name=cairo_type.name, location=cairo_type.location, ) - return dataclasses.replace( - cairo_type, + return TypeStruct( scope=result.get_canonical_name(), - is_fully_resolved=True, + location=cairo_type.location, ) except IdentifierError as exc: raise PreprocessorError(str(exc), location=cairo_type.location) @@ -257,9 +265,9 @@ def resolve_type(self, cairo_type: CairoType) -> CairoType: else: raise NotImplementedError(f"Type {type(cairo_type).__name__} is not supported.") - def get_size_by_type_name(self, struct_name: ScopedName, location: Optional[Location]): + def get_size_by_type_name(self, type_name: ScopedName, location: Optional[Location]): res = self.get_identifier_definition( - name=struct_name, supported_types=(StructDefinition, TypeDefinition), location=location + name=type_name, supported_types=(StructDefinition, TypeDefinition), location=location ) assert isinstance(res, (StructDefinition, TypeDefinition)) if isinstance(res, StructDefinition): @@ -273,18 +281,17 @@ def get_size(self, cairo_type: CairoType): """ if isinstance(cairo_type, (TypeFelt, TypePointer, TypeCodeoffset)): return 1 + elif isinstance(cairo_type, TypeIdentifier): + return self.get_size_by_type_name( + type_name=cairo_type.name, location=cairo_type.location + ) elif isinstance(cairo_type, TypeStruct): - if cairo_type.is_fully_resolved: - try: - return get_struct_definition( - struct_name=cairo_type.scope, identifier_manager=self.identifiers - ).size - except DefinitionError as exc: - raise PreprocessorError(str(exc), location=cairo_type.location) - else: - return self.get_size_by_type_name( - struct_name=cairo_type.scope, location=cairo_type.location - ) + try: + return get_struct_definition( + struct_name=cairo_type.scope, identifier_manager=self.identifiers + ).size + except DefinitionError as exc: + raise PreprocessorError(str(exc), location=cairo_type.location) elif isinstance(cairo_type, TypeTuple): return sum(self.get_size(member_type) for member_type in cairo_type.types) else: @@ -300,6 +307,16 @@ def inside_a_struct(self) -> bool: return parent.element_type == "struct" + def get_return_type(self, func_call: RvalueFuncCall) -> CairoType: + """ + Returns the return type of 'func_call'. + """ + return self.get_type_definition( + name=ScopedName.from_string(func_call.func_ident.name) + + CodeElementFunction.RETURN_SCOPE, + location=func_call.location, + ).cairo_type + def verify_tuple_type(cairo_type: TypeTuple): """ diff --git a/src/starkware/cairo/lang/compiler/preprocessor/identifier_collector.py b/src/starkware/cairo/lang/compiler/preprocessor/identifier_collector.py index e7ced017..0ad71a80 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/identifier_collector.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/identifier_collector.py @@ -1,6 +1,7 @@ -from typing import Dict, Optional, Type +from typing import Dict, Optional, Type, Union from starkware.cairo.lang.compiler.ast.arguments import IdentifierList +from starkware.cairo.lang.compiler.ast.cairo_types import CairoType from starkware.cairo.lang.compiler.ast.code_elements import ( CodeBlock, CodeElement, @@ -139,13 +140,13 @@ def visit_CodeElementFunction(self, elm: CodeElementFunction): rets_scope = function_scope + CodeElementFunction.RETURN_SCOPE def handle_definition( - identifier_list: Optional[IdentifierList], + defintion: Optional[Union[IdentifierList, CairoType]], name: ScopedName, identifier_type: Type[IdentifierDefinition], ): location = elm.identifier.location - if identifier_list is not None: - location = identifier_list.location + if defintion is not None: + location = defintion.location self.add_future_identifier( name=name, identifier_type=identifier_type, location=location @@ -155,7 +156,7 @@ def handle_function_arguments( identifier_list: Optional[IdentifierList], struct_name: ScopedName ): handle_definition( - identifier_list=identifier_list, + defintion=identifier_list, name=struct_name, identifier_type=StructDefinition, ) @@ -183,23 +184,21 @@ def handle_function_arguments( identifier_list=elm.implicit_arguments, struct_name=implicit_args_scope ) - handle_definition( - identifier_list=elm.returns, name=rets_scope, identifier_type=TypeDefinition - ) + handle_definition(defintion=elm.returns, name=rets_scope, identifier_type=TypeDefinition) # Make sure there is no name collision. if elm.implicit_arguments is not None: implicit_arg_names = {arg_id.name for arg_id in elm.implicit_arguments.identifiers} - arg_and_return_identifiers = list(elm.arguments.identifiers) - if elm.returns is not None: - arg_and_return_identifiers += elm.returns.identifiers + arg_and_return_named_locations = [ + (typed_identifier.name, typed_identifier.identifier.location) + for typed_identifier in elm.arguments.identifiers + ] - for arg_id in arg_and_return_identifiers: - if arg_id.name in implicit_arg_names: + for arg_name, arg_location in arg_and_return_named_locations: + if arg_name in implicit_arg_names: raise PreprocessorError( - "Arguments and return values cannot have the same name of an implicit " - "argument.", - location=arg_id.location, + "An argument cannot have the same name as an implicit argument.", + location=arg_location, ) # Add SIZEOF_LOCALS for current block at identifier definition location if available. diff --git a/src/starkware/cairo/lang/compiler/preprocessor/identifier_collector_test.py b/src/starkware/cairo/lang/compiler/preprocessor/identifier_collector_test.py index 207a18cc..45e455c8 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/identifier_collector_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/identifier_collector_test.py @@ -29,12 +29,13 @@ def _extract_identifiers(code): def test_collect_single_binds(): code = """ -tempvar a = [ap] -const b = [ap] -local c = [ap] -let d = [fp] + 2 +tempvar a = [ap]; +const b = [ap]; +local c = [ap]; +let d = [fp] + 2; + f: -let g : H = f(1, 2, 3) +let g: H = f(1, 2, 3); """ assert set(_extract_identifiers(code)) == { ("a", ReferenceDefinition), @@ -48,10 +49,10 @@ def test_collect_single_binds(): def test_collect_multi_binds(): code = """ -func a(b, c) -> (d): - [ap] = [ap] -end -let (e, f) = g() +func a(b, c) -> (d: felt) { + [ap] = [ap]; +} +let (e, f) = g(); """ assert set(_extract_identifiers(code)) == { ("a", FunctionDefinition), @@ -68,12 +69,12 @@ def test_collect_multi_binds(): def test_nested_funcs(): code = """ -func foo{z}(x): - local a - func bar(y): - tempvar b = [ap] - end -end +func foo{z}(x) { + local a; + func bar(y) { + tempvar b = [ap]; + } +} """ assert set(_extract_identifiers(code)) == { ("foo", FunctionDefinition), @@ -96,8 +97,8 @@ def test_nested_funcs(): def test_redefinition(): code = """ -tempvar name = [ap] -local name = [ap] +tempvar name = [ap]; +local name = [ap]; """ assert _extract_identifiers(code) == [ ("name", ReferenceDefinition), @@ -108,25 +109,25 @@ def test_redefinition_failures(): verify_exception( """ name: -local name = [ap] +local name = [ap]; """, """ file:?:?: Redefinition of 'test_scope.name'. -local name = [ap] +local name = [ap]; ^**^ """, ) verify_exception( """ -func foo(): -end +func foo() { +} -func foo(): -end +func foo() { +} """, """ file:?:?: Redefinition of 'test_scope.foo'. -func foo(): +func foo() { ^*^ """, ) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/if_labels_test.py b/src/starkware/cairo/lang/compiler/preprocessor/if_labels_test.py index bb5c8d3b..7eb99c62 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/if_labels_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/if_labels_test.py @@ -4,47 +4,47 @@ def test_if_labels_are_set(): program = preprocess_str( code=""" -namespace B: - func foo(x, y) -> (res : felt): - if x == 0: - if y == 0: - return (res=0) - else: - return (res=1) - end - else: - if y == 0: - return (res=2) - else: - return (res=3) - end - end - end -end -func main(): - B.foo(1, 2) - ret -end +namespace B { + func foo(x, y) -> (res: felt) { + if (x == 0) { + if (y == 0) { + return (res=0); + } else { + return (res=1); + } + } else { + if (y == 0) { + return (res=2); + } else { + return (res=3); + } + } + } +} +func main() { + B.foo(1, 2); + ret; +} """, prime=PRIME, ) assert ( program.format() == """\ -jmp rel 10 if [fp + (-4)] != 0 -jmp rel 5 if [fp + (-3)] != 0 -[ap] = 0; ap++ -ret -[ap] = 1; ap++ -ret -jmp rel 5 if [fp + (-3)] != 0 -[ap] = 2; ap++ -ret -[ap] = 3; ap++ -ret -[ap] = 1; ap++ -[ap] = 2; ap++ -call rel -22 -ret +jmp rel 10 if [fp + (-4)] != 0; +jmp rel 5 if [fp + (-3)] != 0; +[ap] = 0, ap++; +ret; +[ap] = 1, ap++; +ret; +jmp rel 5 if [fp + (-3)] != 0; +[ap] = 2, ap++; +ret; +[ap] = 3, ap++; +ret; +[ap] = 1, ap++; +[ap] = 2, ap++; +call rel -22; +ret; """ ) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/local_variables.py b/src/starkware/cairo/lang/compiler/preprocessor/local_variables.py index 2a639711..fff69135 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/local_variables.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/local_variables.py @@ -168,10 +168,10 @@ def visit_CodeElementLocalVariable(self, elm: CodeElementLocalVariable) -> List[ def visit_CodeElementUnpackBinding(self, elm: CodeElementUnpackBinding): """ Replaces - let (local a : T, b) = foo() + let (local a: T, b) = foo(); with - let (local a : T , b) = foo() - local a : T = a + let (local a: T , b) = foo(); + local a: T = a; """ result = [elm] diff --git a/src/starkware/cairo/lang/compiler/preprocessor/local_variables_test.py b/src/starkware/cairo/lang/compiler/preprocessor/local_variables_test.py index 56ca08d0..cc167e47 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/local_variables_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/local_variables_test.py @@ -8,158 +8,158 @@ def test_local_variable(): code = """\ -struct MyStruct: - member a : felt - member b : felt -end +struct MyStruct { + a: felt, + b: felt, +} -func main(): - ap += 5 + SIZEOF_LOCALS - local x - local y : MyStruct - local z = x * y.a - x = y.a - y.b = z - local w : MyStruct* = cast(17, MyStruct*) - # Check implicit cast from MyStruct* to felt*. - local w_as_felt_ptr : felt* = w - z = w.b - ret -end +func main() { + ap += 5 + SIZEOF_LOCALS; + local x; + local y: MyStruct; + local z = x * y.a; + x = y.a; + y.b = z; + local w: MyStruct* = cast(17, MyStruct*); + // Check implicit cast from MyStruct* to felt*. + local w_as_felt_ptr: felt* = w; + z = w.b; + ret; +} -func no_locals(): - ap += SIZEOF_LOCALS - ret -end +func no_locals() { + ap += SIZEOF_LOCALS; + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 11 -[fp + 3] = [fp] * [fp + 1] -[fp] = [fp + 1] -[fp + 2] = [fp + 3] -[fp + 4] = 17 -[fp + 5] = [fp + 4] -[fp + 3] = [[fp + 4] + 1] -ret -ap += 0 -ret +ap += 11; +[fp + 3] = [fp] * [fp + 1]; +[fp] = [fp + 1]; +[fp + 2] = [fp + 3]; +[fp + 4] = 17; +[fp + 5] = [fp + 4]; +[fp + 3] = [[fp + 4] + 1]; +ret; +ap += 0; +ret; """ ) def test_local_variable_unpack_binding(): code = """\ -struct MyStruct: - member a : felt - member b : felt -end +struct MyStruct { + a: felt, + b: felt, +} -func foo() -> (x : MyStruct*, y : MyStruct, z : felt): - ret -end +func foo() -> (x: MyStruct*, y: MyStruct, z: felt) { + ret; +} -func main(): - alloc_locals - let (local x, y, local z) = foo() - x.b = z - y.a = z - y.b = z - z = z - ret -end +func main() { + alloc_locals; + let (local x, y, local z) = foo(); + x.b = z; + y.a = z; + y.b = z; + z = z; + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ret -ap += 2 -call rel -3 -[fp] = [ap + (-4)] -[fp + 1] = [ap + (-1)] -[[fp] + 1] = [fp + 1] -[ap + (-3)] = [fp + 1] -[ap + (-2)] = [fp + 1] -[fp + 1] = [fp + 1] -ret +ret; +ap += 2; +call rel -3; +[fp] = [ap + (-4)]; +[fp + 1] = [ap + (-1)]; +[[fp] + 1] = [fp + 1]; +[ap + (-3)] = [fp + 1]; +[ap + (-2)] = [fp + 1]; +[fp + 1] = [fp + 1]; +ret; """ ) def test_local_rebinding(): code = """\ -func main(): - alloc_locals - local x = 5 - local x = x * x - local x = x + x - local x = x * x - ret -end +func main() { + alloc_locals; + local x = 5; + local x = x * x; + local x = x + x; + local x = x * x; + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 4 -[fp] = 5 -[fp + 1] = [fp] * [fp] -[fp + 2] = [fp + 1] + [fp + 1] -[fp + 3] = [fp + 2] * [fp + 2] -ret +ap += 4; +[fp] = 5; +[fp + 1] = [fp] * [fp]; +[fp + 2] = [fp + 1] + [fp + 1]; +[fp + 3] = [fp + 2] * [fp + 2]; +ret; """ ) def test_n_locals_used_in_static_assert(): code = """\ -func main(): - static_assert 3 == SIZEOF_LOCALS + 2 - local x - ret -end +func main() { + static_assert 3 == SIZEOF_LOCALS + 2; + local x; + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ret +ret; """ ) def test_inner_scopes_local_variables(): code = """\ -func main(): - alloc_locals +func main() { + alloc_locals; - if 1 == 1: - local a - end + if (1 == 1) { + local a; + } - with_attr error_message("test"): - local b - end + with_attr error_message("test") { + local b; + } - let x = 0 - with x: - local c - end + let x = 0; + with x { + local c; + } - return () -end + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 3 -[ap] = 0; ap++ -jmp rel 2 if [ap + (-1)] != 0 -ret +ap += 3; +[ap] = 0, ap++; +jmp rel 2 if [ap + (-1)] != 0; +ret; """ ) @@ -167,85 +167,85 @@ def test_inner_scopes_local_variables(): def test_local_variable_failures(): verify_exception( """ -func main(SIZEOF_LOCALS): - static_assert SIZEOF_LOCALS == SIZEOF_LOCALS - local x -end +func main(SIZEOF_LOCALS) { + static_assert SIZEOF_LOCALS == SIZEOF_LOCALS; + local x; +} """, """ file:?:?: The name 'SIZEOF_LOCALS' is reserved and cannot be used as an argument name. -func main(SIZEOF_LOCALS): +func main(SIZEOF_LOCALS) { ^***********^ """, ) verify_exception( """ -func main(): - local x -end +func main() { + local x; +} """, """ file:?:?: A function with local variables must use alloc_locals. - local x - ^*****^ + local x; + ^******^ """, ) verify_exception( """ -func main(): - alloc_locals - local x = x + x -end +func main() { + alloc_locals; + local x = x + x; +} """, """ file:?:?: Identifier 'x' referenced before definition. - local x = x + x + local x = x + x; ^ """, ) for inst in ["tempvar a = 0", "ret", "ap += [ap]"]: verify_exception( f""" -func main(): - {inst} - alloc_locals -end +func main() {{ + {inst}; + alloc_locals; +}} """, """ file:?:?: alloc_locals must be used before any instruction that changes the ap register. - alloc_locals - ^**********^ + alloc_locals; + ^***********^ """, ) verify_exception( - f""" -alloc_locals + """ +alloc_locals; """, """ file:?:?: alloc_locals cannot be used outside of a function. -alloc_locals -^**********^ +alloc_locals; +^***********^ """, ) def test_local_variable_type_failures(): verify_exception( - f""" -struct T: - member a : felt -end + """ +struct T { + a: felt, +} -func main(): - alloc_locals - local x : T* = [ap] - ret -end +func main() { + alloc_locals; + local x: T* = [ap]; + ret; +} """, """ file:?:?: Cannot cast 'felt' to 'test_scope.T*'. - local x : T* = [ap] - ^**^ + local x: T* = [ap]; + ^**^ """, exc_type=CairoTypeError, ) @@ -254,13 +254,13 @@ def test_local_variable_type_failures(): def test_local_variable_modifier_failures(): verify_exception( """ -func main(): - local local x -end +func main() { + local local x; +} """, """ file:?:?: Unexpected modifier 'local'. - local local x + local local x; ^***^ """, ) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/memento_test.py b/src/starkware/cairo/lang/compiler/preprocessor/memento_test.py index 0061d670..d9593e3e 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/memento_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/memento_test.py @@ -135,31 +135,31 @@ def strip_identifiers(identifiers: IdentifierManager): def test_preprocessor_checkpoint(): code0 = """\ - struct A: - member a : felt - end - func foo0(a : A) -> (res : felt): - return (res=1) - end - """ +struct A { + a: felt, +} +func foo0(a: A) -> (res: felt) { + return (res=1); +} +""" code1 = """\ - struct B: - member b : felt - end - func foo1(b : B) -> (res : felt): - with_attr attr: - return (res=2) - end - end - """ +struct B { + b: felt, +} +func foo1(b: B) -> (res: felt) { + with_attr attr { + return (res=2); + } +} +""" code2 = """\ - struct C: - member c : felt - end - func foo2(c : C) -> (res : felt): - return (res=3) - end - """ +struct C { + c: felt, +} +func foo2(c: C) -> (res: felt) { + return (res=3); +} +""" identifiers = get_identifiers([code0, code1, code2]) preprocessor = Preprocessor(prime=PRIME, identifiers=identifiers, builtins=[]) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/pass_manager.py b/src/starkware/cairo/lang/compiler/preprocessor/pass_manager.py index d761315e..1988e333 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/pass_manager.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/pass_manager.py @@ -1,6 +1,6 @@ import dataclasses from abc import ABC, abstractmethod -from typing import Dict, List, Optional, Set, Tuple +from typing import Any, Dict, List, Optional, Set, Tuple, Type, TypeVar from starkware.cairo.lang.compiler.ast.module import CairoModule from starkware.cairo.lang.compiler.error_handling import Location @@ -9,6 +9,8 @@ from starkware.cairo.lang.compiler.scoped_name import ScopedName from starkware.cairo.lang.compiler.unique_name_provider import UniqueNameProvider +T = TypeVar("T") + @dataclasses.dataclass class PassManagerContext: @@ -29,6 +31,15 @@ class PassManagerContext: # If the unused function optimization is enabled, only reachable functions will be compiled. functions_to_compile: Optional[Set[ScopedName]] = None unique_names: UniqueNameProvider = dataclasses.field(default_factory=UniqueNameProvider) + # A general purpose map of resources that need to be shared between stages. + # resources[T] should be of type T. + # Use get_resource() instead of accessing this dictionary directly. + _resources: Dict[Type, Any] = dataclasses.field(default_factory=dict) + + def get_resource(self, typ: Type[T]) -> T: + if typ not in self._resources: + self._resources[typ] = typ() + return self._resources[typ] class Stage(ABC): diff --git a/src/starkware/cairo/lang/compiler/preprocessor/preprocessor.py b/src/starkware/cairo/lang/compiler/preprocessor/preprocessor.py index 32df239b..bbac267f 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/preprocessor.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/preprocessor.py @@ -3,7 +3,7 @@ from contextlib import contextmanager from dataclasses import field from enum import Enum, auto -from typing import DefaultDict, Dict, List, Optional, Set, Tuple, Type, Union, cast +from typing import DefaultDict, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast import marshmallow.fields as mfields @@ -14,6 +14,7 @@ CastType, TypeCodeoffset, TypeFelt, + TypeIdentifier, TypePointer, TypeStruct, TypeTuple, @@ -35,7 +36,6 @@ CodeElementInstruction, CodeElementLabel, CodeElementLocalVariable, - CodeElementMember, CodeElementReference, CodeElementReturn, CodeElementReturnValueReference, @@ -104,7 +104,7 @@ get_struct_definition, get_type_definition, ) -from starkware.cairo.lang.compiler.injector import inject_code_elements +from starkware.cairo.lang.compiler.injector import InjectionError, inject_code_elements from starkware.cairo.lang.compiler.instruction import Register from starkware.cairo.lang.compiler.instruction_builder import ( InstructionBuilderError, @@ -161,6 +161,7 @@ from starkware.cairo.lang.compiler.type_casts import CairoTypeError, check_cast from starkware.cairo.lang.compiler.type_system_visitor import get_expr_addr, simplify_type_system from starkware.python.utils import safe_zip +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata from starkware.starkware_utils.validated_dataclass import ValidatedDataclass # Indicates that the compiler should be able to deduce the change in the ap register for this @@ -186,6 +187,11 @@ def visit_ExprNewOperator(self, expr: ExprNewOperator): "The use of 'new' in reference expressions is not allowed.", location=expr.location ) + def visit_ExprFuncCall(self, expr: ExprFuncCall): + raise PreprocessorError( + "Function calls are not allowed inside reference expressions.", location=expr.location + ) + class ReferenceTrial: """ @@ -221,13 +227,14 @@ class PreprocessedInstruction: def format(self, with_locations: bool = False) -> str: location_str = ( - f" # {self.instruction.location.topmost_location()}." + f" // {self.instruction.location.topmost_location()}." if with_locations and self.instruction.location is not None else "" ) return ( "".join(hint.format(get_max_line_length()) + "\n" for hint, _ in self.hints) + self.instruction.format() + + ";" + location_str ) @@ -244,7 +251,9 @@ class AttributeScope(AttributeBase, ValidatedDataclass): end_pc: int flow_tracking_data: Optional[FlowTrackingDataActual] = field(metadata=dict(load_default=None)) accessible_scopes: List[ScopedName] = field( - metadata=dict(marshmallow_field=mfields.List(ScopedNameAsStr, load_default=list)), + metadata=additional_metadata( + marshmallow_field=mfields.List(ScopedNameAsStr, load_default=list) + ), ) @@ -391,7 +400,7 @@ def __init__( self.attributes: List[AttributeScope] = [] self.auxiliary_info = ( - auxiliary_info_cls.create(prime) if auxiliary_info_cls is not None else None + auxiliary_info_cls.create(prime, self) if auxiliary_info_cls is not None else None ) # Current code element that is being processed. @@ -658,6 +667,8 @@ def visit_CodeElementFunction(self, elm: CodeElementFunction): start_pc=self.current_pc, implicit_args_struct=implicit_args_struct, args_struct=args_struct, + ret_names=[] if elm.returns is None else ["ret"], + ret_types=[] if elm.returns is None else [self.resolve_type(elm.returns)], ) # Process code_elements. @@ -688,7 +699,10 @@ def visit_CodeElementFunction(self, elm: CodeElementFunction): self.function_metadata[new_scope].total_ap_change = RegChangeUnknown() if self.auxiliary_info is not None: - self.auxiliary_info.finish_function_info(end_pc=self.current_pc) + self.auxiliary_info.finish_function_info( + end_pc=self.current_pc, + total_ap_change=self.function_metadata[new_scope].total_ap_change, + ) def visit_function_body_with_retries(self, code_block: CodeBlock, location: Optional[Location]): """ @@ -740,9 +754,14 @@ def visit_function_body_with_retries(self, code_block: CodeBlock, location: Opti memento = None # Fix revocations. - code_block = self.fix_reference_revocations( - code_block=code_block, reference_trial=reference_trial - ) + try: + code_block = self.fix_reference_revocations( + code_block=code_block, reference_trial=reference_trial + ) + except InjectionError: + # Injection error may be raised when new code elements were created during + # processing the original AST. + raise reference_trial.exception finally: if memento is not None: assert self is memento.apply(preprocessor) @@ -997,19 +1016,7 @@ def visit_CodeElementConst(self, elm: CodeElementConst): ) if self.auxiliary_info is not None: - self.auxiliary_info.add_const(name, val.val) - - def visit_CodeElementMember(self, elm: CodeElementMember): - self.check_no_hints("Hints before member definitions are not allowed.") - - if self.inside_a_struct(): - # Was already handled by the struct collector. - return - - raise PreprocessorError( - "The member keyword may only be used inside a struct.", - location=elm.typed_identifier.location, - ) + self.auxiliary_info.add_const(name, elm.expr, val.val) def visit_CodeElementReference(self, elm: CodeElementReference): name = self.current_scope + elm.typed_identifier.identifier.name @@ -1038,6 +1045,14 @@ def visit_CodeElementReference(self, elm: CodeElementReference): location = val.location + if self.auxiliary_info is not None: + self.auxiliary_info.add_reference( + identifier=elm.typed_identifier, + resolved_type=dst_type, + expr=elm.expr, + identifier_loc=elm.typed_identifier.location, + ) + # At this point 'val' is a simplified typeless expression and we need 'ref_expr' # to include a cast to the correct type. # We insert the cast at the correct location according to the outermost expression in 'val'. @@ -1064,9 +1079,6 @@ def visit_CodeElementReference(self, elm: CodeElementReference): location=elm.typed_identifier.location, ) - if self.auxiliary_info is not None: - self.auxiliary_info.add_reference(name, elm.expr, elm.typed_identifier.location) - def visit_CodeElementLocalVariable(self, elm: CodeElementLocalVariable): raise PreprocessorError( "Local variables are not supported outside of functions.", location=elm.location @@ -1132,7 +1144,7 @@ def visit_CodeElementTemporaryVariable(self, elm: CodeElementTemporaryVariable): if self.auxiliary_info is not None: self.auxiliary_info.start_temp_var( - self.current_scope + elm.typed_identifier.identifier.name, + elm.typed_identifier, elm.expr, elm.typed_identifier.location, ) @@ -1212,7 +1224,7 @@ def visit_CodeElementTemporaryVariable(self, elm: CodeElementTemporaryVariable): ) if self.auxiliary_info is not None: - self.auxiliary_info.finish_temp_var() + self.auxiliary_info.finish_temp_var(dest_type) def visit_CodeElementCompoundAssertEq(self, instruction: CodeElementCompoundAssertEq): expr_a, expr_type_a = self.simplify_expr(instruction.a) @@ -1224,7 +1236,9 @@ def visit_CodeElementCompoundAssertEq(self, instruction: CodeElementCompoundAsse ) if self.auxiliary_info is not None: - self.auxiliary_info.start_compound_assert_eq(lhs=instruction.a, rhs=instruction.b) + self.auxiliary_info.start_compound_assert_eq( + lhs=instruction.a, rhs=instruction.b, resolved_type=expr_type_a + ) dst_exprs = self.simplified_expr_to_felt_expr_list(expr=expr_a, expr_type=expr_type_a) src_exprs = self.simplified_expr_to_felt_expr_list(expr=expr_b, expr_type=expr_type_b) @@ -1303,20 +1317,20 @@ def get_ap_minus_n(expr: Expression) -> Optional[int]: return exprs[prefix_size:] def process_expr_assignment_list( - self, exprs: List[ExprAssignment], def_name: ScopedName, location: Optional[Location] + self, + exprs: List[ExprAssignment], + members: Sequence[Tuple[Optional[str], CairoType]], + location: Optional[Location], ) -> List[Expression]: """ - Returns the expressions for an argument list. + Returns the expressions that assign 'exprs' to 'members' Used both for function call and a return instruction. - Verifies the correctness of expr assignment with respect to the expected struct. + Verifies the correctness of expr assignment with respect to the members. exprs - list of ExprAssignment objects to process. - def_name - ScopedName of the struct/type against which the expr list is verified. + members - A sequence of members against which the expr list is verified. location - location to attach to errors if no finer location is relevant. """ - - members = self.get_type_or_struct_definition_members(name=def_name, location=location) - n_members = len(members) # Make sure we have the correct number of expressions. if len(exprs) != n_members: @@ -1338,8 +1352,12 @@ def process_expr_assignment_list( reached_named = True name = expr_assignment.identifier.name if name != member_name: + if member_name is None: + error_msg = f"Expected unnamed argument, found: '{name}'." + else: + error_msg = f"Expected named argument: '{member_name}', found: '{name}'." raise PreprocessorError( - f"Expected named argument: '{member_name}', found: '{name}'.", + error_msg, location=expr_assignment.identifier.location, ) @@ -1488,7 +1506,7 @@ def push_arguments( self, arguments: List[ExprAssignment], implicit_args: Optional[List[Optional[ExprIdentifier]]], - def_name: ScopedName, + members: Sequence[Tuple[Optional[str], CairoType]], implicit_args_struct_name: ScopedName, location: Optional[Location], ): @@ -1496,20 +1514,33 @@ def push_arguments( Generates instructions to push all arguments (including the implicit arguments) onto the stack. Used both for function call and a return instruction. - Verifies the correctness of expr assignment with respect to the expected struct. + Verifies the correctness of expr assignment with respect to the 'members' and + 'implicit_args_struct_name'. In more detail: translates a list of expressions to a set of instructions evaluating the expressions and storing the values to memory, starting from address 'ap'. arguments - list of ExprAssignment objects to process. implicit_args - list of implicit argument bindings. - def_name - ScopedName of the struct/type against which the expr list is verified. - implicit_args_struct_name - Similar to def_name, for the implicit arguments. + members - A sequence of members against which the expr list is verified. + implicit_args_struct_name - ScopedName of the the implicit arguments struct. location - location to attach to errors if no finer location is relevant. """ args_expressions = self.process_expr_assignment_list( - exprs=arguments, def_name=def_name, location=location + exprs=arguments, members=members, location=location + ) + + # Note that it is important to process the arguments before the implicit arguments + # as the implicit arguments might be updated during the processing of the arguments. + args_expressions = process_compound_expressions( + exprs=args_expressions, + simplicity=SimplicityLevel.OPERATION, + context=self._compound_expression_context, ) + # args_expressions might reference tempvars so they need to be simplified before they can be + # passed to 'push_compound_expressions'. + args_expressions = [self.simplify_expr_as_felt(expr) for expr in args_expressions] + implicit_args_expressions = self.process_implicit_arguments( implicit_args=implicit_args, implicit_args_struct_name=implicit_args_struct_name, @@ -1530,10 +1561,14 @@ def visit_CodeElementReturn(self, elm: CodeElementReturn): if self.auxiliary_info is not None: self.auxiliary_info.start_return() + return_type_definition = self.get_type_definition( + name=CodeElementFunction.RETURN_SCOPE, + location=elm.location, + ) self.push_arguments( - arguments=cast(List[ExprAssignment], elm.exprs), + arguments=[ExprAssignment(identifier=None, expr=elm.expr, location=elm.location)], implicit_args=None, - def_name=CodeElementFunction.RETURN_SCOPE, + members=[(None, return_type_definition.cairo_type)], implicit_args_struct_name=CodeElementFunction.IMPLICIT_ARGUMENT_SCOPE, location=elm.location, ) @@ -1543,7 +1578,7 @@ def visit_CodeElementReturn(self, elm: CodeElementReturn): self.visit(code_elm_ret) if self.auxiliary_info is not None: - self.auxiliary_info.finish_return(exprs=elm.exprs) + self.auxiliary_info.finish_return(exprs=[elm.expr]) def check_tail_call_cast( self, @@ -1577,20 +1612,14 @@ def visit_CodeElementTailCall(self, elm: CodeElementTailCall): # Visit function call before type check to get better error message. self.visit(CodeElementFuncCall(func_call=elm.func_call)) - func_name = elm.func_call.func_ident.name - - src_type_def = self.get_type_definition( - name=ScopedName.from_string(func_name) + CodeElementFunction.RETURN_SCOPE, - location=elm.location, - ) - dest_type_def = get_type_definition( name=self.current_scope + CodeElementFunction.RETURN_SCOPE, identifier_manager=self.identifiers, ) + func_name = elm.func_call.func_ident.name if not self.check_tail_call_cast( - src_type=src_type_def.cairo_type, + src_type=self.get_return_type(func_call=elm.func_call), dest_type=dest_type_def.cairo_type, location=elm.location, ): @@ -1654,7 +1683,7 @@ def add_implicit_return_references( name=called_function + CodeElementFunction.IMPLICIT_ARGUMENT_SCOPE, location=location ) return_size = self.get_size_by_type_name( - struct_name=called_function + CodeElementFunction.RETURN_SCOPE, location=location + type_name=called_function + CodeElementFunction.RETURN_SCOPE, location=location ) assert len(implicit_args_struct.members) == len(implicit_args) @@ -1737,7 +1766,10 @@ def visit_CodeElementFuncCall(self, elm: CodeElementFuncCall): self.push_arguments( arguments=cast(List[ExprAssignment], elm.func_call.arguments.args), implicit_args=processed_implicit_args, - def_name=called_function + CodeElementFunction.ARGUMENT_SCOPE, + members=self.get_type_or_struct_definition_members( + name=called_function + CodeElementFunction.ARGUMENT_SCOPE, + location=elm.func_call.arguments.location, + ), implicit_args_struct_name=called_function + CodeElementFunction.IMPLICIT_ARGUMENT_SCOPE, location=elm.func_call.location, ) @@ -1823,10 +1855,8 @@ def visit_CodeElementReturnValueReference(self, elm: CodeElementReturnValueRefer expr_type = elm.typed_identifier.expr_type if expr_type is None: if func_ident is not None: - expr_type = TypeStruct( - scope=ScopedName.from_string(func_ident.name) - + CodeElementFunction.RETURN_SCOPE, - is_fully_resolved=False, + expr_type = TypeIdentifier( + name=ScopedName.from_string(func_ident.name) + CodeElementFunction.RETURN_SCOPE, location=func_ident.location, ) else: @@ -1855,15 +1885,26 @@ def get_unpacking_type(self, elm: CodeElementUnpackBinding) -> TypeTuple: """ if not isinstance(elm.rvalue, RvalueFuncCall): raise PreprocessorError( - f"Cannot unpack {elm.rvalue.format()}.", location=elm.rvalue.location + "Unpack binding is currently only supported for function calls. " + f"Got: {elm.rvalue.format()}.", + location=elm.rvalue.location, ) - func_ident = elm.rvalue.func_ident - return_type = self.get_type_definition( - name=ScopedName.from_string(func_ident.name) + CodeElementFunction.RETURN_SCOPE, - location=func_ident.location, - ).cairo_type - assert isinstance(return_type, TypeTuple) + return_type = self.get_return_type(func_call=elm.rvalue) + if not isinstance(return_type, TypeTuple): + notes = [] + + suggestion_ast = self.get_suggestion_for_wrong_unpacking(elm=elm) + if suggestion_ast is not None: + suggestion_txt = suggestion_ast.format(get_max_line_length()) + notes.append(f"Did you mean:\n{suggestion_txt}") + + raise PreprocessorError( + f"Cannot unpack the return value of '{elm.rvalue.func_ident.format()}'. " + "The return type is not a tuple.", + location=elm.rvalue.location, + notes=notes, + ) expected_len = len(return_type.members) unpacking_identifiers = elm.unpacking_list.identifiers @@ -1877,6 +1918,28 @@ def get_unpacking_type(self, elm: CodeElementUnpackBinding) -> TypeTuple: return return_type + def get_suggestion_for_wrong_unpacking( + self, elm: CodeElementUnpackBinding + ) -> Optional[CodeElement]: + """ + Generates a 'did you mean' suggestion for a wrong unpack binding. + """ + unpacking_identifiers = elm.unpacking_list.identifiers + if len(unpacking_identifiers) != 1 or not isinstance(elm.rvalue, RvalueFuncCall): + return None + + identifier = unpacking_identifiers[0] + if identifier.modifier is None: + return CodeElementReturnValueReference( + typed_identifier=identifier, func_call=elm.rvalue + ) + elif identifier.modifier.name == "local": + return CodeElementLocalVariable( + typed_identifier=identifier.strip_modifier(), expr=ExprFuncCall(rvalue=elm.rvalue) + ) + + return None + def visit_CodeElementUnpackBinding(self, elm: CodeElementUnpackBinding): unpacking_type = self.get_unpacking_type(elm) @@ -1899,6 +1962,9 @@ def visit_CodeElementUnpackBinding(self, elm: CodeElementUnpackBinding): # Forbid locals outside of functions. assert_no_modifier(typed_identifier, excluded=excluded) + if self.auxiliary_info is not None: + self.auxiliary_info.add_func_ret_vars([typed_identifier.name]) + if typed_identifier.name == "_": continue @@ -1928,9 +1994,6 @@ def visit_CodeElementUnpackBinding(self, elm: CodeElementUnpackBinding): location=typed_identifier.location, ) - if self.auxiliary_info is not None: - self.auxiliary_info.add_func_ret_vars([typed_identifier.identifier.name]) - def add_label(self, identifier: ExprIdentifier): name = self.current_scope + identifier.name self.flow_tracking.converge_with_label(name) @@ -2201,7 +2264,9 @@ def simplify_expr(self, expr) -> Tuple[Expression, CairoType]: resolve_type_callback=self.resolve_type, get_struct_members_callback=self.get_struct_members, ) - expr, expr_type = simplify_type_system(expr, identifiers=self.identifiers) + expr, expr_type = simplify_type_system( + expr=expr, identifiers=self.identifiers, accessible_scopes=self.accessible_scopes + ) return self.simplifier.visit(expr), self.resolve_type(expr_type) def simplify_expr_as_felt(self, expr) -> Expression: @@ -2478,7 +2543,7 @@ def get_struct_members(self, struct_type: TypeStruct) -> List[str]: """ Returns the list of members of the given struct. """ - struct_definition = self.identifiers.get_by_full_name(name=struct_type.resolved_scope) + struct_definition = self.identifiers.get_by_full_name(name=struct_type.scope) assert isinstance( struct_definition, StructDefinition ), f"Expected StructDefinition, found: {type(struct_definition).__name__}." diff --git a/src/starkware/cairo/lang/compiler/preprocessor/preprocessor_test.py b/src/starkware/cairo/lang/compiler/preprocessor/preprocessor_test.py index 98d51a9f..3e865ef3 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/preprocessor_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/preprocessor_test.py @@ -36,62 +36,62 @@ def test_compiler(): program = preprocess_str( code=""" +const x = 5; +const y = 2 * x; +[ap] = [[fp + 2 * 0x3] + ((7 - 1 + y))], ap++; +ap += 3 + 'a'; +dw x + 5; + +// An empty line with a comment. +[ap] = [fp]; // This is a comment. +let z = ap - 3; +[ap] = [ap - x]; +jmp rel 2 - 3; +ret; -const x = 5 -const y = 2 * x -[ap] = [[fp + 2 * 0x3] + ((7 - 1 + y))]; ap++ -ap += 3 + 'a' -dw x + 5 - -# An empty line with a comment. -[ap] = [fp] # This is a comment. -let z = ap - 3 -[ap] = [ap - x] -jmp rel 2 - 3 -ret label: -jmp label if [fp + 3 + 1] != 0 +jmp label if [fp + 3 + 1] != 0; """, prime=PRIME, ) assert ( program.format() == """\ -[ap] = [[fp + 6] + 16]; ap++ -ap += 100 -dw 10 -[ap] = [fp] -[ap] = [ap + (-5)] -jmp rel -1 -ret -jmp rel 0 if [fp + 4] != 0 +[ap] = [[fp + 6] + 16], ap++; +ap += 100; +dw 10; +[ap] = [fp]; +[ap] = [ap + (-5)]; +jmp rel -1; +ret; +jmp rel 0 if [fp + 4] != 0; """ ) def test_scope_const(): code = """\ -const x = 5 -[ap] = x; ap++ -func f(): - const x = 1234 - [ap + 1] = x; ap++ - [ap + 2] = f.x; ap++ - ret -end -[ap + 3] = x; ap++ -[ap + 4] = f.x; ap++ +const x = 5; +[ap] = x, ap++; +func f() { + const x = 1234; + [ap + 1] = x, ap++; + [ap + 2] = f.x, ap++; + ret; +} +[ap + 3] = x, ap++; +[ap + 4] = f.x, ap++; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 5; ap++ -[ap + 1] = 1234; ap++ -[ap + 2] = 1234; ap++ -ret -[ap + 3] = 5; ap++ -[ap + 4] = 1234; ap++ +[ap] = 5, ap++; +[ap + 1] = 1234, ap++; +[ap + 2] = 1234, ap++; +ret; +[ap + 3] = 5, ap++; +[ap + 4] = 1234, ap++; """ ) @@ -99,25 +99,25 @@ def test_scope_const(): def test_pow_failure(): verify_exception( """\ -func foo(x : felt): - tempvar y = x ** 2 -end +func foo(x: felt) { + tempvar y = x ** 2; +} """, """ file:?:?: Operator '**' is only supported for constant values. - tempvar y = x ** 2 + tempvar y = x ** 2; ^****^ """, ) verify_exception( """\ -const X = 2 -const Y = 2 ** (2 * 3) -const Z = 2 ** (X * 3) +const X = 2; +const Y = 2 ** (2 * 3); +const Z = 2 ** (X * 3); """, """ file:?:?: Identifier 'X' is not allowed in this context. -const Z = 2 ** (X * 3) +const Z = 2 ** (X * 3); ^ """, exc_type=CairoTypeError, @@ -127,28 +127,28 @@ def test_pow_failure(): def test_referenced_before_definition_failure(): verify_exception( """ -const x = 5 -func f(): - [ap + 1] = x; ap++ - const x = 1234 -end +const x = 5; +func f() { + [ap + 1] = x, ap++; + const x = 1234; +} """, """ file:?:?: Identifier 'x' referenced before definition. - [ap + 1] = x; ap++ + [ap + 1] = x, ap++; ^ """, ) verify_exception( """ -foo.x = 6 -func foo(): - const x = 6 -end +foo.x = 6; +func foo() { + const x = 6; +} """, """ file:?:?: Identifier 'foo.x' referenced before definition. -foo.x = 6 +foo.x = 6; ^***^ """, ) @@ -156,21 +156,23 @@ def test_referenced_before_definition_failure(): def test_assign_future_label(): code = """\ -[ap] = future_label2 - future_label1; ap++ -[ap] = future_label1; ap++ +[ap] = future_label2 - future_label1, ap++; +[ap] = future_label1, ap++; + future_label1: -[ap] = future_label2; ap++ +[ap] = future_label2, ap++; + future_label2: -[ap] = 8; ap++ +[ap] = 8, ap++; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 2; ap++ -[ap] = 4; ap++ -[ap] = 6; ap++ -[ap] = 8; ap++ +[ap] = 2, ap++; +[ap] = 4, ap++; +[ap] = 6, ap++; +[ap] = 8, ap++; """ ) @@ -178,15 +180,15 @@ def test_assign_future_label(): def test_assign_future_function_label(): code = """\ start: -g(f - start) -g((f - start + 1) * 2 + 3) - -func f() -> (): - ret -end -func g(x: felt) -> (): - ret -end +g(f - start); +g((f - start + 1) * 2 + 3); + +func f() -> () { + ret; +} +func g(x: felt) -> () { + ret; +} """ program = preprocess_str(code=code, prime=PRIME) f_definition = program.identifiers.get_by_full_name(ScopedName.from_string("test_scope.f")) @@ -194,61 +196,61 @@ def test_assign_future_function_label(): assert ( program.format() == f"""\ -[ap] = {f_definition.pc}; ap++ -call rel 13 -[ap] = {f_definition.pc}; ap++ -[ap] = [ap + (-1)] + 1; ap++ -[ap] = [ap + (-1)] * 2; ap++ -[ap] = [ap + (-1)] + 3; ap++ -call rel 3 -ret -ret +[ap] = {f_definition.pc}, ap++; +call rel 13; +[ap] = {f_definition.pc}, ap++; +[ap] = [ap + (-1)] + 1, ap++; +[ap] = [ap + (-1)] * 2, ap++; +[ap] = [ap + (-1)] + 3, ap++; +call rel 3; +ret; +ret; """ ) def test_temporary_variable(): code = """\ -struct T: - member pad0 : felt - member t : felt -end -tempvar x = [ap - 1] + [fp - 3] -ap += 3 -tempvar y : T* = cast(x, T*) -ap += 4 -[fp] = y.t -ap += 5 -tempvar z : (felt, felt) = (1, 2) -# Check the expression pushing optimization. -tempvar z : (felt, felt) = ([ap - 1], 3) -tempvar q : T -assert q.t = 0 -tempvar w -tempvar h1 = nondet %{ 5**i %} -tempvar h2 : felt* = cast(nondet %{ segments.add_temp_segment() %}, felt*) + 3 +struct T { + pad0: felt, + t: felt, +} +tempvar x = [ap - 1] + [fp - 3]; +ap += 3; +tempvar y: T* = cast(x, T*); +ap += 4; +[fp] = y.t; +ap += 5; +tempvar z: (felt, felt) = (1, 2); +// Check the expression pushing optimization. +tempvar z: (felt, felt) = ([ap - 1], 3); +tempvar q: T; +assert q.t = 0; +tempvar w; +tempvar h1 = nondet %{ 5**i %}; +tempvar h2: felt* = cast(nondet %{ segments.add_temp_segment() %}, felt*) + 3; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = [ap + (-1)] + [fp + (-3)]; ap++ -ap += 3 -[ap] = [ap + (-4)]; ap++ -ap += 4 -[fp] = [[ap + (-5)] + 1] -ap += 5 -[ap] = 1; ap++ -[ap] = 2; ap++ -[ap] = 3; ap++ -ap += 2 -[ap + (-1)] = 0 -ap += 1 +[ap] = [ap + (-1)] + [fp + (-3)], ap++; +ap += 3; +[ap] = [ap + (-4)], ap++; +ap += 4; +[fp] = [[ap + (-5)] + 1]; +ap += 5; +[ap] = 1, ap++; +[ap] = 2, ap++; +[ap] = 3, ap++; +ap += 2; +[ap + (-1)] = 0; +ap += 1; %{ memory[ap] = to_felt_or_relocatable(5**i) %} -ap += 1 +ap += 1; %{ memory[ap] = to_felt_or_relocatable(segments.add_temp_segment()) %} -ap += 1 -[ap] = [ap + (-1)] + 3; ap++ +ap += 1; +[ap] = [ap + (-1)] + 3, ap++; """ ) @@ -256,36 +258,36 @@ def test_temporary_variable(): def test_temporary_variable_failures(): verify_exception( """ -tempvar x : felt = cast([ap], felt*) +tempvar x: felt = cast([ap], felt*); """, """ file:?:?: Cannot assign an expression of type 'felt*' to a temporary variable of type 'felt'. -tempvar x : felt = cast([ap], felt*) - ^**^ +tempvar x: felt = cast([ap], felt*); + ^**^ """, ) verify_exception( """ -tempvar _ = 0 +tempvar _ = 0; """, """ file:?:?: Reference name cannot be '_'. -tempvar _ = 0 +tempvar _ = 0; ^ """, ) verify_exception( """ -struct T: - member x : felt - member y : felt -end -tempvar a : T = nondet %{ 1 %} +struct T { + x: felt, + y: felt, +} +tempvar a: T = nondet %{ 1 %}; """, """ file:?:?: Hint tempvars must be of type felt or a pointer. -tempvar a : T = nondet %{ 1 %} - ^************^ +tempvar a: T = nondet %{ 1 %}; + ^************^ """, ) @@ -293,28 +295,28 @@ def test_temporary_variable_failures(): def test_tempvar_modifier_failures(): verify_exception( """ -func main(): - tempvar local x = 5 -end +func main() { + tempvar local x = 5; +} """, """ file:?:?: Unexpected modifier 'local'. - tempvar local x = 5 + tempvar local x = 5; ^***^ """, ) verify_exception( """ -tempvar x = [ap - 1] + [fp - 3] -[x] = [[ap]] +tempvar x = [ap - 1] + [fp - 3]; +[x] = [[ap]]; """, """ file:?:?: While expanding the reference 'x' in: -[x] = [[ap]] +[x] = [[ap]]; ^ file:?:?: Expected a register. Found: [ap + (-1)]. -tempvar x = [ap - 1] + [fp - 3] +tempvar x = [ap - 1] + [fp - 3]; ^ Preprocessed instruction: [[ap + (-1)]] = [[ap]] @@ -325,16 +327,16 @@ def test_tempvar_modifier_failures(): def test_static_assert(): code = """\ -static_assert 3 + fp + 10 == 0 + fp + 13 -let x = ap -ap += 3 -static_assert x + 7 == ap + 4 +static_assert 3 + fp + 10 == 0 + fp + 13; +let x = ap; +ap += 3; +static_assert x + 7 == ap + 4; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 3 +ap += 3; """ ) @@ -342,24 +344,24 @@ def test_static_assert(): def test_static_assert_failures(): verify_exception( """ -static_assert 3 + fp + 10 == 0 + fp + 14 +static_assert 3 + fp + 10 == 0 + fp + 14; """, """ file:?:?: Static assert failed: fp + 13 != fp + 14. -static_assert 3 + fp + 10 == 0 + fp + 14 -^**************************************^ +static_assert 3 + fp + 10 == 0 + fp + 14; +^***************************************^ """, ) verify_exception( """ -let x = ap -ap += 3 -static_assert x + 7 == 0 +let x = ap; +ap += 3; +static_assert x + 7 == 0; """, """ file:?:?: Static assert failed: ap + 4 != 0. -static_assert x + 7 == 0 -^**********************^ +static_assert x + 7 == 0; +^***********************^ """, ) @@ -370,21 +372,21 @@ def test_static_assert_failures(): "jmp body if [ap] != 0", "ap += 0", "[ap] = [ap]", - "[ap] = [ap]; ap++", + "[ap] = [ap], ap++", ], ) def test_func_failures(last_statement): verify_exception( f""" -func f(x): +func f(x) {{ body: - ret - {last_statement} -end + ret; + {last_statement}; +}} """, """ file:?:?: Function must end with a return instruction or a jump. -func f(x): +func f(x) { ^ """, ) @@ -392,71 +394,65 @@ def test_func_failures(last_statement): def test_func_modifier_failures(): verify_exception( - f""" -func f(local x): - ret -end -""", """ -file:?:?: Unexpected modifier 'local'. -func f(local x): - ^***^ -""", - ) - - verify_exception( - f""" -func f(x) -> (local y): - ret -end +func f(local x) { + ret; +} """, """ file:?:?: Unexpected modifier 'local'. -func f(x) -> (local y): - ^***^ +func f(local x) { + ^***^ """, ) def test_return(): code = """\ -func f() -> (a : felt, b : felt, c : felt): - return (1, [fp], c=[fp + 1] + 2) - - tempvar z = 5 - tempvar x = 1 - tempvar y = 2 - return (x, y, z) - - tempvar x = 1 - tempvar y = 2 - return (x, y, x + x + y) -end -func g(): - return () -end +func f() -> (a: felt, b: felt, c: felt) { + return (a=1, b=[fp], c=[fp + 1] + 2); + + tempvar z = 5; + tempvar x = 1; + tempvar y = 2; + return (x, y, z); + + tempvar x = 1; + tempvar y = 2; + return (x, y, x + x + y); + + tempvar tup = (1, 2, 3); + return tup; +} +func g() { + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 1; ap++ -[ap] = [fp]; ap++ -[ap] = [fp + 1] + 2; ap++ -ret -[ap] = 5; ap++ -[ap] = 1; ap++ -[ap] = 2; ap++ -[ap] = [ap + (-3)]; ap++ -ret -[ap] = 1; ap++ -[ap] = 2; ap++ -[ap] = [ap + (-2)] + [ap + (-2)]; ap++ -[ap] = [ap + (-3)]; ap++ -[ap] = [ap + (-3)]; ap++ -[ap] = [ap + (-3)] + [ap + (-4)]; ap++ -ret -ret +[ap] = 1, ap++; +[ap] = [fp], ap++; +[ap] = [fp + 1] + 2, ap++; +ret; +[ap] = 5, ap++; +[ap] = 1, ap++; +[ap] = 2, ap++; +[ap] = [ap + (-3)], ap++; +ret; +[ap] = 1, ap++; +[ap] = 2, ap++; +[ap] = [ap + (-2)] + [ap + (-2)], ap++; +[ap] = [ap + (-3)], ap++; +[ap] = [ap + (-3)], ap++; +[ap] = [ap + (-3)] + [ap + (-4)], ap++; +ret; +[ap] = 1, ap++; +[ap] = 2, ap++; +[ap] = 3, ap++; +ret; +ret; """ ) @@ -465,76 +461,111 @@ def test_return_failures(): # Named after positional. verify_exception( """ -func f() -> (a : felt, b : felt, c : felt): - return (a=1, b=1, [fp] + 1) -end +func f() -> (a: felt, b: felt, c: felt) { + return (a=1, b=1, [fp] + 1); +} """, """ -file:?:?: Positional arguments must not appear after named arguments. - return (a=1, b=1, [fp] + 1) - ^******^ +file:?:?: All fields in a named tuple must have a name. + return (a=1, b=1, [fp] + 1); + ^******************^ """, ) # Wrong num. verify_exception( """ -func f() -> (a : felt, b : felt, c : felt, d : felt): - return (1, [fp] + 1) -end +func f() -> (a: felt, b: felt, c: felt, d: felt) { + return (1, [fp] + 1); +} """, """ -file:?:?: Expected exactly 4 expressions, got 2. - return (1, [fp] + 1) - ^******************^ +file:?:?: Cannot cast an expression of type '(felt, felt)' to \ +'(a: felt, b: felt, c: felt, d: felt)'. +The former has 2 members while the latter has 4 members. + return (1, [fp] + 1); + ^***********^ """, + exc_type=CairoTypeError, ) # Wrong num. verify_exception( """ -func f() -> (a : felt, b : felt): - return () -end +func f() -> (a: felt, b: felt) { + return (); +} """, """ -file:?:?: Expected exactly 2 expressions, got 0. - return () - ^*******^ +file:?:?: Cannot cast an expression of type '()' to '(a: felt, b: felt)'. +The former has 0 members while the latter has 2 members. + return (); + ^^ """, + exc_type=CairoTypeError, ) # Unknown name. verify_exception( """ -func f() -> (a : felt, b : felt, c : felt): - return (a=1, d=1, [fp] + 1) -end +func f() -> (a: felt, b: felt, c: felt) { + return (a=1, d=1, c=[fp] + 1); +} """, """ -file:?:?: Expected named argument: 'b', found: 'd'. - return (a=1, d=1, [fp] + 1) - ^ +file:?:?: Cannot cast '(a: felt, d: felt, c: felt)' to '(a: felt, b: felt, c: felt)'. +Expected argument name 'b'. Found: 'd'. + return (a=1, d=1, c=[fp] + 1); + ^********************^ """, + exc_type=CairoTypeError, ) # Not in func. verify_exception( """ -return (a=1, [fp] + 1) +return (a=1, [fp] + 1); """, """ file:?:?: return cannot be used outside of a function. -return (a=1, [fp] + 1) -^********************^ +return (a=1, [fp] + 1); +^*********************^ +""", + ) + + verify_exception( + """ +func f() -> (a: felt) { + return 2 * 3; +} +""", + """ +file:?:?: Expected expression of type '(a: felt)', got 'felt'. + return 2 * 3; + ^***^ +""", + ) + + verify_exception( + """ +struct MyStruct { +} +func f() -> (a: felt) { + return MyStruct(); +} +""", + """ +file:?:?: Expected MyStruct to be a function name. Found: struct. + return MyStruct(); + ^******^ """, ) def test_tail_call(): code = """\ -func f(a) -> (a : felt): - return f(a) -end -func g(a, b) -> (a : felt): - return f(a) -end +func f(a) -> (a: felt) { + return f(a); +} +func g(a, b) -> (a: felt) { + return f(a); +} """ program = preprocess_str( code=code, prime=PRIME, main_scope=ScopedName.from_string("test_scope") @@ -542,12 +573,12 @@ def test_tail_call(): assert ( program.format() == """\ -[ap] = [fp + (-3)]; ap++ -call rel -1 -ret -[ap] = [fp + (-4)]; ap++ -call rel -5 -ret +[ap] = [fp + (-3)], ap++; +call rel -1; +ret; +[ap] = [fp + (-4)], ap++; +call rel -5; +ret; """ ) @@ -555,121 +586,121 @@ def test_tail_call(): def test_tail_call_failure(): verify_exception( """ -func g() -> (a : felt): - return (a=0) -end -return g() +func g() -> (a: felt) { + return (a=0); +} +return g(); """, """ file:?:?: return cannot be used outside of a function. -return g() -^********^ +return g(); +^*********^ """, ) verify_exception( """ -func g() -> (a : felt): - return (a=0) -end -func f(x, y) -> (a : felt, b : felt, c : felt, d : felt, e : felt): - return g() -end +func g() -> (a: felt) { + return (a=0); +} +func f(x, y) -> (a: felt, b: felt, c: felt, d: felt, e: felt) { + return g(); +} """, """ file:?:?: Cannot convert the return type of g to the return type of f. - return g() - ^********^ + return g(); + ^*********^ """, ) verify_exception( """ -func g{x, y}() -> (a : felt): - return (a=0) -end -func f{y, x}() -> (a : felt): - return g() -end +func g{x, y}() -> (a: felt) { + return (a=0); +} +func f{y, x}() -> (a: felt) { + return g(); +} """, """ file:?:?: Cannot convert the implicit arguments of g to the implicit arguments of f. - return g() - ^********^ + return g(); + ^*********^ The implicit arguments of 'g' were defined here: file:?:? -func g{x, y}() -> (a : felt): +func g{x, y}() -> (a: felt) { ^**^ The implicit arguments of 'f' were defined here: file:?:? -func f{y, x}() -> (a : felt): +func f{y, x}() -> (a: felt) { ^**^ """, ) verify_exception( """ -func f(x, y) -> (a : felt, b : felt, c : felt, d : felt, e : felt): - return g() -end +func f(x, y) -> (a: felt, b: felt, c: felt, d: felt, e: felt) { + return g(); +} """, """ file:?:?: Unknown identifier 'g'. - return g() + return g(); ^ """, ) verify_exception( """ -func g(x, y) -> (a : felt): - return (a=5) -end -func f(x, y) -> (a : felt*): - return g(x, y) -end +func g(x, y) -> (a: felt) { + return (a=5); +} +func f(x, y) -> (a: felt*) { + return g(x, y); +} """, """ file:?:?: Cannot convert the return type of g to the return type of f. - return g(x, y) - ^************^ + return g(x, y); + ^*************^ """, ) def test_function_call(): code = """\ -func foo(a, b) -> (c : felt): - bar(a=a) - return (1) -end -func bar(a): - return () -end -foo(2, 3) -foo(2, b=3) -let res = foo(a=2, b=3) -res.c = 1 +func foo(a, b) -> (c: felt) { + bar(a=a); + return (c=1); +} +func bar(a) { + return (); +} +foo(2, 3); +foo(2, b=3); +let res = foo(a=2, b=3); +res.c = 1; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = [fp + (-4)]; ap++ -call rel 5 -[ap] = 1; ap++ -ret -ret -[ap] = 2; ap++ -[ap] = 3; ap++ -call rel -11 -[ap] = 2; ap++ -[ap] = 3; ap++ -call rel -17 -[ap] = 2; ap++ -[ap] = 3; ap++ -call rel -23 -[ap + (-1)] = 1 +[ap] = [fp + (-4)], ap++; +call rel 5; +[ap] = 1, ap++; +ret; +ret; +[ap] = 2, ap++; +[ap] = 3, ap++; +call rel -11; +[ap] = 2, ap++; +[ap] = 3, ap++; +call rel -17; +[ap] = 2, ap++; +[ap] = 3, ap++; +call rel -23; +[ap + (-1)] = 1; """ ) @@ -677,16 +708,16 @@ def test_function_call(): def test_func_args(): scope = TEST_SCOPE code = """\ -struct T: - member s : felt - member t : felt -end -func f(x, y : T, z : T*): - x = 1; ap++ - y.s = 2; ap++ - z.t = y.t; ap++ - ret -end +struct T { + s: felt, + t: felt, +} +func f(x, y: T, z: T*) { + x = 1, ap++; + y.s = 2, ap++; + z.t = y.t, ap++; + ret; +} """ program = preprocess_str(code=code, prime=PRIME, main_scope=scope) reference_x = program.instructions[-1].flow_tracking_data.resolve_reference( @@ -704,10 +735,10 @@ def test_func_args(): assert ( program.format() == """\ -[fp + (-6)] = 1; ap++ -[fp + (-5)] = 2; ap++ -[[fp + (-3)] + 1] = [fp + (-4)]; ap++ -ret +[fp + (-6)] = 1, ap++; +[fp + (-5)] = 2, ap++; +[[fp + (-3)] + 1] = [fp + (-4)], ap++; +ret; """ ) @@ -715,16 +746,16 @@ def test_func_args(): def test_func_args_failures(): verify_exception( """ -func f(x): - [ap] = [x] + 1 -end +func f(x) { + [ap] = [x] + 1; +} """, """ file:?:?: While expanding the reference 'x' in: - [ap] = [x] + 1 + [ap] = [x] + 1; ^ file:?:?: Expected a register. Found: [fp + (-3)]. -func f(x): +func f(x) { ^ Preprocessed instruction: [ap] = [[fp + (-3)]] + 1 @@ -735,54 +766,54 @@ def test_func_args_failures(): def test_with_statement(): code = """ -let x = 1000 -[ap] = 0 -with x: - [ap] = 1 - [ap] = 2 - [ap] = x - let x = 1001 -end -[ap] = x +let x = 1000; +[ap] = 0; +with x { + [ap] = 1; + [ap] = 2; + [ap] = x; + let x = 1001; +} +[ap] = x; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 0 -[ap] = 1 -[ap] = 2 -[ap] = 1000 -[ap] = 1001 +[ap] = 0; +[ap] = 1; +[ap] = 2; +[ap] = 1000; +[ap] = 1001; """ ) def test_with_statement_locals(): code = """ -func foo() -> (z : felt): - ret -end - -func bar(): - alloc_locals - local x = 0 - with x: - let (local z) = foo() - end - ret -end +func foo() -> (z: felt) { + ret; +} + +func bar() { + alloc_locals; + local x = 0; + with x { + let (local z) = foo(); + } + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ret -ap += 2 -[fp] = 0 -call rel -5 -[fp + 1] = [ap + (-1)] -ret +ret; +ap += 2; +[fp] = 0; +call rel -5; +[fp + 1] = [ap + (-1)]; +ret; """ ) @@ -790,39 +821,39 @@ def test_with_statement_locals(): def test_with_statement_failure(): verify_exception( """ -with x: - [ap] = [ap] -end +with x { + [ap] = [ap]; +} """, """ file:?:?: Unknown reference 'x'. -with x: +with x { ^ """, ) verify_exception( """ -const x = 0 -with x: - [ap] = [ap] -end +const x = 0; +with x { + [ap] = [ap]; +} """, """ file:?:?: Expected 'x' to be a reference, found: const. -with x: +with x { ^ """, ) verify_exception( """ -let x = 0 -with x as y: - [ap] = [ap] -end +let x = 0; +with x as y { + [ap] = [ap]; +} """, """ file:?:?: The 'as' keyword is not supported in 'with' statements. -with x as y: +with x as y { ^ """, ) @@ -830,27 +861,27 @@ def test_with_statement_failure(): def test_with_attr_statement(): code = """ -func a(): - alloc_locals - local x = 0 - ap += 7 - with_attr attr_name("attribute value"): - [ap] = 1 - end - [ap] = 2 - ret -end +func a() { + alloc_locals; + local x = 0; + ap += 7; + with_attr attr_name("attribute value") { + [ap] = 1; + } + [ap] = 2; + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 1 -[fp] = 0 -ap += 7 -[ap] = 1 -[ap] = 2 -ret +ap += 1; +[fp] = 0; +ap += 7; +[ap] = 1; +[ap] = 2; +ret; """ ) expected_flow_tracking_data = FlowTrackingDataActual( @@ -880,9 +911,9 @@ def test_attribute_scope_deserialization_with_missing_fields(): are missing from the serialization. """ code = """ -with_attr attr_name("attribute value"): - [ap] = 1 -end +with_attr attr_name("attribute value") { + [ap] = 1; +} """ program = compile_cairo(code, prime=DEFAULT_PRIME) assert len(program.attributes) == 1 @@ -899,69 +930,69 @@ def test_attribute_scope_deserialization_with_missing_fields(): def test_implicit_args(): code = """\ -struct T: - member a : felt - member b : felt -end - -func f{x: T}() -> (): - # Rebind x. - let x = [cast(fp - 1234, T*)] - return () -end - -func g{x: T, y}(z, w) -> (res : felt): - x.a = 0 - x.b = 1 - y = 2 - z = 3 - w = 4 - # Rebind y. This affects the implicit return values. - let y = z - # We don't need a 'with' statement, since x and y are implicit arguments. - f() - return (res=z + w) -end - -func h(): - let y = 10 - let x: T = [cast(fp - 100, T*)] - with x, y: - let (res2) = g(0, 0) - end - # Below, x and y refer to the implicit return values. - tempvar a = x.a + y - tempvar b = res2 - ret -end +struct T { + a: felt, + b: felt, +} + +func f{x: T}() -> () { + // Rebind x. + let x = [cast(fp - 1234, T*)]; + return (); +} + +func g{x: T, y}(z, w) -> (res: felt) { + x.a = 0; + x.b = 1; + y = 2; + z = 3; + w = 4; + // Rebind y. This affects the implicit return values. + let y = z; + // We don't need a 'with' statement, since x and y are implicit arguments. + f(); + return (res=z + w); +} + +func h() { + let y = 10; + let x: T = [cast(fp - 100, T*)]; + with x, y { + let (res2) = g(0, 0); + } + // Below, x and y refer to the implicit return values. + tempvar a = x.a + y; + tempvar b = res2; + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = [fp + (-1234)]; ap++ -[ap] = [fp + (-1233)]; ap++ -ret -[fp + (-7)] = 0 -[fp + (-6)] = 1 -[fp + (-5)] = 2 -[fp + (-4)] = 3 -[fp + (-3)] = 4 -[ap] = [fp + (-7)]; ap++ -[ap] = [fp + (-6)]; ap++ -call rel -15 -[ap] = [fp + (-4)]; ap++ -[ap] = [fp + (-4)] + [fp + (-3)]; ap++ -ret -[ap] = [fp + (-100)]; ap++ -[ap] = [fp + (-99)]; ap++ -[ap] = 10; ap++ -[ap] = 0; ap++ -[ap] = 0; ap++ -call rel -25 -[ap] = [ap + (-4)] + [ap + (-2)]; ap++ -[ap] = [ap + (-2)]; ap++ -ret +[ap] = [fp + (-1234)], ap++; +[ap] = [fp + (-1233)], ap++; +ret; +[fp + (-7)] = 0; +[fp + (-6)] = 1; +[fp + (-5)] = 2; +[fp + (-4)] = 3; +[fp + (-3)] = 4; +[ap] = [fp + (-7)], ap++; +[ap] = [fp + (-6)], ap++; +call rel -15; +[ap] = [fp + (-4)], ap++; +[ap] = [fp + (-4)] + [fp + (-3)], ap++; +ret; +[ap] = [fp + (-100)], ap++; +[ap] = [fp + (-99)], ap++; +[ap] = 10, ap++; +[ap] = 0, ap++; +[ap] = 0, ap++; +call rel -25; +[ap] = [ap + (-4)] + [ap + (-2)], ap++; +[ap] = [ap + (-2)], ap++; +ret; """ ) @@ -969,103 +1000,90 @@ def test_implicit_args(): def test_implicit_args_failures(): verify_exception( """ -func f{x}(x : felt): - ret -end +func f{x}(x: felt) { + ret; +} """, """ -file:?:?: Arguments and return values cannot have the same name of an implicit argument. -func f{x}(x : felt): - ^******^ -""", - ) - - verify_exception( - """ -func f{x}() -> (x : felt): - ret -end -""", - """ -file:?:?: Arguments and return values cannot have the same name of an implicit argument. -func f{x}() -> (x : felt): - ^******^ +file:?:?: An argument cannot have the same name as an implicit argument. +func f{x}(x: felt) { + ^ """, ) verify_exception( """ -func f{x}(): - ret -end +func f{x}() { + ret; +} -func g(): - f() - ret -end +func g() { + f(); + ret; +} """, """ file:?:?: While trying to retrieve the implicit argument 'x' in: - f() + f(); ^*^ file:?:?: Unknown identifier 'x'. -func f{x}(): +func f{x}() { ^ """, ) verify_exception( """ -func f{x}(y): - ret -end -func g(x): - with x: - f(0) - end - # This should fail, as it is outside the "with x". - f(1) - ret -end +func f{x}(y) { + ret; +} +func g(x) { + with x { + f(0); + } + // This should fail, as it is outside the "with x". + f(1); + ret; +} """, """ file:?:?: While trying to update the implicit return value 'x' in: - f(1) + f(1); ^**^ file:?:?: 'x' cannot be used as an implicit return value. Consider using a 'with' statement. -func f{x}(y): +func f{x}(y) { ^ """, ) verify_exception( """ -func f{x}(): - let x = cast(0, felt*) - return () -end +func f{x}() { + let x = cast(0, felt*); + return (); +} """, """ file:?:?: Reference rebinding must preserve the reference type. Previous type: 'felt', new type: \ 'felt*'. - let x = cast(0, felt*) + let x = cast(0, felt*); ^ """, ) verify_exception( """ -func f{x}(): - ret -end -func g(): - const x = 0 - f() - ret -end +func f{x}() { + ret; +} +func g() { + const x = 0; + f(); + ret; +} """, """ file:?:?: While trying to update the implicit return value 'x' in: - f() + f(); ^*^ file:?:?: Redefinition of 'test_scope.g.x'. -func f{x}(): +func f{x}() { ^ """, ) @@ -1073,27 +1091,27 @@ def test_implicit_args_failures(): def test_implcit_argument_bindings(): code = """\ -func f{x, y}(): - ret -end - -func g{x, y, z}(): - f{y=z}() - return () -end +func f{x, y}() { + ret; +} + +func g{x, y, z}() { + f{y=z}(); + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ret -[ap] = [fp + (-5)]; ap++ -[ap] = [fp + (-3)]; ap++ -call rel -3 -[ap] = [ap + (-2)]; ap++ -[ap] = [fp + (-4)]; ap++ -[ap] = [ap + (-3)]; ap++ -ret +ret; +[ap] = [fp + (-5)], ap++; +[ap] = [fp + (-3)], ap++; +call rel -3; +[ap] = [ap + (-2)], ap++; +[ap] = [fp + (-4)], ap++; +[ap] = [ap + (-3)], ap++; +ret; """ ) @@ -1101,53 +1119,53 @@ def test_implcit_argument_bindings(): def test_implcit_argument_bindings_failures(): verify_exception( """ -func foo{x}(y) -> (z : felt): - ret -end +func foo{x}(y) -> (z: felt) { + ret; +} -func bar(): - let x = foo{5}(0) - ret -end +func bar() { + let x = foo{5}(0); + ret; +} """, """ file:?:?: Implicit argument binding must be of the form: arg_name=var. - let x = foo{5}(0) + let x = foo{5}(0); ^ """, ) verify_exception( """ -func foo{x}(y) -> (z : felt): - ret -end +func foo{x}(y) -> (z: felt) { + ret; +} -func bar(): - let x = 0 - let (res) = foo{y=x}(0) - ret -end +func bar() { + let x = 0; + let (res) = foo{y=x}(0); + ret; +} """, """ file:?:?: Unexpected implicit argument binding: y. - let (res) = foo{y=x}(0) + let (res) = foo{y=x}(0); ^ """, ) verify_exception( """ -func foo{x}(y) -> (z : felt): - ret -end +func foo{x}(y) -> (z: felt) { + ret; +} -func bar(): - foo{x=2}(0) - ret -end +func bar() { + foo{x=2}(0); + ret; +} """, """ file:?:?: Implicit argument binding must be an identifier. - foo{x=2}(0) + foo{x=2}(0); ^ """, ) @@ -1155,82 +1173,82 @@ def test_implcit_argument_bindings_failures(): def test_func_args_scope(): code = """\ -const x = 1234 -[ap] = x; ap++ -func f(x, y, z): - x = 1; ap++ - y = 2; ap++ - z = 3; ap++ - ret -end -[ap + 4] = x; ap++ -[ap + 5] = f.Args.z; ap++ +const x = 1234; +[ap] = x, ap++; +func f(x, y, z) { + x = 1, ap++; + y = 2, ap++; + z = 3, ap++; + ret; +} +[ap + 4] = x, ap++; +[ap + 5] = f.Args.z, ap++; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 1234; ap++ -[fp + (-5)] = 1; ap++ -[fp + (-4)] = 2; ap++ -[fp + (-3)] = 3; ap++ -ret -[ap + 4] = 1234; ap++ -[ap + 5] = 2; ap++ +[ap] = 1234, ap++; +[fp + (-5)] = 1, ap++; +[fp + (-4)] = 2, ap++; +[fp + (-3)] = 3, ap++; +ret; +[ap + 4] = 1234, ap++; +[ap + 5] = 2, ap++; """ ) def test_func_args_and_rets_scope(): code = """\ -const x = 1234 -[ap] = x; ap++ -func f(x, y, z) -> (a : felt, b : felt, x : felt): - x = 1; ap++ - y = 2; ap++ - [ap] = Args.y; ap++ - ret -end -[ap + 4] = x; ap++ -[ap + 5] = f.Args.x; ap++ +const x = 1234; +[ap] = x, ap++; +func f(x, y, z) -> (a: felt, b: felt, x: felt) { + x = 1, ap++; + y = 2, ap++; + [ap] = Args.y, ap++; + ret; +} +[ap + 4] = x, ap++; +[ap + 5] = f.Args.x, ap++; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 1234; ap++ -[fp + (-5)] = 1; ap++ -[fp + (-4)] = 2; ap++ -[ap] = 1; ap++ -ret -[ap + 4] = 1234; ap++ -[ap + 5] = 0; ap++ +[ap] = 1234, ap++; +[fp + (-5)] = 1, ap++; +[fp + (-4)] = 2, ap++; +[ap] = 1, ap++; +ret; +[ap + 4] = 1234, ap++; +[ap + 5] = 0, ap++; """ ) def test_func_named_args(): code = """\ -func f(x, y, z): - ret -end - -let f_args = cast(ap, f.Args*) -f_args.z = 2; ap++ -f_args.x = 0; ap++ -f_args.y = 1; ap++ -static_assert f_args + f.Args.SIZE == ap -call f +func f(x, y, z) { + ret; +} + +let f_args = cast(ap, f.Args*); +f_args.z = 2, ap++; +f_args.x = 0, ap++; +f_args.y = 1, ap++; +static_assert f_args + f.Args.SIZE == ap; +call f; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ret -[ap + 2] = 2; ap++ -[ap + (-1)] = 0; ap++ -[ap + (-1)] = 1; ap++ -call rel -7 +ret; +[ap + 2] = 2, ap++; +[ap + (-1)] = 0, ap++; +[ap + (-1)] = 1, ap++; +call rel -7; """ ) @@ -1238,57 +1256,57 @@ def test_func_named_args(): def test_func_named_args_failures(): verify_exception( """ -func f(x, y, z): - ret -end +func f(x, y, z) { + ret; +} -let f_args = cast(ap, f.Args*) -f_args.z = 2; ap++ -f_args.x = 0; ap++ -static_assert f_args + f.Args.SIZE == ap -call f +let f_args = cast(ap, f.Args*); +f_args.z = 2, ap++; +f_args.x = 0, ap++; +static_assert f_args + f.Args.SIZE == ap; +call f; """, """ file:?:?: Static assert failed: ap + 1 != ap. -static_assert f_args + f.Args.SIZE == ap -^**************************************^ +static_assert f_args + f.Args.SIZE == ap; +^***************************************^ """, ) def test_function_call_by_value_args(): code = """\ -struct S: - member a : felt - member b : felt -end - -struct T: - member s : felt - member t : S -end -func f(w : S, x, y : T, z : T): - let s = S(a=13, b=17) - let t : T = [cast(ap, T*)] - let res = f(w=s, x=2, y=z, z=t) - return() -end +struct S { + a: felt, + b: felt, +} + +struct T { + s: felt, + t: S, +} +func f(w: S, x, y: T, z: T) { + let s = S(a=13, b=17); + let t: T = [cast(ap, T*)]; + let res = f(w=s, x=2, y=z, z=t); + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 13; ap++ -[ap] = 17; ap++ -[ap] = 2; ap++ -[ap] = [fp + (-5)]; ap++ -[ap] = [fp + (-4)]; ap++ -[ap] = [fp + (-3)]; ap++ -[ap] = [ap + (-6)]; ap++ -[ap] = [ap + (-6)]; ap++ -[ap] = [ap + (-6)]; ap++ -call rel -12 -ret +[ap] = 13, ap++; +[ap] = 17, ap++; +[ap] = 2, ap++; +[ap] = [fp + (-5)], ap++; +[ap] = [fp + (-4)], ap++; +[ap] = [fp + (-3)], ap++; +[ap] = [ap + (-6)], ap++; +[ap] = [ap + (-6)], ap++; +[ap] = [ap + (-6)], ap++; +call rel -12; +ret; """ ) @@ -1304,24 +1322,24 @@ def test_function_call_by_value_args(): def test_func_by_value_args_failures(test_line, expected_type, actual_type, arrow): verify_exception( f""" -struct T: - member s : felt - member t : felt -end -struct S: - member s : felt - member t : felt -end -func f(x, y : {expected_type}): - local t : {actual_type} - alloc_locals - {test_line} - ret -end +struct T {{ + s: felt, + t: felt, +}} +struct S {{ + s: felt, + t: felt, +}} +func f(x, y: {expected_type}) {{ + local t: {actual_type}; + alloc_locals; + {test_line}; + ret; +}} """, f""" file:?:?: Expected expression of type '{expected_type}', got '{actual_type}'. - {test_line} + {test_line}; {arrow} """, main_scope=ScopedName(), @@ -1330,28 +1348,325 @@ def test_func_by_value_args_failures(test_line, expected_type, actual_type, arro def test_func_by_value_return(): code = """\ -struct T: - member s : felt - member t : felt -end -func f(s : T) -> (x : T, y : T): - let t : T = [cast(ap - 100, T*)] - return(x=s, y=t) -end +struct T { + s: felt, + t: felt, +} +func f(s: T) -> (x: T, y: T) { + let t: T = [cast(ap - 100, T*)]; + return (x=s, y=t); +} +""" + program = preprocess_str(code=code, prime=PRIME) + assert ( + program.format() + == """\ +[ap] = [fp + (-4)], ap++; +[ap] = [fp + (-3)], ap++; +[ap] = [ap + (-102)], ap++; +[ap] = [ap + (-102)], ap++; +ret; +""" + ) + + +def test_unnamed_return_tuple_flow(): + code = """\ +func foo() -> (felt*, felt) { + return (cast(1, felt*), 2); +} +""" + program = preprocess_str(code=code, prime=PRIME) + assert ( + program.format() + == """\ +[ap] = 1, ap++; +[ap] = 2, ap++; +ret; +""" + ) + + +def test_return_type_def(): + code = """\ +using A = (felt*, felt); +func foo() -> A { + return (cast(1, felt*), 2); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = [fp + (-4)]; ap++ -[ap] = [fp + (-3)]; ap++ -[ap] = [ap + (-102)]; ap++ -[ap] = [ap + (-102)]; ap++ -ret +[ap] = 1, ap++; +[ap] = 2, ap++; +ret; """ ) +def test_func_composition_flow1(): + code = """\ +@known_ap_change +func foo{x}(arg: felt) -> felt { + return 1; +} + +func bar{x, y}() { + tempvar res = 0; + tempvar res2 = foo(1) + foo(res); + tempvar res3 = foo(3 + foo(res2) + foo{x=y}(res) + foo(res2) + 2); + return (); +} +""" + program = preprocess_str(code=code, prime=PRIME) + assert program.format() == strip_comments_and_linebreaks( + """\ +// foo. +[ap] = [fp + (-4)], ap++; +[ap] = 1, ap++; +ret; + +// tempvar res = 0; +[ap] = 0, ap++; + +// tempvar res2 = foo(1) + foo(res); +[ap] = [fp + (-4)], ap++; +[ap] = 1, ap++; +call rel -9; +[ap] = [ap + (-2)], ap++; +[ap] = [ap + (-8)], ap++; +call rel -13; +[ap] = [ap + (-7)] + [ap + (-1)], ap++; + +// tempvar res3 = foo(3 + foo(res2) + foo{x=y}(res) + foo(res2) + 2); +[ap] = [ap + (-3)], ap++; +[ap] = [ap + (-2)], ap++; +call rel -18; +[ap] = [ap + (-1)] + 3, ap++; +[ap] = [fp + (-3)], ap++; +[ap] = [ap + (-22)], ap++; +call rel -24; +[ap] = [ap + (-7)] + [ap + (-1)], ap++; +[ap] = [ap + (-10)], ap++; +[ap] = [ap + (-16)], ap++; +call rel -29; +[ap] = [ap + (-1)] + 2, ap++; +[ap] = [ap + (-3)], ap++; +[ap] = [ap + (-9)] + [ap + (-2)], ap++; +call rel -35; +[ap] = [ap + (-2)], ap++; +[ap] = [ap + (-17)], ap++; +ret; +""" + ) + + code = """\ +@known_ap_change +func foo{x}() -> felt* { + return cast(1, felt*); +} + +func bar{x}() -> felt { + return foo() - foo(); +} +""" + program = preprocess_str(code=code, prime=PRIME) + assert program.format() == strip_comments_and_linebreaks( + """\ +// foo. +[ap] = [fp + (-3)], ap++; +[ap] = 1, ap++; +ret; + +// bar. +// tempvar res = foo() + 3; +[ap] = [fp + (-3)], ap++; +call rel -5; +[ap] = [ap + (-2)], ap++; +call rel -8; +[ap] = [ap + (-2)], ap++; +[ap] = [ap + (-7)] - [ap + (-2)], ap++; +ret; +""" + ) + + code = """\ +@known_ap_change +func foo(x: felt) -> felt { + return x; +} + +tempvar res = foo([ap - 1]) + foo([ap - 1]); +""" + program = preprocess_str(code=code, prime=PRIME) + assert program.format() == strip_comments_and_linebreaks( + """\ +// foo. +[ap] = [fp + (-3)], ap++; +ret; + +// tempvar res = foo([ap - 1]) + foo([ap - 1]); +call rel -2; +[ap] = [ap + (-4)], ap++; +call rel -5; +[ap] = [ap + (-5)] + [ap + (-1)], ap++; +""" + ) + + +def test_func_composition_flow2(): + code = """\ +@known_ap_change +func foo{x, y, z}(arg1: felt, arg2: felt) -> felt { + return 1; +} + +func bar{x, y, z, w}() -> felt { + if (foo{y=w}(foo{x=w}(1, 2), 3) != foo{x=z, z=w}(2, 1)) { + return 1; + } + + return foo{z=y}(foo(1, 1) + foo{x=w, y=z}(3, 1) + foo(w, x), 4) + foo{y=x}(x, y); +} +""" + program1 = preprocess_str(code=code, prime=PRIME) + + code = """\ +@known_ap_change +func foo{x, y, z}(arg1: felt, arg2: felt) -> felt { + return 1; +} + +func bar{x, y, z, w}() -> felt { + let foo_1_2 = foo{x=w}(1, 2); + let lhs = foo{y=w}(foo_1_2, 3); + let rhs = foo{x=z, z=w}(2, 1); + if (lhs != rhs) { + return 1; + } + + let foo_1_1 = foo(1, 1); + let foo_3_1 = foo{x=w, y=z}(3, 1); + tempvar sum = foo_1_1 + foo_3_1; + let foo_w_x = foo(w, x); + + let temp = foo{z=y}(sum + foo_w_x, 4); + let foo_x_y = foo{y=x}(x, y); + let res = temp + foo_x_y; + return res; +} +""" + + program2 = preprocess_str(code=code, prime=PRIME) + + assert program1.format() == program2.format() + + +def test_func_composition_failure(): + verify_exception( + """ +func foo() { + ret; +} + +foo(3) = foo(4); +""", + """ +file:?:?: Only functions with a simple return type are supported inside an expression. Got: '()'. +foo(3) = foo(4); +^****^ +""", + exc_type=CairoTypeError, + ) + + verify_exception( + """ +@known_ap_change +func foo() -> (felt, felt) { + return (1, 2); +} + +tempvar res = foo(); +""", + """ +file:?:?: Only functions with a simple return type are supported inside an expression. \ +Got: '(felt, felt)'. +tempvar res = foo(); + ^***^ +""", + exc_type=CairoTypeError, + ) + + verify_exception( + """ +func foo() -> felt { + ap += [ap]; + return 1; +} + +tempvar res = foo() + 3; +""", + """ +file:?:?: Only functions with known ap change may be used in an expression. \ +Consider calling 'foo' in a separate line. +tempvar res = foo() + 3; + ^***^ +""", + ) + + verify_exception( + """ +@known_ap_change +func foo(p: felt*) -> felt { + return 1; +} + +tempvar res = foo(2) + 3; +""", + """ +file:?:?: Expected expression of type 'felt*', got 'felt'. +tempvar res = foo(2) + 3; + ^ +""", + ) + + verify_exception( + """ +@known_ap_change +func foo{x}() -> felt { + return (1); +} + + +tempvar res = foo{x=[ap]}(); +""", + """ +file:?:?: Implicit argument binding must be an identifier. +tempvar res = foo{x=[ap]}(); + ^**^ +""", + ) + + +def test_func_call_in_reference(): + verify_exception( + """\ +@known_ap_change +func foo(p: felt*) -> felt { + return 1; +} + +let res = foo(2) + 3; +""", + """ +file:?:?: Function calls are not allowed inside reference expressions. +let res = foo(2) + 3; + ^****^ +""", + ) + + @pytest.mark.parametrize( "jmp_code", [ @@ -1364,26 +1679,26 @@ def test_func_by_value_return(): def test_function_flow_revoke(jmp_code): verify_exception( f""" -func foo(): +func foo() {{ loop: - {jmp_code} - ret -end + {jmp_code}; + ret; +}} -func bar(): - tempvar x = 0 - foo() - assert x = 0 - ret -end +func bar() {{ + tempvar x = 0; + foo(); + assert x = 0; + ret; +}} """, """ file:?:?: Reference 'x' was revoked. - assert x = 0 + assert x = 0; ^ Reference was defined here: file:?:? - tempvar x = 0 + tempvar x = 0; ^ """, ) @@ -1392,34 +1707,35 @@ def test_function_flow_revoke(jmp_code): def test_scope_label(): code = """\ x: -jmp x -jmp f -call f -func f(): - jmp x +jmp x; +jmp f; +call f; +func f() { + jmp x; + x: - jmp x - jmp f.x -end -jmp x -jmp f.x -jmp f -call f + jmp x; + jmp f.x; +} +jmp x; +jmp f.x; +jmp f; +call f; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -jmp rel 0 -jmp rel 4 -call rel 2 -jmp rel 2 -jmp rel 0 -jmp rel -2 -jmp rel -12 -jmp rel -6 -jmp rel -10 -call rel -12 +jmp rel 0; +jmp rel 4; +call rel 2; +jmp rel 2; +jmp rel 0; +jmp rel -2; +jmp rel -12; +jmp rel -6; +jmp rel -10; +call rel -12; """ ) @@ -1428,17 +1744,17 @@ def test_import(): files = { ".": """ from a import f as g, h as h2 -call g -call h2 +call g; +call h2; """, "a": """ -func f(): - jmp f -end +func f() { + jmp f; +} -func h(): - jmp h -end +func h() { + jmp h; +} """, } program = preprocess_codes( @@ -1451,10 +1767,10 @@ def test_import(): assert ( program.format() == """\ -jmp rel 0 -jmp rel 0 -call rel -4 -call rel -4 +jmp rel 0; +jmp rel 0; +call rel -4; +call rel -4; """ ) @@ -1469,12 +1785,12 @@ def test_import_identifiers(): """, "a.b.c": """ from tau import xi -const alpha = 0 -const beta = 1 -const gamma = 2 +const alpha = 0; +const beta = 1; +const gamma = 2; """, "tau": """ -const xi = 42 +const xi = 42; """, } @@ -1537,20 +1853,20 @@ def test_import_errors(): verify_exception( """ from foo import bar as notbar -[ap] = bar +[ap] = bar; """, """ file:?:?: Unknown identifier 'bar'. -[ap] = bar +[ap] = bar; ^*^ """, - files={"foo": "const bar = 3"}, + files={"foo": "const bar = 3;"}, ) # Identifier redefinition. verify_exception( """ -const bar = 0 +const bar = 0; from foo import bar """, """ @@ -1558,12 +1874,12 @@ def test_import_errors(): from foo import bar ^*^ """, - files={"foo": "const bar=0"}, + files={"foo": "const bar = 0;"}, ) verify_exception( f""" -const lambda = 0 +const lambda = 0; from foo import bar as lambda """, """ @@ -1571,7 +1887,7 @@ def test_import_errors(): from foo import bar as lambda ^****^ """, - files={"foo": "const bar=0"}, + files={"foo": "const bar = 0;"}, ) verify_exception( @@ -1594,43 +1910,43 @@ def test_error_scope_redefinition(): """ Scope 'a.b' collides with a different identifier of type 'const'. """, - files={"a": "const b = 0", "a.b": "const c = 1"}, + files={"a": "const b = 0;", "a.b": "const c = 1;"}, ) def test_scope_failures(): verify_exception( """ -func f(): -const x = 5 -ret -end -func g(): -[ap] = x; ap++ -ret -end +func f() { + const x = 5; + ret; +} +func g() { + [ap] = x, ap++; + ret; +} """, """ file:?:?: Unknown identifier 'x'. -[ap] = x; ap++ - ^ + [ap] = x, ap++; + ^ """, ) verify_exception( """ -func f(): -label: -ret -end -func g(): -call label -ret -end +func f() { + label: + ret; +} +func g() { + call label; + ret; +} """, """ file:?:?: Unknown identifier 'label'. -call label - ^***^ + call label; + ^***^ """, ) @@ -1638,33 +1954,33 @@ def test_scope_failures(): def test_const_failures(): verify_exception( """ -const x = y +const x = y; """, """ file:?:?: Unknown identifier 'y'. -const x = y +const x = y; ^ """, ) verify_exception( """ -const x = 0 -[ap] = x.y.z +const x = 0; +[ap] = x.y.z; """, """ file:?:?: Unexpected '.' after 'test_scope.x' which is const. -[ap] = x.y.z +[ap] = x.y.z; ^***^ """, ) verify_exception( """ -const x = [ap] + 5 +const x = [ap] + 5; """, """ file:?:?: Expected a constant expression. -const x = [ap] + 5 +const x = [ap] + 5; ^******^ """, ) @@ -1674,19 +1990,22 @@ def test_labels(): scope = ScopedName.from_string("my.cool.scope") program = preprocess_str( """ -const x = 7 +const x = 7; + a0: -[ap] = x; ap++ # Size: 2. -[ap] = [fp] + 123 # Size: 2. +[ap] = x, ap++; // Size: 2. +[ap] = [fp] + 123; // Size: 2. a1: -[ap] = [fp] # Size: 1. -jmp rel [fp] # Size: 1. +[ap] = [fp]; // Size: 1. +jmp rel [fp]; // Size: 1. + a2: -jmp rel x # Size: 2. -jmp a3 # Size: 2. -jmp a3 if [ap] != 0 # Size: 2. -call a3 # Size: 2. +jmp rel x; // Size: 2. +jmp a3; // Size: 2. +jmp a3 if [ap] != 0; // Size: 2. +call a3; // Size: 2. + a3: """, prime=PRIME, @@ -1703,7 +2022,7 @@ def test_labels(): def test_process_file_scope(): # Verify the good scenario. valid_scope = ScopedName.from_string("some.valid.scope") - program = preprocess_str("const x = 4", prime=PRIME, main_scope=valid_scope) + program = preprocess_str("const x = 4;", prime=PRIME, main_scope=valid_scope) assert program.identifiers.as_dict() == {valid_scope + "x": ConstDefinition(4)} @@ -1711,33 +2030,34 @@ def test_process_file_scope(): def test_label_resolution(): program = preprocess_str( code=""" -[ap] = 7; ap++ # Size: 2. +[ap] = 7, ap++; // Size: 2. loop: -[ap] = [ap - 1] + 1 # Size: 2. -jmp future_label # Size: 2. -jmp future_label if [ap] != 0 # Size: 2. -call future_label # Size: 2. -[fp] = [fp] # Size: 1. +[ap] = [ap - 1] + 1; // Size: 2. +jmp future_label; // Size: 2. +jmp future_label if [ap] != 0; // Size: 2. +call future_label; // Size: 2. +[fp] = [fp]; // Size: 1. + future_label: -jmp loop # Size: 2. -jmp loop if [ap] != 0 # Size: 2. -call loop # Size 2. +jmp loop; // Size: 2. +jmp loop if [ap] != 0; // Size: 2. +call loop; // Size 2. """, prime=PRIME, ) assert ( program.format() == """\ -[ap] = 7; ap++ -[ap] = [ap + (-1)] + 1 -jmp rel 7 -jmp rel 5 if [ap] != 0 -call rel 3 -[fp] = [fp] -jmp rel -9 -jmp rel -11 if [ap] != 0 -call rel -13 +[ap] = 7, ap++; +[ap] = [ap + (-1)] + 1; +jmp rel 7; +jmp rel 5 if [ap] != 0; +call rel 3; +[fp] = [fp]; +jmp rel -9; +jmp rel -11 if [ap] != 0; +call rel -13; """ ) @@ -1745,22 +2065,22 @@ def test_label_resolution(): def test_labels_failures(): verify_exception( """ -jmp x.y.z +jmp x.y.z; """, """ file:?:?: Unknown identifier 'x'. -jmp x.y.z +jmp x.y.z; ^***^ """, ) verify_exception( """ -const x = 0 -jmp x +const x = 0; +jmp x; """, """ file:?:?: Expected a label name. Identifier 'x' is of type const. -jmp x +jmp x; ^ """, ) @@ -1770,28 +2090,29 @@ def test_redefinition_failures(): verify_exception( """ name: -const name = 0 +const name = 0; """, """ file:?:?: Redefinition of 'test_scope.name'. -const name = 0 +const name = 0; ^**^ """, ) verify_exception( """ -const name = 0 -let name = ap +const name = 0; +let name = ap; """, """ file:?:?: Redefinition of 'test_scope.name'. -let name = ap +let name = ap; ^**^ """, ) verify_exception( """ -let name = ap +let name = ap; + name: """, """ @@ -1802,29 +2123,29 @@ def test_redefinition_failures(): ) verify_exception( """ -func f(name, x, name): - [ap + name] = 1 - [ap + x] = 2 -end +func f(name, x, name) { + [ap + name] = 1; + [ap + x] = 2; +} """, """ file:?:?: Redefinition of 'test_scope.f.Args.name'. -func f(name, x, name): +func f(name, x, name) { ^**^ """, ) verify_exception( """ -func f() -> (name : felt, x : felt, name : felt): - [ap] = 1 - [ap] = 2 - ret -end +func f() -> (name: felt, x: felt, name: felt) { + [ap] = 1; + [ap] = 2; + ret; +} """, """ file:?:?: Named tuple cannot have two entries with the same name. -func f() -> (name : felt, x : felt, name : felt): - ^*********^ +func f() -> (name: felt, x: felt, name: felt) { + ^********^ """, ) @@ -1832,12 +2153,11 @@ def test_redefinition_failures(): def test_directives(): program = preprocess_str( code="""\ -# This is a comment. - +// This is a comment. %builtins ab cd ef -[fp] = [fp] +[fp] = [fp]; """, prime=PRIME, ) @@ -1847,7 +2167,7 @@ def test_directives(): == """\ %builtins ab cd ef -[fp] = [fp] +[fp] = [fp]; """ ) @@ -1855,7 +2175,7 @@ def test_directives(): def test_directives_failures(): verify_exception( """ -[fp] = [fp] +[fp] = [fp]; %builtins ab cd ef """, """ @@ -1879,136 +2199,136 @@ def test_directives_failures(): def test_conditionals(): program = preprocess_str( code=""" -let x = 2 -if [ap] * 2 == [fp] + 3: - let x = 3 - [ap] = x; ap++ -else: - let x = 4 - [ap] = x; ap++ -end +let x = 2; +if ([ap] * 2 == [fp] + 3) { + let x = 3; + [ap] = x, ap++; +} else { + let x = 4; + [ap] = x, ap++; +} """, prime=PRIME, ) assert ( program.format() == """\ -[ap] = [ap] * 2; ap++ -[ap] = [fp] + 3; ap++ -[ap] = [ap + (-2)] - [ap + (-1)]; ap++ -jmp rel 6 if [ap + (-1)] != 0 -[ap] = 3; ap++ -jmp rel 4 -[ap] = 4; ap++ +[ap] = [ap] * 2, ap++; +[ap] = [fp] + 3, ap++; +[ap] = [ap + (-2)] - [ap + (-1)], ap++; +jmp rel 6 if [ap + (-1)] != 0; +[ap] = 3, ap++; +jmp rel 4; +[ap] = 4, ap++; """ ) program = preprocess_str( code=""" -if [ap] == [fp]: - ret -else: - [ap] = [ap] -end -[fp] = [fp] +if ([ap] == [fp]) { + ret; +} else { + [ap] = [ap]; +} +[fp] = [fp]; """, prime=PRIME, ) assert ( program.format() == """\ -[ap] = [ap] - [fp]; ap++ -jmp rel 3 if [ap + (-1)] != 0 -ret -[ap] = [ap] -[fp] = [fp] +[ap] = [ap] - [fp], ap++; +jmp rel 3 if [ap + (-1)] != 0; +ret; +[ap] = [ap]; +[fp] = [fp]; """ ) program = preprocess_str( code=""" -if [ap] == 0: - ret -end -[fp] = [fp] +if ([ap] == 0) { + ret; +} +[fp] = [fp]; """, prime=PRIME, ) assert ( program.format() == """\ -jmp rel 3 if [ap] != 0 -ret -[fp] = [fp] +jmp rel 3 if [ap] != 0; +ret; +[fp] = [fp]; """ ) # No jump if there is no "Non-equal" block. program = preprocess_str( code=""" -if [ap] == 0: - [fp + 1] = [fp + 1] -end -[fp] = [fp] +if ([ap] == 0) { + [fp + 1] = [fp + 1]; +} +[fp] = [fp]; """, prime=PRIME, ) assert ( program.format() == """\ -jmp rel 3 if [ap] != 0 -[fp + 1] = [fp + 1] -[fp] = [fp] +jmp rel 3 if [ap] != 0; +[fp + 1] = [fp + 1]; +[fp] = [fp]; """ ) program = preprocess_str( code=""" -if [ap] != 0: - ret -end -[fp] = [fp] +if ([ap] != 0) { + ret; +} +[fp] = [fp]; """, prime=PRIME, ) assert ( program.format() == """\ -jmp rel 4 if [ap] != 0 -jmp rel 3 -ret -[fp] = [fp] +jmp rel 4 if [ap] != 0; +jmp rel 3; +ret; +[fp] = [fp]; """ ) # With locals. program = preprocess_str( code=""" -func a(): - alloc_locals - local a - if [ap] != 0: - local b = 7 - a = 5 - else: - # This is a different local named b also. - local b = 6 - # This is the same local defined above. - a = 3 - end - [fp] = [fp] - ret -end +func a() { + alloc_locals; + local a; + if ([ap] != 0) { + local b = 7; + a = 5; + } else { + // This is a different local named b also. + local b = 6; + // This is the same local defined above. + a = 3; + } + [fp] = [fp]; + ret; +} """, prime=PRIME, ) assert ( program.format() == """\ -ap += 3 -jmp rel 8 if [ap] != 0 -[fp + 2] = 6 -[fp] = 3 -jmp rel 6 -[fp + 1] = 7 -[fp] = 5 -[fp] = [fp] -ret +ap += 3; +jmp rel 8 if [ap] != 0; +[fp + 2] = 6; +[fp] = 3; +jmp rel 6; +[fp + 1] = 7; +[fp] = 5; +[fp] = [fp]; +ret; """ ) @@ -2016,12 +2336,12 @@ def test_conditionals(): def test_hints_good(): code = """\ %{ hint0 %} -[fp] = [fp] +[fp] = [fp]; %{ hint1 hint2 %} -[fp] = [fp] +[fp] = [fp]; """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == code @@ -2029,32 +2349,32 @@ def test_hints_good(): def test_hints_unindent(): before = """\ - %{ - hint1 - hint2 -%} -[fp] = [fp] -func f(): - %{ - if a: - b +%{ + hint1 + hint2 %} -[fp] = [fp] -ret -end +[fp] = [fp]; +func f() { + %{ + if a: + b + %} + [fp] = [fp]; + ret; +} """ after = """\ %{ hint1 hint2 %} -[fp] = [fp] +[fp] = [fp]; %{ if a: b %} -[fp] = [fp] -ret +[fp] = [fp]; +ret; """ program = preprocess_str(code=before, prime=PRIME) assert program.format() == after @@ -2064,7 +2384,7 @@ def test_hints_failures(): verify_exception( """ %{ -hint + hint %} """, """ @@ -2075,27 +2395,28 @@ def test_hints_failures(): ) verify_exception( """ -func f(): -%{ -hint -%} -end -[ap] = 1 +func f() { + %{ + hint + %} +} +[ap] = 1; """, """ file:?:?: Found a hint at the end of a code block. Hints must be followed by an instruction. -%{ -^^ + %{ + ^^ """, ) verify_exception( """ -[fp] = [fp] +[fp] = [fp]; %{ -hint + hint %} + label: -[fp] = [fp] +[fp] = [fp]; """, """ file:?:?: Hints before labels are not allowed. @@ -2135,56 +2456,59 @@ def test_builtin_directive_duplicate_entry(): def test_references(): program = preprocess_str( code=""" -call label1 +call label1; + label1: -ret +ret; + +let x = ap + 1; -let x = ap + 1 label2: -[x] = 1; ap++ -[x + 3] = 2; ap++ -[x - 2] = 3; ap++ -[x - 2] = 3; ap++ -jmp label1 if [x] != 0; ap++ -jmp label3 if [x] != 0 -[x - 2] = 4 -[x - 4] = 5 -[x - 6] = 6; ap++ -[ap] = [ap]; ap++ -ap += 4 -[x] = 7 - -call label3 +[x] = 1, ap++; +[x + 3] = 2, ap++; +[x - 2] = 3, ap++; +[x - 2] = 3, ap++; +jmp label1 if [x] != 0, ap++; +jmp label3 if [x] != 0; +[x - 2] = 4; +[x - 4] = 5; +[x - 6] = 6, ap++; +[ap] = [ap], ap++; +ap += 4; +[x] = 7; + +call label3; + label3: -ret +ret; -let y = ap -[y] = 0; ap++ -[y] = 0; ap++ +let y = ap; +[y] = 0, ap++; +[y] = 0, ap++; """, prime=PRIME, ) assert ( program.format() == """\ -call rel 2 -ret -[ap + 1] = 1; ap++ -[ap + 3] = 2; ap++ -[ap + (-3)] = 3; ap++ -[ap + (-4)] = 3; ap++ -jmp rel -9 if [ap + (-3)] != 0; ap++ -jmp rel 15 if [ap + (-4)] != 0 -[ap + (-6)] = 4 -[ap + (-8)] = 5 -[ap + (-10)] = 6; ap++ -[ap] = [ap]; ap++ -ap += 4 -[ap + (-10)] = 7 -call rel 2 -ret -[ap] = 0; ap++ -[ap + (-1)] = 0; ap++ +call rel 2; +ret; +[ap + 1] = 1, ap++; +[ap + 3] = 2, ap++; +[ap + (-3)] = 3, ap++; +[ap + (-4)] = 3, ap++; +jmp rel -9 if [ap + (-3)] != 0, ap++; +jmp rel 15 if [ap + (-4)] != 0; +[ap + (-6)] = 4; +[ap + (-8)] = 5; +[ap + (-10)] = 6, ap++; +[ap] = [ap], ap++; +ap += 4; +[ap + (-10)] = 7; +call rel 2; +ret; +[ap] = 0, ap++; +[ap + (-1)] = 0, ap++; """ ) @@ -2193,18 +2517,18 @@ def test_reference_type_deduction(): scope = TEST_SCOPE program = preprocess_str( code=""" -struct T: - member t : felt -end - -func foo(): - let a = cast(0, T***) - tempvar b = [a] - tempvar c : felt* = [a] - let d = [b] - let e : felt* = [b] - return () -end +struct T { + t: felt, +} + +func foo() { + let a = cast(0, T***); + tempvar b = [a]; + tempvar c: felt* = [a]; + let d = [b]; + let e: felt* = [b]; + return (); +} """, prime=PRIME, main_scope=scope, @@ -2227,27 +2551,27 @@ def get_reference_type(name): def test_rebind_reference(): program = preprocess_str( code=""" -struct T: - member pad0 : felt - member pad1 : felt - member t : felt -end - -let x : T* = cast(ap + 1, T*) -let y = &x.t -[cast(x, felt)] = x.t -let x : T* = cast(fp - 3, T*) -[cast(x, felt)] = x.t -[y] = [y] +struct T { + pad0: felt, + pad1: felt, + t: felt, +} + +let x: T* = cast(ap + 1, T*); +let y = &x.t; +[cast(x, felt)] = x.t; +let x: T* = cast(fp - 3, T*); +[cast(x, felt)] = x.t; +[y] = [y]; """, prime=PRIME, ) assert ( program.format() == """\ -[ap + 1] = [ap + 3] -[fp + (-3)] = [fp + (-1)] -[ap + 3] = [ap + 3] +[ap + 1] = [ap + 3]; +[fp + (-3)] = [fp + (-1)]; +[ap + 3] = [ap + 3]; """ ) @@ -2255,13 +2579,13 @@ def test_rebind_reference(): def test_rebind_reference_failures(): verify_exception( """ -let x = cast(ap, felt*) -let x = cast(ap, felt**) +let x = cast(ap, felt*); +let x = cast(ap, felt**); """, """ file:?:?: Reference rebinding must preserve the reference type. Previous type: 'felt*', \ new type: 'felt**'. -let x = cast(ap, felt**) +let x = cast(ap, felt**); ^ """, ) @@ -2270,11 +2594,11 @@ def test_rebind_reference_failures(): def test_invalid_references(): verify_exception( """ -let x = 3 * cast(nondet %{ rnadom.randrange(10) %}, felt) + 5 +let x = 3 * cast(nondet %{ rnadom.randrange(10) %}, felt) + 5; """, """ file:?:?: The use of hints in reference expressions is not allowed. -let x = 3 * cast(nondet %{ rnadom.randrange(10) %}, felt) + 5 +let x = 3 * cast(nondet %{ rnadom.randrange(10) %}, felt) + 5; ^*******************************************^ """, ) @@ -2287,23 +2611,23 @@ def test_rvalue_func_call_reference_with_nondet(): """ program = preprocess_str( code=""" -func foo(val) -> (res : felt): - return (res=val) -end -let x = foo(nondet %{ 5 %}) -assert x = x +func foo(val) -> (res: felt) { + return (res=val); +} +let x = foo(nondet %{ 5 %}); +assert x = x; """, prime=PRIME, ) assert ( program.format() == """\ -[ap] = [fp + (-3)]; ap++ -ret +[ap] = [fp + (-3)], ap++; +ret; %{ memory[ap] = to_felt_or_relocatable(5) %} -ap += 1 -call rel -4 -[ap + (-1)] = [ap + (-1)] +ap += 1; +call rel -4; +[ap + (-1)] = [ap + (-1)]; """ ) @@ -2311,127 +2635,129 @@ def test_rvalue_func_call_reference_with_nondet(): def test_reference_over_calls(): program = preprocess_str( code=""" -func f(): - ap += 3 - jmp label1 if [ap] != 0; ap++ - [ap] = [ap]; ap++ - ret +func f() { + ap += 3; + jmp label1 if [ap] != 0, ap++; + [ap] = [ap], ap++; + ret; + label1: - ap += 1 - ret -end + ap += 1; + ret; +} -let x = ap + 1 -[x] = 0 -call f -[x] = 0 +let x = ap + 1; +[x] = 0; +call f; +[x] = 0; """, prime=PRIME, ) assert ( program.format() == """\ -ap += 3 -jmp rel 4 if [ap] != 0; ap++ -[ap] = [ap]; ap++ -ret -ap += 1 -ret -[ap + 1] = 0 -call rel -11 -[ap + (-6)] = 0 +ap += 3; +jmp rel 4 if [ap] != 0, ap++; +[ap] = [ap], ap++; +ret; +ap += 1; +ret; +[ap + 1] = 0; +call rel -11; +[ap + (-6)] = 0; """ ) def test_struct_no_revocation(): program = preprocess_str( - code=f""" -struct A: - member x : felt - member y : felt -end -func main() -> (res : A): - alloc_locals - tempvar a : A = A(1, 2) - ap += [ap] - return (res=a) -end + code=""" +struct A { + x: felt, + y: felt, +} +func main() -> (res: A) { + alloc_locals; + tempvar a: A = A(1, 2); + ap += [ap]; + return (res=a); +} """, prime=PRIME, ) assert ( program.format() == """\ -ap += 2 -[ap] = 1; ap++ -[ap] = 2; ap++ -[fp] = [ap + (-2)] -[fp + 1] = [ap + (-1)] -ap += [ap] -[ap] = [fp]; ap++ -[ap] = [fp + 1]; ap++ -ret +ap += 2; +[ap] = 1, ap++; +[ap] = 2, ap++; +[fp] = [ap + (-2)]; +[fp + 1] = [ap + (-1)]; +ap += [ap]; +[ap] = [fp], ap++; +[ap] = [fp + 1], ap++; +ret; """ ) def test_reference_over_calls_no_revocation(): program = preprocess_str( - code=f""" -func f(): - ap += 3 - jmp label1 if [ap] != 0 - [ap] = [ap]; ap++ + code=""" +func f() { + ap += 3; + jmp label1 if [ap] != 0; + [ap] = [ap], ap++; + label1: - ret -end + ret; +} -func main(): - alloc_locals - let x = [ap + 1] - call f - x = 0 - ret -end +func main() { + alloc_locals; + let x = [ap + 1]; + call f; + x = 0; + ret; +} """, prime=PRIME, ) assert ( program.format() == """\ -ap += 3 -jmp rel 3 if [ap] != 0 -[ap] = [ap]; ap++ -ret -ap += 1 -[fp] = [ap + 1] -call rel -9 -[fp] = 0 -ret +ap += 3; +jmp rel 3 if [ap] != 0; +[ap] = [ap], ap++; +ret; +ap += 1; +[fp] = [ap + 1]; +call rel -9; +[fp] = 0; +ret; """ ) def test_revoke_correction_invalid_reference(): verify_exception( - f""" -func main(): - alloc_locals - let x = ap - ap += [ap] - x = x -end + """ +func main() { + alloc_locals; + let x = ap; + ap += [ap]; + x = x; +} """, """\ file:?:?: While auto generating local variable for 'x'. - let x = ap + let x = ap; ^ file:?:?: While expanding the reference 'x' in: - let x = ap + let x = ap; ^ file:?:?: ap may only be used in an expression of the form [ap + ]. - let x = ap + let x = ap; ^^ """, ) @@ -2440,37 +2766,37 @@ def test_revoke_correction_invalid_reference(): def test_dummy_reference_expr_error_flow(): verify_exception( """\ -func test(): - alloc_locals - tempvar a - ap += [ap] # Revoke reference to trigger auto locals flow. - tempvar addr = &a - return () -end +func test() { + alloc_locals; + tempvar a; + ap += [ap]; // Revoke reference to trigger auto locals flow. + tempvar addr = &a; + return (); +} """, """ file:?:?: Using the value of fp directly, requires defining a variable named __fp__. - tempvar addr = &a + tempvar addr = &a; ^ """, ) verify_exception( """\ -struct MyStruct: -end +struct MyStruct { +} -func test(): - alloc_locals - tempvar a : MyStruct - ap += [ap] # Revoke reference to trigger auto locals flow. - assert a.missing_member = 5 - return () -end +func test() { + alloc_locals; + tempvar a: MyStruct; + ap += [ap]; // Revoke reference to trigger auto locals flow. + assert a.missing_member = 5; + return (); +} """, """ file:?:?: Member 'missing_member' does not appear in definition of struct 'test_scope.MyStruct'. - assert a.missing_member = 5 + assert a.missing_member = 5; ^**************^ """, exc_type=CairoTypeError, @@ -2479,60 +2805,90 @@ def test_dummy_reference_expr_error_flow(): def test_references_revoked_multiple_location(): verify_exception( - f""" -func main(): - alloc_locals - if [ap] == 0: - let x = [ap] - else: - let y = [ap] - let x = y - end - ap += [fp] - x = 0 -end + """ +func main() { + alloc_locals; + if ([ap] == 0) { + let x = [ap]; + } else { + let y = [ap]; + let x = y; + } + ap += [fp]; + x = 0; +} """, """\ file:?:?: Reference 'x' was revoked. - x = 0 + x = 0; ^ Reference was defined here: file:?:? - let x = y + let x = y; ^ file:?:? - let x = [ap] + let x = [ap]; ^ """, ) +def test_auto_locals_inject_failed(): + verify_exception( + """ +func foo{x}() -> felt { + ret; +} +func bar{x}() { + alloc_locals; + if (foo() == 0) { + } + ap += [ap]; + x = 0; + return (); +} +""", + """\ +file:?:?: While trying to retrieve the implicit argument 'x' in: + return (); + ^********^ +file:?:?: Reference 'x' was revoked. +func bar{x}() { + ^ +Reference was defined here: +file:?:? + if (foo() == 0) { + ^***^ +""", + ) + + @pytest.mark.parametrize( "revoking_instruction, alloc_locals, valid, has_def_location", [ - ("ap += [fp]", "alloc_locals", True, None), + ("ap += [fp]", "alloc_locals;", True, None), ("ap += [fp]", "", False, True), - ("ap += [fp]", "ap += SIZEOF_LOCALS", False, True), - ("call label", "alloc_locals", True, None), + ("ap += [fp]", "ap += SIZEOF_LOCALS;", False, True), + ("call label", "alloc_locals;", True, None), ("call label", "", False, True), - ("call rel 0", "alloc_locals", True, None), + ("call rel 0", "alloc_locals;", True, None), ("call rel 0", "", False, True), - ("ret", "alloc_locals", False, False), - ("jmp label", "alloc_locals", False, False), - ("jmp rel 0", "alloc_locals", False, False), - ("jmp abs 0", "alloc_locals", False, False), + ("ret", "alloc_locals;", False, False), + ("jmp label", "alloc_locals;", False, False), + ("jmp rel 0", "alloc_locals;", False, False), + ("jmp abs 0", "alloc_locals;", False, False), ], ) def test_references_revoked(revoking_instruction, valid, alloc_locals, has_def_location): code = f""" -func main(): +func main() {{ {alloc_locals} label: - let x = [ap] - {revoking_instruction} - x = 0 - ret -end + let x = [ap]; + {revoking_instruction}; + x = 0; + ret; +}} """ if not valid: assert has_def_location is not None @@ -2540,7 +2896,7 @@ def test_references_revoked(revoking_instruction, valid, alloc_locals, has_def_l """\ Reference was defined here: file:?:? - let x = [ap] + let x = [ap]; ^ """ if has_def_location @@ -2550,7 +2906,7 @@ def test_references_revoked(revoking_instruction, valid, alloc_locals, has_def_l code, f""" file:?:?: Reference 'x' was revoked. - x = 0 + x = 0; ^ {def_loction_str} """, @@ -2562,19 +2918,19 @@ def test_references_revoked(revoking_instruction, valid, alloc_locals, has_def_l def test_references_failures(): verify_exception( """ -let ref = [fp] -let ref2 = ref -[ref2] = [[fp]] +let ref = [fp]; +let ref2 = ref; +[ref2] = [[fp]]; """, """ file:?:?: While expanding the reference 'ref2' in: -[ref2] = [[fp]] +[ref2] = [[fp]]; ^**^ file:?:?: While expanding the reference 'ref' in: -let ref2 = ref +let ref2 = ref; ^*^ file:?:?: Expected a register. Found: [fp]. -let ref = [fp] +let ref = [fp]; ^**^ Preprocessed instruction: [[fp]] = [[fp]] @@ -2596,19 +2952,19 @@ def test_references_failures(): ], ) def test_reference_flow_revokes(valid, has0, has1, has2): - def0 = "let ref = [fp]" if has0 else "" - def1 = "let ref = [fp + 1]" if has1 else "" - def2 = "let ref = [fp + 2]" if has2 else "" + def0 = "let ref = [fp];" if has0 else "" + def1 = "let ref = [fp + 1];" if has1 else "" + def2 = "let ref = [fp + 2];" if has2 else "" code = f""" {def0} -jmp b if [ap] != 0 +jmp b if [ap] != 0; a: {def1} -jmp c +jmp c; b: {def2} c: -[ref] = [fp + 3] +[ref] = [fp + 3]; """ if valid: preprocess_str(code, prime=PRIME) @@ -2617,7 +2973,7 @@ def test_reference_flow_revokes(valid, has0, has1, has2): code, """ file:?:?: Reference 'ref' was revoked. -[ref] = [fp + 3] +[ref] = [fp + 3]; ^*^ """, ) @@ -2626,23 +2982,23 @@ def test_reference_flow_revokes(valid, has0, has1, has2): def test_implicit_arg_revocation(): verify_exception( """ -func foo{x}(y): - foo(y=1) - # The following instruction revokes the implicit argument x - ap += [fp] - return foo(y=2) -end +func foo{x}(y) { + foo(y=1); + // The following instruction revokes the implicit argument x + ap += [fp]; + return foo(y=2); +} """, """ file:?:?: While trying to retrieve the implicit argument 'x' in: - return foo(y=2) + return foo(y=2); ^******^ file:?:?: Reference 'x' was revoked. -func foo{x}(y): +func foo{x}(y) { ^ Reference was defined here: file:?:? - foo(y=1) + foo(y=1); ^******^ """, ) @@ -2651,39 +3007,39 @@ def test_implicit_arg_revocation(): def test_implicit_arg_no_revocation(): program = preprocess_str( code=""" -struct T: - member a : felt - member b : felt -end -func foo{x}(y): - alloc_locals - tempvar z: T = T(1,2) - foo(y=1) - # The following instruction revokes the implicit argument x, which is therefore copied to a - # local variable. - ap += [fp] - return foo(y=z.a) -end +struct T { + a: felt, + b: felt, +} +func foo{x}(y) { + alloc_locals; + tempvar z: T = T(1, 2); + foo(y=1); + // The following instruction revokes the implicit argument x, which is therefore copied to a + // local variable. + ap += [fp]; + return foo(y=z.a); +} """, prime=PRIME, ) assert ( program.format() == """\ -ap += 3 -[ap] = 1; ap++ -[ap] = 2; ap++ -[fp] = [ap + (-2)] -[fp + 1] = [ap + (-1)] -[ap] = [fp + (-4)]; ap++ -[ap] = 1; ap++ -call rel -11 -[fp + 2] = [ap + (-1)] -ap += [fp] -[ap] = [fp + 2]; ap++ -[ap] = [fp]; ap++ -call rel -17 -ret +ap += 3; +[ap] = 1, ap++; +[ap] = 2, ap++; +[fp] = [ap + (-2)]; +[fp + 1] = [ap + (-1)]; +[ap] = [fp + (-4)], ap++; +[ap] = 1, ap++; +call rel -11; +[fp + 2] = [ap + (-1)]; +ap += [fp]; +[ap] = [fp + 2], ap++; +[ap] = [fp], ap++; +call rel -17; +ret; """ ) @@ -2691,24 +3047,24 @@ def test_implicit_arg_no_revocation(): def test_reference_flow_converge(): program = preprocess_str( """ -if [ap] != 0: - tempvar a = 1 -else: - tempvar a = 2 -end +if ([ap] != 0) { + tempvar a = 1; +} else { + tempvar a = 2; +} -assert a = a +assert a = a; """, prime=PRIME, ) assert ( program.format() == """\ -jmp rel 6 if [ap] != 0 -[ap] = 2; ap++ -jmp rel 4 -[ap] = 1; ap++ -[ap + (-1)] = [ap + (-1)] +jmp rel 6 if [ap] != 0; +[ap] = 2, ap++; +jmp rel 4; +[ap] = 1, ap++; +[ap + (-1)] = [ap + (-1)]; """ ) @@ -2717,30 +3073,30 @@ def test_typed_references(): scope = TEST_SCOPE program = preprocess_str( code=""" -func main(): - struct T: - member pad0 : felt - member pad1 : felt - member pad2 : felt - member b : T* - end - - struct Struct: - member pad0 : felt - member pad1 : felt - member a : T* - end - - let x : Struct* = cast(ap + 10, Struct*) - let y : Struct = [x] - - [fp] = x.a - assert [fp] = cast(x.a.b, felt) - assert [fp] = cast(x.a.b.b, felt) - - [fp] = y.a + 1 - ret -end +func main() { + struct T { + pad0: felt, + pad1: felt, + pad2: felt, + b: T*, + } + + struct Struct { + pad0: felt, + pad1: felt, + a: T*, + } + + let x: Struct* = cast(ap + 10, Struct*); + let y: Struct = [x]; + + [fp] = x.a; + assert [fp] = cast(x.a.b, felt); + assert [fp] = cast(x.a.b.b, felt); + + [fp] = y.a + 1; + ret; +} """, prime=PRIME, main_scope=scope, @@ -2765,12 +3121,12 @@ def get_reference(name): assert ( program.format() == """\ -[fp] = [ap + 12] -[fp] = [[ap + 12] + 3] -[ap] = [[ap + 12] + 3]; ap++ -[fp] = [[ap + (-1)] + 3] -[fp] = [ap + 11] + 1 -ret +[fp] = [ap + 12]; +[fp] = [[ap + 12] + 3]; +[ap] = [[ap + 12] + 3], ap++; +[fp] = [[ap + (-1)] + 3]; +[fp] = [ap + 11] + 1; +ret; """ ) @@ -2778,43 +3134,43 @@ def get_reference(name): def test_typed_references_failures(): verify_exception( f""" -let x = fp -x.a = x.a +let x = fp; +x.a = x.a; """, """ file:?:?: Cannot apply dot-operator to non-struct type 'felt'. -x.a = x.a +x.a = x.a; ^*^ """, exc_type=CairoTypeError, ) verify_exception( - f""" -struct T: - member z : felt -end + """ +struct T { + z: felt, +} -let x : T = ap -x.z = x.z +let x: T = ap; +x.z = x.z; """, """ file:?:?: Cannot assign an expression of type 'felt' to a reference of type 'test_scope.T'. -let x : T = ap - ^ +let x: T = ap; + ^ """, ) verify_exception( - f""" -struct T: - member z : felt -end + """ +struct T { + z: felt, +} -let x : T* = [cast(ap, T*)] +let x: T* = [cast(ap, T*)]; """, """ file:?:?: Cannot assign an expression of type 'test_scope.T' to a reference of type 'test_scope.T*'. -let x : T* = [cast(ap, T*)] - ^^ +let x: T* = [cast(ap, T*)]; + ^^ """, ) @@ -2823,20 +3179,20 @@ def test_return_value_reference(): scope = TEST_SCOPE program = preprocess_str( code=""" -func foo() -> (val : felt, x : felt, y : felt): - ret -end +func foo() -> (val: felt, x: felt, y: felt) { + ret; +} -func main(): - let x = call foo - [ap] = 0; ap++ - x.val = 9 +func main() { + let x = call foo; + [ap] = 0, ap++; + x.val = 9; - let y : main.Return = call foo + let y: main.Return = call foo; - let z = call abs 0 - ret -end + let z = call abs 0; + ret; +} """, prime=PRIME, main_scope=scope, @@ -2851,7 +3207,7 @@ def get_reference(name): ) assert simplify_type_system(get_reference("main.x").value)[1] == parse_type( - "(val : felt, x : felt, y : felt)" + "(val: felt, x: felt, y: felt)" ) assert simplify_type_system(get_reference("main.y").value)[1] == parse_type("()") @@ -2861,67 +3217,67 @@ def get_reference(name): assert ( program.format() == """\ -ret -call rel -1 -[ap] = 0; ap++ -[ap + (-4)] = 9 -call rel -7 -call abs 0 -ret +ret; +call rel -1; +[ap] = 0, ap++; +[ap + (-4)] = 9; +call rel -7; +call abs 0; +ret; """ ) def test_return_value_reference_failures(): verify_exception( - f""" -let x = call foo + """ +let x = call foo; """, """ file:?:?: Unknown identifier 'foo'. -let x = call foo +let x = call foo; ^*^ """, ) verify_exception( - f""" -func foo(): - ret -end -let x = call foo -[x.a] = 0 + """ +func foo() { + ret; +} +let x = call foo; +[x.a] = 0; """, """ file:?:?: Member 'a' does not appear in definition of tuple type '()'. -[x.a] = 0 +[x.a] = 0; ^*^ """, exc_type=CairoTypeError, ) verify_exception( - f""" -func foo(): - ret -end -let x : unknown_type* = call foo + """ +func foo() { + ret; +} +let x: unknown_type* = call foo; """, """ file:?:?: Unknown identifier 'unknown_type'. -let x : unknown_type* = call foo - ^**********^ +let x: unknown_type* = call foo; + ^**********^ """, ) verify_exception( - f""" -struct T: - member s : felt -end -let x : T* = cast(ap, T*) -[ap] = x.a + """ +struct T { + s: felt, +} +let x: T* = cast(ap, T*); +[ap] = x.a; """, """ file:?:?: Member 'a' does not appear in definition of struct 'test_scope.T'. -[ap] = x.a +[ap] = x.a; ^*^ """, exc_type=CairoTypeError, @@ -2930,186 +3286,186 @@ def test_return_value_reference_failures(): def test_unpacking(): code = """\ -struct T: - member a : felt - member b : felt -end -func f() -> (a : felt, b : felt, c : felt, d : felt , e : T): - return (1,2,3,4,[cast(5,T*)]) -end -func g(): - alloc_locals - let (a, local b, local c, d : T*, e) = f() - a = d.b - a = b + c; ap++ - a = b + c - # The type of e is deduced from the return type of f(). - a = e.b - let (a, _, local c, x, _) = f() - ap += [ap] - a = a - x = x - ret -end +struct T { + a: felt, + b: felt, +} +func f() -> (a: felt, b: felt, c: felt, d: felt, e: T) { + return (1, 2, 3, 4, [cast(5, T*)]); +} +func g() { + alloc_locals; + let (a, local b, local c, d: T*, e) = f(); + a = d.b; + a = b + c, ap++; + a = b + c; + // The type of e is deduced from the return type of f(). + a = e.b; + let (a, _, local c, x, _) = f(); + ap += [ap]; + a = a; + x = x; + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 5; ap++ -[ap] = 6; ap++ -[ap] = 1; ap++ -[ap] = 2; ap++ -[ap] = 3; ap++ -[ap] = 4; ap++ -[ap] = [[ap + (-6)]]; ap++ -[ap] = [[ap + (-6)]]; ap++ -ret -ap += 5 -call rel -17 -[fp] = [ap + (-5)] -[fp + 1] = [ap + (-4)] -[ap + (-6)] = [[ap + (-3)] + 1] -[ap + (-6)] = [fp] + [fp + 1]; ap++ -[ap + (-7)] = [fp] + [fp + 1] -[ap + (-7)] = [ap + (-2)] -call rel -25 -[fp + 2] = [ap + (-4)] -[fp + 3] = [ap + (-6)] -[fp + 4] = [ap + (-3)] -ap += [ap] -[fp + 3] = [fp + 3] -[fp + 4] = [fp + 4] -ret +[ap] = 5, ap++; +[ap] = 6, ap++; +[ap] = 1, ap++; +[ap] = 2, ap++; +[ap] = 3, ap++; +[ap] = 4, ap++; +[ap] = [[ap + (-6)]], ap++; +[ap] = [[ap + (-6)]], ap++; +ret; +ap += 5; +call rel -17; +[fp] = [ap + (-5)]; +[fp + 1] = [ap + (-4)]; +[ap + (-6)] = [[ap + (-3)] + 1]; +[ap + (-6)] = [fp] + [fp + 1], ap++; +[ap + (-7)] = [fp] + [fp + 1]; +[ap + (-7)] = [ap + (-2)]; +call rel -25; +[fp + 2] = [ap + (-4)]; +[fp + 3] = [ap + (-6)]; +[fp + 4] = [ap + (-3)]; +ap += [ap]; +[fp + 3] = [fp + 3]; +[fp + 4] = [fp + 4]; +ret; """ ) def test_unpacking_failures(): verify_exception( - f""" -func foo() -> (a : felt): - ret -end -let (a, b) = foo() + """ +func foo() -> (a: felt) { + ret; +} +let (a, b) = foo(); """, """ file:?:?: Expected 1 unpacking identifier, found 2. -let (a, b) = foo() +let (a, b) = foo(); ^**^ """, ) verify_exception( f""" -let (a, b) = 1 + 3 +let (a, b) = 1 + 3; """, """ -file:?:?: Cannot unpack 1 + 3. -let (a, b) = 1 + 3 +file:?:?: Unpack binding is currently only supported for function calls. Got: 1 + 3. +let (a, b) = 1 + 3; ^***^ """, ) verify_exception( - f""" -struct T: - member a : felt - member b : felt -end -func foo() -> (a : felt, b : T): - ret -end -let (a, b, c) = foo() + """ +struct T { + a: felt, + b: felt, +} +func foo() -> (a: felt, b: T) { + ret; +} +let (a, b, c) = foo(); """, """ file:?:?: Expected 2 unpacking identifiers, found 3. -let (a, b, c) = foo() +let (a, b, c) = foo(); ^*****^ """, ) verify_exception( - f""" -struct T: - member a : felt - member b : felt -end -func foo() -> (a : felt, b : felt): - ret -end -let (a, b : T) = foo() + """ +struct T { + a: felt, + b: felt, +} +func foo() -> (a: felt, b: felt) { + ret; +} +let (a, b: T) = foo(); """, """ file:?:?: Expected expression of type 'felt', got 'test_scope.T'. -let (a, b : T) = foo() - ^***^ +let (a, b: T) = foo(); + ^**^ """, ) verify_exception( - f""" -struct T: - member a : felt - member b : felt -end -struct S: - member a : felt - member b : felt -end -func foo() -> (a : felt, b : T): - ret -end -func test(): - alloc_locals - let (a, local b : S) = foo() - ret -end + """ +struct T { + a: felt, + b: felt, +} +struct S { + a: felt, + b: felt, +} +func foo() -> (a: felt, b: T) { + ret; +} +func test() { + alloc_locals; + let (a, local b: S) = foo(); + ret; +} """, """ file:?:?: Expected expression of type 'test_scope.T', got 'test_scope.S'. - let (a, local b : S) = foo() - ^*********^ + let (a, local b: S) = foo(); + ^********^ """, ) verify_exception( - f""" -struct T: -end + """ +struct T { +} -func foo() -> (a : T*): - ret -end +func foo() -> (a: T*) { + ret; +} -func test(): - alloc_locals - let (local _ : T*) = foo() - ret -end +func test() { + alloc_locals; + let (local _: T*) = foo(); + ret; +} """, """ file:?:?: Reference name cannot be '_'. - let (local _ : T*) = foo() - ^**********^ + let (local _: T*) = foo(); + ^*********^ """, ) verify_exception( - f""" -func foo() -> (a : felt): - ret -end -let (a) = foo() -[a] = [a] + """ +func foo() -> (a: felt) { + ret; +} +let (a) = foo(); +[a] = [a]; """, """ file:?:?: While expanding the reference 'a' in: -[a] = [a] +[a] = [a]; ^ file:?:?: Expected a register. Found: [ap + (-1)]. -let (a) = foo() +let (a) = foo(); ^ Preprocessed instruction: [[ap + (-1)]] = [[ap + (-1)]] @@ -3117,73 +3473,101 @@ def test_unpacking_failures(): exc_type=InstructionBuilderError, ) - -def test_unpacking_modifier_failure(): verify_exception( """ -func foo() -> (a : felt, b : felt): - ret -end -let (a, local b) = foo() +func foo() -> felt { + ret; +} +func bar() { + let (a) = foo(); + ret; +} """, """ -file:?:?: Unexpected modifier 'local'. -let (a, local b) = foo() - ^***^ +file:?:?: Cannot unpack the return value of 'foo'. The return type is not a tuple. + let (a) = foo(); + ^***^ +Did you mean: +let a = foo(); """, ) - -def test_member_def_failures(): verify_exception( """ -struct T: - member t -end +func foo() -> felt { + ret; +} +func bar() { + alloc_locals; + let (local a) = foo(); + ret; +} """, """ -file:?:?: Struct members must be explicitly typed (e.g., member x : felt). - member t - ^ +file:?:?: Cannot unpack the return value of 'foo'. The return type is not a tuple. + let (local a) = foo(); + ^***^ +Did you mean: +local a = foo(); """, ) verify_exception( """ -member t : felt +func foo() -> felt { + ret; +} +let (a, b) = foo(); """, """ -file:?:?: The member keyword may only be used inside a struct. -member t : felt - ^******^ +file:?:?: Cannot unpack the return value of 'foo'. The return type is not a tuple. +let (a, b) = foo(); + ^***^ + """, ) + +def test_unpacking_modifier_failure(): verify_exception( """ -struct T: - member local t -end +func foo() -> (a: felt, b: felt) { + ret; +} +let (a, local b) = foo(); """, """ file:?:?: Unexpected modifier 'local'. - member local t - ^***^ +let (a, local b) = foo(); + ^***^ """, ) -def test_bad_struct(): +def test_member_def_failures(): verify_exception( """ -struct T: - return() -end +struct T { + t, +} """, """ -file:?:?: Unexpected statement inside a struct definition. - return() - ^******^ +file:?:?: Struct members must be explicitly typed (e.g., x: felt). + t, + ^ +""", + ) + + verify_exception( + """ +struct T { + local t, +} +""", + """ +file:?:?: Unexpected modifier 'local'. + local t, + ^***^ """, ) @@ -3191,49 +3575,49 @@ def test_bad_struct(): def test_bad_type_annotation(): verify_exception( """ -func foo(): - local a : foo - ret -end +func foo() { + local a: foo; + ret; +} """, """ file:?:?: Expected 'test_scope.foo' to be struct or type_definition. Found: 'function'. - local a : foo - ^*^ + local a: foo; + ^*^ """, ) verify_exception( """ -func foo(): - struct test: - member a : foo* - end +func foo() { + struct test { + a: foo*, + } - ret -end + ret; +} """, """ file:?:?: Expected 'foo' to be a struct. Found: 'function'. - member a : foo* - ^*^ + a: foo*, + ^*^ """, ) verify_exception( """ -func foo(): - struct test: - member a : foo.abc* - end +func foo() { + struct test { + a: foo.abc*, + } - ret -end + ret; +} """, """ file:?:?: Unknown identifier 'test_scope.foo.abc'. - member a : foo.abc* - ^*****^ + a: foo.abc*, + ^*****^ """, ) @@ -3241,17 +3625,17 @@ def test_bad_type_annotation(): def test_cast_failure(): verify_exception( """ -struct A: -end +struct A { +} -func foo(a : A*): - let a = cast(5, A) - return () -end +func foo(a: A*) { + let a = cast(5, A); + return (); +} """, """ file:?:?: Cannot cast 'felt' to 'test_scope.A'. - let a = cast(5, A) + let a = cast(5, A); ^********^ """, exc_type=CairoTypeError, @@ -3261,19 +3645,19 @@ def test_cast_failure(): def test_nested_function_failure(): verify_exception( """ -func foo(): - func bar(): - return() - end - return () -end +func foo() { + func bar() { + return (); + } + return (); +} """, """ file:?:?: Nested functions are not supported. - func bar(): + func bar() { ^*^ Outer function was defined here: file:?:? -func foo(): +func foo() { ^*^ """, ) @@ -3282,20 +3666,18 @@ def test_nested_function_failure(): def test_namespace_inside_function_failure(): verify_exception( """ -func foo(): - namespace MyNamespace: - end - return () -end - - +func foo() { + namespace MyNamespace { + } + return (); +} """, """ file:?:?: Cannot define a namespace inside a function. - namespace MyNamespace: + namespace MyNamespace { ^*********^ Outer function was defined here: file:?:? -func foo(): +func foo() { ^*^ """, ) @@ -3304,13 +3686,13 @@ def test_namespace_inside_function_failure(): def test_namespace_is_not_a_label(): verify_exception( """ -namespace MyNamespace: -end -jmp MyNamespace +namespace MyNamespace { +} +jmp MyNamespace; """, """ file:?:?: Expected a label name. Identifier 'MyNamespace' is of type namespace. -jmp MyNamespace +jmp MyNamespace; ^*********^ """, ) @@ -3318,368 +3700,365 @@ def test_namespace_is_not_a_label(): def test_struct_assignments(): struct_def = """\ -struct B: - member a : felt - member b : felt -end - -struct T: - member a : B - member b : felt -end +struct B { + a: felt, + b: felt, +} + +struct T { + a: B, + b: felt, +} """ code = f"""\ {struct_def} -func f(t : T*): - alloc_locals - local a : T = [t] - return () -end +func f(t: T*) {{ + alloc_locals; + local a: T = [t]; + return (); +}} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 3 -[fp] = [[fp + (-3)]] -[fp + 1] = [[fp + (-3)] + 1] -[fp + 2] = [[fp + (-3)] + 2] -ret +ap += 3; +[fp] = [[fp + (-3)]]; +[fp + 1] = [[fp + (-3)] + 1]; +[fp + 2] = [[fp + (-3)] + 2]; +ret; """ ) code = f"""\ {struct_def} -func copy(src : T**, dest: T**): - assert [[dest]] = [[src]] - return () -end +func copy(src: T**, dest: T**) {{ + assert [[dest]] = [[src]]; + return (); +}} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = [[fp + (-3)]]; ap++ -[ap] = [[fp + (-4)]]; ap++ -[ap] = [[ap + (-1)]]; ap++ -[[ap + (-3)]] = [ap + (-1)] -[ap] = [[fp + (-3)]]; ap++ -[ap] = [[fp + (-4)]]; ap++ -[ap] = [[ap + (-1)] + 1]; ap++ -[[ap + (-3)] + 1] = [ap + (-1)] -[ap] = [[fp + (-3)]]; ap++ -[ap] = [[fp + (-4)]]; ap++ -[ap] = [[ap + (-1)] + 2]; ap++ -[[ap + (-3)] + 2] = [ap + (-1)] -ret +[ap] = [[fp + (-3)]], ap++; +[ap] = [[fp + (-4)]], ap++; +[ap] = [[ap + (-1)]], ap++; +[[ap + (-3)]] = [ap + (-1)]; +[ap] = [[fp + (-3)]], ap++; +[ap] = [[fp + (-4)]], ap++; +[ap] = [[ap + (-1)] + 1], ap++; +[[ap + (-3)] + 1] = [ap + (-1)]; +[ap] = [[fp + (-3)]], ap++; +[ap] = [[fp + (-4)]], ap++; +[ap] = [[ap + (-1)] + 2], ap++; +[[ap + (-3)] + 2] = [ap + (-1)]; +ret; """ ) def test_continuous_structs(): - code = f"""\ -struct A: - member a: felt - member b: felt -end -struct B: - member a: A - member b: felt -end -struct C: - member a: A - member b: B - member c: felt -end - -func foo(x: C): - x.a.a = 1 - x.a.b = 2 - x.b.a.a = 3 - x.b.a.b = 4 - x.b.b = 5 - x.c = 6 - return () -end + code = """\ +struct A { + a: felt, + b: felt, +} +struct B { + a: A, + b: felt, +} +struct C { + a: A, + b: B, + c: felt, +} + +func foo(x: C) { + x.a.a = 1; + x.a.b = 2; + x.b.a.a = 3; + x.b.a.b = 4; + x.b.b = 5; + x.c = 6; + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[fp + (-8)] = 1 -[fp + (-7)] = 2 -[fp + (-6)] = 3 -[fp + (-5)] = 4 -[fp + (-4)] = 5 -[fp + (-3)] = 6 -ret +[fp + (-8)] = 1; +[fp + (-7)] = 2; +[fp + (-6)] = 3; +[fp + (-5)] = 4; +[fp + (-4)] = 5; +[fp + (-3)] = 6; +ret; """ ) def test_nested_struct_casting(): code = """\ -struct S: - member a: felt - member b: felt -end -func f(x : (felt, S)): - return () -end - -func main(): - let s : S = S(2,3) - let arg : (felt, S) = (1, s) - f(arg) - return () -end +struct S { + a: felt, + b: felt, +} +func f(x: (felt, S)) { + return (); +} + +func main() { + let s: S = S(2, 3); + let arg: (felt, S) = (1, s); + f(arg); + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ret -[ap] = 1; ap++ -[ap] = 2; ap++ -[ap] = 3; ap++ -call rel -7 -ret +ret; +[ap] = 1, ap++; +[ap] = 2, ap++; +[ap] = 3, ap++; +call rel -7; +ret; """ ) def test_subscript_operator(): code = """\ -struct T: - member x: felt - member y: felt -end - -struct S: - member a : T - member b : T - member c : T -end - -func f(s_arr : S*, table : felt**, perm : felt*): - assert s_arr[0].b.x = s_arr[1].a.y - assert (&s_arr[0].a)[2].x = (&s_arr[1].b.y)[-2] - - assert table[1][2] = 11 - - assert perm[0] = 1 - assert perm[1] = 0 - assert perm[perm[0]] = 0 - - tempvar i = 2 - tempvar j = 5 - tempvar k = -13 - assert (&(&s_arr[i].b)[j].x)[k] = s_arr[1].c.y - assert table[i][j] = 17 - - return() -end +struct T { + x: felt, + y: felt, +} + +struct S { + a: T, + b: T, + c: T, +} + +func f(s_arr: S*, table: felt**, perm: felt*) { + assert s_arr[0].b.x = s_arr[1].a.y; + assert (&s_arr[0].a)[2].x = (&s_arr[1].b.y)[-2]; + + assert table[1][2] = 11; + + assert perm[0] = 1; + assert perm[1] = 0; + assert perm[perm[0]] = 0; + + tempvar i = 2; + tempvar j = 5; + tempvar k = -13; + assert (&(&s_arr[i].b)[j].x)[k] = s_arr[1].c.y; + assert table[i][j] = 17; + + return (); +} """ program = preprocess_str(code=code, prime=PRIME) expected_result = """\ -[ap] = [[fp + (-5)] + 7]; ap++ # push s_arr[1].a.y -[[fp + (-5)] + 2] = [ap + (-1)] # assert s_arr[0].b.x = s_arr[1].a.y - -[ap] = [[fp + (-5)] + 7]; ap++ # push (&s_arr[1].b.y)[-2] -[[fp + (-5)] + 4] = [ap + (-1)] # assert (&s_arr[0].a)[2].x = (&s_arr[1].b.y)[-2] - - -[ap] = [[fp + (-4)] + 1]; ap++ # push table[1] -[ap] = 11; ap++ # push 11 -[[ap + (-2)] + 2] = [ap + (-1)] # assert table[1][2] = 11 - - -[ap] = 1; ap++ # push 1 -[[fp + (-3)]] = [ap + (-1)] # assert perm[0] = 1 - -[ap] = 0; ap++ # push 0 -[[fp + (-3)] + 1] = [ap + (-1)] # assert perm[1] = 0 - -[ap] = [[fp + (-3)]]; ap++ # push perm[0] -[ap] = [fp + (-3)] + [ap + (-1)]; ap++ # push perm + perm[0] -[ap] = 0; ap++ # push 0 -[[ap + (-2)]] = [ap + (-1)] # assert perm[perm[0]] = 0 - - -[ap] = 2; ap++ # tempvar i = 2 -[ap] = 5; ap++ # tempvar j = 5 -[ap] = -13; ap++ # tempvar k = -13 - -[ap] = [ap + (-3)] * 6; ap++ # push i * 6 -[ap] = [ap + (-1)] + 2; ap++ # push i * 6 + 2 -[ap] = [fp + (-5)] + [ap + (-1)]; ap++ # push &s_arr[i].b ( = s_arr + i * 6 + 2) -[ap] = [ap + (-5)] * 2; ap++ # push j * 2 -[ap] = [ap + (-2)] + [ap + (-1)]; ap++ # push &(&s_arr[i].b)[j].x -[ap] = [ap + (-1)] + [ap + (-6)]; ap++ # push &(&s_arr[i].b)[j].x + k -[ap] = [[fp + (-5)] + 11]; ap++ # push s_arr[1].b.y -[[ap + (-2)]] = [ap + (-1)] # assert (&(&s_arr[i].a)[j].x)[k] = s_arr[1].b.y - -[ap] = [fp + (-4)] + [ap + (-10)]; ap++ # push table + i -[ap] = [[ap + (-1)]]; ap++ # push table[i] -[ap] = [ap + (-1)] + [ap + (-11)]; ap++ # push table[i] + j -[ap] = 17; ap++ # push 17 -[[ap + (-2)]] = [ap + (-1)] # assert table[i][j] = 17 -ret +[ap] = [[fp + (-5)] + 7], ap++; // push s_arr[1].a.y +[[fp + (-5)] + 2] = [ap + (-1)]; // assert s_arr[0].b.x = s_arr[1].a.y + +[ap] = [[fp + (-5)] + 7], ap++; // push (&s_arr[1].b.y)[-2] +[[fp + (-5)] + 4] = [ap + (-1)]; // assert (&s_arr[0].a)[2].x = (&s_arr[1].b.y)[-2] + +[ap] = [[fp + (-4)] + 1], ap++; // push table[1] +[ap] = 11, ap++; // push 11 +[[ap + (-2)] + 2] = [ap + (-1)]; // assert table[1][2] = 11 + +[ap] = 1, ap++; // push 1 +[[fp + (-3)]] = [ap + (-1)]; // assert perm[0] = 1 + +[ap] = 0, ap++; // push 0 +[[fp + (-3)] + 1] = [ap + (-1)]; // assert perm[1] = 0 + +[ap] = [[fp + (-3)]], ap++; // push perm[0] +[ap] = [fp + (-3)] + [ap + (-1)], ap++; // push perm + perm[0] +[ap] = 0, ap++; // push 0 +[[ap + (-2)]] = [ap + (-1)]; // assert perm[perm[0]] = 0 + +[ap] = 2, ap++; // tempvar i = 2 +[ap] = 5, ap++; // tempvar j = 5 +[ap] = -13, ap++; // tempvar k = -13 + +[ap] = [ap + (-3)] * 6, ap++; // push i * 6 +[ap] = [ap + (-1)] + 2, ap++; // push i * 6 + 2 +[ap] = [fp + (-5)] + [ap + (-1)], ap++; // push &s_arr[i].b ( = s_arr + i * 6 + 2) +[ap] = [ap + (-5)] * 2, ap++; // push j * 2 +[ap] = [ap + (-2)] + [ap + (-1)], ap++; // push &(&s_arr[i].b)[j].x +[ap] = [ap + (-1)] + [ap + (-6)], ap++; // push &(&s_arr[i].b)[j].x + k +[ap] = [[fp + (-5)] + 11], ap++; // push s_arr[1].b.y +[[ap + (-2)]] = [ap + (-1)]; // assert (&(&s_arr[i].a)[j].x)[k] = s_arr[1].b.y + +[ap] = [fp + (-4)] + [ap + (-10)], ap++; // push table + i +[ap] = [[ap + (-1)]], ap++; // push table[i] +[ap] = [ap + (-1)] + [ap + (-11)], ap++; // push table[i] + j +[ap] = 17, ap++; // push 17 +[[ap + (-2)]] = [ap + (-1)]; // assert table[i][j] = 17 +ret; """ assert program.format() == strip_comments_and_linebreaks(expected_result) def test_dot_operator(): code = """\ -struct R: - member x: felt - member r : R* -end - -struct S: - member x : felt - member y : felt -end - -struct T: - member x : felt - member s : S - member sp : S* -end - -func f(): - alloc_locals - let __fp__ = [fp - 100] - - local s : S - local s2 : S - local t : T - local r1 : R - - s.x = 14 - (s).y = 2 - (&t).x = 7 - assert t.s = s - - ((t).s).x = t.x * 2 - assert t.s = (t).s - assert (t.s).x = t.s.x - assert (&(t.s)).y = ((t).s).y - - assert t.sp = &s - assert t.sp.x = 14 - assert [t.sp].y = 2 - assert [t.sp] = s - assert [t.sp] = (&t).s - assert &((t).s) = t.sp + 5 - - assert t.sp + 2 = &s2 - assert [t.sp + 2].x = s.x - assert (t.sp + 2).y = s.y - - assert [r1.r.r].r.r.r.r = &r1 - - return() -end +struct R { + x: felt, + r: R*, +} + +struct S { + x: felt, + y: felt, +} + +struct T { + x: felt, + s: S, + sp: S*, +} + +func f() { + alloc_locals; + let __fp__ = [fp - 100]; + + local s: S; + local s2: S; + local t: T; + local r1: R; + + s.x = 14; + (s).y = 2; + (&t).x = 7; + assert t.s = s; + + ((t).s).x = t.x * 2; + assert t.s = (t).s; + assert (t.s).x = t.s.x; + assert (&(t.s)).y = ((t).s).y; + + assert t.sp = &s; + assert t.sp.x = 14; + assert [t.sp].y = 2; + assert [t.sp] = s; + assert [t.sp] = (&t).s; + assert &((t).s) = t.sp + 5; + + assert t.sp + 2 = &s2; + assert [t.sp + 2].x = s.x; + assert (t.sp + 2).y = s.y; + + assert [r1.r.r].r.r.r.r = &r1; + + return (); +} """ program = preprocess_str(code=code, prime=PRIME) expected_result = """\ -ap += 10 # alloc_locals -[fp] = 14 # s.x = 14 -[fp + 1] = 2 # (s).y = 2 -[fp + 4] = 7 # (&t).x = 7 -[fp + 5] = [fp] # assert t.s = s (x member) -[fp + 6] = [fp + 1] # assert t.s = s (y member) - -[fp + 5] = [fp + 4] * 2 # ((t).s).x = t.x * 2 -[fp + 5] = [fp + 5] # assert t.s = (t).s (x member) -[fp + 6] = [fp + 6] # assert t.s = (t).s (y member) -[fp + 5] = [fp + 5] # assert (t.s).x = t.s.x -[fp + 6] = [fp + 6] # assert (&(t.s)).y = ((t).s).y - -[fp + 7] = [fp + (-100)] # assert t.sp = &s -[ap] = 14; ap++ # push 14 -[[fp + 7]] = [ap + (-1)] # assert t.sp.x = 14 -[ap] = 2; ap++ # push 2 -[[fp + 7] + 1] = [ap + (-1)] # assert [t.sp].y = 2 -[[fp + 7]] = [fp] # assert [t.sp] = s (x member) -[[fp + 7] + 1] = [fp + 1] # assert [t.sp] = s (y member) -[[fp + 7]] = [fp + 5] # assert [t.sp] = (&t).s (x member) -[[fp + 7] + 1] = [fp + 6] # assert [t.sp] = (&t).s (y member) -[ap] = [fp + 7] + 5; ap++ # push t.sp + 5 -[fp + (-100)] + 5 = [ap + (-1)] # assert &(t.s) = t.sp + 5 - -[ap] = [fp + (-100)] + 2; ap++ # push &s2 -[fp + 7] + 2 = [ap + (-1)] # assert t.sp + 2 = &s2 -[[fp + 7] + 2] = [fp] # assert [t.sp + 2].x = s.x -[[fp + 7] + 3] = [fp + 1] # assert (t.sp + 2).y = s.y - - # assert [r1.r.r].r.r.r.r = &r1 : -[ap] = [[fp + 9] + 1]; ap++ # push (r1.r).r ([fp + 9] = r1.r) -[ap] = [[ap + (-1)] + 1]; ap++ # push (r1.r.r).r -[ap] = [[ap + (-1)] + 1]; ap++ # push (r1.r.r.r).r -[ap] = [[ap + (-1)] + 1]; ap++ # push (r1.r.r.r.r).r -[ap] = [fp + (-100)] + 8; ap++ # push &r1 -[[ap + (-2)] + 1] = [ap + (-1)] # assert (r1.r.r.r.r.r).r = &r1 -ret +ap += 10; // alloc_locals +[fp] = 14; // s.x = 14 +[fp + 1] = 2; // (s).y = 2 +[fp + 4] = 7; // (&t).x = 7 +[fp + 5] = [fp]; // assert t.s = s (x member) +[fp + 6] = [fp + 1]; // assert t.s = s (y member) + +[fp + 5] = [fp + 4] * 2; // ((t).s).x = t.x * 2 +[fp + 5] = [fp + 5]; // assert t.s = (t).s (x member) +[fp + 6] = [fp + 6]; // assert t.s = (t).s (y member) +[fp + 5] = [fp + 5]; // assert (t.s).x = t.s.x +[fp + 6] = [fp + 6]; // assert (&(t.s)).y = ((t).s).y + +[fp + 7] = [fp + (-100)]; // assert t.sp = &s +[ap] = 14, ap++; // push 14 +[[fp + 7]] = [ap + (-1)]; // assert t.sp.x = 14 +[ap] = 2, ap++; // push 2 +[[fp + 7] + 1] = [ap + (-1)]; // assert [t.sp].y = 2 +[[fp + 7]] = [fp]; // assert [t.sp] = s (x member) +[[fp + 7] + 1] = [fp + 1]; // assert [t.sp] = s (y member) +[[fp + 7]] = [fp + 5]; // assert [t.sp] = (&t).s (x member) +[[fp + 7] + 1] = [fp + 6]; // assert [t.sp] = (&t).s (y member) +[ap] = [fp + 7] + 5, ap++; // push t.sp + 5 +[fp + (-100)] + 5 = [ap + (-1)]; // assert &(t.s) = t.sp + 5 + +[ap] = [fp + (-100)] + 2, ap++; // push &s2 +[fp + 7] + 2 = [ap + (-1)]; // assert t.sp + 2 = &s2 +[[fp + 7] + 2] = [fp]; // assert [t.sp + 2].x = s.x +[[fp + 7] + 3] = [fp + 1]; // assert (t.sp + 2).y = s.y + +// assert [r1.r.r].r.r.r.r = &r1 : +[ap] = [[fp + 9] + 1], ap++; // push (r1.r).r ([fp + 9] = r1.r) +[ap] = [[ap + (-1)] + 1], ap++; // push (r1.r.r).r +[ap] = [[ap + (-1)] + 1], ap++; // push (r1.r.r.r).r +[ap] = [[ap + (-1)] + 1], ap++; // push (r1.r.r.r.r).r +[ap] = [fp + (-100)] + 8, ap++; // push &r1 +[[ap + (-2)] + 1] = [ap + (-1)]; // assert (r1.r.r.r.r.r).r = &r1 +ret; """ assert program.format() == strip_comments_and_linebreaks(expected_result) def test_tuple_assertions(): - code = f"""\ -func f(): - alloc_locals - local var : (felt, felt) = [cast(ap, (felt, felt)*)] - return () -end + code = """\ +func f() { + alloc_locals; + local var: (felt, felt) = [cast(ap, (felt, felt)*)]; + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 2 -[fp] = [ap] -[fp + 1] = [ap + 1] -ret +ap += 2; +[fp] = [ap]; +[fp + 1] = [ap + 1]; +ret; """ ) def test_tuple_expression(): code = """\ -struct A: - member x : felt - member y : felt* -end -struct B: - member x : felt - member y : A - member z : A* -end -func foo(a : A*): - alloc_locals - let a : A* = cast([fp], A*) - local b : B = cast((1, [a], a), B) - - assert (b.x, b.z, a) = (5, a, a) - return () -end +struct A { + x: felt, + y: felt*, +} +struct B { + x: felt, + y: A, + z: A*, +} +func foo(a: A*) { + alloc_locals; + let a: A* = cast([fp], A*); + local b: B = cast((1, [a], a), B); + + assert (b.x, b.z, a) = (5, a, a); + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 4 -[fp] = 1 -[fp + 1] = [[fp]] -[fp + 2] = [[fp] + 1] -[fp + 3] = [fp] -[fp] = 5 -[fp + 3] = [fp] -[fp] = [fp] -ret +ap += 4; +[fp] = 1; +[fp + 1] = [[fp]]; +[fp + 2] = [[fp] + 1]; +[fp + 3] = [fp]; +[fp] = 5; +[fp + 3] = [fp]; +[fp] = [fp]; +ret; """ ) @@ -3687,18 +4066,18 @@ def test_tuple_expression(): def test_tuple_expression_failures(): verify_exception( """ -struct A: - member x : felt -end -struct B: -end -let a = cast(fp, A*) -let b = cast((1, a), B) +struct A { + x: felt, +} +struct B { +} +let a = cast(fp, A*); +let b = cast((1, a), B); """, """ file:?:?: Cannot cast an expression of type '(felt, test_scope.A*)' to 'test_scope.B'. The former has 2 members while the latter has 0 members. -let b = cast((1, a), B) +let b = cast((1, a), B); ^****^ """, exc_type=CairoTypeError, @@ -3706,23 +4085,23 @@ def test_tuple_expression_failures(): verify_exception( """ -struct A: - member x : felt - member y : felt -end -struct B: - member a : felt - member b : felt -end -let a = [cast(fp, A*)] -let b = cast((a, 1), B) +struct A { + x: felt, + y: felt, +} +struct B { + a: felt, + b: felt, +} +let a = [cast(fp, A*)]; +let b = cast((a, 1), B); """, """ file:?:?: While expanding the reference 'a' in: -let b = cast((a, 1), B) +let b = cast((a, 1), B); ^ file:?:?: Cannot cast 'test_scope.A' to 'felt'. -let a = [cast(fp, A*)] +let a = [cast(fp, A*)]; ^************^ """, exc_type=CairoTypeError, @@ -3730,19 +4109,19 @@ def test_tuple_expression_failures(): verify_exception( """ -struct A: - member x : felt - member y : felt -end -struct B: - member a : felt - member b : A -end -let b = cast([cast(ap, (felt, felt*)*)], B) +struct A { + x: felt, + y: felt, +} +struct B { + a: felt, + b: A, +} +let b = cast([cast(ap, (felt, felt*)*)], B); """, """ file:?:?: Cannot cast 'felt*' to 'test_scope.A'. -let b = cast([cast(ap, (felt, felt*)*)], B) +let b = cast([cast(ap, (felt, felt*)*)], B); ^************************^ """, exc_type=CairoTypeError, @@ -3750,81 +4129,81 @@ def test_tuple_expression_failures(): verify_exception( """ -struct B: -end -let b = cast([cast(ap, (felt, felt*)*)], B) +struct B { +} +let b = cast([cast(ap, (felt, felt*)*)], B); """, """ file:?:?: Cannot cast an expression of type '(felt, felt*)' to 'test_scope.B'. The former has 2 members while the latter has 0 members. -let b = cast([cast(ap, (felt, felt*)*)], B) +let b = cast([cast(ap, (felt, felt*)*)], B); ^************************^ """, exc_type=CairoTypeError, ) verify_exception( """ -(1, 1) = 1 +(1, 1) = 1; """, """ file:?:?: Expected a 'felt' or a pointer type. Got: '(felt, felt)'. -(1, 1) = 1 +(1, 1) = 1; ^****^ """, ) verify_exception( """ -assert (1, 1) = 1 +assert (1, 1) = 1; """, """ file:?:?: Cannot compare '(felt, felt)' and 'felt'. -assert (1, 1) = 1 -^***************^ +assert (1, 1) = 1; +^****************^ """, ) verify_exception( """ -let x = (1 , a=2, b=(c=())) +let x = (1, a=2, b=(c=())); """, """ file:?:?: All fields in a named tuple must have a name. -let x = (1 , a=2, b=(c=())) - ^*****************^ +let x = (1, a=2, b=(c=())); + ^****************^ """, ) def test_named_tuple_types(): code = """ -func foo(a : (felt, (x : felt, y : felt))): - tempvar tmp0 = a[0] - tempvar tmp1 = a[1].y - tempvar tmp2 = a[1][1] - ret -end - -foo((0, (x=1, y=2))) -# You can pass named to unnamed and vice versa. -foo((a=0, b=(1, 2))) +func foo(a: (felt, (x: felt, y: felt))) { + tempvar tmp0 = a[0]; + tempvar tmp1 = a[1].y; + tempvar tmp2 = a[1][1]; + ret; +} + +foo((0, (x=1, y=2))); +// You can pass named to unnamed and vice versa. +foo((a=0, b=(1, 2))); """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = [fp + (-5)]; ap++ -[ap] = [fp + (-3)]; ap++ -[ap] = [fp + (-3)]; ap++ -ret -[ap] = 0; ap++ -[ap] = 1; ap++ -[ap] = 2; ap++ -call rel -10 -[ap] = 0; ap++ -[ap] = 1; ap++ -[ap] = 2; ap++ -call rel -18 +[ap] = [fp + (-5)], ap++; +[ap] = [fp + (-3)], ap++; +[ap] = [fp + (-3)], ap++; +ret; +[ap] = 0, ap++; +[ap] = 1, ap++; +[ap] = 2, ap++; +call rel -10; +[ap] = 0, ap++; +[ap] = 1, ap++; +[ap] = 2, ap++; +call rel -18; """ ) @@ -3832,107 +4211,107 @@ def test_named_tuple_types(): def test_named_tuple_types_failure(): verify_exception( """ -func foo(arg : (a : (b : felt, b : felt), c : felt)): -end +func foo(arg: (a: (b: felt, b: felt), c: felt)) { +} """, """ file:?:?: Named tuple cannot have two entries with the same name. -func foo(arg : (a : (b : felt, b : felt), c : felt)): - ^******^ +func foo(arg: (a: (b: felt, b: felt), c: felt)) { + ^*****^ """, ) verify_exception( """ -let x = (a=(b=1, b=2), c=0) +let x = (a=(b=1, b=2), c=0); """, """ file:?:?: Named tuple cannot have two entries with the same name. -let x = (a=(b=1, b=2), c=0) +let x = (a=(b=1, b=2), c=0); ^*^ """, ) verify_exception( """ -func foo(x : (felt, b : felt)): - ret -end +func foo(x: (felt, b: felt)) { + ret; +} """, """ file:?:?: All fields in a named tuple must have a name. -func foo(x : (felt, b : felt)): - ^**************^ +func foo(x: (felt, b: felt)) { + ^*************^ """, ) def test_struct_constructor(): code = """\ -struct M: -end -struct A: - member x : M* - member y : felt -end -struct B: - member x : felt - member y : A - member z : A - member w : A* -end -func foo(m_ptr: M*, a_ptr : A*): - alloc_locals - local b1 : B = B(x=0, y=A(m_ptr, 2), z=[a_ptr], w=a_ptr) - let a = A(x=a_ptr.x, y=0) - assert a = A(x=m_ptr, y=2) - - let b2 : B = B(x=0, y=A(m_ptr, 2), z=[a_ptr], w=a_ptr) - assert b2 = b2 - - tempvar y: felt* = cast(1, felt*) - tempvar x: A* = cast(0, A*) - assert [x] = A(x=m_ptr, y=[y]) - return () -end +struct M { +} +struct A { + x: M*, + y: felt, +} +struct B { + x: felt, + y: A, + z: A, + w: A*, +} +func foo(m_ptr: M*, a_ptr: A*) { + alloc_locals; + local b1: B = B(x=0, y=A(m_ptr, 2), z=[a_ptr], w=a_ptr); + let a = A(x=a_ptr.x, y=0); + assert a = A(x=m_ptr, y=2); + + let b2: B = B(x=0, y=A(m_ptr, 2), z=[a_ptr], w=a_ptr); + assert b2 = b2; + + tempvar y: felt* = cast(1, felt*); + tempvar x: A* = cast(0, A*); + assert [x] = A(x=m_ptr, y=[y]); + return (); +} """ program = preprocess_str(code=code, prime=PRIME) expected_result = """\ -ap += 6 -# Populate b1. -[fp] = 0 -[fp + 1] = [fp + (-4)] -[fp + 2] = 2 -[fp + 3] = [[fp + (-3)]] -[fp + 4] = [[fp + (-3)] + 1] -[fp + 5] = [fp + (-3)] - -# assert a = A(x=m_ptr, y=2) (x component). -[[fp + (-3)]] = [fp + (-4)] - -# assert a = A(x=m_ptr, y=2) (y component). -[ap] = 2; ap++ -0 = [ap + (-1)] - -# assert b2 = b2. -[ap] = 0; ap++ -0 = [ap + (-1)] -[fp + (-4)] = [fp + (-4)] -[ap] = 2; ap++ -2 = [ap + (-1)] -[ap] = [[fp + (-3)]]; ap++ -[[fp + (-3)]] = [ap + (-1)] -[ap] = [[fp + (-3)] + 1]; ap++ -[[fp + (-3)] + 1] = [ap + (-1)] -[fp + (-3)] = [fp + (-3)] - -# tempvar y: felt* = cast(1, felt*). -[ap] = 1; ap++ -# tempvar x: A* = cast(0, A*). -[ap] = 0; ap++ -# assert [x] = A(x=m_ptr, y=[y]). -[[ap + (-1)]] = [fp + (-4)] -[ap] = [[ap + (-2)]]; ap++ -[[ap + (-2)] + 1] = [ap + (-1)] -ret +ap += 6; +// Populate b1. +[fp] = 0; +[fp + 1] = [fp + (-4)]; +[fp + 2] = 2; +[fp + 3] = [[fp + (-3)]]; +[fp + 4] = [[fp + (-3)] + 1]; +[fp + 5] = [fp + (-3)]; + +// assert a = A(x=m_ptr, y=2) (x component). +[[fp + (-3)]] = [fp + (-4)]; + +// assert a = A(x=m_ptr, y=2) (y component). +[ap] = 2, ap++; +0 = [ap + (-1)]; + +// assert b2 = b2. +[ap] = 0, ap++; +0 = [ap + (-1)]; +[fp + (-4)] = [fp + (-4)]; +[ap] = 2, ap++; +2 = [ap + (-1)]; +[ap] = [[fp + (-3)]], ap++; +[[fp + (-3)]] = [ap + (-1)]; +[ap] = [[fp + (-3)] + 1], ap++; +[[fp + (-3)] + 1] = [ap + (-1)]; +[fp + (-3)] = [fp + (-3)]; + +// tempvar y: felt* = cast(1, felt*). +[ap] = 1, ap++; +// tempvar x: A* = cast(0, A*). +[ap] = 0, ap++; +// assert [x] = A(x=m_ptr, y=[y]). +[[ap + (-1)]] = [fp + (-4)]; +[ap] = [[ap + (-2)]], ap++; +[[ap + (-2)] + 1] = [ap + (-1)]; +ret; """ assert program.format() == strip_comments_and_linebreaks(expected_result) @@ -3940,43 +4319,29 @@ def test_struct_constructor(): def test_struct_constructor_failures(): verify_exception( """ -func foo(): - ret -end - -foo(3) = foo(4) -""", - """ -file:?:?: Expected 'foo' to be a struct. Found: 'function'. -foo(3) = foo(4) -^****^ -""", - ) - verify_exception( - """ -using A = (felt, felt) -using B = A +using A = (felt, felt); +using B = A; -assert B(1, 2) = 0 +assert B(1, 2) = 0; """, """ file:?:?: Struct constructor cannot be used for type '(felt, felt)'. -assert B(1, 2) = 0 +assert B(1, 2) = 0; ^*****^ """, exc_type=CairoTypeError, ) verify_exception( """ -struct A: - member next: A* -end +struct A { + next: A*, +} -assert A(next=0) = A(next=0) +assert A(next=0) = A(next=0); """, """ file:?:?: Cannot cast 'felt' to 'test_scope.A*'. -assert A(next=0) = A(next=0) +assert A(next=0) = A(next=0); ^ """, exc_type=CairoTypeError, @@ -3985,15 +4350,15 @@ def test_struct_constructor_failures(): def verify_exception_for_expr(expr_str: str, expected_error: str): verify_exception( f""" -struct T: - member x : felt - member y : felt -end +struct T {{ + x: felt, + y: felt, +}} -func foo(a): - alloc_locals - local a : T = {expr_str} -end +func foo(a) {{ + alloc_locals; + local a: T = {expr_str}; +}} """, expected_error, exc_type=CairoTypeError, @@ -4002,20 +4367,20 @@ def verify_exception_for_expr(expr_str: str, expected_error: str): verify_exception_for_expr( "T(x=5, y=6, z=7)", """ -file:?:?: Cannot cast an expression of type '(x : felt, y : felt, z : felt)' to 'test_scope.T'. +file:?:?: Cannot cast an expression of type '(x: felt, y: felt, z: felt)' to 'test_scope.T'. The former has 3 members while the latter has 2 members. - local a : T = T(x=5, y=6, z=7) - ^**************^ + local a: T = T(x=5, y=6, z=7); + ^**************^ """, ) verify_exception_for_expr( "T(x=5)", """ -file:?:?: Cannot cast an expression of type '(x : felt)' to 'test_scope.T'. +file:?:?: Cannot cast an expression of type '(x: felt)' to 'test_scope.T'. The former has 1 members while the latter has 2 members. - local a : T = T(x=5) - ^****^ + local a: T = T(x=5); + ^****^ """, ) @@ -4023,8 +4388,8 @@ def verify_exception_for_expr(expr_str: str, expected_error: str): "&T(5, 6)", """ file:?:?: Expression has no address. - local a : T = &T(5, 6) - ^*****^ + local a: T = &T(5, 6); + ^*****^ """, ) @@ -4032,8 +4397,8 @@ def verify_exception_for_expr(expr_str: str, expected_error: str): "T(a=5, b=6)", """ file:?:?: Argument name mismatch for 'test_scope.T': expected 'x', found 'a'. - local a : T = T(a=5, b=6) - ^ + local a: T = T(a=5, b=6); + ^ """, ) @@ -4041,8 +4406,8 @@ def verify_exception_for_expr(expr_str: str, expected_error: str): "T(5, x=6)", """ file:?:?: Argument name mismatch for 'test_scope.T': expected 'y', found 'x'. - local a : T = T(5, x=6) - ^ + local a: T = T(5, x=6); + ^ """, ) @@ -4050,8 +4415,8 @@ def verify_exception_for_expr(expr_str: str, expected_error: str): "T(5, 6).x", """ file:?:?: Accessing struct/tuple members for r-value structs is not supported yet. - local a : T = T(5, 6).x - ^*******^ + local a: T = T(5, 6).x; + ^*******^ """, ) @@ -4059,8 +4424,8 @@ def verify_exception_for_expr(expr_str: str, expected_error: str): "T{a}(5, 6)", """ file:?:?: Implicit arguments cannot be used with struct constructors. - local a : T = T{a}(5, 6) - ^ + local a: T = T{a}(5, 6); + ^ """, ) @@ -4069,9 +4434,9 @@ def test_unsupported_decorator(): verify_exception( """ @external -func foo(): - return() -end +func foo() { + return (); +} """, """ file:?:?: Unsupported decorator: 'external'. @@ -4084,22 +4449,22 @@ def test_unsupported_decorator(): def test_skipped_functions(): files = { "module": """ -func func0(): - tempvar x = 0 - return () -end -func func1(): - tempvar x = 1 - return () -end -func func2(): - tempvar x = 2 - return func1() -end +func func0() { + tempvar x = 0; + return (); +} +func func1() { + tempvar x = 1; + return (); +} +func func2() { + tempvar x = 2; + return func1(); +} """, ".": """ from module import func2 -func2() +func2(); """, } program = preprocess_codes( @@ -4111,12 +4476,12 @@ def test_skipped_functions(): assert ( program.format() == """\ -[ap] = 1; ap++ -ret -[ap] = 2; ap++ -call rel -5 -ret -call rel -5 +[ap] = 1, ap++; +ret; +[ap] = 2, ap++; +call rel -5; +ret; +call rel -5; """ ) program = preprocess_codes( @@ -4129,15 +4494,15 @@ def test_skipped_functions(): ) assert program.format() == strip_comments_and_linebreaks( """\ -ret # get_ap is here because opt_unused_functions is false. -[ap] = 0; ap++ -ret -[ap] = 1; ap++ -ret -[ap] = 2; ap++ -call rel -5 -ret -call rel -5 +ret; // get_ap is here because opt_unused_functions is false. +[ap] = 0, ap++; +ret; +[ap] = 1, ap++; +ret; +[ap] = 2, ap++; +call rel -5; +ret; +call rel -5; """ ) @@ -4145,19 +4510,18 @@ def test_skipped_functions(): def test_known_ap_change_decorator(): # Positive case. code = """\ -func bar(): - return () -end +func bar() { + return (); +} @known_ap_change -func foo(arg : felt): - alloc_locals - local local_var - tempvar tmp = 0 - bar() - return () -end - +func foo(arg: felt) { + alloc_locals; + local local_var; + tempvar tmp = 0; + bar(); + return (); +} """ preprocess_str(code=code, prime=PRIME) @@ -4165,10 +4529,10 @@ def test_known_ap_change_decorator(): verify_exception( """ @known_ap_change -func foo(): - foo() - return () -end +func foo() { + foo(); + return (); +} """, """ file:?:?: The compiler was unable to deduce the change of the ap register, as required by this \ @@ -4182,15 +4546,15 @@ def test_known_ap_change_decorator(): def test_define_word_failure(): verify_exception( """ -tempvar x = 5 -dw x +tempvar x = 5; +dw x; """, """ file:?:?: While expanding the reference 'x' in: -dw x +dw x; ^ file:?:?: dw must be followed by a constant expression. -tempvar x = 5 +tempvar x = 5; ^ Preprocessed instruction: dw [ap + (-1)] @@ -4202,18 +4566,19 @@ def test_define_word_failure(): def test_label_arithmetic_flow(): code = """ label1: -assert 4 = label2 - label1 +assert 4 = label2 - label1; + label2: -assert 4 = label2 - label1 +assert 4 = label2 - label1; """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 4; ap++ -4 = [ap + (-1)] -[ap] = 4; ap++ -4 = [ap + (-1)] +[ap] = 4, ap++; +4 = [ap + (-1)]; +[ap] = 4, ap++; +4 = [ap + (-1)]; """ ) @@ -4221,12 +4586,12 @@ def test_label_arithmetic_flow(): def test_label_arithmetic_failure(): verify_exception( """ -tempvar code_offset : codeoffset -assert 0 = code_offset - 5 +tempvar code_offset: codeoffset; +assert 0 = code_offset - 5; """, """ file:?:?: Operator '-' is not implemented for types 'codeoffset' and 'felt'. -assert 0 = code_offset - 5 +assert 0 = code_offset - 5; ^*************^ """, exc_type=CairoTypeError, @@ -4234,16 +4599,15 @@ def test_label_arithmetic_failure(): verify_exception( """ -func foo(): - assert foo = 5 - return() -end - +func foo() { + assert foo = 5; + return (); +} """, """ file:?:?: Cannot compare 'codeoffset' and 'felt'. - assert foo = 5 - ^************^ + assert foo = 5; + ^*************^ """, ) @@ -4256,16 +4620,18 @@ def test_future_label_substraction_failure(): verify_exception( """ -assert 0 = label2 - label1 +assert 0 = label2 - label1; + label1: + label2: """, """ file:?:?: Expected a constant expression or a dereference expression. -assert 0 = label2 - label1 +assert 0 = label2 - label1; ^****^ Preprocessed instruction: -[ap] = [ap + (-1)] - label1; ap++ +[ap] = [ap + (-1)] - label1, ap++ """, exc_type=InstructionBuilderError, ) @@ -4273,108 +4639,109 @@ def test_future_label_substraction_failure(): def test_future_label_minus_tempvar(): code = """ -tempvar a = cast(0, codeoffset) -assert 0 = label1 - a +tempvar a = cast(0, codeoffset); +assert 0 = label1 - a; + label1: """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 0; ap++ -[ap] = 7; ap++ -[ap] = [ap + (-1)] - [ap + (-2)]; ap++ -0 = [ap + (-1)] +[ap] = 0, ap++; +[ap] = 7, ap++; +[ap] = [ap + (-1)] - [ap + (-2)], ap++; +0 = [ap + (-1)]; """ ) def test_new_operator_flow(): code = """ -struct MyStruct: - member a : felt - member b : felt -end - -func test() -> (my_struct: MyStruct*): - tempvar t = 37 - tempvar my_struct = new MyStruct(a=1, b=2) - - # Check that 't' wasn't revoked and that the type of a is MyStruct*. - assert cast(t, MyStruct*) = my_struct - assert cast(t, MyStruct*) = new MyStruct(a=3, b=[new 4]) - return (my_struct=my_struct) -end +struct MyStruct { + a: felt, + b: felt, +} + +func test() -> (my_struct: MyStruct*) { + tempvar t = 37; + tempvar my_struct = new MyStruct(a=1, b=2); + + // Check that 't' wasn't revoked and that the type of a is MyStruct*. + assert cast(t, MyStruct*) = my_struct; + assert cast(t, MyStruct*) = new MyStruct(a=3, b=[new 4]); + return (my_struct=my_struct); +} """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == strip_comments_and_linebreaks( """\ -# A dummy get_ap(). -ret - -[ap] = 37; ap++ - -# tempvar my_struct = new MyStruct(a=1, b=2). -[ap] = 1; ap++ -[ap] = 2; ap++ -call rel -7 # call get_ap() -[ap] = [ap + (-1)] + (-2); ap++ # [ap] = get_ap() - MyStruct.SIZE -# assert cast(t, MyStruct*) = my_struct. -[ap + (-6)] = [ap + (-1)] - -# new 4. -[ap] = 4; ap++ -call rel -14 -[ap] = [ap + (-1)] + (-1); ap++ - -# new MyStruct(a=3, b=[new 4]). -[ap] = 3; ap++ -[ap] = [[ap + (-2)]]; ap++ -call rel -21 -[ap] = [ap + (-1)] + (-2); ap++ - -# assert cast(t, MyStruct*) = new MyStruct(a=3, b=[new 4]). -[ap + (-15)] = [ap + (-1)] -# return (my_struct=my_struct). -[ap] = [ap + (-10)]; ap++ -ret +// A dummy get_ap(). +ret; + +[ap] = 37, ap++; + +// tempvar my_struct = new MyStruct(a=1, b=2). +[ap] = 1, ap++; +[ap] = 2, ap++; +call rel -7; // call get_ap() +[ap] = [ap + (-1)] + (-2), ap++; // [ap] = get_ap() - MyStruct.SIZE +// assert cast(t, MyStruct*) = my_struct. +[ap + (-6)] = [ap + (-1)]; + +// new 4. +[ap] = 4, ap++; +call rel -14; +[ap] = [ap + (-1)] + (-1), ap++; + +// new MyStruct(a=3, b=[new 4]). +[ap] = 3, ap++; +[ap] = [[ap + (-2)]], ap++; +call rel -21; +[ap] = [ap + (-1)] + (-2), ap++; + +// assert cast(t, MyStruct*) = new MyStruct(a=3, b=[new 4]). +[ap + (-15)] = [ap + (-1)]; +// return (my_struct=my_struct). +[ap] = [ap + (-10)], ap++; +ret; """ ) code = """ -func test() -> (felt_ptr : felt*): - return (felt_ptr=new ([fp] + 5)) -end +func test() -> (felt_ptr: felt*) { + return (felt_ptr=new ([fp] + 5)); +} """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == strip_comments_and_linebreaks( """\ -# A dummy get_ap(). -ret +// A dummy get_ap(). +ret; -[ap] = [fp] + 5; ap++ -call rel -3 # call get_ap() -[ap] = [ap + (-1)] + (-1); ap++ -ret +[ap] = [fp] + 5, ap++; +call rel -3; // call get_ap() +[ap] = [ap + (-1)] + (-1), ap++; +ret; """ ) code = """ -func test() -> (tuple_ptr : (felt, felt)*): - return (tuple_ptr=new (7, 8)) -end +func test() -> (tuple_ptr: (felt, felt)*) { + return (tuple_ptr=new (7, 8)); +} """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == strip_comments_and_linebreaks( """\ -# A dummy get_ap(). -ret - -[ap] = 7; ap++ -[ap] = 8; ap++ -call rel -5 # call get_ap() -[ap] = [ap + (-1)] + (-2); ap++ -ret +// A dummy get_ap(). +ret; + +[ap] = 7, ap++; +[ap] = 8, ap++; +call rel -5; // call get_ap() +[ap] = [ap + (-1)] + (-2), ap++; +ret; """ ) @@ -4382,29 +4749,29 @@ def test_new_operator_flow(): def test_new_operator_failure(): verify_exception( """ -new MyStruct(a=1, b=2) = 13 +new MyStruct(a=1, b=2) = 13; """, """ file:?:?: The new operator is not supported outside of a function. -new MyStruct(a=1, b=2) = 13 +new MyStruct(a=1, b=2) = 13; ^********************^ """, ) verify_exception( """ -struct MyStruct: - member a : felt - member b : felt -end -func test(): - new MyStruct(a=1, b=2) = 13 - return() -end +struct MyStruct { + a: felt, + b: felt, +} +func test() { + new MyStruct(a=1, b=2) = 13; + return (); +} """, """ file:?:?: Expected a dereference expression. - new MyStruct(a=1, b=2) = 13 + new MyStruct(a=1, b=2) = 13; ^********************^ Preprocessed instruction: new (1, 2) = 13 @@ -4414,26 +4781,25 @@ def test_new_operator_failure(): verify_exception( """ -new MyStruct(a=1, b=2) = 13 +new MyStruct(a=1, b=2) = 13; """, """ file:?:?: The new operator is not supported outside of a function. -new MyStruct(a=1, b=2) = 13 +new MyStruct(a=1, b=2) = 13; ^********************^ """, ) verify_exception( """ -func test(): - alloc_locals - local x = new 5 - return() -end - +func test() { + alloc_locals; + local x = new 5; + return (); +} """, """ file:?:?: Cannot cast 'felt*' to 'felt'. - local x = new 5 + local x = new 5; ^***^ """, exc_type=CairoTypeError, @@ -4441,15 +4807,14 @@ def test_new_operator_failure(): verify_exception( """ -func test(): - let x = new 5 - return() -end - +func test() { + let x = new 5; + return (); +} """, """ file:?:?: The use of 'new' in reference expressions is not allowed. - let x = new 5 + let x = new 5; ^***^ """, ) @@ -4457,35 +4822,35 @@ def test_new_operator_failure(): def test_type_definition(): code = """ -namespace a: - namespace b: - using Point = (felt, felt) - end - namespace c: - using TwoPoints = (b.Point, b.Point) - end -end - -func foo(z : a.b.Point): - alloc_locals - tempvar x : a.c.TwoPoints = ((0, 1), [cast(fp, a.b.Point*)]) - local y : a.c.TwoPoints - assert x[0] = z - return () -end +namespace a { + namespace b { + using Point = (felt, felt); + } + namespace c { + using TwoPoints = (b.Point, b.Point); + } +} + +func foo(z: a.b.Point) { + alloc_locals; + tempvar x: a.c.TwoPoints = ((0, 1), [cast(fp, a.b.Point*)]); + local y: a.c.TwoPoints; + assert x[0] = z; + return (); +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -ap += 4 -[ap] = 0; ap++ -[ap] = 1; ap++ -[ap] = [fp]; ap++ -[ap] = [fp + 1]; ap++ -[ap + (-4)] = [fp + (-4)] -[ap + (-3)] = [fp + (-3)] -ret +ap += 4; +[ap] = 0, ap++; +[ap] = 1, ap++; +[ap] = [fp], ap++; +[ap] = [fp + 1], ap++; +[ap + (-4)] = [fp + (-4)]; +[ap + (-3)] = [fp + (-3)]; +ret; """ ) two_points = program.identifiers.get_by_full_name(TEST_SCOPE + "a.c.TwoPoints") @@ -4498,29 +4863,29 @@ def test_type_definition(): def test_type_definition_failure(): verify_exception( """ -using Point = Point +using Point = Point; """, """ file:?:?: Cannot use a type before its definition. -using Point = Point +using Point = Point; ^***^ """, ) verify_exception( """ -using Point2 = (Point, Point) -using Point = (felt, felt) +using Point2 = (Point, Point); +using Point = (felt, felt); """, """ file:?:?: Cannot use a type before its definition. -using Point2 = (Point, Point) +using Point2 = (Point, Point); ^***^ """, ) verify_exception( """ %{ %} -using Point = (felt, felt) +using Point = (felt, felt); """, """ file:?:?: Hints before "using" statements are not allowed. @@ -4532,26 +4897,26 @@ def test_type_definition_failure(): def test_if_with_single_and(): code = """ -func main(): - tempvar a = 10 - tempvar b = 12 - if a == 10 and b == 12: - tempvar x = a + b - end - ret -end +func main() { + tempvar a = 10; + tempvar b = 12; + if (a == 10 and b == 12) { + tempvar x = a + b; + } + ret; +} """ program = preprocess_str(code=code, prime=PRIME) assert ( program.format() == """\ -[ap] = 10; ap++ -[ap] = 12; ap++ -[ap] = [ap + (-2)] + (-10); ap++ -jmp rel 7 if [ap + (-1)] != 0 -[ap] = [ap + (-2)] + (-12); ap++ -jmp rel 3 if [ap + (-1)] != 0 -[ap] = [ap + (-4)] + [ap + (-3)]; ap++ -ret +[ap] = 10, ap++; +[ap] = 12, ap++; +[ap] = [ap + (-2)] + (-10), ap++; +jmp rel 7 if [ap + (-1)] != 0; +[ap] = [ap + (-2)] + (-12), ap++; +jmp rel 3 if [ap + (-1)] != 0; +[ap] = [ap + (-4)] + [ap + (-3)], ap++; +ret; """ ) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/preprocessor_test_utils.py b/src/starkware/cairo/lang/compiler/preprocessor/preprocessor_test_utils.py index ae060867..0933bd5b 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/preprocessor_test_utils.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/preprocessor_test_utils.py @@ -23,9 +23,9 @@ CAIRO_TEST_MODULES = { "starkware.cairo.lang.compiler.lib.registers": """ @known_ap_change -func get_ap() -> (ap_val : felt): - ret -end +func get_ap() -> (ap_val: felt) { + ret; +} """, } @@ -34,7 +34,7 @@ def strip_comments_and_linebreaks(program: str): """ Removes all comments and empty lines from the given program. """ - program = re.sub(r"\s*#.*\n", "\n", program) + program = re.sub(r"\s*//.*\n", "\n", program) return re.sub("\n+", "\n", program).lstrip() diff --git a/src/starkware/cairo/lang/compiler/preprocessor/struct_collector.py b/src/starkware/cairo/lang/compiler/preprocessor/struct_collector.py index edaeac3b..3ecdb6ed 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/struct_collector.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/struct_collector.py @@ -102,28 +102,19 @@ def create_struct_from_identifier_list( members_list=members_list, struct_name=struct_name, location=location ) - def create_tuple_type_from_identifier_list( + def handle_type_definition( self, - identifier_list: Optional[IdentifierList], + cairo_type: Optional[CairoType], type_name: ScopedName, location: Optional[Location], ): """ - Creates a tuple type alias based on the given 'identifier_list'. + Creates a type definition for the given type. """ - members: List[TypeTuple.Item] = [] - if identifier_list is not None: - for arg in identifier_list.identifiers: - assert_no_modifier(arg) - members.append( - TypeTuple.Item( - name=arg.identifier.name, typ=arg.get_type(), location=arg.location - ) - ) - - location = identifier_list.location + if cairo_type is None: + cairo_type = TypeTuple.from_members(members=[], location=location) - cairo_type = self.resolve_type(TypeTuple.from_members(members=members, location=location)) + cairo_type = self.resolve_type(cairo_type=cairo_type) self.add_name_definition( type_name, TypeDefinition( @@ -151,7 +142,7 @@ def handle_struct_definition(self, struct_name: ScopedName, code_block: CodeBloc if elm.typed_identifier.expr_type is None: raise PreprocessorError( - "Struct members must be explicitly typed (e.g., member x : felt).", + "Struct members must be explicitly typed (e.g., x: felt).", location=elm.typed_identifier.location, ) @@ -194,8 +185,8 @@ def visit_CodeElementFunction(self, elm: CodeElementFunction): struct_name=new_scope + CodeElementFunction.IMPLICIT_ARGUMENT_SCOPE, location=elm.identifier.location, ) - self.create_tuple_type_from_identifier_list( - identifier_list=elm.returns, + self.handle_type_definition( + cairo_type=elm.returns, type_name=new_scope + CodeElementFunction.RETURN_SCOPE, location=elm.identifier.location, ) diff --git a/src/starkware/cairo/lang/compiler/preprocessor/struct_collector_test.py b/src/starkware/cairo/lang/compiler/preprocessor/struct_collector_test.py index cc5eac3e..5400b01c 100644 --- a/src/starkware/cairo/lang/compiler/preprocessor/struct_collector_test.py +++ b/src/starkware/cairo/lang/compiler/preprocessor/struct_collector_test.py @@ -50,22 +50,22 @@ def _collect_struct_definitions(codes: Dict[str, str]) -> Dict[str, Set[str]]: def test_struct_collector(): modules = { "module": """ -struct S: - member x : S* - member y : S* -end +struct S { + x: S*, + y: S*, +} """, "__main__": """ from module import S -func foo{z}(a : S, b) -> (c : S): - struct T: - member x : S* - end - const X = 5 - return (c=a + X) -end -const Y = 1 + 1 +func foo{z}(a: S, b) -> (c: S) { + struct T { + x: S*, + } + const X = 5; + return (c=a + X); +} +const Y = 1 + 1; """, } @@ -79,15 +79,11 @@ def test_struct_collector(): members={ "x": MemberDefinition( offset=0, - cairo_type=TypePointer( - pointee=TypeStruct(scope=scope("module.S"), is_fully_resolved=True) - ), + cairo_type=TypePointer(pointee=TypeStruct(scope=scope("module.S"))), ), "y": MemberDefinition( offset=1, - cairo_type=TypePointer( - pointee=TypeStruct(scope=scope("module.S"), is_fully_resolved=True) - ), + cairo_type=TypePointer(pointee=TypeStruct(scope=scope("module.S"))), ), }, size=2, @@ -96,9 +92,7 @@ def test_struct_collector(): "__main__.foo.Args": StructDefinition( full_name=scope("__main__.foo.Args"), members={ - "a": MemberDefinition( - offset=0, cairo_type=TypeStruct(scope=scope("module.S"), is_fully_resolved=True) - ), + "a": MemberDefinition(offset=0, cairo_type=TypeStruct(scope=scope("module.S"))), "b": MemberDefinition(offset=2, cairo_type=TypeFelt()), }, size=3, @@ -109,16 +103,14 @@ def test_struct_collector(): size=1, ), "__main__.foo.Return": TypeDefinition( - cairo_type=mark_type_resolved(parse_type("(c : module.S)")), + cairo_type=mark_type_resolved(parse_type("(c: module.S)")), ), "__main__.foo.T": StructDefinition( full_name=scope("__main__.foo.T"), members={ "x": MemberDefinition( offset=0, - cairo_type=TypePointer( - pointee=TypeStruct(scope=scope("module.S"), is_fully_resolved=True) - ), + cairo_type=TypePointer(pointee=TypeStruct(scope=scope("module.S"))), ), }, size=1, @@ -131,10 +123,10 @@ def test_struct_collector(): def test_struct_collector_failure(): modules = { "module": """ -struct S: - member x : S* - member x : S* -end +struct S { + x: S*, + x: S*, +} """ } @@ -143,29 +135,19 @@ def test_struct_collector_failure(): modules = { "module": """ -struct S: - member local a -end +struct S { + local a, +} """ } with pytest.raises(PreprocessorError, match="Unexpected modifier 'local'."): _collect_struct_definitions(modules) - modules = { - "module": """ -struct S: - return() -end -""" - } - with pytest.raises(PreprocessorError, match="Unexpected statement inside a struct definition."): - _collect_struct_definitions(modules) - verify_exception( """ @decorator -struct Struct: -end +struct Struct { +} """, """ file:?:?: Decorators for structs are not supported. diff --git a/src/starkware/cairo/lang/compiler/program.py b/src/starkware/cairo/lang/compiler/program.py index 083439b7..22000abb 100644 --- a/src/starkware/cairo/lang/compiler/program.py +++ b/src/starkware/cairo/lang/compiler/program.py @@ -2,17 +2,18 @@ import string from abc import ABC, abstractmethod from dataclasses import field -from typing import Dict, List, Optional, Type, Union +from typing import Any, Dict, List, Optional, Type, Union +import marshmallow import marshmallow.fields as mfields import marshmallow_dataclass from starkware.cairo.lang.compiler.debug_info import DebugInfo from starkware.cairo.lang.compiler.identifier_definition import ( ConstDefinition, - IdentifierDefinition, LabelDefinition, ReferenceDefinition, + TIdentifierDefinition, ) from starkware.cairo.lang.compiler.identifier_manager import ( IdentifierManager, @@ -23,7 +24,7 @@ from starkware.cairo.lang.compiler.preprocessor.preprocessor import AttributeScope from starkware.cairo.lang.compiler.references import Reference from starkware.cairo.lang.compiler.scoped_name import ScopedName, ScopedNameAsStr -from starkware.starkware_utils.marshmallow_dataclass_fields import IntAsHex +from starkware.starkware_utils.marshmallow_dataclass_fields import IntAsHex, additional_metadata from starkware.starkware_utils.serializable_dataclass import SerializableMarshmallowDataclass @@ -31,7 +32,7 @@ class CairoHint: code: str accessible_scopes: List[ScopedName] = field( - metadata=dict(marshmallow_field=mfields.List(ScopedNameAsStr)) + metadata=additional_metadata(marshmallow_field=mfields.List(ScopedNameAsStr)) ) flow_tracking_data: FlowTrackingDataActual @@ -81,21 +82,32 @@ def run_validity_checks(self): @marshmallow_dataclass.dataclass(repr=False) class Program(ProgramBase, SerializableMarshmallowDataclass): - prime: int = field(metadata=dict(marshmallow_field=IntAsHex(required=True))) + prime: int = field(metadata=additional_metadata(marshmallow_field=IntAsHex(required=True))) data: List[int] = field( - metadata=dict(marshmallow_field=mfields.List(IntAsHex(), required=True)) + metadata=additional_metadata(marshmallow_field=mfields.List(IntAsHex(), required=True)) ) hints: Dict[int, List[CairoHint]] builtins: List[str] - main_scope: ScopedName = field(metadata=dict(marshmallow_field=ScopedNameAsStr())) + main_scope: ScopedName = field( + metadata=additional_metadata(marshmallow_field=ScopedNameAsStr()) + ) identifiers: IdentifierManager = field( - metadata=dict(marshmallow_field=IdentifierManagerField()) + metadata=additional_metadata(marshmallow_field=IdentifierManagerField()) ) # Holds all the allocated references in the program. reference_manager: ReferenceManager + compiler_version: Optional[str] = field( + metadata=dict(marshmallow_field=mfields.String(required=False, load_default=None)) + ) attributes: List[AttributeScope] = field(default_factory=list) debug_info: Optional[DebugInfo] = None + @marshmallow.post_dump + def remove_version(self, data: Dict[Any, Any], many: bool = False): + if data["compiler_version"] is None: + del data["compiler_version"] + return data + def stripped(self) -> StrippedProgram: assert self.main is not None return StrippedProgram( @@ -108,9 +120,9 @@ def stripped(self) -> StrippedProgram: def get_identifier( self, name: Union[str, ScopedName], - expected_type: Type[IdentifierDefinition], + expected_type: Type[TIdentifierDefinition], full_name_lookup: Optional[bool] = None, - ): + ) -> TIdentifierDefinition: scoped_name = name if isinstance(name, ScopedName) else ScopedName.from_string(name) if full_name_lookup is True: result = self.identifiers.root.get(scoped_name) @@ -120,16 +132,20 @@ def get_identifier( identifier_definition = result.identifier_definition assert isinstance(identifier_definition, expected_type), ( f"'{scoped_name}' is expected to be {expected_type.TYPE}, " - + f"found {identifier_definition.TYPE}." # type: ignore - ) # type: ignore + + f"found {identifier_definition.TYPE}." + ) return identifier_definition - def get_label(self, name: Union[str, ScopedName], full_name_lookup: Optional[bool] = None): + def get_label( + self, name: Union[str, ScopedName], full_name_lookup: Optional[bool] = None + ) -> int: return self.get_identifier( name=name, expected_type=LabelDefinition, full_name_lookup=full_name_lookup ).pc - def get_const(self, name: Union[str, ScopedName], full_name_lookup: Optional[bool] = None): + def get_const( + self, name: Union[str, ScopedName], full_name_lookup: Optional[bool] = None + ) -> int: return self.get_identifier( name=name, expected_type=ConstDefinition, full_name_lookup=full_name_lookup ).value diff --git a/src/starkware/cairo/lang/compiler/references.py b/src/starkware/cairo/lang/compiler/references.py index a99e0478..c5cdc5fa 100644 --- a/src/starkware/cairo/lang/compiler/references.py +++ b/src/starkware/cairo/lang/compiler/references.py @@ -24,6 +24,7 @@ RegChangeLike, RegTrackingData, ) +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata class FlowTrackingError(Exception): @@ -64,15 +65,17 @@ class Reference: The reference may be evaluated for other locations in the program, as long as its value is well defined. For example, - let x = ap # Defines a reference to ap, that is attached to the following instruction. - [ap] = 5; ap++ - # Since ap increased, the reference evaluated now should be (ap - 1), rather than ap. - [ap] = [x] * 2; ap++ # Thus, this instruction will translate to '[ap] = [ap - 1] * 2; ap++' - # and will set [ap] to 10. + let x = ap; // Defines a reference to ap, that is attached to the following instruction. + [ap] = 5, ap++; + // Since ap increased, the reference evaluated now should be (ap - 1), rather than ap. + [ap] = [x] * 2, ap++; // Thus, this instruction will translate to '[ap] = [ap - 1] * 2, ap++;' + // and will set [ap] to 10. """ pc: int - value: Expression = field(metadata=dict(marshmallow_field=ExpressionAsStr(required=True))) + value: Expression = field( + metadata=additional_metadata(marshmallow_field=ExpressionAsStr(required=True)) + ) # The value of flow_tracking when this reference was defined. ap_tracking_data: RegTrackingData @@ -82,13 +85,15 @@ class Reference: locations: List[Location] = field( default_factory=list, compare=False, - metadata=dict(marshmallow_field=marshmallow.fields.Field(load_only=True, dump_only=True)), + metadata=additional_metadata( + marshmallow_field=marshmallow.fields.Field(load_only=True, dump_only=True) + ), ) # The code element responsible of creating this reference. definition_code_element: Optional[CodeElement] = field( default=None, - metadata=dict( + metadata=additional_metadata( marshmallow_field=marshmallow.fields.Nested( marshmallow.Schema(), dump_only=True, diff --git a/src/starkware/cairo/lang/compiler/substitute_identifiers.py b/src/starkware/cairo/lang/compiler/substitute_identifiers.py index 0113f36a..5cfe95a3 100644 --- a/src/starkware/cairo/lang/compiler/substitute_identifiers.py +++ b/src/starkware/cairo/lang/compiler/substitute_identifiers.py @@ -1,6 +1,11 @@ from typing import Callable, List, Optional, Union -from starkware.cairo.lang.compiler.ast.cairo_types import CairoType, TypeStruct +from starkware.cairo.lang.compiler.ast.cairo_types import ( + CairoType, + TypeFunction, + TypeIdentifier, + TypeStruct, +) from starkware.cairo.lang.compiler.ast.expr import ( ExprCast, ExprConst, @@ -74,31 +79,35 @@ def visit_RvalueFuncCall(self, rvalue: RvalueFuncCall): ) def visit_ExprFuncCall(self, expr: ExprFuncCall): - # Convert ExprFuncCall to ExprCast. rvalue = expr.rvalue - if rvalue.implicit_arguments is not None: - raise CairoTypeError( - "Implicit arguments cannot be used with struct constructors.", - location=rvalue.implicit_arguments.location, - ) - - struct_type = self.resolve_type_callback( - TypeStruct( - scope=ScopedName.from_string(rvalue.func_ident.name), - is_fully_resolved=False, + cairo_type = self.resolve_type_callback( + TypeIdentifier( + name=ScopedName.from_string(rvalue.func_ident.name), location=expr.location, ) ) - if not isinstance(struct_type, TypeStruct): + if isinstance(cairo_type, TypeFunction): + # Note that arguments to the given function call ('expr') are left as is and not visited + # here. + return expr + + if not isinstance(cairo_type, TypeStruct): raise CairoTypeError( - f"Struct constructor cannot be used for type '{struct_type.format()}'.", + f"Struct constructor cannot be used for type '{cairo_type.format()}'.", location=expr.location, ) + # Convert the constructor call to ExprCast. + if rvalue.implicit_arguments is not None: + raise CairoTypeError( + "Implicit arguments cannot be used with struct constructors.", + location=rvalue.implicit_arguments.location, + ) + # Verify named arguments in struct constructor. if self.get_struct_members_callback is not None: - struct_members = self.get_struct_members_callback(struct_type) + struct_members = self.get_struct_members_callback(cairo_type) # Note that it's OK if len(struct_members) != len(rvalue.arguments.args) as # length compatibility of cast is checked later on. for member, expr_assignment in zip(struct_members, rvalue.arguments.args): @@ -109,7 +118,7 @@ def visit_ExprFuncCall(self, expr: ExprFuncCall): call_member = identifier.name if call_member != member: raise CairoTypeError( - f"Argument name mismatch for '{struct_type.format()}': " + f"Argument name mismatch for '{cairo_type.format()}': " f"expected '{member}', found '{call_member}'.", location=identifier.location, ) @@ -117,7 +126,7 @@ def visit_ExprFuncCall(self, expr: ExprFuncCall): return self.visit( ExprCast( expr=ExprTuple(rvalue.arguments, location=expr.location), - dest_type=struct_type, + dest_type=cairo_type, location=expr.location, ) ) diff --git a/src/starkware/cairo/lang/compiler/type_casts.py b/src/starkware/cairo/lang/compiler/type_casts.py index 98425728..0d74700e 100644 --- a/src/starkware/cairo/lang/compiler/type_casts.py +++ b/src/starkware/cairo/lang/compiler/type_casts.py @@ -88,7 +88,7 @@ def check_cast( if isinstance(src_type, TypeTuple) and isinstance(dest_type, TypeStruct): struct_def = get_struct_definition( - struct_name=dest_type.resolved_scope, identifier_manager=identifier_manager + struct_name=dest_type.scope, identifier_manager=identifier_manager ) dest_members = [ TypeTuple.Item(name=name, typ=member.cairo_type) @@ -160,7 +160,7 @@ def verify_tuple_like_cast( raise CairoTypeError( f"""\ Cannot cast '{src_type.format()}' to '{dest_type.format()}'. -Expected argument name {dest_name}. Found: {src_name}.""", +Expected argument name '{dest_name}'. Found: '{src_name}'.""", location=item_location, ) diff --git a/src/starkware/cairo/lang/compiler/type_casts_test.py b/src/starkware/cairo/lang/compiler/type_casts_test.py index 5d20b9f2..e9d314c0 100644 --- a/src/starkware/cairo/lang/compiler/type_casts_test.py +++ b/src/starkware/cairo/lang/compiler/type_casts_test.py @@ -15,9 +15,9 @@ @pytest.fixture(scope="session") def identifier_manager() -> IdentifierManager: code = """ -struct T: - member x : (felt, felt) -end +struct T { + x: (felt, felt), +} """ return preprocess_str(code, PRIME, main_scope=ScopedName()).identifiers @@ -35,12 +35,12 @@ def identifier_manager() -> IdentifierManager: # Tuples and named tuples. ["felt", "(felt,felt)", False, False, False], ["((felt, felt))", "T", True, False, False], - ["(x : (felt, felt))", "T", True, False, False], - ["(y : (felt, felt))", "T", "Expected argument name x. Found: y.", False, False], - ["(felt)", "(a : felt)", True, True, True], - ["(a : felt)", "(felt)", True, True, True], - ["(a : felt, b : felt)", "(a : felt, c : felt)"] - + ["Expected argument name c. Found: b."] * 3, + ["(x: (felt, felt))", "T", True, False, False], + ["(y: (felt, felt))", "T", "Expected argument name 'x'. Found: 'y'.", False, False], + ["(felt)", "(a: felt)", True, True, True], + ["(a: felt)", "(felt)", True, True, True], + ["(a: felt, b: felt)", "(a: felt, c: felt)"] + + ["Expected argument name 'c'. Found: 'b'."] * 3, ], ) def test_type_casts( diff --git a/src/starkware/cairo/lang/compiler/type_system.py b/src/starkware/cairo/lang/compiler/type_system.py index 2bc9bb5c..eb269eb9 100644 --- a/src/starkware/cairo/lang/compiler/type_system.py +++ b/src/starkware/cairo/lang/compiler/type_system.py @@ -4,6 +4,7 @@ CairoType, TypeCodeoffset, TypeFelt, + TypeIdentifier, TypePointer, TypeStruct, TypeTuple, @@ -17,14 +18,13 @@ def mark_type_resolved(cairo_type: CairoType) -> CairoType: Marks the given type as resolved (struct names are absolute). This function can be used after parsing a string which is known to contain resolved types. """ - if isinstance(cairo_type, (TypeFelt, TypeCodeoffset)): + if isinstance(cairo_type, (TypeFelt, TypeCodeoffset, TypeStruct)): return cairo_type elif isinstance(cairo_type, TypePointer): return dataclasses.replace(cairo_type, pointee=mark_type_resolved(cairo_type.pointee)) - elif isinstance(cairo_type, TypeStruct): - if cairo_type.is_fully_resolved: - return cairo_type - return dataclasses.replace(cairo_type, is_fully_resolved=True) + elif isinstance(cairo_type, TypeIdentifier): + # Assume that the type is a struct. + return TypeStruct(scope=cairo_type.name, location=cairo_type.location) elif isinstance(cairo_type, TypeTuple): return dataclasses.replace( cairo_type, @@ -41,12 +41,10 @@ def is_type_resolved(cairo_type: CairoType) -> bool: """ Returns true if the type is resolved (struct names are absolute). """ - if isinstance(cairo_type, (TypeFelt, TypeCodeoffset)): + if isinstance(cairo_type, (TypeFelt, TypeCodeoffset, TypeStruct)): return True elif isinstance(cairo_type, TypePointer): return is_type_resolved(cairo_type.pointee) - elif isinstance(cairo_type, TypeStruct): - return cairo_type.is_fully_resolved elif isinstance(cairo_type, TypeTuple): return all(map(is_type_resolved, cairo_type.types)) else: diff --git a/src/starkware/cairo/lang/compiler/type_system_visitor.py b/src/starkware/cairo/lang/compiler/type_system_visitor.py index 0830e7c5..7e12e181 100644 --- a/src/starkware/cairo/lang/compiler/type_system_visitor.py +++ b/src/starkware/cairo/lang/compiler/type_system_visitor.py @@ -1,10 +1,11 @@ import dataclasses -from typing import Optional, Tuple +from typing import List, Optional, Tuple from starkware.cairo.lang.compiler.ast.cairo_types import ( CairoType, TypeCodeoffset, TypeFelt, + TypeIdentifier, TypePointer, TypeStruct, TypeTuple, @@ -27,6 +28,7 @@ ExprSubscript, ExprTuple, ) +from starkware.cairo.lang.compiler.ast.expr_func_call import ExprFuncCall from starkware.cairo.lang.compiler.error_handling import Location from starkware.cairo.lang.compiler.expression_simplifier import ExpressionSimplifier from starkware.cairo.lang.compiler.identifier_manager import IdentifierManager @@ -34,6 +36,7 @@ from starkware.cairo.lang.compiler.preprocessor.identifier_aware_visitor import ( IdentifierAwareVisitor, ) +from starkware.cairo.lang.compiler.scoped_name import ScopedName from starkware.cairo.lang.compiler.type_casts import CairoTypeError, check_cast from starkware.python.utils import safe_zip @@ -49,8 +52,12 @@ class TypeSystemVisitor(IdentifierAwareVisitor): Helper class for simplify_type_system(). """ - def __init__(self, identifiers: Optional[IdentifierManager] = None): - super().__init__(identifiers) + def __init__( + self, + identifiers: Optional[IdentifierManager] = None, + accessible_scopes: Optional[List[ScopedName]] = None, + ): + super().__init__(identifiers=identifiers, accessible_scopes=accessible_scopes) self.identifiers_initalized = identifiers is not None def visit_ExprConst(self, expr: ExprConst) -> Tuple[ExprConst, TypeFelt]: @@ -142,6 +149,19 @@ def verify_offset_is_felt(offset_type: CairoType, offset_location: Location): location=offset_location, ) + def visit_ExprFuncCall(self, expr: ExprFuncCall) -> Tuple[ExprFuncCall, CairoType]: + return_type = self.get_return_type(func_call=expr.rvalue) + if not isinstance(return_type, (TypeFelt, TypeCodeoffset, TypePointer)): + raise CairoTypeError( + "Only functions with a simple return type are supported inside an expression. " + f"Got: '{return_type.format()}'.", + location=expr.location, + ) + + # Note that arguments to the given function call ('expr') are left as is (not visited here). + # The argument types will be validated when the code for the function call is generated. + return (expr, return_type) + def visit_ExprSubscript(self, expr: ExprSubscript) -> Tuple[Expression, CairoType]: inner_expr, inner_type = self.visit(expr.expr) offset_expr, offset_type = self.visit(expr.offset) @@ -235,6 +255,12 @@ def visit_ExprDot(self, expr: ExprDot) -> Tuple[ExprDeref, CairoType]: inner_expr, inner_type = self.visit(expr.expr) if isinstance(inner_type, TypePointer): if not isinstance(inner_type.pointee, (TypeStruct, TypeTuple)): + if isinstance(inner_type.pointee, TypeIdentifier): + raise CairoTypeError( + f"Type is expected to be fully resolved at this point.", + location=inner_type.pointee.location, + ) + raise CairoTypeError( f"Cannot apply dot-operator to pointer-to-non-struct type " f"'{inner_type.format()}'.", @@ -259,7 +285,7 @@ def visit_ExprDot(self, expr: ExprDot) -> Tuple[ExprDeref, CairoType]: if isinstance(inner_type, TypeStruct): try: struct_def = get_struct_definition( - struct_name=inner_type.resolved_scope, identifier_manager=self.identifiers + struct_name=inner_type.scope, identifier_manager=self.identifiers ) except Exception as exc: raise CairoTypeError(str(exc), location=expr.location) @@ -367,7 +393,9 @@ def visit_ExprNewOperator(self, expr: ExprNewOperator) -> Tuple[ExprNewOperator, def simplify_type_system( - expr: Expression, identifiers: Optional[IdentifierManager] = None + expr: Expression, + identifiers: Optional[IdentifierManager] = None, + accessible_scopes: Optional[List[ScopedName]] = None, ) -> Tuple[Expression, CairoType]: """ Given an expression returns a type-simplified expression and its Cairo type. @@ -381,4 +409,7 @@ def simplify_type_system( In the second and third examples, the definition of struct T is looked up, and must be present, in the IdentifierManager 'identifiers'. """ - return TypeSystemVisitor(identifiers=identifiers).visit(expr) + return TypeSystemVisitor( + identifiers=identifiers, + accessible_scopes=accessible_scopes, + ).visit(expr) diff --git a/src/starkware/cairo/lang/compiler/type_system_visitor_test.py b/src/starkware/cairo/lang/compiler/type_system_visitor_test.py index 8a67b143..38305dac 100644 --- a/src/starkware/cairo/lang/compiler/type_system_visitor_test.py +++ b/src/starkware/cairo/lang/compiler/type_system_visitor_test.py @@ -3,7 +3,6 @@ import pytest -from starkware.cairo.lang.compiler.ast.ast_objects_test_utils import remove_parentheses from starkware.cairo.lang.compiler.ast.cairo_types import TypeFelt, TypePointer, TypeStruct from starkware.cairo.lang.compiler.ast.expr import ExprFutureLabel, ExprNewOperator from starkware.cairo.lang.compiler.ast_objects_test import remove_parentheses @@ -83,14 +82,14 @@ def test_type_tuples(): simplify_type_system_test( "(a=fp, b=[cast(fp, T*)], c=cast(fp,T*))", "(fp, [fp], fp)", - "(a : felt, b : T, c : T*)", + "(a: felt, b: T, c: T*)", ) # Nested. simplify_type_system_test( "(fp, (), ([cast(fp, T*)],))", "(fp, (), ([fp],))", - "(felt, (), (T))", + "(felt, (), (T,))", ) @@ -119,7 +118,7 @@ def test_type_tuples_failures(): def test_type_subscript_op(): - t = TypeStruct(scope=scope("T"), is_fully_resolved=True) + t = TypeStruct(scope=scope("T")) identifier_dict = {scope("T"): StructDefinition(full_name=scope("T"), members={}, size=7)} identifiers = IdentifierManager.from_dict(identifier_dict) @@ -236,25 +235,25 @@ def test_type_dot_op(): """ Tests type_system_visitor for ExprDot-s, in the following struct architecture: - struct S: - member x : felt - member y : felt - end + struct S { + x: felt, + y: felt, + } - struct T: - member t : felt - member s : S - member sp : S* - end + struct T { + t: felt, + s: S, + sp: S*, + } - struct R: - member r : R* - end + struct R { + r: R*, + } """ - t = TypeStruct(scope=scope("T"), is_fully_resolved=True) - s = TypeStruct(scope=scope("S"), is_fully_resolved=True) + t = TypeStruct(scope=scope("T")) + s = TypeStruct(scope=scope("S")) s_star = TypePointer(pointee=s) - r = TypeStruct(scope=scope("R"), is_fully_resolved=True) + r = TypeStruct(scope=scope("R")) r_star = TypePointer(pointee=r) identifier_dict = { @@ -366,7 +365,7 @@ def test_type_dot_op(): """ file:?:?: Type is expected to be fully resolved at this point. cast(fp, Z*).x -^************^ + ^ """, identifiers=identifiers, resolve_types=False, @@ -378,11 +377,11 @@ def test_type_dot_op_named_tuples(): Tests type_system_visitor for ExprDot-s for named tuples. """ identifiers = IdentifierManager() - tuple_ref = "[cast(fp, (x : felt, y : (a : felt, b : felt), z : felt)*)]" - tuple_ptr = "cast(fp, (x : felt, y : (a : felt, b : felt)*, z : felt)*)" + tuple_ref = "[cast(fp, (x: felt, y: (a: felt, b: felt), z: felt)*)]" + tuple_ptr = "cast(fp, (x: felt, y: (a: felt, b: felt)*, z: felt)*)" for (orig_expr, simplified_expr, simplified_type) in [ (f"{tuple_ref}.x", "[fp]", "felt"), - (f"{tuple_ref}.y", "[fp + 1]", "(a : felt, b : felt)"), + (f"{tuple_ref}.y", "[fp + 1]", "(a: felt, b: felt)"), (f"{tuple_ref}.y.a", "[fp + 1]", "felt"), (f"{tuple_ref}.y.b", "[fp + 1 + 1]", "felt"), (f"{tuple_ref}.z", "[fp + 3]", "felt"), @@ -405,11 +404,11 @@ def test_type_dot_op_named_tuples(): identifiers=identifiers, ) verify_exception( - "[cast(fp, (a : felt, b : felt)*)].x", + "[cast(fp, (a: felt, b: felt)*)].x", """ -file:?:?: Member 'x' does not appear in definition of tuple type '(a : felt, b : felt)'. -[cast(fp, (a : felt, b : felt)*)].x -^*********************************^ +file:?:?: Member 'x' does not appear in definition of tuple type '(a: felt, b: felt)'. +[cast(fp, (a: felt, b: felt)*)].x +^*******************************^ """, identifiers=identifiers, ) diff --git a/src/starkware/cairo/lang/compiler/type_utils.py b/src/starkware/cairo/lang/compiler/type_utils.py index 3545f93b..03322e2d 100644 --- a/src/starkware/cairo/lang/compiler/type_utils.py +++ b/src/starkware/cairo/lang/compiler/type_utils.py @@ -17,7 +17,7 @@ def check_felts_only_type( return 1 elif isinstance(cairo_type, TypeStruct): struct_definition = get_struct_definition( - cairo_type.resolved_scope, identifier_manager=identifier_manager + cairo_type.scope, identifier_manager=identifier_manager ) size = 0 diff --git a/src/starkware/cairo/lang/compiler/type_utils_test.py b/src/starkware/cairo/lang/compiler/type_utils_test.py index 0415072a..cc99b6ce 100644 --- a/src/starkware/cairo/lang/compiler/type_utils_test.py +++ b/src/starkware/cairo/lang/compiler/type_utils_test.py @@ -8,27 +8,27 @@ def test_check_felts_only_type(): program = preprocess_str( """ -struct A: - member x : felt -end +struct A { + x: felt, +} -struct B: -end +struct B { +} -struct C: - member x : felt - member y : (felt, A, B) - member z : A -end +struct C { + x: felt, + y: (felt, A, B), + z: A, +} -struct D: - member x : felt* -end +struct D { + x: felt*, +} -struct E: - member x : D -end - """, +struct E { + x: D, +} +""", prime=DEFAULT_PRIME, ) diff --git a/src/starkware/cairo/lang/ide/vim/syntax/cairo.vim b/src/starkware/cairo/lang/ide/vim/syntax/cairo.vim index f02de553..c6af6942 100644 --- a/src/starkware/cairo/lang/ide/vim/syntax/cairo.vim +++ b/src/starkware/cairo/lang/ide/vim/syntax/cairo.vim @@ -18,12 +18,12 @@ hi def link funcName Function hi def link num Constant hi def link specialIdentifier Special -syn keyword statement call jmp ret abs rel if const let end from import static_assert local tempvar - \ felt return assert member cast else alloc_locals as with with_attr nondet dw codeoffset new +syn keyword statement call jmp ret abs rel if const let from import static_assert local tempvar + \ felt return assert cast else alloc_locals as with with_attr nondet dw codeoffset new \ using and syn keyword register ap fp syn keyword specialIdentifier SIZEOF_LOCALS SIZE -syn match comment '#[^\n]*\n' +syn match comment '//[^\n]*\n' syn keyword funcDef func namespace struct nextgroup=funcName skipwhite syn match funcName '[a-zA-Z_][a-zA-Z0-9_]*' display contained syn match num '[+-]\?\d\+' diff --git a/src/starkware/cairo/lang/ide/vscode-cairo/language-configuration.json b/src/starkware/cairo/lang/ide/vscode-cairo/language-configuration.json index fba5a9c6..941c4110 100644 --- a/src/starkware/cairo/lang/ide/vscode-cairo/language-configuration.json +++ b/src/starkware/cairo/lang/ide/vscode-cairo/language-configuration.json @@ -1,7 +1,7 @@ { "comments": { // Symbol used for single line comment. - "lineComment": "#", + "lineComment": "//", }, // Symbols used as brackets. "brackets": [ diff --git a/src/starkware/cairo/lang/ide/vscode-cairo/package.json b/src/starkware/cairo/lang/ide/vscode-cairo/package.json index 2c230dfa..ba045f60 100644 --- a/src/starkware/cairo/lang/ide/vscode-cairo/package.json +++ b/src/starkware/cairo/lang/ide/vscode-cairo/package.json @@ -2,7 +2,7 @@ "name": "cairo", "displayName": "Cairo", "description": "Support Cairo syntax", - "version": "0.9.1", + "version": "0.10.0", "engines": { "vscode": "^1.30.0" }, diff --git a/src/starkware/cairo/lang/ide/vscode-cairo/snippets.json b/src/starkware/cairo/lang/ide/vscode-cairo/snippets.json index 62dbe004..d4f3bdde 100644 --- a/src/starkware/cairo/lang/ide/vscode-cairo/snippets.json +++ b/src/starkware/cairo/lang/ide/vscode-cairo/snippets.json @@ -5,8 +5,8 @@ ], "body": [ "@storage_var", - "func ${1:name}() -> (${2:res : felt}):", - "end", + "func ${1:name}() -> (${2:res: felt}) {", + "}", "$0" ], "description": "A StarkNet storage variable." @@ -17,11 +17,11 @@ ], "body": [ "@external", - "func ${1:name}{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(", + "func ${1:name}{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(", "\t${2:arguments}", - "):", + ") {", "\t$0", - "end" + "}" ], "description": "A StarkNet contract external function." }, @@ -31,9 +31,9 @@ ], "body": [ "@contract_interface", - "namespace ${1:name}:", + "namespace ${1:name} {", "\t$0", - "end" + "}" ], "description": "A contract interface for another contract." } diff --git a/src/starkware/cairo/lang/ide/vscode-cairo/syntaxes/cairo.tmLanguage.json b/src/starkware/cairo/lang/ide/vscode-cairo/syntaxes/cairo.tmLanguage.json index 76bae14e..de288c07 100644 --- a/src/starkware/cairo/lang/ide/vscode-cairo/syntaxes/cairo.tmLanguage.json +++ b/src/starkware/cairo/lang/ide/vscode-cairo/syntaxes/cairo.tmLanguage.json @@ -4,7 +4,7 @@ "patterns": [ { "name": "meta.control.if", - "begin": "\\b(if)\\s+(.+)\\s*\\:", + "begin": "\\b(if).*\\(", "beginCaptures": { "1": { "name": "keyword.control.if" @@ -14,7 +14,7 @@ } }, "contentName": "source.cairo", - "end": "\\bend\\b", + "end": "\\}", "patterns": [ { "include": "source.cairo" @@ -28,7 +28,7 @@ }, { "name": "meta.control.with", - "begin": "\\b(with)\\s+(.+)\\s*\\:", + "begin": "\\b(with)\\s+(.+)\\s*\\{", "beginCaptures": { "1": { "name": "keyword.control.with" @@ -38,7 +38,7 @@ } }, "contentName": "source.cairo", - "end": "\\bend\\b", + "end": "\\}", "patterns": [ { "include": "source.cairo" @@ -52,7 +52,7 @@ }, { "name": "meta.control.with_attr", - "begin": "\\b(with_attr)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*[(:]", + "begin": "\\b(with_attr)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*[({]", "beginCaptures": { "1": { "name": "keyword.control.with_attr" @@ -62,7 +62,7 @@ } }, "contentName": "source.cairo", - "end": "\\bend\\b", + "end": "\\}", "patterns": [ { "include": "source.cairo" @@ -88,7 +88,7 @@ }, { "name": "keyword.other.meta", - "match": "\\b(const|let|local|tempvar|felt|as|from|import|static_assert|return|assert|member|cast|alloc_locals|with|with_attr|nondet|dw|codeoffset|new|using|and)\\b" + "match": "\\b(const|let|local|tempvar|felt|as|from|import|static_assert|return|assert|cast|alloc_locals|with|with_attr|nondet|dw|codeoffset|new|using|and)\\b" }, { "name": "markup.italic", @@ -96,11 +96,11 @@ }, { "name": "comment.line.sharp", - "match": "#[^\n]*\n" + "match": "//[^\n]*\n" }, { "name": "entity.name.function", - "match": "\\b[a-zA-Z_][a-zA-Z0-9_]*:" + "match": "\\b[a-zA-Z_][a-zA-Z0-9_]*:\\s*$" }, { "name": "meta.function.cairo", @@ -114,7 +114,7 @@ } }, "contentName": "source.cairo", - "end": "\\bend\\b", + "end": "\\}", "patterns": [ { "include": "source.cairo" @@ -128,7 +128,7 @@ }, { "name": "meta.function.cairo", - "begin": "\\b(struct|namespace)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*:", + "begin": "\\b(struct|namespace)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\{", "beginCaptures": { "1": { "name": "storage.type.function.cairo" @@ -138,7 +138,7 @@ } }, "contentName": "source.cairo", - "end": "\\bend\\b", + "end": "\\}", "patterns": [ { "include": "source.cairo" @@ -189,30 +189,6 @@ "include": "source.python" } ] - }, - { - "begin": "%\\[", - "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.python" - } - }, - "end": "%\\]", - "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.python" - }, - "1": { - "name": "source.python" - } - }, - "name": "meta.embedded.block.python", - "contentName": "source.python", - "patterns": [ - { - "include": "source.python" - } - ] } ], "scopeName": "source.cairo" diff --git a/src/starkware/cairo/lang/instances.py b/src/starkware/cairo/lang/instances.py index f9eafb47..fb827c57 100644 --- a/src/starkware/cairo/lang/instances.py +++ b/src/starkware/cairo/lang/instances.py @@ -5,6 +5,7 @@ from starkware.cairo.lang.builtins.bitwise.instance_def import BitwiseInstanceDef from starkware.cairo.lang.builtins.ec.instance_def import EcOpInstanceDef from starkware.cairo.lang.builtins.hash.instance_def import PedersenInstanceDef +from starkware.cairo.lang.builtins.keccak.instance_def import KeccakInstanceDef from starkware.cairo.lang.builtins.range_check.instance_def import RangeCheckInstanceDef from starkware.cairo.lang.builtins.signature.instance_def import EcdsaInstanceDef @@ -104,6 +105,123 @@ class CairoLayout: n_trace_columns=22, ) +perpetual_with_bitwise_instance = CairoLayout( + layout_name="perpetual_with_bitwise", + rc_units=4, + diluted_pool_instance_def=DilutedPoolInstanceDef( + units_per_step=2, + spacing=4, + n_bits=16, + ), + builtins=dict( + output=True, + pedersen=PedersenInstanceDef( + ratio=32, + repetitions=1, + element_height=256, + element_bits=252, + n_inputs=2, + hash_limit=PRIME, + ), + range_check=RangeCheckInstanceDef( + ratio=16, + n_parts=8, + ), + ecdsa=EcdsaInstanceDef( + ratio=2048, + repetitions=1, + height=256, + n_hash_bits=251, + ), + bitwise=BitwiseInstanceDef( + ratio=64, + total_n_bits=251, + ), + ec_op=EcOpInstanceDef( + ratio=1024, + scalar_height=256, + scalar_bits=252, + scalar_limit=PRIME, + ), + ), + n_trace_columns=10, +) + +# A layout with a lot of bitwise instances (e.g., for a Cairo implementation of hash functions). +bitwise_instance = CairoLayout( + layout_name="bitwise", + rc_units=4, + public_memory_fraction=8, + diluted_pool_instance_def=DilutedPoolInstanceDef( + units_per_step=16, + spacing=4, + n_bits=16, + ), + builtins=dict( + output=True, + pedersen=PedersenInstanceDef( + ratio=256, + repetitions=1, + element_height=256, + element_bits=252, + n_inputs=2, + hash_limit=PRIME, + ), + range_check=RangeCheckInstanceDef( + ratio=8, + n_parts=8, + ), + ecdsa=EcdsaInstanceDef( + ratio=1024, + repetitions=1, + height=256, + n_hash_bits=251, + ), + bitwise=BitwiseInstanceDef( + ratio=8, + total_n_bits=251, + ), + ), + n_trace_columns=10, +) + +# A layout optimized for a cairo verifier program that is being verified by a cairo verifier. +recursive_instance = CairoLayout( + layout_name="recursive", + rc_units=4, + public_memory_fraction=8, + diluted_pool_instance_def=DilutedPoolInstanceDef( + units_per_step=16, + spacing=4, + n_bits=16, + ), + builtins=dict( + output=True, + pedersen=PedersenInstanceDef( + ratio=256, + repetitions=1, + element_height=256, + element_bits=252, + n_inputs=2, + hash_limit=PRIME, + ), + range_check=RangeCheckInstanceDef( + ratio=8, + n_parts=8, + ), + bitwise=BitwiseInstanceDef( + ratio=16, + total_n_bits=251, + ), + keccak=KeccakInstanceDef( + ratio=2**11, + state_rep=[200] * 8, + instances_per_component=16, + ), + ), + n_trace_columns=11, +) + all_instance = CairoLayout( layout_name="all", rc_units=8, @@ -151,5 +269,7 @@ class CairoLayout: "plain": plain_instance, "small": small_instance, "dex": dex_instance, + "bitwise": bitwise_instance, + "perpetual_with_bitwise": perpetual_with_bitwise_instance, "all": all_instance, } diff --git a/src/starkware/cairo/lang/lang.cmake b/src/starkware/cairo/lang/lang.cmake index 124c0eb1..7ac360b7 100644 --- a/src/starkware/cairo/lang/lang.cmake +++ b/src/starkware/cairo/lang/lang.cmake @@ -7,7 +7,7 @@ python_lib(cairo_version_lib ) if (NOT DEFINED CAIRO_PYTHON_INTERPRETER) - set(CAIRO_PYTHON_INTERPRETER python3.7) + set(CAIRO_PYTHON_INTERPRETER python3.9) endif() python_venv(cairo_lang_venv @@ -36,8 +36,10 @@ python_venv(cairo_lang_package_venv sharp_client_config_lib sharp_client_lib starknet_block_hash_lib + starknet_business_logic_fact_state_lib starknet_business_logic_state_lib starknet_script_lib + starknet_sequencer_api_utils_lib starknet_testing_lib starkware_eth_test_utils_lib ) diff --git a/src/starkware/cairo/lang/migrators/CMakeLists.txt b/src/starkware/cairo/lang/migrators/CMakeLists.txt new file mode 100644 index 00000000..8f1b7c60 --- /dev/null +++ b/src/starkware/cairo/lang/migrators/CMakeLists.txt @@ -0,0 +1,35 @@ +python_lib(cairo_migrator_lib + PREFIX starkware/cairo/lang/migrators + + FILES + migrator_grammar.ebnf + migrator.py + + LIBS + cairo_compile_lib +) + +full_python_test(cairo_migrator_test + PREFIX starkware/cairo/lang/migrators + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/lang/migrators + + FILES + migrator_test.py + + LIBS + cairo_migrator_lib + cairo_compile_lib + pip_pytest +) + +python_venv(cairo_migrator_venv + PYTHON ${PYTHON_COMMAND} + LIBS + cairo_migrator_lib +) + +python_exe(cairo_migrator + VENV cairo_migrator_venv + MODULE starkware.cairo.lang.migrators.migrator +) diff --git a/src/starkware/crypto/starkware/crypto/__init__.py b/src/starkware/cairo/lang/migrators/__init__.py similarity index 100% rename from src/starkware/crypto/starkware/crypto/__init__.py rename to src/starkware/cairo/lang/migrators/__init__.py diff --git a/src/starkware/cairo/lang/migrators/migrator.py b/src/starkware/cairo/lang/migrators/migrator.py new file mode 100644 index 00000000..4be2f772 --- /dev/null +++ b/src/starkware/cairo/lang/migrators/migrator.py @@ -0,0 +1,305 @@ +import functools +import os +import sys +from typing import Iterable, List, Optional, Set + +import lark + +from starkware.cairo.lang.compiler.ast.cairo_types import TypeTuple +from starkware.cairo.lang.compiler.ast.code_elements import ( + CodeElement, + CodeElementFunction, + CodeElementImport, + CodeElementLocalVariable, + CodeElementReturn, + CodeElementReturnValueReference, + CodeElementScoped, + CodeElementTailCall, + CodeElementUnpackBinding, + CommentedCodeElement, +) +from starkware.cairo.lang.compiler.ast.expr import ( + ArgList, + ExprAssignment, + ExprParentheses, + ExprTuple, +) +from starkware.cairo.lang.compiler.ast.expr_func_call import ExprFuncCall +from starkware.cairo.lang.compiler.ast.module import CairoFile +from starkware.cairo.lang.compiler.ast.notes import Notes +from starkware.cairo.lang.compiler.ast.rvalue import RvalueFuncCall +from starkware.cairo.lang.compiler.ast.visitor import Visitor +from starkware.cairo.lang.compiler.cairo_format import cairo_format_arg_parser, cairo_format_common +from starkware.cairo.lang.compiler.error_handling import InputFile +from starkware.cairo.lang.compiler.parser import get_grammar_parser, parse, parse_file +from starkware.cairo.lang.compiler.parser_transformer import ParserContext, ParserTransformer +from starkware.cairo.lang.compiler.scoped_name import ScopedName + +GRAMMER_FILE = os.path.join(os.path.dirname(__file__), "migrator_grammar.ebnf") +MIGRATE_FUNCTIONS: List[str] = [ + "starkware.cairo.common.ec.is_x_on_curve", + "starkware.cairo.common.math_cmp.is_in_range", + "starkware.cairo.common.math_cmp.is_le_felt", + "starkware.cairo.common.math_cmp.is_le", + "starkware.cairo.common.math_cmp.is_nn_le", + "starkware.cairo.common.math_cmp.is_nn", + "starkware.cairo.common.math_cmp.is_not_zero", + "starkware.cairo.common.math.abs_value", + "starkware.cairo.common.math.is_quad_residue", + "starkware.cairo.common.math.sign", + "starkware.cairo.common.math.sqrt", +] + + +class MigratorParserTransformer(ParserTransformer): + """ + Modified ParserTransformer that works with migrator_grammar.ebnf. + """ + + def __init__(self, input_file: InputFile, parser_context: Optional[ParserContext]): + super().__init__(input_file, parser_context) + + def code_element_function(self, value): + decorators, identifier, implicit_arguments, arguments = value[:4] + if len(value) == 6: + # Return values present. + returns_identifier_list = value[4] + code_block = value[5] + returns = TypeTuple.from_members( + members=[ + TypeTuple.Item( + name=typed_identifier.name, + typ=typed_identifier.get_type(), + location=typed_identifier.location, + ) + for typed_identifier in returns_identifier_list.identifiers + ], + location=returns_identifier_list.location, + ) + elif len(value) == 5: + # Return values not present. + returns = None + code_block = value[4] + else: + raise NotImplementedError(f"Unexpected argument: value={value}") + + return CodeElementFunction( + element_type="func", + identifier=identifier, + arguments=arguments, + implicit_arguments=implicit_arguments, + returns=returns, + code_block=code_block, + decorators=decorators, + ) + + @lark.v_args(meta=True) + def commented_code_element(self, value, meta): + comment = value[1][1:] if len(value) == 2 else None + return CommentedCodeElement( + code_elm=value[0], comment=comment, location=self.meta2loc(meta) + ) + + @lark.v_args(meta=True) + def code_element_return(self, value, meta): + (expr,) = value + + if not isinstance(expr, ExprParentheses): + return super().code_element_return(value, meta) + + # Replace the outer parentheses with an ExprTuple with has_trailing_comma=True. + location = self.meta2loc(meta) + expr = ExprTuple( + members=ArgList( + args=[ExprAssignment(identifier=None, expr=expr.val, location=expr.location)], + notes=[Notes(), Notes()], + has_trailing_comma=True, + location=expr.location, + ), + location=location, + ) + + return CodeElementReturn(expr=expr, location=location) + + +class MigrateFunctionCalls(Visitor): + """ + Migrate calls to some single-return standard library functions. + A different instance of this visitor should be used per file. + """ + + def __init__(self, single_return_functions: Iterable[str]): + super().__init__() + self.local_functions_to_migrate: Set[str] = set() + self.single_return_functions = list(single_return_functions) + + def _visit_default(self, elm: CodeElement): + assert isinstance(elm, CodeElement) + return elm + + def visit_CodeElementImport(self, elm: CodeElementImport): + for item in elm.import_items: + imported_function = f"{elm.path.name}.{item.orig_identifier.name}" + if imported_function in self.single_return_functions: + self.local_functions_to_migrate.add(item.identifier.name) + return elm + + def visit_CodeElementUnpackBinding(self, elm: CodeElementUnpackBinding): + """ + Migrates statements of the form: + let (x) = foo(); + to: + let x = foo(); + """ + + if not isinstance(elm.rvalue, RvalueFuncCall): + return elm + if elm.rvalue.func_ident.name not in self.local_functions_to_migrate: + return elm + if len(elm.unpacking_list.identifiers) != 1: + return elm + + # Don't convert if there are comments inside the unpacking. + if any(len(note.comments) > 0 for note in elm.unpacking_list.notes): + return elm + + identifier = elm.unpacking_list.identifiers[0] + location = elm.unpacking_list.location + + if identifier.modifier is not None: + if identifier.modifier.name != "local": + return elm + return CodeElementLocalVariable( + typed_identifier=identifier.strip_modifier(), + expr=ExprFuncCall(rvalue=elm.rvalue, location=location), + location=location, + ) + + return CodeElementReturnValueReference( + typed_identifier=identifier, + func_call=elm.rvalue, + ) + + def visit_CodeElementTailCall(self, elm: CodeElementTailCall): + """ + Migrates statements of the form: + return foo(); + to: + return (foo(),); + """ + if elm.func_call.func_ident.name not in self.local_functions_to_migrate: + return elm + + location = elm.location + return CodeElementReturn( + expr=ExprTuple( + members=ArgList( + args=[ + ExprAssignment( + identifier=None, + expr=ExprFuncCall(rvalue=elm.func_call, location=location), + location=location, + ) + ], + notes=[Notes(), Notes()], + has_trailing_comma=True, + location=location, + ), + location=location, + ), + location=location, + ) + + +@functools.lru_cache(None) +def get_old_grammar() -> lark.Lark: + return get_grammar_parser(grammar=open(GRAMMER_FILE, "r").read()) + + +def parse_and_migrate( + code: str, filename: str, migrate_syntax: bool, single_return_functions: Optional[Iterable[str]] +): + if migrate_syntax: + ast = parse( + filename=filename, + code=code, + code_type="cairo_file", + expected_type=CairoFile, + parser_transformer_class=MigratorParserTransformer, + grammar_parser=get_old_grammar(), + ) + else: + ast = parse_file(code=code, filename=filename) + + if single_return_functions is not None: + scoped_ast = CodeElementScoped(scope=ScopedName.from_string(""), code_elements=[ast]) + scoped_ast = MigrateFunctionCalls(single_return_functions=single_return_functions).visit( + scoped_ast + ) + assert isinstance(scoped_ast, CodeElementScoped) and len(scoped_ast.code_elements) == 1 + ast = scoped_ast.code_elements[0] + + return ast + + +def main(): + validate_parser = lambda code, filename: parse_file(code=code, filename=filename) + + arg_parser = cairo_format_arg_parser( + description="A tool to migrate Cairo code from versions before 0.10.0.", + ) + + arg_parser.add_argument( + "--migrate_syntax", + dest="migrate_syntax", + action="store_true", + default=True, + help="Convert the syntax from Cairo versions before 0.10.0.", + ) + arg_parser.add_argument( + "--no_migrate_syntax", + dest="migrate_syntax", + action="store_false", + help=( + "Don't convert the syntax. This flag should only be used if the syntax was " + "already migrated." + ), + ) + + arg_parser.add_argument( + "--single_return_functions", + dest="single_return_functions", + action="store_true", + default=True, + help=( + "In version 0.10.0 some standard library functions, such as abs(), " + "have changed to return 'felt' instead of '(res: felt)'. " + "This requires syntax changes in the calling functions. " + "For example, 'let (x) = abs(-5)' should change to 'let x = abs(-5)'." + ), + ) + arg_parser.add_argument( + "--no_single_return_functions", + dest="single_return_functions", + action="store_false", + help=( + "Don't migrate calls to some single-return functions, such as abs(). " + "See '--single_return_functions'." + ), + ) + + args = arg_parser.parse_args() + + return cairo_format_common( + args=args, + cairo_parser=functools.partial( + parse_and_migrate, + migrate_syntax=args.migrate_syntax, + single_return_functions=MIGRATE_FUNCTIONS if args.single_return_functions else None, + ), + validate_parser=validate_parser, + ) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/starkware/cairo/lang/migrators/migrator_grammar.ebnf b/src/starkware/cairo/lang/migrators/migrator_grammar.ebnf new file mode 100644 index 00000000..82b27823 --- /dev/null +++ b/src/starkware/cairo/lang/migrators/migrator_grammar.ebnf @@ -0,0 +1,178 @@ +%import common.INT +%import common.WS_INLINE +%import common.NEWLINE +%ignore WS_INLINE + +HEXINT: /0x[0-9a-fA-F]+/ +HINT: /%\{(.*?)%\}/s +IDENTIFIER: /[a-zA-Z_][a-zA-Z_0-9]*/ +STRING: /"(.*?)"/ +SHORT_STRING: /'(.*?)'/ +_DBL_PLUS: "++" +_DBL_EQ: "==" +_DBL_STAR: "**" +_NEQ: "!=" +_ARROW: "->" +_AT: "@" + +// Comma separated list with notes. +COMMA: "," +_expr_sep: (COMMA | nonempty_notes)+ +comma_separated_with_notes{item}: notes item? (_expr_sep item)* _expr_sep? + +// Types. +named_type: identifier (":" type)? | non_identifier_type +non_identifier_type: "felt" -> type_felt + | "codeoffset" -> type_codeoffset + | type "*" -> type_pointer + | type _DBL_STAR -> type_pointer2 + | "(" comma_separated_with_notes{named_type} ")" -> type_tuple +?type: non_identifier_type + | identifier -> type_struct + +// Expressions. +expr_assignment: expr | identifier_def "=" expr +arg_list: comma_separated_with_notes{expr_assignment} + +decorator: _AT identifier_def +decorator_list: (decorator _NEWLINE*)* + +?expr: sum +?sum: product + | sum "+" notes product -> expr_add + | sum "-" notes product -> expr_sub +?product: unary + | product "*" notes unary -> expr_mul + | product "/" notes unary -> expr_div +?unary: pow + | "&" unary -> unary_addressof + | "-" unary -> unary_neg + | "new" unary -> unary_new_operator +?pow: atom + | atom _DBL_STAR notes pow -> expr_pow +identifier: IDENTIFIER ("." IDENTIFIER)* +identifier_def: IDENTIFIER +?atom: INT -> atom_number + | HEXINT -> atom_hex_number + | SHORT_STRING -> atom_short_string + | "nondet" HINT -> atom_hint + | reg -> atom_reg + | function_call -> atom_func_call + | identifier + | "[" notes expr "]" -> atom_deref + | atom "[" notes expr "]" -> atom_subscript + | atom "." identifier_def -> atom_dot + | "cast" "(" notes expr "," type ")" -> atom_cast + | "(" arg_list ")" -> atom_tuple_or_parentheses +!reg: "ap" -> reg_ap + | "fp" -> reg_fp + +?bool_expr: bool_and + +?bool_and: bool_and "and" notes bool_atom -> bool_and_expr + | bool_atom + +?bool_atom: expr _DBL_EQ notes expr -> bool_expr_eq + | expr _NEQ notes expr -> bool_expr_neq + +!modifier: "local" -> modifier_local + +typed_identifier: (modifier)? identifier_def (":" type)? + +_ref_binding: typed_identifier | "(" identifier_list ")" + +identifier_list: notes ((typed_identifier notes "," notes)* typed_identifier notes ","?)? notes + +// Instructions. +// Define RET as a terminal to get the location of the instruction correctly. +RET: "ret" +call_instruction: "call" "rel" expr -> inst_call_rel + | "call" "abs" expr -> inst_call_abs + | "call" identifier -> inst_call_label +?instruction_body: expr "=" expr -> inst_assert_eq + | "jmp" "rel" expr -> inst_jmp_rel + | "jmp" "abs" expr -> inst_jmp_abs + | "jmp" identifier -> inst_jmp_to_label + | "jmp" "rel" expr "if" expr _NEQ INT -> inst_jnz + | "jmp" identifier "if" expr _NEQ INT -> inst_jnz_to_label + | call_instruction + | RET -> inst_ret + | "ap" "+=" expr -> inst_add_ap + | "dw" expr -> inst_data_word +instruction: instruction_body -> instruction_noap + | instruction_body ";" "ap" _DBL_PLUS -> instruction_ap + +function_call: identifier ("{" arg_list "}")? "(" arg_list ")" + +// Reference expressions. +rvalue: call_instruction -> rvalue_call_instruction + | expr -> rvalue_expr + +// Directives. +BUILTINS: "%builtins" +LANG: "%lang" +directive: BUILTINS identifier+ -> directive_builtins + | LANG identifier -> directive_lang + +// Import statement. +aliased_identifier: identifier_def ("as" identifier_def)? + +_import_body: aliased_identifier ("," aliased_identifier)* + | "(" notes (aliased_identifier notes "," notes)* aliased_identifier notes ","? notes ")" + +_import: "from" identifier "import" _import_body + +// Function/Namespace/Struct definition. +_returns: _ARROW _NEWLINE* "(" identifier_list ")" +_arguments: "(" identifier_list ")" +implicit_arguments: ("{" identifier_list "}")? +_funcdecl: "func" identifier_def implicit_arguments _arguments _NEWLINE* _returns? ":" +_func: decorator_list _funcdecl _NEWLINE code_block "end" +_if: "if" bool_expr ":" _NEWLINE code_block ("else" ":" _NEWLINE code_block)? "end" + +_struct: decorator_list "struct" identifier_def ":"_NEWLINE code_block "end" +_namespace: decorator_list "namespace" identifier_def ":"_NEWLINE code_block "end" + +_with_statement: "with" (aliased_identifier ",")* aliased_identifier ":" _NEWLINE code_block "end" + +_attr_val: "(" notes (STRING notes)* ")" +_with_attr_statement: "with_attr" identifier_def _attr_val? ":" _NEWLINE code_block "end" + +// Cairo file. +_NEWLINE: "\n" +COMMENT: /#.*/ + +// Note: code_element_label is using identifier instead of identifier_def, in order to make the +// parser LALR-friendly. +code_element: instruction -> code_element_instruction + | "const" identifier_def "=" expr -> code_element_const + | "member" typed_identifier -> code_element_member + | "let" _ref_binding "=" rvalue -> code_element_reference + | "local" typed_identifier ("=" expr)? -> code_element_local_var + | "tempvar" typed_identifier ("=" expr)? -> code_element_temp_var + | "assert" expr "=" expr -> code_element_compound_assert_eq + | "static_assert" expr _DBL_EQ expr -> code_element_static_assert + | "return" expr -> code_element_return + | _if -> code_element_if + | function_call -> code_element_func_call + | identifier ":" -> code_element_label + | _func -> code_element_function + | _struct -> code_element_struct + | _namespace -> code_element_namespace + | "using" identifier_def "=" type -> code_element_typedef + | _with_attr_statement -> code_element_with_attr + | _with_statement -> code_element_with + | HINT -> code_element_hint + | directive -> code_element_directive + | _import -> code_element_import + | "alloc_locals" -> code_element_alloc_locals + | -> code_element_empty_line +commented_code_element: code_element [COMMENT] +code_block: (commented_code_element _NEWLINE)* + +cairo_file: code_block + +// Notes (comments inside parentheses). +note_new_line: _NEWLINE +nonempty_notes: (note_new_line | COMMENT)+ -> notes +notes: (note_new_line | COMMENT)* diff --git a/src/starkware/cairo/lang/migrators/migrator_test.py b/src/starkware/cairo/lang/migrators/migrator_test.py new file mode 100644 index 00000000..b78b67c9 --- /dev/null +++ b/src/starkware/cairo/lang/migrators/migrator_test.py @@ -0,0 +1,179 @@ +from typing import Iterable, Optional + +from starkware.cairo.lang.migrators.migrator import parse_and_migrate + + +def run_migrator_test( + input: str, + expected_output: str, + migrate_syntax: bool = True, + single_return_functions: Optional[Iterable[str]] = None, +): + filename = "" + ast = parse_and_migrate( + input, + filename, + migrate_syntax=migrate_syntax, + single_return_functions=single_return_functions, + ) + assert ast.format() == expected_output + + +def test_return_type_migration(): + run_migrator_test( + input="""\ +func test{x}(y) -> (a, b : felt*, c): + foo(4, 5) + if a == c and 1 == 2: + [ap] = 0; ap++ + end + ret +end +""", + expected_output="""\ +func test{x}(y) -> (a: felt, b: felt*, c: felt) { + foo(4, 5); + if (a == c and 1 == 2) { + [ap] = 0, ap++; + } + ret; +} +""", + ) + + run_migrator_test( + input="""\ +func test(y): + ret +end +""", + expected_output="""\ +func test(y) { + ret; +} +""", + ) + + run_migrator_test( + input="""\ +func test{y}() -> (): + ret +end +""", + expected_output="""\ +func test{y}() -> () { + ret; +} +""", + ) + + +def test_struct_migration(): + run_migrator_test( + input="""\ +struct A: + member x : felt # Comment +end +""", + expected_output="""\ +struct A { + x: felt, // Comment +} +""", + ) + + +def test_namespace_migration(): + run_migrator_test( + input="""\ +namespace A: + const x = 0 +end +""", + expected_output="""\ +namespace A { + const x = 0; +} +""", + ) + + +def test_return_expr_migration(): + run_migrator_test( + input=""" +func test(): + return (res=1) + return (5) + return (x=1, y=2) + # Test partially named return statement. + # Note that the migrated line will not compile, and the developer will have to manually fix it. + return (1, x=2) + + # Test that tail calls can be parsed. + return test() +end +""", + expected_output="""\ +func test() { + return (res=1); + return (5,); + return (x=1, y=2); + // Test partially named return statement. + // Note that the migrated line will not compile, and the developer will have to manually fix it. + return (1, x=2); + + // Test that tail calls can be parsed. + return test(); +} +""", + ) + + +def test_single_return_functions(): + before = """ +from a import is_nn +from a import abs_value as abs_value2 +namespace A: + func test() -> (x): + let (res) = foo(x) + return abs_value(res) + let (res) = is_nn(x) + return abs_value2(res) + end +end +""" + after_only_syntax = """\ +from a import is_nn +from a import abs_value as abs_value2 +namespace A { + func test() -> (x: felt) { + let (res) = foo(x); + return abs_value(res); + let (res) = is_nn(x); + return abs_value2(res); + } +} +""" + after = """\ +from a import is_nn +from a import abs_value as abs_value2 +namespace A { + func test() -> (x: felt) { + let (res) = foo(x); + return abs_value(res); + let res = is_nn(x); + return (abs_value2(res),); + } +} +""" + single_return_functions = ["a.is_nn", "a.abs_value"] + run_migrator_test(before, after_only_syntax, migrate_syntax=True, single_return_functions=None) + run_migrator_test( + after_only_syntax, + after, + migrate_syntax=False, + single_return_functions=single_return_functions, + ) + run_migrator_test( + before, after, migrate_syntax=True, single_return_functions=single_return_functions + ) diff --git a/src/starkware/cairo/lang/package_test/main.cairo b/src/starkware/cairo/lang/package_test/main.cairo index e87aab52..0c763101 100644 --- a/src/starkware/cairo/lang/package_test/main.cairo +++ b/src/starkware/cairo/lang/package_test/main.cairo @@ -4,8 +4,8 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.hash import hash2 from starkware.cairo.common.serialize import serialize_word -func main{output_ptr : felt*, pedersen_ptr : HashBuiltin*}(): - let (hash) = hash2{hash_ptr=pedersen_ptr}(1, 2) - serialize_word(hash) - return () -end +func main{output_ptr: felt*, pedersen_ptr: HashBuiltin*}() { + let (hash) = hash2{hash_ptr=pedersen_ptr}(1, 2); + serialize_word(hash); + return (); +} diff --git a/src/starkware/cairo/lang/package_test/run_test.sh b/src/starkware/cairo/lang/package_test/run_test.sh index acdba4b2..649e005a 100755 --- a/src/starkware/cairo/lang/package_test/run_test.sh +++ b/src/starkware/cairo/lang/package_test/run_test.sh @@ -13,7 +13,7 @@ tmpdir=$(mktemp -d) cd ${tmpdir} # Create a new virtual environment. -python3.7 -m venv venv +python3.9 -m venv venv # Activate the environment. source venv/bin/activate @@ -31,6 +31,8 @@ res=$(cairo-run --program=main_compiled.json --layout=small --print_output) cairo-reconstruct-traceback --version > /dev/null +# Test cairo-migrate. +cairo-migrate --help > /dev/null # Test StarkNet compiler. starknet-compile ${root_dir}/src/starkware/starknet/apps/amm_sample/amm_sample.cairo > /dev/null diff --git a/src/starkware/cairo/lang/scripts/CMakeLists.txt b/src/starkware/cairo/lang/scripts/CMakeLists.txt index f3931415..dfe529e0 100644 --- a/src/starkware/cairo/lang/scripts/CMakeLists.txt +++ b/src/starkware/cairo/lang/scripts/CMakeLists.txt @@ -4,6 +4,7 @@ python_lib(cairo_script_lib cairo-compile cairo-format cairo-hash-program + cairo-migrate cairo-reconstruct-traceback cairo-run cairo-sharp @@ -11,6 +12,7 @@ python_lib(cairo_script_lib LIBS cairo_compile_lib cairo_hash_program_lib + cairo_migrator_lib cairo_run_lib cairo_vm_utils_lib sharp_client_lib diff --git a/src/starkware/cairo/lang/scripts/cairo-format b/src/starkware/cairo/lang/scripts/cairo-format index a22c648f..27616baf 100755 --- a/src/starkware/cairo/lang/scripts/cairo-format +++ b/src/starkware/cairo/lang/scripts/cairo-format @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.7 +#!/usr/bin/env python3.9 import os import sys diff --git a/src/starkware/cairo/lang/scripts/cairo-migrate b/src/starkware/cairo/lang/scripts/cairo-migrate new file mode 100755 index 00000000..d1490c55 --- /dev/null +++ b/src/starkware/cairo/lang/scripts/cairo-migrate @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +import os +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../../..')) +from starkware.cairo.lang.migrators.migrator import main # noqa + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/starkware/cairo/lang/setup.py b/src/starkware/cairo/lang/setup.py index 6ffd40fa..e86d1ace 100644 --- a/src/starkware/cairo/lang/setup.py +++ b/src/starkware/cairo/lang/setup.py @@ -23,6 +23,7 @@ package_data={ "starkware.cairo.common": ["*.cairo", "*/*.cairo"], "starkware.cairo.lang.compiler": ["cairo.ebnf", "lib/*.cairo"], + "starkware.cairo.lang.migrators": ["*.ebnf"], "starkware.cairo.lang.tracer": ["*.html", "*.css", "*.js", "*.png"], "starkware.cairo.lang": ["VERSION"], "starkware.cairo.sharp": ["config.json"], @@ -38,6 +39,7 @@ "starkware/cairo/lang/scripts/cairo-compile", "starkware/cairo/lang/scripts/cairo-format", "starkware/cairo/lang/scripts/cairo-hash-program", + "starkware/cairo/lang/scripts/cairo-migrate", "starkware/cairo/lang/scripts/cairo-reconstruct-traceback", "starkware/cairo/lang/scripts/cairo-run", "starkware/cairo/lang/scripts/cairo-sharp", diff --git a/src/starkware/cairo/lang/tracer/tracer_data_test.py b/src/starkware/cairo/lang/tracer/tracer_data_test.py index cf968a8e..a4c88fed 100644 --- a/src/starkware/cairo/lang/tracer/tracer_data_test.py +++ b/src/starkware/cairo/lang/tracer/tracer_data_test.py @@ -24,17 +24,17 @@ def test_tracer_data(): code = """ %builtins output -func main(output_ptr : felt*) -> (output_ptr : felt*): - [ap] = 1000; ap++ - let x = 2000 - [ap] = x; ap++ - let x = 5000 - let y = [ap] - [ap] = [ap - 2] + [ap - 1]; ap++ - assert [output_ptr] = 1234 - assert [output_ptr + 1] = 4321 - ret -end +func main(output_ptr: felt*) -> (output_ptr: felt*) { + [ap] = 1000, ap++; + let x = 2000; + [ap] = x, ap++; + let x = 5000; + let y = [ap]; + [ap] = [ap - 2] + [ap - 1], ap++; + assert [output_ptr] = 1234; + assert [output_ptr + 1] = 4321; + ret; +} """ program: Program = compile_cairo(code=code, prime=PRIME, debug_info=True) runner = CairoRunner(program, layout="small") diff --git a/src/starkware/cairo/lang/vm/CMakeLists.txt b/src/starkware/cairo/lang/vm/CMakeLists.txt index 91620f62..e5894ed4 100644 --- a/src/starkware/cairo/lang/vm/CMakeLists.txt +++ b/src/starkware/cairo/lang/vm/CMakeLists.txt @@ -6,6 +6,7 @@ python_lib(cairo_relocatable_lib relocatable_fields.py LIBS + starkware_python_utils_lib pip_marshmallow ) @@ -124,7 +125,7 @@ full_python_test(cairo_vm_test cairo_vm_lib cairo_vm_test_utils_lib cairo_vm_utils_lib - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib starkware_python_utils_lib starkware_python_test_utils_lib pip_marshmallow_dataclass diff --git a/src/starkware/cairo/lang/vm/air_public_input.py b/src/starkware/cairo/lang/vm/air_public_input.py index bcf2b409..95cbf435 100644 --- a/src/starkware/cairo/lang/vm/air_public_input.py +++ b/src/starkware/cairo/lang/vm/air_public_input.py @@ -1,18 +1,19 @@ import re from dataclasses import field -from typing import ClassVar, Dict, List, Tuple, Type +from typing import ClassVar, Dict, List, Optional, Tuple, Type import marshmallow import marshmallow_dataclass from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME from starkware.cairo.lang.vm.utils import IntAsHex, MemorySegmentAddresses +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata @marshmallow_dataclass.dataclass class PublicMemoryEntry: address: int - value: int = field(metadata=dict(marshmallow_field=IntAsHex(required=True))) + value: int = field(metadata=additional_metadata(marshmallow_field=IntAsHex(required=True))) # The public memory may be divided into several chunks, called "pages". page: int @@ -22,6 +23,8 @@ class PublicInput: # The name of the layout (e.g., 'small'), see the LAYOUTS dict in # starkware/cairo/lang/instances.py. layout: str + # If layout is "dynamic", layout_params will contain all the computed layout parameters. + layout_params: Optional[Dict[str, int]] rc_min: int rc_max: int n_steps: int diff --git a/src/starkware/cairo/lang/vm/builtin_runner.py b/src/starkware/cairo/lang/vm/builtin_runner.py index 9285c5be..103da56b 100644 --- a/src/starkware/cairo/lang/vm/builtin_runner.py +++ b/src/starkware/cairo/lang/vm/builtin_runner.py @@ -168,17 +168,26 @@ class SimpleBuiltinRunner(BuiltinRunner): """ def __init__( - self, name: str, included: bool, ratio: int, cells_per_instance: int, n_input_cells: int + self, + name: str, + included: bool, + ratio: int, + cells_per_instance: int, + n_input_cells: int, + instances_per_component: int = 1, ): """ Constructs a SimpleBuiltinRunner. cells_per_instance is the number of memory cells per invocation. n_input_cells is the number of the first memory cells in each invocation that form the input. The rest of the cells are considered output. + instances_per_component is the number of invocations being handled in each call to the + corresponding component. It must divide the total number of invocations. """ self.name = name self.included = included self.ratio = ratio + self.instances_per_component = instances_per_component self._base: Optional[RelocatableValue] = None self.stop_ptr: Optional[RelocatableValue] = None self.cells_per_instance = cells_per_instance @@ -219,9 +228,10 @@ def get_allocated_memory_units(self, runner): return self.cells_per_instance * safe_div(runner.vm.current_step, self.ratio) def get_used_cells_and_allocated_size(self, runner): - if runner.vm.current_step < self.ratio: + min_steps = self.ratio * self.instances_per_component + if runner.vm.current_step < min_steps: raise InsufficientAllocatedCells( - f"Number of steps must be at least {self.ratio} for the {self.name} builtin." + f"Number of steps must be at least {min_steps} for the {self.name} builtin." ) used = self.get_used_cells(runner) size = self.cells_per_instance * safe_div(runner.vm.current_step, self.ratio) @@ -266,6 +276,14 @@ def run_security_checks(self, runner): missing_offsets_str = ", ".join(map(str, missing_offsets[:20])) + dots raise AssertionError(f"Missing memory cells for {self.name}: {missing_offsets_str}") + # Verify auto deduction rules for the unassigned output cells. + # Assigned output cells are checked as part of the call to verify_auto_deductions(). + for i in range(n): + for j in range(self.n_input_cells, self.cells_per_instance): + addr = self.base + (self.cells_per_instance * i + j) + if runner.vm.validated_memory.get(addr) is None: + runner.vm.verify_auto_deductions_for_addr(addr) + def get_memory_accesses(self, runner): segment_size = runner.segments.get_segment_size(self.base.segment_index) return {self.base + x for x in range(segment_size)} diff --git a/src/starkware/cairo/lang/vm/cairo_pie.py b/src/starkware/cairo/lang/vm/cairo_pie.py index 184d012e..fbd40e27 100644 --- a/src/starkware/cairo/lang/vm/cairo_pie.py +++ b/src/starkware/cairo/lang/vm/cairo_pie.py @@ -20,6 +20,7 @@ from starkware.cairo.lang.vm.memory_segments import is_valid_memory_addr, is_valid_memory_value from starkware.cairo.lang.vm.relocatable import RelocatableValue from starkware.python.utils import add_counters, multiply_counter_by_scalar, sub_counters +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata DEFAULT_CAIRO_PIE_VERSION = "1.0" CURRENT_CAIRO_PIE_VERSION = "1.1" @@ -127,7 +128,9 @@ class ExecutionResources: n_steps: int builtin_instance_counter: Dict[str, int] - n_memory_holes: int = field(metadata=dict(marshmallow_field=mfields.Integer(load_default=0))) + n_memory_holes: int = field( + metadata=additional_metadata(marshmallow_field=mfields.Integer(load_default=0)) + ) Schema: ClassVar[Type[marshmallow.Schema]] = marshmallow.Schema def run_validity_checks(self): @@ -193,6 +196,20 @@ def to_dict(self) -> Dict[str, int]: n_steps=self.n_steps + self.n_memory_holes, ) + def filter_unused_builtins(self) -> "ExecutionResources": + """ + Returns a copy of the execution resources where all the builtins with a usage counter + of 0 are omitted. + """ + return dataclasses.replace( + self, + builtin_instance_counter={ + name: counter + for name, counter in self.builtin_instance_counter.items() + if counter > 0 + }, + ) + @dataclasses.dataclass class CairoPie: diff --git a/src/starkware/cairo/lang/vm/cairo_pie_test.py b/src/starkware/cairo/lang/vm/cairo_pie_test.py index 5d53d0d0..fccb45f5 100644 --- a/src/starkware/cairo/lang/vm/cairo_pie_test.py +++ b/src/starkware/cairo/lang/vm/cairo_pie_test.py @@ -21,7 +21,7 @@ def test_cairo_pie_serialize_deserialize(): program = compile_cairo( - code=[("%builtins output pedersen range_check ecdsa\nmain:\n[ap] = [ap]\n", "")], + code=[("%builtins output pedersen range_check ecdsa\nmain:\n[ap] = [ap];\n", "")], prime=DEFAULT_PRIME, ) metadata = CairoPieMetadata( @@ -68,9 +68,9 @@ def cairo_pie(): code = """ %builtins output pedersen -func main(output_ptr, pedersen_ptr) -> (output_ptr, pedersen_ptr): - return (output_ptr=output_ptr, pedersen_ptr=pedersen_ptr) -end +func main(output_ptr: felt*, pedersen_ptr: felt*) -> (output_ptr: felt*, pedersen_ptr: felt*) { + return (output_ptr=output_ptr, pedersen_ptr=pedersen_ptr); +} """ runner = get_runner_from_code(code=[(code, "")], layout="small", prime=DEFAULT_PRIME) return runner.get_cairo_pie() @@ -147,7 +147,7 @@ def test_cairo_pie_memory_invalid_value(cairo_pie: CairoPie): def test_add_execution_resources(): """ - Tests ExecutionResources __add__ calculation. + Tests ExecutionResources.__add__(). """ dummy_builtins = ["builtin1", "builtin2", "builtin3", "builtin4"] @@ -185,3 +185,24 @@ def test_add_execution_resources(): assert total_execution_resources.builtin_instance_counter == total_builtin_instance_counter assert total_execution_resources.n_steps == total_steps + + +def test_filter_unused_builtins(): + """ + Tests ExecutionResources.filter_unused_builtins(). + """ + execution_resources1 = ExecutionResources( + n_steps=17, + builtin_instance_counter={"builtin1": 1, "builtin2": 2, "builtin3": 1, "builtin4": 4}, + n_memory_holes=5, + ) + + execution_resources2 = ExecutionResources( + n_steps=17, + builtin_instance_counter={"builtin1": 1, "builtin2": 2, "builtin3": 3, "builtin4": 4}, + n_memory_holes=5, + ) + + diff = (execution_resources2 - execution_resources1).filter_unused_builtins() + + assert diff.builtin_instance_counter == {"builtin3": 2} diff --git a/src/starkware/cairo/lang/vm/cairo_run.py b/src/starkware/cairo/lang/vm/cairo_run.py index e5b8bcdf..5e041f26 100644 --- a/src/starkware/cairo/lang/vm/cairo_run.py +++ b/src/starkware/cairo/lang/vm/cairo_run.py @@ -6,7 +6,8 @@ import sys import tempfile import time -from typing import IO, Dict, List, Tuple +import traceback +from typing import IO, Dict, List, Optional, Tuple import starkware.python.python_dependencies as python_dependencies from starkware.cairo.lang.compiler.debug_info import DebugInfo @@ -156,6 +157,11 @@ def main(): parser.add_argument( "--proof_mode", action="store_true", help="Prepare a provable execution trace." ) + parser.add_argument( + "--show_trace", + action="store_true", + help="Print the full Python error trace in case of an internal error.", + ) parser.add_argument( "--flavor", type=str, @@ -193,9 +199,15 @@ def main(): res = cairo_run(args) except VmException as err: print(err, file=sys.stderr) + if args.show_trace: + print(file=sys.stderr) + traceback.print_exc() res = 1 except AssertionError as err: print(f"Error: {err}", file=sys.stderr) + if args.show_trace: + print(file=sys.stderr) + traceback.print_exc() res = 1 # Generate python dependencies. @@ -314,6 +326,9 @@ def cairo_run(args): except (VmException, AssertionError) as exc: if args.debug_error: print(f"Got an error:\n{exc}") + if args.show_trace: + print(file=sys.stderr) + traceback.print_exc() ret_code = 1 else: raise exc @@ -368,10 +383,21 @@ def cairo_run(args): field_bytes = math.ceil(program.prime.bit_length() / 8) write_binary_memory(memory_file, runner.relocated_memory, field_bytes) + def select_builtin_ratios(runner): + """ + Temporary fucntion that returns the ratios of the bitwise builtin until actual desirable + dynamic ratios can be computed from the runner. + """ + return { + f"{builtin}_ratio": instance_def.ratio + for builtin, instance_def in LAYOUTS["bitwise"].builtins.items() + } + if args.air_public_input is not None: rc_min, rc_max = runner.get_perm_range_check_limits() write_air_public_input( layout=args.layout, + layout_params=select_builtin_ratios(runner) if args.layout == "dynamic" else None, public_input_file=args.air_public_input, memory=runner.relocated_memory, public_memory_addresses=runner.segments.get_public_memory_addresses( @@ -473,6 +499,7 @@ def write_air_public_input( public_input_file: IO[str], memory: MemoryDict, layout: str, + layout_params: Optional[Dict[str, int]], public_memory_addresses: List[Tuple[int, int]], memory_segment_addresses: Dict[str, MemorySegmentAddresses], trace: List[TraceEntry[int]], @@ -487,6 +514,7 @@ def write_air_public_input( assert isinstance(initial_pc, int) public_input = PublicInput( # type: ignore layout=layout, + layout_params=layout_params, rc_min=rc_min, rc_max=rc_max, n_steps=len(trace), diff --git a/src/starkware/cairo/lang/vm/cairo_runner.py b/src/starkware/cairo/lang/vm/cairo_runner.py index b3212cf6..f3c106e6 100644 --- a/src/starkware/cairo/lang/vm/cairo_runner.py +++ b/src/starkware/cairo/lang/vm/cairo_runner.py @@ -3,6 +3,7 @@ from starkware.cairo.lang.builtins.bitwise.bitwise_builtin_runner import BitwiseBuiltinRunner from starkware.cairo.lang.builtins.ec.ec_op_builtin_runner import EcOpBuiltinRunner from starkware.cairo.lang.builtins.hash.hash_builtin_runner import HashBuiltinRunner +from starkware.cairo.lang.builtins.keccak.keccak_builtin_runner import KeccakBuiltinRunner from starkware.cairo.lang.builtins.range_check.range_check_builtin_runner import ( RangeCheckBuiltinRunner, ) @@ -117,6 +118,9 @@ def __init__( ec_op=lambda name, included: EcOpBuiltinRunner( included=included, ec_op_builtin=instance.builtins["ec_op"] ), + keccak=lambda name, included: KeccakBuiltinRunner( + included=included, instance_def=instance.builtins["keccak"] + ), ) for name in instance.builtins: @@ -822,11 +826,16 @@ def get_runner_from_code( return get_main_runner(program=program, hint_locals={}, layout=layout) -def get_main_runner(program: Program, hint_locals: Dict[str, Any], layout: str): +def get_main_runner( + program: Program, + hint_locals: Dict[str, Any], + layout: str, + allow_missing_builtins: Optional[bool] = None, +): """ Runs a main-entrypoint program using Cairo runner and returns the runner. """ - runner = CairoRunner(program, layout=layout) + runner = CairoRunner(program, layout=layout, allow_missing_builtins=allow_missing_builtins) runner.initialize_segments() end = runner.initialize_main_entrypoint() runner.initialize_vm(hint_locals=hint_locals) diff --git a/src/starkware/cairo/lang/vm/cairo_runner_test.py b/src/starkware/cairo/lang/vm/cairo_runner_test.py index acd279fb..87e3967d 100644 --- a/src/starkware/cairo/lang/vm/cairo_runner_test.py +++ b/src/starkware/cairo/lang/vm/cairo_runner_test.py @@ -37,9 +37,9 @@ def test_run_until_label(): def test_run_past_end(): code = """\ -func main(): - ret -end +func main() { + ret; +} """ program = compile_cairo(code, PRIME) runner = CairoRunner(program, layout="plain") @@ -56,12 +56,12 @@ def test_bad_stop_ptr(): code = """\ %builtins output -func main(output_ptr : felt*) -> (output_ptr : felt*): - [ap] = 0; ap++ - [ap - 1] = [output_ptr] - [ap] = output_ptr + 3; ap++ # The correct return value is output_ptr + 1 - ret -end +func main(output_ptr: felt*) -> (output_ptr: felt*) { + [ap] = 0, ap++; + [ap - 1] = [output_ptr]; + [ap] = output_ptr + 3, ap++; // The correct return value is output_ptr + 1 + ret; +} """ with pytest.raises( AssertionError, match="Invalid stop pointer for output. Expected: 2:1, found: 2:3" @@ -82,9 +82,10 @@ def test_builtin_list(): AssertionError, match=re.escape( "The builtins specified by the %builtins directive must be subsequence of" - " ['output', 'pedersen', 'range_check', 'ecdsa', 'bitwise', 'ec_op']. " - "Got ['pedersen', 'output']." - ), + " ['output', 'pedersen'" + ) + + ".*" + + re.escape("]. Got ['pedersen', 'output']."), ): CairoRunner(program, layout="small") @@ -97,10 +98,10 @@ def test_builtin_list(): def test_missing_exit_scope(): code = """\ -func main(): +func main() { %{ vm_enter_scope() %} - ret -end + ret; +} """ with pytest.raises( VmExceptionBase, @@ -111,9 +112,9 @@ def test_missing_exit_scope(): def test_load_data_after_init(): code = """\ -func main(): - ret -end +func main() { + ret; +} """ runner = get_runner_from_code(code, layout="plain", prime=PRIME) addr = runner.segments.add() @@ -124,12 +125,12 @@ def test_load_data_after_init(): def test_small_memory_hole(): code = """\ -func main(): - [ap] = 0 - ap += 4 - [ap] = 0 - ret -end +func main() { + [ap] = 0; + ap += 4; + [ap] = 0; + ret; +} """ runner = get_runner_from_code(code, layout="plain", prime=PRIME) runner.check_memory_usage() @@ -137,12 +138,12 @@ def test_small_memory_hole(): def test_memory_hole_insufficient(): code = """\ -func main(): - [ap] = 0 - ap += 1000 - [ap] = 0 - ret -end +func main() { + [ap] = 0; + ap += 1000; + [ap] = 0; + ret; +} """ runner = get_runner_from_code(code, layout="plain", prime=PRIME) @@ -157,25 +158,25 @@ def test_memory_hole_insufficient(): def test_hint_memory_holes(): code_base_format = """\ -func main(): - [ap] = 0 +func main() {{ + [ap] = 0; %{{ memory[fp + 1] = segments.add_temp_segment() %}} - [[fp + 1]] = [ap] - ap += 7 + [[fp + 1]] = [ap]; + ap += 7; {} - ap += 1 - [ap] = 0 + ap += 1; + [ap] = 0; %{{ memory.add_relocation_rule(memory[fp + 1], fp + 3) %}} - ret -end + ret; +}} """ code_no_hint, code_untouched_hint, code_touched_hint = [ code_base_format.format(extra_code) - for extra_code in ["", "%{ memory[ap] = 7 %}", "%{ memory[ap] = 7 %}\n [ap]=[ap]"] + for extra_code in ["", "%{ memory[ap] = 7 %}", "%{ memory[ap] = 7 %}\n [ap]=[ap];"] ] runner_no_hint, runner_untouched_hint, runner_touched_hint = [ diff --git a/src/starkware/cairo/lang/vm/memory_dict_test.py b/src/starkware/cairo/lang/vm/memory_dict_test.py index 356d760b..b45c6a01 100644 --- a/src/starkware/cairo/lang/vm/memory_dict_test.py +++ b/src/starkware/cairo/lang/vm/memory_dict_test.py @@ -71,6 +71,8 @@ def test_memory_dict_check_element(): memory["not a number"] = 12 # type: ignore with pytest.raises(KeyError, match="must be nonnegative"): memory[-12] = 13 + with pytest.raises(ValueError, match="must be nonnegative"): + memory[12] = -13 with pytest.raises(ValueError, match="The offset of a relocatable value must be nonnegative"): memory[RelocatableValue(segment_index=10, offset=-2)] = 13 # A value may have a negative offset. diff --git a/src/starkware/cairo/lang/vm/memory_segments_test.py b/src/starkware/cairo/lang/vm/memory_segments_test.py index 73f8f29c..3c68edc7 100644 --- a/src/starkware/cairo/lang/vm/memory_segments_test.py +++ b/src/starkware/cairo/lang/vm/memory_segments_test.py @@ -122,15 +122,15 @@ def test_gen_typed_args(): """ code = """ -struct Inner: - member a : felt - member b : felt -end - -struct MyStruct: - member nested : Inner - member ptr : Inner* -end +struct Inner { + a: felt, + b: felt, +} + +struct MyStruct { + nested: Inner, + ptr: Inner*, +} """ program = compile_cairo(code=code, prime=DEFAULT_PRIME) diff --git a/src/starkware/cairo/lang/vm/output_builtin_runner_test.py b/src/starkware/cairo/lang/vm/output_builtin_runner_test.py index 3cf4172b..9303cf26 100644 --- a/src/starkware/cairo/lang/vm/output_builtin_runner_test.py +++ b/src/starkware/cairo/lang/vm/output_builtin_runner_test.py @@ -12,9 +12,9 @@ def runner_and_output_runner(): code = """ %builtins output -func main{output_ptr}(): - ret -end +func main{output_ptr}() { + ret; +} """ program = compile_cairo(code=[(code, "")], prime=DEFAULT_PRIME, add_start=True) runner = CairoRunner( diff --git a/src/starkware/cairo/lang/vm/reconstruct_traceback_test.py b/src/starkware/cairo/lang/vm/reconstruct_traceback_test.py index a2a2d041..12bfa944 100644 --- a/src/starkware/cairo/lang/vm/reconstruct_traceback_test.py +++ b/src/starkware/cairo/lang/vm/reconstruct_traceback_test.py @@ -9,21 +9,21 @@ def test_reconstruct_traceback(): code = """ - func bar(): - assert 0 = 1 - return () - end +func bar() { + assert 0 = 1; + return (); +} - func foo(): - bar() - return () - end +func foo() { + bar(); + return (); +} - func main(): - foo() - return () - end - """ +func main() { + foo(); + return (); +} +""" codes = [(code, "filename")] program_with_debug_info = compile_cairo(code=codes, prime=DEFAULT_PRIME, debug_info=True) program_without_debug_info = compile_cairo(code=codes, prime=DEFAULT_PRIME, debug_info=False) @@ -50,16 +50,16 @@ def test_reconstruct_traceback(): assert ( res == """\ -filename:3:9: Error at pc=0:2: - assert 0 = 1 - ^**********^ +filename:3:5: Error at pc=0:2: + assert 0 = 1; + ^***********^ An ASSERT_EQ instruction failed: 1 != 0. Cairo traceback (most recent call last): -filename:13:9 - foo() - ^***^ -filename:8:9 - bar() - ^***^\ +filename:13:5 + foo(); + ^***^ +filename:8:5 + bar(); + ^***^\ """ ) diff --git a/src/starkware/cairo/lang/vm/relocatable.py b/src/starkware/cairo/lang/vm/relocatable.py index 22cb1bf4..d5229404 100644 --- a/src/starkware/cairo/lang/vm/relocatable.py +++ b/src/starkware/cairo/lang/vm/relocatable.py @@ -1,6 +1,8 @@ import dataclasses from typing import Dict, Mapping, SupportsInt, Tuple, Union +from starkware.python.utils import Endianness + RELOCATABLE_OFFSET_LOWER_BOUND = -(2**63) RELOCATABLE_OFFSET_UPPER_BOUND = 2**63 @@ -68,7 +70,7 @@ def __str__(self): return f"{self.segment_index}:{self.offset}" @staticmethod - def to_bytes(value: "MaybeRelocatable", n_bytes: int, byte_order: str) -> bytes: + def to_bytes(value: "MaybeRelocatable", n_bytes: int, byte_order: Endianness) -> bytes: """ Serializes RelocatableValue as: 1bit | SEGMENT_BITS | OFFSET_BITS @@ -85,7 +87,7 @@ def to_bytes(value: "MaybeRelocatable", n_bytes: int, byte_order: str) -> bytes: return num.to_bytes(n_bytes, byte_order) @classmethod - def from_bytes(cls, data: bytes, byte_order: str) -> "MaybeRelocatable": + def from_bytes(cls, data: bytes, byte_order: Endianness) -> "MaybeRelocatable": n_bytes = len(data) num = int.from_bytes(data, byte_order) if num & (2 ** (8 * n_bytes - 1)): diff --git a/src/starkware/cairo/lang/vm/relocatable_fields_test.py b/src/starkware/cairo/lang/vm/relocatable_fields_test.py index da8f13b5..8dfec0ff 100644 --- a/src/starkware/cairo/lang/vm/relocatable_fields_test.py +++ b/src/starkware/cairo/lang/vm/relocatable_fields_test.py @@ -11,13 +11,18 @@ MaybeRelocatableDictField, MaybeRelocatableField, ) +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass @marshmallow_dataclass.dataclass(frozen=True) class DummyStruct(ValidatedMarshmallowDataclass): - val: MaybeRelocatable = field(metadata=dict(marshmallow_field=MaybeRelocatableField())) - dct: MaybeRelocatableDict = field(metadata=dict(marshmallow_field=MaybeRelocatableDictField())) + val: MaybeRelocatable = field( + metadata=additional_metadata(marshmallow_field=MaybeRelocatableField()) + ) + dct: MaybeRelocatableDict = field( + metadata=additional_metadata(marshmallow_field=MaybeRelocatableDictField()) + ) def test_relocatable_fields_serialize_deserialize(): diff --git a/src/starkware/cairo/lang/vm/security_test.py b/src/starkware/cairo/lang/vm/security_test.py index 03e753bc..83880605 100644 --- a/src/starkware/cairo/lang/vm/security_test.py +++ b/src/starkware/cairo/lang/vm/security_test.py @@ -17,8 +17,8 @@ def test_completeness(): run_code_in_runner( """ main: -[ap] = 1 -ret +[ap] = 1; +ret; """ ) ) @@ -28,8 +28,8 @@ def test_negative_address(): runner = run_code_in_runner( """ main: -[ap] = 0; ap++ -ret +[ap] = 0, ap++; +ret; """ ) # Access negative offset manually, so it is not taken modulo prime. @@ -44,12 +44,13 @@ def test_out_of_program_bounds(): run_code_in_runner( """ main: -call test -ret +call test; +ret; + test: -[ap] = [fp - 1] # pc. -[ap] = [[ap] + 4] # Write right after end of program. -ret +[ap] = [fp - 1]; // pc. +[ap] = [[ap] + 4]; // Write right after end of program. +ret; """ ) ) @@ -59,8 +60,8 @@ def test_pure_address_access(): runner = run_code_in_runner( """ main: -[fp - 1] = [fp - 1] # nop. -ret +[fp - 1] = [fp - 1]; // nop. +ret; """ ) # Access a pure address manually, because runner disallows it as well. @@ -77,13 +78,14 @@ def test_builtin_segment_access(): run_code_in_runner( """ %builtins pedersen + main: -[ap] = 1; ap++ -[ap - 1] = [[fp - 3] + 0] -[ap - 1] = [[fp - 3] + 1] -[ap] = [[fp - 3] + 2]; ap++ # Read hash result. -[ap] = [fp - 3] + 3; ap++ # Return pedersen_ptr. -ret +[ap] = 1, ap++; +[ap - 1] = [[fp - 3] + 0]; +[ap - 1] = [[fp - 3] + 1]; +[ap] = [[fp - 3] + 2], ap++; // Read hash result. +[ap] = [fp - 3] + 3, ap++; // Return pedersen_ptr. +ret; """, layout="small", ) @@ -93,10 +95,11 @@ def test_builtin_segment_access(): runner = run_code_in_runner( """ %builtins pedersen + main: -[fp - 1] = [[fp - 3] + 2] # Access only the result portion of the builtin. -[ap] = [fp - 3] + 3; ap++ # Return pedersen_ptr. -ret +[fp - 1] = [[fp - 3] + 2]; // Access only the result portion of the builtin. +[ap] = [fp - 3] + 3, ap++; // Return pedersen_ptr. +ret; """, layout="small", ) @@ -113,14 +116,14 @@ def test_builtin_segment_access(): run_code_in_runner( """ %builtins pedersen -func main{pedersen_ptr}(): - assert [pedersen_ptr] = 0 - assert [pedersen_ptr + 2] = 0 - assert [pedersen_ptr + 3] = 0 - assert [pedersen_ptr + 5] = 0 - let pedersen_ptr = pedersen_ptr + 6 - return () -end +func main{pedersen_ptr}() { + assert [pedersen_ptr] = 0; + assert [pedersen_ptr + 2] = 0; + assert [pedersen_ptr + 3] = 0; + assert [pedersen_ptr + 5] = 0; + let pedersen_ptr = pedersen_ptr + 6; + return (); +} """, layout="small", ) diff --git a/src/starkware/cairo/lang/vm/test.cairo b/src/starkware/cairo/lang/vm/test.cairo index 09dbe031..3f3a8da7 100644 --- a/src/starkware/cairo/lang/vm/test.cairo +++ b/src/starkware/cairo/lang/vm/test.cairo @@ -1,17 +1,17 @@ -[ap - 1] = [ap - 1] -[ap - 1] = [ap - 1] -[ap - 1] = [ap - 1] -[ap - 1] = [ap - 1] -[ap - 1] = [ap - 1] +[ap - 1] = [ap - 1]; +[ap - 1] = [ap - 1]; +[ap - 1] = [ap - 1]; +[ap - 1] = [ap - 1]; +[ap - 1] = [ap - 1]; label0: -[ap - 1] = [ap - 1] +[ap - 1] = [ap - 1]; label1: -[ap - 1] = [ap - 1] +[ap - 1] = [ap - 1]; label2: -[ap - 1] = [ap - 1] +[ap - 1] = [ap - 1]; __end__: -jmp rel 0 +jmp rel 0; diff --git a/src/starkware/cairo/lang/vm/trace_entry_test.py b/src/starkware/cairo/lang/vm/trace_entry_test.py index 37955330..0b10b791 100644 --- a/src/starkware/cairo/lang/vm/trace_entry_test.py +++ b/src/starkware/cairo/lang/vm/trace_entry_test.py @@ -3,7 +3,7 @@ def test_trace_entry_serialization(): # Test serialization of a TraceEntry (values taken from the instruction - # "[ap] = [ap - 1] + 2; ap++"). + # "[ap] = [ap - 1] + 2, ap++;"). entry = TraceEntry(ap=0x66, fp=0x64, pc=0xA) serialized = entry.serialize() assert len(serialized) == TraceEntry.serialization_size() diff --git a/src/starkware/cairo/lang/vm/virtual_machine_base.py b/src/starkware/cairo/lang/vm/virtual_machine_base.py index 99a6fe60..c6903a42 100644 --- a/src/starkware/cairo/lang/vm/virtual_machine_base.py +++ b/src/starkware/cairo/lang/vm/virtual_machine_base.py @@ -470,18 +470,28 @@ def verify_auto_deductions(self): Makes sure that all assigned memory cells are consistent with their auto deduction rules. """ for addr in self.validated_memory: - if not isinstance(addr, RelocatableValue): + self.verify_auto_deductions_for_addr(addr) + + def verify_auto_deductions_for_addr(self, addr: MaybeRelocatable): + """ + Makes sure that the value at the given address is consistent with the auto deduction rules. + """ + if not isinstance(addr, RelocatableValue): + return + + for rule, args in self.auto_deduction.get(addr.segment_index, []): + value = rule(self, addr, *args) + if value is None: continue - for rule, args in self.auto_deduction.get(addr.segment_index, []): - value = rule(self, addr, *args) - if value is None: - continue - - current = self.validated_memory[addr] - # If the values are not the same, try using check_eq to allow a subclass - # to override this result. - if current != value and not self.check_eq(current, value): - raise InconsistentAutoDeductionError(addr, current, value) + + current = self.validated_memory.get(addr) + if current is None: + continue + + # If the values are not the same, try using check_eq to allow a subclass + # to override this result. + if current != value and not self.check_eq(current, value): + raise InconsistentAutoDeductionError(addr, current, value) def end_run(self): self.verify_auto_deductions() diff --git a/src/starkware/cairo/lang/vm/vm_consts_test.py b/src/starkware/cairo/lang/vm/vm_consts_test.py index a9e37a8a..dbf5b16f 100644 --- a/src/starkware/cairo/lang/vm/vm_consts_test.py +++ b/src/starkware/cairo/lang/vm/vm_consts_test.py @@ -155,7 +155,7 @@ def test_references(): ), } - my_struct = TypeStruct(scope=scope("MyStruct"), is_fully_resolved=True) + my_struct = TypeStruct(scope=scope("MyStruct")) my_struct_star = TypePointer(pointee=my_struct) identifier_values = { scope("x.ref"): ReferenceDefinition( @@ -325,7 +325,7 @@ def test_reference_rebinding(): def test_reference_to_structs(): - t = TypeStruct(scope=scope("T"), is_fully_resolved=True) + t = TypeStruct(scope=scope("T")) t_star = TypePointer(pointee=t) identifier_values = { scope("ref"): ReferenceDefinition(full_name=scope("ref"), cairo_type=t, references=[]), diff --git a/src/starkware/cairo/lang/vm/vm_core.py b/src/starkware/cairo/lang/vm/vm_core.py index 8f24053f..28eef80f 100644 --- a/src/starkware/cairo/lang/vm/vm_core.py +++ b/src/starkware/cairo/lang/vm/vm_core.py @@ -456,6 +456,7 @@ def step(self): exec_locals["vm_enter_scope"] = self.enter_scope exec_locals["vm_exit_scope"] = self.exit_scope exec_locals.update(self.static_locals) + exec_locals["builtin_runners"] = self.builtin_runners exec_locals.update(self.builtin_runners) self.exec_hint(hint.compiled, exec_locals, hint_index=hint_index) @@ -465,6 +466,7 @@ def step(self): for name in self.builtin_runners: del exec_locals[name] + del exec_locals["builtin_runners"] for name in self.static_locals: del exec_locals[name] diff --git a/src/starkware/cairo/lang/vm/vm_test.py b/src/starkware/cairo/lang/vm/vm_test.py index c2b5f9bd..35863310 100644 --- a/src/starkware/cairo/lang/vm/vm_test.py +++ b/src/starkware/cairo/lang/vm/vm_test.py @@ -46,17 +46,17 @@ def test_memory_dict(): def test_simple(): code = """ - [ap] = [ap - 1] + 2; ap++ - [ap] = [ap - 1] * 3; ap++ - [ap] = 10; ap++ - # Skip two instructions. - jmp rel 6 - [ap] = [ap - 1] + 4; ap++ # Skipped. - [ap] = [ap - 1] + 5; ap++ # Skipped. - [ap] = [ap - 1] + 6; ap++ - jmp abs 12 - [ap] = [ap - 1] * 7; ap++ - """ +[ap] = [ap - 1] + 2, ap++; +[ap] = [ap - 1] * 3, ap++; +[ap] = 10, ap++; +// Skip two instructions. +jmp rel 6; +[ap] = [ap - 1] + 4, ap++; // Skipped. +[ap] = [ap - 1] + 5, ap++; // Skipped. +[ap] = [ap - 1] + 6, ap++; +jmp abs 12; +[ap] = [ap - 1] * 7, ap++; +""" vm = run_single(code, 9, pc=10, ap=102, extra_mem={101: 1}) @@ -70,16 +70,16 @@ def test_simple(): def test_jnz(): code = """ - [ap] = 7; ap++ +[ap] = 7, ap++; - loop: - jmp body if [ap - 1] != 0 - [ap] = 4; ap++ +loop: +jmp body if [ap - 1] != 0; +[ap] = 4, ap++; - body: - [ap] = [ap - 1] - 1; ap++ - jmp loop - """ +body: +[ap] = [ap - 1] - 1, ap++; +jmp loop; +""" vm = run_single(code, 100, ap=101) @@ -95,11 +95,12 @@ def test_jnz(): @pytest.mark.parametrize("offset", [0, -1]) def test_jnz_relocatables(offset: int): code = """ - jmp body if [ap - 1] != 0 - [ap] = 0; ap++ - body: - [ap] = 1; ap++ - """ +jmp body if [ap - 1] != 0; +[ap] = 0, ap++; + +body: +[ap] = 1, ap++; +""" relocatable_value = RelocatableValue(segment_index=5, offset=offset) error_message = ( None @@ -113,27 +114,27 @@ def test_jnz_relocatables(offset: int): def test_call_ret(): code = """ - [fp] = 1000; ap++ - call a - [ap] = [fp] + 1; ap++ - call a - [ap] = [fp] + 2; ap++ - - l_end: - jmp l_end - - a: - [fp] = 2000; ap++ - call b - [ap] = [fp] + 1; ap++ - call b - [ap] = [fp] + 2; ap++ - ret - - b: - [fp] = 3000; ap++ - ret - """ +[fp] = 1000, ap++; +call a; +[ap] = [fp] + 1, ap++; +call a; +[ap] = [fp] + 2, ap++; + +l_end: +jmp l_end; + +a: +[fp] = 2000, ap++; +call b; +[ap] = [fp] + 1, ap++; +call b; +[ap] = [fp] + 2, ap++; +ret; + +b: +[fp] = 3000, ap++; +ret; +""" vm = run_single(code, 30) @@ -158,10 +159,10 @@ def test_call_ret(): def test_addap(): code = """ - [ap] = 3; ap++ - ap += 30 - [ap] = 4 - """ +[ap] = 3, ap++; +ap += 30; +[ap] = 4; +""" vm = run_single(code, 3) @@ -172,10 +173,10 @@ def test_addap(): def test_access_op1_ap(): code = """ - [ap] = 3; ap++ - [ap] = [ap - 1] * [ap - 1]; ap++ - jmp abs [ap - 1] + [ap - 2] - """ +[ap] = 3, ap++; +[ap] = [ap - 1] * [ap - 1], ap++; +jmp abs [ap - 1] + [ap - 2]; +""" vm = run_single(code, 3, ap=200) @@ -186,49 +187,47 @@ def test_access_op1_ap(): def test_hints(): code = """ -const x = 1200 -const y = 8000 +const x = 1200; +const y = 8000; %{ -# Test math utils. -x = fdiv(3, 2) -assert fmul(x, 2) == 3 -assert (x * 2) % PRIME == 3 -assert fsub(0, 1) == PRIME - 1 + # Test math utils. + x = fdiv(3, 2) + assert fmul(x, 2) == 3 + assert (x * 2) % PRIME == 3 + assert fsub(0, 1) == PRIME - 1 %} -call foo +call foo; %{ -assert ids.x + ids.foo.y == 1234 -assert ids.y == 8000 -memory[fp + 1] = ids.z + assert ids.x + ids.foo.y == 1234 + assert ids.y == 8000 + memory[fp + 1] = ids.z %} -[fp] = [fp] - -func foo(): - const y = 34 - const z = 0 - let mem_at_fp_plus_one = [fp + 1] - %{ - abc = 123 - %} - [fp] = 2000 - %{ - v = memory[fp] // 2 - - ids.mem_at_fp_plus_one = v - memory[fp + 2] = ids.x + ids.y - - # Make sure abc is accessible. - assert abc == 123 - - # Try to use imports in list comprehension (check that exec() is called correctly). - import random - [random.randrange(10) for _ in range(10)] - %} - [fp] = [fp + 1] + [fp + 1] - ret -end +[fp] = [fp]; + +func foo() { + const y = 34; + const z = 0; + let mem_at_fp_plus_one = [fp + 1]; + %{ abc = 123 %} + [fp] = 2000; + %{ + v = memory[fp] // 2 + + ids.mem_at_fp_plus_one = v + memory[fp + 2] = ids.x + ids.y + + # Make sure abc is accessible. + assert abc == 123 + + # Try to use imports in list comprehension (check that exec() is called correctly). + import random + [random.randrange(10) for _ in range(10)] + %} + [fp] = [fp + 1] + [fp + 1]; + ret; +} """ vm = run_single(code, 4, ap=200) @@ -243,11 +242,11 @@ def test_hints(): def test_hint_between_references(): code = """ -let x = 1 +let x = 1; %{ assert ids.x == 1 %} -let x = 2 +let x = 2; %{ assert ids.x == 2 %} -ap += 0 +ap += 0; """ run_single(code=code, steps=1) @@ -255,7 +254,7 @@ def test_hint_between_references(): def test_nondet_hint_pointer(): code = """ %{ from starkware.cairo.lang.vm.relocatable import RelocatableValue %} -tempvar x : felt* = cast(nondet %{ RelocatableValue(12, 34) %}, felt*) + 3 +tempvar x: felt* = cast(nondet %{ RelocatableValue(12, 34) %}, felt*) + 3; """ vm = run_single(code=code, steps=2) assert vm.run_context.memory[101] == RelocatableValue(12, 37) @@ -263,7 +262,7 @@ def test_nondet_hint_pointer(): def test_hint_exception(): code = """ -# Some comment. +// Some comment. %{ x = 0 %} @@ -271,7 +270,7 @@ def test_hint_exception(): def f(): 0 / 0 # Raises exception. %} -[ap] = 0; ap++ +[ap] = 0, ap++; %{ y = 0 %} %{ @@ -279,7 +278,7 @@ def f(): f() %} -[ap] = 1; ap++ +[ap] = 1, ap++; """ # In this test we actually do write the code to a file, to allow the linecache module to fetch @@ -326,14 +325,14 @@ def f(): def test_hint_indentation_error(): code = """ -# Some comment. +// Some comment. %{ -def f(): - b = 1 - a = 1 # Wrong indentation. + def f(): + b = 1 + a = 1 # Wrong indentation. %} -[ap] = 0; ap++ +[ap] = 0, ap++; """ # In this test we actually do write the code to a file, to allow the linecache module to fetch @@ -363,10 +362,8 @@ def f(): Got an exception while compiling a hint. %{{ ^^ -Traceback (most recent call last): File "{cairo_file.name}", line 7 a = 1 # Wrong indentation. - ^ IndentationError: unexpected indent\ """ assert expected_error == str(excinfo.value) @@ -374,15 +371,15 @@ def f(): def test_hint_syntax_error(): code = """ -# Make sure the hint is not located at the start of the program. -[ap] = 1 +// Make sure the hint is not located at the start of the program. +[ap] = 1; %{ -def f(): - b = # Wrong syntax. - a = 1 + def f(): + b = # Wrong syntax. + a = 1 %} -[ap] = 0; ap++ +[ap] = 0, ap++; """ # In this test we actually do write the code to a file, to allow the linecache module to fetch @@ -412,10 +409,9 @@ def f(): Got an exception while compiling a hint. %{{ ^^ -Traceback (most recent call last): File "{cairo_file.name}", line 7 b = # Wrong syntax. - ^ + ^ SyntaxError: invalid syntax\ """ assert expected_error == str(excinfo.value) @@ -429,33 +425,33 @@ def test_hint_scopes(): assert outer_scope_var == 17 assert 'inner_scope_var' not in locals() %} -[ap] = 1; ap++ +[ap] = 1, ap++; %{ assert 'outer_scope_var' not in locals() assert inner_scope_var == 'scope 1' # create new inner_scope_var local in the inner scope. vm_enter_scope({'inner_scope_var': 'scope 2'}) %} -[ap] = 2; ap++ +[ap] = 2, ap++; %{ assert 'outer_scope_var' not in locals() assert inner_scope_var == 'scope 2' vm_exit_scope() %} -[ap] = 3; ap++ +[ap] = 3, ap++; %{ # Make sure that the we get the original inner_scope_var. assert inner_scope_var == 'scope 1' vm_exit_scope() %} -[ap] = 4; ap++ +[ap] = 4, ap++; %{ assert outer_scope_var == 17 # Try to access a variable in the scope we just exited. inner_scope_var %} -[ap] = 5; ap++ - """ +[ap] = 5, ap++; +""" vm = run_single(code, 4) with pytest.raises(VmException, match="name 'inner_scope_var' is not defined"): @@ -469,12 +465,10 @@ def test_skip_instruction_execution(): vm.run_context.pc += 2 vm.skip_instruction_execution = True %} -[ap] = [ap] + 1; ap++ # This intruction will not be executed. -%{ - x = 1 -%} -[ap] = 10; ap++ - """ +[ap] = [ap] + 1, ap++; // This intruction will not be executed. +%{ x = 1 %} +[ap] = 10, ap++; +""" program = compile_cairo(code, PRIME, debug_info=True) @@ -510,7 +504,7 @@ def test_skip_instruction_execution(): def test_auto_deduction_rules(): code = """ -[fp + 1] = [fp] + [ap] +[fp + 1] = [fp] + [ap]; """ program = compile_cairo(code=code, prime=PRIME, debug_info=True) @@ -551,9 +545,9 @@ def rule_ap_segment( def test_memory_validation_in_hints(): code = """ %{ memory[ap] = 0 %} -[ap] = [ap]; ap++ +[ap] = [ap], ap++; %{ memory[ap] = 0 %} -[ap] = [ap]; ap++ +[ap] = [ap], ap++; """ program = compile_cairo(code=code, prime=PRIME, debug_info=True) @@ -587,8 +581,8 @@ def fail_validation(memory, addr): def test_nonpure_mul(): code = """ - [ap] = [ap - 1] * 2; ap++ - """ +[ap] = [ap - 1] * 2, ap++; +""" with pytest.raises(VmException, match="Could not complete computation *"): run_single(code, 1, ap=102, extra_mem={101: RelocatableValue(1, 0)}) @@ -596,8 +590,8 @@ def test_nonpure_mul(): def test_nonpure_jmp_rel(): code = """ - jmp rel [ap - 1] - """ +jmp rel [ap - 1]; +""" with pytest.raises(VmException, match="Could not complete computation jmp rel"): run_single(code, 1, ap=102, extra_mem={101: RelocatableValue(1, 0)}) @@ -605,8 +599,8 @@ def test_nonpure_jmp_rel(): def test_jmp_segment(): code = """ - jmp abs [ap]; ap++ - """ +jmp abs [ap], ap++; +""" program = compile_cairo(code=code, prime=PRIME, debug_info=True) program_base_a = RelocatableValue(0, 10) @@ -638,19 +632,19 @@ def test_jmp_segment(): def test_simple_deductions(): code = """ - # 2 = 3 * ?. - [fp] = [fp - 1] * [ap]; ap++ - # 2 = ? * 3. - [fp] = [ap] * [fp - 1]; ap++ - # 2 = 3 + ?. - [fp] = [fp - 1] + [ap]; ap++ - # 2 = ? + 3. - [fp] = [ap] + [fp - 1]; ap++ - # 2 = ?. - [fp] = [ap]; ap++ - # ? = 2. - [ap] = [fp]; ap++ - """ +// 2 = 3 * ?. +[fp] = [fp - 1] * [ap], ap++; +// 2 = ? * 3. +[fp] = [ap] * [fp - 1], ap++; +// 2 = 3 + ?. +[fp] = [fp - 1] + [ap], ap++; +// 2 = ? + 3. +[fp] = [ap] + [fp - 1], ap++; +// 2 = ?. +[fp] = [ap], ap++; +// ? = 2. +[ap] = [fp], ap++; +""" vm = run_single(code, 6, ap=101, extra_mem={99: 3, 100: 2}) @@ -666,8 +660,8 @@ def test_simple_deductions(): def test_failing_assert_eq(): code = """ - [ap] = [ap + 1] + [ap + 2] - """ +[ap] = [ap + 1] + [ap + 2]; +""" with pytest.raises(VmException, match="An ASSERT_EQ instruction failed"): run_single(code, 1, extra_mem={100: 1, 101: 3, 102: 2}) @@ -675,33 +669,33 @@ def test_failing_assert_eq(): def test_call_unknown(): code = """ - call rel [ap] - """ +call rel [ap]; +""" with pytest.raises(VmException, match="Unknown value for memory cell at address 100"): run_single(code, 1) def test_invalid_instruction(): code = """ - dw -1 - """ +dw -1; +""" with pytest.raises(VmException) as exc_info: run_single(code, 1) assert str(exc_info.value) == ( """\ -:2:5: Error at pc=0:10: +:2:1: Error at pc=0:10: Unsupported instruction. - dw -1 - ^***^\ +dw -1; +^***^\ """ ) def test_call_wrong_operands(): code = """ - call rel 0 - """ +call rel 0; +""" with pytest.raises( VmException, match=r"Call failed to write return-pc \(inconsistent op0\): 0 != 0:12. " @@ -718,24 +712,24 @@ def test_call_wrong_operands(): def test_traceback(): code = """ - call main - - func foo(x): - %{ assert ids.x != 0 %} - return () - end - - func bar(x): - foo(x * x * x) - return () - end - - func main(): - bar(x=1) - bar(x=0) # This line will cause an error. - return () - end - """ +call main; + +func foo(x) { + %{ assert ids.x != 0 %} + return (); +} + +func bar(x) { + foo(x * x * x); + return (); +} + +func main() { + bar(x=1); + bar(x=0); // This line will cause an error. + return (); +} +""" with pytest.raises(VmException) as exc_info: run_single(code, 100, ap=101, extra_mem={99: 3, 100: 2}) @@ -743,20 +737,20 @@ def test_traceback(): assert ( str(exc_info.value) == """\ -:5:9: Error at pc=0:12: +:5:5: Error at pc=0:12: Got an exception while executing a hint. - %{ assert ids.x != 0 %} - ^*********************^ + %{ assert ids.x != 0 %} + ^*********************^ Cairo traceback (most recent call last): -:2:5: (pc=0:10) - call main - ^*******^ -:16:9: (pc=0:24) - bar(x=0) # This line will cause an error. - ^******^ -:10:9: (pc=0:15) - foo(x * x * x) - ^************^ +:2:1: (pc=0:10) +call main; +^*******^ +:16:5: (pc=0:24) + bar(x=0); // This line will cause an error. + ^******^ +:10:5: (pc=0:15) + foo(x * x * x); + ^************^ Traceback (most recent call last): File "", line 5, in @@ -767,42 +761,42 @@ def test_traceback(): def test_traceback_with_attr(): code = """ - call main - - func foo(x): - with_attr error_message("Error in foo (x={x})."): - with_attr error_message("Should not appear in trace."): - assert 0 = 0 - end - with_attr attr_name("Should not appear in trace (attr_name instead of error_message)."): - %{ assert ids.x != 1 %} - [ap] = 1; ap++ - end - end - return () - end - - func bar(x): - tempvar y = x + 2 - # y and x.y evaluation should fail (y is ap-based and x.y doesn't exist). - with_attr error_message("Error in bar (x={x}, y={y}, {x.y})."): - foo(y * y * y) - end - return () - end - - func main(): - with_attr error_message("Error in main."): - with_attr error_message("Running bar(x=1)."): - bar(x=1) - end - with_attr error_message("Running bar(x=0)."): - bar(x=-1) # This line will cause an error. - end - end - return () - end - """ +call main; + +func foo(x) { + with_attr error_message("Error in foo (x={x}).") { + with_attr error_message("Should not appear in trace.") { + assert 0 = 0; + } + with_attr attr_name("Should not appear in trace (attr_name instead of error_message).") { + %{ assert ids.x != 1 %} + [ap] = 1, ap++; + } + } + return (); +} + +func bar(x) { + tempvar y = x + 2; + // y and x.y evaluation should fail (y is ap-based and x.y doesn't exist). + with_attr error_message("Error in bar (x={x}, y={y}, {x.y}).") { + foo(y * y * y); + } + return (); +} + +func main() { + with_attr error_message("Error in main.") { + with_attr error_message("Running bar(x=1).") { + bar(x=1); + } + with_attr error_message("Running bar(x=0).") { + bar(x=-1); // This line will cause an error. + } + } + return (); +} +""" with pytest.raises(VmException) as exc_info: run_single(code, 100, pc=RelocatableValue(0, 10), ap=101, extra_mem={99: 3, 100: 2}) @@ -811,24 +805,24 @@ def test_traceback_with_attr(): str(exc_info.value) == """\ Error message: Error in foo (x=1). -:10:17: Error at pc=0:16: +:10:13: Error at pc=0:16: Got an exception while executing a hint. - %{ assert ids.x != 1 %} - ^*********************^ + %{ assert ids.x != 1 %} + ^*********************^ Cairo traceback (most recent call last): -:2:5: (pc=0:10) - call main - ^*******^ +:2:1: (pc=0:10) +call main; +^*******^ Error message: Running bar(x=0). Error message: Error in main. -:32:17: (pc=0:32) - bar(x=-1) # This line will cause an error. - ^*******^ +:32:13: (pc=0:32) + bar(x=-1); // This line will cause an error. + ^*******^ Error message: Error in bar (x=-1, y={y}, {x.y}). (Cannot evaluate ap-based or complex references: \ ['y', 'x.y']) -:21:13: (pc=0:23) - foo(y * y * y) - ^************^ +:21:9: (pc=0:23) + foo(y * y * y); + ^************^ Traceback (most recent call last): File "", line 10, in diff --git a/src/starkware/cairo/sharp/sharp_client_test.py b/src/starkware/cairo/sharp/sharp_client_test.py index 6eeba26d..986637cc 100644 --- a/src/starkware/cairo/sharp/sharp_client_test.py +++ b/src/starkware/cairo/sharp/sharp_client_test.py @@ -30,12 +30,10 @@ def test_compile_and_run(): cairo_program = """ %builtins output -func main(output_ptr : felt*) -> (output_ptr : felt*): - %{ - memory[ids.output_ptr] = program_input['x'] ** 2 - %} - return (output_ptr=output_ptr + 1) -end +func main(output_ptr: felt*) -> (output_ptr: felt*) { + %{ memory[ids.output_ptr] = program_input['x'] ** 2 %} + return (output_ptr=output_ptr + 1); +} """ program_input = {"x": 3} diff --git a/src/starkware/cairo/stark_verifier/CMakeLists.txt b/src/starkware/cairo/stark_verifier/CMakeLists.txt new file mode 100644 index 00000000..d433795a --- /dev/null +++ b/src/starkware/cairo/stark_verifier/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(air) +add_subdirectory(core) diff --git a/src/starkware/crypto/starkware/crypto/signature/__init__.py b/src/starkware/cairo/stark_verifier/__init__.py similarity index 100% rename from src/starkware/crypto/starkware/crypto/signature/__init__.py rename to src/starkware/cairo/stark_verifier/__init__.py diff --git a/src/starkware/cairo/stark_verifier/air/CMakeLists.txt b/src/starkware/cairo/stark_verifier/air/CMakeLists.txt new file mode 100644 index 00000000..6dc81d3d --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/CMakeLists.txt @@ -0,0 +1,45 @@ +add_subdirectory(layouts) + +python_lib(starkware_cairo_stark_verifier_air_lib + PREFIX starkware/cairo/stark_verifier/air + + FILES + config.cairo + diluted.cairo + layout.cairo + oods.cairo + params.cairo + parser.py + public_input.cairo + public_memory.cairo + traces.cairo + utils.py + + LIBS + starkware_cairo_stark_verifier_core_stark_lib +) + +full_python_test(starkware_cairo_stark_verifier_air_test + PREFIX starkware/cairo/stark_verifier/air + PYTHON ${PYTHON_COMMAND} + TESTED_MODULES starkware/cairo/stark_verifier/air + + FILES + example_proof.json + stark_test.py + + LIBS + cairo_common_lib + cairo_common_validate_utils_lib + cairo_compile_lib + cairo_function_runner_lib + starkware_cairo_stark_verifier_air_bitwise_lib + starkware_cairo_stark_verifier_air_dex_lib + starkware_cairo_stark_verifier_air_perpetual_with_bitwise_lib + starkware_cairo_stark_verifier_air_recursive_lib + starkware_cairo_stark_verifier_air_lib + starkware_cairo_stark_verifier_core_stark_lib + starkware_python_utils_lib + pip_eth_hash + pip_pytest +) diff --git a/src/starkware/cairo/stark_verifier/air/__init__.py b/src/starkware/cairo/stark_verifier/air/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/starkware/cairo/stark_verifier/air/config.cairo b/src/starkware/cairo/stark_verifier/air/config.cairo new file mode 100644 index 00000000..ee46fae7 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/config.cairo @@ -0,0 +1,25 @@ +from starkware.cairo.common.math import assert_in_range +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.core.table_commitment import TableCommitmentConfig + +const MAX_N_COLUMNS = 128; + +// Configuration for the Traces component. +struct TracesConfig { + original: TableCommitmentConfig*, + interaction: TableCommitmentConfig*, +} + +// Validates the configuration of the traces. +// log_eval_domain_size - Log2 of the evaluation domain size. +func traces_config_validate{range_check_ptr}( + air: AirWithLayout*, config: TracesConfig*, log_eval_domain_size: felt +) { + assert_in_range(config.original.n_columns, 1, MAX_N_COLUMNS + 1); + assert_in_range(config.interaction.n_columns, 1, MAX_N_COLUMNS + 1); + assert config.original.n_columns = air.layout.n_original_columns; + assert config.interaction.n_columns = air.layout.n_interaction_columns; + assert config.original.vector.height = log_eval_domain_size; + assert config.interaction.vector.height = log_eval_domain_size; + return (); +} diff --git a/src/starkware/cairo/stark_verifier/air/diluted.cairo b/src/starkware/cairo/stark_verifier/air/diluted.cairo new file mode 100644 index 00000000..08b87628 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/diluted.cairo @@ -0,0 +1,59 @@ +from starkware.cairo.common.pow import pow + +// Computes the correct value for the diluted component product. +func get_diluted_prod{range_check_ptr}(n_bits: felt, spacing: felt, z: felt, alpha: felt) -> ( + res: felt +) { + alloc_locals; + let (diff_multiplier) = pow(2, spacing); + let (p, q) = get_diluted_prod_inner( + n_bits=n_bits - 1, + x=1, + diff_x=diff_multiplier - 2, + diff_multiplier=diff_multiplier, + z=z, + p=1 + z, + q=1, + ); + return (res=p + q * alpha); +} + +// The cumulative value is defined using the next recursive formula: +// r_1 = 1, r_{j+1} = r_j * (1 + z * u_j) + alpha * u_j^2 +// where u_j = Dilute(j, spacing, n_bits) - Dilute(j-1, spacing, n_bits) +// and we want to compute the final value r_{2^n_bits}. +// Note that u_j depends only on the number of trailing zeros in the binary representation of j. +// Specifically, u_{(1+2k)*2^i} = u_{2^i} = u_{2^{i-1}} + 2^{i*spacing} - 2^{(i-1)*spacing + 1}. +// +// The recursive formula can be reduced to a nonrecursive form: +// r_j = prod_{n=1..j-1}(1+z*u_n) + alpha*sum_{n=1..j-1}(u_n^2 * prod_{m=n+1..j-1}(1+z*u_m)) +// +// We rewrite this equation to generate a recursive formula that converges in log(j) steps: +// Denote: +// p_i = prod_{n=1..2^i-1}(1+z*u_n) +// q_i = sum_{n=1..2^i-1}(u_n^2 * prod_{m=n+1..2^i-1}(1+z*u_m)) +// x_i = u_{2^i}. +// +// Clearly +// r_{2^i} = p_i + alpha * q_i. +// Moreover, +// p_i = p_{i-1} * (1 + z * x_{i-1}) * p_{i-1} +// q_i = q_{i-1} * (1 + z * x_{i-1}) * p_{i-1} + x_{i-1}^2 * p_{i-1} + q_{i-1} +// +// Now we can compute p_{n_bits} and q_{n_bits} in just n_bits recursive steps and we are done. +func get_diluted_prod_inner( + n_bits: felt, x: felt, diff_x: felt, diff_multiplier: felt, z: felt, p: felt, q: felt +) -> (p: felt, q: felt) { + if (n_bits == 0) { + return (p=p, q=q); + } + tempvar x = x + diff_x; + let diff_x = diff_x * diff_multiplier; + tempvar x_p = x * p; + tempvar y = p + z * x_p; + let q = q * y + x * x_p + q; + let p = p * y; + return get_diluted_prod_inner( + n_bits=n_bits - 1, x=x, diff_x=diff_x, diff_multiplier=diff_multiplier, z=z, p=p, q=q + ); +} diff --git a/src/starkware/cairo/stark_verifier/air/example_proof.json b/src/starkware/cairo/stark_verifier/air/example_proof.json new file mode 100644 index 00000000..034a51a5 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/example_proof.json @@ -0,0 +1,4623 @@ +{ + "annotations": [ + "title cpu air Proof Protocol", + "", + "P->V[0:32]: /cpu air/STARK/Original/Commit on Trace: Commitment: Hash(0x903d315c75757826b2dbd765a42c10a5b5ce34c000000000000000000000000)", + "V->P: /cpu air/STARK/Interaction: Interaction element #0: Field Element(0x37ed7db5ce4be80bd33eba73d5258f7b205bab82c9b7878ec88194787624762)", + "V->P: /cpu air/STARK/Interaction: Interaction element #1: Field Element(0x454984e0cd70c0b53ce046292600f2d20d20bcaa3c2847f32c0701fe62aa6c8)", + "V->P: /cpu air/STARK/Interaction: Interaction element #2: Field Element(0x243f2636a6915a571b0da5fd09febef895c550a36f8a55570d3ac670f244fa7)", + "V->P: /cpu air/STARK/Interaction: Interaction element #3: Field Element(0x3b44236979c5ce52dbd4b3259af40c1ccb76e4bf1e8ba581ccaa1b6ecd4d24d)", + "V->P: /cpu air/STARK/Interaction: Interaction element #4: Field Element(0x6abd1b4f1e5e12a29f62b5ceb1c9aef8f7a8dc04b848434210bf07b055f5870)", + "V->P: /cpu air/STARK/Interaction: Interaction element #5: Field Element(0x37a6d6bcc2e0116ff86c715c2ad9bdaa64f0aa06facea2fb54002e07db07711)", + "P->V[32:64]: /cpu air/STARK/Interaction/Commit on Trace: Commitment: Hash(0x72600ef7d5d17d4f5ac2c742cb35ed7737ce6d1f000000000000000000000000)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 0: Field Element(0x78ee8a8bbeef62feb9124b75dda48de71cc5b85762e7e934339116389e935bf)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 1: Field Element(0x76944ac0c6c327e3a39e777417b5a479839177f0c694cfc69850156af414789)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 2: Field Element(0x6ecbc347f1a1d02c1b5387d5d1fb1489ae369ced8d7c55ac44e90aedfa0bb7e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 3: Field Element(0x36493c3eb9ce44a5a7a1c40041ce69d6c09d98885571d84ae1949ea45939a48)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 4: Field Element(0x546712f2a5555c3d4b9b51a327585182f6806ebb13bc5f76b8e22f8974cc1b2)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 5: Field Element(0x9cc71c62a2f32e1b311f1b28028a937c4d148ec580df80498a2a306ba22eb6)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 6: Field Element(0x484657b3d5c601abbdcc2019ca2f43256a3282ccfec5edce4d65d02b66ce278)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 7: Field Element(0x2bfba5ca3cd6cc4db98f77c35c257f1f30a3b6fed356e394bbf84323869d62d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 8: Field Element(0x476d389fc68fba05d5f44e44db74e8712072a24cf2e3967a8bfff31226699c1)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 9: Field Element(0x6e3f0d3af9f2bb1abe4b58fdc64a696bd26a78c6af3981059e1f8793cc7b6c7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 10: Field Element(0x15fe0151c924ff51a35b432d1b3501975a57794d4f808ae2490f15a153a9899)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 11: Field Element(0x52f8877ea0bb45c558ea6d914c8f970188599cfa65d0a080a0de98971be8197)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 12: Field Element(0x57c212e3ac53a0814becf2cf593b3550e7c910cddc7874cfd00f5e6c2e832f4)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 13: Field Element(0x36378caf437cf7235234f5a1f6ea9fbb74a9a12e084f7d2a28754a534f6c1f0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 14: Field Element(0x79f9794e9bbb5f0c0fce8ebc20b1665c2eccb8dbabdee7d6efa2cd4339ad467)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 15: Field Element(0xa6618ac04b0ed1f8fffee61ccac90ee560930624f652b8333ecd0ac1f783ad)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 16: Field Element(0x45a0eb5d026e114be13b670aaa449fc08d6bb8ab49c79c30011dd7f61e1286e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 17: Field Element(0x2c3b4e1d6efca4df705cff2a1d7fb8e7ef3d79aac4199a41e814714f7594e2c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 18: Field Element(0x71c4dc8b9fa7774909b3effb1248a1f3c05b0a25846852c8f896762e0067827)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 19: Field Element(0x72fce9a81486f964805185d9865db810b9d3fd5a2d2e3bfc302e94199374fba)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 20: Field Element(0x5effcd7d494cdb8c3f120a12c3e587e8adb49ddfcb7961baa994459c6e69dba)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 21: Field Element(0x7501327796b03de253eb895e80eefca3187c548826bb38eca24764c6564974e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 22: Field Element(0x627495ba48b17c903dcf22f91d621b616961795970f02f75531a4a89afd6558)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 23: Field Element(0x352c990778d373ade0f3355bd9d8a3d7e2cbdcc7ef9b28f89774bc58906f4f5)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 24: Field Element(0x4e08e46c7139727c4b0ba9762dab75c0a688cdccf673e9a2dec859be783b1fb)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 25: Field Element(0x4abe59da03795aa87d9b8531fe1733dde2d2bd53dd477f5944d80932ce06271)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 26: Field Element(0x2926224888aee6003a3a5db7908784417daf93f70c2311bf92e5e1948588854)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 27: Field Element(0x3edb8fef8b2d06c1c064a5dd08a6f9c9c5d06ccc569e6527cf24fbbaed17343)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 28: Field Element(0x353f53842811e8795f93120a733c78c7122e636ad2aa3ff30b8af1fbc91219a)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 29: Field Element(0x3000c4f57ea5720a0025ec68321462c4d986a443ff276638d8ff2f44b87c1f4)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 30: Field Element(0x87ace93aad6392848449f26596641da52d708289f9bf1dbbd71489a2b7e2bb)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 31: Field Element(0x1df328e25cbb72030a99bfd84d776da2ee63aeaf1d8d43c93e48a28d6c4a7f4)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 32: Field Element(0x3eae50ac36cc62c6625e280d43c87ba247e4135c8c3d9efa80f2f59c077af44)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 33: Field Element(0x76072ce6c3bd1025463fc0607ba25be447154f8e42e0ec297e2c75b8e58b2e7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 34: Field Element(0x7e1bfa93be8ec352cf7e9369fcc419eb6cf744969932417ccf7b671970ae9cd)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 35: Field Element(0x593157c06f29825e0b0d081116dc815982880929052facef50344c764c62f4)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 36: Field Element(0x6cc98a6ec872a7af53f315cc14798d0a9e0c0315c9ad0a2d848a6d170fb72b)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 37: Field Element(0x119b24159c4a75975b16c7ebeaca36802fe5f6500ca9c25d681b23649cdfb3d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 38: Field Element(0x27594f1223bfa03fb54b09a7a4efdb8f1e8b416d993a346c1562a2b65af0c8e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 39: Field Element(0x1e929eed1259180703a70e3fa5f3531f3a3e62e7269d02334393d824faaa33f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 40: Field Element(0x61d05c6c814f6281aa2311ebebb8999ca700cdf0b3c664072570f4f05aa3368)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 41: Field Element(0x148c5b70bfd8309f15400ac86d7326c80b2d36dddf10ffcfddb1e66d1162158)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 42: Field Element(0x57f0b9485a22433bbffa78aebff3e71b1ee7f2aee240393de2e3c5bd9cac0a6)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 43: Field Element(0x7fbaf9e37812515ba8dbd991d455e04c2931ff59b7f741ad732daca35f4c728)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 44: Field Element(0x4687d4b0dc1ea9165ef7380160734482e856ff94318ace1c0c1ac21a77384c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 45: Field Element(0x45d4760e36baf44dae3763b9c3c6272b6819bb28d1508f8aed1b64456d91d06)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 46: Field Element(0x19da73e5986521fd0d177b91d3fbc55e4471d32f8add0eaa1a2f8982907b986)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 47: Field Element(0x61360a4548515c14af248ef172369b46d715b1e1ed7a1de0fb77b46ce54afa7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 48: Field Element(0x2a78dfc75e418208012d44c08beba9510a1989072b2cf0fa9203b166ecde86f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 49: Field Element(0x4602e14721e12cec337e5c0e9a6636a1eaa65fc3d09d648cb6e600fd6ff881b)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 50: Field Element(0x7c62a70881f616d1037a8ab2f162b718608179d07c9bb8ae2e26da50e2e25b4)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 51: Field Element(0x7f9fe75c8773821d9832993eceae8e4cada8fc2df93cf621de6341794fe0c9d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 52: Field Element(0x68d71c745b8c3c10622065d8ea2394dea48670c8cc9d98ff7c8be8fb2afcbdb)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 53: Field Element(0x7fc5b4c4f0f1b560e9c6811644d65272e9b9fc25fa30f28c1f37995b844d6d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 54: Field Element(0x77ebe7daff7939a9b68829891da9095041855f1b39c53e84b766c152815ee18)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 55: Field Element(0x673c1f085da7e9ccf9c15bdf58bc0d55c68c3c51ff577649e0951c514f2804b)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 56: Field Element(0x39324f9ce8bdafa051662ea03f44c364f4b229be3a1d4f6e98209d11e65417d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 57: Field Element(0x513478bb6499828d8e2f9595e2e212749ca3076b6fa53cbc27df8735461d24c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 58: Field Element(0x3ac40f30243f9bfc8937d0bcccca2915c6a5fb64973e4a23f84d60729e518bb)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 59: Field Element(0x70e3a55a4f1fa7932d6221e2afb77ac7a7c77cab9e5237b65623d6b5b84155f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 60: Field Element(0x6845c45ae5351a2dfea3e3cf2a352a153f1e66f477931089a74bc4e2fa090a4)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 61: Field Element(0x7a5b65307480687a9a8b24f5f8c1d4fd93f17fa5f96f7e238908ee9756d2d86)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 62: Field Element(0x4aaa0523a4aaacc57824579c1b7c7c96a0799af51ded0e196582241454385f7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 63: Field Element(0xf30aadd396ead05c316e90b9114cd661b5ab53e0bbb1480adcb938844e7b6d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 64: Field Element(0x1fad13cdcab9a66f5b0667304a9f33fc396c10e68b82cf13b8d717c0f2cb7bc)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 65: Field Element(0x1416ec92b8a87df49d04ff25fd1d3f44202b3bf64b08b02b0ca6d931dd1ac16)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 66: Field Element(0x46e6631e9f55f048571d83ab25aa4d6529b4bef634cfc97c284e8b5847f1182)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 67: Field Element(0x6dcab260a17977445d45a24032b3ac5c5ac983f1d21d5eef1bcc7b7442967a3)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 68: Field Element(0x760084d01a62e5ccb850f913f6cbfcf30f89090890da6e3313bcb66183d656f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 69: Field Element(0xacec750cce5253284d313548f709cb2675bc02abff9dd64f822e6638f327ff)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 70: Field Element(0xd227ad99691dcf05f00e4cd458417ebb4473d6a204e717d514fd62deaacbcd)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 71: Field Element(0x540fec1e275de476b86db725695efef986ca24ae30430d09919d5b6eac584e8)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 72: Field Element(0x23a47b09c3c790efd76ce69b2c284bb6234ae6b2c793012bb9a9421e36702b1)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 73: Field Element(0x4f2ef6ea9e69c2dab5cec53fedb66c6a2fd8795e9420f0ee1c3a139b3c3ae04)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 74: Field Element(0x30f07faaa15c89efd98f91726b214b9f9c6ed19196a1cd8058344a651f55398)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 75: Field Element(0x3d074fec5c96b0fc7c953312e3be9a2b696da1dfdfe78c13a7f2da5b9f020d0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 76: Field Element(0x61ab1a41707c72438428a9b54fa9b40efd2db357f42fff651b999e152d98c8c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 77: Field Element(0x58b2d7ff6f3e81969c0082cf153ef7998451823dcecc9209766d00ca984f640)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 78: Field Element(0x354b0a79640d5a6606039fbb4c08ac44c157c6e818553224abf18c5f7ac9533)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 79: Field Element(0x6f0f5e5ac6d6d6603586e9cd0372f604b2a5f331bafec5e92480cfd162fcc1c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 80: Field Element(0x170d778b5c94eaa2b03b9ff08b0f6a46168290634b44d2173defdfa564d4f2e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 81: Field Element(0x75fb2762f536f79ba2b1b4aa86070ed7d5f81cd1e81ab3e70a8f50d5d5ea6a0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 82: Field Element(0x2c37ef1927eb7c54b90399f968d582d8ed9ccebdc00e3619aca47d85754bc0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 83: Field Element(0x31bd0923fd53e37ab9819d98b1bb4cac9aeb5e991aa7c8bda1e44fcc9b2e429)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 84: Field Element(0x60805d24bc190f0cb8c2240889de1e46d7da6c6c4a83a0163dc2420ee56a9ac)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 85: Field Element(0x57aec75852f84790f2d53163f2b09e3682073c17015b8ac9503e76a597a83d3)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 86: Field Element(0x343c3534ce7b7854e3e5a1ecc49da34b30464de456e6d91787f4b8cedc5b190)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 87: Field Element(0x42ab3bee1c209ca9d235eb7fa9942c0944bcda741221b9708f595ba830b26ff)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 88: Field Element(0x892ff3329ba944d943fc9945e46ae5a4d598a4a48339ea7b1ce740ed26a86f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 89: Field Element(0x7f498aa2c7b8cafd162f39c409952a1b7cb09dac040a1893bd44d47cd86104c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 90: Field Element(0x3f8d70136e2474c9022c3002d5cd287f869da274fba2c989d16497748fb1a7f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 91: Field Element(0x40d04136a22aa1a147c69b9d4eafb00b3137b2d96aa4cbcdaeb6717e338761d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 92: Field Element(0x65dd7b9e1b296d9744933617f31b52d79c1b292e8547b10097aad0dc32695d6)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 93: Field Element(0x2a89a0b64021cc56da92091b74e4618bd8c5342ef9d6b41c2490abfc8ef6a23)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 94: Field Element(0x4826ec53dc0bd37f4c778f94f9b4d60833580c95e896bfabc420b4fe4548012)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 95: Field Element(0xe92ffc1efed1534771372edffea72c047957fb6276ac792a42c6b2791a4c10)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 96: Field Element(0x297e62f394892ee729c3a02180d95fd14b3bd7e6af6248967ee0cae416cecde)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 97: Field Element(0x5d90f33aae8c1e2b6dd2dbdbb00c74eefe5f100076b337e2c9bf2dd968592ec)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 98: Field Element(0x7d8131b10504b33f29f293b9b93c179b2c1ef598279d2b52854e0050f372a29)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 99: Field Element(0x360f3a810ebd5e2ace80abc04a40c43ed04129917dea5a8cd97bb8d2861d275)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 100: Field Element(0x31b6a347b8daa3727e10ea877235213abd001a7123b302db921afc015ca6d6e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 101: Field Element(0x51a66d90ececf3f12240e3edd9b7e039d103a6b0413daf80635f68f800d5fb1)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 102: Field Element(0xb54cb1b614dcca17e7d1f97a65a6b46c5f665d81782dc3d3f67bcc083906b5)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 103: Field Element(0x73ad1937cd57aaa5c78a87e65404cbfa0e35e0052dc71aa8596f5ba382b8191)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 104: Field Element(0x6a599a4439e8f4a9a7ba4c224e79d696234ef55506a8d6573e2f2b2e871bd1)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 105: Field Element(0x44a89730811862df9c36d15c4e8ad7c7f5346b815f932e026b77c964dad23cf)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 106: Field Element(0x62a107efbafedf75c11573a0d00b7e523265717bce7e35c626ecec563602097)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 107: Field Element(0x331b620485e79eba48c52419dd5fee5833e0a5f7a45731c30a55bf01456333c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 108: Field Element(0x59e137e8453fa64f513e4ac3657ba659ac107c2e3c5a4ca6a4ad3224d6934c7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 109: Field Element(0x52de02f8a8e6041f53047cf88cca9f79c420825113d31492954d1a833202b2)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 110: Field Element(0x1ee1d37709368654e3759746723be32bda4ff34e332520086d5b7a952811bf)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 111: Field Element(0x6f2f9d35ce6120e84e59b4781b7f49472bf7199857aee41099605af24cd1980)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 112: Field Element(0x52baaf7dac393296c0ca103501ec9d977123bf42d3a9a15ca449117e1695b7f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 113: Field Element(0x5c99bee33c9b527fd6783a9971408f4051ecebf42fee8f8ab4293c8fb63b112)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 114: Field Element(0x6da5275fea3edb8911f9cb0722208813ea6541976f88d6e81817746117e2614)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 115: Field Element(0x466895a6731a88c49f967f17405adc49d3904d7e6b820bdfe19869daee3e812)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 116: Field Element(0x6896ed0475e800f77f7fccafe9c39e4aba1630fab72e3e0c0d611b74f23657d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 117: Field Element(0x3bfe64b8823131560ce5ffab0df3811bb25af1988574429507a1faad74293e3)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 118: Field Element(0x7c604b619bcff74d7ad07bab0ef94326bbf1b7b0f25bdc80d9fa0bf253d017d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 119: Field Element(0x69f2fff0fbdf6dc34a5327f27be8fbcbf72e1feec14168e74deba54ab2afeb8)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 120: Field Element(0x1dccc7f93b2fa7207613da3b144b27d727c594316775748d93a2c01cb9daf12)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 121: Field Element(0x4225a14cec92a054708c8db4a97ea59bd7a0ade9bbc6d85c3fbfc0efb25e940)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 122: Field Element(0x11d2189cd4d60b4745f460a8d0bc5f98a72ee67f029765826fc4468bf6fde8d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 123: Field Element(0x403a8ffa6348c8d4b5ec89cc968c22d8bd0991fc64edca0f989b81f9f1fbedc)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 124: Field Element(0x717e50f641d854b31bfa601433a79b25a71a275e4145c75405bef12b4e046ce)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 125: Field Element(0x4711a1ed8f75567ba766d5d3d431d2a403af2c1672f3ee97b4633c79c84f523)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 126: Field Element(0x63584771217deb63d85f5f23d8d87186f6f0a6264c743377b92d57e6130dbec)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 127: Field Element(0x177753349545bb887786530ea2a2e2566b4e7c74717f7962f3ae8c1dcb26a48)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 128: Field Element(0x668f96b307c6dbe620c2fcdd35d6269f9da1ae0a153f48cba69356a9cec3e5)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 129: Field Element(0x6774b8075468f0fd9f55216d704902d03414ddbb7bb9165226e2607478991ce)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 130: Field Element(0x5dbb7f843b7abae8cc60ad6feeb7feb5e0351dd7c65b7207a69e035efa7dbc2)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 131: Field Element(0x26f211c0a943a67a1227c4e6226e7b1e05395b45aa3a171564a55fb5aacb8e5)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 132: Field Element(0x454bc508c8da4cee5ba5a87cbaede8b8ac13a5ed2c694f3757d73ca335abc6a)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 133: Field Element(0x5b8f6a571a3a501faa3373b2253fbcf95237c8b7b2f27049f79d82874727f67)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 134: Field Element(0x3d2b8fdb52fbee04bff62b2cac10b4c67c02e95ceac107dcf0a20dd9b9e2023)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 135: Field Element(0xbebe8cb3e018ce95bec360f90295fc3777b46c8c5a93f8e7473a8ac88b0ba7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 136: Field Element(0x280dc2818a1c6083653dfdf005ffe9ac19a9ef1aaf843393cb12fe4676fbbe6)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 137: Field Element(0x72d0da34497fcb809c7795f9d795ed92a54d57891718fc37f28890c54517cd2)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 138: Field Element(0x3b547bbd2e5d20fdcf76231c2abede88186eab6d37790f048f09de5fd7ed9d3)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 139: Field Element(0xeb4d8a1473e426a26cd1729bf78eef7efd78525b7734e389b194ac89918d9b)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 140: Field Element(0x22b9c63e29ba99307f8cf3ea6409bde8beca6cecf39b7644076538454751e5a)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 141: Field Element(0xa3cc539f391a59b1cd564ccbf3ab7eec6dcbf85ec946eea2b657eddd5635e0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 142: Field Element(0x1096d11be66bd3cc648aad4f6a64afce41439ac2af98bdc575015e319964f66)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 143: Field Element(0x314524ec0af99eb743c8d10c7b11f3e5f4685aba7b02c4f4155085c2e451c81)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 144: Field Element(0x386ff3b24b03f6f37067b0d2d6a16a4c83cddfe97512eadb503193dac8a4464)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 145: Field Element(0x2e2a9cc93f49bdbc96981f48a55d109a84167ceaed9eeb2adaddc6de0ea8b18)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 146: Field Element(0x6443ae2baeac167ccac03793f2267ca013a7a836455313c8b3ecbdf8e35a32c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 147: Field Element(0x36ce3f59896c9590a66386cc9fd57e6a38560b1efecb0422567b60f117741b7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 148: Field Element(0x78f658c1cef2a0b3f24b8327751590e6edb3965d255f48761b427deba569a08)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 149: Field Element(0x32ef600f2c5cd2f291c790b54d25764f0d7eda189977b4520bca26eb22121b5)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 150: Field Element(0x63fae3d40badbcf65a514d8f714fbae6640005b59da935eb87c9a3c57e872a0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 151: Field Element(0x73db421da56303020949646348a0ddef2fee76657fa2daae8428336fc7ddcb2)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 152: Field Element(0x3fd4c99a15782241512db7b0de3c348050bb2c861d2cfab71829562d8b303f0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 153: Field Element(0x1ec4d546d5fb2106515b3702f325bb10b85d8f5ddf1559cef770164cc4ebd35)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 154: Field Element(0x4cbfc9d0f6bf1ee3b578d16c47df5d43bda53319f3a56c7cdedd566b6c42053)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 155: Field Element(0x3ddb02e330dcf17cca841b3ad802e4a334035c10dffc4ca5e6dbb88c043302)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 156: Field Element(0x7e8e343f3f8be81e665d203c393bd0c3509339a11206ba518f8ec0aac04d4a3)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 157: Field Element(0x1b578c249e7eca7ea871c6b60ee504b47ad666c256e4901435f3365b2b7dbd7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 158: Field Element(0x16e9c92919108e7553398cb30a63ff977a065c959e457a5d4afef80d1a18eeb)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 159: Field Element(0x65214dc02b7b111ac6e43dffd887d8684ae0c31fc85a3da05c93ff5dabd71ba)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 160: Field Element(0x2a70dbd3f81f0e12229a3c41b736c5aef4fa13ee401bf0f5b2fbda9d9dbdba7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 161: Field Element(0x7baa24ade89af6f7e732959d2233f796d81c24422e53a3feb2586295bf673a5)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 162: Field Element(0x6ec2eb9c5f61d9d32eb9e425d76e115f4637ef5c64d14aa1f12f7ae3eab67c7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 163: Field Element(0x17b278a5c883aa666c62860e9a3b7583846baf248035fd2277579e0f9e33d1f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 164: Field Element(0x781418386f90bd6b2539afb693c86465140382b4f28c6d7a28328ce6205282e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 165: Field Element(0x670b4f7075188464fe23ba1780324cfd917a5c6f2ab462fb13e784d4bb7919)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 166: Field Element(0x179287c7130c706e1bd98738ee507eff3a25350c36165c5df1abbf28e048256)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 167: Field Element(0x4a21af02509c163456e690d60ec46c4ea0f9faae2244d6b62f8f0e70f4017d1)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 168: Field Element(0x4da079a2087cb5696e0175a7da0c5b73410b3ea9533d71b70e8e9d16497663a)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 169: Field Element(0x49f32dc3edf2e7c89e0ebd7de79a6a62ae08585c7a3b3710dd74f8f2392e853)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 170: Field Element(0x5c5a6761b4ab96381ba8755dd665246848f99c67d3c55cf1d093c0003debdf1)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 171: Field Element(0x5e0f41714329a46ec5ee6b2f51f1c25ef45fc8a8a2217c43639d9221af94774)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 172: Field Element(0x6ba45bd8fd6efdcfec4b6333b284fc32346009e30dc6891d06a5d0941037530)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 173: Field Element(0x2f4cfec09deeff3fe4bb62443871715f08ca9225fd359a6bd218b65b21ef4a9)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 174: Field Element(0x20b98807a5c05849eb100d13c4f4dd5ee50de8ff7efc41bbf3525956c3adb1a)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 175: Field Element(0x202ed1c9517a8ee8e374fcb6e97ffd55be909e50aaf27ccee9c0f0dfeb57081)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 176: Field Element(0x66372a09ffec81376d0f052a578f31f55fbb5b2d5f61b22e2fc5138a97e3ecd)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 177: Field Element(0x1711b7326dc80fba4fc73ca875640ec0a1cc2fea915b6192bbc36246edebeaf)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 178: Field Element(0x76eb6e2dae1332f54dd3e8b0e14333e4c308c915fc6356f1d750b5359af2332)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 179: Field Element(0x3c4b850d454a7cee15f8fa127e58d955dc6a07732e120e50c7c5dc6c2c914af)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 180: Field Element(0x2b2c7e05b80b5c7d88b14651d77d8b3bd43985b1e9ec77d58af805d9b18a935)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 181: Field Element(0x6a2195a284cedc0be87d5ada790a64daef299f487a93171b2d738c45f206fd7)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 182: Field Element(0x6d6fca4a39b5d7b1bd67e257798aa3c9a4e84ca1bde5f52d402495d407bccd)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 183: Field Element(0x48d5a11adf48a91cff9e8498c82b7d9528d7dc4b3cecf486a05f0ac34fed1b4)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 184: Field Element(0x5d8f0738a8cd7294beabdb543c2ff51dd35b1fb816f4ccb184338069eeda5a4)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 185: Field Element(0x77935fab53e933735ce986a2e0671ae9a161e1d79cc3e662728375d17a18049)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 186: Field Element(0x44a0b32ea12e51a48de1750afe9db303f91387ba9f7faf8a26e32c581e9519d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 187: Field Element(0x22db088ce9a2856f708f9ecbf631e239016dd88147dc66750f8f04d6d4a914d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 188: Field Element(0x4f12d5f589c97f9ff7c3b24d5426cc2fb903a679917222c9066838af7aa4b8)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 189: Field Element(0x7bd67bcd9477e4398a65c0fc1734c13a9d13c3b8083eca5f939e29281564d88)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 190: Field Element(0x867e1feab4c0eeda019dc3c485b2523f53f094b81cb9db1d6369c75274e0dd)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 191: Field Element(0x4fb316d1b312c986eb58001ab4d23cd9884c3086b4f40549ab7d5b81fedde11)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 192: Field Element(0x7a519bdaed04b18962c8d4ca62e7a78562ba589dcf9fc45a714e03664f16b18)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 193: Field Element(0x12ba18c3c768a3b1f8d19481efaa98485b4002b6aa9a19b5a2e88c0f7d4087)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 194: Field Element(0x3b7912f885dc30bfca6f27f4f547bf7d2362d0d6cc101d217680ec4673129fc)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 195: Field Element(0x3fade7317cfef5034b8810f3da44e1c2e0ad86c07f97e65e02d2c00c01cf96d)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 196: Field Element(0x79bf38a9e306960be55d2103a66c58561b531fb2ff1d25b4c22fcd8ec2ef989)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 197: Field Element(0x5d959d8d86baec9f21ab23c8df4bec9c1a5d3f26734cdda2c520ea355e59b84)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 198: Field Element(0x6b7ae64b2701c44432ebb6f97bdbc2b07cd7abded48b2be38ced8014edbe61e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 199: Field Element(0x51278a413d162b768143e514333de227bf4c3cad4aa5de76d111a0445a71a0c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 200: Field Element(0x79b5474538708827fabf97a48df048a5b44d6347d4c3c219568829e0109fa65)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 201: Field Element(0x2bb4b64874c1bb5fe7dc78de6c34d43bb726bae72af17f8921561a5d02666d9)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 202: Field Element(0x21cd97a44d0aeb1f093007f12671959aac8d0d1446899375e56d3775e69aebe)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 203: Field Element(0x5b9024bb878fee131e257ae9b644493ca3a477b39819ab169a890608455f6a3)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 204: Field Element(0x2ffab8d3b78a12727d00bc85d7eafd5af31f3619a8aa7755b757bd390a0dfb2)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 205: Field Element(0x1a477facfa8bd824a198a08000d0a3f21cbfd32a3e79a67b7ed6649b54db7d9)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 206: Field Element(0xa2820a964639da49cf80aa7acfdfb3c9fee7f06aaad1bdc7a29c37feb713dc)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 207: Field Element(0x5250cc5f2e0341e93f4022bfdbbc7d5003f24df7224dc9d705504007c3e5769)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 208: Field Element(0x612f3e3908cc72247d1a83709b40469fd02b098388d779d0e58d3af2ea66afa)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 209: Field Element(0x5c66cc9d02c9145b1d0303a562d7c275afe7f854a0172d381f2d8b6bc8814d2)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 210: Field Element(0x3405b3d77b8f7e5402560394713fa5530e8e9eec1f6ce56f137d633a9943acc)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 211: Field Element(0x1b66e130de4a33932d849e4a45e0f9a678192067698ca2cbc0283f2b4731eb1)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 212: Field Element(0xac659f577d6cb2acaae87112fec325e1d7bff7f5c30b621d81ac08f68aeafc)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 213: Field Element(0x162d6a2d97e5ff8fee5d538a5dfa95ac8d251b6873996007dacd93dd6fc02fd)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 214: Field Element(0x52b3eaf692d8280f7a98c25328928f38fe02e3a047d331d9192c95e4f31fab8)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 215: Field Element(0x2ae8ee2454a1d1e7d44052e58babe5b5af22725cb1bce6c919bfe17ef5108de)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 216: Field Element(0x51915e9a20928d9b4353f6959ce0e04e73e7d91d51051124cfca01510d80b71)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 217: Field Element(0x7f0e188220055bdf39f66dbd2be5901408a24c1be60eb30c6c4408ee5dbc8bc)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 218: Field Element(0x61d737e850d55702d2accedbf14f6307341ec6a221db72b766c50480a72f259)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 219: Field Element(0x2a737cc39b7282969460f27191ece830b76eb9ab1b3704b90396c95881ab469)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 220: Field Element(0x40435376bce1ef3f0257b56808ccae7ecb3645d8368f2b1aae815fdfe01a8fe)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 221: Field Element(0x6129d66770c6a44bb462464d8b13b24591b12d1b3192639ada338cd857c777)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 222: Field Element(0x2b6be9302d7d06eac4d51a236f7d87e975f3bc5a2993ed78ec2c0b29b4430e0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 223: Field Element(0xd0b771faf3dee3d8b6b7b84dbb4e88d9b58fce622ca8d6201486c8d3cae4b0)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 224: Field Element(0x7bc1113d6794b9bbdde96781ee532de5fb68b81b54a44d17277a4a558879db8)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 225: Field Element(0x7c62ae81c84e9a4e9adbbcae908c5531df92a2582fe8bf31ca3b123a2a88c1e)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 226: Field Element(0xa3c010d43348dde6191d1664c42ecc58fd556b5ec909b22a3093717d6debed)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 227: Field Element(0x57baf1b272057b5821fb12422714e44f8644b29d3b49399b28a696676da39a9)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 228: Field Element(0x5a5f947327735ba809a988e8f94bc4a12b382c36148236746e17c7b488e903b)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 229: Field Element(0x7c38e76ace7ebe4b3392c61df54907c14e9ec13cd2352e69bf2251711faea3f)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 230: Field Element(0x531888799c7cc366caf80fa0ac204e77f7130865cceaddccc5f8df1a64544f9)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 231: Field Element(0x73c7417a8d62aee396e95367902366d71bf9c5c08193ed046fcffad61e7e704)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 232: Field Element(0x29dad700c0cf7528e3de88de6bc6a9b2b161ce4c6a238baf2071eafb7db9fc2)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 233: Field Element(0x411426197355a2e71d6777d338b6408f589c6574af52c78aaf1c19af1362a8)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 234: Field Element(0xeeb5f81dcd9e11d39e3519099370591ad8d72664d547bfc516e67fa7054686)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 235: Field Element(0x41b109a1020ad336bafbd2d5ef83f31c8875ce9380ca1a5220f1c17deb9c88a)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 236: Field Element(0x77685725e7f52f46439d41f8d8727f10ff8963cb2a63f700e1030c3dd1a4772)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 237: Field Element(0x739a8b8023f829512a554a7f50e4165e87add4e446f8257b308c0be5de11c86)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 238: Field Element(0x171191a9cf6ec02927bcf4fc6b37ef22ddd2ef5579f62183378345c488d980a)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 239: Field Element(0x5b5cd42e20f97cfea840e7a18de5eefb3599729c1d0cb259ffbb2cfa50c45e9)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 240: Field Element(0x3cd146fa65ab837c6564d1e6503a493f10fc7feb38c11d7a5353620c06bd7c)", + "V->P: /cpu air/STARK/Original/Constraint Coefficients: 241: Field Element(0x5007fb6192dada399581d97ebe0e64a3a295f43e906a446ed9806f2b9195bb6)", + "P->V[64:96]: /cpu air/STARK/Out Of Domain Sampling/Commit on Trace: Commitment: Hash(0xdb714528b96e7b6762d3fb3f6b6d0744b4b655f000000000000000000000000)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/OODS values: Evaluation point: Field Element(0x1283f8e0d8b4a759a35ee96eb5e577555ea0065db1a5fe75bdca1b2cd72956e)", + "P->V[96:128]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 0: Field Element(0x584f382eda3a77b7fd78ae144e5805fda2863a903c36d59f0806d6949d9cca7)", + "P->V[128:160]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 1: Field Element(0x25f05708ff7dcbd411be94a179751e58e3f2cf546c2a0fa9d57828ec9e80fa0)", + "P->V[160:192]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 2: Field Element(0x51094f3858d4ab5379bf8589e5d616762f3abacc070dce4f831ef21e27ecb69)", + "P->V[192:224]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 3: Field Element(0x26480ed20adb9aad275c1d3590fadb31c39d082bfdc4f7f413461ab33fc0a64)", + "P->V[224:256]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 4: Field Element(0x720385af8a43c1e75c1300b0f86332e63eb133159373353d0a347b0d66646b0)", + "P->V[256:288]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 5: Field Element(0x184b6b9e480d69217f24442451be9a492b09953ef3ee5972efab83ef7e72383)", + "P->V[288:320]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 6: Field Element(0x27bf974d57d497362f044c5c02e13a8ea8dce0b1f226d54b1122d95636c3d3c)", + "P->V[320:352]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 7: Field Element(0x3d5a482d834928892982051657671f9b80adcef2ecccd6dd34181bb33882566)", + "P->V[352:384]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 8: Field Element(0x3a745682a9ce4de98185c3ff8c1a65affcff30e69f9be9415c437dd7d51e807)", + "P->V[384:416]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 9: Field Element(0x1b3109b0ff5d0bf15a1d29be0ea8d8481005040109c2283fa30e22d2181b8af)", + "P->V[416:448]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 10: Field Element(0x28400875a5dc0ed92f1b3c5f20e1471aead298a60ddb985744cf3cfdfe6aca4)", + "P->V[448:480]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 11: Field Element(0x5772bb58a2be429332e7a6d77c968718a86e37c52ecc3c0ac44bed4fcde4d2)", + "P->V[480:512]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 12: Field Element(0x2772d4fcb78457c7847b0b371d4726679749fc20da703e73525de97270638e7)", + "P->V[512:544]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 13: Field Element(0x5c969aec007bd1efba0f92176df0676f8b3ecd6e866c6755cd4ce8c58f16148)", + "P->V[544:576]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 14: Field Element(0x153e7bc18d0ecdf853a9d29bfef227e761c03ee678c526637ab828959355db2)", + "P->V[576:608]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 15: Field Element(0x297f511344ae11f1788ec7bdf0e5df521d83ab77f7d16a856159c28d5b8e7a1)", + "P->V[608:640]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 16: Field Element(0x5b696ddd6801bf0133835cf0ef487e5bc1fb8c402754746ef7be6e1f36cf827)", + "P->V[640:672]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 17: Field Element(0x2aca620e7e2fd6e445f158776073f09d855e9bc45dd2b337fadce5561fed693)", + "P->V[672:704]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 18: Field Element(0x666b79604360f6cd786725a9251c1ce38293e9687b549fbd2baafda2e2659cb)", + "P->V[704:736]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 19: Field Element(0x53e33866ea09d34ff898925d50276e8bb649c03b014338367acf523ba37e1e6)", + "P->V[736:768]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 20: Field Element(0x2f959ebf43ff01830d30047de75111d90170753b53b2d3d8bd149c4eb76c7bd)", + "P->V[768:800]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 21: Field Element(0x5c17a198cc2ba3f7aecd9c2a84e00d34a078747fc87c5aa61bf593ac1c11a0a)", + "P->V[800:832]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 22: Field Element(0x5d963f27dc4a7a2a1fea22c04e8ddad17e3ec8510620da6d54d5a2014f22bf6)", + "P->V[832:864]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 23: Field Element(0x1b93ddd2c4dddb2203367049f28c05ee45f7fbcc65994e4d92d41c486a04d1)", + "P->V[864:896]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 24: Field Element(0x24ff63fe3ab671505452e9ccf9a1b68fe12d229601f61e1d9fb81e11bfb5433)", + "P->V[896:928]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 25: Field Element(0x48aada79d55c02fd80fdfaa3fdac37ce0272eca647b98d64dc16f5df8a1800f)", + "P->V[928:960]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 26: Field Element(0x56462a578fbe703b566c5babc4971e9e47230aa4ba4bc868455e06457343678)", + "P->V[960:992]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 27: Field Element(0x421a4d31a05e99b9f6cb400a05ceac40294aacbdbe12135301f8ddfc0972d4b)", + "P->V[992:1024]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 28: Field Element(0xad60a75214325cd409e8607ebd956dae94023be9a953bcd29a1975962d7fd0)", + "P->V[1024:1056]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 29: Field Element(0x2099742df65d37159d32eb0c57e18bab89c5a6838339446e1a91c52b71a86bf)", + "P->V[1056:1088]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 30: Field Element(0x3569d20d39938894ac90d4ba80cbe80fcb7d309a7555d3350dad937ff78556d)", + "P->V[1088:1120]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 31: Field Element(0x2780c0e5e36ab1cb906e0185b214ccc01ed99bf1a51ebeb67f43914cc6b3307)", + "P->V[1120:1152]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 32: Field Element(0x5bd3079b78629e51a266a79ca9df7d08fe1381b8597c64617585846c75ed9d2)", + "P->V[1152:1184]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 33: Field Element(0x6a3b4b52449fdecb82d1684c724845d875fe6f3d635d04fbb46258a3820ffff)", + "P->V[1184:1216]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 34: Field Element(0x5cd8ba719f3137eecd8e6100e24611755987e4881798ce0d78a2e31b0c7cc7d)", + "P->V[1216:1248]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 35: Field Element(0x1df99b0d548ec888d32d3b78aeedbe8d1ded37baa1cf39f75b8930987d92cc0)", + "P->V[1248:1280]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 36: Field Element(0xce8a16c6886b657a3376b7a4955360aaa9c4dee6262a980229ff1c3f0f36b0)", + "P->V[1280:1312]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 37: Field Element(0x41ce8ec7331f8e2deb12f2a9acdd9c592e233b73eccb29f30bf115fe983595)", + "P->V[1312:1344]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 38: Field Element(0x1ee8ed6f4134c4fb29737d7479f72798dbae5df2f7e1ecf1353ec0389a863e6)", + "P->V[1344:1376]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 39: Field Element(0x73630ad86faae056138e5fd5c6917167e76f9509a8930143980fc2e9aa6ab93)", + "P->V[1376:1408]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 40: Field Element(0x247b36e15ce0155cc5b02995ea6b9c017b794b10a07fea2499ce136dfa299d1)", + "P->V[1408:1440]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 41: Field Element(0x47e2d14f2ef2c5a0c693195863bfea349d0f4b93d038f05b4805e598642f8db)", + "P->V[1440:1472]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 42: Field Element(0x2fbd9c190baced97d1557de02801ded5cdb8fe4a93f2af7dd61573dcb410a21)", + "P->V[1472:1504]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 43: Field Element(0x151b236962391fda98c044d0f441a861fbdebbc72188581788d9e2c5446a703)", + "P->V[1504:1536]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 44: Field Element(0x8c6572ecc9d79fa45bff91e5f2182a63f485c9b9a63aa1dce41effa541f554)", + "P->V[1536:1568]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 45: Field Element(0x18608a9d83e7a9f134ea13b5457aa91a5a139415d1ab5d354d5befec754a031)", + "P->V[1568:1600]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 46: Field Element(0x46f3def2b74aef718059a9afd25f6fb3d9ac27fd395ac0df25fc3fd0b9cbabf)", + "P->V[1600:1632]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 47: Field Element(0x1e32623f119142fc22aedb5c8c260f1ddf371fb26cabf12f8c268d6311fcdf6)", + "P->V[1632:1664]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 48: Field Element(0x45b70f9489fe6bc85af81477dd9e53703ed347c3627a957520907091f4e4518)", + "P->V[1664:1696]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 49: Field Element(0x4b2096ba4a4fa3b6fadee9db2f6adac8a90d611db2977b9fa55e5f0abdb6c27)", + "P->V[1696:1728]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 50: Field Element(0x4280cb3807e9f4c85a98f5d7228be38a582517e7c9ba72f53f3b5216abe15ea)", + "P->V[1728:1760]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 51: Field Element(0x5b9ceacd90e5ec9cf3fdb3ee7806690d9232974adc58bbb7eddafeddc558da8)", + "P->V[1760:1792]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 52: Field Element(0x859576006c809175ff68a367aea53fb336ee0efcbe2e707d87800e55f3fe75)", + "P->V[1792:1824]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 53: Field Element(0x32fc9edcc4c1e915e112882669a86398db9233281c1e21e1c675df2f355d39e)", + "P->V[1824:1856]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 54: Field Element(0x226f8d2d015337c6dfae786628e866ab6c9c8ebbb61271ee924951224f62743)", + "P->V[1856:1888]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 55: Field Element(0x3c73e10224e5b9a977a6de1abd77baf1da580ada7a71d315fc440d8c63a4575)", + "P->V[1888:1920]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 56: Field Element(0x49eda334c7fd05b2e888cfcd286945d8c5e9925813d26572bc0e7b54c1e8f64)", + "P->V[1920:1952]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 57: Field Element(0x6b4cdde21bdcfedc40349110828cdfa28cfd80913b79b8609a490f1c76b54df)", + "P->V[1952:1984]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 58: Field Element(0x3f5558de8cb48fe1da347b8bf2a3e3c8212e990c7a5b6deb6673affccaa9c90)", + "P->V[1984:2016]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 59: Field Element(0x730a6ddbab29f7592a95329786107600a4876fff9862e42672193045abd5e1e)", + "P->V[2016:2048]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 60: Field Element(0x7fd237f22f9feb1af1e679dd705a1887ff3c13442057d858b7924160876b682)", + "P->V[2048:2080]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 61: Field Element(0x3dcbf4e4f8fb2002ec3cea3550dec44eb5424bf7922125e51e878f96cf2eb95)", + "P->V[2080:2112]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 62: Field Element(0x274e75e9f21e44a52c07ec62ffb1510506a719026736ebd9198cda641ea8af1)", + "P->V[2112:2144]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 63: Field Element(0x65b21f4b0f91e2cd4817b0707203ddef9a271b6e335bd1f32074e8bb7709f41)", + "P->V[2144:2176]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 64: Field Element(0x280e7eef4c31bc3ea32f18d10f1c7789d7038ac4a28c6e8f4f5518e6b15a544)", + "P->V[2176:2208]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 65: Field Element(0x719c584ba23da8ca38defeb6f6af9d5891599448d1edfe37aca96da64f93005)", + "P->V[2208:2240]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 66: Field Element(0x58297e868a23062e178ead1edb0208d6ec011d6d11b58822e00917ccf18480c)", + "P->V[2240:2272]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 67: Field Element(0x7af5c735590216b89ec47a4f3c77214fd8ab302205aab288babd752781cdc6)", + "P->V[2272:2304]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 68: Field Element(0x237444540f385fd97a470b6918b1d3bcd52ed64906bdccf96e4ea43c823a713)", + "P->V[2304:2336]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 69: Field Element(0x6240e2bec11c33c75f11412db69c7232f77ae0669e51ef200a368c1fa2305eb)", + "P->V[2336:2368]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 70: Field Element(0x5ec9436dbc2bb6b478afbe4539d8362a4033c22040ae0115e34d45abf1bca57)", + "P->V[2368:2400]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 71: Field Element(0x251af94a3f13a71ecc8d06b548549d10d42b7c3422c72e9b7e89159572513a0)", + "P->V[2400:2432]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 72: Field Element(0x3d6f6ce565059c00beb2e7101b41d60c3ff4f8ad7385de5158fb5a2f62c0a07)", + "P->V[2432:2464]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 73: Field Element(0x283c5fd843adc46f56782cb89c054eaf96129d4310708a6f22eecda9667b4c5)", + "P->V[2464:2496]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 74: Field Element(0x7a9c2262312162d2d7c55a548b66d6ca2784f39464f5fa4f4c2a01e833bc5ef)", + "P->V[2496:2528]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 75: Field Element(0x7a0a19d53b4f61da9ac2d5df80241668d737a9a3f9236b9adf1dd5ea01dc1a)", + "P->V[2528:2560]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 76: Field Element(0x3497bee87457f22657016d1306651b0b6a8142e691057d3d17166378de8a2bf)", + "P->V[2560:2592]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 77: Field Element(0x78bdf1db6bbe35682a87bc2f3c54709b5a9e40a7371a1df9ec19018296c5cf6)", + "P->V[2592:2624]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 78: Field Element(0x204b48b54c9b7382ce976628a802cdcbb4816e6cec2f64c5c34f939e5cb0968)", + "P->V[2624:2656]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 79: Field Element(0x37a229bf43195c92ef4d5e711a9cc0093d3d47121b193fef650492dfd16fceb)", + "P->V[2656:2688]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 80: Field Element(0x7f4416a681981200e12a20a7b2ee2a4a6286777ff455117e6a0a9eaa2e558ce)", + "P->V[2688:2720]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 81: Field Element(0x3dfc482a9a62c27af40c740c945a10236aec17a1fbc6ee8cb0a4bf99821b9c9)", + "P->V[2720:2752]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 82: Field Element(0x19100dc6b35418a16e61684070dd0f7599e08a98888a784a7c1c155047e1d0b)", + "P->V[2752:2784]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 83: Field Element(0x7874ff6acb6aa9fe265d9750b3a3a46aa34f7b1b3ce2efd5f59edcddc6ac102)", + "P->V[2784:2816]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 84: Field Element(0x410e24c9e84b340db053274b153d7bb2b0c9a2cb47cb6d4fa2d8f7a784483ad)", + "P->V[2816:2848]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 85: Field Element(0x3f17e70e0352dfc648cba32d0240142d7f3d2a7810fa828701d0b8be9f17b9c)", + "P->V[2848:2880]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 86: Field Element(0x14e802f210275cadde8e5577666862dd27eb259f836b07678758496cfdd2a8d)", + "P->V[2880:2912]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 87: Field Element(0x4cf00dfc30bd43dd3b283afea6b002193e469c8be77603543f8f13121a048e3)", + "P->V[2912:2944]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 88: Field Element(0x3516decd745bd7ec399849a3a39bb55ccbafcc334097760ba39751d62d37eda)", + "P->V[2944:2976]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 89: Field Element(0x2184b322506e203c4ae4558a8f558302807b27ffa7cf645827b907f421dcfc8)", + "P->V[2976:3008]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 90: Field Element(0x798be045ef9a638327c318584b6a60dfea1c3c48e21c54276fcb129dbf41f08)", + "P->V[3008:3040]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 91: Field Element(0x6a9fd28672ac5fcb3be5ddd8120b6e402c13dbf923863409fa0257afa8ada4)", + "P->V[3040:3072]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 92: Field Element(0x1bc93c97f87aa2182a84150da352e9b8e776df14fcbcaca929b2cff5290d3f0)", + "P->V[3072:3104]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 93: Field Element(0x198824fffe0451b40c72a817042242bf6b74b840934a11cd3a9ef8dc4cfe8d9)", + "P->V[3104:3136]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 94: Field Element(0x362e1e391a50969d9125625680d767b4a88f39ae5ad03ee94e880cef26752a1)", + "P->V[3136:3168]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 95: Field Element(0x666f1334795b4fd84c42df7d6259ff5eadfb5f590c1d834541dae5b2cd1b713)", + "P->V[3168:3200]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 96: Field Element(0x1b3de328cecd440623784d0ef71b4c7e430a321a341aa9079fb76b0e63f40f3)", + "P->V[3200:3232]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 97: Field Element(0x6a75e1f9de0dea3c980038814ab1c0584656464d898277c43e2bc3abb3cb1b6)", + "P->V[3232:3264]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 98: Field Element(0x14c4c5d238b6da665c5135737d0cf3aeffa061972556ec349f949788b4ffb64)", + "P->V[3264:3296]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 99: Field Element(0x2af4eaac5d9d867f2ba397b6cf4f537a29688be471dcdde4f17ad06b7f7971a)", + "P->V[3296:3328]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 100: Field Element(0x37b03f45c7f7c9d759936cbb5a407a5a12f35d6c223f29f4a21ed1085857671)", + "P->V[3328:3360]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 101: Field Element(0x10528bf2fd2bcf3e998597d9414485f49e3bf08e520025863673714d9ad0066)", + "P->V[3360:3392]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 102: Field Element(0x33f4e2d65ed898782e595eaea563b9dcd321ac2b2f49e08181fa071b9147863)", + "P->V[3392:3424]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 103: Field Element(0x28cbfbea1ac0a3720cc1f89620f285bbc82f70000df777d8ef0bdba943f0338)", + "P->V[3424:3456]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 104: Field Element(0x17eef1bc57630c64a52d1adfa2b50b37a04f4364c51e7d6bb25444c6be91637)", + "P->V[3456:3488]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 105: Field Element(0x2bbc141d79107410c7698cda9b6207c721410a5c823d2df2b8b52a9a8713813)", + "P->V[3488:3520]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 106: Field Element(0x6689809551970fb30be7709a71a0799e758b56a035d9532aa407a7bf5a02ba6)", + "P->V[3520:3552]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 107: Field Element(0x3874f9c00b7c29a01d6b0d3668f4a9fc6789383f41205ec37b1960a194e9b94)", + "P->V[3552:3584]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 108: Field Element(0x1ff47219923d391c86a557271974852f9045bcd85f80508c6c12bca4cb42d81)", + "P->V[3584:3616]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 109: Field Element(0x123bdbf75489aaf07806ee5fc45b7a1e3fd6f0473979686a4b79c5acf03d11)", + "P->V[3616:3648]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 110: Field Element(0x51e039292f48f2b1687cd8964af4b1f71622be69651ece799fd742117146d9)", + "P->V[3648:3680]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 111: Field Element(0x4be29b9648728caa6b7c9197c8e20a13982d8c7818cbabfdfd542bd8fe01fd5)", + "P->V[3680:3712]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 112: Field Element(0x5bd4f22bfa223445bcd5325b968dfa6df33b02f079e6a0542a1c0709a665808)", + "P->V[3712:3744]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 113: Field Element(0x2af4f01222a32e3fdef87b668ea6dd56f58038c1646cb5d57c3731abce012ee)", + "P->V[3744:3776]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 114: Field Element(0x7e998b7507c2d13f0443a777ef9300b6527aa0a48822811a7d12c9f46aea71f)", + "P->V[3776:3808]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 115: Field Element(0x1bf648d5fc8bab5367f4ec184d59d1b62ada7aa66ec7823b3fb4f224e103645)", + "P->V[3808:3840]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 116: Field Element(0x6f59dc0eff38b6be6d01e334fca0390633b2c9c96380f6321111b9111082218)", + "P->V[3840:3872]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 117: Field Element(0xef9522145c2231b5bac9f39d935b79d74e3026b2348ac4f63b5154374fccd7)", + "P->V[3872:3904]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 118: Field Element(0x4bc3d7af5a2fe2cdfb39be1fe9af037a61abf4e7c05b4f3fe30d0969cb5dfd3)", + "P->V[3904:3936]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 119: Field Element(0x520558a29bdc8401f6f0578c201c265609baebab52b0161ffb6d2e97a3dab7e)", + "P->V[3936:3968]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 120: Field Element(0x4a388e63291ca86e93535ce33c0e614f337b0ece3f41160899337a7e8c968ca)", + "P->V[3968:4000]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 121: Field Element(0x792067bef895ee3eceb40509acf77ca8b385ecf8a05a2c2bb88e46ebd20a0c3)", + "P->V[4000:4032]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 122: Field Element(0x57cde35c5988e81dfbd3feec230e8bedd78ee74e7ad7adf1a843caedc00ec7a)", + "P->V[4032:4064]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 123: Field Element(0x67a150f8b61e48c3b3d0c35ac2578c55798a6fcdfadcf069838e8d1f4dad454)", + "P->V[4064:4096]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 124: Field Element(0x1d112b55877e7d10beb1c0d5c36bc873751748953448b8d9ceef4835417f1c6)", + "P->V[4096:4128]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 125: Field Element(0x68263fe16cb484284f3b9ccae5028e83aeb2faa779592e2f105f7ce824c5f31)", + "P->V[4128:4160]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 126: Field Element(0x6c50ecb899e55183c2c4b1da2fe93f112804e7d52f2b28dc05df5033051a71)", + "P->V[4160:4192]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 127: Field Element(0x2b5077a4865253d2a0c816c2c7f035dc2359fff3d11af88280e83fdca69789a)", + "P->V[4192:4224]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 128: Field Element(0x485f8894c638db606778be8e0396dc0f388d1260245a8cccf74eee10a8bdb92)", + "P->V[4224:4256]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 129: Field Element(0x171fffa223a8ff4353ec9cd735e47ad3d2da5fd85a2464f1a6576341211f92b)", + "P->V[4256:4288]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 130: Field Element(0x51afc246a1d34488f9ff3ecb4e5354c718307d7ff315b2ea059aad5ab87f328)", + "P->V[4288:4320]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 131: Field Element(0x1de2e53c0b420451c2547219772ec24f8f088496dceb48b50c376ca440f8984)", + "P->V[4320:4352]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 132: Field Element(0x731093a68928ef069ad43afb59516124a3f9fc4ce80112450087aa5061bcde2)", + "P->V[4352:4384]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 133: Field Element(0x1ad9f23b4814771c9091669e0384ad5949dbd7470f590944fa0c5283e394e41)", + "P->V[4384:4416]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 134: Field Element(0x631284fed790e5d7d00357f1de149a71b666318d0db1101595f3b406b12aa46)", + "P->V[4416:4448]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 135: Field Element(0x3249c006ff06cd00d545c2cf14e717e8a143b9519f4706f3b94f054e88d3bd9)", + "P->V[4448:4480]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 136: Field Element(0x35aa5956f0819dd72af36d8d721617eebf4dcdba5e2fb203989eee13b28093e)", + "P->V[4480:4512]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 137: Field Element(0x48ff3bcdeaa15693ae14fb960665b766eb448fc73ea13a8b3d1a441970d30f2)", + "P->V[4512:4544]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 138: Field Element(0x11b1e9e70a9219a867d87f33ebee680824de68772ce9ddaa9ce7cad06fbe082)", + "P->V[4544:4576]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 139: Field Element(0x8efa254ba0779a60eaa7458637594982bbb12b66217968622e0aa9c60fb5c6)", + "P->V[4576:4608]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 140: Field Element(0x79246a5ac4766b2a34e8191f46f7b637691379b19139fd95ce6e1192d304e2a)", + "P->V[4608:4640]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 141: Field Element(0x263a6e7ee8d45192f0e84e1e5add0bde387513eae878512a9c12d7fd5eafcbc)", + "P->V[4640:4672]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 142: Field Element(0x4d261788e79c0287c2756dbbbfe96bc30090693a2ccd488c22ca1b079e3bdfd)", + "P->V[4672:4704]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 143: Field Element(0x44a4ae363eb3b8e3e17b587720389d15ee2d07bbfb7f7593bb3ac10cf74b39a)", + "P->V[4704:4736]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 144: Field Element(0x4f4e508514c0a466a18290a65ceaa1f934db032391b621e62de91899b744ecd)", + "P->V[4736:4768]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 145: Field Element(0x3b8f68689f94962ba11a711817bacd0a08a1809c8f24f4e1fca1cc5f06bcf)", + "P->V[4768:4800]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 146: Field Element(0xcfdb592efd6f5421a8dbf631f01578b930ff2786175d6cdbc0adc6b5014082)", + "P->V[4800:4832]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 147: Field Element(0x2ab682163c5beb36da5542c6353c31320c58349f1a546e1515f0d944d1c8a26)", + "P->V[4832:4864]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 148: Field Element(0x1b5040c43b7286f775c8a39c09a3e47057d4ba99bfdba6c4dbac713a75b0e53)", + "P->V[4864:4896]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 149: Field Element(0x711aff155948afd660a1138d2ddac3ffe1346e010f49814e27a661b1efeaa96)", + "P->V[4896:4928]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 150: Field Element(0x11096b242078a5789f270947c71363fb4765a9f60aabc45c054a1dc385889ce)", + "P->V[4928:4960]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 151: Field Element(0x4d09837c0e2f81664aeecc6fa1835edc7f45ecedf35b2d6a0e48c6b62430e2b)", + "P->V[4960:4992]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 152: Field Element(0x3caf70f22cd3427c66578568db885f92a4deb1d91e8449feb90d03a241da9a)", + "P->V[4992:5024]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 153: Field Element(0x507f930cfe57eab0cb6e9e322fd5d7b5d0a4565a2f3fd0cfc52e0453eda19a0)", + "P->V[5024:5056]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 154: Field Element(0x2a95728243c0af93f08bdf6abb343c0bb88ef61cf07a71c4bb6112a6c34bc69)", + "P->V[5056:5088]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 155: Field Element(0x700134e51fee9aa07700e83556ca618b5749126a2a5232c11318956f3b6d72c)", + "P->V[5088:5120]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 156: Field Element(0x6704e458aaef8ad3002df90f96a1e8aba19ca7b69c4461db4996e4238e6fec6)", + "P->V[5120:5152]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 157: Field Element(0x7d0e1a39d8f1b0f6f7e95b11cdadf731857d223c6f528246e37e4cfcad6c2c0)", + "P->V[5152:5184]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 158: Field Element(0x32c2b46ee54ffb6560762de0b7d660aaac0ccbb66b03fe0a28e4cc39625d7cd)", + "P->V[5184:5216]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 159: Field Element(0x42a0ec0ee3fa353fdfdd5855f5ff0047166fb0532df5046e33a779e6f284fe1)", + "P->V[5216:5248]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 160: Field Element(0x51d6c4fb7396cac2bb9752dbe496f5477006e2f9eb45192101dd6489640e96)", + "P->V[5248:5280]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 161: Field Element(0x525afcdb087ddf3cafd3d2d9f126010f6c8890d679ae749969177cffd27f33b)", + "P->V[5280:5312]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 162: Field Element(0xda898de1333efca54db5ef4d06bfb2547c5dda1b1d942bb598be234346782d)", + "P->V[5312:5344]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 163: Field Element(0x5fb0109442c076039a47167bf78f76875dbb3ad04bd01748d60ba9e59ae77c)", + "P->V[5344:5376]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 164: Field Element(0x7daa84ceba35122f24f46b7574fd03395e5f7899ad3bde6317757bda2b6a6d0)", + "P->V[5376:5408]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 165: Field Element(0xc509b751488f3c87929fecb36bf61599cdba155b1020ade48c7156abe544a0)", + "P->V[5408:5440]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 166: Field Element(0x57da80d55a09fe4a22f7803830165bf56e8ddcc0f277955a5b6c150cf9baa2d)", + "P->V[5440:5472]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 167: Field Element(0x31e0d11b189702db9552a168ea8607cc1233548fd8d297fa125acbed9c6933d)", + "P->V[5472:5504]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 168: Field Element(0x6cd47850d1fc89fa7273119809c74138beaa724dc91ab102e823b634ad14bfa)", + "P->V[5504:5536]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 169: Field Element(0x93f7b58a976cf4f844a5be0a6c753fe1f28a5443e68ac456d61faa2506f7a4)", + "P->V[5536:5568]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 170: Field Element(0x6622f8bbf4a0834287e06e710acf1074628dbb6f08b74be92642bf7b84b043e)", + "P->V[5568:5600]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 171: Field Element(0x14aba0e57389e506fee7cc9db62f3d55666958e2a31ad8ded7e422ff5306b46)", + "P->V[5600:5632]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 172: Field Element(0x10158fc3f6cccc08f249461325b788c5b262b43ac79c1ad97d0126b9b3bb595)", + "P->V[5632:5664]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 173: Field Element(0x27787bdea99debe61f5eb40cdf4cce888917a221acca898c16b59c19f9fa73e)", + "P->V[5664:5696]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 174: Field Element(0x675244db64834eed627b82d54f6db535c8e71d007592db0e562f002aa23801)", + "P->V[5696:5728]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 175: Field Element(0x79f17b4fffdde0c442aea3f923d1275a9cd4d3ed870ade42a3cbebaeba045d1)", + "P->V[5728:5760]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 176: Field Element(0x193e60bb75bc13cc8f4ef9416fa817d4aec3c857495353701d0e8bf43a6c60b)", + "P->V[5760:5792]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 177: Field Element(0x4fe2bba5dddd7b1be76da8f0e5e5c74f8f67f6f8361fc43158c3b853c9cadc3)", + "P->V[5792:5824]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 178: Field Element(0x681898e561e962b8fa3c50ff15ebd471b65cc32ab015168a58d8dbb9ff19250)", + "P->V[5824:5856]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 179: Field Element(0x7e687fcdcc38e3056084e5ea8a5b44585e037b660782057a3521cfbb7e9a28c)", + "P->V[5856:5888]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 180: Field Element(0x1316aa90b8c61a33bbe09c8b4e79c5fdb50ee5a22a91f33f5e1c4ddc60cac2a)", + "P->V[5888:5920]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 181: Field Element(0x16bf4f13986561445504753278172a3edd355003d0d76def622aa6801679969)", + "P->V[5920:5952]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 182: Field Element(0x43b61117ed50b3287611b3401e6ef163ddc252d195e9dfca0c804daa62c8222)", + "P->V[5952:5984]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 183: Field Element(0x5e0da1b813365dacd02ba5a027444579faf452530203021383f63c47ca0c8)", + "P->V[5984:6016]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 184: Field Element(0x5f01d7871f7389ec0a5e2a6d15816b2c4e7fa5b05bf185d3b43b71328acb176)", + "P->V[6016:6048]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 185: Field Element(0x736d62cab49921bc18cfdbef909bc6d5171ed9a03e876a68955fb2b627b0c94)", + "P->V[6048:6080]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 186: Field Element(0x28c145877c8683d79c2b4cd37fbe8d68cddf87afc9805c811f395defdd8336c)", + "P->V[6080:6112]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 187: Field Element(0x2d5bdee37c2a46a58e6a7fbf105930a199922e0d094bab82dd3f8282509be14)", + "P->V[6112:6144]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 188: Field Element(0x294d43e8986ac20f89ef6ec60cbcc400957cf30524b93bf9f25776f3e6b4e47)", + "P->V[6144:6176]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 189: Field Element(0x5c6afe3fa3574ebabb7a816b3ea5e58dca81dbb891c8d77b160dc76ae52ee2a)", + "P->V[6176:6208]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 190: Field Element(0xc4c5f97f994d3f8def55096733c8e488e5cf8ab2db78e4bf87590064924a49)", + "P->V[6208:6240]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 191: Field Element(0x1cd308a37024f552f06bd1ad7d5930f32d7aec74afabc9cf3355729de9ee6b0)", + "P->V[6240:6272]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 192: Field Element(0xaef822a65a72097e25df0ee7ebdcb28320b11db5a994c27586e158e6dffa05)", + "P->V[6272:6304]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 193: Field Element(0x27f3ad616dbfebd46fbb3a6d6771a074bba5a305f9aacc5067fb4336bb968fa)", + "P->V[6304:6336]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 194: Field Element(0x7c52c5b9f0cb81770dc309be033a6f9245ba86447d2094dd9d6194c1484a365)", + "P->V[6336:6368]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 195: Field Element(0x229208e7371220c523fb2fe88ec5a38d23870f301c300169efac1f9cddba21c)", + "P->V[6368:6400]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 196: Field Element(0x21edb7c471267c366ed84a236db345d549abdce0da42c9af0bbae96c9236cff)", + "P->V[6400:6432]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 197: Field Element(0x3ab9c7092fee3b163d0cc99382cdae3c1a16985fc291a8783c8956b930244db)", + "P->V[6432:6464]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 198: Field Element(0x61745a967f634d79de90fac7e93c34415deccc4710c4a6a856d7e7d9aab7fda)", + "P->V[6464:6496]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 199: Field Element(0x4fbd8378e418e677ce958d8fdb7fa265d04a251b39f2ef4e03c3062635e759d)", + "P->V[6496:6528]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 200: Field Element(0xd3b687af59ff0d49ad5c9e4e7291a487b68204d4904f0f84a80db2b12244a8)", + "P->V[6528:6560]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 201: Field Element(0x2015b2d5ead21d6752dee4483d12121a72639566e2a9c5f73244de53ea5d477)", + "P->V[6560:6592]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 202: Field Element(0x2b26f5024e765cc99183f756367d707ba22ca2962d874b904e420ed6073f6b)", + "P->V[6592:6624]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 203: Field Element(0x7d296c78f622e22687f106bcfd1d7513019b9f8c4d616d87698a8db41f347b9)", + "P->V[6624:6656]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 204: Field Element(0x3ada2f64bb03fb51aa760273a7a9b2e351918258db85656b9fc157c1f4f3ad)", + "P->V[6656:6688]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 205: Field Element(0x65d9598d4e64a219360b98c3783c2a43fa4166de9aee44ef4f7d39f15a8d59e)", + "P->V[6688:6720]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 206: Field Element(0x6345d53299ed2b60eac16f6c13329dad12b277ed7d495cb2c6163b394dd1090)", + "P->V[6720:6752]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 207: Field Element(0x54b52514418edf5b2b902a6d67f3ba7f630cf16883c926209a55ec74bb49da6)", + "P->V[6752:6784]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 208: Field Element(0x501cbaef13dd58f916329b076393fcff2deed92cc1efb3c947ce40ed58b37a4)", + "P->V[6784:6816]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 209: Field Element(0x6177cc9d7eedda844f1ff32962450458f48470cecdf40768f36ff03562c1087)", + "P->V[6816:6848]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 210: Field Element(0x44bd692a75eb4920e85a1397e6fb48835e2e6fb3e02786544e7f1a1d937a2)", + "P->V[6848:6880]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 211: Field Element(0x14bef83227f72374a8d6a051edf94be941448e3024a94afb609d9e51ba0d2f)", + "P->V[6880:6912]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 212: Field Element(0x5e6ac62fe68f03bce2963662bbd6964928a1832ff35af46b7c03bedca5e805b)", + "P->V[6912:6944]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 213: Field Element(0x48e86eb4adfc940b7eb14ba7e5f32e75ebc413f2d7af4d3215291e27fbbc9ff)", + "P->V[6944:6976]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 214: Field Element(0xf51aa17e886bdb643f2b1fa7a8b99397c7a70eab86b43c6169d60ccf30c1fe)", + "P->V[6976:7008]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 215: Field Element(0x4790f3cceb89d78ac0f58c27503789c13e2fa8d603c21a8eed15e15c5f2353b)", + "P->V[7008:7040]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 216: Field Element(0x2d364ab707a1cac7e1a488dccd4a407792785239c0901971fee9525799d559c)", + "P->V[7040:7072]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 217: Field Element(0x706c35464b5a7a037fa0f72382915c36aeec81f5b6b4054f3dad0ab99f119fc)", + "P->V[7072:7104]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 218: Field Element(0x31fddde5dffdb253741d5ca74144d9a3bfa7ec7126ca8cc57a42566e619192a)", + "P->V[7104:7136]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 219: Field Element(0x134a01fda6b402a3044c2e7f0aaeab597a51fab8595042faf65e32373064447)", + "P->V[7136:7168]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 220: Field Element(0x73d86f52f98fe3de0092352edb0e0564ca2725a740bf0c100aa452991f8a68)", + "P->V[7168:7200]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 221: Field Element(0x5de1d3832016740d270ee7029ffe37e4dfd95f0d0e44efe974daff507c6d82f)", + "P->V[7200:7232]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 222: Field Element(0x4803b6165c07fd7cd6fefd2be0d5f665a76ca14c817ce6efa4ddf78b6b7b57e)", + "P->V[7232:7264]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 223: Field Element(0x378cf577eab60bb6a3f68498505407ea8ab200dbedb010cbb4c81edec938573)", + "P->V[7264:7296]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 224: Field Element(0x518f704a03ae38f4bb195efb9ef05864c2b7ef7f7091a0511e1a7c46099005f)", + "P->V[7296:7328]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 225: Field Element(0x47e311318e683edd0e2676d5662d2c5ff33fb2ee781c931f4c8d1cdb45321fe)", + "P->V[7328:7360]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 226: Field Element(0xf45956e0ec71389ae02d8d597117da4f3c3cf8b0384d2b44fbe9f9dab37139)", + "P->V[7360:7392]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 227: Field Element(0x55d00a95b4aa19e1b0ae44bbb188805a8cbbe0f7ed31263ac76db67133e7d61)", + "P->V[7392:7424]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 228: Field Element(0x53dbb9d62140aa141bbaab081405ebac0a78c2a0d82c4cd7ead10cc3247e168)", + "P->V[7424:7456]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 229: Field Element(0x32a918ffd7fe121450f19ded56db121b870b0caa66088693bf648e7f583c6a1)", + "P->V[7456:7488]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 230: Field Element(0x58ce90f748a9c0dd799659d21abcb533dec230874e29c5d1385889d24e1237d)", + "P->V[7488:7520]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 231: Field Element(0x1b184ffc4393aedd1c69bfe5c26d970cf5f8975ce33476b45ccc7e9f8d5465)", + "P->V[7520:7552]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 232: Field Element(0xef4a516e51dc03aa88f09b8304898505bb9ac0d05711ddda65429ed3094130)", + "P->V[7552:7584]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 233: Field Element(0x3a95fbe28686c1dd5b5ea4647d2d1bab86b86dd6eadd698d9e67fe353d8641c)", + "P->V[7584:7616]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 234: Field Element(0xf59ecf53b9c9ca9be6f6d2941329fe73faa529db4f21b155c56183cb2e1691)", + "P->V[7616:7648]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 235: Field Element(0x7f50674d07815546fc18040a1f394510edd0a8ed144c3bf6edacf41fc37aeb3)", + "P->V[7648:7680]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 236: Field Element(0x4cbd7d13db18bd6b941c2046a59d6525e7fa352f9fe2595ccfb758fc3dbfaa6)", + "P->V[7680:7712]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 237: Field Element(0x7f8294b5ce4403ba371e50bf4d7e10e9a937f7151132f5dc8d96109f967e09b)", + "P->V[7712:7744]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 238: Field Element(0x1aea412fdb57133e6353156584de3eaa13e3a0f4beff3f17c90c6f3fe2b5a44)", + "P->V[7744:7776]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 239: Field Element(0x42273364dbaa4f289d0e7c231841fee0bbc5a1f37b5193a4b1181b75f516ee6)", + "P->V[7776:7808]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 240: Field Element(0x28b3ba9036b8ad5f4b0b82628f34fae4a1b0a1f820b99015f33e50ca8fe84e)", + "P->V[7808:7840]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 241: Field Element(0x5dc6f4b3192366fb78f96a1587bb1a25d1a8eb64a2848408e49564ff01fd0b8)", + "P->V[7840:7872]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 242: Field Element(0x773a3aa8e02b6f914443af38340438aa93a610672531e0cdc44b8f73b502f91)", + "P->V[7872:7904]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 243: Field Element(0x4096b8a6d5559d48da217f824591ee266c7c1dc07b4ebb71f812f70167d0e66)", + "P->V[7904:7936]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 244: Field Element(0x1acde2796fa1e2c13018f6db4746d9e91462923bae7447862d354a68ca635bd)", + "P->V[7936:7968]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 245: Field Element(0x3e509c2d20a23786bc41334d9641e4556fd3b124f2acf88a3b05751cdace79b)", + "P->V[7968:8000]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 246: Field Element(0x478a09ff8d5b81cc728b4a10997ac6daa865805f57e143e5608fd45d5f68558)", + "P->V[8000:8032]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 247: Field Element(0x1430af628f4ad43379c880a21d11caced1c45a9689eb0c6edd7aad5359ba33f)", + "P->V[8032:8064]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 248: Field Element(0x57d74704564485ed220e4aae6d5d8a379d3908ed37b4d6bfcf2c3fbeb21b51c)", + "P->V[8064:8096]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 249: Field Element(0x7c1d091192443293582c39538d6a1dc70b27fda6ebab271331031b31f8bee37)", + "P->V[8096:8128]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 250: Field Element(0xbde9676ce28e3c0b680c07527d0d0e1746f10eec14d72d1f60f7a234144984)", + "P->V[8128:8160]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 251: Field Element(0x6b48abf9fcaf2ed14101fc33ffb434b9d5d947fcd1660373ef3e2de9f1deae1)", + "P->V[8160:8192]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 252: Field Element(0x4e3bf4f9958335824c0a93ab9976d955a29b98bcd2b25366d6abb5fab258431)", + "P->V[8192:8224]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 253: Field Element(0x3411eb6358b4be0dda6dc51e70e8fa14cfd5a8971d2070908e0034f20536865)", + "P->V[8224:8256]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 254: Field Element(0x3b74735a0dd9564c1936fd4ab95ca27a164294b8b79d03b4eebe33d7e345ef)", + "P->V[8256:8288]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 255: Field Element(0x202a3d598a62eda086a7da7a7aa1a9b526399e90fc539250b41961996468e49)", + "P->V[8288:8320]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 256: Field Element(0x203857f24d051f75230b0699c17683f999027f538d6918f91fb711c342fa469)", + "P->V[8320:8352]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 257: Field Element(0x40305debf0b93a032d4632fe8eea244f2baa7957794b9ba73313fba8f9ce22e)", + "P->V[8352:8384]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 258: Field Element(0x56f3f21a22c6c9e8508337bd43f766197fafd5b5fea552de4b0d0a0a2c1afb6)", + "P->V[8384:8416]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 259: Field Element(0x752593419f067da9c12ac5368d4ebfe5b010fe937682c9916a4d2825dd16044)", + "P->V[8416:8448]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 260: Field Element(0x1ecd6a61b1f75def6ec0772a0a38a61c9914a9f2d045055cdf20bf08d301e02)", + "P->V[8448:8480]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 261: Field Element(0x1e3a7310e1adf2e1f095849734569f0ab8389541129d8cd365ba05999f203)", + "P->V[8480:8512]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 262: Field Element(0x32faa83d63f8d596ddbe2180930a93d14a3e1eec163fd9a509104f28fd0f6af)", + "P->V[8512:8544]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 263: Field Element(0x3dfbd73a55a955a65a6f60edca191a80ea17f77cbec9e5c7ee99b1936ef424b)", + "P->V[8544:8576]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 264: Field Element(0x4fa42c0079f83117cc556b23120b88f8fb56d2e2ca41643f500a15d99f95ab5)", + "P->V[8576:8608]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 265: Field Element(0x5598c313eea2df1c7fbcb3f67f22ca1eae01912be590e808e3e552f86c47be0)", + "P->V[8608:8640]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 266: Field Element(0x5ceec28c24bb968b8b0d7c094f12b1d3a0fe4b17f9aac9dc9fe666968f1129e)", + "P->V[8640:8672]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 267: Field Element(0x1c84a867062fbe965c8c17f850fc134b728e0c7d8fd4fc4fa417390fd1f91f1)", + "P->V[8672:8704]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 268: Field Element(0x1a6c9a98222930d41f71485fefe2c156a5f3fbadafb335f44cd477b6318163d)", + "P->V[8704:8736]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 269: Field Element(0x34fac3420d1615a8e15b56bc747bf9094b7c8a9510d9f70fab2cfb8edd8f6e0)", + "P->V[8736:8768]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 270: Field Element(0x6c81ae964e2f0f35259d1ba53e30a589647127c1239fe2d1c824d9134494ac)", + "P->V[8768:8800]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 271: Field Element(0x2f2d8a973045aceaf4d68c5ad669da092f69e6eab5ef343cb3cef39acbdce61)", + "P->V[8800:8832]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 272: Field Element(0x60fbc6f8e5f5b755a1d9548b7ef08fd8a83611a414c1793e2d9f6df11bf17b4)", + "P->V[8832:8864]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 273: Field Element(0xefecb8e6bb912fd0131733978f7b56141a43e2400c6a6b2cb3fe22107f6959)", + "P->V[8864:8896]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 274: Field Element(0x4f71d0c902b5a93cb64d18f31d03056413761fe2cda28b0f1952d387783b11d)", + "P->V[8896:8928]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 275: Field Element(0x247a5546d0f702858d6890e4df35373ffb63e7c7b2526eeefa719fcf12f9dd7)", + "P->V[8928:8960]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 276: Field Element(0x5ef57eec21dec63b7375fdc3f03b5e6dacaa154665c70e6d9e60b381897dd39)", + "P->V[8960:8992]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 277: Field Element(0x35102c8e52af969618528584e065e0b30cfa85d460c2b4b43586161657663fc)", + "P->V[8992:9024]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 278: Field Element(0x34130a19723bddb48d7a107fe09ad17830324980d3c73ce3d0540397f89b9b5)", + "P->V[9024:9056]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 279: Field Element(0x41314a19921cd23d2b25b2b420fbd251bc9de11b8dbe15afc6cb4c0ba62b7df)", + "P->V[9056:9088]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 280: Field Element(0xee56c5d6856f3ce95e8f9d1293df28722da30a24f23cf0c6d5708a9badd5a4)", + "P->V[9088:9120]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 281: Field Element(0x2a95650600feaefa40a59d51c882de513e35b12b1e3e3e6d170d9310a085679)", + "P->V[9120:9152]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 282: Field Element(0x596fcfa9858857b29805e6d0e7723bb4375c4a1805b2ab3533f8e8a47481858)", + "P->V[9152:9184]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 283: Field Element(0x893f42645c7d829eda07518fee4553e9ec5fa85ea3da6b0d196ed51da66819)", + "P->V[9184:9216]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 284: Field Element(0x6b72a674557dab45fdaeeab3d54e3610050d0935038429fc5129fef824400a9)", + "P->V[9216:9248]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 285: Field Element(0x591175a1e769619d5c476212c17179d221af18ef04ee4865a346cabeb3e981c)", + "P->V[9248:9280]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 286: Field Element(0x77d285cef486a7ec2b7f6a815254f3560b8a298fb2060134b8c586149a44c4a)", + "P->V[9280:9312]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 287: Field Element(0x355460cff361b8dd11b3531f2d16145789b43958b4caf81967029b50dfdf8e2)", + "P->V[9312:9344]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 288: Field Element(0x6e006e785f5a10c5aa1ce7b358232c9bcfa85c52feab82f188413ca267355ec)", + "P->V[9344:9376]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 289: Field Element(0x3be00b55a6c96977460e0e2ddee1806f851968e6dd3a8c087caf2fac28bbe4a)", + "P->V[9376:9408]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 290: Field Element(0x37a3e07009d7480e819eef6dc162d6ef6c00d3fc02ea67fb63644315ebe8a18)", + "P->V[9408:9440]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 291: Field Element(0x33c1c537a1cc3a3b1976e06e7accaff6fde3688ccc530b92b49459e81317474)", + "P->V[9440:9472]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 292: Field Element(0xa0d4f6aac9892c982cdbdd87d1f4ce0a9a8a5fbc682c76985efdcd8ae75496)", + "P->V[9472:9504]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 293: Field Element(0x22c0a6bff03f03cdb3e4663cd51a96a4f9c10853f7ac01e139ccc9436889742)", + "P->V[9504:9536]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 294: Field Element(0x4f43b42277771f4af98dc73f7a81c8cc02ee390abd09d949f5c45a95fd05e05)", + "P->V[9536:9568]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 295: Field Element(0x2cdb38be62b7e5547dde3cead50428688c54afa3ba160e34334630efaf5441a)", + "P->V[9568:9600]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 296: Field Element(0x2ed86a2d7505bff946cdec856ef33213182df6991cdb3d3bfc58501e05f1258)", + "P->V[9600:9632]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 297: Field Element(0x4447b6f7e91b8fca90133bba18fb74945ad5acba5a5520d95aa225a224a73fa)", + "P->V[9632:9664]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 298: Field Element(0x51c0f595087666996f94c8a2931c1a77830ee6cbd678a6d75b3378d84e182a2)", + "P->V[9664:9696]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 299: Field Element(0x74afdc6c9f57fca194e6d04b67f20450305e549e0fd908e7149781240da1d94)", + "P->V[9696:9728]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 300: Field Element(0x23e216a0850a62ad54b08acb9a81b7a51cf9a7bbb2829dc10d15ab755d3817c)", + "P->V[9728:9760]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 301: Field Element(0x1330bc434a0abbf931a203ee184cd428aec72daa58535f334ff90d6e420addd)", + "P->V[9760:9792]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 302: Field Element(0x2d95d7b16e434d84beb0e1f942249585c1b5b0e991fc26a622e9b8647157d7a)", + "P->V[9792:9824]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 303: Field Element(0x1e4746a1db42cf297295f356e9a206296aa79a1985212fcb2c206b24970f03b)", + "P->V[9824:9856]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 304: Field Element(0x217c4608fb050b0fd20b9072c93d74e284ffb0a2e9886d7eb613edaa82cd700)", + "P->V[9856:9888]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 305: Field Element(0x79933f58bbd7c5dcd78be6b8c853397e088cc39290cbc901c33023c13778334)", + "P->V[9888:9920]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 306: Field Element(0x2de936a15406317b957f1d507810ac8c4d0eb0ca4ac53167a9d787cf26434f6)", + "P->V[9920:9952]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 307: Field Element(0x70e2de19c8a66e6920cc9715bb75507914741431f6e5c7795e80354cef9c235)", + "P->V[9952:9984]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 308: Field Element(0x5490d591adcff37e986b22d910d584e21406aad4ae67e543cca56dd2eacb961)", + "P->V[9984:10016]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 309: Field Element(0x3d075b2a5f224d3eec1d8415213bebfa57ffa98021bacefb2c19b551d33de36)", + "P->V[10016:10048]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 310: Field Element(0x11e8219115db37fb89357c1ed74d635adf3a63b1440c193200047be5d3d0e67)", + "P->V[10048:10080]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 311: Field Element(0x71a30df173356d3e639173c69bd90b0c9589e579a48ce1a6526348cc46b698e)", + "P->V[10080:10112]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 312: Field Element(0x354870644fb92f31c03c506c1644f7c8cc31dc830e7a84b621a48919fced1d8)", + "P->V[10112:10144]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 313: Field Element(0x22fa62f00005d00421c137366797ce8633c52f62de270791ee0aa7210b940f7)", + "P->V[10144:10176]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 314: Field Element(0x65433f1d7ca62d302b85c3d07b0f2f2bdf21b8d299228dca3a46320c2ab16e9)", + "P->V[10176:10208]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 315: Field Element(0x70024bb0a8b13c7b481e4aa88cc1a5373a7ebbbfa440921f63e324ddf4a5487)", + "P->V[10208:10240]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 316: Field Element(0x21c8b175d2fc3e7195c1d343bbd18b1fd7b5a79417b5816b9723f7181e524a5)", + "P->V[10240:10272]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 317: Field Element(0x67f42266914882786d3d16c6e3827e2b978d731532349616cc53b442e8f2078)", + "P->V[10272:10304]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 318: Field Element(0x62c17ebc4c5bffbc5f33cf3e1d322ab3e1d14701bde426ba90679231c6d2e5a)", + "P->V[10304:10336]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 319: Field Element(0x5f41a81a424937bd7d9783cc51c7d190b78ae79a858d18350495ed1e1622efb)", + "P->V[10336:10368]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 320: Field Element(0x9475df3ef2d0f2f89a3cba093562eb83aa55d2ad5389ba3ace783fdcecde42)", + "P->V[10368:10400]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 321: Field Element(0x613d0e685c0f6ceb4e0396c8654c33c98cd9f2e5654195b347afc2c18784cf2)", + "P->V[10400:10432]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 322: Field Element(0x41c5c038e93dfede256668aee05a36c6d0d765065ab44cd3e4f0714bfe4e617)", + "P->V[10432:10464]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 323: Field Element(0x2e84e3320f1a0c6cb01d2c4e3994e703fb362d0123b628207e3f6897c997ca9)", + "P->V[10464:10496]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 324: Field Element(0x1bd04e4f50c2ef1c885a806bdc9822477c33f7e3f0345013405948c21c6d74c)", + "P->V[10496:10528]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 325: Field Element(0x1d45de8afe80ade099cb2c8c87f537efadca836d6a85138b08f8c91f2f3e21f)", + "P->V[10528:10560]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 326: Field Element(0x3268beeac4b8123cb40548f9cb4ded4af977a05218a85d860205991013640fb)", + "P->V[10560:10592]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 327: Field Element(0x714d8bc8fd963ce146880354102f69d1e696be27d46d26c7d4dd6f5576f1926)", + "P->V[10592:10624]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 328: Field Element(0x21c11e7705ad45da311fb03053cac2d22892542a1707a6ef45f52fb7e6b31af)", + "P->V[10624:10656]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 329: Field Element(0x27f596319814755a0ef98ff88d650ce7af015a0aaebf35b05d95d0d48c027d1)", + "P->V[10656:10688]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 330: Field Element(0x34d3e5025b11cec88795bdbc1d9c40122c0f2c94c6dce4fe6ed4899367c3f61)", + "P->V[10688:10720]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 331: Field Element(0x79fac6798e53be4be95e4fda0b6e6a292f876f9cd464e8c342f9f82da385fa2)", + "P->V[10720:10752]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 332: Field Element(0x2663a7c332308483a41259a5b682e5d1ce84eb16016596567a79a48b1bf4d1e)", + "P->V[10752:10784]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 333: Field Element(0x553db187d1345696d74d16b9b5acbdad04a9b62edbd220fc4fa04f54d2968b3)", + "P->V[10784:10816]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 334: Field Element(0x6c0a6a94149143ff54bc4a23c75855f6c9f222d1ae69fb69c199913d675e7ae)", + "P->V[10816:10848]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 335: Field Element(0x422a4475b3c3874081c38ecba9e116834d9f0a1ba81b0ce4a57e71f6f3a955f)", + "P->V[10848:10880]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 336: Field Element(0x78703ae31921abbe9ce849214a4d24734fcb87863fa7ec07933cd309bca34ec)", + "P->V[10880:10912]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 337: Field Element(0x730bb924096b60fafaa86df211567367f7c848821de63e92f83ef6b1ee669c)", + "P->V[10912:10944]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 338: Field Element(0x7da8d085ce1c8c76b14ffbb289590adf14a1c071428b9cd25c5b954f7baf87d)", + "P->V[10944:10976]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 339: Field Element(0x3a6cb31d005042c4a4020ff39902290547bc506e2dcb8fa2579133df0c42a8)", + "P->V[10976:11008]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 340: Field Element(0x3e434131abbef1405cf2ddb0aed56c3890c987385e0a459a39da50a4c629028)", + "P->V[11008:11040]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 341: Field Element(0x4ff114e0cf52c42e339a3dcab49e86dac84123783dde8b709190e1c9880b35b)", + "P->V[11040:11072]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 342: Field Element(0x4a72795687c60e13aa73a2ce905398a912d5273d2897715816ff60ca3b43b40)", + "P->V[11072:11104]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 343: Field Element(0x738eed0a48d896e554cd6b92e3f0d1da015d12c872a3bd36c4391309e3ae9e)", + "P->V[11104:11136]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 344: Field Element(0x59e3a59df2556ee0db6a7cb6350f4430cd30e931ed434c27f93ed48617e041f)", + "P->V[11136:11168]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 345: Field Element(0x200742040548accd23f3caccf9a838ab3bec182862f3d6f78be7207f5805136)", + "P->V[11168:11200]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 346: Field Element(0x4b69ba014e01a8ecf9b4aa938edcdc41ba6e2d679fa9ac9352769878bb86040)", + "P->V[11200:11232]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 347: Field Element(0x63060db20fd7cbc2ffe6a4988010f525c4085b376b06a65c11d2a9e5cb66fa4)", + "P->V[11232:11264]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 348: Field Element(0x5ec4ea410888643502c17144696a166a06ce854890be862c5473e979e73adc9)", + "P->V[11264:11296]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 349: Field Element(0x5adf23113caca47ce9085c1a468b8fbcefd647bd24bea5044860b284ec09518)", + "P->V[11296:11328]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 350: Field Element(0xeb6a62e721514e7b1fcda61312a02c2d5a24a38ad27b7b983a7396e07cb4d7)", + "P->V[11328:11360]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 351: Field Element(0x4ff0885a85c06fd8f3b9438bc5efed6aa1d304e2d85e1632eb25825d8f8844c)", + "P->V[11360:11392]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 352: Field Element(0x34cfe1d7a7d10b4741a8fd0fefcee359bba9cb09c7e098cccb481575e88315f)", + "P->V[11392:11424]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 353: Field Element(0x15beff7f5a93d58c9651b9f6f701875f529a534ad26b889d647c2ec96b28cd)", + "P->V[11424:11456]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 354: Field Element(0x4351e196b241fbb328ecf3015061e5f1638a3254608e7adc31932b2f7f9180)", + "P->V[11456:11488]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 355: Field Element(0x26eec547466c95000d5f4cb6623e22ed208f88cd279a95448da764c487b184)", + "P->V[11488:11520]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 356: Field Element(0x6b4dfd6d952641598be642b7dcb0443b803eaf7f3ecb52339f68ba00bc5e213)", + "P->V[11520:11552]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 357: Field Element(0x313719782f38b1efa24c9fd6f0904ee99c7df4ff197290cd25dd8b26ce1f2fd)", + "P->V[11552:11584]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 358: Field Element(0x49e97cd15633e8a85f1d3c114d0f1d05f9b8f1e28f1aea77e431f2795baa7f5)", + "P->V[11584:11616]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 359: Field Element(0x7ca64ff2a1942e32fca64b1bb6af95ccbfe771a3265147bbd8a2d416077f2c6)", + "P->V[11616:11648]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 360: Field Element(0x6d816dab7920fe5e356ec97176477ff976442b4fa654acbc09c7a17ba8a96f6)", + "P->V[11648:11680]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 361: Field Element(0x47b3dc21d96f11c60805b503c720dfbbfe8358186dd04f1195506d71a100adb)", + "P->V[11680:11712]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 362: Field Element(0x908c635a9728c82f0f2e5f492dc31df93f657c4a61d61c931b56e061201a8a)", + "P->V[11712:11744]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 363: Field Element(0x307a8bd776b7d0759edd13bf104453b6d6016f19d5450791416dc1a6c2fa080)", + "P->V[11744:11776]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 364: Field Element(0x6b4ff73346b01c70e829b673e7e764d589b9fd8597792a84fdd2eb1e25e4590)", + "P->V[11776:11808]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 365: Field Element(0x750c05a84dc2df9ff6bb9fd3c30d2d3937123a2fe5ffe496ac69311a79e4bb5)", + "P->V[11808:11840]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 366: Field Element(0x1eba3297d3239fbdb57d3d0091b81de41e6d4bbdb065412d5d7639c7581547f)", + "P->V[11840:11872]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 367: Field Element(0x30069898fcf22ee6dba129aa4853923a8baf8e83acd259adcd0c029829e7227)", + "P->V[11872:11904]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 368: Field Element(0x31e348de60b29878fae13429fd768225fff01a46ccf57eb2c5eb64260ccd28f)", + "P->V[11904:11936]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 369: Field Element(0x339b3751c5e6c7bde88fd2d7f206d9aabb596dc507640e607c5d1bab6989355)", + "P->V[11936:11968]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 370: Field Element(0x133b3d24eebaa8bb420dddd3568d4a3efb30536fcee3b4e67f142a7a5a4c4ff)", + "P->V[11968:12000]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 371: Field Element(0x6cdca28f8f088c3dbd78f886eb4e526bc2980bf6a453d3ec844bfa1757b7106)", + "P->V[12000:12032]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 372: Field Element(0xf7248ed2b2db16d80fae60eeaf99095b5d8f23c4069ef0add0fb7df6079fbe)", + "P->V[12032:12064]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 373: Field Element(0x29c546c46a176162942c0bec8caae74c2f41308cbba496587823000e9f83286)", + "P->V[12064:12096]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 374: Field Element(0x4a7247f4bd58af63a467be9d4e57844a8b22d969941620cc01f07d26aace7ba)", + "P->V[12096:12128]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 375: Field Element(0x439f0b40f4ce247151314d2a7e0fde6210548d60fc28c706e3672783d9b3a94)", + "P->V[12128:12160]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 376: Field Element(0x339617a7f532f343fd51ea71a0788c53bee4a8cf6c0ca187f392a883575ac16)", + "P->V[12160:12192]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 377: Field Element(0x3f0c9d1dc40d2c0b29641786863341617105e3120a9900d3fddc7fbc1345ea5)", + "P->V[12192:12224]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 378: Field Element(0x7ff9e54dcc69f7fdf403798d4be43296470cdac54fe2f7c766890f7e64aac37)", + "P->V[12224:12256]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 379: Field Element(0x487de89356de5c8db095eb79cdf44f9dc311dd075b071f18cc1f7b4a0d9e3a8)", + "P->V[12256:12288]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 380: Field Element(0xd670d04e8bc0c9407108a0c6fda051d13fd92acc410e1a19277bf00794588c)", + "P->V[12288:12320]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 381: Field Element(0x7956bf606015f86ae9178f7c8e511f3c5b0bf48a57c7aa7d1d08d025a307d39)", + "P->V[12320:12352]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 382: Field Element(0x5e54d40b5f06490d6fce5f6bd165cbb7d3f94d74804265b745ad6dcf5399d68)", + "P->V[12352:12384]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 383: Field Element(0x76da79b5abaf076bb9e0eb4d8b02c9b1853349a5f5c276c195468b54ecaffaa)", + "P->V[12384:12416]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 384: Field Element(0x7b3be24821ba5eab18519fb6baeadcbf67acd155292f6713e32cdf683fa5268)", + "P->V[12416:12448]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 385: Field Element(0x33f50b9ebcc3aa48d0b3e94646b2a7405215e7c23ba35a9d2c5c4f8c57491bc)", + "P->V[12448:12480]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 386: Field Element(0x59ff77345f0921ee17fc289342635dd64732691814298ccc1b6ec8f6c11e834)", + "P->V[12480:12512]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 387: Field Element(0x4ef5a1c2ef8630335929dd908b0db9d0e5542c49220d4f9a6912e90c5bc9b1)", + "P->V[12512:12544]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 388: Field Element(0x44ce62190029b5d0cc0d12b9d3b484587d06f458f98a572ccc64383d106ed6c)", + "P->V[12544:12576]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 389: Field Element(0x40727440dd831f9c9aec50de2774ed5b481c8f2aea89bd9824ef183a46a257e)", + "P->V[12576:12608]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 390: Field Element(0xbd92f182777f53734f81bc17fec9a9e440dd313d0e5107394a8cc49e1546b7)", + "P->V[12608:12640]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 391: Field Element(0x20dd9c020ca926fe6dee86f9758a85d94d345fae69f7d9a237c7e462e8a4aed)", + "P->V[12640:12672]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 392: Field Element(0x39c043ac26585e481faa4e953f8abc5c33676704e31cd3572238ee9bedf7990)", + "P->V[12672:12704]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 393: Field Element(0xb88f4e56080d2d6670100292cb19f5cc16747a430c803466b42c7b9e86076)", + "P->V[12704:12736]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 394: Field Element(0x64b44ff616f7bdd08c6553cb543f1f2a494749d9eddad771032970bb293a0e8)", + "P->V[12736:12768]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 395: Field Element(0x342b3b6d7b0c63eb0a86a166d6506d342d31a2836bf93732a9a372d2a3fda8b)", + "P->V[12768:12800]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 396: Field Element(0x722fbb8e56437f2295d10ec4e71b6224d5f80d12e1cb1f23179da219f99d040)", + "P->V[12800:12832]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 397: Field Element(0x58c054c4d731215722a83bfe89926ae8b0ef58cdf2c27244e4399d2c7066ead)", + "P->V[12832:12864]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 398: Field Element(0x10c87fecdbf4bc7e9ab8a1d75be181b37baede6cd516fe101ed580d36202ee6)", + "P->V[12864:12896]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 399: Field Element(0x6e92f243bdba0ee0e4efae01ddc06abc676034a9c30a1af0c182f995e5311a9)", + "P->V[12896:12928]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 400: Field Element(0x224e3764d1e80677a1218c7942b4de0219b002c1ce1f642738bbd56f436db5c)", + "P->V[12928:12960]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 401: Field Element(0x70bd4fdb8d7137dbd1c165f0b9995442cdad025012f6556fe2d55ce2c8275e4)", + "P->V[12960:12992]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 402: Field Element(0x7ceaa642bbcfa3b469db5d7ddd5cd93d53518e7c4975aa81c945d114914856f)", + "P->V[12992:13024]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 403: Field Element(0x186c901109a967a5d2397336dd827b6453b0665091e33a8b979ac49270a0ba6)", + "P->V[13024:13056]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 404: Field Element(0x2c10c08a0864bb0981290a9d0850589d651d375b372a07e1d3133db73052144)", + "P->V[13056:13088]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 405: Field Element(0x6c968037b103d70d7d80d4a884da77b33c64647961883036e22c42f58a09e3c)", + "P->V[13088:13120]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 406: Field Element(0x41d15c8c2176a125dd64a6d07e56e2024e99c92b390263400414d10347fa97e)", + "P->V[13120:13152]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 407: Field Element(0x7c3f2b649a5a0757e269dcff16989b64036cf31c22c4b1a48fab8ae72eee89e)", + "P->V[13152:13184]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 408: Field Element(0x5f8a560a6d1d3fbfe218b739cf32127b6cb1fd960cbe385065d2438b7bd51e5)", + "P->V[13184:13216]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 409: Field Element(0x22ecd3c8a4fae119d364d24ace6c857ef74743c5c6b8dcd5129fa2efe4ae3f5)", + "P->V[13216:13248]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 410: Field Element(0x5d00ac8d613cda0540288ef41bc25af8b5999973cfc3a7a95a7168efb432d65)", + "P->V[13248:13280]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 411: Field Element(0x1e21dccd3b8ad41668240f210ccb2c2754169dcf816ed86451569d45aae1521)", + "P->V[13280:13312]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 412: Field Element(0x58ea861210be22f4e61080e6298f43a8e7f43690b0cccc61fb64cc22624f044)", + "P->V[13312:13344]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 413: Field Element(0x19184dca937eeedf35d6975cb5fa17f20c4f16e2de6ab9dc2f7f073fd84194)", + "P->V[13344:13376]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 414: Field Element(0x6477b3e34ded1f41e8bb1cd670008640eb14f29e3be079eab4b5b84d06e4acb)", + "P->V[13376:13408]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 415: Field Element(0x5b625ed7195ba79a317a62ca02fbbc549799683c7a3d3821afafee74ee9d239)", + "P->V[13408:13440]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 416: Field Element(0x1e920bf788ed204e6eee4e06b659bcddd91f38a5daa4c94080af908fb2d7999)", + "P->V[13440:13472]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 417: Field Element(0x3e1cacf6361fb5c269193d84a934db308251ebe1db45aff9cdcad841b132b08)", + "P->V[13472:13504]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 418: Field Element(0x2643aefcb0e252148c93e661eb862d8eef9a7aec36cb8cd9046298d8d8980ce)", + "P->V[13504:13536]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 419: Field Element(0x4f85bb6800b72155927c3e7a90966d0fe48f76012b80b85a0bc15fb00607010)", + "P->V[13536:13568]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 420: Field Element(0x54cd1fca2cd1bf4ce1a83cc07cdc88f5ef50f92b4d92f965c8b2e7e35d8d999)", + "P->V[13568:13600]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 421: Field Element(0x44e0953f08e05d6becab1cc7011cbee9f278be0891926739e09af450dedbc3c)", + "P->V[13600:13632]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 422: Field Element(0x53d20f1f4a3b896affb6986be74fb5af96c78c62a88def4a8b20cc9a2b677f6)", + "P->V[13632:13664]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 423: Field Element(0x714b295d149fc21f04ff6058b7ea89c2c935715e8d3f07f1d044297d68b274d)", + "P->V[13664:13696]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 424: Field Element(0x3aae5921dabf224ce50d4512bc68330f683030b0dc5b03988515b363a554d9c)", + "P->V[13696:13728]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 425: Field Element(0x4fd53b8343f89f33916981ce986661bf976ff716b42583d6492fcdb61c79543)", + "P->V[13728:13760]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 426: Field Element(0x4b9822676eccf0cfe00b74aa0322a5ebc9eb2d07f887da096bf13c1aa416764)", + "P->V[13760:13792]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 427: Field Element(0xe7b6251f1c144d1b1bcb54c15f46aa54e3e4b6b19e574215fda6be067e1043)", + "P->V[13792:13824]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 428: Field Element(0x3d2b679b57a4a41baf74e511ed8067b6a79dd63f43c4d0d0f6388e78c033448)", + "P->V[13824:13856]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 429: Field Element(0xb5b5aa6ae3188cb492bc24a67b61614ef972cd7bfdc01b67bf7eea7174d2c5)", + "P->V[13856:13888]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 430: Field Element(0x36d54e37d9e7aac04296bb43bfcb0d3ec805445230574a195309bb4b8341389)", + "P->V[13888:13920]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 431: Field Element(0x3d93003caa42d6ccfd8e3bc21f9c5166ebd1a407999f5e8b6945459ae481463)", + "P->V[13920:13952]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 432: Field Element(0x72e374d69664fbd2877093b17b8aae69e54dd0ff3762575e1718cb3a7811e97)", + "P->V[13952:13984]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 433: Field Element(0x54d56832efa7f104a23d650ad771fbea95ad10e13436f5d9d31ce26e75c11e7)", + "P->V[13984:14016]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 434: Field Element(0x301de639fcc05a2ca4408092fe376b1f97d58858d228165e5699df8279d0d00)", + "P->V[14016:14048]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 435: Field Element(0x135b996fbf2772bff868202957fe2c14a0317deeed6bea1c5c8db44e8949acd)", + "P->V[14048:14080]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 436: Field Element(0x9f49ca83f6d1c20b08ce459557fa8dd8180937c31b26f9f5548132c58d7c39)", + "P->V[14080:14112]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 437: Field Element(0x46c4e893ed42381d9dd3c20c47802f3954c468c6f72c512eb8fba7c023a9b48)", + "P->V[14112:14144]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 438: Field Element(0x3e2ec9d78035cbf9ff6bbc65a736989c4616cb4a8e97fdc6e3a98778b033949)", + "P->V[14144:14176]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 439: Field Element(0x73fd4e09ed5803bfa92ba08516d55bce7ab181c85d5aaf242b224d6d0475cb1)", + "P->V[14176:14208]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 440: Field Element(0x196ea1a175dc32b0e5a412f02ddd8526737295626872e3b6d2af186737de4f1)", + "P->V[14208:14240]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 441: Field Element(0x1a4cb8d838feb2b0448d832577ca73c30a1a9cc564dcde24a4c74cb505b928d)", + "P->V[14240:14272]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 442: Field Element(0x4b240ac68308e69fa4fcc4d9f07ae28157f0c7adf95d6f21fae3d8b500ef293)", + "P->V[14272:14304]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 443: Field Element(0x338cf1a225c655d61a157acdf3303be43260843551d52615113ee1d342f88dc)", + "P->V[14304:14336]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 444: Field Element(0x43b8a388b64fdff40fe3ea498b7690842c932656228d20a55d0cc1bce407871)", + "P->V[14336:14368]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 445: Field Element(0x6d254e0239263fec27652004672a4b40ef24862a140fc919498e1e5ea61d61c)", + "P->V[14368:14400]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 446: Field Element(0x3d59cf4c08a970363dd0b5b72c60dc6704cf05e2bfcd3d331e5e71e7e680643)", + "P->V[14400:14432]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 447: Field Element(0x227f5c00e8f747b83ecb105c35bca5c658a1ef3cc45448e9133b8b6269f7b93)", + "P->V[14432:14464]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 448: Field Element(0xc44a5589da24203d8d78448a46e0d92bfd3c781cf34f1e5fe2293c24ff4593)", + "P->V[14464:14496]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 449: Field Element(0x6aee43a37165fcbbe1557fd0419447e46b9cb5dc740219ad3470c93b5550946)", + "P->V[14496:14528]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 450: Field Element(0x44655138bdc5a309d5c8542cff770b52a1ef4cf8bcd66e8128b8de102f9f1ea)", + "P->V[14528:14560]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 451: Field Element(0x7d5b609435fc1610b59626ade55873bafad4255109dbfaf025e1d2c25495672)", + "P->V[14560:14592]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 452: Field Element(0x6d6e575d6cba662817f02fde0a83e0616e090ce1f03f553646b189cbc6bbb74)", + "P->V[14592:14624]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 453: Field Element(0x5ca82059a9420761af6f935252448b741fa43d66553d8c8bfd86e872b94bb5e)", + "P->V[14624:14656]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 454: Field Element(0x66eb988694d8431c9bdd2b252b5828e0885776e3c5c6a61cef1c38a5f982d8a)", + "P->V[14656:14688]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 455: Field Element(0x72098effe70f4fb2d2fac167f0c4a08722af4fefbef0cfed9d86db1d61a9647)", + "P->V[14688:14720]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 456: Field Element(0x6d0e05cc6e9c94f8fb95be5e12e9805ee2613a78c01df6db38f7906ab15a7ca)", + "P->V[14720:14752]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 457: Field Element(0x639470baebd2fa0e2c6a4ccfeab2547bf760c79fbe166d70edf72c195cba011)", + "P->V[14752:14784]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 458: Field Element(0x65682e88563cbf8ce430ff9dd51dc4a605df493a683805f6d25f4b1015e039d)", + "P->V[14784:14816]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 459: Field Element(0x5ca7afe5fda6eb1e7df33ff3b1185b7bdb56d35c814378201c33f6a58743b65)", + "P->V[14816:14848]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 460: Field Element(0x73651f432a4ff17f6b910ce004d9f387189395d84e73d04864e86878e044dc3)", + "P->V[14848:14880]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 461: Field Element(0x6935a0ed15d19f0d325d9ac4ef7fcc92c9f835aae57870bb6a8d498e6238218)", + "P->V[14880:14912]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 462: Field Element(0x739932160edd0529f93292993a95578130cde1fe7e4f2a25e04e877b5ae5212)", + "P->V[14912:14944]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 463: Field Element(0x1b020dd0a40c63ce4a2a9a71a0746f9640ffe73093b6b9e67f04dc621d6e6e0)", + "P->V[14944:14976]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 464: Field Element(0x293c56c4448c3f1e5ba71626b63a28e4d190e4048da708da010e79f38bc0826)", + "P->V[14976:15008]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 465: Field Element(0x30ad4897cda98c67a02b70baa861a8da6630a4694bfaea8cc13c281e6577f54)", + "P->V[15008:15040]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 466: Field Element(0xb54d4b133f18c83aef6daef15a874f15c3149b4d4a770061c9bb4816e6ea9e)", + "P->V[15040:15072]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 467: Field Element(0x606d8540cdd3c2a6bae6275e657f2b9fa11f91ab7a21c6906f3a263209b8edc)", + "P->V[15072:15104]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 468: Field Element(0x58e4b734718b9a74258d15724e5edbc0381f1f750443c52029689702ad4a765)", + "P->V[15104:15136]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 469: Field Element(0x4bee4049fcadc6f4a62c2baa9da0acdccd1595ae90a8e497d77ed12d5145c70)", + "P->V[15136:15168]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 470: Field Element(0x6e544532f3e86aac3ca1124c378e3c4a69052e7dd8872fdbad3a6fc1834af14)", + "P->V[15168:15200]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 471: Field Element(0x72c105f0398d45ce55e8fd507a232c9bb2bb5f1f411a15148a409730fc7cc68)", + "P->V[15200:15232]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 472: Field Element(0x6c6fb1bb329a6ed091e0da8fac3cbd14598cb09a7dac8eb5f669155cd2506f4)", + "P->V[15232:15264]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 473: Field Element(0x7932354a424b3abef8eb2ffe7ee9971fdb41da770caf2f705850e0417645cad)", + "P->V[15264:15296]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 474: Field Element(0x3a1ea7d08a8428915925050caa7c240d86a7a2e954d9361943488b3c685651d)", + "P->V[15296:15328]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 475: Field Element(0x2e15f806361c35f99e57a8aae1eb20c1768dc1112b4e117dd255eee8a8b4db3)", + "P->V[15328:15360]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 476: Field Element(0x7f32c5131505d81cb6991886fb177ccd19e1cf95fec3a12a78f27d73c56736d)", + "P->V[15360:15392]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 477: Field Element(0x6fac477baf53f8c103cac97822f09627f50459c020945b2f7b75409f354ae63)", + "P->V[15392:15424]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 478: Field Element(0x5544d80b9b00cbdf82170dea3d38d14e96492500b796851f3e9f0a3c73a5125)", + "P->V[15424:15456]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 479: Field Element(0x2c5eb6e5846204fb87266bf037e3afd638b449bfcf1c2f0a5e1365d0840ef4a)", + "P->V[15456:15488]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 480: Field Element(0x7f9c43c00a008847da181c3778da07251769b56d848b94da56c5c195da1375a)", + "P->V[15488:15520]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 481: Field Element(0x701aaf93252fb693e2a3c3b86f3249f8d4d67609abcac53f1f68a9d8d5ed4c4)", + "P->V[15520:15552]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 482: Field Element(0x56d39b3dedd1129b9c73b1c40f3e68663accb85e53819033bdcf958ac551a8c)", + "P->V[15552:15584]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 483: Field Element(0x4a34ed06704e162752aec056e70136baf7307fbdd4c13099f811621f2067b42)", + "P->V[15584:15616]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 484: Field Element(0x12222d2deb47009feb44d947c84a10a1c11f0569408e8aed39099e61bf9ac4f)", + "P->V[15616:15648]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 485: Field Element(0x2e2890eed5875c10ca2968baf334c1089c7839a09e9c37d2d892f938b8cbd35)", + "P->V[15648:15680]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 486: Field Element(0x20f22ed0e416ab57ecf01fab5d6e886f58f846040e15721862640010d90ac73)", + "P->V[15680:15712]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 487: Field Element(0x4606ba33684fa776aae35579c7ab20be5acb521e6d8920b3d134d213ae974f8)", + "P->V[15712:15744]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 488: Field Element(0xcbd27750bdf015e3318b65bc281c01d81ec1342b6b4ab0eb21e0bc11477b8e)", + "P->V[15744:15776]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 489: Field Element(0x1295ced276b84445b8f0a60c3221cfa410f0894201299434e6bfa41d7991553)", + "P->V[15776:15808]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 490: Field Element(0x757e333d2d2e7c9b7f8ca20d074bb8a2725241426fe169e7e9039374e57fb50)", + "P->V[15808:15840]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 491: Field Element(0x3bb4e02e6b7790686ba860e90b6211f6398519d3ff75e39503641fccb8f3157)", + "P->V[15840:15872]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 492: Field Element(0x20b1610804cf4c3bea1998e11b1b295513e2755bf9200b3bcbb9c515e1a3d9c)", + "P->V[15872:15904]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 493: Field Element(0x3ca322781628b032752fc674003b66cfed89b53f3513a302e2c48945657da88)", + "P->V[15904:15936]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 494: Field Element(0x204f25a3fe709ae9235c8eb64552b8d80ce3e978e7d57bb8198269bf604b6ad)", + "P->V[15936:15968]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 495: Field Element(0x42405b48c2287305ef4c7a0b8b779650db9cce374dcff8691c990988a4de32a)", + "P->V[15968:16000]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 496: Field Element(0x7bd9d39b318996ad65fc4dfa65cb104435a1f2aa9a612f87a046c4423cb150b)", + "P->V[16000:16032]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 497: Field Element(0x4a35fcdcfeac6183e338957d6c31c06ab2d3c7f45e97d794949f9c4186cd0b8)", + "P->V[16032:16064]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 498: Field Element(0x6edd474e4e5c8a4152563e384542709940499bf7ce478ef0e4e7304bdd6b062)", + "P->V[16064:16096]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 499: Field Element(0x650d45d4d5d8bdf905c22d4928a3d7a896ae4a371204c695ebc4ffb27cc7739)", + "P->V[16096:16128]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 500: Field Element(0x28ac81071ddbd692de372c5521e63f05613d60c965164a97a6c8208e96f5329)", + "P->V[16128:16160]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 501: Field Element(0x2f7d586dba1a779fd394442e153fd708840a1a38bccd0160bc0cdf0669e40a6)", + "P->V[16160:16192]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 502: Field Element(0x1e37bdc2efce5885cd74118ded4c1e603bb83534376fe5d74614ff2c884cbab)", + "P->V[16192:16224]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 503: Field Element(0x2a55382dd46f4b1d8f1a449d983a10f15d818904c577e7f2d6a466e9178225e)", + "P->V[16224:16256]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 504: Field Element(0x48f72834d19c80c1f37a42b756d8f5f908363327ca73368330cd8fd4f7aff82)", + "P->V[16256:16288]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 505: Field Element(0x190e71ecf96052257cb9349ebc2740c89c8c1aff5fc1dfefdc865cb66e0e5f9)", + "P->V[16288:16320]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 506: Field Element(0x76ccf17c5ec357b31ff232ac799d7a37b6b46ac8ea0a5035eed2cd912dc7240)", + "P->V[16320:16352]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 507: Field Element(0x579bb06d4a983f27dd7b2da11ebba5022f3430f0611b2f1daad88898a1458e3)", + "P->V[16352:16384]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 508: Field Element(0x29bca2a06baa4d1f4dc22572cb4ec2d25ce5d5e25f5f33f4cea16a3c8bbaf82)", + "P->V[16384:16416]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 509: Field Element(0x6cfbe85e26dc00fe36bfb1270293b90d4708fcfcd1ca6065935ec2f04ef0e32)", + "P->V[16416:16448]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 510: Field Element(0x36af99f04ccd979a4a05bd72f29f82b8d0923e0a10ed563d709b12e6e97d945)", + "P->V[16448:16480]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 511: Field Element(0x473c5161aa41c985aa3171fa3d8de258ca69da339345640880704394e54eb8c)", + "P->V[16480:16512]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 512: Field Element(0x4846cc008aa7809caf3dde087c01c14e9b6226407e5a3897c8a6158b34df355)", + "P->V[16512:16544]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 513: Field Element(0x6aff09d0fdb4f750198e01eeb6cdbb4a9b34b9f7db1a788be6a1ff6551c7679)", + "P->V[16544:16576]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 514: Field Element(0x6cb919902432240c2d5dbab00ee4b18224c8fa314a810545e047d4de834a98d)", + "P->V[16576:16608]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 515: Field Element(0xeabc708a2e1f35ec652d789b9e6b6cf8032f9a8845edfb108eeb7be9700315)", + "P->V[16608:16640]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 516: Field Element(0x276ccd5bfc9e997df303b2bc0ea62f674cc2bf02392921d4afda1a9640ec0cc)", + "P->V[16640:16672]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 517: Field Element(0x3826ead8fa67e8cdfa46c0a59095fc37b441a6ef1928bc51eb8d963ca1da7a7)", + "P->V[16672:16704]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 518: Field Element(0x28dd92eb5453723d2b2332b19e64ba9f82bd467690c8e9e388a6521e847bdd4)", + "P->V[16704:16736]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 519: Field Element(0x28cfd372cca300fa070312be9c3590328ce7f12574c384a5cfb5027170370e9)", + "P->V[16736:16768]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 520: Field Element(0x49d00ec20aa81598ee33e998f8bdd717bdc4aff10f3bc7d06c7d863805df0a5)", + "P->V[16768:16800]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 521: Field Element(0x44d92332b5abdf77cf83fd559792024a9a35be734fec5f09db889359a350ea3)", + "P->V[16800:16832]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 522: Field Element(0x4df20d22e338c16847ad51dfff819e8af1cf122dd3eefc16102767fa008e886)", + "P->V[16832:16864]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 523: Field Element(0x2b3bdb73a1999a04fd56cb32c2647848769666c4a4d776cfd89e253ceac6150)", + "P->V[16864:16896]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 524: Field Element(0x383fd2aa7bffbef9fee63482a794975c99ea7063aa3a2814fc83ed4954bdf49)", + "P->V[16896:16928]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 525: Field Element(0x1ae9735277fbe9a032f4cbddd841e3366220c0c7f537503648198dd4bbca07)", + "P->V[16928:16960]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 526: Field Element(0x6c49e5692f157b9c9a1239a297b81b648a1b49d1483da715978327c402d1a77)", + "P->V[16960:16992]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 527: Field Element(0x28d4fd5d2e5446dce37e96836780af9b684b9aefb54f0193798feccf737f869)", + "P->V[16992:17024]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 528: Field Element(0x242200c011887776f775121e3b48abaffbb928bfcaabd2709cdc50ee3ef1f99)", + "P->V[17024:17056]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 529: Field Element(0x6366d6a1cf7600b0927df0815e808e422481d1022785204e778ba532ce72af1)", + "P->V[17056:17088]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 530: Field Element(0xfbf42665f7585ee8377cde0c7b302df983eb17ae61869ee66b6ec7f92ac094)", + "P->V[17088:17120]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 531: Field Element(0x296c83eb1310c6615fe30a0d210b5bebcfbd8d472a987d70743b509eda67db5)", + "P->V[17120:17152]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 532: Field Element(0x6c043ba950a9fb2afb56cadae88240b19e758de9c21b0ca9deebbc107f1ab50)", + "P->V[17152:17184]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 533: Field Element(0x6dd53143e29a47030fc976cb749d4aef4c6af72c94756ce283640e91f8951a2)", + "P->V[17184:17216]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 534: Field Element(0x561b46519d466968602f15939c06ea56013d717afe1aaaad4bf154199235d95)", + "P->V[17216:17248]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 535: Field Element(0x1e0cce23dd90bd8c9118739d459d123c12729abb314a12be7b8b92568083880)", + "P->V[17248:17280]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 536: Field Element(0x732cc34f3c076deca4db4e9e41896baea316fcc62c5aa6e9025a695d62718d6)", + "P->V[17280:17312]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 537: Field Element(0x79d8b963d9e365475f58d489432d9edf7a5681231d4ef8d95044e2c65c22dd4)", + "P->V[17312:17344]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 538: Field Element(0x7a5d2a1309b5e0399f40916efe226d019f6cba2ee43f912ee2bd5c2be100a72)", + "P->V[17344:17376]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 539: Field Element(0x737f6f1852cb6bda742f339da9655b44dc0db3c91f2b092faac6d3e69b17127)", + "P->V[17376:17408]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 540: Field Element(0x2da2bcf444392d30418018a8a8b299474b28f3506e91579a39a4196a77c6172)", + "P->V[17408:17440]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 541: Field Element(0x6fabd5e65bcfdfb0a717e3ff748f5dd08ad520c5248fc4ed3b895b10206d314)", + "P->V[17440:17472]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 542: Field Element(0x77d11b71801e14e8513398bf35b08f04e33d7dc6fd0f51269efcc15cf14a38a)", + "P->V[17472:17504]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 543: Field Element(0x22d39fcf3c9033f01acfe5cafbcac1a7dc400618484f504658840ed28baa34a)", + "P->V[17504:17536]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 544: Field Element(0x5e88dd15264b699be5f83331e301e227c8feb87c31fa05fadb7968b2b0f3c70)", + "P->V[17536:17568]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 545: Field Element(0x4da297cfaee8c0b12ee1e817262dc9d68a042dea821ad915e4d2e534cce22d8)", + "P->V[17568:17600]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 546: Field Element(0x1cbe5c20e7d2de7e5f774a2569194c63a7950ea102031d0880fdde997c66ddf)", + "P->V[17600:17632]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 547: Field Element(0x6fd35a7c913f4d3d1dc2da348825232603bbb9926ea504b71c7232ac56797ff)", + "P->V[17632:17664]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 548: Field Element(0x699ae74e3829483cba3da12be4afd19188c95ebb84169ebdc525feae436cdb0)", + "P->V[17664:17696]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 549: Field Element(0x447c0baf8efa0bc5ab2c26d03eebdc4d382b87f74b0385917619714eeca752b)", + "P->V[17696:17728]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 550: Field Element(0x1f791affbcd5516ea475512a706d4d3c5e6a59f9be5f96ed6a0701d6bf07aed)", + "P->V[17728:17760]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 551: Field Element(0x1c751038ee77003b804495f48efb682e515846541b1a1ba8e2d3bb3d552034)", + "P->V[17760:17792]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 552: Field Element(0x510a82ba482e9ec5a45cef57510ac224ab8159e48f03ff50437fa135d7a454d)", + "P->V[17792:17824]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 553: Field Element(0x2b1481c9419b61946aee3733ef67926ee0afda9e1f1a96520d616abe5c6d3b3)", + "P->V[17824:17856]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 554: Field Element(0x23f5f6272ed5bea46530100f1c5478a462c7eec414e76adc5d5aaf77fbb6962)", + "P->V[17856:17888]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 555: Field Element(0x72b6fe2c27f04a75819367d097e44ad3209588ce0d49fc3539304ee63cded81)", + "P->V[17888:17920]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 556: Field Element(0x6cff5fda4c0cd9ce6bc73d43fb6fb180ff97aa6e9f95ee458a8c5ceb2bba6c5)", + "P->V[17920:17952]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 557: Field Element(0x7238372622ccd15da97cc1f87599215e5c65d957e0cdb25dc7a9c30a9b30699)", + "P->V[17952:17984]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 558: Field Element(0x4ba7d60c436e1f45874fbd28c5a637e6f0473e56d2bf8c631cdffa9f1a9b95d)", + "P->V[17984:18016]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 559: Field Element(0x15d0f629d3686a979ad659b275f6f15b999cdc450f93f3c79b1f005efd7144b)", + "P->V[18016:18048]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 560: Field Element(0x63160f1b11745fabe3bb19b1ea3ae2c42bb9d387cbbc3301e17643e94c45259)", + "P->V[18048:18080]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 561: Field Element(0xbfe32e16171184792ae1b3f8259fdef289596832db973db29243aa982906bb)", + "P->V[18080:18112]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 562: Field Element(0x5f1cf7654b8c1fd0b3989c5485ce3594ca8d8e44409e5cc31c52ae5558d29fe)", + "P->V[18112:18144]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 563: Field Element(0x2d63dbf62fb4b287c08cb9a8fe54e61f51f7c0b5bec18c045e0c2f611afb4bd)", + "P->V[18144:18176]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 564: Field Element(0x7105258cd8d27654c4b895eb4d367b348f8cca13e97ddddf1dd2a719d52553c)", + "P->V[18176:18208]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 565: Field Element(0x1935f8e587c8b62d64d9da97bece959f5b8d12d1fd1383e0e3d50a68ef62ff2)", + "P->V[18208:18240]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 566: Field Element(0x5bb2a3eea6ba46baa700d7fd44e837cf8abbe2e6cc01a5ce5e3fcc95736688c)", + "P->V[18240:18272]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 567: Field Element(0x5ca1c30fd857af10c20c6f186f3db10542fb84b5a9ae7aa1ab8b6e982e40e4f)", + "P->V[18272:18304]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 568: Field Element(0x615387c63653f4bfb127bd8a020d1f82d8a3c40881489f493fcdb13484fad92)", + "P->V[18304:18336]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 569: Field Element(0x4cd20117fd010ce4233940266088d98e4f4c1c55510c20dc0a8ed8b315ef946)", + "P->V[18336:18368]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 570: Field Element(0x5655f121b78d6e924011c464957421d9e68b55df31efb98dbd7b192fd9eb28c)", + "P->V[18368:18400]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 571: Field Element(0x75b85a4c4db85819daed47db16d7a5ac71a62fab094b929a71787427c7693c)", + "P->V[18400:18432]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 572: Field Element(0x10d0cf0ec74c32552fab429568f869b5a63df4bb3e2c4a16f15267e56e19d89)", + "P->V[18432:18464]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 573: Field Element(0x2a18475489a7be2fc3b752ed46349bfbed18ce109db1800881498f27462c7d9)", + "P->V[18464:18496]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 574: Field Element(0x4ddeee711eab8bc473df4f9259a0041738779f1b73f824bd18f304de8a5946f)", + "P->V[18496:18528]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 575: Field Element(0x172e171b3da7eea8abed021ca2c55ecf2f395d457ed387f7d26736b82ac25cc)", + "P->V[18528:18560]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 576: Field Element(0x62c400e72b51af9cda60a0a00524a2344e811dc39ac42ec706a24cf4dec4a11)", + "P->V[18560:18592]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 577: Field Element(0x30dee9163252f0373618b9fcf757f919fc0afcf039627ecaaf2beaa92ed2260)", + "P->V[18592:18624]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 578: Field Element(0x782a83b8ecdfd4550461b9b0ede36b1f2f8165783fb64afbfa53ec500c3d415)", + "P->V[18624:18656]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 579: Field Element(0x4c2aec5556c15f47dc5f200f0d71619d57062fe683f61dadd9f0b1fec905578)", + "P->V[18656:18688]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 580: Field Element(0x734622333a503e6381b2afb06441f3a9f2b1b889eaa949995fe51219297ce2f)", + "P->V[18688:18720]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 581: Field Element(0x22c712ee663b6c87989a4d8ca3889e3591b549626e664e5444571dce4ef2f37)", + "P->V[18720:18752]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 582: Field Element(0x65b51bde65ee8cf8475959d684aa806d447e72bb53133beb1a22584a7f0b55d)", + "P->V[18752:18784]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 583: Field Element(0x34923d8cb71e9a7d83b51695e95d94e040d3f9114ae96c5d8a35f1494ae3e10)", + "P->V[18784:18816]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 584: Field Element(0x1c94b4adc66ed09d1fe623f8218cc173c686001bf0cbea69fc002737d4853fd)", + "P->V[18816:18848]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 585: Field Element(0x10d61654ebe60895f7eab9301617df5b26d38850fd50f57ecf910e9b92095d4)", + "P->V[18848:18880]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 586: Field Element(0x60e4d7daec1eb649d2c096e856684c0a7a88308bf47d55b3b7b0d7b4e7c565a)", + "P->V[18880:18912]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 587: Field Element(0xb5dcc8bbaad995c6ee27dca218a2b9b996655782eeb8a9b9730f823efdcd74)", + "P->V[18912:18944]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 588: Field Element(0x71a82d227f622869e7305609779387ad9181acd1aab0abc28e5abf6ee4cf65f)", + "P->V[18944:18976]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 589: Field Element(0x7e4de6e903bd1e5fee6725a49628ac70d2e0b52c2027fca50676fb8feeb5963)", + "P->V[18976:19008]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 590: Field Element(0x732976c8e843dbbd32bb1e0fca1e56d2b47086f1749a28414a1eb5c3a5eb42e)", + "P->V[19008:19040]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 591: Field Element(0x44832d103dd17f424f0b90a3ed0df8c2625c219ce9548d45d8ecdc87c993c)", + "P->V[19040:19072]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 592: Field Element(0xdc1a554ab2a4ea7abf27db066676f566cb5be1b08994b387d288132567eb3b)", + "P->V[19072:19104]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 593: Field Element(0x553124e49f655933d690ba6bf44dda046a0e5cd5c763ecc85db66acc8b79fd9)", + "P->V[19104:19136]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 594: Field Element(0x4a8bb75058726827ea9b31f7f583aeb72d83373b684cd32369e827629079d07)", + "P->V[19136:19168]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 595: Field Element(0x7f587d5727d9dfc0184b29f962a038a89ea933edc18ca613abefb1a1c39e27d)", + "P->V[19168:19200]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 596: Field Element(0x46102ac7a0a394de46f454c7e9c1c475e2ce56459c6a7d1393fe6864f3ea286)", + "P->V[19200:19232]: /cpu air/STARK/Out Of Domain Sampling/OODS values: 597: Field Element(0x62fd41776ddf30d1eccfe8adc0fc21e0d9d8f0cbe200cf7ba1f40d7ff725432)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 0: Field Element(0x6d48e1b91bbbbbd39e4fcc95b0692189c9c355f89dcae5ae7b815b36e4d7f5f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 1: Field Element(0x75a6ee670945d5c4d97f26a978f19b7f69d1f160954bbbf39b69c753074785b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 2: Field Element(0x37bec7b7111e7edb30e202ac5effa762543bcd579c13a714c3c15d8ebe50063)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 3: Field Element(0x7721e1bd5bc14fb5b97f563f19116cec68a96a055cc12664ddd25c9238562a7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 4: Field Element(0x1d12f591b75ad0f4a6194bbef7332b72d442524c33964e885d39d7504cd034)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 5: Field Element(0x812dda6cc6a5be2656cc8738bc5f3aba250ae2b6b9e5e91edb5d2094fbf4c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 6: Field Element(0x4a2452f6d775c74c38ba09970112da3be33ad62839de2adffbc7e7afba39ee4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 7: Field Element(0x281c0d165053f1e814f52aff0a7758113bf0dcede2cd957002760188a931a21)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 8: Field Element(0x5b138f0e4a3f32ce0b264e2626ca65dd49c98a5e9c92b5cb22d10e0ace2cc3a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 9: Field Element(0x4edbaf8f405c8706092bd6b0e171a8ee55c74953a2e9ab0356401cee3b5313a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 10: Field Element(0x47aace4550b8689b3e62edc80b41f1927742f4eb2229677e48b4badba7491a4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 11: Field Element(0x42a19e83ab3f0f0c41b5ff300f2f3cf637cc6ae91fb45d175e4810153b318a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 12: Field Element(0x49dffc40cd58f11574d647d819fd1901c1d2ca44993780d79ca87521b251fac)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 13: Field Element(0x4d99531aaf28206e6a7dd97fd3e7baef5e507d9c4c212ca750bc8d920448ed9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 14: Field Element(0x71f9d0815e7110ca50940a712d69b6780766bb5b80af8c406079e4ab6faba1b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 15: Field Element(0x1f002ebd0011b45b975767a8fb47aa3bbf0ce89b5197003b3720e87182393aa)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 16: Field Element(0x6e1f1c82d0923438db4cdd211c3f05ae555651973640d6d71e2dc7f49c0e7be)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 17: Field Element(0x25807626009bcfa0db6ba0361d88e6ceece2bfc63cdc14e980567cf89282c5c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 18: Field Element(0x70c00093b07e8d38d3175eee86852714aef6db838a79cc79a7fda2fe1c04b0c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 19: Field Element(0xc8c84ce6dfcac46791b11ae3054313ee2f868db684a817ef5859645e0159fc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 20: Field Element(0x6686d03e0b7c76b18bd65615af62c1510232ef29f38a6670f0c19787d3ed0bf)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 21: Field Element(0x2f2724b6cc6b527b5f776e451510df45de65f7b669f704210fbebaaa3c71eac)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 22: Field Element(0x8d407dcf57c69cc8b4ac997a76e386af3a7b338eefc3de76e5596342e353e0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 23: Field Element(0x19f4967b91e2c72da2114fcadc6353bef4771422b3b39bbc9871c6110415d61)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 24: Field Element(0x107266d2721ac419f5e6e35e08e234cc24b22bf58f8688e3f4ce9e3b17361af)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 25: Field Element(0x65c3be43823b178afb54714e22c5d09aa923bec6c4abc163268c4b775f27399)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 26: Field Element(0x3e938fe32d8f4f9f9382bed0d53579e4b493e7b705456d421b45e74f55df7d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 27: Field Element(0x29ecdc770781a1de4c79dabb4a0c9140a2714befdf49e92cce20464c0f220ba)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 28: Field Element(0x52afd6e01e5bdfd3e2e018d568c8751513fa029d0ccd15063bfd222b28efb64)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 29: Field Element(0x6f6b0499decdc547373b6f8bc57afca5c84edc965ff20bd446a9e838e30cfcb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 30: Field Element(0x4f4370b9adc8a7e06de792d02103b2a01d331378c771732f01888164ccbbacc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 31: Field Element(0x24308fd219e6597ff430b1faad9a59d1edcc9dc028155f97eb855e73b39deae)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 32: Field Element(0x77e945ff7b3120b2d95d19741df41b65f9d5fc6c8d6a473704fc4d8abd28a4d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 33: Field Element(0x3594fe1d7167f53d6e287acce79a356e231d74f41d893b483113550b0f5c9f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 34: Field Element(0x62ec18a584f94b53195b8c55e1b3a930b1fb71f38a68811b6b7a0bae3eb4fde)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 35: Field Element(0x14ce6b843e3920e2f23b8d3bf4c213297feaa7b17fb6fe95e4c46f3a73287de)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 36: Field Element(0x2673f3562878663ab28ebfd4001d2d032f7a1dc4272b865d139a2ace4c6a457)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 37: Field Element(0x7508161bfc63790d0e697e8c73c778b93c71a5217ba637a381c9ea327d28568)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 38: Field Element(0x1838e209c05be34a660125b85b127a6dad7002766dd5fcae8a8ddc4245f6742)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 39: Field Element(0x16521d7d0ac63eb06f15b2f3ecb3c5d117ea601332aba0248a31de126a058e2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 40: Field Element(0x7b3fdaea4f1bdb54ae6824d4af197854961cc70984471678d9cdfa89f3d4a1c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 41: Field Element(0x313824ec7febb25210e45d6262a8354b7b8950ac6dd390b03eb4f96f9a7f1fe)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 42: Field Element(0x5596a545f83a02f0f1dba208e7a80d941bbc4ac2f362efb017e1164c8112bfc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 43: Field Element(0x5fe555582a508dfa3506ad08d6ce1dcbfa7824ab87170068ba4c241be0bdfa5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 44: Field Element(0x389eecaa1621e15af41f190e2d7e7b7ef4ca74450b00e25b642b4ff6b6784e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 45: Field Element(0x3a506900c916a3f40fe3abd3186624c6d4765eba3551ef921e3107d861d805)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 46: Field Element(0x381ff966c3fc6f03f0d3126255197de3b19390eef151fd4b5a70a9a45d4da0c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 47: Field Element(0x79ec77c900088ba917c1658c40503b0b2c1234a7c02b344766b4b7a7ca16946)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 48: Field Element(0x4537a83cea03904c3690be2879842f7e41e8d0df0e0d67c7b4b86275639385)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 49: Field Element(0xcdf4e84b3caefaf387fb0f62ced48d40453e36ce94217c8017099c37e6cef3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 50: Field Element(0x18e61506ca2b3b41ba8be3c6eb6a7d01dc4b960c04932b145de48ef006cfb5c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 51: Field Element(0x11e2caa0641e44c63bd0bf9f9ebb466e457d920b433f4964b0b3a271b1173c0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 52: Field Element(0x130c06711e885a3eef4f5085dd01a0dc93350d43f927367f9fbc8688014aad6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 53: Field Element(0x4db538cf4b4774cf3c21883d426c855afbea21ffd314d518a6ad246979dde6c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 54: Field Element(0x31e5d10d4f690df0c54cea469decc94804dbb5b2f66586f5d881d291773c876)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 55: Field Element(0x15849196681788db332ea3a55eed839e7bf4727f8c8cf7a7ce0c81dbfa8df26)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 56: Field Element(0x3f184bdc18f2b63ee1696e41fa6a70cc2f7d915993ca953a5ab5ea1f14214b1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 57: Field Element(0x3f323af76a9af87ef717cd6542a0955c6a63ce98c4b951744f01fe06b03db9d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 58: Field Element(0x5c78296db4ac73da4fdeef9f613f1a4c849da3b597f376621b4b7414e735653)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 59: Field Element(0x4b50656042a9b51e6ae44574b2bf860a319c9130456b95e1a58e9755b3a751e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 60: Field Element(0x4bac52d31deed62ce4f04ac69c405290fc461a18d7deef5521c0c5f011a26db)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 61: Field Element(0x17b146ef07b1e550eeb0cbd4b279726603440d986c3c25b39be84b87bbe7125)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 62: Field Element(0x89f4be7e7734f60aded55a228d73c5b25025ac7248cb675631756814fc79dd)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 63: Field Element(0x23478522b4424e3ec64de051004396c7927f26450dfd1f51b3f901c5d323a5f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 64: Field Element(0x4e1eb914d2dba982c22a09a5c09d6519a1ab621cb21f31fc4ac68d1d60195f0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 65: Field Element(0x2aecf295f9e51443d752c570aa637fecf7d32cb9193fa0876a4a321eb1a4a2e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 66: Field Element(0x6467b097f3479c5c217d98385a353771ed3f90f9e42d24363261c132f1ca45d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 67: Field Element(0x4a70672449ce4b9bee508ec44a4efac318a3b2e0d980fcc768d8dff5e6dbe1e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 68: Field Element(0x4b1e15151f6adce9a34f71d44309d3d476b2db5edceab413b233365b374521f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 69: Field Element(0xe32ae91a5f299380f5f09a8b853ea35761da896a8c58a947c5c515f3f1da35)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 70: Field Element(0x2723c8ea49d8a2e5adfb94c5aef0d26d4753e3570fae69ac569d62b750f9590)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 71: Field Element(0x5a1b637978ea5e07d1179da4126bb48c9b941a0079c9234c5db7c7017392361)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 72: Field Element(0x8aa3ea72ee10277891d65ad5afbda54dc8b2da842ce640f081d8e26329219d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 73: Field Element(0x611856b4e17eae1f65e8a6ba47ee71f2a9f578c23252c50249c08ae5312af62)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 74: Field Element(0x78dd99821ef793a760af48f9498bf5aeb466e8cc4b40e3a628904fddf2b2d57)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 75: Field Element(0x4535a529bbfcd92e898d1068c9d3e86081ea1a353225b431e7f8db9c01e0553)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 76: Field Element(0x5d2e73d44855feaf6ffcab7b58ace3bdf91642c38b2ff47616317483d8c2ec2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 77: Field Element(0x22631425f4a446262a097dab16cbaa7fbbc5a6fccef38cc4133a0b2ea4c1f9f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 78: Field Element(0x436d438e4c7ec6471475a8626e11404a3935263a1944c9d06e6b93e22ef8d91)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 79: Field Element(0x1fd32a8ebcc7401b02cba2c38ded25a440223e410f7b092fc014619280aafff)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 80: Field Element(0x3e8799a54cdc1a89e31db63a3ddb6597c69b36854d61b63eea8f5c6286fb34e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 81: Field Element(0x2f314f0b8754df1056e9fbf2ffda46c7adc0e2ea3298aa18de1f35d3c24f4b4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 82: Field Element(0x33ac69aab5069c891031bd912647500e235ef1decd6b909f1e28cbedaf820d7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 83: Field Element(0xc54363fe3874fa43a6440f0860a416b0bfab51c99a39605552172a524d67af)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 84: Field Element(0x642b9996245cd0fd162e536a787a92eff18cf966f7eef31f4a609b915673f25)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 85: Field Element(0x6e2d646ae8e7688319b38a86c3e1919f864e9c792dbc27ca5792fa31ee27d05)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 86: Field Element(0x6770942a670c577d35b54730cf8c3b870564e0ad252bc5e6b8bca0665e13610)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 87: Field Element(0x7f09141553cf68b090e68aba05956b12e35dc2293a18ea3c369f4af087bcb58)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 88: Field Element(0x2930ebff77f15258179b17f69a60b268ae4e66f6e83affeefb25d718157a0f8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 89: Field Element(0x3c1e856b49deb2eba9c37cb2d55b1ce781824fcdd09cb68a3ddc9129cb0f13e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 90: Field Element(0x7ea6bd9b4d30f6f7bb018b0b6a26786edd1e2947f8045a09aa82f968eed7ffa)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 91: Field Element(0x3210f184c4e2caf98d816f8777e12754bd0290d4260f9749dffa45ab220b5f9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 92: Field Element(0x68a377d26dcf03be0fcea94c256dc783a79a434b4fbb9df3421f7c5cd471416)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 93: Field Element(0x7a6220c31b991c12d4e6bdfae6599d850a8ed4337d9d580358d8fddf8b409ed)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 94: Field Element(0x41a67d226e43d102bc8cfaed93c72b29a407f1ee1628bdb15dbc80df941d15d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 95: Field Element(0x61bd576b193cc90034d64ef27018328d758da9200d87fc778ead471512b57d1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 96: Field Element(0x2324d21031df2408d8ec2e8d88650e79655c4be9aebe5be27fffc94ac85f74b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 97: Field Element(0x4e46eb38f02b3d958d783526b2eeb97dfaf2339a55e3013a857f06fefaaf3cb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 98: Field Element(0x6f3b572d347e1dcc7353234b48f208587f3dbe4383726c5fb29d5aadce8566)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 99: Field Element(0x3d231858d11fee83529933b05d6851062aa99745d1632a0669a84945f02877c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 100: Field Element(0x7e7ef12e515110f5619518b0198893334a49f2a5a59676175f8e59a060bdab)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 101: Field Element(0x3445af21c6ecb68f692f8bd323d2b91f74e01e7c1cf7e4936e890211c8ce901)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 102: Field Element(0x257f3f853342c17ae8b1d0aac9cd1f5994eb67d1d95756bfd3ab7246fbee832)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 103: Field Element(0x4cdea00156860bfd39bde1c38bc8e26afbe742b4da4f73bed182d1bc9ee53f5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 104: Field Element(0x33ce97e6344a7be9af4a2bd141616f7ddd3cfc31ce4f27b3832070718d755f0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 105: Field Element(0x525c16e11b2be37765f5bf989cd74fa3a5185056857c873ce88c7acb4c50bcf)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 106: Field Element(0x2256669b98f8031ff2457587c3f1382c51cb71534a508c7c950998ba4939311)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 107: Field Element(0x315934c6c07bf5018a7eaab4a1789ba30b988825d8345973ede195f97646e58)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 108: Field Element(0x16d2150244d0dafc6e583a8dde1fa0ccb36367acbe106b4adefc4726d069d82)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 109: Field Element(0x60a8855ed5165e5271942c71b7ee51edc109b34a9539b461057d26122e5a25c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 110: Field Element(0x1ee8669eedf3e430e84511c5ad03e416454ad9c97c7d7301c2155e29d672287)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 111: Field Element(0x71852199ab87d05bcd7c7c93637cfc5c5093f9fc580dd7ec3d6ac5b6b94a9d4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 112: Field Element(0x6b19861a7ae4b4c9df888e44d0415733181110d55cd0790cff00a1f9d69025c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 113: Field Element(0x34e7613cea3872fc61a775383af40b437f22e32ad7c35e6189989519ca29c68)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 114: Field Element(0x4528981617b2c24dd287dd7f2da6a3bf94678fe4a694316c6bf717e023d27cb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 115: Field Element(0x6e628072bffcf56088d1c375ac0ccbcb2a7c24724205bdb4ece75ce68d3e044)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 116: Field Element(0xd5e17637262c6066a55e356d31d211c84693270248ff2d10b4b77584586c65)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 117: Field Element(0x429efd0509c0d2b131d8bde5849799a4991bad48417b99de5dba76e31c1d91a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 118: Field Element(0x32af9839faec7ec9a2d2aeb8f655b21ad76775e6cfa9926bb6ff1360c71a462)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 119: Field Element(0x2a58c85a522def0726cdbe0c77434b86b5e7a16ea902343d3a350b5c5206844)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 120: Field Element(0x52e6644806e6414704a77d58606ec7e94afe854b084356c601fa6f5a2d945d6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 121: Field Element(0x63d0e65903062c0b7b175e50f343223d2e9064495a98accbe96093b512d3ec7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 122: Field Element(0x6f74158e398214b0195d38d27b04f1cfbe3ac9e0ba0e02b52ba8ae78326afdb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 123: Field Element(0x7efb2c02571e3cd992e9591c76dd9a25efd4ee70f66d705b67d98e00772cb4b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 124: Field Element(0x54ee381ca6f2b3ca0276e62af2d6078b39aea508e8087e1cee3244831c4e86c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 125: Field Element(0x6867c4531a859472675eb1f1afaf40f2e848a7d0a0199424ec23b1a55d40d92)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 126: Field Element(0x4f2ba0fab69944ff3661fdb258d9e2336582d2add5e0684e15eac89be5a4c92)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 127: Field Element(0x622a79805ea02024638dde17b3b3de070499bedee404f99d9fe5d395f37e6dc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 128: Field Element(0x347f61ce768932dde7508b7321d10582ab9cd1f1a5be3179b7028fb866309eb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 129: Field Element(0x25d84b4967418f3bfe59ea770fde171181b0aec2bb3df7520b3158d45c9b40e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 130: Field Element(0x100a2c3e764cbded8f3c546b7fdb99988336b30c01a08b2d905e11c93ece003)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 131: Field Element(0x76d95e8fcdf96233ac57350b42baa5710d92f07dd8faa64dff53bc5cfd3cbf9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 132: Field Element(0x6b29b42b1944f9fd9d9c178fff0fed3803d6752a63e09a223fb21c9c0026037)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 133: Field Element(0x7b202941af7543ac60adb7bbae069e67f500de9a2510bc0a63c7391893fe6c9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 134: Field Element(0x2ff28d752b458091c288e781551d78223f324867b8a872c6e4a031f16b382b8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 135: Field Element(0x37e9d619d08965abe2cb3294ec768742c50f63b5f5d94ba60502cb24c45c5b4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 136: Field Element(0x6cf3788c3667ee9a332c7017544c930026c090b8eee8bd960fee0380137db9b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 137: Field Element(0x785d0a7a214cf2e1d067d6a49c9b6f8058b00a60d03a4d54e30dc011f9af93c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 138: Field Element(0x7d6ab13af5c94db46b02a3ccc17c2030e240b41689b5c30b3244f057c12478f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 139: Field Element(0x472d55c3e600ccf28282717377f3237adbb6ca9cac69376213d36ad0cb34801)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 140: Field Element(0x21efe7933c9a7739eb2004f345480a49f4fa0dc881c70349ecd8d27bcd34b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 141: Field Element(0x3cdd6c40e2670f13ace2f1ec3efdfd06b7cc153187a60252143a03fe9062be5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 142: Field Element(0x3faa23baf029d5387acb0a52f359612b09f81d0034ff32ee58224f4d99a277f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 143: Field Element(0x54c33ce58ad248012cf9ca245f49f720cd676ebfdf03be7c16cc3a5b021245e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 144: Field Element(0x447bf296e2c1b7264defebb6d73ade8a8c6899efb3cfe1599cdb140c28ff06d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 145: Field Element(0x65513f2b06ea3f5f3ac737310749e03957df500bb8ab160f5e38c94b70f00e2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 146: Field Element(0x50f25b00769766326ff6a30ea600a2ca66c2c23644084989551d649040f2f7a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 147: Field Element(0x58114a288e3b329505439eb68acc2e16153edf243f88b1ffd9b0ca1953077a7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 148: Field Element(0x39039c21aa0d11fca4cde0fc09955e3de3d524c93486f2e56873b15bf2073ad)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 149: Field Element(0x2a3aab1decdb3c0f93eb156d416332c088c2ac2ceca4de8cc82edf0f42438f3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 150: Field Element(0xf589b9c78d270b8e288afa873988d8fa1b8b8bd5f806d2f038f7c0c87855da)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 151: Field Element(0x5b5574db6a145c761c5cba900fa9a11281350582092d79cb33e5dbda5779ab8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 152: Field Element(0x74667f849609a3f37caa393404f71b77aa6ce5cbc687036f3483758c509ad68)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 153: Field Element(0x5ee07cc6ace985dd05c33e536da7c97f01bc3ac3ce50bd47ca8e547bcd96193)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 154: Field Element(0x3ad59ea8920c4ee5f0312ac49d07332bb80183dbf791255ff0915f19ca40654)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 155: Field Element(0x22cc5cf83358ef0d0824c0ce2483b305990dc5232f4b1f87608c2fcee2f232b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 156: Field Element(0x2900eca975375789029fe236b80612b40f64411e29af61d5ae46a7e89bf7d4d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 157: Field Element(0x241fea6412ae1c27ffaec414ff709b1a51b3cbf15709bd930d230390c922bac)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 158: Field Element(0x2aed9dcb76d316b8559bc43ae51ac0cfdc0c5f53bfd28ea3d7ee1cbf34e4a1c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 159: Field Element(0x1fe47b10fdda19d6753b32fb3e56e138bb2106e7b73ea69de3f777ad600545e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 160: Field Element(0xeaf52167d0f3da3835770a54eab914ba22ee5bbfb8b35a3d76e8553d35f27c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 161: Field Element(0x21652e37ab91e661de7c7c6589b1ecec68626f0cdb9942c1872567b6df2e158)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 162: Field Element(0x697a6cd8de590d12e271acdcf6a5e8e9fe1396184c134d3552e81f5e4141e20)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 163: Field Element(0x4f846bb1a9bc28dc502531e184e06bd70579fd43e5f770b1393f7ab5f4572cf)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 164: Field Element(0x4e087a7fc02144b7b7847061847d485af630c9c5eb8ead7f05af47460bad709)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 165: Field Element(0xbbcc46b765e6fe0419073c9248345a24f180f4801004ddf7b4ece0e3762c93)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 166: Field Element(0x4e6f611b080b11038c3e6d61931d5114bf734135416da06cc1b7e61ffd3d280)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 167: Field Element(0x1b795e90dda0749c2287f61e380cce5411f871256b947a37aa0fd39f8bae9dc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 168: Field Element(0x43ac8c81dfcd563f7e51b66eab29b6363d6873deb74730844fa81ad8e25c6fa)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 169: Field Element(0x170b63582f33dc98dddc1c3bdba63a02e0e334e7a225b136774f177bfb6e58b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 170: Field Element(0x776b0dc611c544ca98c74777b0a10ab13a60ad6c81240638910c4382210d97a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 171: Field Element(0x7ff9d37696cf40748fcd8f6a1fe891456719aa756d71f6fbfd1cabd7d75ca95)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 172: Field Element(0x37ed5f1a279411f830365941874a6af03c9cb3449a81c85f755e007619e476e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 173: Field Element(0x64873b9ca50bd5eb7f049725bc6501c1faac5596456cf70dd9e3324c698e1c8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 174: Field Element(0x390d9673622fbc6cd4f0b0560953216653f41a4fb7f19e71ae26d6cd800f2bb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 175: Field Element(0x1a2ea16d2d499cc1e30942b4ea7c4a738167dff3a03a8da6bf168833590e89a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 176: Field Element(0x621864caca184da9b7b56e783548fe472e2b12af6a7e4afb3f82932486d3763)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 177: Field Element(0x10fd7b2e865ac05e4a5b50f7de379d086322f72fba40affa7564fe3b0edfabc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 178: Field Element(0x69fb9b4746815f2071f9890a14ea0c612160dee228cbea6ec08efb7c8f5a082)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 179: Field Element(0x428be278d015bd69f1c48d9761699987d33387fab9861c13ea65a038977eec9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 180: Field Element(0x723f4848c65e0a9d8209fb3c2de17facfc102a94d2e3e61ff865e9c7325338c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 181: Field Element(0x5ea6bea4b7b36a77ba6aad86d20013ff5ea4e14e2d4df77f9c7a8db54835c37)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 182: Field Element(0x53aa481b9775ba0e848d1ca8d3a55dddb9d763deeca5ab64863dfd12dd9ac82)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 183: Field Element(0xca5a630c64762effc456f201947136bdc1bc4628ae7910ea8b06253e45bff7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 184: Field Element(0xe8f9c3fd98b9d774d46c621e64ca56f9f6256e34ad3185830ca93f81cde4ec)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 185: Field Element(0x14cd1b2a42bd859257c7cb60899e150bf130a968a6986e7d5deb066b29ef5f8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 186: Field Element(0x116cbc7a8031b602cd54c49aae5ad312c90d6f48d751924bb6557b2223bd01a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 187: Field Element(0x7e68e220e7deddf75fcfd022f68b1486cbac3a78d316b2259fd40f4574adf1b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 188: Field Element(0xacad90ab8cf0e246e2331644d0cc6f6c90f1bd755ff67c2739a2d69e66bf4e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 189: Field Element(0x7b47ad812dd37121ab14bda41323ef8fe78a83ac7e7b4a074a2a2f86517804d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 190: Field Element(0xe948ff82a7709b277a76cf7f14088e27d0d72c219412644af13651d6721e6c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 191: Field Element(0x252cadc7e78eb9fcad7325f99b8137b82419456d8b66048196fef9eee662665)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 192: Field Element(0x4252fd6fa2ff7ee2e3a2dce3b8d8e4324aabfe2c7aec8541bd7225d454f78bb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 193: Field Element(0x46bbcbe03ea6a135b7a4811ad30309fd99ef4eaca1a6e90c85b6f75dc82a3c8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 194: Field Element(0x463bd9a5f0e1a2adc05ce52107fd5b7d23e6824c9bcdfe3977561ed14992c4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 195: Field Element(0x55b43b0336bc6398c79e948aabe415e3887c77853980b6f9da364f415f6435a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 196: Field Element(0x6785eb244177977fd9917ebf7ad09efd0eee8560b2cb56d2a786bc26a57c230)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 197: Field Element(0x63f0a410656302f3b39f4fc50f1f6f4eec9fad72d71c6b5502ebed2e2ef95ba)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 198: Field Element(0x4f9415994e6821a667de950e6c1af01ad583ce37fd1166f1cc57f9185b68483)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 199: Field Element(0x48fbabd8cb1d624597bebcb46fe08a3073ab5db68690fab5152436a4829d81c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 200: Field Element(0xee49428383306e2bb0afd22d3273aa4de6366ec23a9f3b856cf4d04789b875)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 201: Field Element(0x39eec744e0613ac8b7f8e38bf736a313a5d41135c935245d04b605931f3d9a3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 202: Field Element(0x6ad516b4326b0e3ac708afb3b3ce9c2bda13f3fc8c8cb5ee5dcf158201d9c35)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 203: Field Element(0xb346b7d27bdfb28ca0c0962ad76e4cd22142361760e8d9820a0743956bf2b0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 204: Field Element(0x1a9b7a65aea64ca8b7d67f47c66f89fba39f6e7d0501465aa1700a597bad67a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 205: Field Element(0x6076e4acd02eabd36fdf8d4f2b37e00702336bee6b8299a1e2541e6da8f011)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 206: Field Element(0x7384c496627111be43e46ee7c001382199e71c3b833fdb5174c35c4c9a7f4c8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 207: Field Element(0x3e8926711c88e879c0b0ce19496b897bb75132daad31b665e82636e31202125)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 208: Field Element(0x7d0ea69765f232090b0139b843406e909dbcf706b86bdd667f4fd7a5d568a6e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 209: Field Element(0x6a8a5fb8db549b6d9695441e2d98a81a4a5a01fc3506af4457c6cf0df7a62fd)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 210: Field Element(0xbb119a609316ffcaa873c9ed3eee58d73b6c75e0afe4f918bc3adf82dd90fe)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 211: Field Element(0x766aa06572d3110cc84194f454de718e1db95fd9cf5970efe1d9d924fbbd537)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 212: Field Element(0x22f423d4ba8c7507fac640d56de600e066f819b59a7162874da60305c4f209c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 213: Field Element(0x2abb541f296199c0b481708b30e782457c5174a295845dfd45fd203c94158d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 214: Field Element(0x4c40173b3c4cedd76f75cfb23c5ae8a6e87f0ba8366071b40b3704cb9a7d52b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 215: Field Element(0x7f70529144b0fb94cb80875a67100713488e42559f7570fa87e3cd12a6f2050)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 216: Field Element(0x151a3060535700a688a91a9ed4d1bd1e87b50f265a1174eabfe8f9e3a749cbc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 217: Field Element(0x64c12cd80701800be2eec487a5671f5217af6ade512d5b0b43cf4de5b63ec34)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 218: Field Element(0x5afc1dd12139e0c604b9d024a1d12095f08637aa8f94dfef2a1138342d907c5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 219: Field Element(0x767d9500dec6317777b3094847492f189265b104e89eedadb51bdae128644da)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 220: Field Element(0x79618c7ddfd079d8b75a783544e3115d5201e417ee8d49d420b18fe9d3aa672)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 221: Field Element(0x353ae0647b382998f4b8b88328fd5a4ed51fdb26517745a496c0a89fc09b0a8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 222: Field Element(0x6bd7c84df588cfbfb2165fb81b13de9245226ea96692a752ae9796fa8128ab7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 223: Field Element(0x48f0c8cb1b6d06c8503ee2675a284f6d2754a95a16fef5f61be2dbb844170d1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 224: Field Element(0x78de7ac4410aa75e15b9a909eb4eecd14ede3783ecbe46927995191c27ca033)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 225: Field Element(0x1cf29ce306800cd966a88b91871f8b10b54229b8f243f1df68297eea43c9a38)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 226: Field Element(0x63a603f52800f3d5d190f56a9580d0c5e65398b2307cd770920883851aa3594)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 227: Field Element(0x5b8f1c374e593c242c5488b797c12dd1b37c465d831168582f4962b4411e4eb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 228: Field Element(0x696e6cd1380f56f02808ab28ad6df68c99343c2c38d754311ad1c495ce5431c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 229: Field Element(0x2ee6750866f445ee17d2e8c006fedf236cc42bd7576d2af051844ef7776dda7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 230: Field Element(0x220f2c1f806dd8b763627e37464b08d408775c7bdbcf9b510c75e07dfa98a65)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 231: Field Element(0x7580881ad04db3947c3da3525f830b5eaca5da4cede509aba3a05f663fc0d4f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 232: Field Element(0x4df8f1886139319f200d84cd431f6af3e016ae3a5bfdebe1902bbe22fa97935)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 233: Field Element(0x19b61187dccae18dcf6d0c3ccd5763a545bdb7ba558c8b91077ec9dfeaa9aea)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 234: Field Element(0x362aa5bb60838ee3d68775e55f2ed3f24ab4750a6eb3d413c880ee670178648)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 235: Field Element(0x5e9311be61aac8e29b4966a6bc93797a39334586aeec1898806a5b9b798ee70)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 236: Field Element(0x14e006af0d5950a0700e5b224e9eee611944486bf56321599add97251beb4e2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 237: Field Element(0x6b44916f3cc8ca51f77f18f347e0110eee63f14cf1ce474be82469aee0be79)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 238: Field Element(0x40d09625f20e9d869232c96926c57908f6ad55f7df29fd76d13eeab6ce5a6ec)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 239: Field Element(0x236e4da894fa3f187c687d59bb2a746e45e9e174c19855254364a72b17b5f31)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 240: Field Element(0x65cd520c09865ee51d36e950a03506f1f20a9220d3333617af16ae6a5cd7f2f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 241: Field Element(0x5773357496394e12994e77c4f0b01d01fda87d4e8df4106fe29e3f33c5398d7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 242: Field Element(0x56aa16a039e8b2fb94821270e9760fdc431d3d0602db126a17054579dc9910c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 243: Field Element(0x1b2a5ca9652b2d004f9dee78ca13ae1e0d4a6ace9209f18964704c4b91ab6e1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 244: Field Element(0xe8c920e483076e3b9795e122bc8589c3dda7ba012b54f0694b7023cb147d53)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 245: Field Element(0x26d2457d8d6f6302fed9b33d14724dff254fe57e387d981c5ed1c70a0c1285d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 246: Field Element(0x102332cfedc74e882f960c0503fa2f379efb20ee68f59e9601b71c85b3a22e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 247: Field Element(0x416a2489a483ce78c5cbcdd5437d760d7903fd1963d5eadfea5aae359af8f3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 248: Field Element(0x4ce0b6bdf7c6b04e00ec22da1355b5c4abd51fe3ae1205852c9b8b26b6975a6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 249: Field Element(0x558b32451067a67f66ee2dd566b33c375b86f11b2f0c367112ea65e8f877fa8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 250: Field Element(0x3da2526deaa393e84dd75f7ef24309bcdce6eccd1be739126e7aea4959c327f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 251: Field Element(0x9c892451819cc6334c44cabfc6f781749aa315fe3308889112689f51e3116b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 252: Field Element(0x1442c2a0cbfc8b215a247e8ad2b6d406093b627bfd192679b8968c28a260f56)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 253: Field Element(0xcbf629fcd8904744839da074dd3960a057855c0986f828d1425aa8c8c818a9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 254: Field Element(0x3bc3c8e7ecb53da2423e0d36dcce6222a5965b1aac744e4b549fcf11708dc3a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 255: Field Element(0x6b724a4709becb2f5a31934d99c04d324d7b302738621e713062914ff1b2780)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 256: Field Element(0x255a37593b8c0e7681394ae27cb530d1dd274d375428820faa6d8f1acc5393b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 257: Field Element(0x60a5d3d8cc8c6124a4870bb3e5d5aac86bc9370e51570a556eef4d9678cfe50)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 258: Field Element(0x7bd1a084838559b34217a25405fa4692bf18f286fd3121f947aa78dc2da2aa7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 259: Field Element(0x2c78bd1ed4632e57d8792b7d14e9adfc76801b755837ad8c30a83bf869580a3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 260: Field Element(0xac63c06ebee0dd013197a9096684c376f90aa63ca3aa3a59397ac593553372)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 261: Field Element(0x7935bf333834e6a44435c3b8c55f54fb249b2ed73c68ecbf68ac87400d92ec1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 262: Field Element(0x17e805a279c23368bf1c757db24c8fa7fded5f883b886bad0837913a8391bb4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 263: Field Element(0x343b5de9b94dffd6357b1c6c6923db4d11d02e79ef9bceb89443b47eeb1576)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 264: Field Element(0x3e89c1c3e8c8a9fce91ddb390b044975fd089e6dc7133cb91f4f0f2a04fc35a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 265: Field Element(0x41d5fe8fa65bc1ec3e3dc7750abba36e79d74411f70e768c4ac7183bf7a719f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 266: Field Element(0x326879746d73cc70dd21e8698541d341667b5b5bb26568180843ae63c2fd496)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 267: Field Element(0x42fac8d461269a1a25414e3d89d4a163fdb191e5968cb5b90880486769402d0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 268: Field Element(0x5373c277a099358f697f0e0e3785be641eae6df700a9cc1ca4f2a7662583ee)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 269: Field Element(0x760cbd7237b29e3cc60f1813c3892bdc62d90fef866c493363ece3bed681a03)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 270: Field Element(0xe2a582abad3037c862fd4ff39edb0195015bd7d9ab31756be7c52317b43760)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 271: Field Element(0x9db9168f9c757969c050112a92d9c89c20a800ff3d227696f2fd52d442b718)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 272: Field Element(0x267c4051bc13fbdfa159ebf34c89bc45be304fc12b3a649b19c8aa1e01355f0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 273: Field Element(0x42ca788c0852c6e7b5871475fce7fabf56e5288499bb8d416141e8799c7b134)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 274: Field Element(0x1a04e977f4823536862dff89079cc9cfc7cbf2842da0f8d808dada4ae00d2bb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 275: Field Element(0x680934a3c64e1ef27aec1b54a2d4a986a3fdf9d457807aa994379fb45836adb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 276: Field Element(0x6c43e2f89acca63ba704a002eae03f3b742f5cebeb73232aa29b6b0104ebde7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 277: Field Element(0x7adf5dac4dd9280a6a1184d16a1e2e5ce9c4f5856d2d8f234afcbf879424ce0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 278: Field Element(0x3137a6a43767514979da624679ad3f75713e0955ecbff687563d398e380d4eb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 279: Field Element(0x3046c06670ac8706bd93b3e2e82e2ed09e50a20cae31e5fb59d739730af3142)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 280: Field Element(0x287741fd475678228cbed93ca2a0ffb2101dfeffbce2cd6ff98135ba75a3f72)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 281: Field Element(0x429299be1ccfcadbb065658433e23cfeada04fa073ea4f2908761681acda84d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 282: Field Element(0x7680a69537883fbafa94ccfa03703732a62bfd3cc8b878d2658690283dccc6d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 283: Field Element(0x1391a7622950b30dc581a3b6fa3a6c2dea2b649fb4e403e1c7b958c56b53a2f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 284: Field Element(0x56520843bf1593f8fc48c7c99782d6eca9b3a3952c77b996d158d59a55a4d51)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 285: Field Element(0x36a68db535f79f51eeffc580778702950951258ace3072526becc7845784dbe)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 286: Field Element(0x172f2ad0d01692a1a06726f9c72b57283c5cc9e597f4101997c4673a192dd01)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 287: Field Element(0x59b401de1fb30d43bffc6a9e38a9ec2d70139f5c53de9b8450b11a705ca93a3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 288: Field Element(0x69bba97d7336c18acb98f75934923825c4cd01905236131bb2c6369f53305dd)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 289: Field Element(0x640a0c10c61fd99ea71d4558975e2d58334aac2c7977fe13bfc47d4b636646b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 290: Field Element(0x32607d4c0b9320e2a28a6e5f3b7b22988bcacdc377f83542ef535d279c216f0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 291: Field Element(0x73b73a0131caa3b4e7d05fa1037cd7feeb2953934a2f3075a9a8af998f50c40)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 292: Field Element(0x5aa5176f43a48a1528b4d17ab0b097d559755ee30c3c291c3b62778896d8bc0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 293: Field Element(0x11a2788f30c5da55fa035ecf5e6bcfe885747ed80c204f500a9f73c7bd7c761)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 294: Field Element(0x6aebf9dad18582adfdbb386ce8237e6461442075558cad73c869afca38d94c4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 295: Field Element(0x7bff12e87941f5c53256611b5e72489eefc6d30c8578f7e0ffe2a3c7cb7b14f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 296: Field Element(0x2084b2cbe2a909b027d1be0ddaa2fd67cd656c704781999ac97c603d16ff159)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 297: Field Element(0x289b0fd40181687e514dafc16de48666afd6f55dcdda630e1a5bd68d8e4b330)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 298: Field Element(0x13532ed2259149b0e28c14b255150fc3396e08aac7b43dc459e9d5b1ecadb74)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 299: Field Element(0x2b4680e10cee78f7fbd41d2d132c2dccea8e33303f52476f9b4992a8527a2ff)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 300: Field Element(0x6a161b366659496dbe9b4268d3569b519ffae49d15cc95b14c7751e874e5cb1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 301: Field Element(0x3c4fb49fc66da49875d6e1f44f20a22fd501ff385a0df47b08840332bab7a12)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 302: Field Element(0x7e40325ef50639532e0f3c5c15405cd5a0bd2857c9c29936dfddf6b5a4efb4f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 303: Field Element(0x2885906ab532eab4ddb415aa5079c9ad63126a605920409894a5ce833f453e0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 304: Field Element(0x49973012210c9a3e7d156da97384dc6b710c6577b221a3573e8a30e5f1fe598)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 305: Field Element(0x529a733a39958d37d5babe7648dc2c6c4dec6618f7e5ac2ae484579bc7599fa)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 306: Field Element(0x4af67febf7c605d8b8928e73cc7f851d224d736890b23899cdac4c6e7122d6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 307: Field Element(0x7dd29607d87a08a5a5aa11a0ca85d3d33b7b4355eb4f2d1afcd77ad5776d55f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 308: Field Element(0x328dd0458af1580e82d95e57839fc63e9b8f2de7433fb85d5ab92cd4bd7deb1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 309: Field Element(0x83da33cedd373d30769b7dcfbc38aa65b7ecd7211ad1175d68aec6bb8cd4fa)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 310: Field Element(0x26bb4246f0cf6743ad0c0fdca8bab8db9709910ea0ddecb3c13c8de02e00254)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 311: Field Element(0xa295093d24cb762e8148631bba61fb16e538531346d3e6ae50b2804f6328c0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 312: Field Element(0x26383b25ee549b0d1ac649866accc9617ef1c1d3480b741ea1f3b0a5fd3c1c2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 313: Field Element(0x6491fa169de0cdc88b0037adb337d6814938b62cf6438e62e22631dbc5308bd)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 314: Field Element(0x52b4e64c044b8a502e2897dbc6345fc9a9f67f42a9a2a9ff841f85c235c912f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 315: Field Element(0x3962c416b1f185674a0dc46d6f34ee69ffb71a12c12eb0d2642423f14f931bb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 316: Field Element(0x1d2fcf8bd96dddbbdba7e17ede3ece338304cd884120634b1f97d6f783e2320)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 317: Field Element(0x706cf1f93701d60c4bda9311d57a1793d55abe433492d43b3d42eb69c15946)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 318: Field Element(0x7a58694129882f124f43a8ab97ce6bf5675692e41a0973906ab1cab3c32376b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 319: Field Element(0x406b502c50f58e7c83d533d189942101c3a8476856cf2687bca2c4e99963cf4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 320: Field Element(0x69d6805aec972d8fe267bc52af627389116e976d673c075fc06b7a37dbb7188)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 321: Field Element(0xb5c8b32c52f22b4e5f6f51e26be793d904e79df5b71a031704bc9c76dfe026)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 322: Field Element(0x3424bcf5693289ae09b17e11468ade6737358605bce8b4cb8c8f840f2839dea)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 323: Field Element(0xd2ca9adf42abaab6f618a1fc7434e799b968a674054080572a85fd87a1273b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 324: Field Element(0x68e0f8c0379b106373cc3b758030e831f7181e9eeea749a09ba6b4c2e582d20)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 325: Field Element(0x65cfbba6f2f93b3ea863add6c330af4e500d6efa1ba72196a1ca417c0d9ca46)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 326: Field Element(0x18e63c69f5e1960e2e8c674c6c5d74e4b84f4e6c9c802d8ce98926b4ca4b68d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 327: Field Element(0x5e4d0478d19008322aac7c8ebefce14d9149e891f5f8908ef4280813ed96e6f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 328: Field Element(0x335d385566f0c328a51a9f676650b3e61091b946a130491a12e0a26676d1458)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 329: Field Element(0x7fbed9c0cce744aa59e5479bfe32177eb9635e5a0fece093df66ad7db2e34fe)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 330: Field Element(0x34b72e602b024397b5dd60f72c017afb3a0917fa0bb1798981fe4d7ea184b8a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 331: Field Element(0x6b902dd984748944741a6d7c74ef2afa2eec6100f9cecb1cc8a3d5a96a6bd5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 332: Field Element(0x3437740f8019f9a4f981b24defa4ce609e4ffe4681febeaf245620d107fe075)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 333: Field Element(0x1450838be8a3b3ff516a9f95fe5e9a8bfe08baa0d8e2a9eeb4915f3a0375770)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 334: Field Element(0x1a9024632f26aa757b58196373ff1c1356c7495132dfef45c36f998f2ce6d9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 335: Field Element(0x1a0ef75d88ebaaeba1b8a11651d8ecc7543f258bbf84a8d854fb76dad346c96)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 336: Field Element(0x4b057e063f714180b169cb6b7d960b677b91710b6836999cfe47ee1f0e15390)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 337: Field Element(0x49793184c5be61c07e83ac6e836dc1e7e20eac609fb516fb1fbd1108560df2c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 338: Field Element(0x67558cec650e2c0ed0f2086c7f0dd9e0ce3b1601a5c94bfb4a92a1749361761)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 339: Field Element(0x5fd7487dd8ecc1a5870b512b75cc53859c0d22d7c31d11164ea8171014cbb91)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 340: Field Element(0x4ef9b8add23802844942b1d9323c9605933d97edb04142cbe717b60b1cb2246)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 341: Field Element(0x4640c30f2c81dab9e8e8b1b1353ad88acb699efbe013157885b42a72b5f0d44)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 342: Field Element(0x488994f4efd5485c971354ebfecc26ac0292d16f47fe65b64918d9758f1d119)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 343: Field Element(0x28aa0c181a8fdf5ecf340ced7b7dd76c6d7696450a28f45e62292449a49c34)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 344: Field Element(0x6843bcc8fdf542c44ee738c751f7099edefe98510cdd05d48d01f221b5f40b9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 345: Field Element(0x3146a8a14f726a80459d3ca3c6ef551f2710b2dfd604fd0d721e1116b034c2f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 346: Field Element(0x37ab10c1d8e5fd6b537bafacaa07ed8217ad55df16e17bae2d109c16116b887)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 347: Field Element(0x6b86e78c516f8ffad3ede6d2ccd1327a87236ed0fde2fce6fc7e0d5e648ec3d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 348: Field Element(0x542c3599680804eb44cbfddd7561daa03a6111d4d2db0fa8578142c202ffb93)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 349: Field Element(0x40b2a3ef4e24b4a065a77662d7ece1b68975b3733627e93b593bf5ebb8a394c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 350: Field Element(0x6ed0f124683ccd84b1c032ae304874c6ce869e928d722f24cbc256a8204460)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 351: Field Element(0x6310ee73a63c76da855e4a0dd38176e9c919f21a93333a5b80bf6fc50f7344e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 352: Field Element(0x39c0735bccee32e82b09a19cc6289fc68ec3bedd543aad2bf735c328461f7f7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 353: Field Element(0x40ab612411737e713461836ed388cd8b302d0740c86ef5961fb79aab50c6cd1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 354: Field Element(0x4f464591e18f6678914a30d446f8660e735677c8f13572795b77e0f04a897ae)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 355: Field Element(0x44dfe7dd4339d1c37d2358bb7782a7eb8161ee7b6b043978a81684f5f5ac121)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 356: Field Element(0x1eb96600676f0c04e054da149180722527186e660b1b513bd2d92f60de5f622)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 357: Field Element(0x7886470295fc4c52cda9060c78dbda0ac8bd51f79decf741b4029bd46ad873d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 358: Field Element(0x5d97535e439de7028bc208ad7782ca7c814c47cbb07396cc76603964f93a3ae)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 359: Field Element(0x33749c2198b6cfe68a979b84dea6d2f3e2fb48b7b266e0845810b47e8ef6254)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 360: Field Element(0x55eb3ab7c6ca8e0af5d2cef2f1a25eb40d4c406cc56ff5bd4d04015b260bba)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 361: Field Element(0x2624ef4665acf45df1636580fa45d2d150ae35de150764f1f3c84b6856c1e48)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 362: Field Element(0x1cb2963d0d033d5e1ad94e1c620bdc5685c2d69779ce98afc743d80cea69e20)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 363: Field Element(0x1a576d4d0f5a6872dc349fce77146efe4f88acc886e361989a3157780b9e090)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 364: Field Element(0x684b365996df0ad4f2a306d23a745226d57f7a6b4c7534c9fc99b2bdcc9f8ae)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 365: Field Element(0x3be775be4d83b5de3e9cd66f04d79b77fa26a1e5aca523516e43f78d554e460)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 366: Field Element(0x57a1207c59e738951e7525f4a7c65445c6b4c137fbaeac96fbe7f311b828f2b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 367: Field Element(0x3af3504acd5867dcc6e4d46a7e48340e00b600df950eb562882eb6f0e65d703)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 368: Field Element(0x39e9453edd9bf27b4d6aadd70f2ce72ac4186b79bafe430d60e5650c7327e1d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 369: Field Element(0x320798b12f00416f5c8ec48557fdc8a33f687f9e62c1b9007df28d0261c5844)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 370: Field Element(0x777f57052d5b1f0f474b521259808513f883b5767bb11239d3c0d8997f54aa)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 371: Field Element(0x7b1e3f69e1671d59f66c4d10b79635275d3912f047947927ecc1e4efbb4a6db)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 372: Field Element(0x2c51cb671c0161f289918c8f150db601b4dd11f6719d822d214bfb8ebb0a930)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 373: Field Element(0x52c0145dabaeb6243fd9f9d23fc3adb17c22421d76112da89773ad70dc94ca5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 374: Field Element(0x3b668b28271333c18fe3e627d673e29571c64ed672d67c405453afc694aeac1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 375: Field Element(0x52d063689ffe2c2a34253474c9b2cd878f4cce7e9d61a94a96d590108350da2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 376: Field Element(0x61eaa6e98b37f6a5856f0b48fb2e412861c4d4fcd5cd1f169076bf2b602ca45)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 377: Field Element(0x17569b888384b74db9a8448bffd9f6be4951238fdb941130dd22191aa4028a6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 378: Field Element(0x4ff19cd8f321fdb5281643fa9a7d8b722566aff1ccb77fca766ecc9ca620ee0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 379: Field Element(0x3efc10bc4c8b18a8db7a7c5326e705268988909a516b86f1d9e7568394a383d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 380: Field Element(0x37f69d53eeaf40c09159f6832b95240e546b5ba47c9522e18b720d437af70a4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 381: Field Element(0x604d7b21a90f32029a7dcee8d938c6997e6d5b2de27480f4dcab796cf78468e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 382: Field Element(0x714a2a462ec331f29e6fecab2a234f7213bafaa1926aa56b453f06931393c5d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 383: Field Element(0x1cd42858c2eebc399406daf49c3dc3a45f5898f998eaea848895aef3e52b01e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 384: Field Element(0x7d613a5fbe199c77e4c26ee6b94285090befdff6f5d6220f00e5a9f9dde4c73)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 385: Field Element(0x1128f1c19599bb3c3cf1509fa3e85f819bf35b689e912163b71a7613731afa)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 386: Field Element(0x551e5c07ebc39b9c26eeee64322887187be0aa272b059ab9cac856502a3e2a4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 387: Field Element(0x1ac68af62e33a617e49328ed101b8d076372aff9d0905ddd6aba3a59a0d87c9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 388: Field Element(0x3ecb3e9396ba890bb4da463dd8e4ddf39ca96bc0c57103eaf7bdfc7f46e5f65)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 389: Field Element(0x4380f346ab176050258048cc6d7e44c911a2de2abd41f11fcf8487ee42952f5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 390: Field Element(0x34138a4e90ed9b5f18642cc1726846a630ea249f519c0093a8fdae5c819941b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 391: Field Element(0x7ffadfa4612e89c3fae96ca1657d04ce941abe9765412fd02b5e7ce6287c6b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 392: Field Element(0x27941340670578996f2e4e86b581b2745af67d157229c2f9652d2b3ece90d82)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 393: Field Element(0x769d82be2e202b5c730e3cbde6807d03321c7d7b5661c66f728da45516c016a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 394: Field Element(0x23885178efa4afe364f6f5e34d3edc5b1cee316cc25cfc0efd5bb0f51cd1e5b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 395: Field Element(0x64304fef42f0ca62c966d0378d62403c8908643739ff4422bbad6dfa3932bf9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 396: Field Element(0x598786a09eb8b5c530a01bc63d7ffeda6280bd0d31f88802fe5ddfd4a631a1f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 397: Field Element(0x11d6df6dd4e69bfe82e7628890523b8e9c4e2f1fcc5e875b56cceea809bdb61)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 398: Field Element(0x26e911c5cb2fa8e2b5b8c5b18674af15f1c6240d44e53c67a3fcf42db6ce7e6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 399: Field Element(0x220b5cffd952f43f8e7a8027127cefd9f98e1bee0399cbe2cef9f9f2d52f9bb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 400: Field Element(0x740bb849543ee0f137aa611c0406eca6ec85fa224d36fe6ad0725a571765e45)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 401: Field Element(0x170207e1a88e0627b269efa747bacf019cd0d222ea32996928c84c2c535cfda)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 402: Field Element(0x10c6ea6887ea20d107af49c4c6093e9c3e37ca4668930ddae82f066ff60906e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 403: Field Element(0x29346f85eeaa9c841c0fd6292e0d199dd649c263bea8b350be6bd40bc315438)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 404: Field Element(0x304931b73dd5d1733cd88596382fd23bfa1303ed71331ae860930e6bbe810e4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 405: Field Element(0x5ec60a5fcf903d210229e7c5363d2ec06eed7943f46a8776668e0f3c6895aa1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 406: Field Element(0x3ae80235758058b6e5967920981195fce2e05a5152eb1493b4f0cf0aa118eea)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 407: Field Element(0x54422a18e79342c7cad0943550e03848c760bed77c0f88446922f1511a84d21)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 408: Field Element(0x2e48656843aa489521ce36f145d5efe21a3585b711e689d1a75b9e2f172c466)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 409: Field Element(0x5aea3c7ef8327b89308f022536083fc5064dbb2550b673973883b1cd4722d0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 410: Field Element(0x28d7f34705f9919741df3c34e038e34c732aef4be1bb9bf0a759dd53b32ae6c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 411: Field Element(0x3f1788891a1c89b9c115596b301b7ccd2002a36c0ad2811555d4fe3568e4018)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 412: Field Element(0x10ba6006f4c3757c0a710af8d51e824b988f9789b37a7cc7ec173d545a9f9e9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 413: Field Element(0x730aeb88db49cd18df375a87470ca1bf9bf3785c76437f2ef6fda020e06c1a1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 414: Field Element(0x8da5d19cef0a498aa2f44ebf85a43bde73191ca84af30bee1747dc9931a77c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 415: Field Element(0x10e401acf86c790e7eb798bc7c2d28d4db6f01e646902d1c3701e22b806d936)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 416: Field Element(0x32b3480a316794047d078905a51bbe42b4ad25aa19dd8e4f645991d53d099e5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 417: Field Element(0x67db9c33abc3b0ec56f25b10c345fd070e1b0fd0f2645260b9d6b3eb925e8f8)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 418: Field Element(0x117d52b2f336f635ef5c7f7ffca19005f3b2b369ef3f07d5abb0679fb45213b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 419: Field Element(0x1808ebc6c85dfb278a8030a619ae8d8d207ce7b40e681b038804024d54b61ae)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 420: Field Element(0x44e4730f207e75e863eb45cd873d921ea3189fa1cb36fff7db876f2f96ead0e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 421: Field Element(0x78306bb33b4119aa3a862d8de516d7e25304bbcbe8e779a38365c3e1809950f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 422: Field Element(0x36d670cd6ce83958483b115147b3078e815ac81b67a503605524c06e2d673d2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 423: Field Element(0x2400ba0b5c3ef68d13f416af3eeb8125dd32214bc5fce4664025c1aaafe4aaa)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 424: Field Element(0x221e0cbdbe3701fbb6239a882b43c9d4ec785df2c0cb51b2eaf49da3f32a993)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 425: Field Element(0x24dfca656c4f739befb4d4558ca23e261943594080d58541c98cb74ff869a3c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 426: Field Element(0x415d5d02d13578429a3ded61fcb0f093ece871762974de69bbe9b57f49c3832)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 427: Field Element(0x2024faefe01a45ed8a99c946a11855397ba7eb5c7d8ae966e5bb6391e47a6ef)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 428: Field Element(0x3cda8c416b2ee77427ed8afd9d9ce098a256bcd84245f109d100bfdda4d319a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 429: Field Element(0x2edbc22e9b88ae4045e1c179c8b0bd2976eae0d89bccaef7475eac504eef65)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 430: Field Element(0x5ddaf4ec1504a6682d3d836e6da7e7320888e596d047463e8ec3d47cce696e2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 431: Field Element(0x4269191eadb31e7e1b904af5e2bf3fcb11ca833149439c889fa0219985ebe33)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 432: Field Element(0x3459ee224154d9955b9908e23767737e5d529b3829f28b4386a4947cb01455e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 433: Field Element(0x1b39d1befcf2e843e999f887f2fc7db882bf08f76b5f3505dcbe6bec62bf0de)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 434: Field Element(0x415a3d30c34a94d3b2247688d3f1b1c1fb8971ce57b77d58ab32c884cfaa628)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 435: Field Element(0x6d0a3f392f2cded3f5a2eda7f489da39fca26f3b1b3152b107ae5e517c9b82)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 436: Field Element(0x7dc62112f953d85a8f282a04ce2d76290d350bd7522c33ec520ffb83913855a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 437: Field Element(0x1c67e891d9528f53f8f52bdfd55429228e2f7e695e7e4f6b864b2a75eebb9b4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 438: Field Element(0x6b92182bea22ecb4eacd6eea463f9856537b86260efe77ed6f12685a367de1a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 439: Field Element(0xaac619d65d13b7ea0761e4bdf7f7721cd13986b78049d4b37c1ef5125a8d5c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 440: Field Element(0x6fe53dca0afb328729d4c7e6b879dd296db33ffa8b38fc49d8b5f8caf56cee4)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 441: Field Element(0xa5f88f4c774094a978133e7d6506dab62066cc4611f359e2ae7edce97e4322)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 442: Field Element(0x1d91ec8faac29e52cd7ba1543eed1b03a6cd5bfa65ba875776a12e5cd75b0fb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 443: Field Element(0x2bd04d10f6813dd31123055af743efdf33d97c2ae9d6cd66ffe55524d6fa219)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 444: Field Element(0x7ca93435c25074547a4d07362a3502a7a50e985ffc76550e53b0ba6c19af967)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 445: Field Element(0x3aeee43a46bb57780e6b4434ec8681af3c3b2c2ed60a466057cff4c1551a45e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 446: Field Element(0x1c51b8b0f28f653594701b1952a18885d3314d73738d2a14c57a4e64a663c7f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 447: Field Element(0x52c899be6e7be1b6bf3c6b4b07e02c699875216aa9a74d4482fb95222550ec6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 448: Field Element(0x642c482b65816e5395a439d6570af260568b0ecf22ad54827762ceaede5e277)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 449: Field Element(0x439a2be79855045ec4a5c762dacf58bcf749c5bc710e4a93f9c82c74d28c283)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 450: Field Element(0x68013e73e52a72cfcc766842670e4c958b00c4275de6442186f3e6dbcff5248)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 451: Field Element(0x45b636504284c7f4a49b5520aa1e06aafbd5dc93cf7e5a77bdcc085582f99b6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 452: Field Element(0x870affd951d7ea39e1509dbeff68e6f9ffdea6bcd81c00ab41222e784bf73b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 453: Field Element(0x726dc12112402ca7fd49fdc67313355e6cb8257a2e2549c0608701aff27e28a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 454: Field Element(0x6e3058e3118033c743c9ac1ef281f3bdb80742b2a0248f393c338b72b7d2f17)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 455: Field Element(0xe9a676677b45565db6ebb80b8fed23cc1a39aaefe1e6d441a552843ef4fa94)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 456: Field Element(0x6b01a72051238899d0fcb1a88ca52479409efe48df62eff8ef32acc525d80c9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 457: Field Element(0x231a87b73cb1aecf375d5c847f05b81e70e5280bad740205c47b17933d7ec9d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 458: Field Element(0x36c807bf963496350426388caf1eba5ec0bd45e085ddaa6dcaf02e7decb933a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 459: Field Element(0x648710f56b522b2975805228562d60dfed77b3451681c52c557813b3dbfd8dc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 460: Field Element(0x31e43915d392994ca7192fcbf3227a1806dbea437bc387fa13a438f383d1e41)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 461: Field Element(0x4abca775853fca1401cc65d40ffac02dec0661838a22b04caf371e923ebd371)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 462: Field Element(0x2c33a4e3c24cd95b51000e320a5d7f18d8ee2d1077399d764a7c2ec9d5fdbf6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 463: Field Element(0x3cd76ac11683c90513f0e973722004f454e96bd6c849b248e1c94a2ca5ef29)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 464: Field Element(0x4c9446204fa29d1771e847ffdb083d25dcebf7e4c5e6ab40c10fe8739cd11e0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 465: Field Element(0x76b3bac356a681d2f449c4a54dcc00a48a30c6442f401b744915e5fcd235291)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 466: Field Element(0x47347aae586818774784f4ec97b13a57390f1234b88be64cde641e4105c945a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 467: Field Element(0x65f2a74797ffab95d4545bf0ee8a967c166a5296139fc76ea8c80f936bc36cb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 468: Field Element(0x35d1e53f6390b2436565350792407cedca25ded67d9e2239a5beaf13c34366)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 469: Field Element(0x69c95d3ba6351a9a0d1fb5fcceb9d912efb1cc906ffe172da6f63783aeb3acd)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 470: Field Element(0x17e0bf8ca38920effb0718b49b3a7ad1340d98e7fb1774328cbf7df78438e29)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 471: Field Element(0x7237054d21daae719d79ca4164c1071f3f030e87324e687152784becafa8f06)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 472: Field Element(0x4525382ea98f3a44efc9897678098ef347e232ddfe79d18abad88165f4e9e93)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 473: Field Element(0x24f23f58a6c04d5a8a42648b562b341af7dc94f15a574d82d5181d77655d51f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 474: Field Element(0x7b76ae9236a09c98708aa326c0eb3df63f1e5e65b7c39b6bd23c37f9ccc9d0b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 475: Field Element(0x6c113a8293e01bfa3c72c017d37a9a763e917e1a42c9d246b89f680d24793af)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 476: Field Element(0x1cc1c8ac1637009e318231d356c55769116a2c85b3b84a17fbccfe793741150)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 477: Field Element(0x4037a208661d07bcb82602a3884df357fde49a8b5c9a684fae6e4fd0750338a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 478: Field Element(0x37e2de79b8c01856aeeb442982c115d283ebfb2b9bb361094d5d42154bb9733)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 479: Field Element(0x679d216772ef9b0a62e636e9926197041e92a8ffa54c80c1a4e2e679d5924d3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 480: Field Element(0xa2e13cca5b049050b3993635c09c836cf0427a9ca33b2417788ddb5e1f11d9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 481: Field Element(0x4d0f276dc3daf1e4c573de39ae88801b92ef8b40667d6af51948c93a21d9cca)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 482: Field Element(0x31709fa5f2b625c268569be570036e9faadafa089565bf5af64b3cb0533c0f3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 483: Field Element(0x18250c9b2f95614beb6bc461ea38c1f2389903176fc39c6912506eae6ce72fe)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 484: Field Element(0x6df161f26efcdaaae47cb90e84c96a197d6eeefb994f61b8d867c44c0462214)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 485: Field Element(0x583aa77ba7f817ea1e62ddc660c9c7315d440a5fa6a35aff4441cde6c9afb0e)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 486: Field Element(0x476f8fc19f10591fbd8839d6af460e7871cf04e962370713d44a60cd9827ae7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 487: Field Element(0x2e534a77879c93b5ed0e29f1e4e08c1281bfd0e6dd4f1af13dc2ce230b508f1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 488: Field Element(0x54d168f39b58005dea48a24da485367c5322e1e1d69fb3752497f30ccab56ad)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 489: Field Element(0x484da31d0b2267e490c32fe8438915809f934f19dabf1a7725f78a7ef65c8da)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 490: Field Element(0x3576faca21611b417e0b825ca806d9bf955b38d8aa9240a96e3774166e690fc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 491: Field Element(0x7814bab1d45a969ef5eed232a93ed53ef1d731fcb15b2840b049873fcb45326)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 492: Field Element(0x414cf664630c909e5d0f6a921b4c0b6e66b4414ad80f873892c3169d75f37c9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 493: Field Element(0x4be08dec78d79bb4226840e30a3511ed9fae26ac58459942fe787b1a7b88763)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 494: Field Element(0x275c251458126defea2e32eb46c10428534e3c67cb68d9642782a17e672dcb1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 495: Field Element(0x3471aca3be733f490b2769ecf75a3291671d13678a80121eeb59c55da76362c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 496: Field Element(0x7ce33b97d1cad9fa8f00dbcf9bc27943b67986707086b734f44295e31121423)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 497: Field Element(0x1d12e32a88bf8e7bbb201b8a5e7f4ddc3326ccc770ae067ee90fed3565843b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 498: Field Element(0x36ddd3237f6031c23bda8bd4bd4409ca96055879c6ed467662a9dde0d3089ca)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 499: Field Element(0x7604d232ee8fe162f55bae5f74830b1a948e17083ec7079474177182f041a01)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 500: Field Element(0x62c04712c6099049293829b40d9e75ee53bd204535121627fd663bc5a9f4fd3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 501: Field Element(0x4844a2487f3d8e83cc2c2d1817d2c3f07e1cab2abdaf7763b3d7a5a9f4bcadb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 502: Field Element(0x37835726fe7d3ec6bdce5947924c0fbd0c7a81bad90c571dd648e98691043d2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 503: Field Element(0x653028dce6b5b4d534d90f010498e9acbde87708debb15adfa014f7a8313092)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 504: Field Element(0x5d6ffcd066b6c1f37595d66b06284568ef542a02f41cee99ad2b7328e673ba3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 505: Field Element(0x17c3b801e043660373e51b193deb7a4dd07c297827c9ccf259a07538a151824)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 506: Field Element(0x34248b4649cf72fa97ec87610f7f19fc4374bd764d1a5976408735a237beef)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 507: Field Element(0x7a76168f9c35aa635d30ba6f4889d3691c47f567b9059d8ed9d62525f37112f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 508: Field Element(0x4f37113edcaf06ebf5c54e1e70dba290dab31daa2483a1f62001c440563f8b9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 509: Field Element(0x1c6be39caf5e5c5582f0e1b3b8867d46616ee6b4f7ea2b5bc2ea2e0b24e4176)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 510: Field Element(0x2ee3da3116813ac78ec1444d1ae8d6f09ccefa75cac67a2aaa6d37672cb7cce)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 511: Field Element(0x6b1df9279e95ce07c3ff5786e6b312902ec8a8b3bf5565fc30715ccb5008318)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 512: Field Element(0x64f54b8254fb6d122a44ef09617a615bab8b963727d4beb10a19b5de720c0b6)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 513: Field Element(0x78b1998b7c9bb7562fd9ffbee18f5cb86507a7da64c10e38ea6b5437f4dbf96)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 514: Field Element(0x63cf888482492453920f89912978b477c9cbf9aed2644330e876223017df436)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 515: Field Element(0x4a24fa2166eab25d1aaa4b0418e81eb4c240f33d89ebd81459f784598680999)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 516: Field Element(0x46763c29f759008af7c011283f63bcf7ee399b7815890a0ea2d508b40698e5a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 517: Field Element(0x15cb7df4d648e11830d58713bab329346bae538ab0cd25e4ac8485449d83106)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 518: Field Element(0x5f40921a0ccbfe13f8c5004f4745c41de7d254c2c7352f147c18522ff625cde)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 519: Field Element(0x47d79b63680f86f35966315662714ea7669c24bf162a002182f24b02a0b4228)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 520: Field Element(0x34a4a4bca2c7031267d7b059346d2bcc77c8b074eab1908e49f2010b0c58910)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 521: Field Element(0x117bb447110cac92e8a6e29962f15620eccbce5c9b1208b153c85e6915b9c96)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 522: Field Element(0x79e6cfccec422ddc22d4a77bd3ad25df4278a5c30a10b1bbd9f3a345fe9b224)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 523: Field Element(0x41007350b947c81bcd5a9326d5cd12d2e43b57ebb9cf4d9fa36a6e63d4c4ad1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 524: Field Element(0x618098eb1719ea810029684fed003e733fdaf264239a5f89f12e1771090d888)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 525: Field Element(0x381721d9227bfcdb410e2394254a164ebfa2baceb4ee5800ef575c040718623)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 526: Field Element(0x25e1d871f76addb64d770440754e21070c31962286d2c5c742fb8156b3b698d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 527: Field Element(0x43103f290b416d9c2b51bc1b3c2bea3b882da4306fa90c9f6c3f4756f37fcca)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 528: Field Element(0x1b010e5472b512f3a05b0cbd0179fc5ae864d29fd8a2a03dbce8e8c7a84aea7)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 529: Field Element(0x263efd1c87b76f65a7478f24d498d08600a2cdc5c2305a3ddf07e139de425df)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 530: Field Element(0x30609b804a07e7e8fd8cb93dfbe66b9e5f88c2793a563e01dae40af932f03de)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 531: Field Element(0x772173a9067c6c3a758e8eda71c115c122e6e9b7a9642d395e31d64b9431986)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 532: Field Element(0x3777b9da4f4fbd10b1da77e2fe3ffe574f999d9b3273b309d85533b041e0c1a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 533: Field Element(0x7210b4c30f617e7c5707e42005f401f2f253c9aebc9dbaa08672eb335ecab07)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 534: Field Element(0x765847a0e08175f8a9dd800ca5ce5b4202bb7ee489dc7db9f4b5565a586b0fc)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 535: Field Element(0xf7f0826b03ff6c4038ea96f24c52b20fbb79775e341f45b359cb878605188b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 536: Field Element(0x761e0bfe286fa4dc39708a7cfef57bb364099f4b5d07c41ba116d1fff60b130)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 537: Field Element(0x526eb2f6b84425736f8c0a6de48d3861fd7ca6160cd5078902500e11c74ab87)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 538: Field Element(0x5ea90cfa1d42c4eae76cbb839f521b75b301d50d917a4c00e2c6fd5a619d953)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 539: Field Element(0x7ede0ebb82e8c65f5e564343db4108b3f15301f1e3ac61a9ec7caf253618973)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 540: Field Element(0x375e5c5e76f0d7a647a6dbd0e31ce920431a0bb15c941c115327fe9881dc97)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 541: Field Element(0x3f99c919a39d6bad04fb5dbdcf5679350eb3233a06d0acbd17ce7da430c8e37)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 542: Field Element(0x5e4cafd986a9e593d9d0b958de1bf29a679ee24e2ef07823175f4667887be70)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 543: Field Element(0x2a837ad6d2e197ccc9a2cbf8a13b74b2ec5a043c72a7795ddec803dd7db283d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 544: Field Element(0x137e990bc5cf43364811015552e4c282ffe3204f8983ebb5e15395cc727e41f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 545: Field Element(0x624e2935349d941feeb82b30d3b939941ca102e95aeef5654b62373877abbed)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 546: Field Element(0x1060da07d3a4e3ee363fdf80287bd76a50358157f913f38835241254d2e8324)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 547: Field Element(0x6c5abc03797311b6d56b1b5175c61d1cee88edd73745ba80da45a1be9fbaee9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 548: Field Element(0x1c9383e8866ef49b47b999f1085865894a97352d0eef2a86e402cc762dc1218)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 549: Field Element(0x2485a8f95e0bfcedc453f01e8d0694cec194b310cf739be194c1985cb521b70)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 550: Field Element(0x4a97ee07bc17296198624c3a29c76b2ae1f860b17740c89f6ea33e177588d61)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 551: Field Element(0x41c2c2ab90cc4eb44bafc61444b0c079c867c44cfb3d2d6adfe64884a622929)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 552: Field Element(0x2d2d43c5ba37ba32dced0ef2742cf16a2e4626f0d891a242d0daefbdc43598f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 553: Field Element(0x4eeb7a3897c76760a2b241a97146e63ccfa0d0fce4adf9f647c97f705537d02)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 554: Field Element(0x4ffac58b124c3f2c0a803df8a16811908829bd111dcb72e43d4a4756f916b1c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 555: Field Element(0x761cbee68222b96c4e149991a9c95936bd6e804adfd448bcb94028d4d9d166b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 556: Field Element(0x36400cf8a266a470b9685cbd550c87f101aea2b2eb999f80c5e329d07ec9ab5)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 557: Field Element(0x1ae0b01dbc01a1985839ac1fe9e3885a2cdcedb3e9b38aacf1a66a648372bb2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 558: Field Element(0x3ef88cba80b34aeabb57880adf1805efa978e6072084829d279bc615b718a20)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 559: Field Element(0x445ae300589fc9bc8c9c6b309646bc729080a19f06d4531b45815da4ff18073)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 560: Field Element(0x47971ce2c055afbb996dc7409c89270bc6eff918f531529fbe6d6ecfbac6db3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 561: Field Element(0x4347d5b556c27457d8b2cc8287b1b31ea1526e6f9624f1e58be2b7655245754)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 562: Field Element(0x45b02f266aa10f700c4f04cbf38c3b993aa466192cafe8c58ad27299ebb544f)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 563: Field Element(0x708734b5ac00d71c8ee5e6b0ae6caa888c9c3d8303c959677c276d573d398dd)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 564: Field Element(0x5f44393227f20e6307d2bff3904fcd5e9b2d3d663d47d01fe4069feb22862de)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 565: Field Element(0x37f07c6917b2f775c33063daf46a9771669a624e5713f9c3151179dfc9fc66a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 566: Field Element(0x5e045f3d85de3d0e70921ced88357526b60c7993e77d64bedf8eafce523f7ec)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 567: Field Element(0x2d87e24fcdc3b5770522870867f015788c5e586f37f2eeed9f3a22c50676140)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 568: Field Element(0x722020bbca42d11f66d9e9240b77a9d4352ab4af23254a44652d9ad4d440da1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 569: Field Element(0x698dd2a41477a9c2a29d13862b30e55ec3b26f6b9a37b4bfcae846ba0b590bb)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 570: Field Element(0x159fef8d9eaaec76090004a04a1dd68822b6cdff07c6a66032c0304081dab7a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 571: Field Element(0x409fe8014e4df06503cc0257eeaa94631506343bd805b0d3cc4887417a525b1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 572: Field Element(0x688ac21c21809d6b23f4bf16d9a181b891e5009b5de02fab8e2875ecdec5ed0)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 573: Field Element(0x7af74217f3fb4da10e39b355c7caa35afa497bbdb88c30c2947c49248773359)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 574: Field Element(0x1a59d522b58d3a68f19f1f5206b114e1114808e920ddb04a1f6eacb43dfbeb2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 575: Field Element(0x4ff1013b6ab44306279f35b0ff02e57c12db9d3a12eac6bdd2ccd27618f0030)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 576: Field Element(0x6d5b8dc439eb61f68063ec7ca8956a5e7ff29b9c7a940abe4cdd57236ce4b0d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 577: Field Element(0x15a89eb3c56fb701ebd9c937b059a4243c2a6fe18c208f10dd55e4aa3a6af47)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 578: Field Element(0x294ddac0feb9359b5a0e50cb2107721698517bbb981ee9e7ca639cf9cfa07f9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 579: Field Element(0x45193a4610df60d3d044338f6bc2e6e9bb80f06fa6a8112aff748c7a6be6c63)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 580: Field Element(0x5a3fe5eee411637632aea16ad897d5dd83855772a07b9fcef8943843d4c1ee3)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 581: Field Element(0x28998c968b1ffda4bd90bd1618e08532d440f292dccb50f0ec0296d05f2878c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 582: Field Element(0x565ede63c4cbf70a48074a3a5076ba9ec64a09f7c728cd52794cebeee61f36a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 583: Field Element(0x68bd168f92fd4398130bf98e7ab558ffdffb1d543d8ceb89fcbcab57999dc31)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 584: Field Element(0x7716875f3c418bbb9e9452ea3cde3133788d5b39824b94715257522c2dc4b9a)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 585: Field Element(0x3e9aaa1590d175f3a10b4e745c854929d9c23eb7bdc1bb9c733ec9dfbff9a14)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 586: Field Element(0x1712342711fa3c26a1419c0ab8c6c7db433b9bac8c7955ece325e83fcb4a2f1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 587: Field Element(0x2bf159bb8ab1d4471b8744af6f75ff35c0132b9241d8905c510b37bb765594d)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 588: Field Element(0x293be6be92fb0507267d6f387734b8f67e3e670331fd8576ee97ccebfe836ee)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 589: Field Element(0x52d9834200d3a85767fbb6d31d895d2e18623887709cca9ea257450cad7bf5c)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 590: Field Element(0x7ec4fa67b45d4a97735813102d236fe131f847b4ec9d667b0b8a9d9bf4ea3cd)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 591: Field Element(0x3fc145f64371af552604967ea387e4266d0e9f702e85930083c98ae19beaacd)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 592: Field Element(0x7527afa6b3987bf2846e6436cc9c93963a9f631562d5f6de8ae8efa597ae6e2)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 593: Field Element(0x1dff58e50755d824e419f212bea28eb25ca152933afa7bbbca311316636c3b9)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 594: Field Element(0x14572afe0283a3bb1ac1723883a2797499c825b9808849e3bc1519e8136380)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 595: Field Element(0x6f235b7121add82745476c6e6141b6862a63ed65dff424b12508b21574b319b)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 596: Field Element(0x2ddb9e8e758e6d3ae9fe8ac2f7cb4151775169cfab6ce70614da07813dde7c1)", + "V->P: /cpu air/STARK/Out Of Domain Sampling/Constraint Coefficients: 597: Field Element(0x17d4c2ef4ab31000f4a26700f1f909cbe4ce254deaa41e89bf3f2611829a6f)", + "P->V[19232:19264]: /cpu air/STARK/FRI/Commitment/Layer 1: Commitment: Hash(0xfdc08957cc0c0c65ca8ebe551675039e85bed2b000000000000000000000000)", + "V->P: /cpu air/STARK/FRI/Commitment/Layer 2: Evaluation point: Field Element(0xd65c6ff8a79ab4726e8b91ab8764ca65d8ed8ac29c1ac0f4b742cd46f332b5)", + "P->V[19264:19296]: /cpu air/STARK/FRI/Commitment/Layer 2: Commitment: Hash(0xd656d0fa419a75d3e03bbc4e21cbb2d08b6d866e000000000000000000000000)", + "V->P: /cpu air/STARK/FRI/Commitment/Layer 3: Evaluation point: Field Element(0x50163c493b8312b070c0fe34f1eca90ea22f95ac4bcb55b8668a8ba36bac60f)", + "P->V[19296:19328]: /cpu air/STARK/FRI/Commitment/Layer 3: Commitment: Hash(0x647debf7b538efd6304caeb9b49ad931666ecbd000000000000000000000000)", + "V->P: /cpu air/STARK/FRI/Commitment/Layer 4: Evaluation point: Field Element(0xacd31928965b5b15a4e09d64372d3a877f23eef603570c4a7134aef80cb3a5)", + "P->V[19328:19360]: /cpu air/STARK/FRI/Commitment/Layer 4: Commitment: Hash(0xbd85fc591ec81c51b7fb90d74d2681604beed99f000000000000000000000000)", + "V->P: /cpu air/STARK/FRI/Commitment/Layer 5: Evaluation point: Field Element(0x6a30f98c7ac544f3637fcc8da084adf087cda8a35d0ef1a70b704e4bb522f38)", + "P->V[19360:23456]: /cpu air/STARK/FRI/Commitment/Last Layer: Coefficients: Field Elements(0x2f83e82a90aa673af546c1b393301f1f7893e47b2d40b93f44042608f428bb5, 0x7ede4e05415ad0ea61bb495cd57c75d21d5f7e8a3ba6d681c4f3c660620cba5, 0x7cd5de2e6fcaa99ff921aa9a936b7dabd3cbeaa0d423fd39a43aab88c8163aa, 0x7c4ae7199d581751b9077cab701b741c70a2598c2b1527f023d5e9436da24c9, 0x612059cd898c0ed7e1e426a7501451c917527cff322146889aaf78528278e41, 0x473c47f7103602b4274ab549a964ce8923cdf85481af94f67dab9b87c0680e5, 0x264f366c2429bf5f8e6e7154f038edcc4b289420bcaf16d50fc11cfb65209a2, 0x31763d26072ebdc1873b4d689ccd055443b778ca3a5d31a6843eca21ea1da47, 0x43515f93c2490d24de2b4559dc3570b7f4e91d13963d52f36cb97de84699567, 0x12372b43168d44ae6782b5c0e969763e19630a075f4b5dee40c7fce7411e4f7, 0x226e3a087aa0f56baac8977e15d13f4beea342073cb31324849e682692b5b48, 0x1b2997a8e290487e55f6696e7279e9f73c2bf8cebad08d92a61ebf3217ad445, 0x7634ebc076ba0e4c06bc39bf6c912ed920b88dac4b2703c2459cc16ae51afa3, 0x616944454aee399148dd29c180c8107cc72981111cb6df177e7495ae79b1592, 0x46ba4e893b5624476027ffd524ca7b0c5420cff12041213b9309564bc1330a5, 0x4932fb2b44a075fefc314fe365a0a0d662d956ca04207a8fe0e4f3d3997f4dd, 0x57545b5ddf585b1cd38b1a9499b8f64f6e02bb38021761d89f833358017c402, 0x7e1936a7b94225485f25033ee711206db5c7432ac8263181bc488584bd07d2d, 0x57c3ed95a15d705f717f27a3c44a36fde3014d9307d160d645fd6600acf9e64, 0x6c8e32253dd5cbbbed49d16f69f1ce150d9bb17a0ce242af70bfcf1b0eb57ef, 0x946c24b19eddb39309e6dce371dd8e89deb454f1a7b0c4497a662a5f6104e, 0x507b426289d34f61df2d61f9f801b35c5335c7906e981229468274b0df42e5c, 0x7c160566fafa289a0309e90129a94348f508a540c1e89c21935ca02d4466916, 0x3a37ec3c3a81237de2572f6191da6a176e4487ff063a92bfb488ff8bc1c23d2, 0x6611b945d87d2d426488619217f49d3359e95d45605f71a4af5cd511aab97de, 0x3e24640a6890424e66e5107cb4586baa0bf638c80d8d1e8277ae803fcb2579f, 0x1d61beadcb80b4f77ec12cf9838d946d6b4080707a3c6eca710c6ece8d7e142, 0xd7286063fcbcad3258cc5d8f51216eb74d2d9ba393cd4b83ddd3d858421e8f, 0x3c03469b580a4d27ed825f84145b83a13deea1f0c7adc22fc41e9c15f4efd9c, 0x67b82da025b3d654858e84469e0f78045478281cadda4fe4be0dd38fcad9f3a, 0x5da82b1fa852fd47cf7a131932fb499e117b5ffeea9674a39ff5f46a71dc2c5, 0x445d205f652190ad4440ba765495948abb4ed325d674f00c1750f10329b305, 0x1f3a6bb7044c7b93b78ae8664e29f08daee59a48267dac3acab99399218f99d, 0x159113516135ed8498765f711345f8352861169b0aa2f4ce1edcd4225f133a7, 0x462a84fe877c394adc8e8f1d98a55dd8c5e1413d50645fb139af9bff256f607, 0x7532b1a634c8e1fc90d1a740cea04741fb415deb287ea9248d072c7b6e54009, 0x25754c5391cd75d1fb060db9123965a38a27e094d22a30cb7651553af9d0a2d, 0x1642e1b89ca05c15c2779069341ef090d1eb7fb9a08ee340fd2eba29937974f, 0x295c3b1d631850c7056a251e4959502c44fda819b62f143fe549b0238bf4279, 0x5242dd18dd4f3106b4676ac0bc8e9d6d69c2ad679a4a772286e504f7f5df14c, 0x627369bfb223e132906a11b1ea0a75bb9df2366d3ada298516a453297fd4873, 0x672a1a6ef25f9765493bb635333fbdcbe06a30d8cf85e1b114d64317cc7e000, 0x511504adc7c37f9965dac5e2d3043e76d496120be4be48c22289314cd35eeb9, 0x640112ab2c13a9ae92864640503d0fc48ce431054fa8ff5e77a3b83ff106fb1, 0x1606f8bbdfba30e3efb41cf94588d1dd2a84b448e0862689ec350ef2891e0b8, 0x54cbd9a8a685c28e632a20d57e670730a6dd7ed9f123945c51fa9a89c73fb98, 0x2bab16c0e7065a04928854d35be668b23295c89136dbff0fda66ad0e48f9916, 0x3ed043b82f847d2ddc0f798d4d1d18a30de3c35c109b7e552893a33dadeaec8, 0x27661a15c8ffd6541fcefe5443855aa63d127fc04378e49611e71802a499194, 0x361bede60554b0cc6e10b5da692d31da391b1afb3367e07542b2a8f94db8e31, 0x6641f386aab30ac307e4dcf5d52fb2ddf9c67fb758c3d7592f08007a620f25, 0x7d1b03a6602d1ed1efb401f5f0cb24dced9418d0c209a3fa5a10e5609b9a240, 0x6d7ce6f85bbcbcae5b130cbe3d5d6c0cbbe8b485057d0c6ba65882d73506a4b, 0x360351848ec17dfb303a56df44db3a2537b5daa3425c8ecc507eaa45a2191b5, 0x3725f46a1afc14ef6a66873e68cce081d7d6ace0c9ee9164dc37fdfadd867d5, 0x46eef9385526c6e0c20323eb31bc890e8d6cbd0ca94af57c94b68b7d3266c40, 0x28013a06c1c84cc139655307c378528b9e558756848517eca97cfa4fe58b290, 0x73d25d2d8022579fd93f0c4551c7a0ee9adcf128f9989478578716420ee89b8, 0x3db25ad8fbeaa0c95bbad9710c6d2706e9b257bbec8a67cfe40c15b12b098c6, 0x782044b8d4d839e879c4ccdcf19e55086c25ef607bf085c97edc8d8718ed747, 0x64fcbec17a1b25c60b59d0d280b2702edc91e8aaecfed05e83f6436393e003b, 0x1f38dadc5ffefb7c913834d4ec9ffd5d74e913bfbb0b539d1e7d2676f3abf13, 0xc914a7d5fffbd5b7af58a3704003ae6d2d6c5cba431b3f9e2011bc22d502fc, 0x28c0d2a00964919740d946df6d14414d47e4bdacc7ceeba789ce28cefa44f0c, 0x421c7b668404005694513c570724ed43a93b6a98dcdb5a7afd629c806d5d865, 0x7e6b50e9e1fb0e743cc7aac5bf81d8fc0370d5c689f3c91bf85020a11300b01, 0x7eaa11098abbe39ea113ec5255ef1b0429637f141afd327280de57dae0c668f, 0xb178c2b7a77b5f149812e96eaa8638cf69af5145770c11ac8e7b9de76afe04, 0x6b7fa4b5dc623310877b46b0ba9c25d4ba93d7ee82b2e1c869ed21cf50cc324, 0x762c145504d1ecb8664351064cc186d4dd9ccda4f3f405fb10d4cac160983b, 0x1ed81d3cdb197a3dedee5f5a91985b121741b17cb078a144861b0c583587262, 0x5d8c4a10c62c075452cddead1b698314ebca692e1970e06b0141aaef487377c, 0x1211e1ad78c68498f2ec79db3a95a63db2980ede6fa755f222274307953ace1, 0x1113c83ee3ef27ffa25cb70de8b0e7d5f347f28467abbed878d5e8a57b4777e, 0x76e7aaaed83c9b1b1fe1ef1260f683be63ec670b02c5e06558b80a172acb589, 0x41d7c7f738e42864bf44b8f734fd06994c73b12d7d4425d7dac088a54d8e49d, 0x5ff240eec65de2bbb55791a09ca893c7f5b066e74374982bacc94f128afe6d2, 0x680f9273c46388071938dd4275759eedf3acedb09fd08dd2a41e5c7716a03e1, 0x42505f0ce5b421648e30e9093e0d7159beb91f4dc63d4149c2105d54136a226, 0x3cfc56156faa5c75e57f8b031798d5eccf233217028488eddca9c57dd72e843, 0x64ca7a767f3dca798ee3381baa03f6ada54306d063cdd126f31b7e0385a13de, 0x690149e89dcb3ef6465276b11bf810f4e5d78deec9e3da7c180513344d67a6f, 0x520667903eaaa9c90988221d926eda0e80990ccc5e2abd16809eec3dbaef9c1, 0x6c0decb9072043fb4c111e084ba2c76d55c598887c7019c1c9f3a8289e82916, 0x105757196fdffd07aa1177426f088c799de3ca40832fb718e21b5daf5676c2e, 0x404cca0338d0ea9ba329472c8d720b2f9170593956760a5470fe54afd346bdf, 0x396813321d2728692116a97d6e91ac29378349cabdc3c8c66c733f55745f471, 0xbf71e53218dde4daed7fa6ec4a7a25b4faa1113a52fa056f52e453a24b259b, 0x30594e2da48e8d1bf8414f860df8e1900253f2961e707571c3e35fad78bb741, 0x545cf847e6eed02f3a2a3a93673cb5b03d6a5fe8810eeedbd9f7acef8f8bd9e, 0x1c6ae657a46e6c9e03a46c24e1199830646186e187c576920c0a823429f15de, 0x4a26e9d6653b106dd5f79d82321616d09d04408c5b26ee1e075cf0ab1b6f18a, 0x2717d0a853f50af6819ca40de680792d878265224445d45ac826a9f47d70adf, 0x5168f3132826671a62731dba317663e697b0f56952b83ce56378f9ea29df245, 0x6823a99ba9f465ce96f5b9c38d172878e1b6e01e47fc7c4dbcc65dcffe7b171, 0x93eddc4af6718f71db9034ec555965def5aabc8d6b3be8ae72e544f340ab5c, 0x4a2d167ab5b34a8a1be3432f4187a6c13d82a42ef5520ead2a2074ab0493f29, 0x3da227beb1b1941f7a57b7aa6188538ec5e366e6e4bfefea36ad58aa8e44186, 0x599d10e1ef21f3178ce81be8edf988769550d9cee6463436dc7eaba43baa834, 0x2766b10e1503f9c3ff6108d06e1dbecd59f060db45f6d8384d1c6aeecf44c83, 0x177b4293a75d784a39842cacc365192488521189301a2dbc9dbe104603df568, 0x29fc64b84f5e3fcc6fd3e64a611c579e2bd0e1634335ade1c49dae051af1288, 0x7c658cd922dcea7d2db203851999bc61e849a44e1975c3fde0afa72b8553581, 0x1cd5d9f90a08e70ec78dce6a69527c909b06968b2b3b834d0c412be680e1abb, 0x471b4ac11d12515bc8c209d4f6d9169d9fc5ddb2fbcfd8680fb03a446895db3, 0x3f6ef945d262f14d85bf49b6cfc0186937e362cc0c3ed95cbf7013ada49f159, 0x3bad9528a1cd7a3d3e981a7ae8fea92545a0c2a9750d977d751a7cd47324f7c, 0x14097285439b09d5f7f7b450ce54edf11f14af43a7ec6fc3a86acb506030c97, 0x128a2abcd255e74056a04ff9e4c318cc390a0ab4676e9d226769722685fbf49, 0x41113b628ab6599567f0d32f1989c3bb1bc3a2da6ddc88498d762d30c7ee3cc, 0x6a71b63c892211fc80400f569d1ffb1b2cfdc74e5a1230b244c5b69c6ac1f90, 0x49314846b18b6d3358c37225b4be0180f1c05ea60ed572e32c4d493fd90cdbd, 0x5ae53f1d09b00c4b6b95a8e2ab917a88712c6a404d103ef32e19c7287a0df71, 0x583f397b81fa8fdafb5cf4882c9192a39e09ff209fbe9b2c3814b4ebf27da6e, 0x4feeb50af11789af58d381499e4ce95c50e235202f201520631552c167ae863, 0x42940eef3ed9a5be68861b4d6bd009482920d34aa51ef7922919af738cb9468, 0x69db1e4ebe8ddfeb561158d01213510b22adbac44e166572b6bdfedf32128aa, 0x3d3a8925ce6fe99a77703071407bf883b5e001c8f3f236988e8bbaa2b7bc406, 0x239565a489a4eef1a4cbfdf6c8666fd8b0f1cef0d90142a8d750f287a5aa0dc, 0x4a247913be945311677674e64eb0b805c147124455b65019e78621f98f6244d, 0x7b72131006c2b0d6a5f97bdd607ffde1ce48c721e9a39405df033c7c770369e, 0x1733e457fc239d377fee9434ca0d3456511eca87a23e725b557babb18c2642a, 0x26cd4dc9c2d4966b37cd69c782f954d6a5f59aba7356af95701c7dd5afeeb8d, 0x4abe301b407009e513a6afab284891105d06fea77a5702628f2976efa841d5e, 0xc75f50a45189423fe485b78f93309e2d70589a9d529ea71a32cb7031aa767b, 0x5857ef9af2165dd4bdddebc3022bf50ff4c0d8416cd7aaf7ff2ceb7da2487cd, 0x7a3cb4ad0a461694e0b637223de76b084f2390418b8a9534fb276cb13e89109, 0x5a27e5b19b7108c012e8e273c63a7cb94b9b3dff13e4464143dcf330c47ff6d)", + "P->V[23456:23464]: /cpu air/STARK/FRI/Proof of Work: POW: Data(0x9d999)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 0: Number(6768031)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 1: Number(6359094)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 2: Number(2284596)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 3: Number(2071439)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 4: Number(1103176)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 5: Number(2230304)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 6: Number(139993)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 7: Number(2656598)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 8: Number(5455705)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 9: Number(8115330)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 10: Number(4631593)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 11: Number(1834537)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 12: Number(2110874)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 13: Number(2295414)", + "V->P: /cpu air/STARK/FRI/QueryIndices: 14: Number(3513722)", + "P->V[23464:23496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 139993, Column 0: Field Element(0x336306c0dd572d41544469bc5795e530373077e8fc617b6135a93e78eddc2f7)", + "P->V[23496:23528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 139993, Column 1: Field Element(0x5cbce8ac821e414468ae6e131627d3e56dbcb877392805d8d74513b49f0b0cb)", + "P->V[23528:23560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 139993, Column 2: Field Element(0x6af42956b86c70c1d8c22e54085ab37544d911c72ba2af0c087935524576367)", + "P->V[23560:23592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 139993, Column 3: Field Element(0x229f3ca0c31abd9be1f9824511222f2f644ec3c19e893b7a307027e0223ff2b)", + "P->V[23592:23624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 139993, Column 4: Field Element(0x42e2aa6ff342634a2a771667b473ed66ceaa074af3aa1831cdc343c281bf923)", + "P->V[23624:23656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 139993, Column 5: Field Element(0x2f2652d3bea3f431d933e6d21b7f4b44e1cb9f519f64d62b37b5cf865e44d17)", + "P->V[23656:23688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 139993, Column 6: Field Element(0x7c58f4d21d6665ef0c52d0b9e6251a79eee2a98f1c677c308bbf05f0fe752a)", + "P->V[23688:23720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 139993, Column 7: Field Element(0x74113664222cf6f69edbf152129b40b927491da5e55813f16ea49b42668ee0)", + "P->V[23720:23752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1103176, Column 0: Field Element(0x16b48db580c3c9e55ec1f5cf33f931d0acfbec666af56e464a59d0b43c5d0be)", + "P->V[23752:23784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1103176, Column 1: Field Element(0x68baff66e86e205ed3a7cb31763ef553f22c0bd308bf76919a424c7edab9150)", + "P->V[23784:23816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1103176, Column 2: Field Element(0x2ac07ddafa1a7b95160c8935e638bbe6950473cf29945134d79bf2e2ffda295)", + "P->V[23816:23848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1103176, Column 3: Field Element(0x5dc16a3699af61dcff4d8800cc8f7d15aa5badb92a5668d128aeb200ec1621b)", + "P->V[23848:23880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1103176, Column 4: Field Element(0x1ec787daed7f76e666437849da9c8c9cfd3ad7fd098cea7640da63588230fdc)", + "P->V[23880:23912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1103176, Column 5: Field Element(0x696ff15b916cf05698993b423fdcdbed169cec1f204966a9062308e3a5e3efa)", + "P->V[23912:23944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1103176, Column 6: Field Element(0x5eb74dbc993504380062505ed91e8da5a1ec4fc79a3422f3cf5dcee6ab5cd76)", + "P->V[23944:23976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1103176, Column 7: Field Element(0x6433c8b89893116ce9913dc8b126df2f9251d8349649a8cbd244fa1ad546033)", + "P->V[23976:24008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1834537, Column 0: Field Element(0x6923eff954895b1f1c9f3c282022bfb67034ab258b932f80405fa84ee76a9e7)", + "P->V[24008:24040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1834537, Column 1: Field Element(0x294df2f85d5fc5573b9ea50722babedd354094c0d36e7a29f40c86134d6d4a4)", + "P->V[24040:24072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1834537, Column 2: Field Element(0x25a2ca468d8a84f450b47458606a312ec5aba69e60d31c085530eace6e61ab0)", + "P->V[24072:24104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1834537, Column 3: Field Element(0x20fe38fadef7644c8756aaf51acd3d164e4c8975ca6a30f17399fcb4c4bfaa8)", + "P->V[24104:24136]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1834537, Column 4: Field Element(0x2a31595cb4fa1e300769bea373851897b79721467289512239fb59cc1c12b80)", + "P->V[24136:24168]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1834537, Column 5: Field Element(0x3e71b10865390930734463afd5dbe4582b61dfddd1656f0313ce586f50f754d)", + "P->V[24168:24200]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1834537, Column 6: Field Element(0x2a2b9c6f20067fb012f3b75d4afa6b0bc66b50e366307de22aea58f07f147ec)", + "P->V[24200:24232]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 1834537, Column 7: Field Element(0x24ab889cc0b308f48bc9fd51f1fe77fc46752a4c7cf13ac5577bd599df15ef)", + "P->V[24232:24264]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2071439, Column 0: Field Element(0x274192ed27537bc5f8d5981bc51d0520a8c36fa89409f5410748ec38d134254)", + "P->V[24264:24296]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2071439, Column 1: Field Element(0x5bc4143226da54c275ac708761464fce47b640b1ee1f36e73d2377803df36fd)", + "P->V[24296:24328]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2071439, Column 2: Field Element(0x3cbe401980ae9334bb721d53fca1b591842373d59d6b320218314fd5e94b956)", + "P->V[24328:24360]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2071439, Column 3: Field Element(0x4361539a6c813b2fcda01c661443f5877d7e3357728792e7b694cee85d17bbc)", + "P->V[24360:24392]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2071439, Column 4: Field Element(0x54b642962f7c468ce5417657a6e302fc9712c8d069afc4e40ce4a999a2fd3ce)", + "P->V[24392:24424]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2071439, Column 5: Field Element(0x1abc051d6c5c5c66425b395edbb4084282f06f5ebe187c6f7c87dfc5b66e7b9)", + "P->V[24424:24456]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2071439, Column 6: Field Element(0x2436612ecb7d463878e48f6696084e77b0c0964d119a1a9ce103f1e228540da)", + "P->V[24456:24488]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2071439, Column 7: Field Element(0x764ef3a7825097cb5b1b4a2a7aa5652b62d3424e6fbafab7f70cdbd5c2c802d)", + "P->V[24488:24520]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2110874, Column 0: Field Element(0x20d49d6af50562093038d812356fac95e0f9fee9d3204ed9c878a5ee2a0af25)", + "P->V[24520:24552]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2110874, Column 1: Field Element(0x1bc735b54689a249c2cd9af6c3cf8e4899ddb7985552b783dbb6fc33a0d93e8)", + "P->V[24552:24584]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2110874, Column 2: Field Element(0x6b573403ff4ae15e3db90ededeb3da5e5df29215c1722c2994cbca244bd31a3)", + "P->V[24584:24616]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2110874, Column 3: Field Element(0x29e2c2c1dc4fa84d88ab317782b49bf609b27764885563e2c2f4adfd9afb6fb)", + "P->V[24616:24648]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2110874, Column 4: Field Element(0x6f52b05bb44f2c97d987ea9f3be86d68fef2ab70986448fe37e8736c2a127b0)", + "P->V[24648:24680]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2110874, Column 5: Field Element(0x58656a7bf1f351d75dee287aca4b5b5cda456fa14c5ace87ffa14a5d8c554b4)", + "P->V[24680:24712]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2110874, Column 6: Field Element(0x74bbb689b93478a221ab3b9a3b3fbd5b29e53c3fba5b272b0706b5b1ea19be4)", + "P->V[24712:24744]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2110874, Column 7: Field Element(0x57dcb31a731085f795c24dc5071ce790b6f8c3f2b920030fcae87638328e0ca)", + "P->V[24744:24776]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2230304, Column 0: Field Element(0x7c3f7a02efa742f06392c7c27b19c9992deb55e4760cd9477cdabb4b6e31d6a)", + "P->V[24776:24808]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2230304, Column 1: Field Element(0x3157db5696c2801efc28e850c232023cd5d8beeecfcd204af07d270ae2fbaf1)", + "P->V[24808:24840]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2230304, Column 2: Field Element(0x1de516393f8a53605eb915060a163ef59170e806755c60e8e8ebbfb651b42b3)", + "P->V[24840:24872]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2230304, Column 3: Field Element(0x724167dda274409a06f6f80885ea1cb05d998bd0109f696b254e7746a88bfd2)", + "P->V[24872:24904]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2230304, Column 4: Field Element(0x7ce506c475b15b9ed0d788c501e1e6d625d210b4ba532adae5d9be4e5fbdae)", + "P->V[24904:24936]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2230304, Column 5: Field Element(0x37898e7984d5279ce4415ffec4afc70cae2c8ceee1dbef2aa02c0f318268afb)", + "P->V[24936:24968]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2230304, Column 6: Field Element(0x6c6ab93287748300f7d9ac4187e660c334b85844859b4de8e5f0265120f1cf5)", + "P->V[24968:25000]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2230304, Column 7: Field Element(0x2909b1e7943875b1961c4f6f01f8daedb453434483ebbc4abea1cf1807ba91)", + "P->V[25000:25032]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2284596, Column 0: Field Element(0x98f8eb4fdb9f056b6eab1747f3266934cfe274823e732b427c1c63ffc6c163)", + "P->V[25032:25064]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2284596, Column 1: Field Element(0x3a730ed69762880ca95932e434d9e09e576651f8f0d060fc8d1312e31b9bd2a)", + "P->V[25064:25096]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2284596, Column 2: Field Element(0x28434b7366fb68a824f235d2167e64ea90cdd3fe9cc5ff22831955bccc96d3a)", + "P->V[25096:25128]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2284596, Column 3: Field Element(0x4c942ee52f35c8e03c1b62340c5f212e04aefe80aa7940b773523a4f9e74f45)", + "P->V[25128:25160]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2284596, Column 4: Field Element(0x7e1f1ea082bf46bc613a7a187f79328a542ffb6d5b23e2d01c3632203e2808c)", + "P->V[25160:25192]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2284596, Column 5: Field Element(0xae15f485b5bc69d76bbd4e3110522e890508a85545813f5c17d9101cf3381c)", + "P->V[25192:25224]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2284596, Column 6: Field Element(0x3912a2886bcb28a52252e2daba45fb1bcb0e07f5bf60ec49685a18f8197d35a)", + "P->V[25224:25256]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2284596, Column 7: Field Element(0x475b8951d61692dde37b66fe4164afaa2597f296e719163c91ac18d360f5c5d)", + "P->V[25256:25288]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2295414, Column 0: Field Element(0x6d6c9ac14aad77728c505c5dac2405401d6a666e57aa3f3d802f8ed19cb6c05)", + "P->V[25288:25320]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2295414, Column 1: Field Element(0x395a237f9fcc7ae385e65cdbe091839f2c522099d4a01fa82e335aa77b3bd2a)", + "P->V[25320:25352]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2295414, Column 2: Field Element(0x2bfd6a5eac39e59d98a4a179b8122452679828fa4006b411755160e2c6998de)", + "P->V[25352:25384]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2295414, Column 3: Field Element(0x366c0b92d586fbfa1daa35d7c6198ef77a654b9f07a1ae172c45e61355f615d)", + "P->V[25384:25416]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2295414, Column 4: Field Element(0x1855022e261cb5ce69bd34596d5c3163dc678805766482aa0f7cca934b9b68d)", + "P->V[25416:25448]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2295414, Column 5: Field Element(0x62bba04d56431a09a7b3c6c9ca5baedda2b7a84ebbdbc12b0d70699d384d5ee)", + "P->V[25448:25480]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2295414, Column 6: Field Element(0x6f255d1b5583366b9e4cfa5bd65e23b19c08b96530938857b83a638d02a2d03)", + "P->V[25480:25512]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2295414, Column 7: Field Element(0x7e6ecda67cf5a0bb308e4a23d3b9836008541eb56352b886462a64da2aed5af)", + "P->V[25512:25544]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2656598, Column 0: Field Element(0x474935c846674dc51af288ee8c47c559963c1b40d9ac46218f50158da1d9fb)", + "P->V[25544:25576]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2656598, Column 1: Field Element(0x589852e184e933e048f8492145df3f448e28fb865a6222890f393b72a027be)", + "P->V[25576:25608]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2656598, Column 2: Field Element(0x210e87a4f9f2d0c4f8ef76aae9d725a586ad74395d609f6edd5b76fdd67a289)", + "P->V[25608:25640]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2656598, Column 3: Field Element(0x876de6744cc7451b78f656c8f94905a1bd2cb2524a94af3f0f20c0abeb1fd8)", + "P->V[25640:25672]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2656598, Column 4: Field Element(0x49c23b0a7c5b17c92e4e196a06cf960b21aa5e395086f9a9b2cd2978d0201c0)", + "P->V[25672:25704]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2656598, Column 5: Field Element(0x328a69917e9c1a3418c3ceeb3acda043fafcd843730de1af567b337806bfaff)", + "P->V[25704:25736]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2656598, Column 6: Field Element(0x41d1399f4fb3b995c4c2612cd2b8b39732453fa690bb202991497233293f593)", + "P->V[25736:25768]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 2656598, Column 7: Field Element(0x25242609ae04b4747f420aa2dd1a51d8561b322efb3d09d0874087c716a8b28)", + "P->V[25768:25800]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 3513722, Column 0: Field Element(0x4b1d044287ee94dde60c7f3291f9434da8480a2b3c7550e5fb8e6fd3b7a7f1e)", + "P->V[25800:25832]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 3513722, Column 1: Field Element(0x74530110389e0922a974090400eb187679428a0ae595e9342aef2adb89dcc80)", + "P->V[25832:25864]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 3513722, Column 2: Field Element(0x125435b6b762dbc148e1094717b4b3ed71a05bc6c7e88d347d9b42d4b30aedf)", + "P->V[25864:25896]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 3513722, Column 3: Field Element(0x1f3e3b4d16d9023f55197d823e4ac6e83d35f6b226b8f682d65a91e48463486)", + "P->V[25896:25928]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 3513722, Column 4: Field Element(0x422245a7ea90bfe2768b3ef9a3e045f57cf25fd5c8d541189537dad1011aa4d)", + "P->V[25928:25960]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 3513722, Column 5: Field Element(0x27276c0249cd8e954c58ba6288bdd6c1cd22f926f6c5571dd2e99aa9f68bbe)", + "P->V[25960:25992]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 3513722, Column 6: Field Element(0x351d95fbcd8275478172604858c8853f8134b5938e94405040dd4badedaf866)", + "P->V[25992:26024]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 3513722, Column 7: Field Element(0x7bee7264ff443ee9e8fb9c68f2f7c05981376cfcf1724781706d55c6e6f6b27)", + "P->V[26024:26056]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 4631593, Column 0: Field Element(0x2d0bebce4f43e828827f95e49a6365f6f60de498e2b2d4e14ffd5aacaf06fda)", + "P->V[26056:26088]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 4631593, Column 1: Field Element(0x63de8ee1065f56b75ba2c3ff61ddc8b67c7b100138bfac3c53a98be671eda6)", + "P->V[26088:26120]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 4631593, Column 2: Field Element(0x32295ad14fda49521e1b6df0c4a1c1c7fbcce84d26e399574828465a9ed919f)", + "P->V[26120:26152]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 4631593, Column 3: Field Element(0x674b6e53b819a1ab50fdd6f738381717d7d140dfa6e58f9b031cfad8af876fc)", + "P->V[26152:26184]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 4631593, Column 4: Field Element(0x793c72d4e5a80ff0d7327b19cf54b31b2e5e49df8ec4b87df51cefe51990db7)", + "P->V[26184:26216]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 4631593, Column 5: Field Element(0x2f104d64721b4ae4cde163f6a7138e96f0c1551246316417576e944ee5c4b1e)", + "P->V[26216:26248]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 4631593, Column 6: Field Element(0x272307a77078952cd161f6281358bdc2de95ab25b1ebe433037ab172f937302)", + "P->V[26248:26280]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 4631593, Column 7: Field Element(0x4ff296605854cc533b36974f16b22688560aefe91fffbf9be9771b58eda3e61)", + "P->V[26280:26312]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 5455705, Column 0: Field Element(0x3fbbcb6c16a3797c0d360468193ef50f1efd128ecf6fc92c21b464b943072ba)", + "P->V[26312:26344]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 5455705, Column 1: Field Element(0x15773dbf0f4d4534890ecfdbbd8583bd57c76449dc67596316c65bb3854d934)", + "P->V[26344:26376]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 5455705, Column 2: Field Element(0x8c15d5aba5c591424290fc605cfdf57e569c82d09ab89a30c57b523af71cdf)", + "P->V[26376:26408]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 5455705, Column 3: Field Element(0x5a8e8505bd014c072c1283fe1069e23ecc1e5ffe4e19e75fdcab0fc6ef3b3cd)", + "P->V[26408:26440]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 5455705, Column 4: Field Element(0x31a1e92a43eac1833f9184a20ece2fbf5570e8932aad9b4d7579fc8d975de3f)", + "P->V[26440:26472]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 5455705, Column 5: Field Element(0xca3f9ef0f54f918e46a9b89553afac79b39caa2db38ce83c2a52e5049aaca2)", + "P->V[26472:26504]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 5455705, Column 6: Field Element(0x1000287029da1a0d0a80e55bc9e14ba3330c31a31683d341d9b0807fc7dcf9e)", + "P->V[26504:26536]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 5455705, Column 7: Field Element(0x6814cb7da14ccf59b1c5ac7a9932fdf486e93c56d88b47f6eb2ac2696d559b4)", + "P->V[26536:26568]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6359094, Column 0: Field Element(0x7fa167804caac286d0635d29fa30907980080ba08d7ff99501e5f9d97335d95)", + "P->V[26568:26600]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6359094, Column 1: Field Element(0x26542544732f45ab1241e86bddcd59acc0fb61d7734da3de0d1603935d52f14)", + "P->V[26600:26632]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6359094, Column 2: Field Element(0x267bd8cf84c1c5d1160badee9c4e5343c7cf1ed72766a4e2c91782d3fa2223b)", + "P->V[26632:26664]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6359094, Column 3: Field Element(0x5ba639f6a7b81ddfa58111b612ba90fdb0e0ea78e35eee02ee0c850fb800e65)", + "P->V[26664:26696]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6359094, Column 4: Field Element(0x733ba0332939301afce648a27c337f63e0138e394b57306b81f3a076550f3ed)", + "P->V[26696:26728]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6359094, Column 5: Field Element(0x1274b0b609e4e42b878313015c278e1f2034bce18050b2584b32380b48245ad)", + "P->V[26728:26760]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6359094, Column 6: Field Element(0x2890844cb545c5d6e59a3b1af875b04d730e37f032d222b5a1cbdb725624c13)", + "P->V[26760:26792]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6359094, Column 7: Field Element(0x38d567eae476c6004ca93da762bc985ab1b9f88aa885344fbf5558e9563632b)", + "P->V[26792:26824]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6768031, Column 0: Field Element(0x7fccfe6cc93b520b1d59d02b5cafb0acb84be6543acf39458b65e9e82a71e5c)", + "P->V[26824:26856]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6768031, Column 1: Field Element(0x4c85af4dfdb7f77f13076d9189c2569ca533dee383a83caa063936abccade99)", + "P->V[26856:26888]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6768031, Column 2: Field Element(0x34c179f85ff79d2df587221d169f12e6f8d527eeac4d6cb5e7905e9895f95fa)", + "P->V[26888:26920]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6768031, Column 3: Field Element(0x6c47f03f01e5200c897a984c5f374510ac7e53ae3e4003b6e56a97f3ae6f2aa)", + "P->V[26920:26952]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6768031, Column 4: Field Element(0x3390f035f2a1e6864b49dfa49f9a9670cf4cf358af12d479dd962455ea0e402)", + "P->V[26952:26984]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6768031, Column 5: Field Element(0x441c8e44478bad4726e1ebef1cd3fa82d4d36a20aca0132bd5183b0899e83dd)", + "P->V[26984:27016]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6768031, Column 6: Field Element(0x3c8a272b97ff4851b69b49a8ccdf9d98244b3e37f15966e3412e25b5a30a67)", + "P->V[27016:27048]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 6768031, Column 7: Field Element(0x3767dc6f34fff0b35cb4b990d0eb1e3222c0b49ffc9f6aa98e820806861dea7)", + "P->V[27048:27080]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 8115330, Column 0: Field Element(0x2fa4e48a89e78cc6959f710f56821529988755e92af4b8dae040edd0f7946f4)", + "P->V[27080:27112]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 8115330, Column 1: Field Element(0x33f8c2b2e8cf43bdf037c79a79a59d59a5bf2491e808ce3fb0e46541bf5a74c)", + "P->V[27112:27144]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 8115330, Column 2: Field Element(0x121f7356908bf7a131ab3fe42a685d18e14ab7f066ce54dcec5238426ad8045)", + "P->V[27144:27176]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 8115330, Column 3: Field Element(0x18e8b5a405aee5ecc50482ce5050ae28f03c1fc10d981f78fe7edbf45dcd72e)", + "P->V[27176:27208]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 8115330, Column 4: Field Element(0x48d7dd98396282776f9919433f51eea1a011f0f75517c68b7d61a59cce84c32)", + "P->V[27208:27240]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 8115330, Column 5: Field Element(0x7eec7591b11908b6657018575df7732aecde357f5dba16a4b4e68466a408c7b)", + "P->V[27240:27272]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 8115330, Column 6: Field Element(0x22995ff8576d0c90c5b38cc73dd48c5ec115e8b7c76c785ae6328477771203b)", + "P->V[27272:27304]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: Row 8115330, Column 7: Field Element(0x22d0e06fd6b1e0fb267a012480bec7a276037d98d9297b45c2eeb74e6abc88b)", + "P->V[27304:27336]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 8528600: Hash(0x44bf8437ecf00396ea21ccff6bbc901b3cb86cb1000000000000000000000000)", + "P->V[27336:27368]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 9491785: Hash(0xe289b49cca1264fe1a0ef8c5883fae2d9070d5c3000000000000000000000000)", + "P->V[27368:27400]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10223144: Hash(0x1a3c40acb4c3752f5aca6f3593e993f520ba9d15000000000000000000000000)", + "P->V[27400:27432]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10460046: Hash(0x7b63eaa4e2a7de1784a9c8321a2eecc5f8965cea000000000000000000000000)", + "P->V[27432:27464]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10499483: Hash(0xa3ebe499c9183cd132e6aec31e60f1e7486fbbb6000000000000000000000000)", + "P->V[27464:27496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10618913: Hash(0xc4f2a7462414b975a91cbe821c84d8abc2338c9b000000000000000000000000)", + "P->V[27496:27528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10673205: Hash(0xdfe9d74a596876e9f2bb3fd27ebe3fe53e3d5edf000000000000000000000000)", + "P->V[27528:27560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10684023: Hash(0x1114f0ac6756bd8e76d9823d03ac91bfa75e158e000000000000000000000000)", + "P->V[27560:27592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 11045207: Hash(0xd6c7e0ede664519ab70c5a6557fb3ce163bc4b23000000000000000000000000)", + "P->V[27592:27624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 11902331: Hash(0xab415c3a55913279a2c45b4daa1668ca7e494d04000000000000000000000000)", + "P->V[27624:27656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 13020200: Hash(0xc2330e5cc1967562f657925a92b3822240c05fc9000000000000000000000000)", + "P->V[27656:27688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 13844312: Hash(0x6670ce1496621e1a4c9e526a534944560534df46000000000000000000000000)", + "P->V[27688:27720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 14747703: Hash(0x91947a93deabcbf33cbfb6478f94b888efec7b45000000000000000000000000)", + "P->V[27720:27752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 15156638: Hash(0x3a9d2611bcc48dbe5725416f6668ffad02018230000000000000000000000000)", + "P->V[27752:27784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 16503939: Hash(0xd87bbc07fa724cfa45ddfd3f96880e2af999b06c000000000000000000000000)", + "P->V[27784:27816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 4264301: Hash(0x3f15d7d87dffdc1fa4f3b7fb24b7605cada7bbbc000000000000000000000000)", + "P->V[27816:27848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 4745893: Hash(0x92c39132782b6a91086b36112a83cd4576a8f030000000000000000000000000)", + "P->V[27848:27880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5111573: Hash(0xbcc6add4f1549dbb090c39744bac9a1c63dae8fb000000000000000000000000)", + "P->V[27880:27912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5230022: Hash(0xadc5904d2dd1bcc80122c99cf0baa9098b7f618e000000000000000000000000)", + "P->V[27912:27944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5249740: Hash(0x41baae9be62996df91dfb8edbd3bb0466d999ef0000000000000000000000000)", + "P->V[27944:27976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5309457: Hash(0x19d50f91b4902fa02e94dcfc79237a47bf4013b6000000000000000000000000)", + "P->V[27976:28008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5336603: Hash(0x9e52bfe77a22a4ab806b89213f18b45e9ee3c4af000000000000000000000000)", + "P->V[28008:28040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5342010: Hash(0x9dd4b1895423b09bd096297cb6ed98808bfbefda000000000000000000000000)", + "P->V[28040:28072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5522602: Hash(0x4ae1d8074e0da54208c71fcc83e4bbe74245b564000000000000000000000000)", + "P->V[28072:28104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5951164: Hash(0xd058668c36588be15d0a898c207c34e2a31d3d04000000000000000000000000)", + "P->V[28104:28136]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 6510101: Hash(0xb21c0d1b2ae048a2729522f766e88829057bde83000000000000000000000000)", + "P->V[28136:28168]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 6922157: Hash(0xcc3ed923eec53ac5e2d878180d077c043ccf2f52000000000000000000000000)", + "P->V[28168:28200]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 7373850: Hash(0x6a7d770280eb71873c52ca9b1df71eb08355e566000000000000000000000000)", + "P->V[28200:28232]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 7578318: Hash(0x6872ba321d5b3865b32db3a76fc399ee9f0af9b8000000000000000000000000)", + "P->V[28232:28264]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 8251968: Hash(0xe68e356d5e06909bf1d3076e5eaab3803153df56000000000000000000000000)", + "P->V[28264:28296]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2132151: Hash(0x6f3bf7d6616a2adabe7199249a6258671d5034a7000000000000000000000000)", + "P->V[28296:28328]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2372947: Hash(0x7cda735a9fe506109cc425fa03c8228fb6d27516000000000000000000000000)", + "P->V[28328:28360]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2555787: Hash(0x91b6311e406f09ecaee3eac9fa84400fd1355c97000000000000000000000000)", + "P->V[28360:28392]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2615010: Hash(0xb265124728585ced6a42909e5c34f907de56b363000000000000000000000000)", + "P->V[28392:28424]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2624871: Hash(0x41e3cf91366700121409ee51039a41028fdafec6000000000000000000000000)", + "P->V[28424:28456]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2654729: Hash(0x43b6ab8c34e8fd9691733420aa6a2b373e4a095b000000000000000000000000)", + "P->V[28456:28488]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2668300: Hash(0xe195e663c6d09654dc977db5cd9988da56c0b70e000000000000000000000000)", + "P->V[28488:28520]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2671004: Hash(0xa54e99a0eb74b9073f79ff7f0941e3a7e064b70a000000000000000000000000)", + "P->V[28520:28552]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2761300: Hash(0x8854bb8d46337ec6d93e86948b8ce49e69bbd68d000000000000000000000000)", + "P->V[28552:28584]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2975583: Hash(0x666e50091bbefeab0b740a574500ea82c4e44490000000000000000000000000)", + "P->V[28584:28616]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 3255051: Hash(0x6d7a9e0e3b00a16b3d1cd24e3be52901dd604aa2000000000000000000000000)", + "P->V[28616:28648]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 3461079: Hash(0xc0982e96c60106ec13d79291c301e1fa176c1ab7000000000000000000000000)", + "P->V[28648:28680]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 3686924: Hash(0x8dc013d1345a52256f500c588598095835637d05000000000000000000000000)", + "P->V[28680:28712]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 3789158: Hash(0xc67f28c14a6dd33ce67c688278518aeec2144c1d000000000000000000000000)", + "P->V[28712:28744]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 4125985: Hash(0xb410061861da528e1ef331053589994dce66478b000000000000000000000000)", + "P->V[28744:28776]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1066074: Hash(0xafa37024afae7404a983f09b5f4815b941ed961e000000000000000000000000)", + "P->V[28776:28808]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1186472: Hash(0xb714496a5ec940953498468992a35d680f0e2786000000000000000000000000)", + "P->V[28808:28840]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1277892: Hash(0x1350b5ed7d47752c7323c7aaf40cd4651cb28407000000000000000000000000)", + "P->V[28840:28872]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1307504: Hash(0x2a4e4c04af4b3a0691e04f77a3024253728f77b8000000000000000000000000)", + "P->V[28872:28904]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1312434: Hash(0x5dd1a3c290dee12b0c1102fc134fe0521fc47cfa000000000000000000000000)", + "P->V[28904:28936]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1327365: Hash(0x81acb2da88abd7f24bfce38c6d1d43ecfae34c36000000000000000000000000)", + "P->V[28936:28968]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1334151: Hash(0xfb21ae2396754a1ea134308c0c0cfbe256836aa7000000000000000000000000)", + "P->V[28968:29000]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1335503: Hash(0x5506e3eed92dad027f6b785dcc1a0e4597431f63000000000000000000000000)", + "P->V[29000:29032]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1380651: Hash(0xd6f88bef735f00900c422c1dd470d7c6aa007808000000000000000000000000)", + "P->V[29032:29064]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1487790: Hash(0x83dd7b6b7b896fa44ee5446a809fd98872413873000000000000000000000000)", + "P->V[29064:29096]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1627524: Hash(0xa1dc6328a039faa1f25cb12f8aeb7c703711339d000000000000000000000000)", + "P->V[29096:29128]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1730538: Hash(0x4341195e7070c03b6c2e5f394d42a292d8d31568000000000000000000000000)", + "P->V[29128:29160]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1843463: Hash(0x53c1d13fbbe827f10f14b3840184766f3052b679000000000000000000000000)", + "P->V[29160:29192]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1894578: Hash(0x23ca05c3d3c918c01ff8e87275ca8f7fedbad366000000000000000000000000)", + "P->V[29192:29224]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2062993: Hash(0xaf423e33eb6dde4db0754f72715f2c13c44e5388000000000000000000000000)", + "P->V[29224:29256]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 533036: Hash(0x59220b94e4b2defe9f4fa3ccc4a8de5c08b643aa000000000000000000000000)", + "P->V[29256:29288]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 593237: Hash(0x3569e5334e484db394ef8aaf098f274ae8c6fcbe000000000000000000000000)", + "P->V[29288:29320]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 638947: Hash(0xe04e68394dcc5ae3135a8c3dee1a800f59ba8bee000000000000000000000000)", + "P->V[29320:29352]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 653753: Hash(0xf393a1507d23fb632c87344a374b659096987b5d000000000000000000000000)", + "P->V[29352:29384]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 656216: Hash(0x693011a8cc8ba86b6152a02fb448f80355297531000000000000000000000000)", + "P->V[29384:29416]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 663683: Hash(0x44241d19b486f5ab6f1640e01a9db6e1e19a34a2000000000000000000000000)", + "P->V[29416:29448]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 667074: Hash(0xa8f904e87d2db41584b04ed31f76d49907793593000000000000000000000000)", + "P->V[29448:29480]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 667750: Hash(0xeee1aaa495fa88c87cc184d9bb57515a15ae1ffb000000000000000000000000)", + "P->V[29480:29512]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 690324: Hash(0x689cf4004b15c08ffdb8c9fb285b99152226118d000000000000000000000000)", + "P->V[29512:29544]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 743894: Hash(0x549b7aad715d1e7eaeda0348045775be01d30383000000000000000000000000)", + "P->V[29544:29576]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 813763: Hash(0xdea3c28eae02423c290dbf1a49d869c4878f594000000000000000000000000)", + "P->V[29576:29608]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 865268: Hash(0x7f84554c592e5ad5d2fa6d2278fed5fae15f95e4000000000000000000000000)", + "P->V[29608:29640]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 921730: Hash(0x99c5718e30d71435bbc19ccb1c23a8ef9044feb0000000000000000000000000)", + "P->V[29640:29672]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 947288: Hash(0x46f5253c4a77d7982399017a41798b1cc8d8ed53000000000000000000000000)", + "P->V[29672:29704]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1031497: Hash(0x5904352d36e17773c506f3d4ff5e76bec48b2665000000000000000000000000)", + "P->V[29704:29736]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 266519: Hash(0x8dba4257e1d2a36e106cd3bae00ffe0fa5a1570f000000000000000000000000)", + "P->V[29736:29768]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 296619: Hash(0xf422f573612a324c9f5ef9de672432f95fbd98c8000000000000000000000000)", + "P->V[29768:29800]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 319472: Hash(0xbc27fbcc983c72c4f5c02891062ff30b2bb9ab16000000000000000000000000)", + "P->V[29800:29832]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 326877: Hash(0xa08e8c91859f668e8aaab1dfb6fc6c96db265a95000000000000000000000000)", + "P->V[29832:29864]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 328109: Hash(0x283e9db461db43389ab2755b9b70abd9cebbfca4000000000000000000000000)", + "P->V[29864:29896]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 331840: Hash(0x530bb1620fd66978475793a0a563f72d810989f0000000000000000000000000)", + "P->V[29896:29928]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 333536: Hash(0x82706846cc3b598e18fd50843ef10191889cd387000000000000000000000000)", + "P->V[29928:29960]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 333874: Hash(0xe8ecd294afd0d39bf0b632202c71c3cd525b4cf0000000000000000000000000)", + "P->V[29960:29992]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 345163: Hash(0xdf62e97289d52ad5927c9ddcf7707365a4b65cd5000000000000000000000000)", + "P->V[29992:30024]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 371946: Hash(0x70a8208517ada99969d8efbd01f3d46e3e8e3425000000000000000000000000)", + "P->V[30024:30056]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 406880: Hash(0x7f332145ccfd375e18dc2e0eafa4850e6eea68aa000000000000000000000000)", + "P->V[30056:30088]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 432635: Hash(0xce31c4b4979621496e4930eb3dfc03c2f250f039000000000000000000000000)", + "P->V[30088:30120]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 460864: Hash(0x50316f94991333b37234b27991d0ecb7578722fb000000000000000000000000)", + "P->V[30120:30152]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 473645: Hash(0x86750f9cb5fbcf2607dbb45596329c7d42f4c2bc000000000000000000000000)", + "P->V[30152:30184]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 515749: Hash(0xf4443f71ac6290908401ea9b4f2413c5cc8ef7aa000000000000000000000000)", + "P->V[30184:30216]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 133258: Hash(0x203d67976d13fa06072871dfc8b01e9fa5197db000000000000000000000000)", + "P->V[30216:30248]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 148308: Hash(0x36dcff71add5c0dbf096b2a7480d160561d7bc17000000000000000000000000)", + "P->V[30248:30280]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 159737: Hash(0x4f9de14c75bf9212dfb2a6482e64045de2d38e78000000000000000000000000)", + "P->V[30280:30312]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 163439: Hash(0xe2b3ade608118a830380a62c5f57b376a3c8410c000000000000000000000000)", + "P->V[30312:30344]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 164055: Hash(0xb6fdb1a300f03bf65d4f0fb58d610734bcb1c051000000000000000000000000)", + "P->V[30344:30376]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 165921: Hash(0x75f7336b6ae18606bae86729f53108e776dfb43000000000000000000000000)", + "P->V[30376:30408]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 166769: Hash(0x47ba7b55b7a8e5974b283bd0a00ae962a79f4577000000000000000000000000)", + "P->V[30408:30440]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 166936: Hash(0x1f33172479ffb99282095b6939f8c33b39a2441e000000000000000000000000)", + "P->V[30440:30472]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 172580: Hash(0x41c147963ad74cb5e75c2ceb786792b0b1106b2f000000000000000000000000)", + "P->V[30472:30504]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 185972: Hash(0x7b877fbb1929e3acb264bb1e6f9b765b23123a0f000000000000000000000000)", + "P->V[30504:30536]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 203441: Hash(0xf4672c10c176498e350452d9d695fd8fecb24aa7000000000000000000000000)", + "P->V[30536:30568]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 216316: Hash(0xd1247a5a517d6618c0f0a05afe8b71b2f69e6401000000000000000000000000)", + "P->V[30568:30600]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 230433: Hash(0xc030136a8b4002e81d027bea0f981b1b430d97ac000000000000000000000000)", + "P->V[30600:30632]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 236823: Hash(0x5f7ce5a4c30546b5f7ebdcbd01bdf5b8912558e3000000000000000000000000)", + "P->V[30632:30664]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 257875: Hash(0xc6250f22d2cfd7014ae754f318bd260c31e734cd000000000000000000000000)", + "P->V[30664:30696]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 66628: Hash(0x5bd100dd3fb886dc9c2a4c16c40b84960cc7f888000000000000000000000000)", + "P->V[30696:30728]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 74155: Hash(0x3ea626d6ff1f470cf50a2c5ee82b4d58bdccadac000000000000000000000000)", + "P->V[30728:30760]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 79869: Hash(0xa25c7e1a5f1774be75c9e9edea69edeed94fd230000000000000000000000000)", + "P->V[30760:30792]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 81718: Hash(0x481757ac73f6869c92e49d43643a466c592f8dc9000000000000000000000000)", + "P->V[30792:30824]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 82026: Hash(0x3864887745729d9541c4c962d9d2ebc4b5b8f15e000000000000000000000000)", + "P->V[30824:30856]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 82961: Hash(0x15fc985116f25e50e83e5f876a0ad0f1629db16a000000000000000000000000)", + "P->V[30856:30888]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 83385: Hash(0x89dd6379d8557a9c47654436bdf67ebbd96a3351000000000000000000000000)", + "P->V[30888:30920]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 83469: Hash(0x3bb5ee0f1dbf89b7e58b2ef23684348a383595f2000000000000000000000000)", + "P->V[30920:30952]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 86291: Hash(0xd319811af3cfe4debd0b1deb17d928c9eef61928000000000000000000000000)", + "P->V[30952:30984]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 92987: Hash(0xf4e0783db4038c6802649e848b3e546af3270f35000000000000000000000000)", + "P->V[30984:31016]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 101721: Hash(0x9974e56b84469cdc2512f744904b809181c2d5af000000000000000000000000)", + "P->V[31016:31048]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 108159: Hash(0xf96b0ad88b3d6a91ce5eb573111900f96a2bf565000000000000000000000000)", + "P->V[31048:31080]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 115217: Hash(0xc2b09a80551a9a85726e2208c03d6c126a17d5bc000000000000000000000000)", + "P->V[31080:31112]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 118410: Hash(0xd25a42a92f016869312306ed4891e1380c68780f000000000000000000000000)", + "P->V[31112:31144]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 128936: Hash(0x555cd7ce582d61e78a2c9c46d6d47609f7de17d0000000000000000000000000)", + "P->V[31144:31176]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 33315: Hash(0xf0b1908773cb8797e47c4de7a627eb7f1df3f3b1000000000000000000000000)", + "P->V[31176:31208]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 37076: Hash(0xa0737ebf48323dd82bdcfc11b0996217aa176408000000000000000000000000)", + "P->V[31208:31240]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 39935: Hash(0xf2a756ed8d9ac43127120e9ad1261b8d7e1e8e2d000000000000000000000000)", + "P->V[31240:31272]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 40858: Hash(0xf10a7442150f73ff93a516a885dea8cbdcf1c042000000000000000000000000)", + "P->V[31272:31304]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 41012: Hash(0x31148710ebd4736e43e15367bac0ea34489d29bf000000000000000000000000)", + "P->V[31304:31336]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 41481: Hash(0xd5fbc23611a76241b448e8fa95702f8f1af897a6000000000000000000000000)", + "P->V[31336:31368]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 41693: Hash(0xcba43592db065f9d4add7f6af077c0a47af71bd3000000000000000000000000)", + "P->V[31368:31400]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 41735: Hash(0xf2f768876811e8b801f4fc24f83aa008a5c9756b000000000000000000000000)", + "P->V[31400:31432]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 43144: Hash(0x51caa6b0f2bc23a4fc6d05967eadd7f8420a0477000000000000000000000000)", + "P->V[31432:31464]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 46492: Hash(0x642129e6bb28a7697105fd11660cf9aa6298abe0000000000000000000000000)", + "P->V[31464:31496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 50861: Hash(0x1dce6ccc1a9106a7ba36a0a26437d5b823b9c96f000000000000000000000000)", + "P->V[31496:31528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 54078: Hash(0x2841a1bd571207bd81aacee18178719af0bef6b4000000000000000000000000)", + "P->V[31528:31560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 57609: Hash(0xf8a3516f401aba94926f32569a9f5f9f32f4972d000000000000000000000000)", + "P->V[31560:31592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 59204: Hash(0xe043b9936ef5956970e2670013ac0c20caa0ce86000000000000000000000000)", + "P->V[31592:31624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 64469: Hash(0x4f1bf6f3fe21c1c79ed1dea1b75b1397091a2788000000000000000000000000)", + "P->V[31624:31656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 16656: Hash(0x5a135ce5c8dcf14a80e1d60d4cc1c4e9db6e9499000000000000000000000000)", + "P->V[31656:31688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 18539: Hash(0x98ec3273ba952a71f225669927b8d26de94a286000000000000000000000000)", + "P->V[31688:31720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 19966: Hash(0xe98a1e64c5b9d565d1b4b9e21936e4b842c1c308000000000000000000000000)", + "P->V[31720:31752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 20428: Hash(0x8737b2f8069b882b8d327079e63327f972c25b04000000000000000000000000)", + "P->V[31752:31784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 20507: Hash(0x410c6008061efd118ba9ccfe6d5135b6cd9047bc000000000000000000000000)", + "P->V[31784:31816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 20741: Hash(0xaa487042476ad7b84d2b46cfdfa9948de33f4dfd000000000000000000000000)", + "P->V[31816:31848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 20847: Hash(0x58b64f5b20428d0a05d0c72de69d06d2e5c49cc2000000000000000000000000)", + "P->V[31848:31880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 20866: Hash(0xe7b3593d62d5c79c9d8e81d3f203a5b9935dd5f6000000000000000000000000)", + "P->V[31880:31912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 21573: Hash(0xd9aaf69acbcf8f5b66c370b67cee07ae5c40d7d1000000000000000000000000)", + "P->V[31912:31944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 23247: Hash(0x8a0e1c1aabbe501e4f55c700f79546c257c61189000000000000000000000000)", + "P->V[31944:31976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 25431: Hash(0xa2049dc249621e2d210e2226bd52c35b45650b13000000000000000000000000)", + "P->V[31976:32008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 27038: Hash(0xe31890770dab67787b1bd5e648d4cbdc4000a413000000000000000000000000)", + "P->V[32008:32040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 28805: Hash(0x351b20f4b66e0493a06adfe9be212e48be837718000000000000000000000000)", + "P->V[32040:32072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 29603: Hash(0xda77a35a50a207478c0c5892881c3e17a9e6a2c7000000000000000000000000)", + "P->V[32072:32104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 32235: Hash(0xb989d11a8f1c2a2e1b69789591e0dd6941d6387e000000000000000000000000)", + "P->V[32104:32136]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 8329: Hash(0xaf31f1363be86ac920e8c072c98b5ada38b225aa000000000000000000000000)", + "P->V[32136:32168]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 9268: Hash(0x7f02e7dddbe9e2d226dd09f2137bbe75dc36becf000000000000000000000000)", + "P->V[32168:32200]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 9982: Hash(0x5cf8c1d001387aa1bd734204c577cb6a8796604c000000000000000000000000)", + "P->V[32200:32232]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10215: Hash(0xb20f7d769ba6a7516a13d1a5ce226969114d44c3000000000000000000000000)", + "P->V[32232:32264]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10252: Hash(0x5e5bca12c1fdbb64885a26acc18e8db32d916c4b000000000000000000000000)", + "P->V[32264:32296]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10371: Hash(0xe19a9ad4c1a9fe8844404d8e8e888083e40661a1000000000000000000000000)", + "P->V[32296:32328]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10422: Hash(0xf64b7a70f8a3c48c93b0a8eb60560c1ac46a49ef000000000000000000000000)", + "P->V[32328:32360]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10432: Hash(0x2266eb45b1dbf570b823ec68a6188c35cd2a718c000000000000000000000000)", + "P->V[32360:32392]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10787: Hash(0xc377821fda2a32a4bcd67e19528ed9f6073a07f1000000000000000000000000)", + "P->V[32392:32424]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 11622: Hash(0x956607cb84e889cfed142445a546f9c95f8cc8d3000000000000000000000000)", + "P->V[32424:32456]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 12714: Hash(0xd3fe25b15ba6ac3319e03fc02a55081b17c747c7000000000000000000000000)", + "P->V[32456:32488]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 13518: Hash(0xefa3361aeda9548d482a687ed90938491beb2cb2000000000000000000000000)", + "P->V[32488:32520]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 14403: Hash(0x9581b36900f03a64af673f2bd434237a09da4d76000000000000000000000000)", + "P->V[32520:32552]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 14800: Hash(0x9d22afe52b1d58f8a7629fdcc7f3fccf89192316000000000000000000000000)", + "P->V[32552:32584]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 16116: Hash(0x135af72ea4c47a1a8ec5327ddb50e5d91736a84c000000000000000000000000)", + "P->V[32584:32616]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 4165: Hash(0x402d5d23a46372dcf8dc73bd9cf67bc24f371d85000000000000000000000000)", + "P->V[32616:32648]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 4635: Hash(0x68aa8ad8d33e4703e0a3d881566e9d4519e49d41000000000000000000000000)", + "P->V[32648:32680]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 4990: Hash(0xb861bcbff4afb6852761b5f1d056f4a42abead9000000000000000000000000)", + "P->V[32680:32712]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5106: Hash(0xc5faece035e7360de0e597ef8967608ffa295bda000000000000000000000000)", + "P->V[32712:32744]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5127: Hash(0x18ef853b39c7cbc74ac802419340269f90145037000000000000000000000000)", + "P->V[32744:32776]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5184: Hash(0xb75b3b1cd6d6b08b6e09776ebed9681b2f3da749000000000000000000000000)", + "P->V[32776:32808]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5210: Hash(0xa01847e7948a9b18365aed368129f2a8bd8e9957000000000000000000000000)", + "P->V[32808:32840]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5217: Hash(0x8bc2c1938a2a9925f43e5a1c4f58a024491e8797000000000000000000000000)", + "P->V[32840:32872]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5392: Hash(0x32f5dbb4e74239f7746bd430f45ec186ee96f9bc000000000000000000000000)", + "P->V[32872:32904]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 5810: Hash(0x1837b2b71d17dca1a320baf2a0976c72fc646846000000000000000000000000)", + "P->V[32904:32936]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 6356: Hash(0x6043dbbce23b21684933ccf863fb5fc83eeacacd000000000000000000000000)", + "P->V[32936:32968]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 6758: Hash(0x9be34b58707023abebc7ffaca4a049c268d0800000000000000000000000000)", + "P->V[32968:33000]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 7200: Hash(0x1dcb17de8f0a08ec0fa9cb337d15ef38ab81b384000000000000000000000000)", + "P->V[33000:33032]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 7401: Hash(0x3c311953551df199c8b9292d6856428b8315b0be000000000000000000000000)", + "P->V[33032:33064]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 8059: Hash(0xf10a21c88cd71308029b23133e83a85b0096ae7d000000000000000000000000)", + "P->V[33064:33096]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2083: Hash(0x555c60d1fb12f06a8e83641871d6272c515e4ed8000000000000000000000000)", + "P->V[33096:33128]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2316: Hash(0xafb0d206cecdba1e07779b5b4f34b21fab4ff568000000000000000000000000)", + "P->V[33128:33160]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2494: Hash(0x1a5d95ee5f164f97722c0b0df732e0320d7f8bee000000000000000000000000)", + "P->V[33160:33192]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2552: Hash(0xfa4a1bebc101c046ae627bd534bd09105655bd5f000000000000000000000000)", + "P->V[33192:33224]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2562: Hash(0xe4fb242f905c07fde9b44dc765a27d41960f94d9000000000000000000000000)", + "P->V[33224:33256]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2593: Hash(0xc02f56f20d068fbe88c562f5f3d8be82233687ef000000000000000000000000)", + "P->V[33256:33288]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2604: Hash(0xc8a9ec8a7b125050f5f2cf8903463745fb3ccfa8000000000000000000000000)", + "P->V[33288:33320]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2609: Hash(0xe22dd782ba9615185ae1a641dfa695ed70f94183000000000000000000000000)", + "P->V[33320:33352]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2697: Hash(0x53d44ec0d91053c2eaa93e290503af3b71d304e7000000000000000000000000)", + "P->V[33352:33384]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2904: Hash(0x70a09c86006fc5af0d14cbca4f7ca7cf238eb92e000000000000000000000000)", + "P->V[33384:33416]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 3179: Hash(0xf27dac3fa1da95042a552ce16265cf150734134c000000000000000000000000)", + "P->V[33416:33448]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 3378: Hash(0xbe796d5fc305580c43e0a32a3359662a3740f3e6000000000000000000000000)", + "P->V[33448:33480]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 3601: Hash(0x7f9a12dfc2af80a1a8453e18225427d7f5bef8f8000000000000000000000000)", + "P->V[33480:33512]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 3701: Hash(0xcaee5f55f5b6f76a0e97013b1773f3e9a7090d36000000000000000000000000)", + "P->V[33512:33544]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 4028: Hash(0x85bcf55fce4bd94310e1f68056e99b74ce41fab5000000000000000000000000)", + "P->V[33544:33576]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1040: Hash(0x9151879712bda29eabe97640d9c9089d79bbff7000000000000000000000000)", + "P->V[33576:33608]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1159: Hash(0x5da49be3655ecb19d7e66cd75a8d42d318c4e4ef000000000000000000000000)", + "P->V[33608:33640]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1246: Hash(0x28ba11cfd67bd786e5f51aa26e8ff1d16f6fc15b000000000000000000000000)", + "P->V[33640:33672]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1277: Hash(0x8448542f125026a052be865e82c96cc5ed2b232a000000000000000000000000)", + "P->V[33672:33704]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1280: Hash(0x8ec49f67c64c796492464a8c83ea389fce0dbd41000000000000000000000000)", + "P->V[33704:33736]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1297: Hash(0x5d33e397268200645513564d6c1843e52dd81f8e000000000000000000000000)", + "P->V[33736:33768]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1303: Hash(0x39b258c0ec6a2124de3c2a6dfdff177614210885000000000000000000000000)", + "P->V[33768:33800]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1305: Hash(0xfd06d74cadb7628bb0ee63ca2ce176995452ee5e000000000000000000000000)", + "P->V[33800:33832]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1349: Hash(0x83a0a5c0d045c9fe91c03571aa40ef1f6e971f50000000000000000000000000)", + "P->V[33832:33864]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1453: Hash(0x9da130907bb9772af1e62f5a4b19b3ba6aadd90d000000000000000000000000)", + "P->V[33864:33896]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1588: Hash(0x858f3e085ac7c66e0651c00644f3a0a96465006000000000000000000000000)", + "P->V[33896:33928]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1688: Hash(0x91afd0fd89039ff4095978f7bc1d0f977844812c000000000000000000000000)", + "P->V[33928:33960]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1801: Hash(0x6ab259ada835888a08ce81f24c9cb0512b229275000000000000000000000000)", + "P->V[33960:33992]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1851: Hash(0x1178507aef118712a40d45c6d9afc3cf185f6f77000000000000000000000000)", + "P->V[33992:34024]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 2015: Hash(0x2f4d85b11d853fb995dfc73cc5974a5b31add178000000000000000000000000)", + "P->V[34024:34056]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 521: Hash(0x9b0c90dd5bb9bb0e87183e0f15209270f66cc662000000000000000000000000)", + "P->V[34056:34088]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 578: Hash(0xb9024ad61672fd35805b5985a985f4dedf80516f000000000000000000000000)", + "P->V[34088:34120]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 622: Hash(0xb4f4500f6d4313a133e85ec6571cf113c8523e28000000000000000000000000)", + "P->V[34120:34152]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 639: Hash(0x112562122600e5dba6ff4614be5af550a4dc482c000000000000000000000000)", + "P->V[34152:34184]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 641: Hash(0xfac4bdcb78618dd597d59db2be54062a2cb50d48000000000000000000000000)", + "P->V[34184:34216]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 649: Hash(0xbc7b0ef8237e499256aa60e14d14e039dd6e88d6000000000000000000000000)", + "P->V[34216:34248]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 650: Hash(0x64026739b250948f5048305cb1ec3fee2ea8014a000000000000000000000000)", + "P->V[34248:34280]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 653: Hash(0x468bcb995d25ec2b072aa109caeb9377e229ccfd000000000000000000000000)", + "P->V[34280:34312]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 675: Hash(0x68307cedb437f1a94c8446474fd941b6cf05adaa000000000000000000000000)", + "P->V[34312:34344]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 727: Hash(0xb3e688e65ae5b9c75007aea13298f55fbc6167ca000000000000000000000000)", + "P->V[34344:34376]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 795: Hash(0xf1a7fb8b0988bf04428f7dc7ef45a025c94d923c000000000000000000000000)", + "P->V[34376:34408]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 845: Hash(0x941f70ef8f25002a561540d5e5c41ce29f13503b000000000000000000000000)", + "P->V[34408:34440]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 901: Hash(0xe59cc44da9e4f9acb4208b7478984390f112b811000000000000000000000000)", + "P->V[34440:34472]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 924: Hash(0x60538e7ca5389b1173a70b6d5a8e3feb97033cbd000000000000000000000000)", + "P->V[34472:34504]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 1006: Hash(0xd1b84e76b95b642488fd08ab2044205b2a8d7eee000000000000000000000000)", + "P->V[34504:34536]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 261: Hash(0x49d064cfd0db69a41e5e8b99c8f1d10e0eb99eb1000000000000000000000000)", + "P->V[34536:34568]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 288: Hash(0xb9e80f28dc63f0b08570fc66de320011e9204c55000000000000000000000000)", + "P->V[34568:34600]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 310: Hash(0xea618355e0b321201a9aea3943d17ad827fbb430000000000000000000000000)", + "P->V[34600:34632]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 318: Hash(0xfc0ec63477fc6d33b403a7a06ad1d15a131a83fe000000000000000000000000)", + "P->V[34632:34664]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 321: Hash(0xe93c97a3a158cc29f3a4a70ae03c5c35871884e0000000000000000000000000)", + "P->V[34664:34696]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 327: Hash(0x1d79e0f68a899ca8253b1fb0c6b5b54edbf74a5000000000000000000000000)", + "P->V[34696:34728]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 336: Hash(0xd0026453cb7667f7591bdf367d02c22f5e8b29e3000000000000000000000000)", + "P->V[34728:34760]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 362: Hash(0x6c3e55ffed0bfb10a752bb6fb4d84ad8205e260b000000000000000000000000)", + "P->V[34760:34792]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 396: Hash(0xfd0940609a93abaaa39083d65da39eea41ccd2ef000000000000000000000000)", + "P->V[34792:34824]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 423: Hash(0x1749a720b5bebb27e99fb9dab3e59637eb57241f000000000000000000000000)", + "P->V[34824:34856]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 451: Hash(0xd9e3e565e741c1bb9a6ff69af40a7a4c7b6313b6000000000000000000000000)", + "P->V[34856:34888]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 463: Hash(0x2258b67efc10d09a450d018d8c0381fbcf362964000000000000000000000000)", + "P->V[34888:34920]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 502: Hash(0xe195e6690bd127dbea2eb1afe2f40906c07853a000000000000000000000000)", + "P->V[34920:34952]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 131: Hash(0x50895f714aaa713921038961a63bf935519a7d2e000000000000000000000000)", + "P->V[34952:34984]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 145: Hash(0x2488f1176a926cae3545b7cd44e7b24eb00cf4ed000000000000000000000000)", + "P->V[34984:35016]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 154: Hash(0xbdaa2c966a13d7a2cf414729826815eba3f5fbe000000000000000000000000)", + "P->V[35016:35048]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 158: Hash(0xa0fe3ae90a61cca38b05063d1c15c708564d5675000000000000000000000000)", + "P->V[35048:35080]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 161: Hash(0x25c4669b28f07d1f71b49449c2114bf8813da0e000000000000000000000000)", + "P->V[35080:35112]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 169: Hash(0xd243ac194ec3f894fa8112f14ee034cff85eaf5c000000000000000000000000)", + "P->V[35112:35144]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 180: Hash(0x7d7caa0884d257b62e3a52cb72a62d471b98adb2000000000000000000000000)", + "P->V[35144:35176]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 199: Hash(0x3330babb51908609e8374cc1e92fb41b3877680a000000000000000000000000)", + "P->V[35176:35208]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 210: Hash(0xb6937eee743f8ff582373458fb05243cb4d37cb9000000000000000000000000)", + "P->V[35208:35240]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 224: Hash(0x773e44b9a7449f5b702d9290eb1278f91e7e926c000000000000000000000000)", + "P->V[35240:35272]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 230: Hash(0x929ec7d6dec4ac5beca6fa964a81b0dd194f8c83000000000000000000000000)", + "P->V[35272:35304]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 250: Hash(0xca22fb060e548b78956f3f8816c74b00c94942c9000000000000000000000000)", + "P->V[35304:35336]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 64: Hash(0xbd13e8df1a16b6865e6b34e0b2cd567df1797880000000000000000000000000)", + "P->V[35336:35368]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 73: Hash(0xff5cf9abbdcfe37d505b7112182aa2f30b1fce07000000000000000000000000)", + "P->V[35368:35400]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 76: Hash(0xc161c7b1aea2998287d149d61ed88b502d3e2637000000000000000000000000)", + "P->V[35400:35432]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 78: Hash(0xae1e497eacc8f99ccfe5983cf9c01bb8986707dc000000000000000000000000)", + "P->V[35432:35464]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 85: Hash(0x5254b4df78100965f32556ae8e719ec64800a137000000000000000000000000)", + "P->V[35464:35496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 91: Hash(0x1bf6437ca0cecac027def125ab0050155db01c5a000000000000000000000000)", + "P->V[35496:35528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 98: Hash(0x5e4553b63563e6f2d8c50a329b83ca96878f9aae000000000000000000000000)", + "P->V[35528:35560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 104: Hash(0x8145a27b5ba84bc71b49640559efc5b25cf743ae000000000000000000000000)", + "P->V[35560:35592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 113: Hash(0x7034b79d5a4a6bd050cee2fdb407866480473d50000000000000000000000000)", + "P->V[35592:35624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 114: Hash(0xb9d776e948410c64c9e37dc1dddfa4c6dec1fe28000000000000000000000000)", + "P->V[35624:35656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 124: Hash(0x345a32fe6fa501262c6a2d95b522619f34e58e11000000000000000000000000)", + "P->V[35656:35688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 33: Hash(0xf1ae7f73502f5bbad415804d639cfa7885489b49000000000000000000000000)", + "P->V[35688:35720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 37: Hash(0x1e178a56f2ef4614d886f67ec1e47e8be53d7d9f000000000000000000000000)", + "P->V[35720:35752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 41: Hash(0x932cdfa8f74f1955c3da7630bf56290f6791ae98000000000000000000000000)", + "P->V[35752:35784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 43: Hash(0xcb2836b4b45166b78d5c56f65afa9b624f54e677000000000000000000000000)", + "P->V[35784:35816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 44: Hash(0xd1c0dfa762415e2a8cffbe623f12a5b5aa7035fa000000000000000000000000)", + "P->V[35816:35848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 48: Hash(0xe80fda4600ec527c58213b336531d51e13ab8ecd000000000000000000000000)", + "P->V[35848:35880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 53: Hash(0x56a858d130bafb5941d1a7457c75728dc66ed334000000000000000000000000)", + "P->V[35880:35912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 63: Hash(0xbd2bb22b0c9ef35d61fcb3a6e22cc0cdf91e032f000000000000000000000000)", + "P->V[35912:35944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 17: Hash(0xef679a663c2b206bf2c760f8c0161d1e8d765009000000000000000000000000)", + "P->V[35944:35976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 23: Hash(0xdf3d2477005fb2b25d901ad23701e4e391c30025000000000000000000000000)", + "P->V[35976:36008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 25: Hash(0xbcc980ece1ba108f8b27dc89d761d9e057b98fd8000000000000000000000000)", + "P->V[36008:36040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 27: Hash(0x3612a7faf74e8f45c3562ea8995477e0f5041122000000000000000000000000)", + "P->V[36040:36072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 29: Hash(0x1cc0a8ba98f1b52004e6dbcee42a058458681d05000000000000000000000000)", + "P->V[36072:36104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 30: Hash(0x485394a695450f4bee48df523410494b4b0e7237000000000000000000000000)", + "P->V[36104:36136]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 139993, Column 0: Field Element(0x1bd612c37662e3797aa86fc4ebe33cc2ce34127a587a34d9bba82ef5082492)", + "P->V[36136:36168]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 139993, Column 1: Field Element(0x5117275fdb10a82cf4ee7dac81e54fe200d76d402f9182d24d4501a23b00352)", + "P->V[36168:36200]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 139993, Column 2: Field Element(0x29152dccbe12dff55ac142f8ff8aeafe859fd2023e3a95307cc6b0059d72c94)", + "P->V[36200:36232]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 1103176, Column 0: Field Element(0x360b1b0562fdb0941422cd6411ae66555f22a2ae522337b550fdb252035453)", + "P->V[36232:36264]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 1103176, Column 1: Field Element(0x56813d9790c75f30b1ea6323410e5a6fb551b9230c91742fedc647710655ba8)", + "P->V[36264:36296]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 1103176, Column 2: Field Element(0x5a63ede4a407b1d75d91e1220bf562634ddfa80e6eafdb8fa808603cda52a3f)", + "P->V[36296:36328]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 1834537, Column 0: Field Element(0x28cc570edafa2de3f211bdc258e5e8cfe6c132454f1e4f9c3c307b87f2cf03f)", + "P->V[36328:36360]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 1834537, Column 1: Field Element(0x211c1d264ea46fcdd00a6beb697a63de0082a9357b1744e9f7ebf1684b62901)", + "P->V[36360:36392]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 1834537, Column 2: Field Element(0x39717b730e583318003c67766f19bea0ad0ae0466e55790e21872e9e279b847)", + "P->V[36392:36424]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2071439, Column 0: Field Element(0x6bc5f0ac3e81aacb9e6cd9effa87719a48c0d7cc1b1cf8af0dd607f6803970)", + "P->V[36424:36456]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2071439, Column 1: Field Element(0x2a072de8aa9e27394910c8135669aa3d1726a6e70224bec070560e1e022b83a)", + "P->V[36456:36488]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2071439, Column 2: Field Element(0x46696d2d27a56064625e329a5e48ac5e6f546f6d77136dc37c826e9151932b5)", + "P->V[36488:36520]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2110874, Column 0: Field Element(0x3662f30baa3552a91be4002a369d9bbf3fcf87646405bb6dfb8a290bc7672ef)", + "P->V[36520:36552]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2110874, Column 1: Field Element(0x625156ff58ea8a7c1c801c72df82596816accd6aa28ba9e82ca53a51d6b0adb)", + "P->V[36552:36584]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2110874, Column 2: Field Element(0x575a1f9f4b8a361772c4e7ac31f2577e5f90630fcedc4241e9f2c96ab1ab775)", + "P->V[36584:36616]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2230304, Column 0: Field Element(0x6bfa436523c22e510b236bb137a0b4de93e886432a3c3ec4dec4454276ad7bc)", + "P->V[36616:36648]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2230304, Column 1: Field Element(0x633506faa249fb3f0368196fd6ec667b155e5c4d615b4fe775c0afcca6a6b2b)", + "P->V[36648:36680]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2230304, Column 2: Field Element(0x558ba43bb94c15ca72720bf94453361edf7da2d176fd2376d2be0651991abac)", + "P->V[36680:36712]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2284596, Column 0: Field Element(0x675a1ae669107152233744597314d225ffb7c0bac9be79a3741be33a0df2a87)", + "P->V[36712:36744]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2284596, Column 1: Field Element(0x6422fc125207bdb9955ecabdbd4a523cbce94267a20a2e6526ef47da60e89d)", + "P->V[36744:36776]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2284596, Column 2: Field Element(0x4d0deddf3779ed3c86b01ffdb67d0c1e19e89f4f3afdbb31a37ea092741f842)", + "P->V[36776:36808]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2295414, Column 0: Field Element(0x60c2fc8efafd989d78fb46495e7541e0111bf467175438d9ae007f9c1c8a15b)", + "P->V[36808:36840]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2295414, Column 1: Field Element(0x7e26c09052597669c5fd04bba35964a59386ca2bc5f6fd23d216995e1e8c84a)", + "P->V[36840:36872]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2295414, Column 2: Field Element(0x5eb5434034f6f4d4a6400a450e4b9a0bc89bbd34abcfa3132e17f5281609ed8)", + "P->V[36872:36904]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2656598, Column 0: Field Element(0x235c0c0063990f25809c5d03820316b300d6fb1c780ba5b137b0e04b1e11f7d)", + "P->V[36904:36936]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2656598, Column 1: Field Element(0x2663956c91d7d60f12f1ea94c510d09acc47fe0f40fef9370b6878fb7a13809)", + "P->V[36936:36968]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 2656598, Column 2: Field Element(0x40a16416816fc63cbad884a088412b97130c79be9a14f8e001f11dc0ca8de84)", + "P->V[36968:37000]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 3513722, Column 0: Field Element(0x3f36de5c6890c7e8f519ea78f5bbff0631e0a1193fdd78e38d8a108a873251a)", + "P->V[37000:37032]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 3513722, Column 1: Field Element(0x11ed00c5eb7cf716c0799654811f6bbf491fb2866a7c5d0db01ee5575cc2690)", + "P->V[37032:37064]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 3513722, Column 2: Field Element(0x6b0c38c13ddc76aeda7882dd5f27bdbb44e7e1f82ccbd1120e9222f1832eb89)", + "P->V[37064:37096]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 4631593, Column 0: Field Element(0x3242ff6f7f7d8dda871c38ab7f4c7501ce0c9e36c927236831638d1a8d34630)", + "P->V[37096:37128]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 4631593, Column 1: Field Element(0x77fa0208bb7eae343dfcc37ec215996c6193960aad1cf11e75f48ea7c3d824f)", + "P->V[37128:37160]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 4631593, Column 2: Field Element(0x5bf0ebbea3a05e07d52e2221507d1cb19b475509cc57bf69b18b48634ac7ffd)", + "P->V[37160:37192]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 5455705, Column 0: Field Element(0x51638ce88edf20703c002a28579b0b63e5aaf9de8b8b794dbcb00b0178c8708)", + "P->V[37192:37224]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 5455705, Column 1: Field Element(0x333a805095a9d9856b306f1a8f8d1dcf0df925e7ad0ea4eb58c50b91846bcc3)", + "P->V[37224:37256]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 5455705, Column 2: Field Element(0x2436014e32564fa207e041fc49946208ac9987d0ad618d249ff59ad61d67fe6)", + "P->V[37256:37288]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 6359094, Column 0: Field Element(0x14a838ae911ff1406b8127de4ea71eaf993bdca59c53902aa1b35b4cf7d3b74)", + "P->V[37288:37320]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 6359094, Column 1: Field Element(0x68ecb30c3c6e8642e2ef442cb8a742916aaf7a72ba193ec75802f2c4751e454)", + "P->V[37320:37352]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 6359094, Column 2: Field Element(0x1db32caa5ea86fec9b919b8778efe7e3952b6310a34aee1157f784605d3795d)", + "P->V[37352:37384]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 6768031, Column 0: Field Element(0x7fb778d1b7db91b3198078b98e2d1dc1cfb760fc944752f6234026046486b08)", + "P->V[37384:37416]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 6768031, Column 1: Field Element(0x59c2c297b2c77d235b058cb9e57911c7d13c4832b7d084f83374f3e38c65685)", + "P->V[37416:37448]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 6768031, Column 2: Field Element(0x70fda9be78b4f952377b46d0717b7195218d0201a85e73730faf9d51fd7c4e8)", + "P->V[37448:37480]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 8115330, Column 0: Field Element(0x61f55fb6bc98ff54ed14021615afe67a7b4a322753049c9ae36913de7fe910b)", + "P->V[37480:37512]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 8115330, Column 1: Field Element(0x5f4164ba42595642d1793bff0bb09e99d7df862485f8e5f397d3da416d182d1)", + "P->V[37512:37544]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: Row 8115330, Column 2: Field Element(0x3c2fbaa87b8c84eacb1d28d10e316c48cecdaa181ecce9ac7de8e7bbeee92b8)", + "P->V[37544:37576]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 8528600: Hash(0x8fae5bfd815379994dfc9ea85ad3c7c4ac52d31000000000000000000000000)", + "P->V[37576:37608]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 9491785: Hash(0x39dcfa73b87735c48868faf509de138bc895da12000000000000000000000000)", + "P->V[37608:37640]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10223144: Hash(0x4f206f73a5c015b0a2e7df569b755a9f6e9a5352000000000000000000000000)", + "P->V[37640:37672]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10460046: Hash(0xf7565ee9703a38712c340720de044db01f826fa1000000000000000000000000)", + "P->V[37672:37704]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10499483: Hash(0xf096c85571f42f9454cf1e95b546a95fc5c41c1d000000000000000000000000)", + "P->V[37704:37736]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10618913: Hash(0x4a8e85e04012f2058bc2dcba48a637b78c540c13000000000000000000000000)", + "P->V[37736:37768]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10673205: Hash(0x98c70510516c060dedc8cf6556f084ee03fe559e000000000000000000000000)", + "P->V[37768:37800]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10684023: Hash(0xb17360f60fc90770fc1f590aa0291088d57d3e20000000000000000000000000)", + "P->V[37800:37832]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 11045207: Hash(0xa32f00835b5114fb40cb62c46f46afcfd556d5e000000000000000000000000)", + "P->V[37832:37864]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 11902331: Hash(0x56b99495c1b4520e4b5d99432b17bc7460af64e5000000000000000000000000)", + "P->V[37864:37896]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 13020200: Hash(0x15fc0a8f99194ba997815468f2414a139345cf3a000000000000000000000000)", + "P->V[37896:37928]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 13844312: Hash(0x13c1526a203ed1aa2d5dafa667089f68312cd3ba000000000000000000000000)", + "P->V[37928:37960]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 14747703: Hash(0xf854d67df6a59f7603ee593104216a0179a7b08e000000000000000000000000)", + "P->V[37960:37992]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 15156638: Hash(0xf542871a6d3337ae49b2dd92f7dbb9e4cd3a4604000000000000000000000000)", + "P->V[37992:38024]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 16503939: Hash(0x23600ef18ecbe2b4006663d2ce0241ca350a54b4000000000000000000000000)", + "P->V[38024:38056]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 4264301: Hash(0x66ec621e10e74bb9462a18b49e52cef3071449000000000000000000000000)", + "P->V[38056:38088]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 4745893: Hash(0xbabbae77931de07ca8621804cf6b00b72a8c798b000000000000000000000000)", + "P->V[38088:38120]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5111573: Hash(0x17d137728f716148e1346e85d91df7afc14aa54c000000000000000000000000)", + "P->V[38120:38152]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5230022: Hash(0x9039a3cfe16ec563d5e884d2be4d144815730a44000000000000000000000000)", + "P->V[38152:38184]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5249740: Hash(0x9d09262b09a14633dd91e39e379b7da45404c232000000000000000000000000)", + "P->V[38184:38216]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5309457: Hash(0x77621c9116eb261873b5d2ead8f5517597ecead8000000000000000000000000)", + "P->V[38216:38248]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5336603: Hash(0xb9c1aa2ab34d0fa5073a86193d69c3d6ad7b1c3d000000000000000000000000)", + "P->V[38248:38280]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5342010: Hash(0xfd094c0ae01eede51966f96a59187360fa763c1b000000000000000000000000)", + "P->V[38280:38312]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5522602: Hash(0x1f610c960542892fb357f4ab57e74c14a1d42d0e000000000000000000000000)", + "P->V[38312:38344]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5951164: Hash(0xdc432e567b4cd5a8a35f358fcc28a8b1fa303d84000000000000000000000000)", + "P->V[38344:38376]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 6510101: Hash(0xefd0095886461c5ae1cf992e65d133bd5694c7bc000000000000000000000000)", + "P->V[38376:38408]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 6922157: Hash(0xd0535a4c7239ea7a9aaba0c7751f1a19e6334e8d000000000000000000000000)", + "P->V[38408:38440]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 7373850: Hash(0x6064a1ed639ff3c37b16c9683041e23d5e37c452000000000000000000000000)", + "P->V[38440:38472]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 7578318: Hash(0xf4ec5107ad7a0d5a7e509510ae1eecc1f8816bbe000000000000000000000000)", + "P->V[38472:38504]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 8251968: Hash(0x1e3cce021e44aec3a3ac7b112eeeb2d5249d13f2000000000000000000000000)", + "P->V[38504:38536]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2132151: Hash(0xc76bdb8f799f88096f3f4be5b327dffe6e6a1f3e000000000000000000000000)", + "P->V[38536:38568]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2372947: Hash(0x87c353108b4d5a2294f48bc71680fdb4f1c24586000000000000000000000000)", + "P->V[38568:38600]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2555787: Hash(0xc53ed57058c46ecea262a984394df2f416b9c069000000000000000000000000)", + "P->V[38600:38632]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2615010: Hash(0xb121ffa4feb2915c66e297bedd876fdafca013c2000000000000000000000000)", + "P->V[38632:38664]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2624871: Hash(0xd7e5b77362847fbcf55d112046c59828b6ab7922000000000000000000000000)", + "P->V[38664:38696]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2654729: Hash(0x6df6a9304a1443608478226a8fc42fdc4a4ea24a000000000000000000000000)", + "P->V[38696:38728]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2668300: Hash(0xc590f19d9f9b2478fc6e8b91238d297633bf405c000000000000000000000000)", + "P->V[38728:38760]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2671004: Hash(0xf683b67fa2609f74f67a3e3bbd534ea03d70ea65000000000000000000000000)", + "P->V[38760:38792]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2761300: Hash(0x8b014376cd2d286222cfd175c0e611973fca1c94000000000000000000000000)", + "P->V[38792:38824]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2975583: Hash(0xd9991a130b01e23e8a7956c5bc92bd6501407d6000000000000000000000000)", + "P->V[38824:38856]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 3255051: Hash(0xb84942dadfaa0331d7af09a6cd0456e84cbd9dde000000000000000000000000)", + "P->V[38856:38888]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 3461079: Hash(0x842410c4db2782856b5b5c9a6d7543576b9f110a000000000000000000000000)", + "P->V[38888:38920]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 3686924: Hash(0xd089eb1c58ef7937687a7129fd4d5b44ca9cb65e000000000000000000000000)", + "P->V[38920:38952]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 3789158: Hash(0xafe68d7f6a3e5047a1944c27cfcffb22795ed1d6000000000000000000000000)", + "P->V[38952:38984]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 4125985: Hash(0x9e6df8356c4b28f0f7464071151f2af5382c938a000000000000000000000000)", + "P->V[38984:39016]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1066074: Hash(0xea79e29bab7a7efda6af630c8bc026adb7f63edc000000000000000000000000)", + "P->V[39016:39048]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1186472: Hash(0x25c08814539dde601e06905a904ddc3658310b4a000000000000000000000000)", + "P->V[39048:39080]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1277892: Hash(0x3dc6b2294a26effa37af2eb7d171a05c9b4c0946000000000000000000000000)", + "P->V[39080:39112]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1307504: Hash(0xc720cac1849681ce75e307682201557d424871b3000000000000000000000000)", + "P->V[39112:39144]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1312434: Hash(0xbcc60baa83062f0df324a3544c10aaeeebc7483000000000000000000000000)", + "P->V[39144:39176]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1327365: Hash(0x8e24499f6518745410a195cb8759658b7454226b000000000000000000000000)", + "P->V[39176:39208]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1334151: Hash(0x9293f19e2a428e1e327a96316523a3c55b4e62ba000000000000000000000000)", + "P->V[39208:39240]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1335503: Hash(0xd0af95aae30ae3eae38b44e1bb2cdd3e2798e351000000000000000000000000)", + "P->V[39240:39272]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1380651: Hash(0xfd1881088d6de52854b70b6b53277130e3618130000000000000000000000000)", + "P->V[39272:39304]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1487790: Hash(0x97a784deec67dfd84fed9669fe4bf84edfc304e1000000000000000000000000)", + "P->V[39304:39336]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1627524: Hash(0xb92d8af2de23b7b482cdc4dd64be77a7ad4e973e000000000000000000000000)", + "P->V[39336:39368]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1730538: Hash(0xeb6c7057ac92b57de9e7e362ce7670bf1e0f98c2000000000000000000000000)", + "P->V[39368:39400]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1843463: Hash(0xe4c664122aacbc199d92fada904adff78c461315000000000000000000000000)", + "P->V[39400:39432]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1894578: Hash(0x23e635a9bebdf7320fadf0378cfbd3c0f4b8bdf000000000000000000000000)", + "P->V[39432:39464]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2062993: Hash(0xdae5ac9fba36fe12c47a356b05fe7daa3461f8d8000000000000000000000000)", + "P->V[39464:39496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 533036: Hash(0x1f51616dedb9cabf0b50aba5f3813bfaa06414e0000000000000000000000000)", + "P->V[39496:39528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 593237: Hash(0x19bcff9271d08fcb44a078d242879b51b13a8b58000000000000000000000000)", + "P->V[39528:39560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 638947: Hash(0xc9a03583a0ea24ce2042c194d6dd6061e18b53b6000000000000000000000000)", + "P->V[39560:39592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 653753: Hash(0xaa20ae3630ae867b936443a2d0dc930056dc4da6000000000000000000000000)", + "P->V[39592:39624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 656216: Hash(0xe42767281e51c8c67693a5232be62b6b64a5314d000000000000000000000000)", + "P->V[39624:39656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 663683: Hash(0x2d6184deffcd1d5c557762ff241220da4a280ae5000000000000000000000000)", + "P->V[39656:39688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 667074: Hash(0xf29949f9ccc29fb76227ba7087c97eb3d63ad27c000000000000000000000000)", + "P->V[39688:39720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 667750: Hash(0xfb0ba0cec748141d43835c539aae4dcfe4027206000000000000000000000000)", + "P->V[39720:39752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 690324: Hash(0x9859e5aa878c9124cae410e625fb42bb933c22d3000000000000000000000000)", + "P->V[39752:39784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 743894: Hash(0x25daf6f674990ecb76dde6376fcc189ffec81c2b000000000000000000000000)", + "P->V[39784:39816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 813763: Hash(0x6fcf0e71983b02f07c536f5578d05577dd76eb4f000000000000000000000000)", + "P->V[39816:39848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 865268: Hash(0xe5fa567b20f0d83f5fd6af3de913ac1107c0a48000000000000000000000000)", + "P->V[39848:39880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 921730: Hash(0x8f6bb682c3d3f2f10e4bebdd8542f10f5b13f30000000000000000000000000)", + "P->V[39880:39912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 947288: Hash(0x267db37cbf31ae4ec11b729c0e17ab07eeaaf82000000000000000000000000)", + "P->V[39912:39944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1031497: Hash(0xdc8b5700f5d000ee8ed4dda988bd355670a11253000000000000000000000000)", + "P->V[39944:39976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 266519: Hash(0xccb6197304d027234ace6544599679f9e4c15a7a000000000000000000000000)", + "P->V[39976:40008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 296619: Hash(0x940d6211abb4cb7c523eccebb8982d24fb7cdc78000000000000000000000000)", + "P->V[40008:40040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 319472: Hash(0xd22949a6f325e9148d74cc211dadad6519631de9000000000000000000000000)", + "P->V[40040:40072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 326877: Hash(0xdb5ce10839eefa641341b9974362a531f5faedfc000000000000000000000000)", + "P->V[40072:40104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 328109: Hash(0xf6b71d5e9984f1deceeb75129feb61e0a5e45a5c000000000000000000000000)", + "P->V[40104:40136]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 331840: Hash(0x22db04b2259be9054af1831093c6f42ba952c7f8000000000000000000000000)", + "P->V[40136:40168]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 333536: Hash(0x6e32876e757ce272162745419547224c134f6001000000000000000000000000)", + "P->V[40168:40200]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 333874: Hash(0x1c717b450d912192d61ca1db1109cf78f01b530b000000000000000000000000)", + "P->V[40200:40232]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 345163: Hash(0x9e054b41bdc1b208491ab826e9a7388544a8d26a000000000000000000000000)", + "P->V[40232:40264]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 371946: Hash(0xb853fe82f16cc585b2d0eb16dcf0181473e282cd000000000000000000000000)", + "P->V[40264:40296]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 406880: Hash(0xa8a58e3e9d47527b14cdaf1b81bea85fe3c9c6c3000000000000000000000000)", + "P->V[40296:40328]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 432635: Hash(0xde8590ded392d27e9b8e9000ffed09eb951ed557000000000000000000000000)", + "P->V[40328:40360]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 460864: Hash(0x8960af9d702a4b9018173622b4afe48b50ce4d7d000000000000000000000000)", + "P->V[40360:40392]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 473645: Hash(0x25c6c880e2da12cad1851481d1d0ea7598406cdc000000000000000000000000)", + "P->V[40392:40424]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 515749: Hash(0xf0f3bde2263691641483418f88d1e8a77f7c7414000000000000000000000000)", + "P->V[40424:40456]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 133258: Hash(0xfaa2283986c37e748d51790a06f203385fbf075c000000000000000000000000)", + "P->V[40456:40488]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 148308: Hash(0xa3c45e252f133cb403e4b076d9c95b14730c625d000000000000000000000000)", + "P->V[40488:40520]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 159737: Hash(0x14dd479fc655e4e11377ccbf17616c375003d77000000000000000000000000)", + "P->V[40520:40552]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 163439: Hash(0x14deb4d4b2232d731b5f0173c30b491da5b98ed3000000000000000000000000)", + "P->V[40552:40584]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 164055: Hash(0xd61ca15245d63303d2792d7d26e686d59f9d5bcf000000000000000000000000)", + "P->V[40584:40616]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 165921: Hash(0xae969c1c47dc52715fa8c85d05770172b84f490f000000000000000000000000)", + "P->V[40616:40648]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 166769: Hash(0xc7ab38171c8dcb2800748fc7d42946bd1d59d6e0000000000000000000000000)", + "P->V[40648:40680]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 166936: Hash(0xa2be75eb81b883c47f51021f01a5b44ec073a8b2000000000000000000000000)", + "P->V[40680:40712]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 172580: Hash(0x2fb42ad5de23090eb082f36c0dfc4b6f62e9000e000000000000000000000000)", + "P->V[40712:40744]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 185972: Hash(0xfe7059aac8105d6ddffd1cc1510afcc5309d3cbf000000000000000000000000)", + "P->V[40744:40776]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 203441: Hash(0x6c854fae7bb3dcd92bc2e0e2127495ea66a283a4000000000000000000000000)", + "P->V[40776:40808]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 216316: Hash(0xe62c018be1f4e54b9bb41895df221a138188f6a000000000000000000000000)", + "P->V[40808:40840]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 230433: Hash(0xcf5243d72694833a319dd3eb7c488b07d2d6445f000000000000000000000000)", + "P->V[40840:40872]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 236823: Hash(0x5021d1b0947e6be1d5e143dd52c3de6d426d234f000000000000000000000000)", + "P->V[40872:40904]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 257875: Hash(0x8bfe58635d60c458e1798abfc4ef4879e5d0c326000000000000000000000000)", + "P->V[40904:40936]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 66628: Hash(0xc664a0b376c19d3c040241cfbb7b39bf1f472233000000000000000000000000)", + "P->V[40936:40968]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 74155: Hash(0x3ab4d7c8c94edb0349cf96c7273852b3a11ab7c2000000000000000000000000)", + "P->V[40968:41000]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 79869: Hash(0x357bc31abf9617b32ae38f20c450c8168e5c238e000000000000000000000000)", + "P->V[41000:41032]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 81718: Hash(0x54c3735176d13cb9905026e8d96e938a59cd4b2e000000000000000000000000)", + "P->V[41032:41064]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 82026: Hash(0xc44b63b31ce0219983ee3f67462dbf6944c6caff000000000000000000000000)", + "P->V[41064:41096]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 82961: Hash(0x5092eb9caed9998f5a17cef15224c431cbc5c668000000000000000000000000)", + "P->V[41096:41128]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 83385: Hash(0xf37e94404fc4e7d052336f1cb7ca62ccf3ce41d5000000000000000000000000)", + "P->V[41128:41160]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 83469: Hash(0xc25db36d95e66fcc20d185e2f0cdc6820dcca886000000000000000000000000)", + "P->V[41160:41192]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 86291: Hash(0xba0ca55651dd8d65eae830e944f74c100c219c03000000000000000000000000)", + "P->V[41192:41224]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 92987: Hash(0x8257d8d0e850178fb7f0193d629b2b6194b19f41000000000000000000000000)", + "P->V[41224:41256]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 101721: Hash(0x103e84d16c14d3d4e04d9861debf558cd1b72be000000000000000000000000)", + "P->V[41256:41288]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 108159: Hash(0x979b08d51ea7cdf0a88b3239ad1e59a915057299000000000000000000000000)", + "P->V[41288:41320]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 115217: Hash(0x46680916b5dcc5dfdf8a511c03ad28e92d3866e6000000000000000000000000)", + "P->V[41320:41352]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 118410: Hash(0x7e02878d62ccd5c23c55f60e42ce4daa77ec9a79000000000000000000000000)", + "P->V[41352:41384]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 128936: Hash(0x721894a7cb9222a1146faaa745f4f25dd8489f5c000000000000000000000000)", + "P->V[41384:41416]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 33315: Hash(0xf2da95da524cd30e7f402d7425c0c6ed36f20616000000000000000000000000)", + "P->V[41416:41448]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 37076: Hash(0x96cbd1232a18e3b0b4ce4a18e287f3a335260c0d000000000000000000000000)", + "P->V[41448:41480]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 39935: Hash(0x63724faf5056c1909c67bf12824e559cddeb02ed000000000000000000000000)", + "P->V[41480:41512]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 40858: Hash(0xf94d8913aa35a79266ee6787b43237a3a262961e000000000000000000000000)", + "P->V[41512:41544]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 41012: Hash(0x1f9eeb454d801fef0dbdac7bd57b69965d0f004b000000000000000000000000)", + "P->V[41544:41576]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 41481: Hash(0x81c86622b7ea975110295e3ab5a3abfe7f56e60f000000000000000000000000)", + "P->V[41576:41608]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 41693: Hash(0x7baeaa132412ed81e00d580a61476ebac3a3bdfa000000000000000000000000)", + "P->V[41608:41640]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 41735: Hash(0x3e4629cdce66e7edd392f81ced5dfc661b30da7e000000000000000000000000)", + "P->V[41640:41672]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 43144: Hash(0xd4dcd9dcf0380efd23c211fe5c6f178c0e1f754d000000000000000000000000)", + "P->V[41672:41704]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 46492: Hash(0x1f99dc9c3abf4cfd2f7b085b17a3d1925bae9ac4000000000000000000000000)", + "P->V[41704:41736]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 50861: Hash(0x2f7d26429ebca19187d447a0bd7877530c8c68c5000000000000000000000000)", + "P->V[41736:41768]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 54078: Hash(0x287cd8ea04fc0d88fef857aec93198f86563115a000000000000000000000000)", + "P->V[41768:41800]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 57609: Hash(0x266eaace0d388cd4a57fa7849043a35744634a50000000000000000000000000)", + "P->V[41800:41832]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 59204: Hash(0x4b86a06fcd95d0f0ee80d855647473521e35293d000000000000000000000000)", + "P->V[41832:41864]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 64469: Hash(0x709725115564b75a34087b8c6078a6271b9a61bd000000000000000000000000)", + "P->V[41864:41896]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 16656: Hash(0x5c5e4bc0fb1a0cd231bf88c602c98bc015bf92ce000000000000000000000000)", + "P->V[41896:41928]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 18539: Hash(0x171ec4dfa944674b2c24142debca3ca8049d8c71000000000000000000000000)", + "P->V[41928:41960]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 19966: Hash(0x85e3a39ca46f6c73e71b2c5f89939a9a58e88f6d000000000000000000000000)", + "P->V[41960:41992]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 20428: Hash(0xaae2a31ae2b834004c4d887dfc64121d2994faef000000000000000000000000)", + "P->V[41992:42024]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 20507: Hash(0x80afd0d3b6e568eef9e148e5075f36e7ba2f0670000000000000000000000000)", + "P->V[42024:42056]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 20741: Hash(0x3dfbe5a1688cef33a00ef5052279ad9484d97760000000000000000000000000)", + "P->V[42056:42088]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 20847: Hash(0x7df1a07008b526ae0c8728c4b5910ddc06e4f8e6000000000000000000000000)", + "P->V[42088:42120]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 20866: Hash(0xe64c6af55c7969de9545fddce92611ca7a328b7000000000000000000000000)", + "P->V[42120:42152]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 21573: Hash(0x30a95f2e9a16b380fe02aacd0807048b6bed8051000000000000000000000000)", + "P->V[42152:42184]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 23247: Hash(0x1be9082527bc5c6fbdc5b191b8b730d33bf6f542000000000000000000000000)", + "P->V[42184:42216]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 25431: Hash(0x24e94bffc81fb529bff4831b48fcba873658a4b2000000000000000000000000)", + "P->V[42216:42248]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 27038: Hash(0x293df72a87ff0088ef26f6f2e631db54c6fe4564000000000000000000000000)", + "P->V[42248:42280]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 28805: Hash(0x94a7dd237987f3432747418a91e70f080de19ea1000000000000000000000000)", + "P->V[42280:42312]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 29603: Hash(0xf2d560a02b7a5e117a35e67ddd9474529f29fe8c000000000000000000000000)", + "P->V[42312:42344]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 32235: Hash(0x8ea51acb33dd89e4b03c98bc63982bbc07d9bc6a000000000000000000000000)", + "P->V[42344:42376]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 8329: Hash(0x84bfbe8025560f7d808b5c1cce4c76ac303c9fd000000000000000000000000)", + "P->V[42376:42408]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 9268: Hash(0x27dbe02d3f915a57a193350ffb850e3ff4b44bf000000000000000000000000)", + "P->V[42408:42440]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 9982: Hash(0xd91ad817fd1686cbb21b76f13e6ab9b8d100dab8000000000000000000000000)", + "P->V[42440:42472]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10215: Hash(0xd57333bb4d3db1191f9fff1c65008864921e479000000000000000000000000)", + "P->V[42472:42504]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10252: Hash(0x2bfec1bd4d93ca40afe802a9a90f7cb7c539eee8000000000000000000000000)", + "P->V[42504:42536]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10371: Hash(0x3ff92b64d6c973011bce4a423eef6e8d21220b56000000000000000000000000)", + "P->V[42536:42568]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10422: Hash(0x662b849e75f3d2e24194bb3b67e6678fe48d9e4a000000000000000000000000)", + "P->V[42568:42600]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10432: Hash(0xb85eeea0c6e0d7548dd50884909fab58010e7d43000000000000000000000000)", + "P->V[42600:42632]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10787: Hash(0x468220bca43afbb3bf3e2b8568bcb38547928fc1000000000000000000000000)", + "P->V[42632:42664]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 11622: Hash(0xfcc0a4dcdf3d3757b24c2f5282fe9c4af5ff2089000000000000000000000000)", + "P->V[42664:42696]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 12714: Hash(0x1b743a7cafd418fb255266388b4c98a0655a49ef000000000000000000000000)", + "P->V[42696:42728]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 13518: Hash(0xea412637e7916090df5eebfbd8bd5aa2bebcb802000000000000000000000000)", + "P->V[42728:42760]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 14403: Hash(0x92bfcd5964a06443eea3776e6c5b046419cdd32f000000000000000000000000)", + "P->V[42760:42792]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 14800: Hash(0x172d06dd7d6006b7e70d82430c8aee18ac0476f000000000000000000000000)", + "P->V[42792:42824]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 16116: Hash(0xff24d26826d31e330d27f355daacced770b71fc2000000000000000000000000)", + "P->V[42824:42856]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 4165: Hash(0xa43fcb519b8785df5dc4fab93902bf7b892a2b44000000000000000000000000)", + "P->V[42856:42888]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 4635: Hash(0x5b153aa667fb1edd7ae099d6cc50b64a9c28d48a000000000000000000000000)", + "P->V[42888:42920]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 4990: Hash(0x56a4c948cb162e494b7e97ed62e0b7c99d614192000000000000000000000000)", + "P->V[42920:42952]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5106: Hash(0x568c44a051741dff5b39ec363cee05af4fbeba5a000000000000000000000000)", + "P->V[42952:42984]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5127: Hash(0x646efcd706afa00e46b7cd980e4df0e1f8a2fe0a000000000000000000000000)", + "P->V[42984:43016]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5184: Hash(0x1ef86427089e2e92b9aeecec0b1f05914083184000000000000000000000000)", + "P->V[43016:43048]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5210: Hash(0xd3eb3fd20087dd778d32e161e826374b297d3225000000000000000000000000)", + "P->V[43048:43080]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5217: Hash(0x250134a0b80b8d2439efef402c2146051fce433e000000000000000000000000)", + "P->V[43080:43112]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5392: Hash(0xfa9151336b14fec477f050b56b9237386ba2b263000000000000000000000000)", + "P->V[43112:43144]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 5810: Hash(0xe534c91b5de120a23a8b4732ad3832f7f9548b2d000000000000000000000000)", + "P->V[43144:43176]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 6356: Hash(0x7fe5c663326a3383c16732d904ce7e8643042035000000000000000000000000)", + "P->V[43176:43208]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 6758: Hash(0x15b8f57577d71d39e6a34868cddc7782504c74a4000000000000000000000000)", + "P->V[43208:43240]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 7200: Hash(0x91b256a533a84cc3ee40cf6e6801ea61c92298a7000000000000000000000000)", + "P->V[43240:43272]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 7401: Hash(0xb2385ac9599b9ccb879d9305480406c7507c211f000000000000000000000000)", + "P->V[43272:43304]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 8059: Hash(0x73c86834a6a3c1946f0fa5bcd5ba2cfd81d68941000000000000000000000000)", + "P->V[43304:43336]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2083: Hash(0xafcfd20c056465e1803ae033c0ab8ab8a75308a2000000000000000000000000)", + "P->V[43336:43368]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2316: Hash(0x6a15e871c95d9f679aa95599b30e9d1c54baa739000000000000000000000000)", + "P->V[43368:43400]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2494: Hash(0xb37638287f37de8994760bc3319437800e27bab2000000000000000000000000)", + "P->V[43400:43432]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2552: Hash(0x75769a7d655adb9037d86cbe9803cb4c54031309000000000000000000000000)", + "P->V[43432:43464]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2562: Hash(0xc91817a38b996d44f319c1ee157e1680579b1588000000000000000000000000)", + "P->V[43464:43496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2593: Hash(0x753c9f266afbf3a6b17087e759510cfdc7e6edfb000000000000000000000000)", + "P->V[43496:43528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2604: Hash(0x53e57cda7af66191c4d473eea518ff299fdbf811000000000000000000000000)", + "P->V[43528:43560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2609: Hash(0x391d04772298978438fee55d2140ec59330dbe2d000000000000000000000000)", + "P->V[43560:43592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2697: Hash(0x322ebc78b05ee8e2f5bde4a175e55770a40d97d2000000000000000000000000)", + "P->V[43592:43624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2904: Hash(0xd80c4148438d3a3c7dec30d3fb3f44a142a1bdb6000000000000000000000000)", + "P->V[43624:43656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 3179: Hash(0xe0d7f83fe6adf962e47c9633717407bba8c77a86000000000000000000000000)", + "P->V[43656:43688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 3378: Hash(0xd0cccb71b6c4af516af59551ebfe1243491d840c000000000000000000000000)", + "P->V[43688:43720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 3601: Hash(0x9cc5ea34e91f342c8a151b37e1c0ffd8db36cd1b000000000000000000000000)", + "P->V[43720:43752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 3701: Hash(0xfc81c03dbcfe4ac53274f460cd8f2242bc26d230000000000000000000000000)", + "P->V[43752:43784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 4028: Hash(0x7fc8ccec40a75628e75c5cf990f7d6f249f16346000000000000000000000000)", + "P->V[43784:43816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1040: Hash(0x9dcfbba888af99da9693c230d23be85062406f2c000000000000000000000000)", + "P->V[43816:43848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1159: Hash(0xbd6536bfa480cb9b114f74324539084052b857bc000000000000000000000000)", + "P->V[43848:43880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1246: Hash(0xe0fed31a68cb114bfed49fe91e6bd1c745eb7e43000000000000000000000000)", + "P->V[43880:43912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1277: Hash(0xd86c3f30aadd80cb21b7577aac2df32c4ebaadbd000000000000000000000000)", + "P->V[43912:43944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1280: Hash(0x90d20a782413b5ce9df4b25fcbaf6a94725f8ca8000000000000000000000000)", + "P->V[43944:43976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1297: Hash(0x683ca6c0e74ffba5ef978efc53c1585e4c094f04000000000000000000000000)", + "P->V[43976:44008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1303: Hash(0xc429da028a4c26c8f0401ca68ef5fd136d2f24e000000000000000000000000)", + "P->V[44008:44040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1305: Hash(0x4413538011b57145eef29e372f8b7e73780202f7000000000000000000000000)", + "P->V[44040:44072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1349: Hash(0xbfc24ee60403128dd5c4ef6e7863efb12e6bf375000000000000000000000000)", + "P->V[44072:44104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1453: Hash(0xa8a578e69247721c750d6951e8346d1e158786df000000000000000000000000)", + "P->V[44104:44136]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1588: Hash(0x719d6c9931a5c3e23041480f72a29beb946f00a4000000000000000000000000)", + "P->V[44136:44168]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1688: Hash(0x813f5c2786a2a3c39cb00de637ae4050dad148e0000000000000000000000000)", + "P->V[44168:44200]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1801: Hash(0xf76108a374c7444e29cf464cfa79d746b9e0fe82000000000000000000000000)", + "P->V[44200:44232]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1851: Hash(0x71d95f129d590da0d2aba6120b2ad3043c0e1592000000000000000000000000)", + "P->V[44232:44264]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 2015: Hash(0xccf6ba3272dafcf87a72b2f32c9c12f966e95e25000000000000000000000000)", + "P->V[44264:44296]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 521: Hash(0xfc17317d9af6b8769ce257e3c12ac305717c9ef7000000000000000000000000)", + "P->V[44296:44328]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 578: Hash(0xa2232221f456f01931ff0f3ef6440d1cb9c2a8ba000000000000000000000000)", + "P->V[44328:44360]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 622: Hash(0x71e2228e3829cf3f0b461cbcacecb69954368412000000000000000000000000)", + "P->V[44360:44392]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 639: Hash(0xa6e4d5113dd8ae10850e66fc0def1afe54f47b9c000000000000000000000000)", + "P->V[44392:44424]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 641: Hash(0xa84956c4784d24c9b137c10f945395f0037b3bb2000000000000000000000000)", + "P->V[44424:44456]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 649: Hash(0x104eae8510724ad53015b689d862220033c33628000000000000000000000000)", + "P->V[44456:44488]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 650: Hash(0x88ce429744010a61600ccb33a3b5f53235bb319000000000000000000000000)", + "P->V[44488:44520]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 653: Hash(0x91ac045290b895f83f4c0c5bad637262df133246000000000000000000000000)", + "P->V[44520:44552]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 675: Hash(0xd9690b51fb3767a1d8fb794bf32ec8812025c161000000000000000000000000)", + "P->V[44552:44584]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 727: Hash(0x16fba363298d4b344bc78016d5a442d966b8c8a0000000000000000000000000)", + "P->V[44584:44616]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 795: Hash(0xe1862448fa34c7f42f966061d94192bd7c614caa000000000000000000000000)", + "P->V[44616:44648]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 845: Hash(0x2352196b8be75dbfd8e31209675b5a4a8d7ddb6000000000000000000000000)", + "P->V[44648:44680]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 901: Hash(0xffaec6b1d425a6d4b521947d45f66e864aab9d31000000000000000000000000)", + "P->V[44680:44712]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 924: Hash(0xa55b58f5f33eca49cb5499ea90fee88ac61d71f000000000000000000000000)", + "P->V[44712:44744]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 1006: Hash(0x5fceade942f83997ccd1360214de03f428ad966000000000000000000000000)", + "P->V[44744:44776]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 261: Hash(0xf7f9cd9fb11f0fe75822d2d0ce5258ef7fa17b96000000000000000000000000)", + "P->V[44776:44808]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 288: Hash(0xb4577a705467d880edeefed51136715572e8d9d9000000000000000000000000)", + "P->V[44808:44840]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 310: Hash(0x1c90240ecc6f47779c0ee649f81baf4147d07bf5000000000000000000000000)", + "P->V[44840:44872]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 318: Hash(0x997c8f1d748a15189eae721a30ce62eedf3810f6000000000000000000000000)", + "P->V[44872:44904]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 321: Hash(0x6c74e1e733e0b0ca3fd1f2b7b2e9b1a1207a3b92000000000000000000000000)", + "P->V[44904:44936]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 327: Hash(0x74376efe654da1bc33b21c76c34550c7d2bbc31a000000000000000000000000)", + "P->V[44936:44968]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 336: Hash(0xbf12af6ef5289b3b84edacbc8a29e92559e80220000000000000000000000000)", + "P->V[44968:45000]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 362: Hash(0xa53ff0515c2a444232f309d3c92dca400fe7d89b000000000000000000000000)", + "P->V[45000:45032]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 396: Hash(0x6213aac316815e10f9910355f9cca70a76aab5e8000000000000000000000000)", + "P->V[45032:45064]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 423: Hash(0x1e5bd9bf6bdd99f3e19298d84a2be3f8f829f84000000000000000000000000)", + "P->V[45064:45096]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 451: Hash(0x1267e826b639b9ff31a4d9b5bdac83937716f67f000000000000000000000000)", + "P->V[45096:45128]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 463: Hash(0x3f63c7b721c7627035567352a2ed8cc01de330b0000000000000000000000000)", + "P->V[45128:45160]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 502: Hash(0xdd475ea75e008ae00053060267bccb78296807e0000000000000000000000000)", + "P->V[45160:45192]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 131: Hash(0x3a78fba291489fd444834bbae9124f312b83e346000000000000000000000000)", + "P->V[45192:45224]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 145: Hash(0x69d8b63d27cb0b477b4c9ef4f828039ecbe916fb000000000000000000000000)", + "P->V[45224:45256]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 154: Hash(0x843380f221d42d978b99153192a883d7c39810b1000000000000000000000000)", + "P->V[45256:45288]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 158: Hash(0x655fc95b81d8af387f0aa90db2590ae417f34471000000000000000000000000)", + "P->V[45288:45320]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 161: Hash(0xccc425024f472142488fcba92ccd40b6f4a5d667000000000000000000000000)", + "P->V[45320:45352]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 169: Hash(0xff7dda44104eb6a9c690201bead1c045c0ba069c000000000000000000000000)", + "P->V[45352:45384]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 180: Hash(0x8ec5af3c93a96f36c9a942fa8d1d81d2852645a4000000000000000000000000)", + "P->V[45384:45416]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 199: Hash(0xb13b17939cbbdc73daedd6d8775d5d76fce5d8ed000000000000000000000000)", + "P->V[45416:45448]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 210: Hash(0x9eb40358dc13d208130c6bf446c52193a73eaf1b000000000000000000000000)", + "P->V[45448:45480]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 224: Hash(0xe8dc502835d333a3a4a27c75d4e0b24992f84225000000000000000000000000)", + "P->V[45480:45512]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 230: Hash(0xef15fa44ac3c28003c2ef1212c32c40d376430d8000000000000000000000000)", + "P->V[45512:45544]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 250: Hash(0x3a2054e7d73c499bb579f7e65729512bb1a7034d000000000000000000000000)", + "P->V[45544:45576]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 64: Hash(0xc0aea0a993950c7f3814a40815ccc7dc7711cd72000000000000000000000000)", + "P->V[45576:45608]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 73: Hash(0xbe6b3d39956cd2f2959a9b1af70d6622246a4f07000000000000000000000000)", + "P->V[45608:45640]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 76: Hash(0xa47b676cf2ee89b4dba0049b69a9d0ceb77882ac000000000000000000000000)", + "P->V[45640:45672]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 78: Hash(0x175975afa695b9fc68a4aeef2c5ecea172114cbc000000000000000000000000)", + "P->V[45672:45704]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 85: Hash(0x8b21412ae96bd5ed86231d354a525501a45ca811000000000000000000000000)", + "P->V[45704:45736]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 91: Hash(0xd7be5fbcc6b8fa4ce065f7b800eca525ccded7ca000000000000000000000000)", + "P->V[45736:45768]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 98: Hash(0xd60d497f2b054c6ceb098afbd2e19c4f9f770379000000000000000000000000)", + "P->V[45768:45800]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 104: Hash(0x759f778db7c0f5cfb1f8ae17a0d4849bfcf2f6fd000000000000000000000000)", + "P->V[45800:45832]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 113: Hash(0xd01df80b5312b51c54a72fdfe9f7d4ecd9f68f9000000000000000000000000)", + "P->V[45832:45864]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 114: Hash(0x9b9ca31457c3bbca39c2739c0af7283b57d6265d000000000000000000000000)", + "P->V[45864:45896]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 124: Hash(0x42216134d0aacc9f25294d8ce6d14d3f971e3670000000000000000000000000)", + "P->V[45896:45928]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 33: Hash(0xb99defa83ee553475a23feb1b536726791bfec9e000000000000000000000000)", + "P->V[45928:45960]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 37: Hash(0x290c2e952f1bb5d479f0b482f1e15348abf36bf5000000000000000000000000)", + "P->V[45960:45992]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 41: Hash(0x2f3e596b110db1f3f9099f8ce13cc61c2de2c145000000000000000000000000)", + "P->V[45992:46024]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 43: Hash(0x447603984a72e346d8657b9636010efa97aa8c10000000000000000000000000)", + "P->V[46024:46056]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 44: Hash(0xd4fff94eee29a9965aa0aaf2c0fd6e6bdd6e5d01000000000000000000000000)", + "P->V[46056:46088]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 48: Hash(0x67b713a116096985982a6cb67d7b3d26fde4d1b8000000000000000000000000)", + "P->V[46088:46120]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 53: Hash(0xf39b400691bf6387f8dd23761ebdbd5c681339f9000000000000000000000000)", + "P->V[46120:46152]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 63: Hash(0x78e19cbb1fe374ae9118024c900b5e41cf0d9d48000000000000000000000000)", + "P->V[46152:46184]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 17: Hash(0xd7d9c5e4f8e546e25b2d6febfafb0109d40fb1f4000000000000000000000000)", + "P->V[46184:46216]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 23: Hash(0xa1a28f93aabdb0b629be1bb05c18d6a67283583e000000000000000000000000)", + "P->V[46216:46248]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 25: Hash(0x96b33837ac9c0fec80ced9f1d75ba6f5d999a31c000000000000000000000000)", + "P->V[46248:46280]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 27: Hash(0x781c3787aa298f4f918343f482df21a2729e49a9000000000000000000000000)", + "P->V[46280:46312]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 29: Hash(0x47ffe4d9d7e2a78e36170fd52283b7f8352af1c8000000000000000000000000)", + "P->V[46312:46344]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 30: Hash(0x9b4a500ac6e2f8321f612bb8a1ef9766d07594e7000000000000000000000000)", + "P->V[46344:46376]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 139993, Column 0: Field Element(0x161288696894ed9ab23bb12565fd9decf14d748e955f2842f6dcc21af103a84)", + "P->V[46376:46408]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 139993, Column 1: Field Element(0x556abfa9d5fc7f82e5f7de4fcacb08b4168849a6064db28389da8ea40dad0a4)", + "P->V[46408:46440]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 1103176, Column 0: Field Element(0x714f57a398433fb5ad22fac152a45d0b1c7f97aa0af9fa34e8f9847d7d7245d)", + "P->V[46440:46472]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 1103176, Column 1: Field Element(0x2033fbc65a5fa13b745c5d8e8f88287e19350904d45f36875918ed506c63d4b)", + "P->V[46472:46504]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 1834537, Column 0: Field Element(0x712c0281a1a79ef59521e6d61eed496a1eee55db968c6a23d5b1bf3506455be)", + "P->V[46504:46536]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 1834537, Column 1: Field Element(0x54fa03bac5f6fbf8ee4ebb7167e89f6871e6bd54dbe9244229b32f055c9cb4e)", + "P->V[46536:46568]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2071439, Column 0: Field Element(0x1d32d6aaf79d45470a216bb5a34192d75355554aee4c7e8c71684f38f81ba6d)", + "P->V[46568:46600]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2071439, Column 1: Field Element(0xbb43fd1057422a1116b4dd3c8e033dbf2a71c27e2481c719557e71dba26d5a)", + "P->V[46600:46632]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2110874, Column 0: Field Element(0x4972b1ea0ece676c3dd34e841a58ad622a49318d16cebe9dae1c886ff60d3cd)", + "P->V[46632:46664]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2110874, Column 1: Field Element(0x339e238e256131695d02bbe3f182defba563541ec3cf0a31d851b6f383d0330)", + "P->V[46664:46696]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2230304, Column 0: Field Element(0x26b3c994fb7a1c85f91aeb863874a2b2f82b03ca4de819e79b3c92d96fc529b)", + "P->V[46696:46728]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2230304, Column 1: Field Element(0x7fca9d824bc64b45c509915d023ac7a1fcba280675c3c9072ca029b346c819a)", + "P->V[46728:46760]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2284596, Column 0: Field Element(0x60a390e9e1dcd3b24ed2e86d97cdb02a8aaa4bd560eed50ef048022c44ddb99)", + "P->V[46760:46792]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2284596, Column 1: Field Element(0x146781aaf54d3e1ba4df45312c6bfe04f7d2e31c6cc153579625ea69a33c7c1)", + "P->V[46792:46824]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2295414, Column 0: Field Element(0x26a77a99906bb29c23f082373aa0abe57fb04ff12ded4661bb895c28aa25a49)", + "P->V[46824:46856]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2295414, Column 1: Field Element(0x4df442753aa2cbb37798d8790591ff9b664e03d88cb9bbbb5d9fbcbb6404be0)", + "P->V[46856:46888]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2656598, Column 0: Field Element(0xf62291adca543379f76ab49706247adab9728118b9fae1843be2d08731550c)", + "P->V[46888:46920]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 2656598, Column 1: Field Element(0x30e9b792a7a3cb5aa5b407d0321ad38e5cc792df16f15c2f1a9dbb3c77e33d0)", + "P->V[46920:46952]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 3513722, Column 0: Field Element(0x60661f1f9a1db5af10514cbb847e1e63a2bcf570b8f06713f44ab3c25314260)", + "P->V[46952:46984]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 3513722, Column 1: Field Element(0x6dd1046172e96af2dc3077ea914e43090484686f65dc6d978bd0c2c91be4fb3)", + "P->V[46984:47016]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 4631593, Column 0: Field Element(0x4bc4af60d0427034a17e4d610284989a62e12a736b6e15ecd873f6af2d0fe72)", + "P->V[47016:47048]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 4631593, Column 1: Field Element(0x5e8b395984e8f2387d25dd3e147fb4d10142499ac5f108ea1b4498b71dee1de)", + "P->V[47048:47080]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 5455705, Column 0: Field Element(0x69bfdbaac2699bd38c07abe7fafcbcc967f28ef33578ee8cc89304d946b795d)", + "P->V[47080:47112]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 5455705, Column 1: Field Element(0x2d8b9cd4e1c6056875030b45608789cf6f04cbe6222f0d49b835c5b7de11057)", + "P->V[47112:47144]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 6359094, Column 0: Field Element(0x7352323d812b5321f5602463eaa8a1661979a8556c789ee1f5ea91ea0750028)", + "P->V[47144:47176]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 6359094, Column 1: Field Element(0x33ddba50364b5d66a01ecef13ddf2325f008d3c07ee3773ce7737c29e51014a)", + "P->V[47176:47208]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 6768031, Column 0: Field Element(0x7c495ddc094513b853ac6d940c6b0366e438019f2f496bfed63dd8b718ac6b9)", + "P->V[47208:47240]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 6768031, Column 1: Field Element(0x544914d414a0ef4e62af79809282f78e7257f112a59c65aaa9b175913d78dc1)", + "P->V[47240:47272]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 8115330, Column 0: Field Element(0x70e0bd41202aa0b259a68ab1dc0dc80d3db08c8a08e8b8dcd34569cb1fb708)", + "P->V[47272:47304]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: Row 8115330, Column 1: Field Element(0x7ab51e4480ef4ef571291098505f46fc67d511f1274e8cfd4c711548faae6eb)", + "P->V[47304:47336]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 8528600: Hash(0xf1ac4063b956d7ed7dc938a7fa9d4011c2836dce000000000000000000000000)", + "P->V[47336:47368]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 9491785: Hash(0xa30e1a1c8effa786f8d988b28114c599082dd4d4000000000000000000000000)", + "P->V[47368:47400]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10223144: Hash(0x9684e6014cc44f2de22d631a9c382e7392073c49000000000000000000000000)", + "P->V[47400:47432]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10460046: Hash(0xa5bdfd1a57ce8d1257b15ded07342611734a3998000000000000000000000000)", + "P->V[47432:47464]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10499483: Hash(0xfeb3cd1bcae33cd0320596057c258157c4405256000000000000000000000000)", + "P->V[47464:47496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10618913: Hash(0xc03a2514407a7f485e86dd3b15989d3c2ac0380f000000000000000000000000)", + "P->V[47496:47528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10673205: Hash(0x872e3678b36667700369d2f92d7d500b5682d1ce000000000000000000000000)", + "P->V[47528:47560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10684023: Hash(0xd9010076455f84acb9dd2e093cd1782ea5443681000000000000000000000000)", + "P->V[47560:47592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 11045207: Hash(0xcb27505a4457616947973c865f4e86f9db517dd0000000000000000000000000)", + "P->V[47592:47624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 11902331: Hash(0x32fcd9889b2c4af04f66c301f1808d2865c3d4ca000000000000000000000000)", + "P->V[47624:47656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 13020200: Hash(0x48971fab417f06488ed5abc7d61dff54a2ec109d000000000000000000000000)", + "P->V[47656:47688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 13844312: Hash(0x7931457457717c404080974ba7dbf42dd3b4f8ec000000000000000000000000)", + "P->V[47688:47720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 14747703: Hash(0xbc879a0eb5b51cfdd170c9907d3a5f9b7d3782fc000000000000000000000000)", + "P->V[47720:47752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 15156638: Hash(0x9982e690c6b4a7d155020b6a617b295c5ce6dffc000000000000000000000000)", + "P->V[47752:47784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 16503939: Hash(0xb8c92432d80438aff718f827970bf7990eb910b0000000000000000000000000)", + "P->V[47784:47816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 4264301: Hash(0xd2169629ce888daaa0279c7e8f05d129a38b58b000000000000000000000000)", + "P->V[47816:47848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 4745893: Hash(0xc296a3555a20363940404653eeb3cebd1964ef20000000000000000000000000)", + "P->V[47848:47880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5111573: Hash(0xbadcd1f119a9bc54c0c3f54e9203bdd9b7e326d3000000000000000000000000)", + "P->V[47880:47912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5230022: Hash(0xaff93be7621c1719c80252c03190ed2bec1b6856000000000000000000000000)", + "P->V[47912:47944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5249740: Hash(0x488761835bfbc0f5b765cc014acd1bbc3ff9fcd9000000000000000000000000)", + "P->V[47944:47976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5309457: Hash(0xaff81acc2b9e9bea1e46db9b2e855a86249ac19e000000000000000000000000)", + "P->V[47976:48008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5336603: Hash(0x8127f3ee25777097fb421d7597ea879bd3b0488d000000000000000000000000)", + "P->V[48008:48040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5342010: Hash(0x6beb06dc89b69b0beb287014a9efba0389fbfeac000000000000000000000000)", + "P->V[48040:48072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5522602: Hash(0xfc5e1d7f3066ae06699be0f4fec0853d9e28ae74000000000000000000000000)", + "P->V[48072:48104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5951164: Hash(0x63a1e45745741c607baa0ec70c2ecc9ed6831c3a000000000000000000000000)", + "P->V[48104:48136]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 6510101: Hash(0xbfa1b149229d581b97e97acdb6f7fbf7bcbc1bec000000000000000000000000)", + "P->V[48136:48168]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 6922157: Hash(0x493fb24cfc00f7f3d38897c07efb0a686a3b1ed7000000000000000000000000)", + "P->V[48168:48200]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 7373850: Hash(0xff03cbc68dc6e05a63a807836184bd2378081c5f000000000000000000000000)", + "P->V[48200:48232]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 7578318: Hash(0xdee446e1a419c21007e249450b70cee68079c29c000000000000000000000000)", + "P->V[48232:48264]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 8251968: Hash(0x6035532d473baf340a20a4a9ee55c1bcb62248f4000000000000000000000000)", + "P->V[48264:48296]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2132151: Hash(0xcf04dfca20f49fce74518902fc8394d51cc28e51000000000000000000000000)", + "P->V[48296:48328]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2372947: Hash(0xd3f07b7e7d25b43fb93bdd3b9cae1a867a8b77f4000000000000000000000000)", + "P->V[48328:48360]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2555787: Hash(0x52f50aae48ef1477893d25c111afc9722cc587de000000000000000000000000)", + "P->V[48360:48392]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2615010: Hash(0x503dd94a71cdfe02f8faab76fbc2e47f932b79f2000000000000000000000000)", + "P->V[48392:48424]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2624871: Hash(0x94e4e52009f2163d947e2ec0a75e73d0c4e9cd4e000000000000000000000000)", + "P->V[48424:48456]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2654729: Hash(0x960fa51361110ee935b38a8331941c68c8a6ae25000000000000000000000000)", + "P->V[48456:48488]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2668300: Hash(0x9c5169757246fb07abad05cdd0d15d4036684a0b000000000000000000000000)", + "P->V[48488:48520]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2671004: Hash(0xc00d5068bf239b3547a08c61482ceb7ea3206c4f000000000000000000000000)", + "P->V[48520:48552]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2761300: Hash(0x9f100932fb6c6eb714ea6fcc1d55072aa5b3dfbf000000000000000000000000)", + "P->V[48552:48584]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2975583: Hash(0x7249155db9e5ea06b648c74a5de7db8a0ac0fb45000000000000000000000000)", + "P->V[48584:48616]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 3255051: Hash(0x16cdb47244e7ad93a68a49f71ccdf6bb49b0dd7d000000000000000000000000)", + "P->V[48616:48648]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 3461079: Hash(0xe2bd2f3a9119fbbc7bfe95c0786e6a0efe07bd6a000000000000000000000000)", + "P->V[48648:48680]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 3686924: Hash(0x2eab9ba9b8f29bc82bbf5d4b1d54df05f95793b1000000000000000000000000)", + "P->V[48680:48712]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 3789158: Hash(0x831fb2dfa43ddff3d091948a261fd29f0ca239c3000000000000000000000000)", + "P->V[48712:48744]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 4125985: Hash(0x3609b0c198e90fb9accd39a42ae92475c75d509000000000000000000000000)", + "P->V[48744:48776]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1066074: Hash(0x4f74669225a70c97e20fcf56a4ab6e3ca38fd46f000000000000000000000000)", + "P->V[48776:48808]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1186472: Hash(0x7cf665ae2c4ae48485c7d08f0c8a4e85e6f0ddd5000000000000000000000000)", + "P->V[48808:48840]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1277892: Hash(0x1fc5c370691eecbbe08f07b5111113d1017de4c8000000000000000000000000)", + "P->V[48840:48872]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1307504: Hash(0xe9322d4fd290d6730eeea19aee5aa26a0a4645f0000000000000000000000000)", + "P->V[48872:48904]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1312434: Hash(0xa8efab5cf736d5b6f5a3fcbdddfbc25c16c3a3d5000000000000000000000000)", + "P->V[48904:48936]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1327365: Hash(0xdc4f93ca2c5b3857dcd81b4960101e25d2bd1de0000000000000000000000000)", + "P->V[48936:48968]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1334151: Hash(0x3cd5713ea97d15c160df0bb05d52baa82f90d7f5000000000000000000000000)", + "P->V[48968:49000]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1335503: Hash(0x911c95863a662ba44d698178f877a25d645dd76000000000000000000000000)", + "P->V[49000:49032]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1380651: Hash(0x5f41ef14f66cb451acada365663033d8cc211986000000000000000000000000)", + "P->V[49032:49064]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1487790: Hash(0x554c3747c33c9f880404938e687b645baa13a35f000000000000000000000000)", + "P->V[49064:49096]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1627524: Hash(0x2a7ad43c3787523d229c7d2ee2474152f4c707f9000000000000000000000000)", + "P->V[49096:49128]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1730538: Hash(0x43e7e269fd3e63cb4b49ab67e92b77c29e563e61000000000000000000000000)", + "P->V[49128:49160]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1843463: Hash(0x42999409c367184905a4e8b460ff6054b3ee6be4000000000000000000000000)", + "P->V[49160:49192]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1894578: Hash(0x8a02602676c08670f9c4e4d8e2f1abe42bcfbcb0000000000000000000000000)", + "P->V[49192:49224]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2062993: Hash(0x94444f3b682516b2421abddaced3c5c40a43a0ea000000000000000000000000)", + "P->V[49224:49256]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 533036: Hash(0xded78604b26e4c75e7afb061badebd2a113b1091000000000000000000000000)", + "P->V[49256:49288]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 593237: Hash(0x660546156e9b2f36200f40edf1ef24353c490f3000000000000000000000000)", + "P->V[49288:49320]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 638947: Hash(0x28d69d28ba00c9da186f90e0bde6754738977f6f000000000000000000000000)", + "P->V[49320:49352]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 653753: Hash(0x2075ce11978aef9d53f7b26a1f1640d378d8fab3000000000000000000000000)", + "P->V[49352:49384]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 656216: Hash(0x56563df7ab78658f9585f304bf0550f3fba82a05000000000000000000000000)", + "P->V[49384:49416]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 663683: Hash(0x55224255e38b1141591990467b3bcc2eea10026000000000000000000000000)", + "P->V[49416:49448]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 667074: Hash(0xebe9a634307aeb6d676f9f2479a84ef67793af5b000000000000000000000000)", + "P->V[49448:49480]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 667750: Hash(0x8f60c4b79207df6a45b89d9b7e50ab5c7093a0e1000000000000000000000000)", + "P->V[49480:49512]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 690324: Hash(0x7f285fc757127fa629675e809313eb356eee7649000000000000000000000000)", + "P->V[49512:49544]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 743894: Hash(0xa8d0c465c25f2d6981368f8cb67da81cd855224f000000000000000000000000)", + "P->V[49544:49576]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 813763: Hash(0xc99c319945b0630db1102ee71b4e3a42f0c640c0000000000000000000000000)", + "P->V[49576:49608]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 865268: Hash(0x6fa31075581dec1f70e0dd1ad3ada366c416d37b000000000000000000000000)", + "P->V[49608:49640]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 921730: Hash(0x2ccffa40ab7f9e6a5d862a91bc35ca3d9a452b6a000000000000000000000000)", + "P->V[49640:49672]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 947288: Hash(0xa9b2c0018c24a7f187788409691aee30ae3d2d94000000000000000000000000)", + "P->V[49672:49704]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1031497: Hash(0x57f19a2c84609e6709925fed50ed289ecd3aa168000000000000000000000000)", + "P->V[49704:49736]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 266519: Hash(0xe1fa1af37c8832997e5841847339407f9520da9d000000000000000000000000)", + "P->V[49736:49768]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 296619: Hash(0x331a4fca370b111a06fa7c4deb3e8d8c6f21aa30000000000000000000000000)", + "P->V[49768:49800]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 319472: Hash(0x8db43d8bb0886034bd7c5c5341a145430c727c89000000000000000000000000)", + "P->V[49800:49832]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 326877: Hash(0x9f778ce15506be05c6600177f92bcbccad5ed099000000000000000000000000)", + "P->V[49832:49864]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 328109: Hash(0x682bc2c84a2e8e99b8744b5f074f46ef77ab347f000000000000000000000000)", + "P->V[49864:49896]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 331840: Hash(0x131374bf0e90c679b5641daf84f7dd31047237fe000000000000000000000000)", + "P->V[49896:49928]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 333536: Hash(0x38118f515936f42fccf7bae65cc397fb2f8a1725000000000000000000000000)", + "P->V[49928:49960]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 333874: Hash(0x7b57b033f18fd8b7a1758ddaf7b7f232389cdc12000000000000000000000000)", + "P->V[49960:49992]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 345163: Hash(0xd9ba3aac0696b7d3f06ef08059052483d55d277a000000000000000000000000)", + "P->V[49992:50024]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 371946: Hash(0x37536e0913105491cb35cfc341e857195f5b62ba000000000000000000000000)", + "P->V[50024:50056]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 406880: Hash(0x3e97b35e3222e9edf67c721f2d346a3b6be0c33c000000000000000000000000)", + "P->V[50056:50088]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 432635: Hash(0xa80a622d05bcb9d3556ccfa0658b2119953aed46000000000000000000000000)", + "P->V[50088:50120]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 460864: Hash(0x29ba7a3b513a6879f3e4e810632d3f5c715e390a000000000000000000000000)", + "P->V[50120:50152]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 473645: Hash(0xefee25dce211b304fb53865937ab327265a96fd0000000000000000000000000)", + "P->V[50152:50184]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 515749: Hash(0xbb325e95fd1932e1853b9277db472ef1e171bd72000000000000000000000000)", + "P->V[50184:50216]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 133258: Hash(0x98fa627b355d5d7f7633483744b613ecb20789ba000000000000000000000000)", + "P->V[50216:50248]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 148308: Hash(0x35ed0e7a7e5636cd8dde05ac1b1e60ecb4e39dc8000000000000000000000000)", + "P->V[50248:50280]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 159737: Hash(0x322727f9aca0c6f4e993cf786751c70e2847cb1c000000000000000000000000)", + "P->V[50280:50312]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 163439: Hash(0xb2a7557bbb44d73be494124c50b66dfd423b2b44000000000000000000000000)", + "P->V[50312:50344]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 164055: Hash(0x826b9ae82d75e5b936de9e2f31305e2a6de68dd9000000000000000000000000)", + "P->V[50344:50376]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 165921: Hash(0xe1e82e88ec0b24ffde100d1609958e2eab1f97e0000000000000000000000000)", + "P->V[50376:50408]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 166769: Hash(0x153f4f92d31f7299cdf94bccfc10942cae07e901000000000000000000000000)", + "P->V[50408:50440]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 166936: Hash(0x6ac25f312a2558a764aa023af3fe841a09b26bf2000000000000000000000000)", + "P->V[50440:50472]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 172580: Hash(0x989cc528122ba7032d92c8643b06dc901f0fe112000000000000000000000000)", + "P->V[50472:50504]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 185972: Hash(0xf30dd5269080fd2a0ccd2663f7172a64910e39b3000000000000000000000000)", + "P->V[50504:50536]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 203441: Hash(0x3ed001b071b0df71af592fa523855f69c051b9da000000000000000000000000)", + "P->V[50536:50568]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 216316: Hash(0x2622870cdca3a80ca1bedac727370f17fa88ee17000000000000000000000000)", + "P->V[50568:50600]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 230433: Hash(0x8af88e2c67f604af7827e67cceefae9d1437c7d000000000000000000000000)", + "P->V[50600:50632]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 236823: Hash(0xff6ea63882c6f04ee02bb1bfead5d96e1444004000000000000000000000000)", + "P->V[50632:50664]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 257875: Hash(0xa13c44cdb532f437b02535bf6c88a8417486cc86000000000000000000000000)", + "P->V[50664:50696]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 66628: Hash(0xba98a10dedad382b6f09239f8747fb925024643000000000000000000000000)", + "P->V[50696:50728]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 74155: Hash(0x384cd2e03ab08bd46a59eb9fe5f1d7e35ce9a614000000000000000000000000)", + "P->V[50728:50760]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 79869: Hash(0xe9746545e21dcd9fa50731637b07af3c647ee252000000000000000000000000)", + "P->V[50760:50792]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 81718: Hash(0x5c52c4d5ead2f91ccba623f83cc64a17d8b61d2a000000000000000000000000)", + "P->V[50792:50824]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 82026: Hash(0xcb03cd429811c952c9588dbe1e389fefc64794e3000000000000000000000000)", + "P->V[50824:50856]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 82961: Hash(0xccefec7c7c1d70850872d6446fc45be0bfee0175000000000000000000000000)", + "P->V[50856:50888]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 83385: Hash(0x6aa149fdfa86b2f62425c760334c0efb75b2ee6a000000000000000000000000)", + "P->V[50888:50920]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 83469: Hash(0xff1eddb1e0b8a026a4f9b5ddc70126928d6e189c000000000000000000000000)", + "P->V[50920:50952]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 86291: Hash(0x81010722f1fc152d3f865e41acd05b84c052162f000000000000000000000000)", + "P->V[50952:50984]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 92987: Hash(0x329fd600fc9709809cbee24360b908cadbaf497c000000000000000000000000)", + "P->V[50984:51016]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 101721: Hash(0xc62dc4c003cd3f1f259b669c1df371d46349604d000000000000000000000000)", + "P->V[51016:51048]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 108159: Hash(0x262593c3de539d474c927b2dd15a0e176c39773c000000000000000000000000)", + "P->V[51048:51080]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 115217: Hash(0xeae2bfb84cc111be9933f2b95d659a0e9c209712000000000000000000000000)", + "P->V[51080:51112]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 118410: Hash(0x74dab65c80a95664743cb1c4bdbdfda67fc5ed19000000000000000000000000)", + "P->V[51112:51144]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 128936: Hash(0x438c633de732e713a3b23230087d4446deb859e4000000000000000000000000)", + "P->V[51144:51176]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 33315: Hash(0xa09e817809f4cde3720a5a5a9110612457b629f000000000000000000000000)", + "P->V[51176:51208]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 37076: Hash(0xf8490f35e5c7da64e1c7caa7f3f5207f5a393f4d000000000000000000000000)", + "P->V[51208:51240]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 39935: Hash(0x1e803f550f83d3961bf2f78cfcd16b1c9be599d000000000000000000000000)", + "P->V[51240:51272]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 40858: Hash(0x5600bc0a02b233af105cdcd2eb6df789b3729da4000000000000000000000000)", + "P->V[51272:51304]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 41012: Hash(0x242bc269b1d6c596d6cc11c75f21304dd2bda1b0000000000000000000000000)", + "P->V[51304:51336]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 41481: Hash(0x5635ecad573516911c73d0c2b95ef16e604a13dd000000000000000000000000)", + "P->V[51336:51368]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 41693: Hash(0x112ca38ac1d6a0b2451087962aaf11f752f41e57000000000000000000000000)", + "P->V[51368:51400]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 41735: Hash(0x65315333c0cf3b84be4aab55ac96ca511f8b85b3000000000000000000000000)", + "P->V[51400:51432]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 43144: Hash(0xad4845361bcba85c7e148851aa4ea165e121ce5b000000000000000000000000)", + "P->V[51432:51464]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 46492: Hash(0x81654eeb91ef493edb000a1e14a99dd26af566f000000000000000000000000)", + "P->V[51464:51496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 50861: Hash(0xd79e46a582b972f59898ba5ac8d8e8cb9cf2ede5000000000000000000000000)", + "P->V[51496:51528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 54078: Hash(0x27c75923f90bbdc536a9e332ac38e7e6a78e2fc8000000000000000000000000)", + "P->V[51528:51560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 57609: Hash(0x811702622a7729f0976a5bbfb0271ca4d8a93ad3000000000000000000000000)", + "P->V[51560:51592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 59204: Hash(0x525f9e1fc318b6a209073794e1faaffc806216c9000000000000000000000000)", + "P->V[51592:51624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 64469: Hash(0xdb3028e28c2f4b069cf7b7ed7390e4ae495c1520000000000000000000000000)", + "P->V[51624:51656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 16656: Hash(0xa49524c17c1f14f1859df98208ef1944332ffbff000000000000000000000000)", + "P->V[51656:51688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 18539: Hash(0x87ba0f444623eca803e40e5caa94a43c465044d1000000000000000000000000)", + "P->V[51688:51720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 19966: Hash(0x73234c303d30c08da24cd44253ea4f6a559c0822000000000000000000000000)", + "P->V[51720:51752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 20428: Hash(0xdd9a25caee5c1dfeab4b7cae04464d8abbeff082000000000000000000000000)", + "P->V[51752:51784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 20507: Hash(0xb723a48684e22bf8174b5211ff556d39c4f657b9000000000000000000000000)", + "P->V[51784:51816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 20741: Hash(0x367bb285044a616d8d56a0fc4ccec558f243b03c000000000000000000000000)", + "P->V[51816:51848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 20847: Hash(0x2ee899b3bd317f5fe4b875c983f24a6804a582a6000000000000000000000000)", + "P->V[51848:51880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 20866: Hash(0x1e2ca38c3f44c7046aeecadeea451bf42067ed37000000000000000000000000)", + "P->V[51880:51912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 21573: Hash(0xcf60596a39ff8e09a9f043858f727d8b7cf96e08000000000000000000000000)", + "P->V[51912:51944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 23247: Hash(0x43856dc447454d038c05a8ccf9853f5e9d24288a000000000000000000000000)", + "P->V[51944:51976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 25431: Hash(0x11634da381c4c0d5b4d773acdf863b7a50484ff7000000000000000000000000)", + "P->V[51976:52008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 27038: Hash(0x8b38f1f75b5fd4a8fcdaa2dbad8d2ff97ecb797d000000000000000000000000)", + "P->V[52008:52040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 28805: Hash(0x14e8802db136821729b0557ba763d2553def984a000000000000000000000000)", + "P->V[52040:52072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 29603: Hash(0xf889d0f4b3c834ecae0c400b728df07fd3e526df000000000000000000000000)", + "P->V[52072:52104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 32235: Hash(0x3ca44f64955d3bd602d22ba49f14dad28890ae2e000000000000000000000000)", + "P->V[52104:52136]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 8329: Hash(0xe7adc8808f49593de2eb51402cea9283ef20b041000000000000000000000000)", + "P->V[52136:52168]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 9268: Hash(0x42dc49afa27d584701a85affe16df01e8d7e746f000000000000000000000000)", + "P->V[52168:52200]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 9982: Hash(0x20e10c4fecb3a920aeb8812760192d1510bfcaba000000000000000000000000)", + "P->V[52200:52232]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10215: Hash(0xaef34fddec94ba0aa363060153627221597dc92b000000000000000000000000)", + "P->V[52232:52264]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10252: Hash(0x18965eb460880c6365192b09760c539c6094b89f000000000000000000000000)", + "P->V[52264:52296]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10371: Hash(0x4bea635c476d9c309a1d9f561af9f260566366d000000000000000000000000)", + "P->V[52296:52328]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10422: Hash(0xac26c2f0ad4c29f6ac62bf715b30ee6888ce77a5000000000000000000000000)", + "P->V[52328:52360]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10432: Hash(0x18b51c247b2adae48f94b5d85870764bd507cf68000000000000000000000000)", + "P->V[52360:52392]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10787: Hash(0xa27cac46fd525e5f6c60065cb58f95029b80e3e2000000000000000000000000)", + "P->V[52392:52424]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 11622: Hash(0x682d298eee08b05300cdc44bd89144cbc43a9f37000000000000000000000000)", + "P->V[52424:52456]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 12714: Hash(0x14158f553942dbb69e94eddff30aee1c2ed9a9fb000000000000000000000000)", + "P->V[52456:52488]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 13518: Hash(0x2acc0fa186d28ba89c38609ac248ac05d6b50097000000000000000000000000)", + "P->V[52488:52520]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 14403: Hash(0x4f00e1b43dc3531bc9a7968414b43339f3f4a443000000000000000000000000)", + "P->V[52520:52552]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 14800: Hash(0xcdae6a73660a37ddd28762886091832d93b7df89000000000000000000000000)", + "P->V[52552:52584]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 16116: Hash(0x7c20c8ee14f1bbc53ec7bce8c60e983b558f4e6d000000000000000000000000)", + "P->V[52584:52616]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 4165: Hash(0xf6985820b7d2417bcaaee94da737f5d199e4e0be000000000000000000000000)", + "P->V[52616:52648]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 4635: Hash(0x3892f30a7afdd1c25d79cf3e6fa1d4bcaf142635000000000000000000000000)", + "P->V[52648:52680]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 4990: Hash(0xad9818566760f870c46ced3cb3f29661ebf63d74000000000000000000000000)", + "P->V[52680:52712]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5106: Hash(0x3f13f6c85ffd92f3d9ca0882d5eef04c05f36d1000000000000000000000000)", + "P->V[52712:52744]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5127: Hash(0x13a046e9a0864757736c8173e16d6dd4a982372b000000000000000000000000)", + "P->V[52744:52776]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5184: Hash(0x544d9439be9a8edd1ae87f8d36115102515b8b0f000000000000000000000000)", + "P->V[52776:52808]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5210: Hash(0x23c88edab889826b9a553d8490defb171b825faf000000000000000000000000)", + "P->V[52808:52840]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5217: Hash(0xc0eb568af3dd819007effa0c933c669da8bc0493000000000000000000000000)", + "P->V[52840:52872]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5392: Hash(0x10812be2ea05935b8c0f9373dae9f9fede8d05c4000000000000000000000000)", + "P->V[52872:52904]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 5810: Hash(0xfcb9e231465c85aea30a28136efad29956c5b467000000000000000000000000)", + "P->V[52904:52936]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 6356: Hash(0x465fdb0e1bbcd954c00d2c0bc018d3e538312aa7000000000000000000000000)", + "P->V[52936:52968]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 6758: Hash(0xc66adf2248967b7f5279face10a571ad487782ab000000000000000000000000)", + "P->V[52968:53000]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 7200: Hash(0xa3718c58ff6dd52f59bc75838bec1bd8cee335f6000000000000000000000000)", + "P->V[53000:53032]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 7401: Hash(0x7b2fb49187be43fa3a499c25d589c4d9fe7ec97a000000000000000000000000)", + "P->V[53032:53064]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 8059: Hash(0x9041d0a80b5107ac41fb8e74ad3001e864b41644000000000000000000000000)", + "P->V[53064:53096]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2083: Hash(0x771a6262c361ed68669de0534f449cb15dd8ccc1000000000000000000000000)", + "P->V[53096:53128]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2316: Hash(0x8fed236543742f021def62ab16269ed54e1ff32e000000000000000000000000)", + "P->V[53128:53160]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2494: Hash(0xe450ca05d2833cffc7ad0a71b6ee6b9ae4636f91000000000000000000000000)", + "P->V[53160:53192]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2552: Hash(0x9ab1a36a040b50ecbb9087f8323ceced1574f913000000000000000000000000)", + "P->V[53192:53224]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2562: Hash(0xe86600f43247c39ce3b82b40af29eaa6148367ff000000000000000000000000)", + "P->V[53224:53256]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2593: Hash(0x40e8027c4805ae4a2d9a3fab4ad88ba0ec110fd5000000000000000000000000)", + "P->V[53256:53288]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2604: Hash(0xd284a4a479faf953165e89d9edbe902fbfed2149000000000000000000000000)", + "P->V[53288:53320]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2609: Hash(0xca3f1289732c5a9fee341d6336c0b58c93384692000000000000000000000000)", + "P->V[53320:53352]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2697: Hash(0x5c4f877a58ff1b097a8406591639b27cfdbfa627000000000000000000000000)", + "P->V[53352:53384]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2904: Hash(0xe326485ef5fbcbc9402ed7822b42ccee8b499f59000000000000000000000000)", + "P->V[53384:53416]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 3179: Hash(0x683fe7e1a6fd9c6b63fe74cd865129d823be5a84000000000000000000000000)", + "P->V[53416:53448]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 3378: Hash(0xc2e5e5019bfadbe4baded9b162768e2f83452e61000000000000000000000000)", + "P->V[53448:53480]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 3601: Hash(0x4a94a1a29dd9f76267286cd19a02b647be7e4d63000000000000000000000000)", + "P->V[53480:53512]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 3701: Hash(0x6476f56c61d5b833a2fa76a76d7ab0001755a2d2000000000000000000000000)", + "P->V[53512:53544]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 4028: Hash(0x7994f493f36009faea6f012adbc5b99b64e08a04000000000000000000000000)", + "P->V[53544:53576]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1040: Hash(0x5f234add537e78176c925e3b0e63c336c538b251000000000000000000000000)", + "P->V[53576:53608]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1159: Hash(0xa049e6c54aa422246c07f732c97aa2c85ab8851a000000000000000000000000)", + "P->V[53608:53640]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1246: Hash(0x1f8a256b1c49a41fc25fe1d1072bb44f8827a766000000000000000000000000)", + "P->V[53640:53672]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1277: Hash(0xf8a9d8d15df1c22184e54ef5c2e113e63d2065a7000000000000000000000000)", + "P->V[53672:53704]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1280: Hash(0x9fdc0eb602224389d944c02544f24bec4c2ec369000000000000000000000000)", + "P->V[53704:53736]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1297: Hash(0xd9c8198224dda591a18e2e9b535466a23644716a000000000000000000000000)", + "P->V[53736:53768]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1303: Hash(0x9e7f9ece6f6dee6aa2f3346f41581fa2bac21860000000000000000000000000)", + "P->V[53768:53800]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1305: Hash(0xc6dac935b16267ff989819169aa894b9752aa24a000000000000000000000000)", + "P->V[53800:53832]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1349: Hash(0x8d0cda46e1abebfed441283815f7e30237e20a76000000000000000000000000)", + "P->V[53832:53864]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1453: Hash(0x8722a05a3e28b5eaf62143f45f8e0a0a32f1b729000000000000000000000000)", + "P->V[53864:53896]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1588: Hash(0x974990d7f9d1061a7c09da244723dc769706043e000000000000000000000000)", + "P->V[53896:53928]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1688: Hash(0xc579322f2980da8c46a9a7fac2720a8e21f2c08b000000000000000000000000)", + "P->V[53928:53960]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1801: Hash(0x670266086f8164357107218e720e5e535d30941a000000000000000000000000)", + "P->V[53960:53992]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1851: Hash(0x53142c3f70a7700862a5114ae1354182b060d93e000000000000000000000000)", + "P->V[53992:54024]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 2015: Hash(0xc6280ed7c5d97b774b932e3f60ab3bb16e035d87000000000000000000000000)", + "P->V[54024:54056]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 521: Hash(0x4d8e0d81d1ffd40a1dbc4e0a59aa857d04030084000000000000000000000000)", + "P->V[54056:54088]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 578: Hash(0xd65f6b3a0e5267bf18674238a3a1357e2faa1a9000000000000000000000000)", + "P->V[54088:54120]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 622: Hash(0x45442f1b62da0ec452216d45129a8bef2acd52df000000000000000000000000)", + "P->V[54120:54152]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 639: Hash(0x579ea5485d514adf23e51afa6b64cb72d3edf5b9000000000000000000000000)", + "P->V[54152:54184]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 641: Hash(0x14211d6ecd09fa545e2e13ffd3301656b04172ec000000000000000000000000)", + "P->V[54184:54216]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 649: Hash(0xaaf1b526bbcfd82decbb818a1ff275318d4c3fdc000000000000000000000000)", + "P->V[54216:54248]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 650: Hash(0x6cdbcdb9e904d5b60d474e58efab7616b8275578000000000000000000000000)", + "P->V[54248:54280]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 653: Hash(0x54413078c179102153826e9a4821bc6c1ec01ca4000000000000000000000000)", + "P->V[54280:54312]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 675: Hash(0x88371602e5a98eeea070843c05e96ce7743e98c7000000000000000000000000)", + "P->V[54312:54344]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 727: Hash(0xc44817fd7606e820dd3bfa9ee1bacd85eaaa6514000000000000000000000000)", + "P->V[54344:54376]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 795: Hash(0xd00b6d04760d341d69eddae8674c61b7bc1c950e000000000000000000000000)", + "P->V[54376:54408]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 845: Hash(0xcb49ba8e64dae655e4b2f98935dc1b95113d6b8000000000000000000000000)", + "P->V[54408:54440]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 901: Hash(0x5383176cea11e75d105de675578b20d81752f3f4000000000000000000000000)", + "P->V[54440:54472]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 924: Hash(0xea7c39b69e485ed24154961189b2a864a123c677000000000000000000000000)", + "P->V[54472:54504]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 1006: Hash(0xe33381b70564b9d5b4a47e62bd6fbada83447e04000000000000000000000000)", + "P->V[54504:54536]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 261: Hash(0xe93cc6e55fe6ad7ea2c6c807c5fcf578cdf1dc42000000000000000000000000)", + "P->V[54536:54568]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 288: Hash(0x5ab3adb5a3e6bb2d03dd9a8173545ece66f418eb000000000000000000000000)", + "P->V[54568:54600]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 310: Hash(0x18e631a9bdc79f6b4070f342429290e1ca1e25b6000000000000000000000000)", + "P->V[54600:54632]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 318: Hash(0x56b1f3b1b6c0915ca54563cb58f3e574d7862666000000000000000000000000)", + "P->V[54632:54664]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 321: Hash(0x9140f21435017e0f9327373ef7b7499cbfd5d6da000000000000000000000000)", + "P->V[54664:54696]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 327: Hash(0x49a5606d0dc1f4a39491d7bd05ae94eaf4caa07000000000000000000000000)", + "P->V[54696:54728]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 336: Hash(0x5fde61aa782dc4d361d62d37c51ba8d008abf324000000000000000000000000)", + "P->V[54728:54760]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 362: Hash(0xaef534502fd809279b1157a52715e99e1defc786000000000000000000000000)", + "P->V[54760:54792]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 396: Hash(0x87770a2e03da38438e1e68166952bc86a6d56a04000000000000000000000000)", + "P->V[54792:54824]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 423: Hash(0x766f937c04d4a535d6feca9efc78f58fe05b93f0000000000000000000000000)", + "P->V[54824:54856]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 451: Hash(0x8443a0ccc038ebc307bf95ed3cc1d8b47fb0b8d000000000000000000000000)", + "P->V[54856:54888]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 463: Hash(0xbf14930cf148fba5cd3b2a15532054c4483ed0a0000000000000000000000000)", + "P->V[54888:54920]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 502: Hash(0x2b3083b1105904a5ea24e929872795dfd42e70c0000000000000000000000000)", + "P->V[54920:54952]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 131: Hash(0xa8f25fb0a3b7927506519e531bb1656d3365cbb4000000000000000000000000)", + "P->V[54952:54984]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 145: Hash(0x2f6f0a8054d58103485bc8e710eee6fade03da3e000000000000000000000000)", + "P->V[54984:55016]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 154: Hash(0x63b89ee077c2ee47f6e388afea04fbc3836eec05000000000000000000000000)", + "P->V[55016:55048]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 158: Hash(0xe036ee6729f15e036464ffdd972d80ea4ff2bc6f000000000000000000000000)", + "P->V[55048:55080]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 161: Hash(0xf07f88b7a076d6b5e0fce04cd9e53c14a315c282000000000000000000000000)", + "P->V[55080:55112]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 169: Hash(0x7356ac1054e25e916da1012f427cfd3d5614fb42000000000000000000000000)", + "P->V[55112:55144]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 180: Hash(0xeca72063f90477976bc58c9f6cd0bb9c1be70f50000000000000000000000000)", + "P->V[55144:55176]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 199: Hash(0xe4b19291a6e9d50a305714333e95f20376a0a05e000000000000000000000000)", + "P->V[55176:55208]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 210: Hash(0xd9277d08c9fd9281d458a778b617a91997bc12ca000000000000000000000000)", + "P->V[55208:55240]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 224: Hash(0xba34bcfeda57a255d1b8b144b0427e82a9623ee1000000000000000000000000)", + "P->V[55240:55272]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 230: Hash(0xb7628b86c0df3dd957bfde1bcecd2a1725b410cf000000000000000000000000)", + "P->V[55272:55304]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 250: Hash(0x9a3578cdcea9565af09aa893abaee0560bc8974d000000000000000000000000)", + "P->V[55304:55336]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 64: Hash(0x8bf321e2e5a982bbe01ceab404631d12908ca412000000000000000000000000)", + "P->V[55336:55368]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 73: Hash(0xfdbf253e59624d8d5f9face2459cd09e636059f4000000000000000000000000)", + "P->V[55368:55400]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 76: Hash(0x4ee34a14a985bf8ede4667e89bb580c913482c3d000000000000000000000000)", + "P->V[55400:55432]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 78: Hash(0xd0ff0573e6b2ee33219a38b7fe25801bc6171f36000000000000000000000000)", + "P->V[55432:55464]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 85: Hash(0x940f34d675f6c563716eb4b2cc5f010080d62bce000000000000000000000000)", + "P->V[55464:55496]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 91: Hash(0x6cc5162280518ee02db19f97adfbdf6c71de48c3000000000000000000000000)", + "P->V[55496:55528]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 98: Hash(0x4f7d86d9298344343e6e544a59785dc6256376d0000000000000000000000000)", + "P->V[55528:55560]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 104: Hash(0x447d94a61e5400bf5bd48e50ad322aedb052c856000000000000000000000000)", + "P->V[55560:55592]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 113: Hash(0x10c07933ea904ff89722b028a54fc7a8fd762fe4000000000000000000000000)", + "P->V[55592:55624]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 114: Hash(0xc95227214183546fd00d8823a7fc5fdd60f381b2000000000000000000000000)", + "P->V[55624:55656]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 124: Hash(0x86d4419474c6024e7d8f3168a115be64a0205c41000000000000000000000000)", + "P->V[55656:55688]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 33: Hash(0xff3abd02d76253eb9635b0c05cb4dc89e72611b0000000000000000000000000)", + "P->V[55688:55720]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 37: Hash(0xa0196f578cd390446b7989b6f7b1da064cd356a3000000000000000000000000)", + "P->V[55720:55752]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 41: Hash(0x3f6e4b88e6a1ec9e99244a400e2c1c39b21fd90d000000000000000000000000)", + "P->V[55752:55784]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 43: Hash(0xed2dee027f02670d69bf85a84356d9e090a93535000000000000000000000000)", + "P->V[55784:55816]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 44: Hash(0x7895f5ca5f46a60bd6d48a6b448279f4593be668000000000000000000000000)", + "P->V[55816:55848]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 48: Hash(0x3c0c09d6e0a8056a186c68b68f76345d16788989000000000000000000000000)", + "P->V[55848:55880]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 53: Hash(0x49e51010b0cd59e295376e5f0737d7295b984bbc000000000000000000000000)", + "P->V[55880:55912]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 63: Hash(0x900921938837f611190f819f49be016275453928000000000000000000000000)", + "P->V[55912:55944]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 17: Hash(0x600890e9fecd98d4cc44ca5d449beed9412aecdd000000000000000000000000)", + "P->V[55944:55976]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 23: Hash(0x3303aff57be2e7de016aab7b7d806eec1eb232b8000000000000000000000000)", + "P->V[55976:56008]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 25: Hash(0x5f52c013a1fd7d946da1a2631e9278d9f9a90822000000000000000000000000)", + "P->V[56008:56040]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 27: Hash(0x6823b6614b3524afb09b1c585b1ad1bd8fd7ebfb000000000000000000000000)", + "P->V[56040:56072]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 29: Hash(0x8abe21f86c53fca2f5a786c809c81a61edec7e8000000000000000000000000)", + "P->V[56072:56104]: /cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 30: Hash(0x60c520575d498c73f2a5bc186a8dabef697628a7000000000000000000000000)", + "P->V[56104:56136]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 17499, Column 0: Field Element(0x5b92f5ff3e0fd429a4ec6543803ba2abbc26967d846d64b999d47db64706f6c)", + "P->V[56136:56168]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 17499, Column 2: Field Element(0x5d159ad6cd2c0f29845b37e5699c2043088eed93a531ca6386d62f7fc232a41)", + "P->V[56168:56200]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 17499, Column 3: Field Element(0x42e84506b6ac5a3e7a4c12453f0e4f31506a41a07029734f259bce9aebe5a91)", + "P->V[56200:56232]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 17499, Column 4: Field Element(0x21f648463f27055ec238e3fff651833a6e15b80de5bcc478238bc1f41f39217)", + "P->V[56232:56264]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 17499, Column 5: Field Element(0x483e6080f96535a3011b1748df5cabd91701e6fe0483d20b93fd88c2d22d07d)", + "P->V[56264:56296]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 17499, Column 6: Field Element(0x363956d5dff5711e7fc89c3657a98fac6adf6603d48cc3cce5594a39b992055)", + "P->V[56296:56328]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 17499, Column 7: Field Element(0x4027da92923085a8c874bf71855ff3bccabdb166811d4f785f9e3d455977faa)", + "P->V[56328:56360]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 137897, Column 1: Field Element(0x3db0047f188dcb68df7eb6d8f14805db998389ef2e518ffad9cdc438aedc58c)", + "P->V[56360:56392]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 137897, Column 2: Field Element(0x2469b4722c3f9525c43830502c359866bf05fc4d6ac52e7a564ccb8a76b058f)", + "P->V[56392:56424]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 137897, Column 3: Field Element(0xe34afafa7f2de576db5f20df19b61de0fbef20d3419edc40340c71d90f8682)", + "P->V[56424:56456]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 137897, Column 4: Field Element(0x6900aa260c8c60b005e1a9119487e36a3becb829ce9beada4c01cb95005c840)", + "P->V[56456:56488]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 137897, Column 5: Field Element(0x476afa4015d36774a80b014a99ce0c8c98b830f859af1ca643ebc149cec347f)", + "P->V[56488:56520]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 137897, Column 6: Field Element(0x522450b0fb7246557790beb475f1d7b756946826890dae161f643c7c653f431)", + "P->V[56520:56552]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 137897, Column 7: Field Element(0x375f6d9e7b8861cad804bc5ee6dcd996d50cf3d45cc20725c81ffc3b0c35671)", + "P->V[56552:56584]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 229317, Column 0: Field Element(0x3a683a1324d968469597eb1bc65f1d97f1f94281032a4a06facb6c52c907e93)", + "P->V[56584:56616]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 229317, Column 2: Field Element(0x2ff1d2091037011b0a89a54c38a6a6783e6ca76de9fd6df6a9449d58c3418f1)", + "P->V[56616:56648]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 229317, Column 3: Field Element(0x5ab9340f9f0bafcca77d970ebc3f950dc6191cc75f717e3130748dca960a7a7)", + "P->V[56648:56680]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 229317, Column 4: Field Element(0x3e5979c5d41fb845330f3d556f044be81e8998234c7f1f1d962cad38164d2d1)", + "P->V[56680:56712]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 229317, Column 5: Field Element(0x3196bdbeed5497cbe6641c1368561f44dbc5e09ded73ee0ab81159f19e8a5cb)", + "P->V[56712:56744]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 229317, Column 6: Field Element(0x64df46bbfc7d2107b1101d8d4e6abdc585735e2ef23217d66a59f72bd5e8332)", + "P->V[56744:56776]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 229317, Column 7: Field Element(0x59b8569b4f44625e04a137ec75a5a73bd3500bec48ba452337cea7559682a30)", + "P->V[56776:56808]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 258929, Column 0: Field Element(0x659c86310fea02d5af8101ff8af20f677a24b209389b7c8f2e0de6d6f8a0b60)", + "P->V[56808:56840]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 258929, Column 1: Field Element(0x75220e9ab07e7aca3d95096ff857c183e213cd9d9cf0ec9985115f8cfc46196)", + "P->V[56840:56872]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 258929, Column 2: Field Element(0x35186a50e724d5be8a7b9bae22badc74478422f7138bdccef4f23ef19aa92f6)", + "P->V[56872:56904]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 258929, Column 3: Field Element(0x38dae3db4ce1bfb5da1ea272052b7d7b8f93d509c3a3ea09d12e2aded3c7a79)", + "P->V[56904:56936]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 258929, Column 4: Field Element(0x33d52a8bdbf92c4e9ea7a2aefb201b4460e941ceada34c136c536651b298c03)", + "P->V[56936:56968]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 258929, Column 5: Field Element(0x42845c86f9c9e126e0a07ec81f55520a8f2080181ada53f2b784f4a72d4912e)", + "P->V[56968:57000]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 258929, Column 6: Field Element(0x2a062dec204e20ea87862635f9ea16086e6d3f60ad3e67561d943398b2f5b1f)", + "P->V[57000:57032]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 263859, Column 0: Field Element(0x608a0ed649f2b25ff653fc665d44892260fd47658431a9808e6c3e7bf753437)", + "P->V[57032:57064]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 263859, Column 1: Field Element(0x2d0c04b1b057af5d0ee385fba20816d98362ae11efc85e2bd73bb8e61d4b059)", + "P->V[57064:57096]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 263859, Column 3: Field Element(0x434bb99e2f4193894aa59723e6023c3d11443437413edc46404501b8b083f1c)", + "P->V[57096:57128]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 263859, Column 4: Field Element(0x72d41e61179f71849f6cd74780049f654c7bac7115587a216595291a1942ebd)", + "P->V[57128:57160]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 263859, Column 5: Field Element(0x35f42306b1a4f9eb2333c5987e2ca12328ea8de936194415bd0966fc40f0b1a)", + "P->V[57160:57192]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 263859, Column 6: Field Element(0x5bf4cd967d9db9274a51042ebb7be2d777e6740a2606d74579f33136199528a)", + "P->V[57192:57224]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 263859, Column 7: Field Element(0x283a7922ad5e9ec99d59c361f9cc33dc3b7ed9c052d07fed0271eb747f7c869)", + "P->V[57224:57256]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 278788, Column 1: Field Element(0x3993ad84b28c1bb05f7690276fe7cda759fe314fdbf6be3411ddd79adf2e270)", + "P->V[57256:57288]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 278788, Column 2: Field Element(0x6919e5b503530e5bd685377c2ba6dbc29e5fa2baa6aa0bd9d0050c094f8b49d)", + "P->V[57288:57320]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 278788, Column 3: Field Element(0x70d9280fd967f64c38e0de005a1b4019f17cc5f57ad7a19b0d49568fbd642d5)", + "P->V[57320:57352]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 278788, Column 4: Field Element(0x8e7b656561f895615622bd4969bd8d0badfbe047377a8cf9cdd1c8ace46a52)", + "P->V[57352:57384]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 278788, Column 5: Field Element(0x626dd73cb86c20d952ef8c05b30354fe96ef361bbcc99a18d1996b92c1ad32)", + "P->V[57384:57416]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 278788, Column 6: Field Element(0x41a66c5c69cbec1ee6eae238ce96cdca2e1dffecd39c76c4b8311031fa37a56)", + "P->V[57416:57448]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 278788, Column 7: Field Element(0x73501d4812722870d14ea077efc6c307a093047f8fe2bf101f061bf2f418a43)", + "P->V[57448:57480]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 285574, Column 0: Field Element(0x29c0745f6569224b77bb7a77a69e3153c67a56279a23ee5facac67e7ce3fbd4)", + "P->V[57480:57512]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 285574, Column 1: Field Element(0x7a3a70da6a9e53df1564ca17a67f00a4bc7c29eb0ab1eadd8d99efc4addb1ca)", + "P->V[57512:57544]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 285574, Column 2: Field Element(0x5bf3b7e8556e471202fd88c8b1656fea47807908522ce47d1c6a42d6adf5b04)", + "P->V[57544:57576]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 285574, Column 3: Field Element(0xb0eac8947383f1125e0e54f5d198afa88a83451c7297e422c894085bcafa57)", + "P->V[57576:57608]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 285574, Column 5: Field Element(0x2ade6cc89e446e637f4aaa05ca9204149d810c2b05eb5a47502bfc21f0c5b2c)", + "P->V[57608:57640]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 285574, Column 6: Field Element(0x7cb10188e96632892f7bc4bc8d71d59edc2ed54f747771438524d26979235f0)", + "P->V[57640:57672]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 285574, Column 7: Field Element(0x4d5ccf0d3daca5734de015d87ec621cefbcb61e3f788e860a24897c337cdd)", + "P->V[57672:57704]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 286926, Column 0: Field Element(0x3116677d8e6e57bf245c4344daffbc8b976632379e372029d2ef82ce03dc82c)", + "P->V[57704:57736]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 286926, Column 1: Field Element(0x5f0f2c620e444925e28b2f0cdfe7cab62ae3926d61cc689b13ab85a8e396fd4)", + "P->V[57736:57768]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 286926, Column 2: Field Element(0x603712a64d2dddc5cb372441f8faf0632f6eae398663c9345d2521d431e103a)", + "P->V[57768:57800]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 286926, Column 3: Field Element(0x17315ce4550eb4aeb06bdc4852174beedc6a148804517fcfe65ca5a43b3798c)", + "P->V[57800:57832]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 286926, Column 4: Field Element(0x1df6139173ccc456f90a0cbf0a6270664bd58000404e0139c0e95780a74306f)", + "P->V[57832:57864]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 286926, Column 5: Field Element(0x33eccf05f6ba4bf04a19e48141522ca7d4a2a5dd8f0b00d2a15e72db5c95190)", + "P->V[57864:57896]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 286926, Column 7: Field Element(0x17ec08da1f8eeded3a46efd46ddf6930754728a0c5dbf44ef294e2bbe4de93d)", + "P->V[57896:57928]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 332074, Column 0: Field Element(0xcb4c26b7e1290864eb378e1617b78d785cc87fd5182c9ec2baa8e47ae811cb)", + "P->V[57928:57960]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 332074, Column 1: Field Element(0x1cce1ebeb4a23f408d7005ea13d4fa4e9870c3675acdf669fde6c6f6ad94ce0)", + "P->V[57960:57992]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 332074, Column 2: Field Element(0x54fe6dd8b41d8101a4fa9a75e24ef9d7efeb79ee195b40c3942aec1f39665fe)", + "P->V[57992:58024]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 332074, Column 3: Field Element(0x6febe81414894be50e32c529fac9df5a70df341e596ec66a6802eb7d56fee3c)", + "P->V[58024:58056]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 332074, Column 4: Field Element(0x305438ca68d163a831586fab4e391ef3f693d3cdd22a8e813df20ac2b9f958e)", + "P->V[58056:58088]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 332074, Column 5: Field Element(0x15c69eccb6c50a7daf23d006c0166b7274f822361bf4f6f3b4669233ccb9703)", + "P->V[58088:58120]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 332074, Column 7: Field Element(0x161440186f9de64213d82fc6140e8519c75b781370b8a0cdd4b1f01570c6c01)", + "P->V[58120:58152]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 439215, Column 0: Field Element(0x7149af0ce2264259ad9e0f2bcdd85f335bc55a6cdce78f81708c86937cddf94)", + "P->V[58152:58184]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 439215, Column 1: Field Element(0x772af644e923c02debbcdbcfd5a135dd7041cdd02bffc3d7be8854ea31f4ef)", + "P->V[58184:58216]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 439215, Column 3: Field Element(0x14f84206095614a05f2b26057887735daa0b1132a23b9a09ded80ccce0addfa)", + "P->V[58216:58248]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 439215, Column 4: Field Element(0x505ba8318aba5b739fc0d232169c66fe9649abcdc218ff6c8f96cbe78332269)", + "P->V[58248:58280]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 439215, Column 5: Field Element(0x3d3d58a07b05593a899d76d4cd7f3830a48a3b59f49aa565596bf0c3d7ed3a2)", + "P->V[58280:58312]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 439215, Column 6: Field Element(0x3f0b0d665ba05368065895824c3667bec449563a680b8c5d2f713f6cf97563e)", + "P->V[58312:58344]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 439215, Column 7: Field Element(0x46fb07941b90e157d65e5b2ddfc5b596ae1f26cfd8d9b2241cccf069e139ed2)", + "P->V[58344:58376]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 578949, Column 0: Field Element(0xc3857feb1f03b404a13ec8eba1412a6549207edfdeb4fa1d9f8314471fbc2a)", + "P->V[58376:58408]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 578949, Column 2: Field Element(0x7843e46a9efcf91fc11544949d5a774deb89c4924fea46e1026a96eddfe68d6)", + "P->V[58408:58440]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 578949, Column 3: Field Element(0x67ab2489a82f31a85d2d9dd9a8296cb5075c01b0a2e19311cb4aecff398c171)", + "P->V[58440:58472]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 578949, Column 4: Field Element(0x5b3f71eb73dd2d2e02bbcbfb18a5d8619d8d4b0dd43bac00e130c843c98a1c5)", + "P->V[58472:58504]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 578949, Column 5: Field Element(0x1417a5139d7bf94b2021d287818e91621c104b3f5968328da93859df6f7c914)", + "P->V[58504:58536]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 578949, Column 6: Field Element(0x4d95cf11654648539f71b829029789abc829369c1631e7ad47744f9a220f6db)", + "P->V[58536:58568]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 578949, Column 7: Field Element(0x2f9a790b284d6437cc7bcf733ff0cd2bbb785f1eac9a0f1ec6c4fff2ba9cd70)", + "P->V[58568:58600]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 681963, Column 0: Field Element(0x6b241735c7475cba4b4569501a5feb41d44e946d5de7439e4cd64ee7e6c1e4d)", + "P->V[58600:58632]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 681963, Column 2: Field Element(0x71dee3faf323578437d7f8b49e503449935bc29f3b7c938f1654cfdae78a821)", + "P->V[58632:58664]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 681963, Column 3: Field Element(0x15e9809f4a9de21d1accceba77852198101edbcfeb33aaefca2cd54d1a2e51e)", + "P->V[58664:58696]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 681963, Column 4: Field Element(0x690778a64cd90dd83c384b65c4b2db116eb24b928829b72198ba815355349f8)", + "P->V[58696:58728]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 681963, Column 5: Field Element(0x150a05b0bef833fb67c4540796dccb25bc8ced23025ee706022bfded8d39897)", + "P->V[58728:58760]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 681963, Column 6: Field Element(0x3615d4ab427f576b29bdd72a720c3bfa97c4885a2c0cbf156d1aaeb13057d6c)", + "P->V[58760:58792]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 681963, Column 7: Field Element(0x104d4fb792a01581cc119f7a6f3793ae400c7ce8f2378fa4346775021bb25a5)", + "P->V[58792:58824]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 794886, Column 0: Field Element(0x73b9968c58a0046319c9503259850a6ab15d459d1a3ee1a7da24886b7413d60)", + "P->V[58824:58856]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 794886, Column 1: Field Element(0x67472a53c660c0fe26c67f0931fef0a686f9dd6e43974085daf356c0f27b72c)", + "P->V[58856:58888]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 794886, Column 2: Field Element(0x55d4c6d4b5c43bfbd53b6dca4d811c240a92fc9fd90fc1ae81359a945c529c7)", + "P->V[58888:58920]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 794886, Column 3: Field Element(0x159dfd229ad45262b1191b3400cf84648ac568e5e0bdfa52dc71fd6c21478c5)", + "P->V[58920:58952]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 794886, Column 4: Field Element(0x6418b87b64f2005b2d1ae96ab69e6ef318dcc6dd7095779138f5cbef6588869)", + "P->V[58952:58984]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 794886, Column 5: Field Element(0x1f574f9a7a0d974ddf7d2aaa7ea205cc6d5ea57c9469460f7dd446ec74d7538)", + "P->V[58984:59016]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 794886, Column 7: Field Element(0x93f8869a1457f645135b7a0fbb9cc2d5dc5fec07f2dd25c2202736f47c3325)", + "P->V[59016:59048]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 846003, Column 0: Field Element(0x7646246debde68f3c35458b9e969f7ae178f6774bf8d6d10195a84414ce3e2)", + "P->V[59048:59080]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 846003, Column 1: Field Element(0x4d66bcdf73bbbc127d166b052a7d1e67d9296fcbb2888a3de137efc3fa36f35)", + "P->V[59080:59112]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 846003, Column 2: Field Element(0x493c46242bdaab8b2a8f52a0ac5fdbe2f94816acdc1002a08816074bf8398f6)", + "P->V[59112:59144]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 846003, Column 3: Field Element(0x67ad86f8da29f92136c67e206471233ca8012c6c02fdf8872a28ac6f1b0efc3)", + "P->V[59144:59176]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 846003, Column 4: Field Element(0x3cd7d3bb2542e033db8203137fccc5e0f6bf69b0f4ceed8c85c6b0f08c58cce)", + "P->V[59176:59208]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 846003, Column 5: Field Element(0x19f43fb8723ea22f7f141860488a373c4951dba4c262c030e43c19ec8045ae5)", + "P->V[59208:59240]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 846003, Column 6: Field Element(0x7befc2daaa9194f0f5e8134efce3120666e33dc2491469cf326da422acd3c29)", + "P->V[59240:59272]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 1014416, Column 0: Field Element(0x64293f6950610a1b6090b69b3760f3898eb87d7d3dd2cb29284aea7e35f8ac0)", + "P->V[59272:59304]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 1014416, Column 1: Field Element(0x1bfc53189ae630ceac951764d3806e02f8e8cfe4dcd04563f8f0b55dd9f20c)", + "P->V[59304:59336]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 1014416, Column 3: Field Element(0x5dca8ae982d174f5a20953bdbacb5ed0e8423f30e537fc874803a14452167ee)", + "P->V[59336:59368]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 1014416, Column 4: Field Element(0x143a5efff41c4c94fd4b314346c208923e6e1732d070f9a498fb2e4bbf5b4e)", + "P->V[59368:59400]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 1014416, Column 5: Field Element(0x22ad3d1eb9f244f5781dab87ce7381a1cd6b2c3d30965989201eff46f1e5ae6)", + "P->V[59400:59432]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 1014416, Column 6: Field Element(0x1c8e1d108384a3322a2f861b108ac17674a83e9b3ebf7bfe4e26d80dce5293e)", + "P->V[59432:59464]: /cpu air/STARK/FRI/Decommitment/Layer 1: Row 1014416, Column 7: Field Element(0x648a0943b0c530c720b536106d4aaf6ac24f0777ecd8dc3a033e295f93b5ccd)", + "P->V[59464:59496]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1066074: Hash(0xaf74d53e4970490efbb955aae1793b78045df6bc000000000000000000000000)", + "P->V[59496:59528]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1186472: Hash(0x536fc9aefd9b2ecb90c9d84a8257e8ae28cdff11000000000000000000000000)", + "P->V[59528:59560]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1277892: Hash(0x77959553f19fd05c7c79fd2c473018cda94519c4000000000000000000000000)", + "P->V[59560:59592]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1307504: Hash(0xc0a1c24bc9d1c88ae95fc166fb7e478ce315e1ab000000000000000000000000)", + "P->V[59592:59624]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1312434: Hash(0x9606a39a55d585871decdaa9dcfd0950a1614da3000000000000000000000000)", + "P->V[59624:59656]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1327365: Hash(0xe2dd6f57ea3a8b8f3c11e5e7841be18b58913378000000000000000000000000)", + "P->V[59656:59688]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1334151: Hash(0x1f1cfb56725c536c19c50c58886747519f891e80000000000000000000000000)", + "P->V[59688:59720]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1335503: Hash(0x6e1a8475a8d725d241c03e750b81f4e18ec8de37000000000000000000000000)", + "P->V[59720:59752]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1380651: Hash(0x2a502e7e80c6bdeff48eabc234a5896bf673fa0b000000000000000000000000)", + "P->V[59752:59784]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1487790: Hash(0x9bd84eba772cd906bcb7d703c00b6e9a53531bbc000000000000000000000000)", + "P->V[59784:59816]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1627524: Hash(0x59b522ca75c6df4b02883b38e818fbf28c81c742000000000000000000000000)", + "P->V[59816:59848]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1730538: Hash(0x83f2b79eeb077379c8d9a5e5ee592cd8dea56def000000000000000000000000)", + "P->V[59848:59880]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1843463: Hash(0xee0af3f291a86dc997a0e496feac140ff19d4ca8000000000000000000000000)", + "P->V[59880:59912]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1894578: Hash(0x1f66e92f42382bbf0a22c3ba9c013d62edf04863000000000000000000000000)", + "P->V[59912:59944]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2062993: Hash(0xa734bb1db1b91c818ad26315f13b0077799195f000000000000000000000000)", + "P->V[59944:59976]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 533036: Hash(0xe218c7ddd27bc7ea317106a7f04ffae2862e6171000000000000000000000000)", + "P->V[59976:60008]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 593237: Hash(0x7ae2d5c2fea56f5f4dfc4c6da3010739473fc3a000000000000000000000000)", + "P->V[60008:60040]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 638947: Hash(0xd77ca18c5596396224001ddd122177b29238caa4000000000000000000000000)", + "P->V[60040:60072]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 653753: Hash(0xf782cfd03ad1571553f9210d6ed7eba41b51d7ab000000000000000000000000)", + "P->V[60072:60104]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 656216: Hash(0x1c2a6bef0a66cf28b9315221b499776fa3b27ef3000000000000000000000000)", + "P->V[60104:60136]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 663683: Hash(0xd1b16694a2d51e2fdaca54fc29c4303fce91d000000000000000000000000000)", + "P->V[60136:60168]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 667074: Hash(0x411a09edb5c56f4f764a99f35627fe07cf008785000000000000000000000000)", + "P->V[60168:60200]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 667750: Hash(0x1d296d744038f4b44225c80922054aa2c9501a3b000000000000000000000000)", + "P->V[60200:60232]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 690324: Hash(0x7452c0cf59aec72caf21b25b456fa8a2127eff94000000000000000000000000)", + "P->V[60232:60264]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 743894: Hash(0xe47d49d690560745c10f5bb86658763b789caf02000000000000000000000000)", + "P->V[60264:60296]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 813763: Hash(0xdde87a43ae6a2650586359bd9848b66886ddd7d9000000000000000000000000)", + "P->V[60296:60328]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 865268: Hash(0xfb91b47fd4bcd18e80065c8c198ca06231fbd565000000000000000000000000)", + "P->V[60328:60360]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 921730: Hash(0xebc817fbb9fe2c4bea5f38070be1b131c47317bb000000000000000000000000)", + "P->V[60360:60392]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 947288: Hash(0x1e4490f52da8da05508a732626fdc83df6ec2fdb000000000000000000000000)", + "P->V[60392:60424]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1031497: Hash(0x620bcb64664f63c116da751777c19e1868741f1a000000000000000000000000)", + "P->V[60424:60456]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 266519: Hash(0xcdf4d45dbbf95c2b2fe3cb685ab9f80dd32edfee000000000000000000000000)", + "P->V[60456:60488]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 296619: Hash(0xa3fca106e5a07938493b8c1282d015ff639266eb000000000000000000000000)", + "P->V[60488:60520]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 319472: Hash(0x1021b5b780a0bdce9616691c7800f9067b8f0699000000000000000000000000)", + "P->V[60520:60552]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 326877: Hash(0x385f4fd5cac04a47f3f67f455300a8b0a226d658000000000000000000000000)", + "P->V[60552:60584]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 328109: Hash(0xf25c7e0827095fdb5f4cba5d2fb69541c5298849000000000000000000000000)", + "P->V[60584:60616]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 331840: Hash(0x241b91496e87bdbd2a3feff512066ddd973da56000000000000000000000000)", + "P->V[60616:60648]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 333536: Hash(0xf45767de6e7efc28f1b77431b1a76d7828d84c6e000000000000000000000000)", + "P->V[60648:60680]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 333874: Hash(0xda9039e5516c045cf494c0d7a73546a990b66609000000000000000000000000)", + "P->V[60680:60712]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 345163: Hash(0x1ab5711ce9891bdab24b03b30ef894144f5af4f0000000000000000000000000)", + "P->V[60712:60744]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 371946: Hash(0x19bd066711177a9fbc94cdf2b731066578164379000000000000000000000000)", + "P->V[60744:60776]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 406880: Hash(0xad66b6dcec32ad9ebfdaa2e9cde9b398e00d328f000000000000000000000000)", + "P->V[60776:60808]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 432635: Hash(0xf4c3297dec6f3ce40e9986ae66c71ff3640730b1000000000000000000000000)", + "P->V[60808:60840]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 460864: Hash(0x9472b5559ce6d2d128a78e6a78c4a9020fc5628f000000000000000000000000)", + "P->V[60840:60872]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 473645: Hash(0xb1958032d09ebe10ec9443953e932726ea4e2e3b000000000000000000000000)", + "P->V[60872:60904]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 515749: Hash(0x1e578976eb05a81f584fec227ccb5fd80afe13bf000000000000000000000000)", + "P->V[60904:60936]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 133258: Hash(0xce209bc9086aece6cbe2e67c64b43bc210ebf2c3000000000000000000000000)", + "P->V[60936:60968]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 148308: Hash(0xee97b9323e01139ade34cfeb1ee72a2fe2c045cb000000000000000000000000)", + "P->V[60968:61000]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 159737: Hash(0x416ed73be43b551932dbbd12b67cd3fe867187ee000000000000000000000000)", + "P->V[61000:61032]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 163439: Hash(0xa5d4361e50b9fb413715ab0413449c65ea73aaa000000000000000000000000)", + "P->V[61032:61064]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 164055: Hash(0x2e6284176d407dfb1ea27e959609c721006b32c2000000000000000000000000)", + "P->V[61064:61096]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 165921: Hash(0x75573b0d9781aa17f0cee6a3fc11068566276cd9000000000000000000000000)", + "P->V[61096:61128]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 166769: Hash(0xa08503905e89049f9c7e399936197c52845a76d6000000000000000000000000)", + "P->V[61128:61160]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 166936: Hash(0xa12731d04df73bfb276ee28e74f9d8a71754e784000000000000000000000000)", + "P->V[61160:61192]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 172580: Hash(0x8dad26825c891c963e1014e181e6a1d4056efd58000000000000000000000000)", + "P->V[61192:61224]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 185972: Hash(0x12f64fb4816154223be8d6d47a3a8b91faafb831000000000000000000000000)", + "P->V[61224:61256]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 203441: Hash(0x768a63c06b02c21dcca60714cda5bd8364543b2b000000000000000000000000)", + "P->V[61256:61288]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 216316: Hash(0xba0f54c80c152a7ebcfd48df671a09723fd2a5c9000000000000000000000000)", + "P->V[61288:61320]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 230433: Hash(0xbbb4ece8f53b5e401da85257f2c8a5099c008e95000000000000000000000000)", + "P->V[61320:61352]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 236823: Hash(0x9881040f2f316a3397c86c89df3502bc6b4b43ea000000000000000000000000)", + "P->V[61352:61384]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 257875: Hash(0xbbd991f9fcdcbabbf8652ff18edbe7366ee33c2a000000000000000000000000)", + "P->V[61384:61416]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 66628: Hash(0x6f384efb59ef60d4327dfe5e8e376caaf80e2480000000000000000000000000)", + "P->V[61416:61448]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 74155: Hash(0x6b828c11d5203dc2b816598ef520dd233094d097000000000000000000000000)", + "P->V[61448:61480]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 79869: Hash(0xdbaa31698059be6a5078ebc69d2de2d029d9c272000000000000000000000000)", + "P->V[61480:61512]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 81718: Hash(0xcf4c33d2b231f6e0914dcb27169d626b1e39334e000000000000000000000000)", + "P->V[61512:61544]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 82026: Hash(0x81fd8c9cc8932432e421fb40d6aba364f03e8aed000000000000000000000000)", + "P->V[61544:61576]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 82961: Hash(0x1916ef2301d60faba48f4c3afd1e57460707db88000000000000000000000000)", + "P->V[61576:61608]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 83385: Hash(0x71c4a5419b675c8460923de87be742fc57d5be0f000000000000000000000000)", + "P->V[61608:61640]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 83469: Hash(0x8cf93d13076743e9b2f87016447021103f49e95c000000000000000000000000)", + "P->V[61640:61672]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 86291: Hash(0xfeb3fc85fc54b40dc6fb3318c82b129e7b29318000000000000000000000000)", + "P->V[61672:61704]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 92987: Hash(0x18230e14df57180410d449bb8497009129a1baa8000000000000000000000000)", + "P->V[61704:61736]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 101721: Hash(0x4cba6cf3a6271386867bf78aaebd161713a37ab8000000000000000000000000)", + "P->V[61736:61768]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 108159: Hash(0x4ab844a26c98041e1756a3cd185018c9b03a2fd4000000000000000000000000)", + "P->V[61768:61800]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 115217: Hash(0x79c1a27fa59d58004ff897e915297895ddee8d6d000000000000000000000000)", + "P->V[61800:61832]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 118410: Hash(0x64f60a2c71f38dcd0aebc9c0101e7e6f99aa44d1000000000000000000000000)", + "P->V[61832:61864]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 128936: Hash(0x70a3a989ad6f0fd9eb4abe47f8330868019d0f3f000000000000000000000000)", + "P->V[61864:61896]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 33315: Hash(0x3bb089b3771ec07123df48ae092b72cf1b395b73000000000000000000000000)", + "P->V[61896:61928]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 37076: Hash(0xd6016437f6cbf51e02a9035e9087fbddd13670e0000000000000000000000000)", + "P->V[61928:61960]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 39935: Hash(0xaa391a0b987fcd8958653677e642831ca7fa489a000000000000000000000000)", + "P->V[61960:61992]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 40858: Hash(0xaddf41f03aa6c4815f70c37115787efe4eae3a4a000000000000000000000000)", + "P->V[61992:62024]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 41012: Hash(0x4201152d4170e197530bdaddea7982d33f5f49e5000000000000000000000000)", + "P->V[62024:62056]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 41481: Hash(0xbedd3c5a4dd53d03a8fe439db67d4bb74cfbc4f4000000000000000000000000)", + "P->V[62056:62088]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 41693: Hash(0xba05c2aa30f63f886f8d6e7ac1e2f99ef78731c4000000000000000000000000)", + "P->V[62088:62120]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 41735: Hash(0xbe9ba19a509cc0394276509f831ec5b49e146b1b000000000000000000000000)", + "P->V[62120:62152]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 43144: Hash(0x5ffa6728852538c79e08f3aa6a7895d6af93c187000000000000000000000000)", + "P->V[62152:62184]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 46492: Hash(0x5989d855cbc3655e866acb30494dda282f52daab000000000000000000000000)", + "P->V[62184:62216]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 50861: Hash(0x292ce40d51ba51d8492267bb5117a235980691aa000000000000000000000000)", + "P->V[62216:62248]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 54078: Hash(0xde8d984bbdba867b5ec14e9b6e945210afe2fa3f000000000000000000000000)", + "P->V[62248:62280]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 57609: Hash(0x82975662fdea4f7c09a9b5d97aaa272284c91822000000000000000000000000)", + "P->V[62280:62312]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 59204: Hash(0x5e6c4749be5f5d887e511f48ca7f67bd4277ee18000000000000000000000000)", + "P->V[62312:62344]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 64469: Hash(0xc3dccf54451d10eab84b4e9e53ff1be470655e27000000000000000000000000)", + "P->V[62344:62376]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 16656: Hash(0x5327ddabe47eba445f0274ae8987abd72063e260000000000000000000000000)", + "P->V[62376:62408]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 18539: Hash(0x7e575ccd0e2c1609127601fd4d4e88e57d6b1f62000000000000000000000000)", + "P->V[62408:62440]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 19966: Hash(0xfd6fdce4d47a3e80f200ef341fa43f3f8fc16769000000000000000000000000)", + "P->V[62440:62472]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 20428: Hash(0xe56bef70b8bf24584a4de9ad9e1cb10a8736f67000000000000000000000000)", + "P->V[62472:62504]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 20507: Hash(0x9e5f94bad72b82533051228db1a5cfdf8f322a73000000000000000000000000)", + "P->V[62504:62536]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 20741: Hash(0xc0bea97fe39bf84e95919c1dce3f2704baf29dd6000000000000000000000000)", + "P->V[62536:62568]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 20847: Hash(0x3b82b4c2c64e1243c5dd2b4504d6449ee4c1eaec000000000000000000000000)", + "P->V[62568:62600]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 20866: Hash(0x9cab88fddb2acfb6c26c09f3fb96b36699c4015a000000000000000000000000)", + "P->V[62600:62632]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 21573: Hash(0x10f89af695c0cb05c8cd04446c0dc2fa5c345b4a000000000000000000000000)", + "P->V[62632:62664]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 23247: Hash(0x705402b0690e6db6ef3f0faa6369c0d60deec733000000000000000000000000)", + "P->V[62664:62696]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 25431: Hash(0xb1a101a1d1e882847630b9e0350cd4c0bbcb7c49000000000000000000000000)", + "P->V[62696:62728]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 27038: Hash(0xdcd6f6edf814ef6cf5561c170a7f2ace5d974532000000000000000000000000)", + "P->V[62728:62760]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 28805: Hash(0x9be64ce36765b9ebcb1798e57999e735e38ce63f000000000000000000000000)", + "P->V[62760:62792]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 29603: Hash(0x181a9d3c82214cf546b43e4ea9d8c2ff1d68c888000000000000000000000000)", + "P->V[62792:62824]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 32235: Hash(0x5c8c9f06d626c72af81004a18e432e74b6143a27000000000000000000000000)", + "P->V[62824:62856]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 8329: Hash(0xc0c56b0ea324ecdf46cc03a652572a4a42c3b4e3000000000000000000000000)", + "P->V[62856:62888]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 9268: Hash(0x28c5b0710a30101f8feed7f7ae3fdf40a3a33b40000000000000000000000000)", + "P->V[62888:62920]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 9982: Hash(0x8c24566e2e62dfc81c1392cc8ba75a9bbf3ae9f5000000000000000000000000)", + "P->V[62920:62952]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 10215: Hash(0xa46df1406145b8b447ba4eae7c69d21311d5ded5000000000000000000000000)", + "P->V[62952:62984]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 10252: Hash(0x2e1a0ea14a11c2d85f59f15c74eb663e02f9ab9b000000000000000000000000)", + "P->V[62984:63016]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 10371: Hash(0x2ceb70dfeb4339ef850c1429b10dfa94c79a1501000000000000000000000000)", + "P->V[63016:63048]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 10422: Hash(0x6469444a443fdc73656e7ccc55bee4cc91ee1895000000000000000000000000)", + "P->V[63048:63080]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 10432: Hash(0x3a8642c14d5acf63c8a3bd59e919781439e70382000000000000000000000000)", + "P->V[63080:63112]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 10787: Hash(0xf7ed1d370ff03d6e1dc625f1f58b26491f9c24e2000000000000000000000000)", + "P->V[63112:63144]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 11622: Hash(0xda8c5eb1322a188f35cb572b21f50b02fdf0ca93000000000000000000000000)", + "P->V[63144:63176]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 12714: Hash(0xd952b8daafdd019c995af15224d25595bb326572000000000000000000000000)", + "P->V[63176:63208]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 13518: Hash(0xfe551f4762b0d34d014bf032e9b100d9cdc1a4ee000000000000000000000000)", + "P->V[63208:63240]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 14403: Hash(0xe00ffc08203e17be8f1eb0cade032aec9e5e460a000000000000000000000000)", + "P->V[63240:63272]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 14800: Hash(0xa6c298f0283e0f1f8048ec385e474e59d98b90c3000000000000000000000000)", + "P->V[63272:63304]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 16116: Hash(0x9dd19b454797f1392f2805d62bf71d20ca512f21000000000000000000000000)", + "P->V[63304:63336]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 4165: Hash(0xb9c7fb04219619a61326410112f6fda8d61f9fea000000000000000000000000)", + "P->V[63336:63368]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 4635: Hash(0xd0b10804fe79925dc50d54680a7f508e97b0751d000000000000000000000000)", + "P->V[63368:63400]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 4990: Hash(0xe9856576441a6a01a4593d78c02b6b1e33552c14000000000000000000000000)", + "P->V[63400:63432]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 5106: Hash(0x3f2323c25f99511732232dc7ba2d7cada312b23d000000000000000000000000)", + "P->V[63432:63464]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 5127: Hash(0xf2e2097d19088add6f760de40803c52b43dcfa2c000000000000000000000000)", + "P->V[63464:63496]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 5184: Hash(0x7104cf7d6a2f90e053f67779c22d145fd933aa71000000000000000000000000)", + "P->V[63496:63528]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 5210: Hash(0x4fa3258c060e4c7648dd2c34c116cdc6e32eff5e000000000000000000000000)", + "P->V[63528:63560]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 5217: Hash(0x20c204d445cae23e3049e29b895498b17599d361000000000000000000000000)", + "P->V[63560:63592]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 5392: Hash(0xd6c4621febe41d96291e7327c934de135e80c405000000000000000000000000)", + "P->V[63592:63624]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 5810: Hash(0xec2243524a8c6586e240a9ad84817ac1268a0edb000000000000000000000000)", + "P->V[63624:63656]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 6356: Hash(0x4de1d00414511e2d7dbf7dffb42b3d0a3f9660d0000000000000000000000000)", + "P->V[63656:63688]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 6758: Hash(0x599db688ed9312d8e893247369532bcb9e408226000000000000000000000000)", + "P->V[63688:63720]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 7200: Hash(0x7deabba986c58e2e9b6487ab235e0691fa06a227000000000000000000000000)", + "P->V[63720:63752]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 7401: Hash(0xd50b25845a3c2a55ff56f4483a980783ad0d3c5f000000000000000000000000)", + "P->V[63752:63784]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 8059: Hash(0xa8ad06908babed5b78257a518cb5e416d4dcb17b000000000000000000000000)", + "P->V[63784:63816]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2083: Hash(0x4914de52deb2e623438e62aa65137e9c6dd3d39b000000000000000000000000)", + "P->V[63816:63848]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2316: Hash(0x843fde05c8cb2c75872bcfef49a8f06c74911be9000000000000000000000000)", + "P->V[63848:63880]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2494: Hash(0xebd5fd425aa5c38ae5ba4aa3bb1e0eeefbd89d2e000000000000000000000000)", + "P->V[63880:63912]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2552: Hash(0xc84170c5d4444715754bf95808111e2bf223cc96000000000000000000000000)", + "P->V[63912:63944]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2562: Hash(0x41cc5f5036da43442eb4749d00c6a3145f50fc89000000000000000000000000)", + "P->V[63944:63976]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2593: Hash(0xcde1b006f3336cde1b617cbad9cc7d52dc4e3b6b000000000000000000000000)", + "P->V[63976:64008]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2604: Hash(0x7941013f048892b669ae9f024e4db717981021e4000000000000000000000000)", + "P->V[64008:64040]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2609: Hash(0xfd7263b328702112146b1f3047e63d08e69b3afd000000000000000000000000)", + "P->V[64040:64072]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2697: Hash(0x8fdb35273c6b76c15efe35a0985a00d0146fc76e000000000000000000000000)", + "P->V[64072:64104]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2904: Hash(0xe0b725f118118f4d6a6412db0ea594e02e002286000000000000000000000000)", + "P->V[64104:64136]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 3179: Hash(0x2b94e34f3802555b2a17b362f76d8c96f3e4e2fa000000000000000000000000)", + "P->V[64136:64168]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 3378: Hash(0xa061440cc55c724a082615325a5d92de31d4dddb000000000000000000000000)", + "P->V[64168:64200]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 3601: Hash(0x44e32ada153bbc7c959a92ca80898e162b367414000000000000000000000000)", + "P->V[64200:64232]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 3701: Hash(0x9ae9e02fe0bdd323a3ae55e90b97a4118fe31a0d000000000000000000000000)", + "P->V[64232:64264]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 4028: Hash(0xca8573b6ea8bd37cc57e0e117bc3537d97da008000000000000000000000000)", + "P->V[64264:64296]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1040: Hash(0x158e28026702b53a9fb2b276ec7441a19c9f9ade000000000000000000000000)", + "P->V[64296:64328]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1159: Hash(0x32dbcd7816663e30dddb7a9f14d2743061bc2a0b000000000000000000000000)", + "P->V[64328:64360]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1246: Hash(0x95b4805d93bda0265f789b9b08f9ec0051cb440d000000000000000000000000)", + "P->V[64360:64392]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1277: Hash(0x1a1015a616d3002f855b506899b0d6a89e60648f000000000000000000000000)", + "P->V[64392:64424]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1280: Hash(0x8cfcfe3f66e06ef758831b2ab498e8ff71d6dd59000000000000000000000000)", + "P->V[64424:64456]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1297: Hash(0x9d21bffe520e834eb913a114fa27537548a61b8d000000000000000000000000)", + "P->V[64456:64488]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1303: Hash(0x7345573bceea39f35fa55b7e16be46bd38696a5e000000000000000000000000)", + "P->V[64488:64520]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1305: Hash(0x6c5ef7bc3f085afea19091719757c0987e9e3e2a000000000000000000000000)", + "P->V[64520:64552]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1349: Hash(0x19e530a6917c65ff13d4e0db8a32695192190056000000000000000000000000)", + "P->V[64552:64584]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1453: Hash(0xf094f61f7d1e4ab10eebd78620a586aa706feb2c000000000000000000000000)", + "P->V[64584:64616]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1588: Hash(0xf4564ffcb268d80642e53a29da117885ad86dda000000000000000000000000)", + "P->V[64616:64648]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1688: Hash(0xa4f6806bac43d4459302a70e1436479eba058412000000000000000000000000)", + "P->V[64648:64680]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1801: Hash(0xf855e15cbbbc2220e7e9603cfb619260641acf0000000000000000000000000)", + "P->V[64680:64712]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1851: Hash(0x7e49eea1a9f30a989e848ecac1e072cfb3e066be000000000000000000000000)", + "P->V[64712:64744]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 2015: Hash(0x1502b9b379c34eb1df797aa5408968612d03f233000000000000000000000000)", + "P->V[64744:64776]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 521: Hash(0xd98fa8ef2dd60e96f0c165514787ff44fcbc1942000000000000000000000000)", + "P->V[64776:64808]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 578: Hash(0x7de202abd2b7a1e99a62746fd357b6eae45c8cea000000000000000000000000)", + "P->V[64808:64840]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 622: Hash(0x8e75b33d901c884096ce396b3e3876e3f27dbd59000000000000000000000000)", + "P->V[64840:64872]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 639: Hash(0x6dcc18b8d87b85523ac205c4fae62e49d037dfff000000000000000000000000)", + "P->V[64872:64904]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 641: Hash(0x3a965f6af8acab1b844f123f60a39116c66972fc000000000000000000000000)", + "P->V[64904:64936]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 649: Hash(0xd7b7ed2d839a25eb92b2d34a1daa4138011fc2b2000000000000000000000000)", + "P->V[64936:64968]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 650: Hash(0x24d0b765929eb6c7926f66e016606aec15fada82000000000000000000000000)", + "P->V[64968:65000]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 653: Hash(0x13cbec4769fb2a8d8dd2af3d273d43ea2dd1130b000000000000000000000000)", + "P->V[65000:65032]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 675: Hash(0xf1513857d92e5cacb687c9baee1a78f0f0653641000000000000000000000000)", + "P->V[65032:65064]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 727: Hash(0x964f9b49ba9434947c1433fd700451264f5c5bde000000000000000000000000)", + "P->V[65064:65096]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 795: Hash(0x5d4828c5efc5282ea8837ec5743c26c4e39ae35c000000000000000000000000)", + "P->V[65096:65128]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 845: Hash(0x3fdf133094122dc00fc20b0ebdfa38e4f906368c000000000000000000000000)", + "P->V[65128:65160]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 901: Hash(0x762cc4d2e90e701f601b4f040fc01ab6de3fb758000000000000000000000000)", + "P->V[65160:65192]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 924: Hash(0x9dce0aef210e0bcece7ee0c76f10c32f421a14c1000000000000000000000000)", + "P->V[65192:65224]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 1006: Hash(0xb9ec3dc5bb7000490ad5f8a894cb46270cc57e20000000000000000000000000)", + "P->V[65224:65256]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 261: Hash(0x74d0d253ce69faaa9daf973251b8ee9a4d778ad6000000000000000000000000)", + "P->V[65256:65288]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 288: Hash(0xd8bc58e2867fa0b616e05a1fd20f1e1803be5051000000000000000000000000)", + "P->V[65288:65320]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 310: Hash(0xb453eec5a1cb07897026aaff1503db06530763d8000000000000000000000000)", + "P->V[65320:65352]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 318: Hash(0xec1329ea34cec869bfe0422ece9c13c2e37457a9000000000000000000000000)", + "P->V[65352:65384]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 321: Hash(0x93dfa6332baa317fe1e5e07d0cf95c2ad8b220a4000000000000000000000000)", + "P->V[65384:65416]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 327: Hash(0x9bb20340e801f9211a0dcdb0524756e0fa378594000000000000000000000000)", + "P->V[65416:65448]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 336: Hash(0x9b51fa95e2509e93684dd6acf42a653e05ee00e6000000000000000000000000)", + "P->V[65448:65480]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 362: Hash(0x6c2ff7db8bd476c8def4f7934144b9919bc988c9000000000000000000000000)", + "P->V[65480:65512]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 396: Hash(0x5a1a8414b34a95b57b3592ff9d3fee898a7a8dea000000000000000000000000)", + "P->V[65512:65544]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 423: Hash(0xef56413df432e22d5fa8207a298e6b9b35350fb1000000000000000000000000)", + "P->V[65544:65576]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 451: Hash(0x90e6dd33054fb89b9c348a92c0ba211ac1125944000000000000000000000000)", + "P->V[65576:65608]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 463: Hash(0x1f137142637c940a41ded7d7775224d296f9bd83000000000000000000000000)", + "P->V[65608:65640]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 502: Hash(0x310a0403d2a8f0853b5afe0aa8fc5144809f3229000000000000000000000000)", + "P->V[65640:65672]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 131: Hash(0x8ac9661a713cf5c9c63c73780a3be085bfca0136000000000000000000000000)", + "P->V[65672:65704]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 145: Hash(0xf2b44d1d09b137fab51386315df8e1c2803f2542000000000000000000000000)", + "P->V[65704:65736]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 154: Hash(0x74ad8f1e516945c46fce684688e008ffee873919000000000000000000000000)", + "P->V[65736:65768]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 158: Hash(0x984de49bb7814123d8cac8640f3265fe6bf00520000000000000000000000000)", + "P->V[65768:65800]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 161: Hash(0x995c01d7795420f98676d0d6fa265443b0c26946000000000000000000000000)", + "P->V[65800:65832]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 169: Hash(0x1bdcd228e30a4c86ee9d94d288726867fe06cd5c000000000000000000000000)", + "P->V[65832:65864]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 180: Hash(0x5212770d6385f68cf1f49aa86b863851d6dff8c5000000000000000000000000)", + "P->V[65864:65896]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 199: Hash(0x7a003b326e2620fceafb48924223fd58468b4b68000000000000000000000000)", + "P->V[65896:65928]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 210: Hash(0xfb25c83e51777528df468acf39aaf7d5273ce26f000000000000000000000000)", + "P->V[65928:65960]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 224: Hash(0x7eb048589a2a71f268c304d9798f30b03e4ed0a0000000000000000000000000)", + "P->V[65960:65992]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 230: Hash(0x862817e761d5f1621c67635866f23b408b76403e000000000000000000000000)", + "P->V[65992:66024]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 250: Hash(0xe15346c51ea5fdd406113bcca515cc342ebb2e81000000000000000000000000)", + "P->V[66024:66056]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 64: Hash(0xf2a02a6069b82c573a0f7272947d185698a1f357000000000000000000000000)", + "P->V[66056:66088]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 73: Hash(0xe9170c6598ad535bb7aa7307d974e52877c745b2000000000000000000000000)", + "P->V[66088:66120]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 76: Hash(0xde9d372bc17372da355a8818eaa89b47e05c436d000000000000000000000000)", + "P->V[66120:66152]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 78: Hash(0x3cacb59bd552c0aa0aa8f45c4e2ca231ab96fd93000000000000000000000000)", + "P->V[66152:66184]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 85: Hash(0xe69ca947a7d1018ec85daf1e579e7af98df0d939000000000000000000000000)", + "P->V[66184:66216]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 91: Hash(0xb7ea06df338d316ecd9a8033d71fa9ebcbff0fd9000000000000000000000000)", + "P->V[66216:66248]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 98: Hash(0x6fd71c7d33f67c3c17f41dbaa330e346231be5d1000000000000000000000000)", + "P->V[66248:66280]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 104: Hash(0x3b693f3170e05729fe746021aa022b1422fa51b2000000000000000000000000)", + "P->V[66280:66312]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 113: Hash(0x5535c105ea57086001a316295ce8b172852b40fd000000000000000000000000)", + "P->V[66312:66344]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 114: Hash(0x14c2cdde834e3e15f4efd0919d09a93cc00b6dc4000000000000000000000000)", + "P->V[66344:66376]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 124: Hash(0x8dc89a2ab7e251b5a35505271cb3df90ce56bc20000000000000000000000000)", + "P->V[66376:66408]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 33: Hash(0xb7923c5a25b01e351268748bf22839a0313034d5000000000000000000000000)", + "P->V[66408:66440]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 37: Hash(0x3909fa7c983a63f48d8f728eb41f31b886e9fa36000000000000000000000000)", + "P->V[66440:66472]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 41: Hash(0xc3633cd5268e76545cf2b54344f642e7d00bf441000000000000000000000000)", + "P->V[66472:66504]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 43: Hash(0xb78effb6c0ae6970065f3717777194f28989c918000000000000000000000000)", + "P->V[66504:66536]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 44: Hash(0x9f89f79ac288cc90000f57d692872f0f74c3dbef000000000000000000000000)", + "P->V[66536:66568]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 48: Hash(0x47f3682b3a95c17b2266544a7d778b5e1c10bd9a000000000000000000000000)", + "P->V[66568:66600]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 53: Hash(0x79b96490e5220b064d48b3f0164d64c608475cf6000000000000000000000000)", + "P->V[66600:66632]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 63: Hash(0xdd94488c6c4cc5054594c33043960514d11938ab000000000000000000000000)", + "P->V[66632:66664]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 17: Hash(0xb1bc71c2523ed4a97b84d12afcfd61fc289ad4c5000000000000000000000000)", + "P->V[66664:66696]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 23: Hash(0xab78ee33cf87807603abb0569c4885ad946986c7000000000000000000000000)", + "P->V[66696:66728]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 25: Hash(0x883b0d7460379976a9ef934da891a304e6a7b24a000000000000000000000000)", + "P->V[66728:66760]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 27: Hash(0xe0af8b51bd5614501de5505e50ba8d9dbb1f01b5000000000000000000000000)", + "P->V[66760:66792]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 29: Hash(0x72aadb281211e4c896371ae2385a58078f3bcf0c000000000000000000000000)", + "P->V[66792:66824]: /cpu air/STARK/FRI/Decommitment/Layer 1: For node 30: Hash(0x1dc3ced07cf812138060e52dec58700b6497548a000000000000000000000000)", + "P->V[66824:66856]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 2187, Column 0: Field Element(0x466d2ff0dcd4987e0a78057de892e9772f174f7c16f1d778ed380e5f67598af)", + "P->V[66856:66888]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 2187, Column 1: Field Element(0x247817093261732eb8317b8d89e25261e79daacef51436face8f51c41c8ba07)", + "P->V[66888:66920]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 2187, Column 2: Field Element(0x5eceaadb5f9feb54fcc6cbe5b9040807ad7e4fed5cdff9fc0bb5b135c1c0ad0)", + "P->V[66920:66952]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 2187, Column 4: Field Element(0x669317124747af38ce9119a1685b82d8e0c322c47f872732c3ee56885f7d453)", + "P->V[66952:66984]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 2187, Column 5: Field Element(0x5e976e9ff539d6bca5e2a82e95e63d100a065d759a0a4420cded2ed01ede096)", + "P->V[66984:67016]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 2187, Column 6: Field Element(0x53cb66a337d727b67d950671d5a924809c119210becaea8beb765c903fec0af)", + "P->V[67016:67048]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 2187, Column 7: Field Element(0x58749e2b902196ef51cdd28e6dc8f0d1c1a4cad374c2687744fe2136a7755b2)", + "P->V[67048:67080]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 17237, Column 0: Field Element(0x5c069bdb32737c04f2f7d437aa1b1bef1396a026119ecbc0b8dcb0a410b1485)", + "P->V[67080:67112]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 17237, Column 2: Field Element(0xbae0c0a41b41353a0a3de5241e2a01699faf8e08ab6da384b562ceb0efcc18)", + "P->V[67112:67144]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 17237, Column 3: Field Element(0x1c3a181cdb4c45547a7a601bf424ddb374a6d7f1b9791d2591c82d1c97d223)", + "P->V[67144:67176]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 17237, Column 4: Field Element(0x32e07234864d7439e1d49142c577fb01a6dba8ac4ca899af094b4682df1d537)", + "P->V[67176:67208]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 17237, Column 5: Field Element(0x5762eddaca5c8cb6a4854c9646f6ffce3c3b450f5cdfa7806864ec5f6bb91c3)", + "P->V[67208:67240]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 17237, Column 6: Field Element(0x101d05d4a55c077a59e3adc1e41604010a02b84a4b5c1c814af02df82a8fcec)", + "P->V[67240:67272]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 17237, Column 7: Field Element(0x7f0244392ea87a395c9e9da68a8c41bd9605de2f513a4bd2e839deb7958dbd3)", + "P->V[67272:67304]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 28664, Column 0: Field Element(0x603d1a7c71f8b8ab3bf94e1b299e2fe12613d37dae8bcfa25a8faa37fe7818b)", + "P->V[67304:67336]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 28664, Column 1: Field Element(0x705b485abd3d84d29df545b2bc0b7b925e9bea4811aeaadf5068b8dd91c1b48)", + "P->V[67336:67368]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 28664, Column 2: Field Element(0xbccf2537b8cfe9f0baada95a0ad5306a4e1cb7691eed0783943711ee90477c)", + "P->V[67368:67400]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 28664, Column 3: Field Element(0x55e39e85c1985794a9c59c47603306e518e687d59e92b12140c6a33c9ad459b)", + "P->V[67400:67432]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 28664, Column 4: Field Element(0x3c8c44d580cbf1550ce0dac0372816f60eab86e6c543d557fc4c5adb3c88737)", + "P->V[67432:67464]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 28664, Column 6: Field Element(0x39da7e3c47dd77ff984ebb52dc27f65597a33008e1fbb806721253d7600f06d)", + "P->V[67464:67496]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 28664, Column 7: Field Element(0x4cfd7d948f005c69b4a11a1be744c4495f9f195fc048794eb38bbd5893516a5)", + "P->V[67496:67528]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32366, Column 0: Field Element(0x55c9058e7c619f87368075e0d413e3b333dd99d001619975d168b17182ba926)", + "P->V[67528:67560]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32366, Column 2: Field Element(0x2c633d0375508b5175a8fa459f911fd538fb3916f2b1322b26d1aea6b2cc46a)", + "P->V[67560:67592]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32366, Column 3: Field Element(0x7cd2552817eeea52b37e5b8a2c93d65d6b7982ed4db7f227f537e5cc4f93bab)", + "P->V[67592:67624]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32366, Column 4: Field Element(0x3edda661b70c3b4172b51a5039500ec6e190a27f2196e6f501a1ba42e1e94e9)", + "P->V[67624:67656]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32366, Column 5: Field Element(0x794d6715bba9f7a618cce45204659ffcd9d70c94405263fc77caaedf6816669)", + "P->V[67656:67688]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32366, Column 6: Field Element(0x1f7447893ce5c0771db7478488d690099c674fd033650be2f33fb3816102bc5)", + "P->V[67688:67720]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32366, Column 7: Field Element(0x33c610485af30aa6e1d13565d13fd11406a627a0ad20d89844a0e7d814297dd)", + "P->V[67720:67752]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32982, Column 0: Field Element(0x592c48f7375e63d8f64a0a672a646afa4168b889df2a0931502a17a93e1722)", + "P->V[67752:67784]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32982, Column 1: Field Element(0x642d47979c1a5676ac9b2e124f2f384b4a1fe26c22587db792baf4c4a9ee1b4)", + "P->V[67784:67816]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32982, Column 2: Field Element(0x733a069816e90fcb037bfce990546e475ad3bd032b11b08fecc99dde3115622)", + "P->V[67816:67848]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32982, Column 4: Field Element(0x4dc16c92a6805f97818487b53a0394a27c885f71bdc988d317aa87d9536daa5)", + "P->V[67848:67880]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32982, Column 5: Field Element(0x40c46e609b97e6f4ab9827bffd52d20d34892121705277799a27d495a10b50a)", + "P->V[67880:67912]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32982, Column 6: Field Element(0x3343824c89dbefbdbf51a5871c78920c0f0017b2d8c196e71b22678def022f9)", + "P->V[67912:67944]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 32982, Column 7: Field Element(0x7bee5dccdcd0932b8353882f48b6b609a59aaa23093830dc62874bd6f7caac2)", + "P->V[67944:67976]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 34848, Column 0: Field Element(0x1eafa1ea603fdc4e2e6a58104169e621fb3cec22cd586709d019f480d49f627)", + "P->V[67976:68008]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 34848, Column 1: Field Element(0xa6eeb7a53505acee83f836bd89f1c8e24dec3bb8e71aa9e3cc10e5c59ba780)", + "P->V[68008:68040]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 34848, Column 2: Field Element(0x6a123850dd3bfecaabd4776ff2561557c8e89cecdf0dbf5027eb71151ccbaae)", + "P->V[68040:68072]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 34848, Column 3: Field Element(0x3c7972c0b8dbad9e690903682c0e89ef72a61ef645f7308205e195f657aa720)", + "P->V[68072:68104]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 34848, Column 5: Field Element(0x516b11a66fc1413ee6f1d67e4ac89d45fa79f0f88570b26ae85b10aa5c35517)", + "P->V[68104:68136]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 34848, Column 6: Field Element(0x5f57a66363dfc83cf9dc8c7d5bbf5a965c27cbb77960754f5942c1a75e50301)", + "P->V[68136:68168]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 34848, Column 7: Field Element(0x37ed3913aa517652812989a8f2860055e6bc857c5d2a230d0d9fe3b2a60f453)", + "P->V[68168:68200]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35696, Column 0: Field Element(0x32f2f75d566b2985b78facaeb98a7db97e6eac75aaac5d1c82215249ec0d3d4)", + "P->V[68200:68232]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35696, Column 1: Field Element(0x6e1d44e34ac150bd775f504d8616a3ce15ac058654d55c52ffe1eb34b7b0358)", + "P->V[68232:68264]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35696, Column 2: Field Element(0x7e0125497cee70fdcfecd0981e1d7b78c51d5d9772c22f8d342d57e09f4e913)", + "P->V[68264:68296]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35696, Column 3: Field Element(0x58e08e09c7299af21fd9c3a5f3f475078f7561a476f0b3753f281c37bcbdebb)", + "P->V[68296:68328]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35696, Column 4: Field Element(0x54495c841108ba38474259123b723d3920b41decfe8db9c18e146fc04ff8b3a)", + "P->V[68328:68360]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35696, Column 5: Field Element(0x73fef6aaa9970cd24b96f490f239a65c82a9f45df8a075a666c805dc16f4c2a)", + "P->V[68360:68392]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35696, Column 7: Field Element(0x437c66eb0ec7b168df79770a41f0009ef4b8a70723de1a80231468e53dd5f2c)", + "P->V[68392:68424]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35865, Column 0: Field Element(0xb5fc1ba488d59add88c2bd62d777ab594ca57f88c19f2a2ef6ca7231668946)", + "P->V[68424:68456]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35865, Column 1: Field Element(0x264dbc9550ef1e1518b937d04ff483b60a48ed2209c98f1b402694138c8c10f)", + "P->V[68456:68488]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35865, Column 2: Field Element(0x64799548042edb4ce2cffaad95073085bc870b4d2a7171408a3276df212ca50)", + "P->V[68488:68520]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35865, Column 3: Field Element(0x7fa1d69015d6bf8a6df58b42bd616d7402c7d43633e1d2f8ab3a52660cef199)", + "P->V[68520:68552]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35865, Column 4: Field Element(0x24e958effa939f6c2e816e8ec06bbd64090c53cb16f02548795588db1933d96)", + "P->V[68552:68584]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35865, Column 5: Field Element(0x6ebd819284ebfff157a26a11c8a3ab0f81c570259a4a17cc235971aef3f9eea)", + "P->V[68584:68616]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 35865, Column 7: Field Element(0x4e26c5b73a2dbf67d2f4d356759c7b54e5ce2ecb88fc0251a9fb5b02fe6b562)", + "P->V[68616:68648]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 41509, Column 0: Field Element(0x5ff52e8f1e1125a162a81a8402733f5d4db2b2971f0386676cd956998ee76cb)", + "P->V[68648:68680]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 41509, Column 1: Field Element(0x15c89667136a9b846b0d16597089ec3ccaf556b17fcae26800fe3bc042b7d0c)", + "P->V[68680:68712]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 41509, Column 3: Field Element(0x43a1d8895823970603463f5ad01b85600124871d018585b1aea7967e8d0b0f2)", + "P->V[68712:68744]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 41509, Column 4: Field Element(0x3547fefbb6296b5ac41ddb3f8a3d0fe3c40ba6e9b9a3d323e39358790ca8de5)", + "P->V[68744:68776]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 41509, Column 5: Field Element(0x5f69c0cdd5c286bc3194b6c00904a171c483a62802287c32fc4539fbd1033f5)", + "P->V[68776:68808]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 41509, Column 6: Field Element(0x7c0c9c3f08473e62446392083b05216e5178068b16104a20bf46086e3b20837)", + "P->V[68808:68840]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 41509, Column 7: Field Element(0x7b2870abfacaf3122614f521ad093871acb53a02de8bf527d3551433b077953)", + "P->V[68840:68872]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 54901, Column 0: Field Element(0x121e74248b1baee95439fcfa17d8b3a633779d811a44434f6ece9c8f80de837)", + "P->V[68872:68904]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 54901, Column 1: Field Element(0x3428f552ca477ab1e3b8c31315239592f28c93b057a8dae8ae43113b64e011b)", + "P->V[68904:68936]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 54901, Column 2: Field Element(0x1e3dd53b44eb02e9ddcc73616871a11ccd81fb4851d99f986a35b2d6661e52a)", + "P->V[68936:68968]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 54901, Column 3: Field Element(0x1031a11175daa8a37cf33dc3125cb968a5d31d3408ba91c9be1f1697cc3f2ab)", + "P->V[68968:69000]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 54901, Column 4: Field Element(0x2586ee076292c7f7c069f26adbe1c1fe19ec42682787c096461f3d85d25d259)", + "P->V[69000:69032]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 54901, Column 5: Field Element(0x32f885058b6d46cda624cc2ebe97382f9e9e5d105b4e89203d86a0ebbb1c64a)", + "P->V[69032:69064]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 54901, Column 6: Field Element(0x28763487d22293fd6a3cedde502e1b8caf04abcf0ff13cbba553e5ca7712945)", + "P->V[69064:69096]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 72368, Column 0: Field Element(0x6f7d7ec89d19be2e1f48ad9cb26480ef31097d254363c5ef9023a8c31fcbac1)", + "P->V[69096:69128]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 72368, Column 1: Field Element(0x119537fce79b1a23ff2d69dd96c7631f8361ea774b995d2ba64e121ec226fe4)", + "P->V[69128:69160]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 72368, Column 2: Field Element(0x60fe05975cbd2ea225d32c01852d8dcd8860016a03d7c09cd9caf846d9c297d)", + "P->V[69160:69192]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 72368, Column 3: Field Element(0x2b18fdf5b627d7f9ce6f1446a0d6d29e0365b74070e25e8c2c554812346a686)", + "P->V[69192:69224]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 72368, Column 4: Field Element(0x7914671c636fa2c9745fec0b11cb1286c5982341c834b4aa02a20c76fe7b268)", + "P->V[69224:69256]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 72368, Column 6: Field Element(0x2d85fd60d88476aeade06f55c347295f546db543bb7e2503f28175f93d79850)", + "P->V[69256:69288]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 72368, Column 7: Field Element(0x4128a648dde740c6f894c56dbfc5b323fcf04a29f419c624fa15a81129940d6)", + "P->V[69288:69320]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 85245, Column 0: Field Element(0x6ae640318cc3bcc4befd1e6c265527eee1ac96ab9b3e00bfb3246c7c8fef16)", + "P->V[69320:69352]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 85245, Column 1: Field Element(0x21ef3da12b4309e94618fd0a04252043b7b5a2201311e62e55656906d0b59fa)", + "P->V[69352:69384]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 85245, Column 2: Field Element(0x390657eec6ac0b616f8f1b4b21066daa317e3bcc332fed292ac6cef95b09e31)", + "P->V[69384:69416]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 85245, Column 4: Field Element(0x3a074355ecb5cb3649cc64cbe317f30f476c2ba3422a0a11b5ffe0c2f51ca17)", + "P->V[69416:69448]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 85245, Column 5: Field Element(0x4eec77a1038ac2722aff0f6b239d7aeeb266f5f743aa2e992f9422c8324d352)", + "P->V[69448:69480]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 85245, Column 6: Field Element(0x1bd13eab10de076465e2dfd96d6f9669d7fc25014d5f084e7025f0f25e05e7)", + "P->V[69480:69512]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 85245, Column 7: Field Element(0x52a19e8c9a8861060634f16c7639b166377290a48b84c96de2c1a194d0ee8f6)", + "P->V[69512:69544]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 99360, Column 0: Field Element(0x438bfe48fe09348d3f23637b773b04137dd66056dd888a5e1bde3572a4d0c9b)", + "P->V[69544:69576]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 99360, Column 1: Field Element(0x7d4113fd81b2f1e472d2142952a0981b203811f288755e44e612b31a87f420a)", + "P->V[69576:69608]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 99360, Column 2: Field Element(0x31a4c4e9b8fb56c21e6d4094523cc2ecc9bfff9cf0f036262f7c62eeec117fb)", + "P->V[69608:69640]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 99360, Column 3: Field Element(0x1577161ff60413b94ea5125a801fa8384c64849a57552afd26b074b9c23e79f)", + "P->V[69640:69672]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 99360, Column 4: Field Element(0x66a4fb136f762be288bf5a2559314a740533cf82962ab1b212a7b5078b6451a)", + "P->V[69672:69704]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 99360, Column 5: Field Element(0x4a6fcf092665ef0a601f538cbbe24e44f1a0480b9e6d9a20d46c23d09812dd1)", + "P->V[69704:69736]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 99360, Column 7: Field Element(0x393290fdbf383813b493e555d342ec2b16d4ed2ece97d01d3998a81dee428d4)", + "P->V[69736:69768]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 105750, Column 0: Field Element(0x27889f9027c553945a22e21a2ff187cee217b096658b2bb87abcee443404571)", + "P->V[69768:69800]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 105750, Column 1: Field Element(0x6e84da3840e25d4784521a8f2b0efb244445c9570080e789690e621575a4808)", + "P->V[69800:69832]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 105750, Column 2: Field Element(0x480cdecb7c270ef57064583e2a6f19229a3b63f4e4c1df8f98bc08937a15cc2)", + "P->V[69832:69864]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 105750, Column 4: Field Element(0xa4815e3a4a0b9ae1e3d192f558c838854be7ba1e29481e7837f27f535ef194)", + "P->V[69864:69896]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 105750, Column 5: Field Element(0x6bcace1616302bf195fbe14263cb495a6d181f1cbf922d0b4bb645407f27af5)", + "P->V[69896:69928]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 105750, Column 6: Field Element(0x20c072126c51ef83425e7c1d9c22df0abca19ed5391aeb5958a74da0c4ec3e)", + "P->V[69928:69960]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 105750, Column 7: Field Element(0x33a249c611729c3dd175e7bad60d1baed242b728c1232b6d7e49531de0993b4)", + "P->V[69960:69992]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 126802, Column 1: Field Element(0x602b18deac9fd1a749e981b9cf781b89ecf29e13651b9bbe09eca3b2e8da735)", + "P->V[69992:70024]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 126802, Column 2: Field Element(0x124136113d78833254f28e7b20968843cc7a5f3a870a6a7fcec85a6b8fcb0d0)", + "P->V[70024:70056]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 126802, Column 3: Field Element(0x402b2066a80b700795c4d1fda49d02940d7fe119ea06c89492f1eb8152f0c84)", + "P->V[70056:70088]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 126802, Column 4: Field Element(0x2786f8548dafcd224a4844ef88ed39f1fcf11262190339a188ab5e9b0f68006)", + "P->V[70088:70120]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 126802, Column 5: Field Element(0x2724f3b026533655f9ff6dc49348e87e8254ffc6a8bd7e0b24860223f58882d)", + "P->V[70120:70152]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 126802, Column 6: Field Element(0x5005f14a73f0f96aa90806ddaa0fa14ecd3f00f2a6bed9c7d555a8b584d6845)", + "P->V[70152:70184]: /cpu air/STARK/FRI/Decommitment/Layer 2: Row 126802, Column 7: Field Element(0x7879d3c092bf99af4754c8e937fff25d7e00a06c96aabdd7ae929e4ab858250)", + "P->V[70184:70216]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 133258: Hash(0xa8a9cf5f2da99ebf1a80b34c7077dd5cd5dbba32000000000000000000000000)", + "P->V[70216:70248]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 148308: Hash(0xbd449f01b7636779597d9111a9ca7bb4a33b36c8000000000000000000000000)", + "P->V[70248:70280]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 159737: Hash(0x848575cf29bf02c836af54b3f1da89f08a435b56000000000000000000000000)", + "P->V[70280:70312]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 163439: Hash(0x96c78b79e7a11fc99d674dd309a7eb55d16da070000000000000000000000000)", + "P->V[70312:70344]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 164055: Hash(0x52e9cd229f3cd982cd41c7ed0add6fe2121c19ee000000000000000000000000)", + "P->V[70344:70376]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 165921: Hash(0x73cd8ad8d32d15609c2e8d721613f9c32e88f887000000000000000000000000)", + "P->V[70376:70408]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 166769: Hash(0x5196ca96da8f3d622154031bc9100b9dec9d5fed000000000000000000000000)", + "P->V[70408:70440]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 166936: Hash(0xb1de56893a91a126d417f395b3b6a2913981d896000000000000000000000000)", + "P->V[70440:70472]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 172580: Hash(0xa2fa4faebc6fa5e4f9062b12fb657bc1c0cae110000000000000000000000000)", + "P->V[70472:70504]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 185972: Hash(0xf500251bfa440b2ccc8e6c57559c4a3c0eabebf6000000000000000000000000)", + "P->V[70504:70536]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 203441: Hash(0xbdb4dfeb8f27f69457cbe49102b736824c556e38000000000000000000000000)", + "P->V[70536:70568]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 216316: Hash(0x75df71348a252d7d94abc86220aa1ad2124a8960000000000000000000000000)", + "P->V[70568:70600]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 230433: Hash(0xc14671dc8989e020f091b4230366188c4ca4a763000000000000000000000000)", + "P->V[70600:70632]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 236823: Hash(0x3d7a2d801a0b15d03d6db1a200e76f39dcd06963000000000000000000000000)", + "P->V[70632:70664]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 257875: Hash(0x598bc7c95083c287f36b5344054b2f70a74229ce000000000000000000000000)", + "P->V[70664:70696]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 66628: Hash(0xc267d5069fef2f49f20071eac1dd77396c0f48ae000000000000000000000000)", + "P->V[70696:70728]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 74155: Hash(0x5c34387165c8d0aab0d16b3c6aee2dbd9d950022000000000000000000000000)", + "P->V[70728:70760]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 79869: Hash(0x18e939f02aa4354486c087c1b6adb0b9a9528b39000000000000000000000000)", + "P->V[70760:70792]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 81718: Hash(0x10c45e9b8f8dff0d5eb65f0c5f9f3250acc61dfd000000000000000000000000)", + "P->V[70792:70824]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 82026: Hash(0xf565904a434e99aa3cca0bb7c0bf4d47f86a403b000000000000000000000000)", + "P->V[70824:70856]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 82961: Hash(0x8c310d6e8a48be523f197b0669e1a7ccaae69c5d000000000000000000000000)", + "P->V[70856:70888]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 83385: Hash(0x7bc362dcfbe56bf4218a6f6c48824570ed6f0415000000000000000000000000)", + "P->V[70888:70920]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 83469: Hash(0x869d1d8a9c9f861cab93ac2142175162ee6471a7000000000000000000000000)", + "P->V[70920:70952]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 86291: Hash(0x557f09224370c5233ec7e790e3108224bd635e51000000000000000000000000)", + "P->V[70952:70984]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 92987: Hash(0x50071a8e63f258c451da0f893766b563cd68eeb1000000000000000000000000)", + "P->V[70984:71016]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 101721: Hash(0x8aa988062583cdb48eba43bf8b8928aee3b6255f000000000000000000000000)", + "P->V[71016:71048]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 108159: Hash(0x2a5777073a1c072ddfb4e6caae3a69f07442b666000000000000000000000000)", + "P->V[71048:71080]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 115217: Hash(0xf9af0a842ef3e68ef8c087aa51aeb0fe076f2eb7000000000000000000000000)", + "P->V[71080:71112]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 118410: Hash(0xc425b3b1315636dda26c9b5a7f99fd5011935014000000000000000000000000)", + "P->V[71112:71144]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 128936: Hash(0x6a971945105e5edeaa133092328140ec93d9b6c3000000000000000000000000)", + "P->V[71144:71176]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 33315: Hash(0x77a21d5b863743cf1b38613a339bdac8db3b03b3000000000000000000000000)", + "P->V[71176:71208]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 37076: Hash(0xa87f1ed8fe08b7589a63fc0d222213c27e6bb17d000000000000000000000000)", + "P->V[71208:71240]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 39935: Hash(0x5f1471773f4e524bef4fada921c52217311289b3000000000000000000000000)", + "P->V[71240:71272]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 40858: Hash(0x3917e7684231ced89ad0f5b0c182b2e04a4f63be000000000000000000000000)", + "P->V[71272:71304]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 41012: Hash(0x6a6552d9b29eb0b6a16233eed242722dd232df8d000000000000000000000000)", + "P->V[71304:71336]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 41481: Hash(0xb0283677b8f70dc20f4cb40078bd9b806b30562000000000000000000000000)", + "P->V[71336:71368]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 41693: Hash(0x9a500e16878da04cf0ba5d7da92d37b7e2e67dd7000000000000000000000000)", + "P->V[71368:71400]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 41735: Hash(0x6c93c747bd6cc48dfd5a60f33fa5b3aa497f971a000000000000000000000000)", + "P->V[71400:71432]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 43144: Hash(0x148794d31da0dd5d52b3897d5ff2249a19b74031000000000000000000000000)", + "P->V[71432:71464]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 46492: Hash(0xe5520be4f7a0c7c2a891d2dff16986548259d79e000000000000000000000000)", + "P->V[71464:71496]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 50861: Hash(0x3119c23b46c66217c99474ab5566dd98f46474b000000000000000000000000)", + "P->V[71496:71528]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 54078: Hash(0xbb724c85172aef893333cf9db6e2dff636f7e58a000000000000000000000000)", + "P->V[71528:71560]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 57609: Hash(0x82cb7eb17e8b976cd9a85a81cfad3d8c7817bdd9000000000000000000000000)", + "P->V[71560:71592]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 59204: Hash(0xdaa83fca1175d620b619b0fc3979ffafb65175e2000000000000000000000000)", + "P->V[71592:71624]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 64469: Hash(0xb3322d52d9e83ec76b6b4cb156a6b88e7200bd15000000000000000000000000)", + "P->V[71624:71656]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 16656: Hash(0x2405784dd77cffd539d3ed06eaa8ef3f76da2920000000000000000000000000)", + "P->V[71656:71688]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 18539: Hash(0xf30d0de7cb5077e4a7c57eab8de01c4da6870813000000000000000000000000)", + "P->V[71688:71720]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 19966: Hash(0x941cf8654ece2b3ecf0d1584128afffe1b97af3c000000000000000000000000)", + "P->V[71720:71752]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 20428: Hash(0xd56a431d25a270f4c467b042a2a37363b43a1433000000000000000000000000)", + "P->V[71752:71784]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 20507: Hash(0x29167fec77f43abd00fa687aa245283bd70ca51c000000000000000000000000)", + "P->V[71784:71816]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 20741: Hash(0x7f3064881513bc0b6e25c032fa6e0a84fbed8b07000000000000000000000000)", + "P->V[71816:71848]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 20847: Hash(0x13686eda9ebba8649bce54ed1a4469b00599c278000000000000000000000000)", + "P->V[71848:71880]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 20866: Hash(0x2d727e5329d06696fe924d1859ebd42a3b299d10000000000000000000000000)", + "P->V[71880:71912]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 21573: Hash(0x9f480a8088f8ca7e66fdac632b5ed8760aad58ef000000000000000000000000)", + "P->V[71912:71944]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 23247: Hash(0xab6abe363d6a0237c1c8ced00dc9a51121578ffa000000000000000000000000)", + "P->V[71944:71976]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 25431: Hash(0xba9e13429645f0e8311301d820c4e146b7d2af7c000000000000000000000000)", + "P->V[71976:72008]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 27038: Hash(0xbb65629e9e3c9ca7112a713794eedfd4deb47438000000000000000000000000)", + "P->V[72008:72040]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 28805: Hash(0x3d0fe63f5f401f47d1a6a545b200e26e8bab5f78000000000000000000000000)", + "P->V[72040:72072]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 29603: Hash(0xcce1262abaf25ea4c27e91b6b957221d244d0aff000000000000000000000000)", + "P->V[72072:72104]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 32235: Hash(0x43b896538c83799b3225b9ede0d43151ef2227b4000000000000000000000000)", + "P->V[72104:72136]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 8329: Hash(0x5a3a8fed0e18849ee0529b8e327cf0c45fb63ad8000000000000000000000000)", + "P->V[72136:72168]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 9268: Hash(0xb5d851b6faefa09b465110ab179c655323dafc3e000000000000000000000000)", + "P->V[72168:72200]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 9982: Hash(0xd1a21da67b5a28e68e77e0f3f3b061146a99aafa000000000000000000000000)", + "P->V[72200:72232]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 10215: Hash(0xe39339c8f2b9ea7265a43684de665a38d04621da000000000000000000000000)", + "P->V[72232:72264]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 10252: Hash(0x62155db2986616534642362224e4970b530ca87a000000000000000000000000)", + "P->V[72264:72296]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 10371: Hash(0x6d585b17918fd589f4689a26e45795e4e19bb219000000000000000000000000)", + "P->V[72296:72328]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 10422: Hash(0xd76288cc50c970efc752cd6287a058e06704b648000000000000000000000000)", + "P->V[72328:72360]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 10432: Hash(0xc0c65b4271b7f49065c1f2ed4c60a2fee75e21fd000000000000000000000000)", + "P->V[72360:72392]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 10787: Hash(0xa3c8117181a0345e2cb435cd3fa2281fdb10fd4b000000000000000000000000)", + "P->V[72392:72424]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 11622: Hash(0x117a0be665ec9441053d468bb93fb4c26c241341000000000000000000000000)", + "P->V[72424:72456]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 12714: Hash(0x94ced3ac35a2794060008ae56db0751e18173222000000000000000000000000)", + "P->V[72456:72488]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 13518: Hash(0x3bf408beb6b3863969bdfdcf8e4ccee3199f7cf8000000000000000000000000)", + "P->V[72488:72520]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 14403: Hash(0x2edebe55704bac6113a5e89325c544614debd293000000000000000000000000)", + "P->V[72520:72552]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 14800: Hash(0xd5bd257f53ea67db54c026ce27f75cada884dc2a000000000000000000000000)", + "P->V[72552:72584]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 16116: Hash(0xa8896491732d028954bcb20c59d2e75e64663a70000000000000000000000000)", + "P->V[72584:72616]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 4165: Hash(0xd28d5a81942fe09ac69281ec8e0c84bafab12a7d000000000000000000000000)", + "P->V[72616:72648]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 4635: Hash(0x433a25a4d2f7f007401a4ed896878c93598e2f9f000000000000000000000000)", + "P->V[72648:72680]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 4990: Hash(0x74c61897fed4624e78fe5c04a7b3caf486d28e2a000000000000000000000000)", + "P->V[72680:72712]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 5106: Hash(0x448ad483c48c4273008fb804628e88a2c5878172000000000000000000000000)", + "P->V[72712:72744]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 5127: Hash(0x30b583184bfd7d5f9c8dad377f12b495e30d162f000000000000000000000000)", + "P->V[72744:72776]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 5184: Hash(0x842d9bbb97cedd8e87b200e9d88388a00a06787c000000000000000000000000)", + "P->V[72776:72808]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 5210: Hash(0x2ee4c2990a060ad66a33741e8ba4cb08791cdecc000000000000000000000000)", + "P->V[72808:72840]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 5217: Hash(0x72b736b36c21a48bf798fe1c7df43c90c7cd4b34000000000000000000000000)", + "P->V[72840:72872]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 5392: Hash(0x961a94e727ab1352af5459a2ee5dabcee046b6e6000000000000000000000000)", + "P->V[72872:72904]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 5810: Hash(0x2be89ed9032bb3f0a6c6d0e10db5b359be739660000000000000000000000000)", + "P->V[72904:72936]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 6356: Hash(0x6d216eeacb9c8fc9069f71866dfb4dd2b0f323a0000000000000000000000000)", + "P->V[72936:72968]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 6758: Hash(0xc84b7a349c3be14238723aefc6bf9a1807469403000000000000000000000000)", + "P->V[72968:73000]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 7200: Hash(0xa773ff98f23094f7ea17155dfaa63538dfcd6a52000000000000000000000000)", + "P->V[73000:73032]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 7401: Hash(0x3c717a01fb5f6566516e11b07f5a164f2256c25a000000000000000000000000)", + "P->V[73032:73064]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 8059: Hash(0xa503a28d98c36d46a87662b38bee3964cfe5e25000000000000000000000000)", + "P->V[73064:73096]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2083: Hash(0x4c2a214d1de14183af0ce05b42431bec94ec14b5000000000000000000000000)", + "P->V[73096:73128]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2316: Hash(0x61b933f208de2a6e8d2e5b65ae71a0ab5ca0bc24000000000000000000000000)", + "P->V[73128:73160]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2494: Hash(0x2a22dc3fa6ac4089c233be05adfa326fe76c39dc000000000000000000000000)", + "P->V[73160:73192]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2552: Hash(0x12d0a1fe8a99b7ce1b7556336f5e1f136ebb7e41000000000000000000000000)", + "P->V[73192:73224]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2562: Hash(0x52d375e6d36a82be4edd635a768ac91a2dc25d8f000000000000000000000000)", + "P->V[73224:73256]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2593: Hash(0xf14844e404c993e7cb125375e2e579a0a61e7b6b000000000000000000000000)", + "P->V[73256:73288]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2604: Hash(0xade3c10d6ba38d38af7dfdfe1ec217f55a08646f000000000000000000000000)", + "P->V[73288:73320]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2609: Hash(0x9fc065de970ccd4f47439237bf6a3351c6902b71000000000000000000000000)", + "P->V[73320:73352]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2697: Hash(0xd9468dddd55087f543683379fd6e456622a10cbf000000000000000000000000)", + "P->V[73352:73384]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2904: Hash(0x3b6fa9d63d0e77d99f2ae8e6277cdffa9be6f43c000000000000000000000000)", + "P->V[73384:73416]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 3179: Hash(0x7fddf0a5f3156e686f911b6c5eb303f2c5acde17000000000000000000000000)", + "P->V[73416:73448]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 3378: Hash(0x38ff842c5a977151d707bac1be099931e41c5f98000000000000000000000000)", + "P->V[73448:73480]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 3601: Hash(0xc99018f351769eaf3af8ab5a3306c45fe57aad50000000000000000000000000)", + "P->V[73480:73512]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 3701: Hash(0x49121adb843d3cc322955b213c885cdbde5c2aee000000000000000000000000)", + "P->V[73512:73544]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 4028: Hash(0xd4e9b6ed9b1b93b50749ae412ae0e38c54cbfd24000000000000000000000000)", + "P->V[73544:73576]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1040: Hash(0x4a020e6748f9c38e57aa50245938de218ba6c9fb000000000000000000000000)", + "P->V[73576:73608]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1159: Hash(0x90acbe6a46cf3fb66f448833fe60da399b86b4a3000000000000000000000000)", + "P->V[73608:73640]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1246: Hash(0x60a50e8feb2871204732bdfc525592b31df2f696000000000000000000000000)", + "P->V[73640:73672]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1277: Hash(0xcb6dbcedde35d89cd83b77e6bece9a897d563169000000000000000000000000)", + "P->V[73672:73704]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1280: Hash(0x59b18a051b901383735162da635d7b85e9f0ee3e000000000000000000000000)", + "P->V[73704:73736]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1297: Hash(0x175d7ce21562969c7a45643d392fd0838c1650e4000000000000000000000000)", + "P->V[73736:73768]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1303: Hash(0x3d8a301f6153a0e08666a869798cf40c94c3d44e000000000000000000000000)", + "P->V[73768:73800]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1305: Hash(0x5d036811184df86fdcfbd3207011092d52177b3c000000000000000000000000)", + "P->V[73800:73832]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1349: Hash(0xce8ae9cb65f7dd5ef1119c0465ffcab4db45c7c3000000000000000000000000)", + "P->V[73832:73864]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1453: Hash(0x2c74dc95ac397a96ac17ba63f41250f890024abe000000000000000000000000)", + "P->V[73864:73896]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1588: Hash(0x570fee6b9b396b8fa5ab4a7f782b75fc5a497cf000000000000000000000000)", + "P->V[73896:73928]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1688: Hash(0x9caab7202a8ee8324ed0a26c6326b20f4a5cdee9000000000000000000000000)", + "P->V[73928:73960]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1801: Hash(0xe39d392ae4451df6c892a9aa313a678ccc0ad742000000000000000000000000)", + "P->V[73960:73992]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1851: Hash(0x982ed54b097f4f7759d039b43410848ba2f0041a000000000000000000000000)", + "P->V[73992:74024]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 2015: Hash(0x4c5e712a9802fb96dd54d3929a87dab39660a0ec000000000000000000000000)", + "P->V[74024:74056]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 521: Hash(0x721f30bb8298ec977f8f42efc4205c0f2cd78fda000000000000000000000000)", + "P->V[74056:74088]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 578: Hash(0x14da69be028848e37eb222fa44993f652a162a18000000000000000000000000)", + "P->V[74088:74120]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 622: Hash(0x3c81e848fbd5aad783b14ac491699dd467f774cb000000000000000000000000)", + "P->V[74120:74152]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 639: Hash(0x1879098daa3a57b263d210a4df1de21ae846db82000000000000000000000000)", + "P->V[74152:74184]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 641: Hash(0x4eff4e7e2928be6f3f7d53893a34a069e1f3147f000000000000000000000000)", + "P->V[74184:74216]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 649: Hash(0x3db2f55052724219c4887cc4ce8871ffe5459d59000000000000000000000000)", + "P->V[74216:74248]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 650: Hash(0x3c78d689d998cfdf9481b22774bc6513c358f0ab000000000000000000000000)", + "P->V[74248:74280]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 653: Hash(0x3a1f0a9a68debe30afb56ec445f17c11ce5369a7000000000000000000000000)", + "P->V[74280:74312]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 675: Hash(0x3277bc61bb7ee546506a3cd85445ae85897866d7000000000000000000000000)", + "P->V[74312:74344]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 727: Hash(0xa8f2529d98435f7085cef8d44f022c635d60e954000000000000000000000000)", + "P->V[74344:74376]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 795: Hash(0xc9d9e048856bebb8e91e917f2fe9eddff8541e0e000000000000000000000000)", + "P->V[74376:74408]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 845: Hash(0xfc9eccdd666db24f16010cf888274247ecf6086a000000000000000000000000)", + "P->V[74408:74440]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 901: Hash(0xc8600bc9b60dfdd66a109d4bff36465f0948fba7000000000000000000000000)", + "P->V[74440:74472]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 924: Hash(0x2b36a494d34a407b90083bfbdb44b275d4f54786000000000000000000000000)", + "P->V[74472:74504]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 1006: Hash(0x318d9ccdcbe5556cf8e76cae9d2e484db15ed197000000000000000000000000)", + "P->V[74504:74536]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 261: Hash(0x16307ce7151fb254df7949925e949df55a288e8000000000000000000000000)", + "P->V[74536:74568]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 288: Hash(0x9268af94f7f1be9cc2c2b142ed963ae65dca0d6000000000000000000000000)", + "P->V[74568:74600]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 310: Hash(0xbd8ac67abbd51ae1365dedd5d7128eba471cb60f000000000000000000000000)", + "P->V[74600:74632]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 318: Hash(0x6ea99754c67edaba189bb5eec91075770e61f0f2000000000000000000000000)", + "P->V[74632:74664]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 321: Hash(0x9132aba7b9911848613b16a40b36e90a62371824000000000000000000000000)", + "P->V[74664:74696]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 327: Hash(0x24bec7083bb55613e1f9830d9c18e9141f86cdfe000000000000000000000000)", + "P->V[74696:74728]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 336: Hash(0xd8f9805ca237f5103210ed568555ebbbf9ba079e000000000000000000000000)", + "P->V[74728:74760]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 362: Hash(0xefc5fe3635ea9a9f94b9dded6e377b0fb28be0d4000000000000000000000000)", + "P->V[74760:74792]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 396: Hash(0xe49d1632c0e1a0ee2685456b65304d309383ea45000000000000000000000000)", + "P->V[74792:74824]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 423: Hash(0xcab35575af3e1b00a9d20f96950a32fd95273504000000000000000000000000)", + "P->V[74824:74856]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 451: Hash(0x9a92c2fd786916a93d093842f77e578093f31d62000000000000000000000000)", + "P->V[74856:74888]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 463: Hash(0x505d4ce8a87ae5bf9cd31675fc5f9561ac9a9d95000000000000000000000000)", + "P->V[74888:74920]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 502: Hash(0x38abc71f9d0e9135a2697077f56fbc4c8fccdb92000000000000000000000000)", + "P->V[74920:74952]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 131: Hash(0x4f6118afc70e3c82e49f7775bc4301b89d3749ca000000000000000000000000)", + "P->V[74952:74984]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 145: Hash(0x612fd2664348aced060c901345f82a45fc37ae7f000000000000000000000000)", + "P->V[74984:75016]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 154: Hash(0x231e6882aa652669ab4882914be7190c94f71717000000000000000000000000)", + "P->V[75016:75048]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 158: Hash(0x54c65ae1f609db9395658d817503d13e849af586000000000000000000000000)", + "P->V[75048:75080]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 161: Hash(0xc0b92aa16504f0efad3363dd8e6fc171bcabc0e8000000000000000000000000)", + "P->V[75080:75112]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 169: Hash(0xc58c7fe46927fc07e2bf994f4dc8d7cdb742b0c6000000000000000000000000)", + "P->V[75112:75144]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 180: Hash(0x80ad66e14f31c6e469f37e515ffd23e90029e6d4000000000000000000000000)", + "P->V[75144:75176]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 199: Hash(0x5c63952676b399e26f2721dbdab0d062b3c54cdb000000000000000000000000)", + "P->V[75176:75208]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 210: Hash(0xcd7c4dba794c7bedbac5b1519c22359e35cbe585000000000000000000000000)", + "P->V[75208:75240]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 224: Hash(0x60d1131788a31e2fbf200d7da65978f38c70c3b8000000000000000000000000)", + "P->V[75240:75272]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 230: Hash(0xbb35b06528f8e63f9cded3dcf650975efc6010a0000000000000000000000000)", + "P->V[75272:75304]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 250: Hash(0x8f59351f172830f81fee023f853d01abad0b9904000000000000000000000000)", + "P->V[75304:75336]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 64: Hash(0x2e728a66720faceafd6f4456ba7bcdc76c7d0165000000000000000000000000)", + "P->V[75336:75368]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 73: Hash(0xd3c390da72824c39db58b014870597f096a0d9a1000000000000000000000000)", + "P->V[75368:75400]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 76: Hash(0x7328ead403e4ec1ab9e17a23ac6b65ed8fb47a00000000000000000000000000)", + "P->V[75400:75432]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 78: Hash(0x9a55a86ad6dc9dba6aa53a8d7943e6ba390380c7000000000000000000000000)", + "P->V[75432:75464]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 85: Hash(0x6d9a4a87d1daa0c9d02bcde01db66f6a8049dc59000000000000000000000000)", + "P->V[75464:75496]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 91: Hash(0x2c39123755a6d1bbed786c4ba33b3c4ea9cb0d63000000000000000000000000)", + "P->V[75496:75528]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 98: Hash(0xace297f7a0b3ef7d26103c34f59d4622a4f380be000000000000000000000000)", + "P->V[75528:75560]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 104: Hash(0xbae0855c61ba63cf302b27f70021f3f96e6778b6000000000000000000000000)", + "P->V[75560:75592]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 113: Hash(0x3bf0876d1241299a8ee49dcef78c6b9da274cdbf000000000000000000000000)", + "P->V[75592:75624]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 114: Hash(0x893706f5d1a549d5d0e2b98adf53720312b853d7000000000000000000000000)", + "P->V[75624:75656]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 124: Hash(0x7c11d533902a198332cf2bb49a532ccf7765e501000000000000000000000000)", + "P->V[75656:75688]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 33: Hash(0x2f86d0b2890c50d2433f26f3e57e76b203a8e30a000000000000000000000000)", + "P->V[75688:75720]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 37: Hash(0x88ffaad4b09d5bd603b3740b84bfab50019b88df000000000000000000000000)", + "P->V[75720:75752]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 41: Hash(0xf1234835f13b372e0f578c8aa60934d106ed4bf5000000000000000000000000)", + "P->V[75752:75784]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 43: Hash(0x5ff41a6d5a4ce9fa89f8b7f28479ea9fc44430dd000000000000000000000000)", + "P->V[75784:75816]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 44: Hash(0xa1c72ad5c6ea8700c8a85b0e6587464e408ba578000000000000000000000000)", + "P->V[75816:75848]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 48: Hash(0x9f403f39d8c9a586a97bd0cf1354de0f5f4a9fba000000000000000000000000)", + "P->V[75848:75880]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 53: Hash(0xa9a48db0347874dac7aecfc65a2c9f342fe1b511000000000000000000000000)", + "P->V[75880:75912]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 63: Hash(0x55116e24235c0018c891dfedeeffa415b28ca01c000000000000000000000000)", + "P->V[75912:75944]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 17: Hash(0x6c96da14baea66df00d3191a3a0af1e465ce3ecf000000000000000000000000)", + "P->V[75944:75976]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 23: Hash(0x420de8ccb12ae0452bfd77c3f15e3f428777de8f000000000000000000000000)", + "P->V[75976:76008]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 25: Hash(0xb4b979a21ca29235a3fcd99adb56ff5b4da03709000000000000000000000000)", + "P->V[76008:76040]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 27: Hash(0x788937895ca255a9f68e3fd11bae842f5cfe2f23000000000000000000000000)", + "P->V[76040:76072]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 29: Hash(0x6d407f16ff70007c77582429ab491d183993b4c9000000000000000000000000)", + "P->V[76072:76104]: /cpu air/STARK/FRI/Decommitment/Layer 2: For node 30: Hash(0x2f8b2ba8a494c7f0bece1e07fc102d488492ff6e000000000000000000000000)", + "P->V[76104:76136]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 273, Column 0: Field Element(0x707da5be239481204987154dcce9b454d361fb866a867134bf8929f121f552f)", + "P->V[76136:76168]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 273, Column 1: Field Element(0x168e795e329834c4b3f4741e8e8be2d9889d6a94bb3ce7e4c0cf2fa047df9e2)", + "P->V[76168:76200]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 273, Column 2: Field Element(0x1524f8b8414a6a99cfdd9caba35a58d044a5c60e204605a2e9e3fdabf232bb)", + "P->V[76200:76232]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 273, Column 4: Field Element(0x2c66e6352a14571a819c47d86730b949a263d666fcaed3da897b3661c6b1f6c)", + "P->V[76232:76264]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 273, Column 5: Field Element(0x372761e68bf816a83fc575e11b17155cc8be84146551a2bed4a74a662f27a75)", + "P->V[76264:76296]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 273, Column 6: Field Element(0x2d2e1e8cced1e2da1c0fbbad9a1500ec1221f974b37eb325e5a46abb6380895)", + "P->V[76296:76328]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 273, Column 7: Field Element(0x399000cd4a8f206b8a6af7b68a3d305db9172b6a5d9fc28823c558125c030e8)", + "P->V[76328:76360]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 2154, Column 0: Field Element(0x67db890951e39caf1a5455c5b0bf3040527b35d62db611d7ffd497cafab287f)", + "P->V[76360:76392]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 2154, Column 1: Field Element(0x10a0e9aa50e59a534854da0e9b70a4eaa734715d32498d4e79dd622f555a10c)", + "P->V[76392:76424]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 2154, Column 2: Field Element(0xb102d8ea620a3cdc99da8a3a614e7ae0a4288d29fed587ec1b9627617158ba)", + "P->V[76424:76456]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 2154, Column 3: Field Element(0x70eb81303629d0dbdd3a11435bb95c3dcfc21169d12339fbe94a43b38a3817b)", + "P->V[76456:76488]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 2154, Column 4: Field Element(0x65febd6e6a15ff14993438c3078bbcb6d80c3b1e41f75a07e1213ea6ae6f2fe)", + "P->V[76488:76520]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 2154, Column 6: Field Element(0x6a41d3e41b4c4aef51717f4b88b6ebd4d6570c51ea6185e77682f5654674a71)", + "P->V[76520:76552]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 2154, Column 7: Field Element(0x45b21c2e771c75f4e2902819918499e1d035d4bbd6e831ac5c670c44c8d39af)", + "P->V[76552:76584]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 3583, Column 1: Field Element(0x6fae46569a8dd87ac7bca826eb0ac8892323f7b71fe5c7f0b06a61a2f4f3235)", + "P->V[76584:76616]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 3583, Column 2: Field Element(0x61451f5e747578c4fb35b29fcfebb55455ef7b8489a184c29b70b2175a0d05d)", + "P->V[76616:76648]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 3583, Column 3: Field Element(0xdb18c2ff4ba04a87bf075f086f47c6d894a669191fd4af59620bf4534b14e8)", + "P->V[76648:76680]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 3583, Column 4: Field Element(0xafaf3861ed0bf176fe0f3c36c130812d2da5c90f38154d67e43f6df4698f38)", + "P->V[76680:76712]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 3583, Column 5: Field Element(0x49b84b814984e95dae3f1f34fe4b169ffd4b521f25eb500800a1e189f3fc671)", + "P->V[76712:76744]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 3583, Column 6: Field Element(0x3b76768da3572d748cf18dd0df61347dd61a2b9c6c1668c32bda0330c51e2d)", + "P->V[76744:76776]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 3583, Column 7: Field Element(0x557fef53bfd25d8d9646e18976ddac6ff5f5dfb3ddb00a439551c3499a3a0fa)", + "P->V[76776:76808]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4045, Column 0: Field Element(0x6e04814b584cac4c69ce4ea2c20719b43ee35d58345666c2cd18b5904046fc1)", + "P->V[76808:76840]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4045, Column 1: Field Element(0x409c67613e8595931637f5a66890243d9503bfe86cac7bcb35662c03135695d)", + "P->V[76840:76872]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4045, Column 2: Field Element(0x320c09025e8166dd86a65f3b000363c222d72297d246c384e9907fc8d3cbcc)", + "P->V[76872:76904]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4045, Column 3: Field Element(0x251222b2f09b836695c613ae19ff84e13010bda20657035af31468b933f8f4b)", + "P->V[76904:76936]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4045, Column 4: Field Element(0x1999088baa9fea471ae4466a47c516f85d58f4fb83f69d26d912aaa6eafe085)", + "P->V[76936:76968]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4045, Column 5: Field Element(0x2545f1a3e299b036300c18bc6f7b6d0be2cb20bcd409637bcbfef940e203c96)", + "P->V[76968:77000]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4045, Column 7: Field Element(0x3db85791c7defc56cb7031619d1378fda04b60527cbe59e145c7a0c9c173e2b)", + "P->V[77000:77032]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4122, Column 0: Field Element(0x68db960d5074f65cda07926e8a841238d055060ad8713d29dffc32b8194dc3d)", + "P->V[77032:77064]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4122, Column 1: Field Element(0x5dfef6a424f838123563572732d7097f7e59579d069030984b15d6eb55bbccc)", + "P->V[77064:77096]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4122, Column 2: Field Element(0x74b7a8ea40854459c8bb3b18be7bc9927b0883f315889aca968b1fc49012a5a)", + "P->V[77096:77128]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4122, Column 3: Field Element(0x3dfa159654bf3a3f83a701e588660177573172f99a1d663f9e9d428485661e9)", + "P->V[77128:77160]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4122, Column 4: Field Element(0x5a0631fe0ca4a783b5bb3e52142565b76040086390df28a184e21879b45443b)", + "P->V[77160:77192]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4122, Column 5: Field Element(0xe918a0b5dc13c82bf3eb30738e26d5ea5e586db57f64cb1bb4332affd2fb55)", + "P->V[77192:77224]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4122, Column 7: Field Element(0x3d8256e41c44d7fc6d2a8ae48374a08817b8a2381614756f93fba1c2466b3b1)", + "P->V[77224:77256]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4356, Column 1: Field Element(0x33fd75769bd4a3809a4a63d6afba8e9c86abfd78eabc96779f32d72c78a15db)", + "P->V[77256:77288]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4356, Column 2: Field Element(0x3f765acff321999df050713f42a12fa5ba69ae9128bd3180e0d6f3d17d3bd36)", + "P->V[77288:77320]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4356, Column 3: Field Element(0x570720ca21723e9583a834de1e13e90c563136a21f02d8fc365b28a016b6c3e)", + "P->V[77320:77352]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4356, Column 4: Field Element(0x1cc418a224e2a5f4cd77ee3086f081314cd22652674833aa29057d7ba20ac03)", + "P->V[77352:77384]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4356, Column 5: Field Element(0x587d459928aca85db247e6d80fe2a1dc0047d7c5c01641a946da0d623d874c2)", + "P->V[77384:77416]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4356, Column 6: Field Element(0x33c3d3d4f46a495be0e9a38f0bdd94139ed34bbe3f2dd90e2a0fc5d802f3a6b)", + "P->V[77416:77448]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4356, Column 7: Field Element(0x118a6cd26d908e8a12afeb2d0c8ca2aff7001e3cfea4b4a73d327648ec3e4d9)", + "P->V[77448:77480]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4462, Column 1: Field Element(0xffc4e6774c9811f4b53b643577c2b6c9ee9c9e6934229df320300454d56ecf)", + "P->V[77480:77512]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4462, Column 2: Field Element(0x3706f5c85a159835b8ebabf2f6e2480e4b03310909ce7cb23c1e6e80d5c418e)", + "P->V[77512:77544]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4462, Column 3: Field Element(0x71ffc0958bd218693b8a86c3e6ab10e5d7afbbe17e2a5b7c3c0233a032e663d)", + "P->V[77544:77576]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4462, Column 4: Field Element(0x79a3496fd1a5bd5b3efbfb85ea6ade8b94b331609f3f4d417d535b7c1480f7f)", + "P->V[77576:77608]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4462, Column 5: Field Element(0x63bc8b20c88be1192d87e3ceead8b24d3accd548332ec9ad6d783d4902ae31a)", + "P->V[77608:77640]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4462, Column 6: Field Element(0x3df7eb58b46c89ec137ae642917767f3c02892e5983610a2e875f816cbabe92)", + "P->V[77640:77672]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4462, Column 7: Field Element(0x6b2a7ee87e2b753b85c3172cc437eb3220d1cd98d0ef50423082afc423174a7)", + "P->V[77672:77704]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4483, Column 0: Field Element(0xb1591ef52317aabdcf67f22826833c8586aeb73aa538ac118f310597415619)", + "P->V[77704:77736]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4483, Column 2: Field Element(0x3cf6386e461f43bdd3b2b0be87b8374261dc1a5c3443d5dc0e2c88a7c17acb9)", + "P->V[77736:77768]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4483, Column 3: Field Element(0x6cc1bf5a2f64ce8591fe70b2d6f8e97683af0a3ced49d55d3581fa85f129eb2)", + "P->V[77768:77800]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4483, Column 4: Field Element(0x63f83a550b905f956d95ac318fb0db47a856b6d863f591f4637a16ec17bed67)", + "P->V[77800:77832]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4483, Column 5: Field Element(0x58c8e207220eb5ee6a0b11a3607e7d3b0b789fb84052772ff3793d72d930657)", + "P->V[77832:77864]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4483, Column 6: Field Element(0x4e562e0ce2d92e5021d7c05c396daaf4f88de30982517d54dc858ee6eb5a447)", + "P->V[77864:77896]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 4483, Column 7: Field Element(0x3403db9674b29bad6f6d5d257da8020282472c77ac8bffed9d605eb3da81a64)", + "P->V[77896:77928]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 5188, Column 0: Field Element(0xd5f70f0c78063a3bee0a383028fd0443db8f0f40b4344ceb579ae3547d4506)", + "P->V[77928:77960]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 5188, Column 1: Field Element(0x65bb4f8c52ede0df19e2db9160b4a9cd0e5069cbceaa657fa16e0daf173647)", + "P->V[77960:77992]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 5188, Column 2: Field Element(0x504e267a3f435986a81ff10dd9cfaa86ab0675b350435e055d6a41f55c1953b)", + "P->V[77992:78024]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 5188, Column 3: Field Element(0x6a7bfb529909aca801128251d27ecbf4b3c9109281be05e80e3892fd1ac84bd)", + "P->V[78024:78056]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 5188, Column 4: Field Element(0x4d86e03101e75a0ad1eeb1a4820a67d6564716d2748fd7a8bf2392ed9171fad)", + "P->V[78056:78088]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 5188, Column 6: Field Element(0x3bbb294f3128484f562ebbb47255f95a9eb6aec580ef4479e6d57c3ceb9f044)", + "P->V[78088:78120]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 5188, Column 7: Field Element(0x3fde0387f864261b155961837010b3d66cad8b41a6854c8fa7b1d5ed9bfa83a)", + "P->V[78120:78152]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 6862, Column 0: Field Element(0x7ee15afb3b8f5a3384cbd5b8d2047e701f13110711c930461b79ff9d416107a)", + "P->V[78152:78184]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 6862, Column 1: Field Element(0x6e2907662724a4251def8977660f8c8a1869e7c3857e0ad0acb1aed8e6ba471)", + "P->V[78184:78216]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 6862, Column 2: Field Element(0x1219041cb112a3702d8e8a26c7fe3f36d68dd38cff3603dfcc253ec6a388005)", + "P->V[78216:78248]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 6862, Column 3: Field Element(0x660055195db10137f7089b3c5a414f4f5333dd1ee426c135a6dae37603f9a22)", + "P->V[78248:78280]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 6862, Column 4: Field Element(0x50a16c4a255ced5471fe67fe823cb3d82919b63c9a5f9cfbbdf79b3a2a7ccf4)", + "P->V[78280:78312]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 6862, Column 6: Field Element(0x7f0149948edc6131275f01e30c2c7afd3645ae6266f33c45bb09eb643f7f3b)", + "P->V[78312:78344]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 6862, Column 7: Field Element(0xa0d74f21dfce09bfca8253a4017767c349a802b7078f7f648e079884c8da34)", + "P->V[78344:78376]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 9046, Column 1: Field Element(0x609c8cf97aee4c7330d5a11c9264b0b1edd6cb454634ce47b96a413cb546cfe)", + "P->V[78376:78408]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 9046, Column 2: Field Element(0x63ce8e6a90995a04aeff2a67b8ccf70e8682fa2c608870b1dff7c91a00a47da)", + "P->V[78408:78440]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 9046, Column 3: Field Element(0x3253d8984459f819fbb7e8fbe36b07f4caa7e69c58629b96d4c538d3b3ad68f)", + "P->V[78440:78472]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 9046, Column 4: Field Element(0x62058747064786a2277213e1f934143410b6fe49c5e978df7b4260cad5a369b)", + "P->V[78472:78504]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 9046, Column 5: Field Element(0x579aac93cf6c0e09049a81f3993fab89a0403adadbb22257e67a676e7bb2759)", + "P->V[78504:78536]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 9046, Column 6: Field Element(0x1ce68f6f1981f56e7fd3bdf5528b9b09104e5c7b2c17908f2fe628f71407639)", + "P->V[78536:78568]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 9046, Column 7: Field Element(0x18b29383cc96c0c8de4669cd280234a273d19b6ae5f9e36891b6ad54699055f)", + "P->V[78568:78600]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 10655, Column 0: Field Element(0x1107a69dff33cc4f6aba9ecbf10b010b8351ea4ae925695483902dddf551e74)", + "P->V[78600:78632]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 10655, Column 1: Field Element(0x2977ad0c831ebf695490debe2b9861f64fce33bde315f47bb84e9c946d2c2f1)", + "P->V[78632:78664]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 10655, Column 2: Field Element(0x6712598e13d7b9a38425663443e1ee739a6dd1f1e4999b9c8fc93053d8a0d0)", + "P->V[78664:78696]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 10655, Column 3: Field Element(0x4804a48629c1c59af32448aea8ad267055f92c02beaf7779224aeb99cdcbc31)", + "P->V[78696:78728]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 10655, Column 4: Field Element(0x596678bdac2f5999bce9f9a1387599b4b46c73ce8ae7592bdc7fce2bf924c0e)", + "P->V[78728:78760]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 10655, Column 6: Field Element(0x62f8110b0b74953c8bbf7b3ae1f8d731d52c2b5acee5d45a3a51d47ae2c5eb9)", + "P->V[78760:78792]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 10655, Column 7: Field Element(0x7d15b1ab9cab14716c0a041ffd84f6f609e91386de75a894251615349bb9929)", + "P->V[78792:78824]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 12420, Column 1: Field Element(0x598394940ab269953e70799646cdcdee56cdc30b44288ea3c7f983b4b76ffc6)", + "P->V[78824:78856]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 12420, Column 2: Field Element(0x304c5279236d6f6cf03b87c83c4dbf576a2721b8f6dd27a7611e213aeb8dc5f)", + "P->V[78856:78888]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 12420, Column 3: Field Element(0x53b69604c6a150eb87b486d12b8bd99c23a538fe5232b39b7a1dcb2926d77a)", + "P->V[78888:78920]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 12420, Column 4: Field Element(0x18e7b12dc281591ed5875589beb740412b0218b3227a2b55b3b005645a14588)", + "P->V[78920:78952]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 12420, Column 5: Field Element(0x656ff540d6b5ef542944407d7b14575fb14311ab5070c00a91d0c4c8eddf8f2)", + "P->V[78952:78984]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 12420, Column 6: Field Element(0x6ed7ee2182a33fd897fccaf5cabc3434aa37d4ff9c63a83523efdfb8400a31c)", + "P->V[78984:79016]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 12420, Column 7: Field Element(0x4ff0c0224d95e390cb782672b483a59525f9dbe0edee582fb37f79da2d35668)", + "P->V[79016:79048]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 13218, Column 0: Field Element(0x5aca84d72b2e1b54a8138ebb1bf4f6a2416c65646dcc0c4ed04ee971d80d656)", + "P->V[79048:79080]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 13218, Column 1: Field Element(0x6679681b63b557da00da7ce1e7e47adcbcdacd7ac9e8012289561c97a70a6a6)", + "P->V[79080:79112]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 13218, Column 2: Field Element(0x6c6a24b87106534371fc4d324b75373e7f4f752f3f9e4e683fc2d732cd09e19)", + "P->V[79112:79144]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 13218, Column 3: Field Element(0x2f92d3526b3e948dba754dc85b282f19c8ec67d6ad91ddd9d05f034a7774e2e)", + "P->V[79144:79176]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 13218, Column 4: Field Element(0x3b71bf374f06e146831f093711578a2469e004f106e2fd0252e6f49be5819bf)", + "P->V[79176:79208]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 13218, Column 5: Field Element(0x4d8c66674fc4c58ef32a7306374ae82cd1d007b779a7e62996bbfd5b556ed05)", + "P->V[79208:79240]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 13218, Column 7: Field Element(0x57d9b35b573fea90ba221f82ec17ac722cdfee01dbd48cb893e807ba0d9358d)", + "P->V[79240:79272]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 15850, Column 0: Field Element(0x2bce721b619e6cfa3eb951f268b2f99bf550309ffc4f36f2eec3b14b3156818)", + "P->V[79272:79304]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 15850, Column 1: Field Element(0x3bd464264e35b89c95966972848b88fa5bf5223d6169539c40bdd286af9f1c6)", + "P->V[79304:79336]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 15850, Column 3: Field Element(0x6ee1291b9836bc42c0aae49f973946a62e070fc8473b5cde76be3e14f63c11b)", + "P->V[79336:79368]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 15850, Column 4: Field Element(0x1a6941f0fe970baf313e221e842ebf20d5b2888ba7e7e4e1af223dbfbadaed9)", + "P->V[79368:79400]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 15850, Column 5: Field Element(0x5415a6a3f1ebc2d9841a5162b4565280c5dfa297805b8b901626821c65cfe26)", + "P->V[79400:79432]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 15850, Column 6: Field Element(0x5f679d4b579cca7552e0af5af06e8f7f42bc41f20517444b8719047fe72c5d3)", + "P->V[79432:79464]: /cpu air/STARK/FRI/Decommitment/Layer 3: Row 15850, Column 7: Field Element(0x54608e345abfd7a4dd881c617231d4d46e8433f9f4d52de9f5bc028e05bcd47)", + "P->V[79464:79496]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 16656: Hash(0xf3ec345653daf1212544bb4c0d7a23f49a46e76000000000000000000000000)", + "P->V[79496:79528]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 18539: Hash(0x18b1c3e3d7c85d74e01f866f30dd32b2a57db2cf000000000000000000000000)", + "P->V[79528:79560]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 19966: Hash(0x9b91166b028b4873c54f2d4dcdc3e63f07ba6377000000000000000000000000)", + "P->V[79560:79592]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 20428: Hash(0xdd600f9c13e98bef83fe4255407c74ed01448b3c000000000000000000000000)", + "P->V[79592:79624]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 20507: Hash(0xf39095630fca3b4859dd92a1bd4995867590159f000000000000000000000000)", + "P->V[79624:79656]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 20741: Hash(0xb1e7a73d1adf88df390a69e308405a2577fec6f2000000000000000000000000)", + "P->V[79656:79688]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 20847: Hash(0x2bc129ca178217ec5bf19fea8d7797188a917f22000000000000000000000000)", + "P->V[79688:79720]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 20866: Hash(0xfc283a3d702c4e3813d33cbe8121908e968ad7b6000000000000000000000000)", + "P->V[79720:79752]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 21573: Hash(0x7ed01f520b66894a93b52837deba990576673794000000000000000000000000)", + "P->V[79752:79784]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 23247: Hash(0x76491be113edc810e8cce7f4d63e14f9c4a1e895000000000000000000000000)", + "P->V[79784:79816]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 25431: Hash(0x1ec4cda48b6cb461faee32ed49743360ec2b5977000000000000000000000000)", + "P->V[79816:79848]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 27038: Hash(0x615ebf11265b52f584167dcf670a61a79bb03444000000000000000000000000)", + "P->V[79848:79880]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 28805: Hash(0x18c89d000d5bf5a6faf45823378c7fa2d1e7447a000000000000000000000000)", + "P->V[79880:79912]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 29603: Hash(0xfc49091773266e9033b360405209668c3be6adf000000000000000000000000)", + "P->V[79912:79944]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 32235: Hash(0x89d6c88aabbc0faeebb4c1f6a326e6584932304000000000000000000000000)", + "P->V[79944:79976]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 8329: Hash(0xf9afa45e21806f5c19f443d91217aef4ac67ec27000000000000000000000000)", + "P->V[79976:80008]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 9268: Hash(0x9d0c0e8582688ae31d91ef06b74fd9a3a2c83990000000000000000000000000)", + "P->V[80008:80040]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 9982: Hash(0x786564ca9cf0dbb3798f9c3042892ea67bb94cff000000000000000000000000)", + "P->V[80040:80072]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 10215: Hash(0xb63e9472247a4e836b80b6982e69ca8b81f8a3fb000000000000000000000000)", + "P->V[80072:80104]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 10252: Hash(0x33232cf044a9ad0892589fbfd445abdae5b0e6cb000000000000000000000000)", + "P->V[80104:80136]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 10371: Hash(0xa359f39ca46f23bfb4cec1af3d5bb87dc2648c39000000000000000000000000)", + "P->V[80136:80168]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 10422: Hash(0xea6f10ec99058dfa7f47f98edda81e3ba683e5b2000000000000000000000000)", + "P->V[80168:80200]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 10432: Hash(0xba543bc0168ca06ea355b6d534c5e5bed888fb09000000000000000000000000)", + "P->V[80200:80232]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 10787: Hash(0xc77ed813fc8f8b6c3530bc72cc7f997ffa6e5dca000000000000000000000000)", + "P->V[80232:80264]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 11622: Hash(0x35b96ae855f17d7f164fe890a6b68e0c4574c5e2000000000000000000000000)", + "P->V[80264:80296]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 12714: Hash(0x140178042b676aceb32582480faa30e7384002e6000000000000000000000000)", + "P->V[80296:80328]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 13518: Hash(0xde5ae1837c8459170ca0a4da7b8da1ed24c5b8b9000000000000000000000000)", + "P->V[80328:80360]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 14403: Hash(0x76ef67eccf5eefdfebc0d2370f9d80eae083ec42000000000000000000000000)", + "P->V[80360:80392]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 14800: Hash(0x65a3f51a320c44785b7830e6b955c8c836be68d2000000000000000000000000)", + "P->V[80392:80424]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 16116: Hash(0x181131313ae8aa972e2a7fd43f4cbeb33d71da45000000000000000000000000)", + "P->V[80424:80456]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 4165: Hash(0x5c94c2065033c049042327cc6202be88dd98cbe3000000000000000000000000)", + "P->V[80456:80488]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 4635: Hash(0x7f3d0e1a040127f1eab252a932ac3a0f299e9d30000000000000000000000000)", + "P->V[80488:80520]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 4990: Hash(0xd84b2311f4836a9c3ed878354a4bcad3e81d3353000000000000000000000000)", + "P->V[80520:80552]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 5106: Hash(0xcc23ffd7f16ca1c2b8bf4eeb2845f57c82bed1bd000000000000000000000000)", + "P->V[80552:80584]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 5127: Hash(0x3a86d71788ff5467c44e167c505d6ca939d85554000000000000000000000000)", + "P->V[80584:80616]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 5184: Hash(0x8368a2a56817322d5387ddaec212d089fb945f44000000000000000000000000)", + "P->V[80616:80648]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 5210: Hash(0x120167e723e213b756dd49a1b6a2b9110b1c9be000000000000000000000000)", + "P->V[80648:80680]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 5217: Hash(0xb1b5fbe77cbf3f0dbb988cfaf68582a0af482a5d000000000000000000000000)", + "P->V[80680:80712]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 5392: Hash(0xa26408d3139f4578d8263a0468743b090f44a92e000000000000000000000000)", + "P->V[80712:80744]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 5810: Hash(0xaa355023c7ca903a09b5addbcb94a11376847c46000000000000000000000000)", + "P->V[80744:80776]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 6356: Hash(0xff0dc053f4a67f8faccdfecf2846dd8549111443000000000000000000000000)", + "P->V[80776:80808]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 6758: Hash(0x1c8b685416133efb6471ff6a87c96d67afe6d63e000000000000000000000000)", + "P->V[80808:80840]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 7200: Hash(0x348ab066c23fa9ac371983b9f52cffcc063bf541000000000000000000000000)", + "P->V[80840:80872]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 7401: Hash(0x3b9289aa9c92bc3ca9bf622a4f145f82e7a0c66b000000000000000000000000)", + "P->V[80872:80904]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 8059: Hash(0x9c3dc7a9204b360fb12f5dbb82843fcb3a37e202000000000000000000000000)", + "P->V[80904:80936]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2083: Hash(0xcb729e0e83c1b327a576ca2ac51d7154c5ec9b75000000000000000000000000)", + "P->V[80936:80968]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2316: Hash(0xbcc833fb6b54e63138cb73ac1b35a43c61bc210a000000000000000000000000)", + "P->V[80968:81000]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2494: Hash(0x9835c8aed688c7c545629ba72f8b552907ffd63f000000000000000000000000)", + "P->V[81000:81032]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2552: Hash(0xe42d1a37ae1b821b35a29e716363876bef2bd636000000000000000000000000)", + "P->V[81032:81064]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2562: Hash(0x5298d564aaa908d4664c1c3962a6a63aed076e2a000000000000000000000000)", + "P->V[81064:81096]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2593: Hash(0xfd038dd2978ca375457f4bad202827dea6cffd1b000000000000000000000000)", + "P->V[81096:81128]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2604: Hash(0x52c8fb0ffce94886e1f1cab74f1b49d4ff2f5c83000000000000000000000000)", + "P->V[81128:81160]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2609: Hash(0x359c4de4d9eee2f931d0f92419b3c1d07d8d4214000000000000000000000000)", + "P->V[81160:81192]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2697: Hash(0x9fe51eda676184563868e09b4146a19da6287736000000000000000000000000)", + "P->V[81192:81224]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2904: Hash(0x45a8167c13d05aaeea17c56b3832c88334a3fcdd000000000000000000000000)", + "P->V[81224:81256]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 3179: Hash(0x9e4c881c5bd99ac0670b6b7813f0be3ac57a2a69000000000000000000000000)", + "P->V[81256:81288]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 3378: Hash(0x799314abb0b06f951bef0d4ec9abe322fecdb324000000000000000000000000)", + "P->V[81288:81320]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 3601: Hash(0x5a18ec4249f4b50dfee9605210d7837b088a4be1000000000000000000000000)", + "P->V[81320:81352]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 3701: Hash(0xe8f2cd75b059ab32a0931aa8fa918df2b1fb7e02000000000000000000000000)", + "P->V[81352:81384]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 4028: Hash(0x160c4758e421de8a66bda42697dd42e1ef086e95000000000000000000000000)", + "P->V[81384:81416]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1040: Hash(0x4feec51df951b3b754490c93631f92e43fad666000000000000000000000000)", + "P->V[81416:81448]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1159: Hash(0x9687823a40c4c797710013257fc6f9de95248b07000000000000000000000000)", + "P->V[81448:81480]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1246: Hash(0xfc6ee7ad302026d0f5082d4ff99f2f4d70c03373000000000000000000000000)", + "P->V[81480:81512]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1277: Hash(0xc9ad970327ee7c81498f5e58964d7d52db7166ec000000000000000000000000)", + "P->V[81512:81544]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1280: Hash(0xab46ddf30683538363b84e6ac4950b681d7d873f000000000000000000000000)", + "P->V[81544:81576]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1297: Hash(0x670f6bba4b2f8361aa93023b0a111dbc51b7666e000000000000000000000000)", + "P->V[81576:81608]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1303: Hash(0xd61f5074809c41621d046e965ebbb3fdef271c93000000000000000000000000)", + "P->V[81608:81640]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1305: Hash(0x86b3015fd58f1b3c1077d4ddfded627ac4bb924a000000000000000000000000)", + "P->V[81640:81672]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1349: Hash(0xb9004c10795e8fa7d8572ae5837f37ab5e83e038000000000000000000000000)", + "P->V[81672:81704]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1453: Hash(0xeeab0d56e0c9c6eafde72f9082b51449f07d8406000000000000000000000000)", + "P->V[81704:81736]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1588: Hash(0x4c497f7aebc0ea85a1a21ce5fb7abc490ffb5644000000000000000000000000)", + "P->V[81736:81768]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1688: Hash(0xb664be342a556fc055a402dc0b59107d0b6af15000000000000000000000000)", + "P->V[81768:81800]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1801: Hash(0xc5ec321f7a7a0b21aaf1dcad9a6277d0714d06d0000000000000000000000000)", + "P->V[81800:81832]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1851: Hash(0x24a5ebfbce31432f570792c9e790be7c69c80da0000000000000000000000000)", + "P->V[81832:81864]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 2015: Hash(0x67da05a443db45a2863de39701987b847a16970d000000000000000000000000)", + "P->V[81864:81896]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 521: Hash(0x59a223e7e140dcbf881409913135b57919a57a17000000000000000000000000)", + "P->V[81896:81928]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 578: Hash(0x53ec892c1256e6827687af13cb8786cd6ab679b4000000000000000000000000)", + "P->V[81928:81960]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 622: Hash(0xb638ea4724158e4a1406a48a1b8821c0c7f73af4000000000000000000000000)", + "P->V[81960:81992]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 639: Hash(0x34c5cfcc610b558d22adaa4b643ea0ca38a290a8000000000000000000000000)", + "P->V[81992:82024]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 641: Hash(0x936fa967541d9c599fc2289e1bfb3857ca5296e1000000000000000000000000)", + "P->V[82024:82056]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 649: Hash(0xa8333db825e515813f6e9c232f951517082ff006000000000000000000000000)", + "P->V[82056:82088]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 650: Hash(0xa2bc0a8edd10de053daab557e7d6db525d1327b4000000000000000000000000)", + "P->V[82088:82120]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 653: Hash(0x96a42d89f84a974123dfd5ef4fe898926c3585a2000000000000000000000000)", + "P->V[82120:82152]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 675: Hash(0x7f3647a28925da77c177a5b58bb921260e6f19fa000000000000000000000000)", + "P->V[82152:82184]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 727: Hash(0xe15a02d225deb910afe5471b2459fb9cccf32da7000000000000000000000000)", + "P->V[82184:82216]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 795: Hash(0xce5f7e90a61ec58e03f7a74b6201155ab3a55f5d000000000000000000000000)", + "P->V[82216:82248]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 845: Hash(0x1e33321f57a3b21417a2a569468328cfcbee58dc000000000000000000000000)", + "P->V[82248:82280]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 901: Hash(0x2b40c3c22087292c2dbcd4e5d0c47856b7088ad6000000000000000000000000)", + "P->V[82280:82312]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 924: Hash(0x593b0772b2c356bae079b78ed3fcc8371e664eb2000000000000000000000000)", + "P->V[82312:82344]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 1006: Hash(0x7ef727d904e25d1558300d4d94feabd198cd3821000000000000000000000000)", + "P->V[82344:82376]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 261: Hash(0xef8cae5c0012d0499810cbe3cca1063d290c16cf000000000000000000000000)", + "P->V[82376:82408]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 288: Hash(0x111499d0a173c9aba91c05f7a4b59a1c922d3059000000000000000000000000)", + "P->V[82408:82440]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 310: Hash(0xcbeebad3a42668278148b00a8a96cd9aee8be214000000000000000000000000)", + "P->V[82440:82472]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 318: Hash(0x59550ed9962e0d61a352aad0fefb396784083651000000000000000000000000)", + "P->V[82472:82504]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 321: Hash(0x656eab2d4318104974b911e00f719fafff660f18000000000000000000000000)", + "P->V[82504:82536]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 327: Hash(0xe986741fed5cd95daa2b8d0bea2841211bcfd226000000000000000000000000)", + "P->V[82536:82568]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 336: Hash(0x4fe7ca5106d49fbdbf0daaf1383c8390792e592c000000000000000000000000)", + "P->V[82568:82600]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 362: Hash(0xc6269a865de70f62974dbac2919039df05d90007000000000000000000000000)", + "P->V[82600:82632]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 396: Hash(0x8ac554557641b2846546fdadd11bf18dd8fac19e000000000000000000000000)", + "P->V[82632:82664]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 423: Hash(0xc929984f970db1135c72e399a96542025f3dc678000000000000000000000000)", + "P->V[82664:82696]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 451: Hash(0x63d16c97cbf0364939fe0f7313a3e001b7364842000000000000000000000000)", + "P->V[82696:82728]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 463: Hash(0x4eec06c1047a17c4aa6182ba85f74380cd66c73c000000000000000000000000)", + "P->V[82728:82760]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 502: Hash(0xa20528e69298ae009480b49bbef481468906502c000000000000000000000000)", + "P->V[82760:82792]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 131: Hash(0xb745d8ba0b989148f1ff6f85f76822a41b34096a000000000000000000000000)", + "P->V[82792:82824]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 145: Hash(0x166a4d337495d937f8871be14acaf8be57fd2779000000000000000000000000)", + "P->V[82824:82856]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 154: Hash(0xeaedbf36e6954243361d072189d6a4343e127733000000000000000000000000)", + "P->V[82856:82888]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 158: Hash(0x4e87c98dbeec5879c77ccffccecb78aa7b6a48d2000000000000000000000000)", + "P->V[82888:82920]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 161: Hash(0x97a372b3358d2677877d29005a87fea1c280c776000000000000000000000000)", + "P->V[82920:82952]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 169: Hash(0x4fa077123b492df33801d22645f5010326cb2b65000000000000000000000000)", + "P->V[82952:82984]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 180: Hash(0xdee78a4cf5922b697bb9951c1fb93ed772058d3c000000000000000000000000)", + "P->V[82984:83016]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 199: Hash(0x1bb21e47be63a11b0ec5dfa3c1ce20e1531f32ab000000000000000000000000)", + "P->V[83016:83048]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 210: Hash(0xd7a3a1c72ed708674393009a86604999c3bc451000000000000000000000000)", + "P->V[83048:83080]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 224: Hash(0x12596f3b4d08aa9217e1be17eb9512ee7802e3a2000000000000000000000000)", + "P->V[83080:83112]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 230: Hash(0x1cf120a052a8b46aa0ceefe6fb393416753246fc000000000000000000000000)", + "P->V[83112:83144]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 250: Hash(0x11bae8377a9c067e641641f4750e840d1a040980000000000000000000000000)", + "P->V[83144:83176]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 64: Hash(0xb790b5d22371c5f2874ca4bc439ce8b242f376f5000000000000000000000000)", + "P->V[83176:83208]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 73: Hash(0x563ce5072927ac8e078c910b27650902b3afe028000000000000000000000000)", + "P->V[83208:83240]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 76: Hash(0x3f0d8471c2aa89d6e85b135efab364261b8fa20c000000000000000000000000)", + "P->V[83240:83272]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 78: Hash(0x2b65cfb313879e6aa12c9f938282209b564415e1000000000000000000000000)", + "P->V[83272:83304]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 85: Hash(0xe41b444b4ec851fbc197922a881b6a8f39d38bff000000000000000000000000)", + "P->V[83304:83336]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 91: Hash(0x91510293828bc626f87b0c0c6c501cd017dda38e000000000000000000000000)", + "P->V[83336:83368]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 98: Hash(0xe879c61d7f4260f8994535421d2631d8b5c91e23000000000000000000000000)", + "P->V[83368:83400]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 104: Hash(0x4ecf8214fe7ba171d9c12e505b826c6cbbca5913000000000000000000000000)", + "P->V[83400:83432]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 113: Hash(0x61ce46ce65b2cbaaa9390861777194fac61ad230000000000000000000000000)", + "P->V[83432:83464]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 114: Hash(0xeb34627dfcc9f326561f4030c2aaa411bc0b6356000000000000000000000000)", + "P->V[83464:83496]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 124: Hash(0x58242dd3c7fe8763a9b3c88d87cb80781c6bf6c1000000000000000000000000)", + "P->V[83496:83528]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 33: Hash(0x93d7fa29cd9a83f01166413e4709d50059a6d624000000000000000000000000)", + "P->V[83528:83560]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 37: Hash(0xa2eb61d90f10fd4ba02e46f59ffed98fcacecadd000000000000000000000000)", + "P->V[83560:83592]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 41: Hash(0x70f8c01e1a0b5b5470e863ab5715532dd5bb70f6000000000000000000000000)", + "P->V[83592:83624]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 43: Hash(0x271c75113c386b1fee5e077420ee1cba11324a8e000000000000000000000000)", + "P->V[83624:83656]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 44: Hash(0x202c3a155a7e8d379cdc0e35f8dd82283d25ac16000000000000000000000000)", + "P->V[83656:83688]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 48: Hash(0xdd5ef7fca4008f2ec7d4e6237b6ae7dfb9295b2d000000000000000000000000)", + "P->V[83688:83720]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 53: Hash(0xc45ee92ee696ccf0b46d82263e51704220159540000000000000000000000000)", + "P->V[83720:83752]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 63: Hash(0x47cb49c25697f2a8615150c094e27941714eaaad000000000000000000000000)", + "P->V[83752:83784]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 17: Hash(0xa5394f7d8e968b32c9eb20c25ff31ca917756fd2000000000000000000000000)", + "P->V[83784:83816]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 23: Hash(0x90a73e3684cee2109d77a8f2ebe7cca1b09e6720000000000000000000000000)", + "P->V[83816:83848]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 25: Hash(0x4ed4be550283e8c81166ec542a21861b498e33a6000000000000000000000000)", + "P->V[83848:83880]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 27: Hash(0x8c4bf54b0af47312a9d84fa82788fabd7ba359f8000000000000000000000000)", + "P->V[83880:83912]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 29: Hash(0xc914073f6bbddbe8cd061b416d5f3b163bde5db9000000000000000000000000)", + "P->V[83912:83944]: /cpu air/STARK/FRI/Decommitment/Layer 3: For node 30: Hash(0x37ef6bc069ed6af0ec8007f7b2057c4199309ea0000000000000000000000000)", + "P->V[83944:83976]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 34, Column 0: Field Element(0x1dbf124cf3cc8770ee51bb4af951ea367bf99b7df1bb58197df7c1aa2c9f3c8)", + "P->V[83976:84008]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 34, Column 2: Field Element(0x13a0e6fb7bd971ac85c3d5dbfec0f05642fe70ca71bb33fa53f3ec193da3d77)", + "P->V[84008:84040]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 34, Column 3: Field Element(0x276c422c156210cd25172a81c6eee081ea93672e4a8780dedb119b58cb25be3)", + "P->V[84040:84072]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 34, Column 4: Field Element(0x1e98ef1f8dc54cfd215b9cee505074d0b2fda57267604fdf2fd2f427ba76634)", + "P->V[84072:84104]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 34, Column 5: Field Element(0x2d255f2330e8f9fe8fb4ab60e34198aa0882b0ec97895cd1a32c20f78fa7a08)", + "P->V[84104:84136]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 34, Column 6: Field Element(0x95512a6fb1abbcd95d215180685f82cf08f01b231c3ed51741a8bf6623cffc)", + "P->V[84136:84168]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 34, Column 7: Field Element(0x2ca40cd6de6a475de7a80c9f3a96284d59fdc50a0647666bb9dd958e02de61e)", + "P->V[84168:84200]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 269, Column 0: Field Element(0x479c350a5688760cec14a6fe8f4e3532580678b0e7458156ca8b339d49c7fc4)", + "P->V[84200:84232]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 269, Column 1: Field Element(0x7cd613a4996cb7c7fd27a1bb95840a8ff52ef59c8ab4dc910b61e3eabc58522)", + "P->V[84232:84264]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 269, Column 3: Field Element(0x9c284e8e357e49c74d17a4953034111c644ce671a1f31f90fcfc3e1f588e77)", + "P->V[84264:84296]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 269, Column 4: Field Element(0x18828f3d75bc575aad49b34b5843d36b71cffd17e2eb8ae640000bb0daa0e05)", + "P->V[84296:84328]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 269, Column 5: Field Element(0xb1622773947477a74307920dcc0d710ca66e124ed1fe1df193cf3855858c91)", + "P->V[84328:84360]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 269, Column 6: Field Element(0x69c02ec25cd3279503d071503359b63408b7890480140bb76a85b307e7b4646)", + "P->V[84360:84392]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 269, Column 7: Field Element(0x42d3e79b2091d6b9966343253e2f5a855f4140553c22059f08c747c1ce0e6f2)", + "P->V[84392:84424]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 447, Column 0: Field Element(0x210cb910b77cab5a5943e4ab90f725184e4df4cb47521f25e16598f898f0c5b)", + "P->V[84424:84456]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 447, Column 1: Field Element(0x6baeb237b0b49052d75b01962be2b1b8206ce1f646a1fcd3eaa8b17bab15aad)", + "P->V[84456:84488]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 447, Column 2: Field Element(0x58d369490c49e26857db4d6d5f9dba41a02eecb8ee8bc0117eb9acc0d60130e)", + "P->V[84488:84520]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 447, Column 3: Field Element(0x3e5820dc7e004ea35c20c81d8621557ea9212bba94527be027d0c6fc40be4eb)", + "P->V[84520:84552]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 447, Column 4: Field Element(0x14acaa704fb0554d7365f0adbb6cf83ae75a174296889a1a39caa1a60ba5ffc)", + "P->V[84552:84584]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 447, Column 5: Field Element(0x9862176ffd376fdf45b702e930c13236252567a0033aaaa1f45a5ca4f6f22d)", + "P->V[84584:84616]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 447, Column 6: Field Element(0x35a22259ebf5198de09a9b8a44e2cbbb5266a0e08015a28a8a2cdf42867a95d)", + "P->V[84616:84648]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 505, Column 0: Field Element(0x1aeb2ff01d3c310e7d477926a57585ac3d3d532a643983447c12e1b13a07149)", + "P->V[84648:84680]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 505, Column 1: Field Element(0x2dbe3edd155638e6b4a41647ab75631598951b6816cd71f74d9fef083491003)", + "P->V[84680:84712]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 505, Column 2: Field Element(0x30b747b20bf6070699e10cf216693fff7a1880afd7aeaf12da785a6bc8989bf)", + "P->V[84712:84744]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 505, Column 3: Field Element(0x6fe30ddcc8e7e00df5bda253934b915b2532a62e14cf07069b17fcd8e12d73a)", + "P->V[84744:84776]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 505, Column 4: Field Element(0x1c4804e7a597450de5f775ee88919f6b42b7fa475b4f614fbb1c54712b29be0)", + "P->V[84776:84808]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 505, Column 6: Field Element(0x4daf268682ef17cff883afa09afc87cecaf598ce40eec10235ecdb86efc4691)", + "P->V[84808:84840]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 505, Column 7: Field Element(0x26d8014a4953501ef2d5981ee77f796d5025848f47ba41972713202970afef)", + "P->V[84840:84872]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 515, Column 0: Field Element(0x30c6ac62518ee552cbadaeb08233dcb2793025a5f9cb9d4835c94469f2613e8)", + "P->V[84872:84904]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 515, Column 1: Field Element(0x7f920c02cfa4e8bf4ee6ccee39f31d0a1e6c72df8b67b7703d4fe3c79c1b44e)", + "P->V[84904:84936]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 515, Column 3: Field Element(0x5d6a034afa4ed039666ecc651fbf90bbc2009fe8f314554bacd1fbd248ad103)", + "P->V[84936:84968]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 515, Column 4: Field Element(0x3d2152cfabf25bed0c557e91e1da58cd07e6f9596effc46487747b758245e56)", + "P->V[84968:85000]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 515, Column 5: Field Element(0x76815a631c61584088c2bbb63c0a957bc51e4d0b09d564b4b7035aba8212ca6)", + "P->V[85000:85032]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 515, Column 6: Field Element(0x64bfda7f6876a89e369e1c6c34cdcdf5d9d9d57b52731ad09effccbb7feda44)", + "P->V[85032:85064]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 515, Column 7: Field Element(0x5a7a368ef11cdbe0ca9a2b4843441b621bd053a7f3694b1943b488341cd179a)", + "P->V[85064:85096]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 544, Column 0: Field Element(0x3ce92755006571f44c1b9bdb6aa2c1111fb388e945556832a03ba08a90f6f51)", + "P->V[85096:85128]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 544, Column 1: Field Element(0x5cbd1a19dabefe7c54975c8628e56cf362982ef0874d22dc42c8a714d5d0b53)", + "P->V[85128:85160]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 544, Column 2: Field Element(0x73b3caa524ab9bc6569d840bc77bdbb0e23be78a9a2a9667660138a12efcd5f)", + "P->V[85160:85192]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 544, Column 3: Field Element(0xb913d00222136118083e0ee141b25bb2ebe1993478db594b70512d50fe23a4)", + "P->V[85192:85224]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 544, Column 5: Field Element(0x515f2d277ab20556c0041430f25ddd69de73c5842b9612ea06faff343ba6d9e)", + "P->V[85224:85256]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 544, Column 6: Field Element(0x24afe2c3c280d984da8b2da1ecf5a3ca64f265b81dadde0a63461381977b52c)", + "P->V[85256:85288]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 544, Column 7: Field Element(0x441defa4d59f20a55d524d2ee8058a63fe05bc894a8089187bfa5c3435f30e5)", + "P->V[85288:85320]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 557, Column 0: Field Element(0x6838b3084b4e93b2fe105f019cf0a5ab4fecef877027434faa8ec79cef4082b)", + "P->V[85320:85352]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 557, Column 1: Field Element(0x4f0d5fb3b2198f78ba7e5d4f2d5d4e747cce094d898465b7ef8d527e0c48147)", + "P->V[85352:85384]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 557, Column 2: Field Element(0x5417be1ebc1ed97e9de37440789e9e30fd1b379a44469cfae87db4b44f485ed)", + "P->V[85384:85416]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 557, Column 3: Field Element(0x51c5fb3d62ea93de72a9aabedcffb90bf0d9eda8c7ec311e49d65ced49d0d4d)", + "P->V[85416:85448]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 557, Column 4: Field Element(0x1d584a2ecda4048ec73faeb12bd196af35ceb014e54e92c2cbaefad4ab42c6a)", + "P->V[85448:85480]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 557, Column 5: Field Element(0x87cc458a82f2886b535313a1eda2d127399dbf2562037a3dc4700b08c94454)", + "P->V[85480:85512]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 557, Column 7: Field Element(0x18969b46af9b939a3c3718d04cc6e6359b132784115c85bc0e3275981160f25)", + "P->V[85512:85544]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 560, Column 0: Field Element(0x310c60e1a4b900575a3a2a14b2dc58d7ed0337149f042a0b17794bd33572cb1)", + "P->V[85544:85576]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 560, Column 1: Field Element(0x76e5184465ca14d72cc8c74319c1368fb73ae1344323671cf146b68ecef7251)", + "P->V[85576:85608]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 560, Column 2: Field Element(0x2d2958cb037aeebfe0c383ccf4b5694e70fc3e413689e07b696975bf9178d9e)", + "P->V[85608:85640]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 560, Column 4: Field Element(0x56659f206776d1eab5585d9ead23cd701c095dafdda4c3de03e0e687241876e)", + "P->V[85640:85672]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 560, Column 5: Field Element(0x73bb9837689eb975e718637fa1eec6b302f7fde41976ac7ac5fa414f952f08f)", + "P->V[85672:85704]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 560, Column 6: Field Element(0x4377f35d1c8e0d0fa72e60ec74e60949bea720960845fbc3bee296520706941)", + "P->V[85704:85736]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 560, Column 7: Field Element(0x71241ca03eb6fa1bc9a0dba6f246f0452deffe6b9a27a6eb9e248c1c42607e6)", + "P->V[85736:85768]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 648, Column 0: Field Element(0x4549cb01aa3ad593d0ec3940b101b10992d8da158bd096cb5cd6ec62df118b3)", + "P->V[85768:85800]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 648, Column 1: Field Element(0x7c18df2797714e3f90185545359d4250ff7e211c1fb9b8a4accab0d8d97ae7b)", + "P->V[85800:85832]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 648, Column 2: Field Element(0xd0fc0426396261cc37a39361b070ae48da3aad8eb1be33c93b4b79a6fa1b8c)", + "P->V[85832:85864]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 648, Column 3: Field Element(0x655534efa9a2c2334c4f602ae295d0d1aae2ca3de08b877b36e7d96c19eb396)", + "P->V[85864:85896]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 648, Column 5: Field Element(0x715ec1868950b828600922d2a04cc12ffe6ec6e6268c1c090a437e0aa2f0c5e)", + "P->V[85896:85928]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 648, Column 6: Field Element(0x15422e896d441ccec2a5a77e69190c76619599ce4315866958f8b2365d991c1)", + "P->V[85928:85960]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 648, Column 7: Field Element(0x64fceb31d1d71f16b8c9219140f0f29e08426503f26d7bc4a194d5e597a07d4)", + "P->V[85960:85992]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 857, Column 0: Field Element(0x2e331d2f34bdfdfd35422c8419a96259b788086db9fd3095f58c4236ae19e50)", + "P->V[85992:86024]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 857, Column 1: Field Element(0x52b6775735390666f3930a9d8606048d7ac3ea5c4672f00a94b3be434ed8f51)", + "P->V[86024:86056]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 857, Column 2: Field Element(0x1825108e6595b58c1dd40731cab1376cd6c6ecc4303aae0855178e8188f7e22)", + "P->V[86056:86088]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 857, Column 3: Field Element(0x7df3846b7475dce207d7c0939de8c231f85bf1fdfe429c50d603b10e46c08cf)", + "P->V[86088:86120]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 857, Column 4: Field Element(0x291e3b74e71eef32a597e441e5c6752f1219cb8d65269f359b12e6a312c6a87)", + "P->V[86120:86152]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 857, Column 5: Field Element(0x2204f029e91fa92362fa7fe03e9f667cf0a08af506ebb4b56262823d2bcf291)", + "P->V[86152:86184]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 857, Column 7: Field Element(0x2168909477887b74c56c50f2f74ca978dae239b81ef615a813f4088a3fd8128)", + "P->V[86184:86216]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1130, Column 0: Field Element(0x1d2dbd37d5caae521e61ba768bc2541de010393d9992c92d78be68fdb213b27)", + "P->V[86216:86248]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1130, Column 1: Field Element(0x49cc162666bef301ce063ed3aeb39348c8d82ecde70d80f23c679bd1a48fcad)", + "P->V[86248:86280]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1130, Column 2: Field Element(0x22d625247e435c148dbb4b94231b518a31f3ec7816b81e4cd1f67fd98b15124)", + "P->V[86280:86312]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1130, Column 3: Field Element(0x274b21b432da37f52cbd90fea0b0ee903466b38ccdda70d617b764d52caf27d)", + "P->V[86312:86344]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1130, Column 4: Field Element(0x4d82e0c44badb9c0f525cf718b7c5925155a5a75c059a56068506cc0a950a49)", + "P->V[86344:86376]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1130, Column 5: Field Element(0x142d409ff9da296bbf1548bb56ec4e484294f8af1d7c1bbcf2ba6a3a4f80e4a)", + "P->V[86376:86408]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1130, Column 7: Field Element(0x1431266b16b668b7d9a6e55c93e35c2ee511c278de4d75af1188538f227fb11)", + "P->V[86408:86440]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1331, Column 0: Field Element(0x613daf8c033fcc7c4ad47285443844030f0381c7c3ee751d6bc5f4f91f3fa30)", + "P->V[86440:86472]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1331, Column 1: Field Element(0x7ecfb24aea3a1083886758453bee68debda5f80c3457c2983842b9ba31061c9)", + "P->V[86472:86504]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1331, Column 2: Field Element(0x203f5fb4271f7ecbf5b588712b75d56dea0c3338cf4dbe7ce7e84fb75555d6d)", + "P->V[86504:86536]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1331, Column 3: Field Element(0x782437d16e922c47616d5bb57dfa848c14ccae6a6feb82974f7841c88dabfbd)", + "P->V[86536:86568]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1331, Column 4: Field Element(0x66143ae3968e2339dedcb33aaa460e198c282a1dc630eb62d10a26f19528706)", + "P->V[86568:86600]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1331, Column 5: Field Element(0x56cb3bed51bc057bc964dd2340ef4f4f259e4726d937f2f171458f7282e3caf)", + "P->V[86600:86632]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1331, Column 6: Field Element(0x582a835bd3d91c3d749144536a9b5022f63c36bb4f3c38caa87340ca6d4b775)", + "P->V[86632:86664]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1552, Column 0: Field Element(0x83f11b13f01a333e268b7badf86250f217bf04f6d894df63a05d914a93c54b)", + "P->V[86664:86696]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1552, Column 1: Field Element(0x131f87aad751ef5bfd9729220e57c292c41aa63891da4597ee80b2ede70598c)", + "P->V[86696:86728]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1552, Column 2: Field Element(0x26eab8e6f75b8ec8a409fc9b519e6441368302e4b3c0785df379a95ea33103d)", + "P->V[86728:86760]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1552, Column 3: Field Element(0xdbb87db4e40ff35ede6d7c389c2538bcef32573601a04022d0133506a193a6)", + "P->V[86760:86792]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1552, Column 5: Field Element(0x13b1137c0d54d95e1b2f74304fc84677b7111ec13a26605429ef71fc4e2e4c1)", + "P->V[86792:86824]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1552, Column 6: Field Element(0x4672b8ef03d23d362ad72801274e13b1e4f289ef3f6951f0f10174d4719db25)", + "P->V[86824:86856]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1552, Column 7: Field Element(0x76fabb4abc65a60e75c229d7b75293680f4701e334a2ed770895365c246ee43)", + "P->V[86856:86888]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1652, Column 0: Field Element(0x68edf7728b20d3fa7a2eaf5633371e5ea5e52423a45b430a4fcd6cff4644aaf)", + "P->V[86888:86920]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1652, Column 1: Field Element(0x4fd1b425833a759d21df28815e2206a1765918c09590f2bc15e72e5f8f438cc)", + "P->V[86920:86952]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1652, Column 3: Field Element(0x41dd608f94c4736d0f872a0b3b5ebb3425cbdf47217c010381454d4989a3a8f)", + "P->V[86952:86984]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1652, Column 4: Field Element(0x20f33c73bd748cd2cc3aa7fd613484b62d132567ffb2f9f5985d38e06c6957)", + "P->V[86984:87016]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1652, Column 5: Field Element(0x79ec27ec6774421213d551908a9ee20fd640e638186ed8f8d68003b0574a131)", + "P->V[87016:87048]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1652, Column 6: Field Element(0x23480d159ee2a34cbde81486738788ea3358c6488fc96a525436278b9e47c19)", + "P->V[87048:87080]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1652, Column 7: Field Element(0x19c76c4ebd1fd1eb1f922528f14740654cad9caad8b532ac2315fa8f2dc8b2b)", + "P->V[87080:87112]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1981, Column 0: Field Element(0x6ca1741d5e4d25b12d350a97184318c66a20b83e7c0b5d6c24c91749b03bd2f)", + "P->V[87112:87144]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1981, Column 1: Field Element(0x5df8491919a743c4b07db0ef63d3f1bc66932a429da2979d7aaddb963b93968)", + "P->V[87144:87176]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1981, Column 3: Field Element(0xb3b95212928a7939b83198d9f119a36905caa236ff6d9555536203dcd426a0)", + "P->V[87176:87208]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1981, Column 4: Field Element(0x73e520de8969046544f45ecb7bdacef26d9781de32fef06e5e87dc11fb28464)", + "P->V[87208:87240]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1981, Column 5: Field Element(0x5b575de8b03941076159d7da3290992e3e67d65e5ada0e58666c2f181f2909)", + "P->V[87240:87272]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1981, Column 6: Field Element(0x605be1596a6aa5db132c682521d37f3ac5d7595427454b2ada9d460a39e752)", + "P->V[87272:87304]: /cpu air/STARK/FRI/Decommitment/Layer 4: Row 1981, Column 7: Field Element(0x73b99409ffc7fd57bff95e5b43abe741dc34ad1777deca1d90dc65b86de5af3)", + "P->V[87304:87336]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2083: Hash(0x8e5cae0f18009d5ea8102738fe6f477af4b96fcf000000000000000000000000)", + "P->V[87336:87368]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2316: Hash(0x20bc59e5f3f9caadf5f05d8a035abf36da713525000000000000000000000000)", + "P->V[87368:87400]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2494: Hash(0x745a11640e24e9a1cbdfd44875c68b3871feacd9000000000000000000000000)", + "P->V[87400:87432]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2552: Hash(0x5e0ed0fd0cebc324d5f47f13ab1dc911aa01278a000000000000000000000000)", + "P->V[87432:87464]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2562: Hash(0x1130902ba5ce382e120d176914056fd660d5c67000000000000000000000000)", + "P->V[87464:87496]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2593: Hash(0xda631eb0bdb9211661c13147a8cb474efdf23764000000000000000000000000)", + "P->V[87496:87528]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2604: Hash(0x7caddc8d6c82ef0657b1b5aa5c6caf0848aa0420000000000000000000000000)", + "P->V[87528:87560]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2609: Hash(0x9554686bd21b7c50dbc388705afe2e4e62468d98000000000000000000000000)", + "P->V[87560:87592]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2697: Hash(0xa5e9ea90f78ffa2196bc2417fd82629cb912c681000000000000000000000000)", + "P->V[87592:87624]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2904: Hash(0x77a818ad004d5a9b1924ec834306b86074df979e000000000000000000000000)", + "P->V[87624:87656]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 3179: Hash(0x2a9e44e7e93d746e30c25e4c23d568e38cbd872e000000000000000000000000)", + "P->V[87656:87688]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 3378: Hash(0xf1263627574a903d8a3ad6f70a782e4ad5c5cf2c000000000000000000000000)", + "P->V[87688:87720]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 3601: Hash(0x54eacf4ee700548103f032b8a7348ab651f70e13000000000000000000000000)", + "P->V[87720:87752]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 3701: Hash(0xe3d274c3f4a0eb458a55dfac18f116f3b39d2a39000000000000000000000000)", + "P->V[87752:87784]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 4028: Hash(0xaf3a89bd73224b4593854047e5cec2738e9c315000000000000000000000000)", + "P->V[87784:87816]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1040: Hash(0xb342e6df2058ea8e3a31860fc7cb78924f6d4cf3000000000000000000000000)", + "P->V[87816:87848]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1159: Hash(0x11e9d45510a3dbbadc87949aa8d4bc6be2497316000000000000000000000000)", + "P->V[87848:87880]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1246: Hash(0xc2fe1cada44388647ba629fc9e97fbd92b92819a000000000000000000000000)", + "P->V[87880:87912]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1277: Hash(0x731a6550cb6194c370686d4757c8123dbe00b3f000000000000000000000000)", + "P->V[87912:87944]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1280: Hash(0x3fb16977172110b4736e114f10ab6504df047c61000000000000000000000000)", + "P->V[87944:87976]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1297: Hash(0xd9ebb6142808ce7b1b24a50fe31eb82601f49ca6000000000000000000000000)", + "P->V[87976:88008]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1303: Hash(0x3d35ada3dc2162991b3ab96c1386643d3c16f847000000000000000000000000)", + "P->V[88008:88040]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1305: Hash(0xd535e48eb54ef5d731b5b181228c671e09686849000000000000000000000000)", + "P->V[88040:88072]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1349: Hash(0x511a3248d6c59294ff1c900e5a77eefecba48df000000000000000000000000)", + "P->V[88072:88104]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1453: Hash(0xf328330254177242a6a09a5cb64bae4577cd471b000000000000000000000000)", + "P->V[88104:88136]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1588: Hash(0x87999f13d1b0655c50cd9c8512a21777653e8cf8000000000000000000000000)", + "P->V[88136:88168]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1688: Hash(0x823c565e88e78507da8558909f9f13e912794ced000000000000000000000000)", + "P->V[88168:88200]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1801: Hash(0xb6d7fb244a0dd232196fe8e7a6b37198bb6ca4da000000000000000000000000)", + "P->V[88200:88232]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1851: Hash(0x3db14e8dc714f46343921274f481110a4e380e05000000000000000000000000)", + "P->V[88232:88264]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 2015: Hash(0x906682d8aa4e7c669131faafe36b24ef7ad20424000000000000000000000000)", + "P->V[88264:88296]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 521: Hash(0xcde55bc04d7bbda4bf8c989ecabda7bb7611b557000000000000000000000000)", + "P->V[88296:88328]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 578: Hash(0xa8dabbda2d385b7be20a4e5d88115c0291b1192f000000000000000000000000)", + "P->V[88328:88360]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 622: Hash(0xcd729f057337d5b4f1e094ac8da001d3c6fcb661000000000000000000000000)", + "P->V[88360:88392]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 639: Hash(0x1fbd445da6f139b0209d0c08c63d890880e29da5000000000000000000000000)", + "P->V[88392:88424]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 641: Hash(0xf3a6938f7b1022ced063763d2fd2a46cdc68b7fd000000000000000000000000)", + "P->V[88424:88456]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 649: Hash(0x51a94aba83de867cdfb65663a31a7703423dfa63000000000000000000000000)", + "P->V[88456:88488]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 650: Hash(0xbd73f9a3a1281b5f185335ed680bcd7186b82c73000000000000000000000000)", + "P->V[88488:88520]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 653: Hash(0x92a2faed9ae31f2fc22e6ef653dd1bbf7ac40ba0000000000000000000000000)", + "P->V[88520:88552]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 675: Hash(0xb974f0687dc0e7e22efbf28ae572618ac42a6171000000000000000000000000)", + "P->V[88552:88584]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 727: Hash(0x4beeb67d729bea3e860c66a3a1a00af8d478e500000000000000000000000000)", + "P->V[88584:88616]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 795: Hash(0xd1bd0fbe4ee7470411f909fd8c716e4a03b266b2000000000000000000000000)", + "P->V[88616:88648]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 845: Hash(0xf5e6c71c1866d0a5d7d3c30312ebf17ce7e3c914000000000000000000000000)", + "P->V[88648:88680]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 901: Hash(0x1619cf25d03b678141a4599f243cd4580cb5cf30000000000000000000000000)", + "P->V[88680:88712]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 924: Hash(0x803c21974bda54547bd62768f76707c580e09874000000000000000000000000)", + "P->V[88712:88744]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 1006: Hash(0xf4d4ec06f5225613e674f615fe4ba412d97ab195000000000000000000000000)", + "P->V[88744:88776]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 261: Hash(0x78c426a2730fd3c55394312f60f36aa2ba0198e1000000000000000000000000)", + "P->V[88776:88808]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 288: Hash(0x2be5463b919af7bea4b7a74de9c9b24d8a7809ed000000000000000000000000)", + "P->V[88808:88840]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 310: Hash(0x4375855091c87dc13fe59c4079205b0da8fd0f66000000000000000000000000)", + "P->V[88840:88872]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 318: Hash(0xacdbd55dd04cd5a6b46437be0ecd75a03255a910000000000000000000000000)", + "P->V[88872:88904]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 321: Hash(0x8c196c1cf8a18275e1b893540903df043d19a51f000000000000000000000000)", + "P->V[88904:88936]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 327: Hash(0x6dfccd333fa8c1bff53beff776a51a2f3a6af23a000000000000000000000000)", + "P->V[88936:88968]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 336: Hash(0x79c009a8954b6f71a2cf6c3c75a6553024a9216f000000000000000000000000)", + "P->V[88968:89000]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 362: Hash(0x731db3f0ea17e4682fbfbaeff9655b814208f983000000000000000000000000)", + "P->V[89000:89032]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 396: Hash(0x116e53b5ca439837874022554e296b2836486d82000000000000000000000000)", + "P->V[89032:89064]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 423: Hash(0xcfc69261a03f934acc2e650e0bdb69d90ae74aa2000000000000000000000000)", + "P->V[89064:89096]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 451: Hash(0x79135486147fa8a4b9b5e06d3965a63a6b6b4a5d000000000000000000000000)", + "P->V[89096:89128]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 463: Hash(0xdcc4aff3147176f0d39c4f2083ce8c526792cf07000000000000000000000000)", + "P->V[89128:89160]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 502: Hash(0xe98621ce90ba18cb754f0d64522ef45aee10317a000000000000000000000000)", + "P->V[89160:89192]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 131: Hash(0x520b8e150dc3825214324997eab14c1819875b42000000000000000000000000)", + "P->V[89192:89224]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 145: Hash(0x1d2b26322c1e37b5de33bed3974ab3080f9a72f1000000000000000000000000)", + "P->V[89224:89256]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 154: Hash(0xd3d8396c692af83c986d64d1ef65fc0aa20598e8000000000000000000000000)", + "P->V[89256:89288]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 158: Hash(0xf8c55aa929d8b93539675a7a627a6c3e17a74a60000000000000000000000000)", + "P->V[89288:89320]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 161: Hash(0x620045471713a8b95afc4c9fc1e0d447e499be1a000000000000000000000000)", + "P->V[89320:89352]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 169: Hash(0xc2b7ef75b5639c3d1fee72a36daf5b8c24fcb6b5000000000000000000000000)", + "P->V[89352:89384]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 180: Hash(0xaab7af3882c96d4aa802e60083c0b671e80adc32000000000000000000000000)", + "P->V[89384:89416]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 199: Hash(0x2518026ddf624ca1a134ffc3c17eb5a8676bf7b000000000000000000000000)", + "P->V[89416:89448]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 210: Hash(0x4313950c7a45b557267f2a710648423e48166214000000000000000000000000)", + "P->V[89448:89480]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 224: Hash(0x6380c3d21ed612f6f92f2669c77060612e357ee2000000000000000000000000)", + "P->V[89480:89512]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 230: Hash(0x8ab87f12a697dd066f452e1f5d79d0d8e3148e4c000000000000000000000000)", + "P->V[89512:89544]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 250: Hash(0xe188f0e4527bfc35c3738f170669f208c70d8010000000000000000000000000)", + "P->V[89544:89576]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 64: Hash(0x10f33a573e444468e723b146656a27e290f6dc07000000000000000000000000)", + "P->V[89576:89608]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 73: Hash(0x6969104b37d942b630745d532430a83ff02449c5000000000000000000000000)", + "P->V[89608:89640]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 76: Hash(0x9d1036262823f56eeecbcaa0760713c0453c7dd8000000000000000000000000)", + "P->V[89640:89672]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 78: Hash(0xd0494db284c0198da862f59772776bdab9bf3c75000000000000000000000000)", + "P->V[89672:89704]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 85: Hash(0x7cba203611f9160611b5d7aadcebeb18c7d96866000000000000000000000000)", + "P->V[89704:89736]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 91: Hash(0x282d72ed7cec0153e801caddd2e452bd4d2c11b9000000000000000000000000)", + "P->V[89736:89768]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 98: Hash(0xa758538c3ebcba2c951ed2e269d1ee70ddb2f883000000000000000000000000)", + "P->V[89768:89800]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 104: Hash(0xc13524936c92388fd72bd26e3a4a138ecc40ad47000000000000000000000000)", + "P->V[89800:89832]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 113: Hash(0x84a69688b2b0ac7c99b23e87e811dd12bc3ae7c9000000000000000000000000)", + "P->V[89832:89864]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 114: Hash(0x627dfbdee2402d2417bb2a839ab0d7cb1a410f9b000000000000000000000000)", + "P->V[89864:89896]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 124: Hash(0xb2d79e2e3b742c4aac4f5a5c6b2d3d8cbd63cce1000000000000000000000000)", + "P->V[89896:89928]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 33: Hash(0x2f163db740ea1c364962c5fff6b228e8bdd77077000000000000000000000000)", + "P->V[89928:89960]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 37: Hash(0xb3169bcfefd94fc3dfab6bd2fde068e81b074844000000000000000000000000)", + "P->V[89960:89992]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 41: Hash(0xecc146c118d8c0a53a5898c32931a86ff14db434000000000000000000000000)", + "P->V[89992:90024]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 43: Hash(0x1940404ebc91b6fcc3699668ddc9eb8c2020f48f000000000000000000000000)", + "P->V[90024:90056]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 44: Hash(0x3635a61e630c3ac2befbfcb7fb4811c185cb9b18000000000000000000000000)", + "P->V[90056:90088]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 48: Hash(0x7cbef9c2f39ae5ba7905444465f0f07af778feba000000000000000000000000)", + "P->V[90088:90120]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 53: Hash(0x76b1194e45e27811e0a03c2e1d9c5d487100f993000000000000000000000000)", + "P->V[90120:90152]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 63: Hash(0xf0e4765d90046054828481a32193b41b8b0e94a5000000000000000000000000)", + "P->V[90152:90184]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 17: Hash(0x6da61bec4e28f0f289ac087e352d60acf1eb644b000000000000000000000000)", + "P->V[90184:90216]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 23: Hash(0x10a892fd05c1c7e59dee75f0606e1077979cee42000000000000000000000000)", + "P->V[90216:90248]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 25: Hash(0x65ba284e4882eb323cbd887d8e910e592bf0e8d1000000000000000000000000)", + "P->V[90248:90280]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 27: Hash(0x128544b01c22e44cf9d4f5810fc499219a18deb1000000000000000000000000)", + "P->V[90280:90312]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 29: Hash(0x1ceddf7e4ff3bff22037475f5b7d0b9d1b101f51000000000000000000000000)", + "P->V[90312:90344]: /cpu air/STARK/FRI/Decommitment/Layer 4: For node 30: Hash(0x37ef08bff97447f57833ce7e5814dabbe015d3b000000000000000000000000)", + "", + "Proof Statistics:", + "", + "Byte count: 90344", + "Hash count: 1482", + "Commitment count: 7", + "Field element count: 1341", + "Data count: 1" + ], + "proof_hex": "0x0903d315c75757826b2dbd765a42c10a5b5ce34c00000000000000000000000072600ef7d5d17d4f5ac2c742cb35ed7737ce6d1f0000000000000000000000000db714528b96e7b6762d3fb3f6b6d0744b4b655f00000000000000000000000007ae85070937747b55bd6af6dbc9a46e88703e4c7b14e9e0016df05138556f340459269c8868cf0619f4bcfae3b6b1f71008cc334371b3aa425dc1377160423d071b0eced560e29f7411a465bc2919fcfc0d32381a8d29c95db7648b442dc70e064f0e4d1e6d90d76386c243035a4fc8fa692140e48c8503ba0d20b3d5e40b9f052d5f648db5655ed6d228a9af2dabcb04073140980c861d5c4e60a2189a2bb90409dffbbffd1dba4240d8699580be60e020f524668ebf3ddaa00ac713c52c36053797839922e895903a6ffd41beca30321844706644aeff6a28de7a408479c9036f34a7698d97186caeb741481bdda20b5ef760eb2f59ed6e021aa5ca5c3ac6073d08a2281671f76b6423529494451bd1368eb705b55260b389bf643473f1b2067c3090a0ebc4f2dc2edcc12e201b9bfc60dd7be84104086c0d130e45a0584205b6da024d1e379cb1ed7b42a57b215011b4e1143ea2052bd6033afeeadf6e6400396152d57db8c2d41cceb04af6acda2dbb02680df728dd7a116538590c8f1e0600f35d9824a2d29f131b9db7e55edec8d1589783b5e9ae9e67eb233ca8501a0502f61263f3b8720bf346d3325827c7848be457f7d2a95abc20f386422bf64801759cdd78604bdea23a515f81064fb880929740e10c4b27d30e44f69f34952504f25c033d7b80dc6bfb026801ff0cd64f938c0bd261e38c23c2e1c638df821f02823e7cee5ae29e190c331828d78ed3421c5428e747963594504cd61a41c95c0091d6bd75fc517b503e0ca98a67e67a7167e0312790d55f0d89ccdfac5fc3ae0638a5bac969fe5157f58dcc11dd127e110adb89138f74a171978170aa5cefa901d4beeef90e187e947e90a80970412d06791a75eeef0fe5490920ecfd01fc1a06b2db40fef9e3ef2182a3e52d229b86c782ce896f0fd9e68fdfe3568f77fe7b037f98b17e4956d506d3910eafb582883d7ad7cb0d51e931230a492b79cd366d04bd84789d836b6e7eb823e79f68302fbc36232b3657e5b5634a0029e6f25fe5036da34f63be1ff112e01df30c9ca4ba1b015c0ba66ecabceac1e3b54750946e072b35aca43ce7c294c324df941cda241ef75fb93ec43702f2e45a371fa0936600602dd00d8ff508d4249082cbb1b5812d6710c296eb32b5ccce76c038043bdf07a416464a357583fd5b3ccb602bb3c90fd8ba8a2e8a63edc8b78dd23364d7cc07cdda822e43a163023192d5866da8db0412a0c6dad507f154789d76e86975de031d26397ccacc9c8c6f65bd85ad98bfc0c785c6b9f0f0ec04c08b021a50107907d6b2a3d292a9d851c7ed3e5c65de1b239c8e74a1157d781e2dbdd2cf0488e90149cc0c7bd97e1ba89b0ebfb16ac55a1f8647721270fa12e74d0698e0e1ea42048a4be7baba1b8ec257cdfb2148a2e2c7b71275fb6860aa9c71a2b034cc349e0215067fc6e2ac06fc1305864f5ea3965b6d3f26a3eb97bacccec50abf8258e4038cce3616cc5f1a765d4d0ac2de95d38dbf6aa72047947b6078ab9463c47a0e056e2dd62c9c0744fdfba0e2cc9e4d79963a54fd0069c185d2c5a029064b341804266418303823fbbe7881b600f7b9b10411edc8adf6f3e8a2d4545d581419ae066273c7e67e533f963f35c7a9dc13cb64751bda47909cca41e4eca00acbfc3802b41234ce8aa613bd7b8e945ec5eb8233ac9d481dd22613cfb3a400ce68634806e26b7aa88d69e50b0a1dec2c55c516d323ae3bd9f9559ce9b0405f991d95d8026cb588067d559b3dd1582f091278ecd44571f967990635bc4e483085fd5b8d07e79fcb82fb031a8048ea9ee38248cc6e1ad83b4a25794cd3585b267c0b02a9001fd683b4a22cabf6d35dd6c0458daa44ba007fcbc1157764b3253e3d5346fc00d31f566e53097a432c6eb14eec5865a622caa321dec90349e67d9e9e7394ef00be4008a8b6319e81d5f63f8a4351a82197416bede1ca898ce1351bf75cbb5a01c7dc5de2843cbebf7294a8df03131cadf35feee4b00ed2be50446561a1d5ae05bce28b120f0e5f3078f6060d9c12c44ace0af7710164766f70d256f2767e3a01b0d3367a05856e8bc0342b59b8422f5438d3e6e5bdd9aebb4535b658fa14e400b8132f0e44636110c3d551910f80a0a16c7346e5b6c849e13dee91b79ca4490051b6c138efad1c94120e5abe0af704dbfaefa563bdeac249a1df6822a48035019154a0138bce4854c2c405739f6d9a9004b22ee808204eab489e3d734dd407003cacb0dcf531dfee2dc2735d3633d12e789b0a595cfd92c13fe5d4c2a26af6047d5ac15ab6d06a72ea81cae11d8d90a947024be881b5286d6520f661ad552f0660ed02dec6e801bbc643afdc51affa93d2686c3aa43d762ff21838a47d963d02a285afdc7456fcef7e19f764cc09515ce46bf9962fef570daecf426f68f35007c52f647c53fdd59abb0e794fdb08e0594820bee2683f652227c81a43b460c107ad114cff8ca7d3fd2e8ce75563786248647eb597bc88fa31eaa304c8143dc604d68b423565f90860e400b7a28311008fab551681d713e93bce39829323c3f40530f277390f48648645ded5661d9fbd918b79648a191c69830bec219d3904050412ffc4b608cd687650babe1a197c545215f9ef9520f0fac46582e984ac592f053ce4264868485d9728806866363ffd80e042279bf23d013f410b49459299b7026ccd86c1ca52c459a0d18f86ee7f118bca887904824a0582797c155c4be42b0140fcf23803d9f5ca56f8b7898855b49caae20c9a079468d7d0860b11872ea503769c60fb9c12d2b565497f013fb8f47b75a0188a2920c772f217122b48fa1605858b69a0bcd588a4d59e2147f8962285c1c26aa90952bd83590be1de1c45430228483f7fcd276cf73d4761b525b15eefc13ad5cace3923e6b8c7e3a711eb4007845ff4f21bf18766b9440398aa1eb4939c4fc9f2a2c3d6fa83978fc6f9d6a907ae453e7880a089813c618d5ed315ff87ae78bc5c0630b9ed2d40228fcf737f016cf82472b3f8e095705ae1bcfedf7876297a4a21afc9b3d08473d37a39a9270779d30ee67b6708b9944e6e7e32749bfa7ba8a1c74c9a98dc9c5fbf78c298d5037b1909288d1badd5a128594a9fb3941a9481742ffe87076fffd0dabec052eb05bbea5ecf9f1b7be5ff15d54614baa2c18a168a929763f8f3f58e309ad2443207a767ce6200e3be19896e2182dbb9a8139f0061a7871d9f510d05511c3e997e0071115fe7f1c66c9c2900cd21512c3ba8f45abe4c76449646c8773ebf2cffd906b341fc77e4486e53a6fdae6a76d06f10ffb2d7a2a3ff1d9ac65a73968b488203ecdd64b3d5113f68076ca7b711ff2ea12f34722fd5c84ae35c8989f23da31c0240ebd26b19b3c6175681e7d11136614d44fe2f3c4803c8718020e2a6bc72d103d578df55e3ba61d6e881c868f911e07ce9b053ccaf087c613c86fb4ef99fdf04a785c150fe161dd2346c2b6fb5d70a9b5da2642f62cd8200d4e816207fad1d074676806d98758ea2c6363444a42caeb1c9f4144ac2433aac3a2da469cff65b06ac5dd871a9154d9296affaf68df9f6054f7c8fdc1a5555ed0e288ca52b0c170304229913809ab31f0c0257606bb1c9416e1753327c115821f931e05bb00b180211120700c2fa288819ccf6fb043a77f35443e69f75e4018ba636ba214443a7032d8bb26823ad6aa777bbf943adacd0edcf791f1ddbd371aee6733ffd1b0d13000458b176370cf9a482573f1e06ef6d2467a3a9b77d5866b8867d9e884c05960198dad9a7ccc7e71b760b85151ff74043943f9c8c7bbcd11f46e406707e4e0e05882a35e5b382fd93feb5341bb4a88a84449c54fe24d498ea9259e6b38cc79e00191579e74c96c41cefd9d5da786068327ace50b95d13c5ac59019c1e90aa57045e539e0e8be0be85eaf9d1d6fdb130f01fe8ff55fb71593d12bb4515a606120386a3ac9626af592e0255e73f1c61c4a3a9dc336281520cefdd6f2252c1c950014ed4d29e844ba6de30a6c0b55ccb82d7a7567f4b30c1456cf62197f4ab5381031fcd4fed9759ff42f2f889b94de1f1e77762c4764735a542b7f9492a2a1ff100772d21abc375e9eaf72ffb7387c804ad378e2b5b062f8eaab198e89dc53c5703cffa85cdd0de0fc2395bc4c28a1851772f3fb8a112f9906832f7bf65932f2a003e2e823b7248bd69b7efc98a15d120823903396b0f7750d19b3443e525592903aad96cb5cf6a6121b5ae02d4cf64ef0ccfc69f11a906322969d41c2be8815607eaec410360feabbf8be008ff5bbb6b9acd2e2f44d6b4cc884810281d88eb1901a02ad6ba65b16b8014d350fa298b134daa8fb7ff8324ebb61fc2e441696cc4008866146549847d44fff4ed25bc3f5cd36afb74bcf46b36405220971105f612007365a45698119b8ba6528a0f0590193f4fd771c97ff1f0372cff22661e751001610ec8a6550d8d399e2d203edb71913d0f03b189f4ef945d2285e3d890018507465ae352bb2603f9e60f1b2896e798d1392b717ad5875a22460cca49919266043eabacac787f0f2bc7990177a72ab9bb62fbc518c4ea4560c21a9027ee1fd70240bee68d4848d9741151b5cdbeb5cfb4ef05546c29e59c80209e630469071d00e987cd5817b500496ab1c570d028cc6ce75c7029ba5de6b643da54cc180ec701e16fcd79bee9c66d292ab41f89bd28c7e6ba7371110e7fd10b41223e9e698a05d07b628cc1ca255082638d4f27acc6a86a5efec7367df4ac8bcd639e0d55bd00cb8d9b5b9297ecb0939965debe27abdb435a4640390c78c8d0db38d2c00aaf03b0761f84b09ef3b64f55c3fdc596a3c8574f0639df266f50455181dbfae10400333aa39ced3618c19a3e5f51488e4577affbc286d10b48d1e38957ed42552a06840ac869c2973bc8e58fe67c05ee515033582f8c366628497562406e5f4845020af47cbfafe5ae927f93ddc601b2a9ce2170ee0fc07d5ac4f51ddc58ccc3ff064c6c9a4ccf1834ac1c1b84550f12cb13ea6ddb0e60b879b32e36cf767402d70265f83892615983cf5ad62fe43ef62b7882d45a0667a2f795c4b29f16fab0f905a2f5fedcfdfc9ad30b5646183550d19ce83989c5dad6e79a1757e3f2f4f6240317ad807b0e55af040962711cced30ac7198e59b83a86e3ef8bed6fadcc77e3012495c2e2719bc806cbb540b6e382853969e12e7efba06f7f9798e867444a7807d6aceb196d0ea563e37952b7c4499f55389ca6b7e1a106c58fab971f858eb9008da7d51a522c26ec43cef4c6a93dcf0622330391cb4f742fe96de345fd8e3e02e6bb0db5665ffd09e12cff782338363e2877513471ee3c23e8609cf729c5e702faf9053e6c95d7a8d803fe28f5d6ed2181ac9250371bd8d596ebe6432f638f0606a53fe750978949b66ba841ac7504f5651cd7f305296556bbc01e7bdaef7b019176d212c955b62c50e18d23414bb06d14da23d48ad0c0c293e604b4f04e210613d7f922dae54d335e4aa43fba4e972883945b9e69a2e697dd2773df6846d407e6f1a2c6f1b47d05f69a507c027f2860e3355c84f7e95f16118126d5d58b8c01614d1a1100491f0b94a9d452baefc079e88ba5ca31154953f8af47d4b48b75065e7e3dfc9b24fd041844783528e1afef088b40166e0dc5ed191e000c96d56302719f65f98459f84d264acd9aec41f9e9a06e1c240e67d40a5a1a2d00c00f4c06551d95168ae6add46c4db54e024c445326ded298e7fdca4b9600c1c5d59eeb014c16d966445002c712fb2e6a7413fa8690189d80a072081f2dd52d59923c9005545a113ac6a692a0253769227317a40b3580e61724f984e19f508c8f2ea04702a51f64c7dead5b36fb2e992539badcf9dbff90ff278499014b912c5b07d5f20108863ffd521b0e7fa55afcea33c8f1a28d9d60981e6d1c7aa2b9743d66f30305b3f7f97225dbdfd0cb0dd03b510a9b088eace823c75203cfc13e1334f7fbc4040e4487e710b45ffd22aeb64fefec3382950e08037800008f2989f0d9d636b703ea235fa2da5eb26eae8b306ba42191604bd60127d68ae832f1d57df5c389ed0142fcc07f661b930ee4981db3174d8f17b54e402fed22062c1bacfd167037cf067b5351142594f2be14d66342b0bdee951cd19d8c0d00fbf184b50eff5cc0ed07d8f8b0e4a7f635e09433f920e1f194ee886f0ba29c2e6ea3df7f13927736b7045303b24c8e00ff64711785150f9bda45f13444e50114d625a157f87e37a8b50618665bb37520cedd1cff65d8d987d9caeb22266d9024248696191e6bbc79a50061d88870c2cb6970f3cf846953c0e127c0133d0b92265feafafb21c364af0b04fc8e7857a0feea9684ff20d09f3f83b477b26edca865cb497f24705cc8188e01c0ed9f4b686e7c5cf92a60d73530b46d651fc2555def7f43884cfb5beb520407c50afbab4e66a5f8edb59c3b5e22632a840489e0f8021e3100d8e802650caa020290415c3042bdc9d1144b78e2a400b9fed957faf73aa8669ff3d74419809a06aa3cfa0aa5b658a5df46da7608068571782cc3f5d3da851ca79bfcdfc22b44049239983ba54a1d012831b5138f348664767a45acc4b4cf0c26731a3dd7b7ca02034b078431da7ed2fe58f41c2dc4fb8ad29005ea148d4ed4ac40e4f0c273c7047ca0b07997dd2a2981fac49374dc271c21a91327f4df5a811fd4d62c4395550017a6d5e89c1df0f179f3a11931c99f1a716da857a08b4b7faa36e1eb02aced07feab1569a7ea8729b946fa7297ded0c77dd7e067eefba00a01079c19181230059dff7b91dcad81d291365d06dc7d478ce0a07584bf6d20861978d9a0d655970249fa7f41f3320591cf0fa6ccac7ad7d362e751edaa6c1ef6b2d172ad9eeaf5026a82b4699095908753bad495f6e8f4ccca4f8cf4d1562d47baebcfe7e5abdc00c649181a2133251a0eeaca7c803c112f2f257d8e8b77f2450e2fe39109901807c5f22004ea32df171efd5d087873582f937579ab667f18c07532954f57060407d055e9ed6e1050d46e86b74cc68d0551e86b0fa18b90fb5eeeb6819a8c113104f59990ea1d9d8c8c1cbfb667cfc1d337ee57ea87df1a9b5e8893a5eb0f1df705148555d1db4209fa927b8d243de316309fdca6267574c45a81867b81ace52d07ce427a31a1a0176c308e9cfb61f52bebf191c373ecf9ce375b4cdbc3632dbc05e1413671978f396599686f377acedf2c01374add9fc29e5d2ed457e0009cbc05347db291e8f174a30afd3034a5d806af94d7e32c3808981186434263ef559001fc09ea8b4f121862d2f1e7fbe2aa43703237c55aa3ab3ae231b836fb651d4303909cf9fbe82f5df77b84923c2d34212dcee1e6167736958d9e81d38f4f12b5002d6c7cea021b8fcacb97ac778ed2fe529ec04e9607e6ca3fbc614cd860b85803474fbc5f73b97d6440b400d88ce217bcca3b88729b77d240b35336f8f8cd3a069fa58f97ead9921ab48a4e4a48e9bc633e6020402024f8649b915dc83c2aa1048a85eee1030050d0d37056acbe532c1a4a9eb139ea1253fcb92f89b5c6a5f407119ac68dd354d2a219344c5db80f160d1bf91d46aa8f1e544735607b666069065f8fb2cb83fccb4537810eeb621670abbc75c352bef80834c1cbab8951fa130404b5aacee3e2b104e041ed948c1f6cde58704644cea0d5378bebb6bf89b34402205341b9e8bb49db9c35ef9dae2862873ab10ba7b47ce2f37f813cfa693500076a1191671031c7771074b29af3833798429c012b50f429787230108c82754504a22d60724b92f681510a37208f907c219b06977557e5206926c5f2b144336b007c2c1cc4e829c7c58ad9ec08f306157fd406ccece0b6ee92abac834e3444ea03f944c63b97ce65bceecc0d2754a6194ae4bc315e094dbb92583fbab832176805df3176b3eddf812a7d2a31800311bc587ec62166d3a8e3b87de11d09605abf019b998d30e7ab71b4c22f0d217cd680c48c16286a78a5fba4c979762c0990f60287dcfbc486cd8774112ce1f4083d25eec719840e53e24fe7380fed8f8ccc4f0244f543dbcc34907b155ecedd09d889b68f919e3c0fd067a4a6f0496130d26205fe9f1c351ca8b9a893adfaacfb237e5c10800c1530acfda0b74a9a36fadfd0034a8e3f2df882c2030728e2beae407bd65e7e232c081cf9b2dea84241cf404a0624f830b76f6a19d9a53f305a1925a9c555139d5ebc37a89235b641ea79759b047cec36c7b64680361998031158824215a710d67de72d8dd5f44bbbe52b199a023a9d5fbc5e12d3b317a96b8003facad0b8b02f3fa8055d0f12b933a55e6b9807c92090f1f188415f4425a06993bf4b60f257df28faab00d245e05c9bf30bdf03ac8c92027e0a19fd10e62a3c31c974a057d6e083332f2906e4a70978355b5c072a31046844c6c2a99e475192f844b45c84168d9dd6a9b5acd10e0bf69f9b7d024db19d3b5262df7481befbac3dc50741504327b34ad8a150c25dbb3389e05f01e89a7763f94bee4fc38b9fb5bf8bdaeb73952ca5651fd57e47724abebe952b05a787cf9ebc6a6486aba4b7d20b5610b688080b4c79ffe42e03c7f0ea76f202007718ea7f029700a00d1341a25f3a4589413b9d964c989deeb66be4c95eda6c06fa772230d77071b52d525308ce8c6e9b9aebd693e2fca6a5eeace8e1a7dd43050e7970a0aba1beec2a6937a0c59d20ae9523be68bc81ec331d84f3f83ecade01e5f0c6079019d0444242c35a6cf80a67bd1456de2fc02853719de549f33dce036e4050abd7927ca4af76d8ef7ec687c41554a2da3a1cab7353e6b6890ed03400d05fd00ae8e2c2549c6e9a08282941a03d3eecf622c12d6664759bd1b7dfaf00eef3b0b91c96721b7453e4aeddafad74a0894ce3c75e77b1c98f29980ea65500cbc15a8f2bf729715f0a0d938d6d4c5a310a9851ee706faa19ac9e8fe1178f03921a292460ba014843a6a9b2d1683acfa98d2d8f1ca46ab02df2e37753e9be027c2af5d328f0ef06d076ca196cdb808e3351ef66a3ace13df02cefbfe80c60067eacdd2f675ee5b67a449582d7b1275767177c30540077e0645b7178c4726c0156347be5f9d09d442895b210a0df1fb57c5149e474f32c4e0b011fc693547b06acea6b96e27041e02af49c1a01cf3da180f5302164c1f9fae1de50cb7ad5cb049f57557c3b804e6ca5d67338196a1cb5661addae8dd651130ebdf4d3fa1e1903ae472152ad2e846fa567063b34fecacc024504f986072fdc32e18b0e1606a607ed748fe05d051513473836098f9ffce3439d50b4394d3784253e0e6a99d82102016273999b6a01aabd413bcf4ad17667bb7e16797098225ce837547a290250076645a6f88d58174db54205a58f551c82f601a6ab8bbbd7259ffbf8c5a9e26507bf437ac2f439569ee5b708ae53395c6ed22beff33e0cc29a82c1b056a2d1b107da6a0a00212a23e2544acd4559fdce0624aeed39045b26496f49b29b975a65028323b5d53a784bed9f19485fe635c9e5c1b46e32388998584ce20b1099f66503ce53c98d1c110b809ddece681f617c5f438302d69aeede98821c3eaaf45bb407409b09414b66bfde73e893a58c417b72299e5a86963f493d3d43520940449103c1603e39c2591c932d81a7478e89d446579ab28044955e589c8315882a57c80462129ad4641559a6210e9a696273dc7d61a63407459657b6530eb7cdd9de4f075040ecc8e7142e63747826d507b83d83900907ce784a64701a2aba0cb7371e012433883bb8b376cca07c793b5fdf1fcd1e7a7666ddd1cda3e1aef22a7eeba0051bcbe478c7e4aa8eb457a973aa6be94175df07e84596c9f1016255a8fc6dad04fb86affe9c7dabf1f0190667ad2feaed26dcf2fd59a6d220ae173740b4f8a00337965c4f13384c056b4b646ed684e7e2bae5df900db1bc3182fa9abef503190416981fb0154a33b1a51f431f6d783cc16ad3431ad69f12134912c5ff12f3cf022a6599e3a9bc9c61c7e4af6046db64e860c8ba6673fbb2e89984cf7292742405ed8af61ff5b60bcf263474e507c2b2b96c85e17422229e8fd3432ba505c0bd035776768550f3f82b6a7c98668e7eba38475d27300f73a62c25142dcc0a331703fe4e5f05c8ec9768bc24f26eae498189b216f7dd6aa67ccc74f792f2f9f72002611f7fed0698548bb562139fef83ed3707f7361bfe02826f956dc92dcc83b7016e52d52ae3842852d072c86fd9f77aeb945422766fce55d5f1c9e1ea99dd8f0079465c16beaa452e6077fd2ac408c55e0f80c36f14c2e8496c472daae5a57904ea5b4f8fb6fe60acc7037b4a14e899cb0280adc780ac091be571b95e19989207dac4b94e3dcbd67abb67509bf720d3744013a5f686b30687252baf859f229800e367c105acfad68ee807053aecb08eb43201f72ca241ea8a2242ed358960fb000d2b4156c9baf33e9f8ddd5ddf419a357f317e7ab25c93050e7f60e3d321990273bcf4b686858046b139f2c25ba452b9f400752787fd199caf0aa183f9a6220435a08d018e957fc15037ead73406f6b63487bb478cfd9217b3618e8ea2577201ff3d6e0d4f39a81d86ff4ba73365bf65802d628a2f515a7445a65ad47d4989055b83d9ea6f087ffd1b53d5dde789da55f96f2934365d4fae85167890fa620100215ca4b70c48147cbb632e060f36039f5d5008fd474c943e89cba69b8131bb061f05f6a335bd819ceee099285458be5c9b78a0cec4ed4ba386cbc8d81c76cc06dd6d1dc7ddf245ec7d745f634a1967fddd71660be6dbbb273ed03acb3f359e0742935b3e122082e65c1e02372756f9e80a270bc84ffaf02c053cdd040db7e4014cbaced50e7b539b9d24ffc6fc2989aebf89afe31eb35adfd0a03f5ac8c7fc024ee13eda93459c2ef1ef48508d83471697658688e5475475b12335aec27a840121ba7b73126453cc4dc60620b6520101c2f77985f446f8518c2fc0894763a303e1187cafdcb7118ad09663e1750f26dbfb47498a573e602f9deee871d4bc0205c7bd5672c62a6c5e15592f84e6012d32fb18bbb1e38edf346086ec46d3726107ed7f020be6def92593e9f791ef911ad4e3d12b33291f30dac3db7889cd0d42052ac584a41c5fc7db58619cc3e18ed040a7ddb2acda6c98e05389a9fc64d349013f0f9f40289fbc0ed13d11c87b021148ec285b8b31edc56bd1bdfad1b019110307c0190f456b49cb0e180686fe55c26bbcf6d34c3374b4ac6d489a212a3951052b5dc725dc8ebd04fdf801de25e6127b72da2a6cdc3315bfd17192298a414c06ee737e839489d072d6ee09e91ac6f84b939af7044d297787da5742f84a85fb02575f49959c4af9e6bbfd643ab2f48a6b4e59899e53b30e4c2a4f9a2972fb9207efcf30abe890b4974cdbfc1e53f074dd01371153602689416a914ac9410fc307d95250e420252047c7c442568f365834b6a070f8b8e4195e1349747ab28c3a01febbc1817e9f39a63507972f2d745482dca199c6c1a7c882f5d606dba9acd202e20e3e793f334ca95fb893d2d786e4e292c738db2f27ac48aa83a7b5d724ce03f02010623157577302c4c1f560012d42c8f127a1664883aed794771309a27d059f314432fd3432ebbe7f9944e83dd80bd12ee19531ef2a4d624c8e9dadcf72011ad6f41ba4e3ba5d5c4c76c0f46fae3bbb867f0b8d1a9e3ce7e1bbb9fb675c01035329071649ef0b8330e046dcd72e570ecf83ca2cb2cd424589e0bb004b9b0542d42d898638f7bc973dfe90ba99f1292bd1e1f153a46edc168bd3fb04540d035b5f8d74f491b1edcec1e7bb74cd241427b5b97b4c600b197d3788039512970480f6d99ff05eedb973f6107b779e3415652e00243c05c2abcadc8c228b790306f5dde2e7ec6367e1102bc03ab6c3efc6f561bda71cd9fa967c2149a38574f50598279fc08f0b3fc9c3acc935eb9fd5e42db215a02a8969571aec1acd0c843d07215f4c330a57d8e09fdb897f17261b6a50e5a1fb797204d44b3a9c7fcb621506cc97c81d126ff47ab385e9a8f0d6e45d67567de08d621a3c39c2632f9d4a28070e73d96f3a67310eae75d14f491433815dabdc254ea6a47f49dcc455db1ad903e7582b5e98340d67072b3eb4e23d3279cb05957d8a069dda3a2b377f93149e040d7e2a01084b202dbebc781cb9b82d9e215bcad0e4a2b5c01855e1b193a84a0695e2541aca2a1b97dfe9d77b49886ae55b484497dfb45f36688707ace6e9990716b78246c4b3e3ea5af8ba5666a05cae4350c03c68489155b58b9d6a82d4c307d73d6c908bc459b87e36d6e0a0c1157082fb1aa8d8650b532aa317243c1cd4008b8f8d7143fc21371d24654a0669c2bb2668fd171a2c141bbb3f1ff7ec31b90570d62e3e5d94aded194b2e5b5effa833786dee717bdcb4ab3325b0b2d7453e05e9e710cdb97fb3ac6f70081250663639ddc44c4998afe9cbfd76e0888e8827006bcbe9f319af62541851d5a9725d47325d0e4f2b745f4c8f356b96f9e8fddd00ad1e83d2134c6835f6cb25bd36c61cf32bbccc440c88b3a266c6bf74264bb4015cbd55ee355274bb2f8744b883928ec1c4cbc0ccec6544b0386e353d51d23a04bd4406007bf6c8233a99591f0fc266ddc5c159603b474fe11710c00c4dc1c6049e635521de2a3f79a21ee0a9606a5b0b130041d6a181ae49844df6a7c19e8f0697fa90467e0080eb26c2d5b48d17e3dee965b048c7e55be816181c6e3591ca012f753c25a84181998cb876938dba3c776c0efa9e58f220973250cbce3077a1059dc331566a314cabe59903ab77b2f2ae00c5c99a9b68559c07b5a72d42351002bbfc156b34a796d1a52bf1fcf8c4be3da46be865815af1bc0d1caae54bbae7016a99e41eba5b16e7b9da8c979b8ae77dfb421e716cd1aad8887325c438ebd2071ea12bcac1c63a8334cd8c0523a13a1c62c3c3aab37450e01ac99382e9b7f2001974152ce429ee2d9bb02e8e7d0d6775d8e46b38ec7e42829822e23b08f5460707fe0904462da3ec140fa91a3b1d4b4b2be6da87eca7ef49571046d7a35a54026af80f5e025f48753bfd4e502a99480884119d9fa576f720920ae0e891efe904f2524c9c22c8a0c4986b92ae5c47d040549733e3414e51e315fdecef0b038b0184ae8af9b103c0b2f609ac8e30e3e261da255a4b16301d0490e66f13ef2f9901e63a922ce38e254afbe3436199c316b53b0028a9e96bfc6f0617101ee79f5d0315ed454bdcc404eca203fcc53ea13121db14c760d5c50422eb23263fb196aa06e0318da73db3c2a7f4af4de384c129ff621b3511b96a58e8f9cd5af7557fdd069714315cff7aff8a2768267a87d8343be6c109659e1688bcf52bcc042dd27b01bea75a1f7e2f4e10a3262a8329cb13efa38c34928633f00f31c504598322b10428b14a677f13fc94ea281ed0f8f4d4884cf0ec42066eafa61918431624769400a80d49b32883b7c19b2d0e660988443583982b0c0c5d401f2da23e4a76255b03b34598e0b001f2d77f149e371ead4bd800e05379ca8352e3f7f7b27738c065032a8753a80f08ff2bdc161e7d048d716ec2a3e1a5acb08e0271a5a36cf316a001697f0af90d16613f72ee2219bead6da85a95b626d729adf9ae6c249417bf190078dd3276ecb228c9c0493608ab5260721538fa89ae93773aa615523ee89b4b0694c5112f7d9740ac12854542f2eb0d4ea56b8be8bba8bb74539b5c6b9e91b20061715053b6fce402b56bacc45e2d9e2d61a9b996477ddc0a170e1e39242609063e572e09d4c9c4f429f3042a2f55808cbe3591c5dfec05981f1a9d37a3d56901b59679bc07dafb8296bf694c66a25856c117d9b81b7554e8ace6bee66e650e01b1d57f72c30bf936b56570921cd487967b1b2025ec9558a11b800993ab779f06395d48c584003487086bea0f4e4c4c5e1b5b9f36283fc1ada9e30943fcbdbf0586b5eda7955ffd0823b05f35128498f5b46e4cb08e0891e08ca53d2a8bfd28025d6ea3fff669ca2dd85a9c6b5a30c5692ba8a8973e9933de7308260d8d402403bc3b1b2c482dc3f365097aa67cc2a930e8225819ed4f0bcf6df294edddcbf5055f462c405b122964a20d934983389dc018c83e0cd9a1a3ef412de29a6064cd00284116adab13f706c0b5b0cc1e1bd9e83a76a90dbfb55e0f3774aa733bbb1900943592ce9e4e627985197bd7b9cdef502c61564ca93f36d9eadee12f0f1aad0413e4c2d66aa5cb696e8e3938651b6045a6773ff9bad094cffaa9dd16602f2f00ca1c557f460a08f318065bad21d8a43dd79705b3aa76cefd37ab5c63df794001d9ed3ed4adf14cf7f301c84c970f4957f9a859c33736afecab1cdd9d05ff02056332afb2c704cbdbdb68011399e5eb5ead2e814ddd3b6cc6d152fe5d9bd992009ad1f672c503bb5c07b57758d3d8cbfa53a80d93621744b46bdb2b31f2c5c302d7468a926cd1aea7760df676f312490b6e6e7870f5f96125f5ba8ce6447368061fac0f9a889d463da4208186c4708f618c22b4e92835a8ec555cf88df1363b0564f023ad058971548b3c23bb895bc461b3da0f34b0ae6f6551ce80755dbe35058567b8c58b0c3f2497d03f8346f98344fd894128c528e6e489c405242e2be205bbc015face6c4e355b75a092f7824f421103ecdd00f07d89e6166bff84b163057e7d569a4ef761d520d3d077afe025274ea45d78f2f60074d7873ed4ed1fb5051a3b52158fce1cfc820f8d9e1fea839e7176c053535abfa528c8a400fc041e0125a48a4006544e1282197778d228d45a6539cb1359eee15cfad107137e2b430611b8e78ca4de84b5cb32d53c273c0e523146cacf21f6309c1def5ebfcfde9f01cb17b3d93cdaf47561ce8ad0747702380abfdb7ac9514c0b7f3a7444ab525504769b2c3082788f970ee4e8cd07a0aca14ab212a700bfa2bb51a801d75cd2110139355d3dc665e2df644a49e12c0921add84cd57fa16bc19f69713a911160d706b9541c8c051eb8979853c5b31383e3d2fa8f85bee379e70c4e6520b76fdebc02de9ccc099d390282cc610fdaac817c79cd78abf498e0a9a82c701d6c65a1d604b38ae222fc1713301bd6a4ab3a4f932999cddcd3e0cd7e4e2da6cfdaf8a7cb03f64fcd4ca8239ba329b2e83a7b617ea7ccc3773a80facc4666fc9034a4708901e12adb1431f5f92fc81fd43e5ab34d77c353eb3b86338f21e5cd4b45059c5a021b410991ef4cceaad64146e69e73d6cf71c8736a329de2757ee01f5d116f46017443bc88b78be1f05f51b5a23156208c7ad3f9916f88e1300b672f1174cc7b06d7d7e047862758e3ef57b88dd446ca81d28961e0d50677ace76eb8af003cc10340ef3bb50046d359643fdbb681e4ac7a76062bb03cfa9aa2111f966e550c1c016fe4f629a9b37c119c6a23e91201e86df42536688d0f662b322acd5db7def706a4abaddf3589e6075d4948fd09b9751998a28d3d016f82c31f717d207d3664043da1cb5fa10e3250aae5d980f58772fa75bf6a1bb9935bd34b9578e5e65916069259fab8ae7057d6f0fb7c818cd540c811671beed32867c336a3a5cf3ffcca0498ef9c95f65b668ded306469518d8ef31ccfd0f35fd714bdd933095d4aec000384fc18d99bed9dd9eceb9254fc9425607ab29c9137e3dad79f1f7fd26dda8f018064fb89aeb063bf60b1db70d25c9544e9031f1f7e3674e7f18ae945568e8b052b4748ab52acc06244510d50a0beb54f27343a60ed74af3bef9ee82f5568b802c75d7c13502a71244890a277444e4d3a881251348a2c70978aa0944acaf5e206281a54467baed0d6d0f9a0e5f8ad42404780519ed3a6d191c44dd35f2cf93f04d9eb26bd57c9abf02dda6958d04b2e273c4a0fb59f0c53095273b23cffa3ba0074f16408ca131433f1a69530647c25b42ab88fd02abecd78a8488c77c571c0035e65c1e2f5e5507ca24da72f7a78d8faa9b6708fad638fd129eb68bf9a3e6504548855762564dd55c07d57e88fb9ac22e3b41829a21f8d4a6c600ef686c34307effcba4e09a879f3a88c4a29316b0339588369f965f4bee5174acc8e9ba81501d08a42115b4a14e592ff1acfd1e024eea5fd082f1e8fea938b384e42cfcdf3067bc0d6710bf57d6218018bc27bf603998ad33d9a5f6369f09b38253df7c05405cc50e375dee5d0c98730f74860c75a40e90f3fe5b5d0be5f79f00bcea612d502a8b98093ccc2f3fb3485dfdfa6337743db2da572294917baafbd7616f1ceef0596444749fdfa66ac5c25d489c74299bf28ec2a5cf1db269e694b173c0cf2a2022d47f53f539a5783649827011c7729a24ffd94574803f4b29a48ba62f446c7014738c00063da23cb182c3a6cab96a2c09f25a568d5d7042af47d33b3a3073104ffd4e68d209bb543872d049ca64d056d4c5b27efa9ff6dc21874e66af884df052547592585c27d85a0cba2f617ec519c2ad155412a0966cc30c8a092e28f0c0324cc0f7aaad36b2c5c8b4033f594f97e7d80163558eb787a635d3ff2e1102404601075dd15c7d764c636de749e7ef4c36c4a40d58d84851fca3109df782049052bcd0ec1ff78ec103348c6fc193b519325249ab076f541c53b6efce99c826a045b82ab7d9c8e05828b75d930c161b520f2b6ee5648425903810e31d360984601a37f3cb1dbeb4c37a8214fec31d9abc4588f4a784a0931c5a72ccbae13d661077dc3727029698b2ec0f1120db38a6520cfa1b599d241413e3069ea71c734b807744e0e6b13a2dfa3c023d9ac3e64b89c01ecf97a96199ec1c8fe1cc01596e90606211e4c02884f5e14aae9ca069b1fb5926e193aad2fed38900a4610f3d73304027b26548cc4c11ce252ea1c37be8d88ca1bb0e15ed1a54ea42dd3c0e5898c05ce08b9c4ff9730c18d39bb6ff8c220933c36f01711ecb9593cf2c74681a3b4016cd75dc82539f24340b4eed796f66998b632d7071b1c8b95aea60a37add4af0445871def442f0da2d38f742b9273431c6362ff53990fbbb114a1f63432bc9807a0c20e27eb4442fe07978a2a910e57a1c444daebfb963971db8fcdc00b3f2f029a8d94833592bbb5f09b3d951e2c41da92631469d3b5ddf0ae7e0b02e1137305c8e5225c9e5850e7d640c43f80f1d930bb399f85dc4f354d360f02994c9d4006140c128c0030b2de7e3a9f40b9400e7dab8481c6c88c3ab974cbee4fc65c35062d971e417a731e08e8717c37e78dbd6a1c3d20336e020ff8a33ff40f07f12801ddd5078641064eacc36d7e91d5c50dd650bfbe2e38551569db7533eeeb3d5d01dbf25e6367bb398dde7321e23844b3b7f1b554f60f33f15804eca4a0675244033d6b192ba8eecc30099015b22c91b947820260ea03a10db30252f609b78b710134456d8c54f1f64dc24d6d62064b6e34b6a55f8a4c9c37c503030c9af703140157d393ca41a9b08e19bc158e42e9d7eca5cca88d8d6b35d28abcb1a802f7820315c828d41d5f9ed506c4cd09d9414a578fe3991f4093ac5573ea2375e8845c05935a7835141dbcb09571f11e5a38d23234c149ab33c625060712ffa4b641a402b55eefc9215697f117ef24bdf88a6325082bc4ae0fcc6a2551657a5bc4c79403924447832c1b88d1f9fac2e3cf84cf3262627f131614707f5ee9319fcb335a065ae9421659846931cafe787879303dc9d471f6383fd604d81bf7909c6a03c4036779d758c87e614380ece87ca1c684f5dba902a221250cbfd081703c853629076019ac3e4b80fde5892e4af464ea83a9ef0d04cdd7f954ddb17454429a0ec3075b2d4dbfca5e0da2af4e7d4805f55df115f0c01b6429fa5e198220832b7aa607d8b559a24a2a7a1f3aff64d0a18773f6b12f9ee529eb4d983f8a2513b1f33a00ac57b929bf04baec17cc957da5baf8eb8e90b91a4dca81a8993c4f39e3d6f003e749a05148b3151eae6af8185d7f17d5fef3f28f23f139048e9ae90f998a1b0191731261a82cab26a643e29b3a7fb50fef55229d9c695ca0652345493de6270405e51c125533598a28538994b08a9636ee76206c9ab87cd3cd503ab05c8b4703ec69f74f9e057f81109937adf6c3882160650e2db3d3d94d7e8819518f15d8079371418d51a7b0118be0a277b9a420101f89c90297e6da2a6f92b15aa4c2a6031aa6ac9df2216928f161fb54f2ad6057aefd4a58891e2e7cf038defb5e687d026ecdc3bdacca1444e035699b78a932d95410df3144642e8735aa48ee06f4ac022b444413f20526849f435f4699353fb4c80c97375e7832128cb8bf432cce34079741e6c2984e68ff0005ed3b7cca7d82bfd58b24cceeca2030964b3c8f62cd0193b701ee1633d847a4b191d1699c9fbb2cc3eaba09c949218897664d5730f803855c1689c5aee847bc3ddc1de76bb0b69891145abeb7db30272da8330f11b2076f875e08f6ab5cc7ba70278d626759a54324680172a7d6ac135d1d22fed93c02608da4d526be99c28c3af50b1698712acf8460d074c0325223e0659f81e8890769e735d483b3523fa249faf46df6ca1ef58f199375e1b59382af1b4fbdba0f050d7057015b0ef61898cafad4f2e679eb683dda1a3ca427cbb2f8437a852306012970937820c1f2c3b9d6e396f82221d38d7982d4ea20e2ed6de9139371eb4806df2886d909958c2b464c5e4fc040423473d25a0fb67f7b207590048e67c1150739b4fd064dc342ff1e4c97bf8d9d58b06a6d0ffe973345be7861192178c4c30208b274ed5c63ad0ed63ff88314bf84c6799e9dbe9f73593c2fcfab877baf480420efdbe4164d6127ac9b5cb45892eaac92033d0d3c6d5dae236dc07d3237fe0410d4f5abd7c21c867fe52beacf22a451040cd49a3f4921ce9f8a8688547e73043383ba40747c57d363fd0de91e035f0267566e49376566cce596445e3a83a1010d04b2c2bf006aa476a1bd81b0f6f6a5465af5cccd41153918e5e610ba7fdc0561e24927569de4e1241257b7511ecdae6789895079bc79a2c5d3933f97f6180562a50cee01bac63d531423ae65a65e81e61b6816e29896e0c4299b07acc0b8024bb9ab0369dc5175710ae6371ff120dd5df40dc1a18a45f7d10fc9b75541ce00c2c5e9dbeb33639ae045bc337f4eb8130b6eb0d8c2b1a67d89616c179ccac404ec64fe5ae414982769ea43afd506ad100e41fcf306c8914f542b0f58a322ec06012a1140008ed7867b4e42e0b77ceaa62357d28906d94c1d02e867894551d602b0d66e068f8d1c28e871ab497b231e7591dd2da68a77036a55273d4a011062048210d926d42375998e8a10a0b67dcc61def02bf4ab0c0e19d085a6941fd919053948234dcf90c1b1e9bfcf8318cd3c101a0d59eb93dcf0d0b3c39d373027a804446e1d66f183c8855ef6d698fda7670628ef56844db0e042eff18fd465b26005a638b2af27e98cb5a48a4f5cd618502ab6cf4b85cd988e68fcf44de219451101a1c7875df9669037cf689c3614d4559ca6120ea4f81b56f0e80a6c80a2147d0578dc013d68bf6946800e64dad95db5048747ec89aaf3a2ba4d647e8938096a037dae84a1ea3ac93691754c350eb4ecdb3bad5d9c6f5bf173fbda0e9fbafef60741c07cc77d601b547bda99b7aaa8e3386c7d7bda8148ef6059f0329ab1a9b906ed85856178ab6eee80025ae4b7df4a2cf9d7e195e0a321c2851a48d0f5d12604e05d83a77a4a098934f097ca6ba049c5f7ebe3ecf2c0dddf336c2834d2bf980623575286b483a348025b15963383ae6ed0db8bb55831c6bcda682d442f109f0649e50a15397d94a234692688611f6a5b3d8a8d76e7dfb5c6f4f8894a5907b70304d871164e93a84ae6c8548c1b7fd3eeb1219174aa9637223a7a19a5c42cbe0417644a00cc24bb3cf690a74ae198185fd762f616e30feb0cbf1ba5520bdaec044014fd2d759a340f3441f904dbbadd01123f79ba580c19c3716bea0307f6f403ce921ea1594cace2d7fb84a48a849590487db7b5fbf603437715f6c2a41d9e07e361e685d7dff3b0ef3073bc88489faa92bd63194b6b6ace1409f077acaefc0765f372e00eadb18fc1496a14373b6ca6faf240e28226ea97a0f9615f328a1a047da10a3a1895bc420f97b6775903a5953f907ce33dc5bc9c3012cd4fbb06e405f69cca021fa29b1fb0e325af764beff6d971719bf610414b77d7cfc12e02e90279413cb35db96e720fb00ca8bc06681f025615d2087ef21ec3ea1d0e098b2205060bba793d8e49b1f477016e45c8fd0149b13cc3b0b302da85cc697de2714b059658ea65459f00030888cc8904697449feb36b5cf30be07150ffba1c4885e104b9a423ea59f84c592e2889a4a8736c884190e00652c37e28e87e6de6f5c5c9017d821e1b42ca68e512ed5203268d565bb597f56d94fe1090ba02df95ecae6806f02922451d94ce6baa566ab4130372f6bfe274ad1d929bad30f72aae910988034b9a0a7e95f9fe318de5ae40694655a1c8ffef94bd3dce56a7b197fad6f86203ac3d7c6a331cbe02aa3cc61f85710c10e03b1d868e2680e874ab074e9b654f002b8d29d1d5267d846d2819f3a24888d34853e8c6e9ef88945e9083ec2e04a0050ce9404d8e75acde0a80ca6b3e8ff03aecc29c9ee146a0ecf41afba7d5e80202416efb50b59e603263c432d7eef9a8e040818053bd6d35d22e392de1b77a1b00ba61df5519a990ccc5118ea33345d5268d0a2c3084aacddbe274cdd78d9e040097cf55ced3996996a2c3b3ca0a6451b4f8f6420d0331cea523e2b298ac709e00062b8a222a3a68bf30ba12dbe0a8c424842c96f7a87dbb9206ac14f5848e8404797fafb89b521058afb88cb6272f6128fc10fff01cfd3d27bed12b0c9b9be9074240277a90f6aa346581d5f3be59a4264c4af8e4140f619fd6f6571a827494042def14f83f7bfe892295d5e7967ad2f35fd16ac4ecee06d246093671052ccc020e26fb784ec380a01da3b4bfcfaf16f4a2d715ceb61a1ea37ea16bf218947101a67a677ab9d272ca9a3b3e9743df6ebfdf8794e676549c0bc87a9367aee0aa0183a4c41a7030465baa04adf8f9867df476eaf7f97ea737a4d864a9bf6ace5a0726538de135ca5e80f073fdf48f934d90cb456e465f70ebfd3b47a51a9b1dfd032dd5a3a7e20e866838e31ca7498848ecf237bf626c9bd8ce4be6f436a9455d0337d56cd7dba0536ce3f3f42ca4ff03c98f3c257053b83c552b50ee47829d67071f3461fd10e9f008874253a41e47567b1c5004bd743e114f54c78b70028e5501019d8e6cbe4ef1b6f1a677b7d9a8f28b64e064561fdf2bdcd1000f57a4e466007379a7b06be421238c1b9cc1e236d4bfc19df5e5ed1d07d3ee94f47b96b9dc00f16461dc6529a74fff2c335cb214baf472cd085be18686057b37c3f0157fa300e749633c5fe9e9a0aec910340d83279f793b6f0cad28d179b5d633be9f8c890525e18a3a271d7b2a93600b62a303ab531048a26810f19a8b80abfb51302a18014112a5649debb1949a3ab8defc17744e3a83a5e725727accbdbe3665d6eec902fabe21d95679746068157e48edd135f64009a3977663163aad6fe53d234c390571d8b57dceabab843c779230cc3c9a8e1955d8afc6d97d4e02c7e97153ec8604526f13c437ceeaa3efb7bb908aa29973c62691d04f50354d6286f9a34ea39c07370f166eba34e6ac22a9ed2c5f6c208ca9fbee5da4b056d7f751c7562eaf1206c3e69e72af64bbca6c63aa9a0f34656412c4bbf8ad8823dc7ec57a049b626200dc29eab948a09cbb91daaf7dd91b7b7bae4b98e92338653d7c96d25458c0b004abe2175a86e7443ab650985d2de29fba56b1677d6156b995b3c75211f22bc7079d43c0bc749dde9815259598dc246b9a1faed9eefa2bb2cb867e72bacb7d7c05d72c02eeba5a382b66b872a579fb4513c78058409f290533474454fbb3469c078d9ec975dba33f46d0af87c32efe6ccef45b446111176096546a8a5e7fb3d30315b5dbbc305f37bdb644baeec1dd11d8d5cc3f36a0e3f5d571e229c12c23de013bd1f5a444b5628acdb2602adde130e903e120e62e4fa70a4251dbea7412af03a6662e6ce6ae3659407fe5f6f5fe7d724bb4ce5580619d4d18a2a0843127da07b40a41ba3ecb8be9680376a55f7ca38fee7038962b5d441e89482771f3a46f02f8afd345ac0abc1da930523acc84b6d0b4668b1b25e50ce9328e3a8c31911905fa4303e9bbf016caf2f1762c73e530e0ab7a631f91b21cce12dad21f6a31da049ac4fb8690de5409a6db8cd3ebc95b63a5a1cbdb49265c0d035b4f43f7a6cd035b727981b0ff4fb2eb012214f756421563fb24d6c8c2c052583ea64ba5c222030bda1f8b01c6f691cab79dbd25e1e1c5f5eb78dabda12c14de16aab3a6e113049bdf37c43a337e9f01803f84385178b727e91e4b233051a1f1671d479f3b9b03d22a292212a74a87c2905c7ec2cb2d01fa03830581227a02ea28fc92c0b09600c1aed65be89ad76ce46dfa87dc22676d39b731282d570c0dd0b825a6181f5c07098ccda21763f420b60594a28202cfbab96293e18d7163e87e44a38584a69d044cf9af33c4c9b52d8f49fac5fb0c4e276e96a9d0ebd72abce61917370eb07b06840c73cb2019a6d1fe595f525eeb014c11ab08876cd18fce4a8f872829391201f0734e67975884cbfa398ba8899d6bd142a53050a1aafda5182b827970594c0406c6504a2479f633765b0c2b6eb96094121fd41fcfa5bef7e13d92775fda04029291141176c95283f1c5e6610dbb7665234073034de4895c0a522c1e5d9d0302ca841886e9b642a71deb39caf593ed73034f9ee21106ffbb51333d4042d8b0060b2bf628feee899ab7753ac9920832dbbe8132e77835b1b57c62a2de02ca150709780d5b4502aec62edee3fd28c676229aafc14a9bdd0cda07b0c85d54547c03cf67df55898ae1c11c2dd721d8ee0b160c9cde6f7167a5fe7521729121f91f0583dd2f60a5eb9dd642c26084835c6710fe76d24700f881020d5b5b4af4c54a07f3b7da5bf5b0976bf6fb1f1c7a3008fe56a97c55cf24d286f7509fdd344f34005d21c8d735ace4ce67463c4fdc8a8c2dc673554ea524ef28febfa27753193b026cff2e2e0a12c088cdb458d37bd78814774f4ee2a10dbcb5337993c633fffa02ea8b7dd4aadd9db7f12f39b74bfad4d5e9b0f7e988f12daed84772b66a4d6802b5ab766011fb77cd6835a0cc7c60ac822816fc6ef4d20958f1b81709c14987034bb02b3cc8c0e2a861617984be946b978b5fc178b257b498204fb3032d86c704edb8e737705c52b0d898dd186f77d8cb37dc4de0cfdaac5230ae09029a5d00075d8e5aa1413876576a02c325da9da7393f94626ddf28df47980a997cd16b130101c17128c9e976653c82687c5795a3c59affacdc5afab07736abc8de3d2bed06aca963b053490ad7d6e57b58dd8125dbcefa010ad5ffec0f31b158ed8215d305a622b445e002b6fbcd9cd8eb4f4ad3b6a7362557a84008259bc9f273d61a620098c8428bf2eba4b55d3085b22ffe28b65abf89b225f1505eda2b716e42248a01e4d2e37ae3e245c3b7150948041e2f2dc67ebdad90ee1f08f662755679d41801688f6cccd8e3201172eb89afc07bc1b7f69aa33284b42f1aef8aa1fc8532d505e07d9faa031ad91fa4086c23e1c2f5f72a021ac19acb4bfdb85569ff96bda604757edf06521c9a05ea8bc2ebd950ca59606e2841b903d6e40f9aec5134889700dc22f33ad1fcaec2379efe172a5acc7936ee2f5b610a57782601beeacaf90b05a01d47415ecf77a1990c0e0d691be8a35410a3eb4d0cc3b3a401cf7e60ed0c0412f964cc52596950144eaef87e50318bd52a2ba48b5619ebef18dcbb03aae406a422d870a46db7e5ea97542412a1b83d010a3d8c3784a1905c6436e4ae1632062d12f098cab2974d6a92f6c532efe3de0c990e9e9140e73cc41fb156865e0a04127603be2b00411b4ff9e1016325c2b921e6098919a8e2da1fb39bab43b40c076639767e1af643aa7e72ec266f57371a75dbd52a7bd122bec4bde1c7b9620705552b5b244bae87338cafb5332f1d46728fbbfd3fac74f1f6addda58d1bcb4a005fb3d8c3b24622943b31331bea618cdd523dee4b5c8f2cba2540f2da48b0fc05b1ddb307627b10348773829c7c463319fc90e71f358596c2974222e961050007fa6a5d08f0ed7e1a623f4b800ee528fa8c7d49a5bb1738f4ebfdf31a28ec97024561c77922f172cd71ae0b48afc9c82f94b3a7c1f4143d1e87832c1753affe028c906f0b0eecf4f539c0248dbb96cd2d2c4ac0930979a0ac537efa55af65cf029a4e5fed17910070a2dcd0a1993e620f98de07bd38c06a67dffcb8f7daefaf02858579a5dd1a474c1d4b074a54029d2c164ef7c45ae827d9857b5e7df848ee0316ada3eb4caf21964d70e214738336d4f52406906a892e3919ef533b080ca504e0d344899f120ccdc7652b6d45fe9affc8f7873aa45613c3e9e2fe4b74acc9057eff1e2cde2556f9bb337efa79bc7dc0352133595b68d1d826a17cbbd9b42d02037e97da8759b89541627910d4a035c10662e737f5db9a08c80a3f7bc8fdc101fe5bca8784799b6a18f78e6dfdfcb73bc7d4144040c08ff56197c47d99123e019459975074568906badd003cba0b85ab72ec5a175d7a8572e55b35ac68a4a800409f0f03e2fed45ddbca16e60fa5357b5fd1e01693b0de4a1606737f4e71bd0157e26e78a04799b8d95c7f28d7e4fcc1c461da9f325bc1527d2ccfdbae5fe207ef21efbe1e47fd79c81c8da9be5f8479ee9f03ceb5d8a210e0143b3f844a050601cf40de362e341f0fbc60c5bc92b83464a9914be4f51b8dbd33d70ed31ef4077831707421f43923f1b904240a67ca4754236a4bdb7387e6357bb31e61d5ac06a1c9990902b4a8414b28eef58e0cd77ee94ef9f3ef896e3575575cea217f7a0332bbc8e702dcc00af60668d3c0049fefa283b5de27566a0bf2be97f4fb3270074439cf9c48724986916c088d6fd1bbc9cf5c3757ce5888b4fb6c98efc62d7d024ee9be3908ee5d65c8e53b3fba71e5b5e98d3b54a21b525a9b2815d011187b021017e7fbcd10141bf0de22fb4383c7e75c42fa4eec9278cc9e260312e7ec4a03689c6460d90b1f7aae39cd08b5cc6d6d36af9fd82e7eb1b20ad71667fb9ad907f0da77cc696f8d82697e5d8fd65c93ac99c0a439535ea20308a24833f45e6007300dc1a0d4a34d5649ffa65a1d56204b4d1770ea30955c3941a83bc038510006cf72dabe690c3ad2fc075f1bf2c801574528de40a415703ac0b2639e319a27078d6bdefff676dbd3ea35d807e770d419327866b2f383c43c1ac91908e2bf59055db828cf364273674d62f8c34b5ac5d79e2df5825c038d13c5f788c681dca2079c8a771bc7366bcc6e6ac2e405f52476438db3a05b56c674cd9417939cf2e50037dacc85130c395bae1a51976831fe76edecfa486ebb817ebe575435eb8e9901b7fe5d6e3539b76937064a0dd8ed81559adcd4fb04018d5a6b223fb0afa23706522e0e044444032b64252696296099453a049594b5c5098d9f64f3a13b81eb0270f6fd88026dff40b18f52e0b280b0d567e7d1821d49a80398006277cdc8d104a4c7f2cedde425361225a6836260b07ad7c57e2cda4742e05ea27a8449693704d1f6391ba4f3206d1d4682ee2a9e2454b37e0781907fb0879dfdacf91a5776041bf533a65da382099a5349421c2fb609da3e5e22f12ad7c20c6970c697ce06039ef3be645f2f60181979a431e47ec17d61999f7e1a10a7adf4bd492c68ea9300182b39e42e7a415fc0816e7c7d96dcacbb591639bc6affef4f9276c343a50e05ace9827c86ee0b0bb6c19da5cf3b78aab552c8bfb1561b0cca0bab927678b902b36d402316eb6b2c082f8cc42abde410283a5427856b6e05b59fbbaef6fcba007428cd65bf43380c42953810dd9a3d5580ad54f38fe01c414b1190b0ba81ee0409fd03c6310d7e472d2a5bf1cb3f14c7f002bdbd54f641c3a2577b4dd0684d079dc68fa18402e1abec5e8cdb7b55d44ab449bd1a7d06e94c3b75879dd6cdbd00d58ff5b063c315fdae2a929aef7e4a3fd928a9bb2766dc9ea83354ba3abc4202de9ca905fcce22e6abfa570c812e81ed2895f1982a98b549f73a6a5281b900034d19cb0099ab009cdbda19357ac9c78965f7a97e469b537ea37c370c1007bc043dd431b1f1065eb303bd842c7e87c90f1061aaccf8fce9c8ebc47770cfe3af050ff499ffb405af661b68de6f5390e684193530d8993d6c360315a12495b81b00c1e47b0911a9ee38339a9b13dc16c1054b763deab7d100c7a46dfd90595ebf0020d2533f7a5f3d9e09768a65742699de3d09466e8c0e0a1f2a2d1df24f700206ab26aec7e76ffd2714349ad5b2b697ffffd5e1fb41519890f7d06045a7d0a504f4a73c0f7c9d8d70e056451eb70af8f07c022e5d3199c9ca196d3216df84b600443ce9d579e6543c5f268a7200b04492cac02a692816c2f4722702c130d5f50348156bb4e9eeb4ee471306b76b4a2403362761fbb27a2f1ffe58a947512f9c050fc5ee7f154b1b0ac299bb8c252663b998439347da1b930832fb8004aee1ec04b1099aedf8d7ca9e8f6863bee03e7d8a7d73c729a88c1f29b81f0e6a4316480347195e2ede892e1f19ac76a6feedb1100607a71114514cf8deba9707d5d513049007ae78d1834e63bb56cd861c66e33dcad19774dd838bf595c88e92547b8c06b4893bd2500077fc94b187fb30aaf8e900509367fb08ca0b8477fde999b1db07e969763b94b757077e5e7698b200fed624dc2002a4965199ccd8b6db04431a02aa21ce2956ffc936cd26dae3b2aeffc670c250eb77265328664341bafa3e9c0359b42f7f1dcbb4dab66a377293ba6d88ac6894c21238464db9a8e3aafde4740fdc08957cc0c0c65ca8ebe551675039e85bed2b000000000000000000000000d656d0fa419a75d3e03bbc4e21cbb2d08b6d866e0000000000000000000000000647debf7b538efd6304caeb9b49ad931666ecbd000000000000000000000000bd85fc591ec81c51b7fb90d74d2681604beed99f0000000000000000000000000174424467ad79d0060d317fadd4cf3432cf07b841463e9580074c6362698bbc0673e273b3ea93606d55039c16fa7eb37099573ab46515ad303f167fe5187b7a06a39aed3500cf0c9aacf025f675851fa8e9da129dfd2245c69b415eb5eab69a05f511c956377ed0cc473385d627d095076dd080953a736feef91c3c088619240608df157626312f05b55c39f31304c1aff70add13535758dda9f991e9f49b22051d26ce50d55ee7719c6f7192bf5d3c4bf73dff25fab5f197450abfca6d421107139d45dd3a04d6b3ca68efd0fa20895b8fda22731cae734ece3cd498cc16c303bbce5339b7a7b7280d46cd4d0aad225c5a9a27d495b3aeb6fad7186da6e3e8019050cc22685f9a5d7fa945fe0a9b4966e6111cfcfb5e1e7da8a695dca55266067d4a83b3ada4279b72719e059054397a087c256eb64a002c6836a63a6620c706f657134837bfc7fee5750d006f540a7b20c0509a074371512a846b8b25463d01efef3c92d9590dc4d7bae6003f4faf3d3ae5a203d59078969a8953aad2772703b9d64299837e0353717e79bd9639dc6d6221f48a770413043e5583f8e16355008d496b8c39828a6da7d2fb72e118bd6d0ca789a83daf494832d01d8988d21f021943fbb631a596d77dc791e482ba7d6c764a1829b173025e8fe00fe485866903f86276378be8cf2048d81cdeb1a4ee9f821512be408fcd49c9508483cfd03603926d7f06e9717e7f6e19cc040e39325a03b8075d97b14f791289a91aaeb6f5030f69fee0e3f44c2cde42558af7bfe53c2483e3213bd5dcb9d6b24fe6c9e5750380fbf5b4ad771e1db36ca644860f051cb68388537d5376702db24d3bbad7e8039a3e07da0217f181c17b67f8ba6e2229a2601b5a117208a57427aa7d82afdc01d2af0f03821da250b7ce391c4a7ad765ac5df9fe6b94bf5ec3806e9ca1df97035e8f126c354f2f4d7f5ed5d20b2262aaeaea80cb26ca023fc8c4ee8f0cefcd036ff9861b928dd7578323a853d5a7541f42efcc562b34fa6b092d6e5b62493c040f3cd30db26c0da8fda135811ff50a08805e4f8fa2252e862597d743ec82f2066085f9495a6e760242a5b3e41385f47e8d273095c47529b5530e9e69140bb90092dd06585cdadc4cdf0b42fc66c4a88e1ba0178a83dccd15eecd7a117fd8610017ee05cc6b672fe1e808addbe4e9a51c6c8dabc516a38eb73a156014e8488204b993c1068ec70edba00edd37f95a16623ab6749ba6e6fec781cd2a351150bc03fd0ef3322b893032e7552e030ec471588dba57f1430ac44a96ccf367a96b71053e3d00d847306cc3a4e013002c4e7798b387664624a21206649f8b5c73b28d070b74ac2608fbfc6bc32058faba901ede6482ed5e60d5202a7ddec28e82c31e03cd72b502be6a4080348208125794de3901d4744b1509c559326ac00e14dc040206d6f657c385324933f905a8b838a913c39f692b8c40406ada195132d843850656b26c57d5b62b77a55afafea4c0576fdc7d6ccca15c960dbbd0886af4cc4905726ee537498e5d7b981b849ea648c7d10303b43ddc98016638e8fe405e3c39013d9c788f9a11a9f5cfb3deb87bc071b01f0ae1a809bc20a3fa87840ea839a1016788a6b8d2abf73c7847b984c09ed86c17d49c425a128360b9897d0cf7633c05cd962a1b91eed417502fc74148b24cd1c3792204675640464123637d75cd91040498f9009416fcbd26f2a894a337f583410990b8caedc94b384c3038de652b01bc0d6e7d7767da335cd42b17703ab80737c99efcee4aab9ba9843699e329ea06ecfb1bbad7d91249ad4b514464b24c33db86743450cb07a039a2bdd4a7818505b9723138eaa313e078eb1bafc04f2b3e380378e84c00b99f4c18e2c58275a801075460a3f9ea21cd9e56cb58d2f2bd665b6bcb763f9c0238a88d0b1216a43c00ea3ccbca32fa87df82cafab3137f3bf0484938d73fa1e4771cf6b6b6ba047c07039046d021bd4cbe38e4844c3d5e117210fe4c3c8bcdd9c379801a44ae7a4705036ec893446d6c9c08cb18bba9d0f31f956dbd54dcd2a43e8198981c40f01102ac5b958864a02972100a2f233037a938becab2cbd1ba47b5c3e9f2506104e906e726154e8a707f3d00dbaf58d79a584265a4ab14a107c896dacdf8cdf99cd00715536d43bc226a3250dfedb842cc6899ff2757eb1bd88c9dfe35271ba1a2bb0077678994c4e4811a91a5e1d593187318494a23c09c4a81dedd2214186fe5f406839dad0d5dc1a3c88814269ce8abba1f9c5dfba67a9991add7492eef37c5d1023cbaae3647ce1cd3677f2cde2848a4e8e98f066652599c5b8e47a559cd4bdd07a140e100d154209caf8609676330199331c2fa423fb0cfe990a684ce9afcec04f7349458e4a54e2da5c5a02c9f0f749050565aa9460ab4b44b2acd06f7096f01b6decdc667042a8c81b475ddbd4671bcb32bc739ed2b854ad2fcaf2cf68a2f0355acf696013f9bf39ce7938151a87d37ba6c73dfe40af06a6c72c9d69b39300392caa883e7deb1926bf6a80c5426d19de8cc38c42352b71e5412bf69d9e8ea0140b0a33ce141398b8de8d5ee610f7a3cb757137e8df34e4b58ca0ef489c2bd0213751e391839847e8c674c8c4edc85423fcdddff56953370525cdf11efda01005b40fa264842d5959a77ceb3b535113f758a01270e2fc62881a27ecfff9228011b9f8fc70c600c1b7714a1f1f81947e9d05687f6cca6721d5b984c655e463b01a2955b57ac39c38f31beee226bbcb4cc781e7764f8589343c4f55b88ebe4b805d0e0fe7903812e73918069f6e3dd7cc521933c1365eee954a4e8d26cc3f0b0050e831a42650ea9b1cc9a691140d02b9d6e6561c6a7cc0261cc3e9be6e4997b0297005b3af5da3bd069fb0302b5405dcc53c468852083b7d33968e4402d0cd00719e2af6d5d9005ce888c74ebf5465116f3dbfd82e30177492c4407b79b8285011802249f2d538110a08fe8f2a4b434580732d42c06abdfeef74d6cb045f26402c1547651fbdd8e91115b9aa7741631cde76d337a6f53f4e2687edee60dd72204d7dfcbdc2967d8cf8577872c1cefbd8f3a50e53d1cc99ed039d53f813b2a21016590a90417c0a756ecfc747e2a6d6cacb3eebf4758f8519f8a103036dd4b2f00bc840539ed8e463a9f83ee0915ba7f3e84433350e26f121abb1a43b3c5ad4f013b03ab7084a84eee9f09f00448d35b16760f9ab25d1d9a429b8166693a28ca04ed9927dc0024dbe6262d8ad6879a5b89af1b3b4089519727979c07b1bd02b1054c5eebf863abc54f599d2ce707948b7b021b8c408cd9e9a9d9a4abde21ffbc06988be52f40b6c918d188f23fa1f9ee7ae42f22c241247029abc1f4dffbe0a607b55e049cd5168b568868c35faf4c558539fe79b0f57e952f422c1d5b366f6d054aba09886cc5565ae4d389d5af13aeee5dad4b650cfbee1f5d21a42e6bcbd60325c6145cf537d90fbcb17dbc133482a7acf96f178f4eb668313affc238405d00bf457d78272578b93224bdc170b1c2f7ffae29640bbf1d7c8d2d6340359ca8074fa40ddb675a31656ec51464d5226ed656d07bb60dc29cce316e2174656a7a07384d8bcf136d9f3ec20765729108ff592a3acbc4313f14a00c12f80c177886013897455adfb367b8d52f3c67d7c06d6f4c83c5c1bf627b4d5dd55bae7f6c36065580e2034b51e38827e0cf3070fd81aa102e20538fd2499c6022d2f881eb8900f89e6e82138903a30bd64db1d78d4adb4d69d51d138d6a6797cad0f96e5b3f0560925c1cf14bec1f0f3d9699e1b40ac3d58b77fa01faee1600e5ae0edd40560088de18aad1fdee0007ff585cfeba60cc20b1c7b5c7dda558898e3e10bb84d4064c744f35d53788b82442010946600643ed2a36ceec6122cf1fccdd60f307f705d62a526e562f407c90ec7111a11960acb56d933f4ad1e3141a9ca5379d4a1904184ae766b9a9f48b09a2ef41e43f1886ddde67be1900fde0c0a4311966fc6f031132c54994af0e16cabc6ea878636f165ad508fe0ed638cb0bf305016113a6003d4d20e92c0382bf0a1c3113196e8941c109f45a6a2f302db5d4578a78fde6026da2a6283d0b9c79729429d6d7077cb27ca5fec0c23ac8a86561502c64e46d03e9ef828a92085221fd8349046c443cb6443a92116356471eb635b212074d09014b807f53c206b43922d5f640468919669769e4c4ac303b374d0609be5b399f0484ecc74b13c32769a5620b347eb08dbd21e7f3e2cfda329e665e1e095a266a02ce8a6c9902e7170fbc7d4beb7e9a02b0c06719e5913d3298c84059c34888fe07c7c2d6928f7da707d90325b6eadf8cd7d4077d6240d75b092f2c392d0e798006cd05b04e4af22ffc797b1e6fa2b209f2139184fcc5cb0929101411bf285bd90044b0966c3df9bac1b788667452e9d72f5c72ab0342ae4da28efd509af8949d04d8280bb0d7047c75ae6a3874a89f8b397d86518dbf47b53b09bcd52afe0e8d02e03fd04d724e5e58d29a2dc674351a2fd43ba7e8dacce121851aa5274df49f05c4fbcd1c6641ef910442bc8e54fa6f7f506c8b0500774debddfc8b29202976019be61c4e3b27c4543293c9f7acb7c943f2aa357e0dec53daf6fffd17c31dce016aa6557ac92fdbfdc2c595d33001438c0ef488e38649dc47b6054f80dfb48f04c07a986b0c559aa279a111a02516ab7dfdff25b99022c424e15b4cdc8a68e4001aa868ca5124518c24d55084ff1bc3c1f3ef4d49674d4a5ac35468bb3d96ef05e6c6fa8f7110d12489b7b9d7481707d0180fc39cb3e06ae2a986aa1b792d6e040c4cbb8f0f9f0a38374dbdb63f3c864c516e5569c68316821ff3de79c7dd5103643d9180be492d1df5028a238ff867e546850b9f32e8f3fb526300a7d9106f0433d30b7a663307b95abc6f53e6e7dfe7a84db8d99a33a09f6e7cd00875d13e01707784295c6ef162c662999688b997c072eb0369513c2282412b875ddc44c600eda5c3957bf7d35fec4827271182324665ef80dd206f640ec87baa68f993d3034a6373092687fb7720e9a3d50e1691f7b6af5aa7ef8beb3f97d10a2edabe10079892fabef3dc9115fa63d80fbd206a0fd7d69d4e9de845e52e87e10b771dd003e864ed9ac1ee4b04da6bed676c849d0e163d43db2608014a932a4b7fd1f0f60611f2e5fe6133c124334230455dfd62c0d1b2d74e079f01f0309793165b8ef3042185aed9652a78371e1d09b6cd4a149aa6d5d2ef95c951effda2047d8f1cbd018d53d6e86bdfb049e67fcadaa6b67b8a706d5d75d7cc48b400242025f564d10562930a48c06cd2f157ff5b6c2961edc31dbfd8760d616fb2266ef5d83cd72f01c33720c5aa82164c15aa1d58fcfc52cf685d1a3afb2fd3732de44f8b75d51e03727f17c208d1bb58de0c61fa6b399f8b94218808de64eba73245f43962b79c02f7c30b00d621209cad4d860340f1a66d7dae29d18199a0a9f68fbfb44d055d056db79dcf9df85878efc5ed018b3f91b69032e7d16b8b312d5ad7b79b9ac5ea00bc9fb8c4a942d380ff147b8b96486d27e67c286bf8134617e53c3b40535f6002f199c8ae325905f8c0b4b3b60f14a9b874eec975a04274c12b25dfd623f88902355de118a62b07f9fe7afedab3c02cd9b8f1ec68584ac158a412a6ffd02b9a040451cdd9434d9fc09371272e0cd2b628686c3b0dab12802bcb292077668ea20722931fe8b03bb703be6ded13ed08a5741fec37808513e6b47023ad5c35c838000000000009d99905aff6c41a862012bc53e0340352bb2f5f62a1a6f76f4492e316004057d5e90b000664c924b2727151800102d4427567f484690e80767766b81699c5c62c2c70024c55ce64421056dc2b53e7bc260b019a3b9001d7e33e80307b9170b22ec2d403654850af34080460cea6b30f603f7380403bfc1666b39b16a0389021427119012beeffabc0ea4dee662efa713bc457c9881d3979aa9510233b5e5872041966019ab62561b97e51b078364601cd937f3cf56c98ec5ce548070d9bfcfe0f241d06d167d2b30136462616adb8926e29ffd1f28296f259d0dbcb329e7ee15587b3009503c627df914200b6f46ed19defe7564f70cdd3b731ea695bb735cde411e205c3f55c72df5bafc1d657c4d826de22be8da4e7d77d199e7e4df1ed9d6f777a00ad753273581f21736ddef8e787f682d22e176ded953cde29899d696d6c7e020673f90f2f940a6685fdd03b241a3fb61a9c9ab4f50ffa9dc3ff59b13e571e2b03e8b661b6dee1ac7768580b903da256ed8d8bfb285a35a4e1d926486821be5805e0a33ae6d21955037a71dda87f23fea15858ffdeb9adfca28e1995b10c4baf077a00968851058cea8f4ea58f3ffff3623f07f1576d4d7d2dc90d5eebf376da063a41633ff3f3698a45c0cd6f117b4ee7edabe4c671b26b88371c0cf7ab2cd7071994897c55a9f608f294f70eb8c78dd7dfc2978ac4a0fd9ff889c3739ddec60255f82cdfa91eb49f7d6b57077a0f40351290c50579388eb7cd0cb68f9293f404bdd549f8365698140b557e918fbffafd69298907ab1651986eb0a91995fe2703893140f5c194fb5272c328cbdf581340c9fc1203be9f05a866841b2e2abe0405ade7b2a02cf26d29c4d44965cea11aa123d11c14154586acafaaebc94cecda0169179444cc03b342e84cba3ff49de2632eb1ab331ddca8c8cfc09b2865a960041f53fcf785fa197ca79c4e86ad1146c51019662d706b97162d5600cf2cb56104f12d177b6c3b861371698d85a8595f2229117d2de11a1312e6241d837f9a030420a676e6e25fdf2c1709f8f14e7d42c63c29b5a997aac21537e34461d265b406f48ab874e91071e5053faf98929c980351cb8aa05f5276e39da0f9930878e7030905bb5d6376e215fcf4165d585e14b70ccf15c7f9a62c8a8102b6919801d102f94f5a1d85a2cbb1ac31baecac106369cf6b1dd786c8baf6d9c0ea2efe480307c1121821a5c111c2631780fcb13f93f271a7382249bfcd61530ae66918f42304bac76a5ff84de43c18119a8262d3c71eb5060a1a9e6f16a589d754295976360035282e095539311a5f4a4ed11fb0a2efa139c62077ace3d0557b6f94d3a4cc02fd64fe293ea11ef553e813a8588c074c31a9a020a23b44546fa7f65699f39605d461d7680f75191954f394e136297365d3df048d71f557afac5ea7e846a0290303ae19942cdf49272b566cec00256101f45ab6d96ff42847cdef959e0345d00040e20d49dfb64089090c7e4151a20b990a048487e2385313486df7fd95d27e04ff0f0fe3522105b72af33f40d2525e08d5f56abe2c9fda0fbee8e349861c5a04ff4301ab45cf30f26554f94d209750d5467f730a13ac754447cf8f603aa77a027405e6a725040f6c5db07fd8a8bd27bb03997268a57996288906094c38ab06053ab5f71bb1fd45f3283dceb581fe4195f1c97bb30e17915ef14468696354ad05deebc69dfdd7f4da71521ea87d18197b67065a81767b83b705144910060bb906e07be3460d1a563e7494def7fc7399da521e4b954a52f07baeb2f25cf3a7d00004d9dd10c69f7046a0fcf590a488578e0fca63b644936324bc7585d1e3203101dcfefcc5ba93f4bd125f5f363ac1948d43d7cf238a63bdeedb19beb3f4ae51020e3b49756b979b502c4941f7b4cdaa7f0283c4b51233e048d07e9295e96d0d00108a16f131a884880b7de1623a4d5e2c61696f22dcc50b6663054899c54da302fdca003a2c676852badb16a2dfd2d56e342dcf4d15951a74636fb2662b720b07988e271069215d401ac4770086d71e6ac569411dbf0107dc28373dc54c6ffb03d486ea50369cadd5dfbe3c9f5c2f731b1b0ea450e48f949aa09631d86b45b306b2c923af06b836b3cfb7957ec010a4300f79ea175f2b908748b4ab54cc1ac201e3f5b0f84a8f2034491e4d57d84d0a4aa34d150c8de4b91578a6c559a1ca55030af87b586cbfba164caa3af90c64b3ee499ebce4093fac896888d535210c2b037ae0f6195f80c6d41c3ed17f7e9528225edad3d9770c71f03c525849d7e6ac064821f81a994cf5fd9089a08bd4c309237d8dd586ef0b25ae8e25a2071e6761030449974d5037e141cd35faadf5c87f838d54739f6e2b683b40260cb993b1220390643f847a6ceb505d49be24017524192236e8d436eb5f14502f396ce4d278004d1233ab1fed1f4a8cfe14aadec429fe48042967dd4e30d642f61316bf6d070260aa1868441f2d7e10cdd15d244b3fd11abdec44adebea83d438474c7f221a015dace8fcb2f7cdf4f0fcc208efc017451216d053335012393067abf98858c20055098d3a014504b34a24af63e539c4a9cdca180fa4fec6ce4bd78fcaeaf458069ab5b7ae954fa4c3bacf6885ea07db43d6efeeeea1e5ecec9f627f5ac44cd50219113f5fd47a600fdcc45bf179dd8f56142560cdc5d33abca4c6240fb2f79d05e4fd1826fca70b95cedb6f1f4b6eb9ef9ea3d292ebaf8eafea4b6133f41f31062225e2ec9e9c7c4e01bb1b0873cf9ef6e315f0922f4bdd42908d8eeae40c2c0538c050230d91f02231bf73c0e716341e37b73bb3c9c0905925da07ee012cff02c5a25d21c0930af5cd6f4b6c739ef59acb424ec3a8c50a83be4eebe38293e8061aca0267130b0b4c13f814e1e7877322c95037d8caa291e24b86a19d2b4aa1078f966d0546f6967f56fac32535ada8d56601e022a2b4e96554dc48123a984b07c871f29a0f388d8be18fd07447cf4bb3537c962ca6404533e052e571c31bdb02d33d3e63e503858a126c0b45c4ee266134d1c1743358898dde2cd3957fe0b5047ae1ce01863c621cdeb9bc758350cc63609313a7e65a596d2d2349963fca0b0740327ae1f095b39ab90c83a1d2546f40cbb7c13af0d037a2231e72b2c629f5055b7e3dda63dfe02fb022b9166102ec452bb76350638999e087688ed9fce6b40721f04c4bd3f326db1d93ddd9c8fbfdb4ef64333e6e713e74ca038d27fdf65202ec0a01f6bdd1046f391c5c920382185613a6f33fa0ea7d1f205b715abdd2710014d18bb9eb51df0ddc72e89dcc87d59906bd9ae23387b27bcec1283ec614d607211266eebfbbcf542235fd34bbe812540c8e6260e1bea46a1ae948ba3506c40082aa52f2297bb81e490c9c9db2e52f2a5945cc96670ec0559689775c3a1692018bcd2b419a674524918bb19f6ca14750d266e1a77ec6431675aada106567e101c244accf5d4f7cbced994f49820eb64d75d85eecc811b7ab3702f39808e1f506df7bd2fe9b40a2bad8ad98b8df85b3f125b05007db60ff0e2ebe937272d5500104d9ec796acf6ae36ef46afc178229b1c9c2ae6b26d8635267a1ce7f86c83005172569e68209e96dab0107abd24969088206811bbe570b4bb7784bad790ccb0108181f02f37ea99ba99b45c517173e6806a9bd07d6a5db67621cd289a1d906066b8aae9bbca503f38b1db1d672546a80c7157dff456affc8a1c78c4eca6ca301dd6352689b31c45e9935dffc7b45074acb02482c42314b0a6130f09448612404b848e0349296429283129c6b9612724cbbdfdc438f5c21068a6c263c3a831101bcf16759b68139698622f7a5d58631e173079b0de00dd23cb2ade4b8593d8b030004bd4076773db21c9b4dd9c7217fc60aa445d5010815226d88b56b6072e104ca91115d241f415091ead93afd42a41dd7129065d2e408c40a5675c493a15401c75e178792a329c3b4829004442581e27068d95050b9a68db868c2ce6726e30705762904ca6ebc28a8cc498d5a55eee9bf1b1fe73ab1891c59a4cd98ab962a05362aff8bc22f30ed7aa20bfcda87d79094162c9c4842a6aca176ec878ec1f402f03e4349ddf2c58590506724ac2826951864d575f6df4372d39ad774ef172303136b12a5aa611a70fbea5c88184e113dcc2a3876fee4c1c3324ee7f39e1c6e07bc8ff6610f47f7f01100ee7eac4212a56a6fed1b81fb58f887cb84f8744eb403a2d7bdd43a0873ebaa11fa4b2b8fa4d08168da16671b4139a02f90d52c21aa04d72c37a8c2a96cf4d57cf85407954eac83f79fbecc28e3913c47b7b37de606071a27d6bf0d870acd3126f1e1551b58f77d26c01025efc81241b42ac8f6c45a05e6ddf06b074b09c11a9211cd4c098c2592d67cd7d06e740dcc2f8eaa6f66ed021a6ff25a013f2662421616feeab687a3f2d173fe6ed5fe09d3e3db6034fcd507319d86357f001d377434dca90698cec74dd6270b3d6c929e7fe2e8ad777be707dad832c1b4d176c39c482a3aa1633893bf89d0d25ec6ef0513e3544c7ac69301a3026d8c00b74960e8dfa75479f613d0bb42a97c33b133dbade7c181debc3200e16a7317e95f0f9afdcfcc779c025bbe89fda16ed6b79fd72d520fcb704a01012cd5c3da4ab79cf1a72afc334e4f491950b6fda88d1c0ab5d0732727b803ec01fd6adbba81b13bec85ae0082b8cbaff3567241c1b0b78fd18160741396230304b81e387c679ddc121a30533a547bc03df1915d05288e285238acfd7076174502994e4df11ab9224b381b5daf1c0112371b890e8be2dfdf165c03e591f186be0441a4709affdc761ec7db2f4f55d93d3e51941aed12566dc7d016e0dc2a019303150184f1a7d911916925fdf0dcbc2961f55daeccca7f1c1b6ca3e0fd95641300758b70fdc18bd72b98ca51d7f6123db1ab3dd3bbd9168ec9ec27ff9edf950400bb68830200875fdddefe5f46331fd5819a0dc3d5312d70307cfb24431e24ba027df2b84945f2debfff657f9de6c983bbc6e7907c54f2bddc4fdceabf4057ba06a4b66474566337518c6aab6b10735f848ea7ea27216350905952cae9e4165a02537d578e1553cd00cbe9287d92d72b033240d157e52819d36d78a1ba55dfac02fd9b4d65221655a253b01dfe0b0f354b9450635ae305058c30bc5a07e54b9b046229672a1533a452faf37b86aef0fdca4259ffb10fa5c0360308bf0324e1d405b78586e3015796b63b946d64040c798140b59ccd35f0b65bbac7925056f6500280f5bb1053105fa2137a81ee71a691bcdf40e69309dd053bc90d3a42f8c5a1068ac9abe7d4b92c8070c5e513cb16118e2fa7c6619829fc0e567181ae82c10b033bfae119b58a06aac5d907727d61b02f8bd4fb033d730f70fdfbfc47f26dd944bf8437ecf00396ea21ccff6bbc901b3cb86cb1000000000000000000000000e289b49cca1264fe1a0ef8c5883fae2d9070d5c30000000000000000000000001a3c40acb4c3752f5aca6f3593e993f520ba9d150000000000000000000000007b63eaa4e2a7de1784a9c8321a2eecc5f8965cea000000000000000000000000a3ebe499c9183cd132e6aec31e60f1e7486fbbb6000000000000000000000000c4f2a7462414b975a91cbe821c84d8abc2338c9b000000000000000000000000dfe9d74a596876e9f2bb3fd27ebe3fe53e3d5edf0000000000000000000000001114f0ac6756bd8e76d9823d03ac91bfa75e158e000000000000000000000000d6c7e0ede664519ab70c5a6557fb3ce163bc4b23000000000000000000000000ab415c3a55913279a2c45b4daa1668ca7e494d04000000000000000000000000c2330e5cc1967562f657925a92b3822240c05fc90000000000000000000000006670ce1496621e1a4c9e526a534944560534df4600000000000000000000000091947a93deabcbf33cbfb6478f94b888efec7b450000000000000000000000003a9d2611bcc48dbe5725416f6668ffad02018230000000000000000000000000d87bbc07fa724cfa45ddfd3f96880e2af999b06c0000000000000000000000003f15d7d87dffdc1fa4f3b7fb24b7605cada7bbbc00000000000000000000000092c39132782b6a91086b36112a83cd4576a8f030000000000000000000000000bcc6add4f1549dbb090c39744bac9a1c63dae8fb000000000000000000000000adc5904d2dd1bcc80122c99cf0baa9098b7f618e00000000000000000000000041baae9be62996df91dfb8edbd3bb0466d999ef000000000000000000000000019d50f91b4902fa02e94dcfc79237a47bf4013b60000000000000000000000009e52bfe77a22a4ab806b89213f18b45e9ee3c4af0000000000000000000000009dd4b1895423b09bd096297cb6ed98808bfbefda0000000000000000000000004ae1d8074e0da54208c71fcc83e4bbe74245b564000000000000000000000000d058668c36588be15d0a898c207c34e2a31d3d04000000000000000000000000b21c0d1b2ae048a2729522f766e88829057bde83000000000000000000000000cc3ed923eec53ac5e2d878180d077c043ccf2f520000000000000000000000006a7d770280eb71873c52ca9b1df71eb08355e5660000000000000000000000006872ba321d5b3865b32db3a76fc399ee9f0af9b8000000000000000000000000e68e356d5e06909bf1d3076e5eaab3803153df560000000000000000000000006f3bf7d6616a2adabe7199249a6258671d5034a70000000000000000000000007cda735a9fe506109cc425fa03c8228fb6d2751600000000000000000000000091b6311e406f09ecaee3eac9fa84400fd1355c97000000000000000000000000b265124728585ced6a42909e5c34f907de56b36300000000000000000000000041e3cf91366700121409ee51039a41028fdafec600000000000000000000000043b6ab8c34e8fd9691733420aa6a2b373e4a095b000000000000000000000000e195e663c6d09654dc977db5cd9988da56c0b70e000000000000000000000000a54e99a0eb74b9073f79ff7f0941e3a7e064b70a0000000000000000000000008854bb8d46337ec6d93e86948b8ce49e69bbd68d000000000000000000000000666e50091bbefeab0b740a574500ea82c4e444900000000000000000000000006d7a9e0e3b00a16b3d1cd24e3be52901dd604aa2000000000000000000000000c0982e96c60106ec13d79291c301e1fa176c1ab70000000000000000000000008dc013d1345a52256f500c588598095835637d05000000000000000000000000c67f28c14a6dd33ce67c688278518aeec2144c1d000000000000000000000000b410061861da528e1ef331053589994dce66478b000000000000000000000000afa37024afae7404a983f09b5f4815b941ed961e000000000000000000000000b714496a5ec940953498468992a35d680f0e27860000000000000000000000001350b5ed7d47752c7323c7aaf40cd4651cb284070000000000000000000000002a4e4c04af4b3a0691e04f77a3024253728f77b80000000000000000000000005dd1a3c290dee12b0c1102fc134fe0521fc47cfa00000000000000000000000081acb2da88abd7f24bfce38c6d1d43ecfae34c36000000000000000000000000fb21ae2396754a1ea134308c0c0cfbe256836aa70000000000000000000000005506e3eed92dad027f6b785dcc1a0e4597431f63000000000000000000000000d6f88bef735f00900c422c1dd470d7c6aa00780800000000000000000000000083dd7b6b7b896fa44ee5446a809fd98872413873000000000000000000000000a1dc6328a039faa1f25cb12f8aeb7c703711339d0000000000000000000000004341195e7070c03b6c2e5f394d42a292d8d3156800000000000000000000000053c1d13fbbe827f10f14b3840184766f3052b67900000000000000000000000023ca05c3d3c918c01ff8e87275ca8f7fedbad366000000000000000000000000af423e33eb6dde4db0754f72715f2c13c44e538800000000000000000000000059220b94e4b2defe9f4fa3ccc4a8de5c08b643aa0000000000000000000000003569e5334e484db394ef8aaf098f274ae8c6fcbe000000000000000000000000e04e68394dcc5ae3135a8c3dee1a800f59ba8bee000000000000000000000000f393a1507d23fb632c87344a374b659096987b5d000000000000000000000000693011a8cc8ba86b6152a02fb448f8035529753100000000000000000000000044241d19b486f5ab6f1640e01a9db6e1e19a34a2000000000000000000000000a8f904e87d2db41584b04ed31f76d49907793593000000000000000000000000eee1aaa495fa88c87cc184d9bb57515a15ae1ffb000000000000000000000000689cf4004b15c08ffdb8c9fb285b99152226118d000000000000000000000000549b7aad715d1e7eaeda0348045775be01d303830000000000000000000000000dea3c28eae02423c290dbf1a49d869c4878f5940000000000000000000000007f84554c592e5ad5d2fa6d2278fed5fae15f95e400000000000000000000000099c5718e30d71435bbc19ccb1c23a8ef9044feb000000000000000000000000046f5253c4a77d7982399017a41798b1cc8d8ed530000000000000000000000005904352d36e17773c506f3d4ff5e76bec48b26650000000000000000000000008dba4257e1d2a36e106cd3bae00ffe0fa5a1570f000000000000000000000000f422f573612a324c9f5ef9de672432f95fbd98c8000000000000000000000000bc27fbcc983c72c4f5c02891062ff30b2bb9ab16000000000000000000000000a08e8c91859f668e8aaab1dfb6fc6c96db265a95000000000000000000000000283e9db461db43389ab2755b9b70abd9cebbfca4000000000000000000000000530bb1620fd66978475793a0a563f72d810989f000000000000000000000000082706846cc3b598e18fd50843ef10191889cd387000000000000000000000000e8ecd294afd0d39bf0b632202c71c3cd525b4cf0000000000000000000000000df62e97289d52ad5927c9ddcf7707365a4b65cd500000000000000000000000070a8208517ada99969d8efbd01f3d46e3e8e34250000000000000000000000007f332145ccfd375e18dc2e0eafa4850e6eea68aa000000000000000000000000ce31c4b4979621496e4930eb3dfc03c2f250f03900000000000000000000000050316f94991333b37234b27991d0ecb7578722fb00000000000000000000000086750f9cb5fbcf2607dbb45596329c7d42f4c2bc000000000000000000000000f4443f71ac6290908401ea9b4f2413c5cc8ef7aa0000000000000000000000000203d67976d13fa06072871dfc8b01e9fa5197db00000000000000000000000036dcff71add5c0dbf096b2a7480d160561d7bc170000000000000000000000004f9de14c75bf9212dfb2a6482e64045de2d38e78000000000000000000000000e2b3ade608118a830380a62c5f57b376a3c8410c000000000000000000000000b6fdb1a300f03bf65d4f0fb58d610734bcb1c051000000000000000000000000075f7336b6ae18606bae86729f53108e776dfb4300000000000000000000000047ba7b55b7a8e5974b283bd0a00ae962a79f45770000000000000000000000001f33172479ffb99282095b6939f8c33b39a2441e00000000000000000000000041c147963ad74cb5e75c2ceb786792b0b1106b2f0000000000000000000000007b877fbb1929e3acb264bb1e6f9b765b23123a0f000000000000000000000000f4672c10c176498e350452d9d695fd8fecb24aa7000000000000000000000000d1247a5a517d6618c0f0a05afe8b71b2f69e6401000000000000000000000000c030136a8b4002e81d027bea0f981b1b430d97ac0000000000000000000000005f7ce5a4c30546b5f7ebdcbd01bdf5b8912558e3000000000000000000000000c6250f22d2cfd7014ae754f318bd260c31e734cd0000000000000000000000005bd100dd3fb886dc9c2a4c16c40b84960cc7f8880000000000000000000000003ea626d6ff1f470cf50a2c5ee82b4d58bdccadac000000000000000000000000a25c7e1a5f1774be75c9e9edea69edeed94fd230000000000000000000000000481757ac73f6869c92e49d43643a466c592f8dc90000000000000000000000003864887745729d9541c4c962d9d2ebc4b5b8f15e00000000000000000000000015fc985116f25e50e83e5f876a0ad0f1629db16a00000000000000000000000089dd6379d8557a9c47654436bdf67ebbd96a33510000000000000000000000003bb5ee0f1dbf89b7e58b2ef23684348a383595f2000000000000000000000000d319811af3cfe4debd0b1deb17d928c9eef61928000000000000000000000000f4e0783db4038c6802649e848b3e546af3270f350000000000000000000000009974e56b84469cdc2512f744904b809181c2d5af000000000000000000000000f96b0ad88b3d6a91ce5eb573111900f96a2bf565000000000000000000000000c2b09a80551a9a85726e2208c03d6c126a17d5bc000000000000000000000000d25a42a92f016869312306ed4891e1380c68780f000000000000000000000000555cd7ce582d61e78a2c9c46d6d47609f7de17d0000000000000000000000000f0b1908773cb8797e47c4de7a627eb7f1df3f3b1000000000000000000000000a0737ebf48323dd82bdcfc11b0996217aa176408000000000000000000000000f2a756ed8d9ac43127120e9ad1261b8d7e1e8e2d000000000000000000000000f10a7442150f73ff93a516a885dea8cbdcf1c04200000000000000000000000031148710ebd4736e43e15367bac0ea34489d29bf000000000000000000000000d5fbc23611a76241b448e8fa95702f8f1af897a6000000000000000000000000cba43592db065f9d4add7f6af077c0a47af71bd3000000000000000000000000f2f768876811e8b801f4fc24f83aa008a5c9756b00000000000000000000000051caa6b0f2bc23a4fc6d05967eadd7f8420a0477000000000000000000000000642129e6bb28a7697105fd11660cf9aa6298abe00000000000000000000000001dce6ccc1a9106a7ba36a0a26437d5b823b9c96f0000000000000000000000002841a1bd571207bd81aacee18178719af0bef6b4000000000000000000000000f8a3516f401aba94926f32569a9f5f9f32f4972d000000000000000000000000e043b9936ef5956970e2670013ac0c20caa0ce860000000000000000000000004f1bf6f3fe21c1c79ed1dea1b75b1397091a27880000000000000000000000005a135ce5c8dcf14a80e1d60d4cc1c4e9db6e9499000000000000000000000000098ec3273ba952a71f225669927b8d26de94a286000000000000000000000000e98a1e64c5b9d565d1b4b9e21936e4b842c1c3080000000000000000000000008737b2f8069b882b8d327079e63327f972c25b04000000000000000000000000410c6008061efd118ba9ccfe6d5135b6cd9047bc000000000000000000000000aa487042476ad7b84d2b46cfdfa9948de33f4dfd00000000000000000000000058b64f5b20428d0a05d0c72de69d06d2e5c49cc2000000000000000000000000e7b3593d62d5c79c9d8e81d3f203a5b9935dd5f6000000000000000000000000d9aaf69acbcf8f5b66c370b67cee07ae5c40d7d10000000000000000000000008a0e1c1aabbe501e4f55c700f79546c257c61189000000000000000000000000a2049dc249621e2d210e2226bd52c35b45650b13000000000000000000000000e31890770dab67787b1bd5e648d4cbdc4000a413000000000000000000000000351b20f4b66e0493a06adfe9be212e48be837718000000000000000000000000da77a35a50a207478c0c5892881c3e17a9e6a2c7000000000000000000000000b989d11a8f1c2a2e1b69789591e0dd6941d6387e000000000000000000000000af31f1363be86ac920e8c072c98b5ada38b225aa0000000000000000000000007f02e7dddbe9e2d226dd09f2137bbe75dc36becf0000000000000000000000005cf8c1d001387aa1bd734204c577cb6a8796604c000000000000000000000000b20f7d769ba6a7516a13d1a5ce226969114d44c30000000000000000000000005e5bca12c1fdbb64885a26acc18e8db32d916c4b000000000000000000000000e19a9ad4c1a9fe8844404d8e8e888083e40661a1000000000000000000000000f64b7a70f8a3c48c93b0a8eb60560c1ac46a49ef0000000000000000000000002266eb45b1dbf570b823ec68a6188c35cd2a718c000000000000000000000000c377821fda2a32a4bcd67e19528ed9f6073a07f1000000000000000000000000956607cb84e889cfed142445a546f9c95f8cc8d3000000000000000000000000d3fe25b15ba6ac3319e03fc02a55081b17c747c7000000000000000000000000efa3361aeda9548d482a687ed90938491beb2cb20000000000000000000000009581b36900f03a64af673f2bd434237a09da4d760000000000000000000000009d22afe52b1d58f8a7629fdcc7f3fccf89192316000000000000000000000000135af72ea4c47a1a8ec5327ddb50e5d91736a84c000000000000000000000000402d5d23a46372dcf8dc73bd9cf67bc24f371d8500000000000000000000000068aa8ad8d33e4703e0a3d881566e9d4519e49d410000000000000000000000000b861bcbff4afb6852761b5f1d056f4a42abead9000000000000000000000000c5faece035e7360de0e597ef8967608ffa295bda00000000000000000000000018ef853b39c7cbc74ac802419340269f90145037000000000000000000000000b75b3b1cd6d6b08b6e09776ebed9681b2f3da749000000000000000000000000a01847e7948a9b18365aed368129f2a8bd8e99570000000000000000000000008bc2c1938a2a9925f43e5a1c4f58a024491e879700000000000000000000000032f5dbb4e74239f7746bd430f45ec186ee96f9bc0000000000000000000000001837b2b71d17dca1a320baf2a0976c72fc6468460000000000000000000000006043dbbce23b21684933ccf863fb5fc83eeacacd00000000000000000000000009be34b58707023abebc7ffaca4a049c268d08000000000000000000000000001dcb17de8f0a08ec0fa9cb337d15ef38ab81b3840000000000000000000000003c311953551df199c8b9292d6856428b8315b0be000000000000000000000000f10a21c88cd71308029b23133e83a85b0096ae7d000000000000000000000000555c60d1fb12f06a8e83641871d6272c515e4ed8000000000000000000000000afb0d206cecdba1e07779b5b4f34b21fab4ff5680000000000000000000000001a5d95ee5f164f97722c0b0df732e0320d7f8bee000000000000000000000000fa4a1bebc101c046ae627bd534bd09105655bd5f000000000000000000000000e4fb242f905c07fde9b44dc765a27d41960f94d9000000000000000000000000c02f56f20d068fbe88c562f5f3d8be82233687ef000000000000000000000000c8a9ec8a7b125050f5f2cf8903463745fb3ccfa8000000000000000000000000e22dd782ba9615185ae1a641dfa695ed70f9418300000000000000000000000053d44ec0d91053c2eaa93e290503af3b71d304e700000000000000000000000070a09c86006fc5af0d14cbca4f7ca7cf238eb92e000000000000000000000000f27dac3fa1da95042a552ce16265cf150734134c000000000000000000000000be796d5fc305580c43e0a32a3359662a3740f3e60000000000000000000000007f9a12dfc2af80a1a8453e18225427d7f5bef8f8000000000000000000000000caee5f55f5b6f76a0e97013b1773f3e9a7090d3600000000000000000000000085bcf55fce4bd94310e1f68056e99b74ce41fab500000000000000000000000009151879712bda29eabe97640d9c9089d79bbff70000000000000000000000005da49be3655ecb19d7e66cd75a8d42d318c4e4ef00000000000000000000000028ba11cfd67bd786e5f51aa26e8ff1d16f6fc15b0000000000000000000000008448542f125026a052be865e82c96cc5ed2b232a0000000000000000000000008ec49f67c64c796492464a8c83ea389fce0dbd410000000000000000000000005d33e397268200645513564d6c1843e52dd81f8e00000000000000000000000039b258c0ec6a2124de3c2a6dfdff177614210885000000000000000000000000fd06d74cadb7628bb0ee63ca2ce176995452ee5e00000000000000000000000083a0a5c0d045c9fe91c03571aa40ef1f6e971f500000000000000000000000009da130907bb9772af1e62f5a4b19b3ba6aadd90d0000000000000000000000000858f3e085ac7c66e0651c00644f3a0a9646500600000000000000000000000091afd0fd89039ff4095978f7bc1d0f977844812c0000000000000000000000006ab259ada835888a08ce81f24c9cb0512b2292750000000000000000000000001178507aef118712a40d45c6d9afc3cf185f6f770000000000000000000000002f4d85b11d853fb995dfc73cc5974a5b31add1780000000000000000000000009b0c90dd5bb9bb0e87183e0f15209270f66cc662000000000000000000000000b9024ad61672fd35805b5985a985f4dedf80516f000000000000000000000000b4f4500f6d4313a133e85ec6571cf113c8523e28000000000000000000000000112562122600e5dba6ff4614be5af550a4dc482c000000000000000000000000fac4bdcb78618dd597d59db2be54062a2cb50d48000000000000000000000000bc7b0ef8237e499256aa60e14d14e039dd6e88d600000000000000000000000064026739b250948f5048305cb1ec3fee2ea8014a000000000000000000000000468bcb995d25ec2b072aa109caeb9377e229ccfd00000000000000000000000068307cedb437f1a94c8446474fd941b6cf05adaa000000000000000000000000b3e688e65ae5b9c75007aea13298f55fbc6167ca000000000000000000000000f1a7fb8b0988bf04428f7dc7ef45a025c94d923c000000000000000000000000941f70ef8f25002a561540d5e5c41ce29f13503b000000000000000000000000e59cc44da9e4f9acb4208b7478984390f112b81100000000000000000000000060538e7ca5389b1173a70b6d5a8e3feb97033cbd000000000000000000000000d1b84e76b95b642488fd08ab2044205b2a8d7eee00000000000000000000000049d064cfd0db69a41e5e8b99c8f1d10e0eb99eb1000000000000000000000000b9e80f28dc63f0b08570fc66de320011e9204c55000000000000000000000000ea618355e0b321201a9aea3943d17ad827fbb430000000000000000000000000fc0ec63477fc6d33b403a7a06ad1d15a131a83fe000000000000000000000000e93c97a3a158cc29f3a4a70ae03c5c35871884e000000000000000000000000001d79e0f68a899ca8253b1fb0c6b5b54edbf74a5000000000000000000000000d0026453cb7667f7591bdf367d02c22f5e8b29e30000000000000000000000006c3e55ffed0bfb10a752bb6fb4d84ad8205e260b000000000000000000000000fd0940609a93abaaa39083d65da39eea41ccd2ef0000000000000000000000001749a720b5bebb27e99fb9dab3e59637eb57241f000000000000000000000000d9e3e565e741c1bb9a6ff69af40a7a4c7b6313b60000000000000000000000002258b67efc10d09a450d018d8c0381fbcf3629640000000000000000000000000e195e6690bd127dbea2eb1afe2f40906c07853a00000000000000000000000050895f714aaa713921038961a63bf935519a7d2e0000000000000000000000002488f1176a926cae3545b7cd44e7b24eb00cf4ed0000000000000000000000000bdaa2c966a13d7a2cf414729826815eba3f5fbe000000000000000000000000a0fe3ae90a61cca38b05063d1c15c708564d5675000000000000000000000000025c4669b28f07d1f71b49449c2114bf8813da0e000000000000000000000000d243ac194ec3f894fa8112f14ee034cff85eaf5c0000000000000000000000007d7caa0884d257b62e3a52cb72a62d471b98adb20000000000000000000000003330babb51908609e8374cc1e92fb41b3877680a000000000000000000000000b6937eee743f8ff582373458fb05243cb4d37cb9000000000000000000000000773e44b9a7449f5b702d9290eb1278f91e7e926c000000000000000000000000929ec7d6dec4ac5beca6fa964a81b0dd194f8c83000000000000000000000000ca22fb060e548b78956f3f8816c74b00c94942c9000000000000000000000000bd13e8df1a16b6865e6b34e0b2cd567df1797880000000000000000000000000ff5cf9abbdcfe37d505b7112182aa2f30b1fce07000000000000000000000000c161c7b1aea2998287d149d61ed88b502d3e2637000000000000000000000000ae1e497eacc8f99ccfe5983cf9c01bb8986707dc0000000000000000000000005254b4df78100965f32556ae8e719ec64800a1370000000000000000000000001bf6437ca0cecac027def125ab0050155db01c5a0000000000000000000000005e4553b63563e6f2d8c50a329b83ca96878f9aae0000000000000000000000008145a27b5ba84bc71b49640559efc5b25cf743ae0000000000000000000000007034b79d5a4a6bd050cee2fdb407866480473d50000000000000000000000000b9d776e948410c64c9e37dc1dddfa4c6dec1fe28000000000000000000000000345a32fe6fa501262c6a2d95b522619f34e58e11000000000000000000000000f1ae7f73502f5bbad415804d639cfa7885489b490000000000000000000000001e178a56f2ef4614d886f67ec1e47e8be53d7d9f000000000000000000000000932cdfa8f74f1955c3da7630bf56290f6791ae98000000000000000000000000cb2836b4b45166b78d5c56f65afa9b624f54e677000000000000000000000000d1c0dfa762415e2a8cffbe623f12a5b5aa7035fa000000000000000000000000e80fda4600ec527c58213b336531d51e13ab8ecd00000000000000000000000056a858d130bafb5941d1a7457c75728dc66ed334000000000000000000000000bd2bb22b0c9ef35d61fcb3a6e22cc0cdf91e032f000000000000000000000000ef679a663c2b206bf2c760f8c0161d1e8d765009000000000000000000000000df3d2477005fb2b25d901ad23701e4e391c30025000000000000000000000000bcc980ece1ba108f8b27dc89d761d9e057b98fd80000000000000000000000003612a7faf74e8f45c3562ea8995477e0f50411220000000000000000000000001cc0a8ba98f1b52004e6dbcee42a058458681d05000000000000000000000000485394a695450f4bee48df523410494b4b0e72370000000000000000000000000728609c3848f0b43587edf2d4c7f4f5e55fd9ac8c082edd5cdc6b77cd97d75c00ad649b0caa6709b88a5c0a02fd42f3d84d903946aeb42fc0a3830556c0b05b071aaf7d70e54bf0e4802035d12089bd647be99f1e6623297f222dd42c0fb55d0532343d3756ea2cd86ed3c1c92cfc096899afdeb624050b0f4a9072b30abe21004534e350500fb04170fde0cd34ccd585411005d6a9d1e4fa3164b5ca7684820445a4544f3734266d8f497508c5de3093c497307e2821a6ae2df87a361336050610c84d80c0d3e9804e839df575c6af8ba5ebcbc77d2bbec709f7e8306502c4068b516ecb94b4b717670af767e537f244035fd842ba935b88fc71a19cc1bd6602b05c2d9d554b2921d3da1018a3a1f6c3badd3ec79ce183cfdb7d5b8369bf1501e0f2fce5a646892cc652829b20330d91788f7cd82fe414fe1455b5ca342566049e432775db0e150c618cae7351e36b8267bf7cedb33e0a02dcfa4adec52385061c68ad15da54a57b539ab3c245d5fd0fae63283d726ab7b4686d5ac9b6e313043bc8970ad545daecc0f13ef5622c0a66604b6dc756f30a7c4b64a0d86d2be604b08ebaf9d8dc71a0b1845425c464ba596d325a7992a0319eaa8b19fb0a3b4807a9106578aee8c3597c95a8a77e1fc51821337c7643f8a8e58d04af4c38aa8f03f5b09888124a63d157967589ff9f85fe0f39b46c5485ba621cd614df08dc8b067dfbce26a50a6b9a8d76520c8f7ee168a7d90a8c5bc132afd169fc6fb80f0407aa2ba94644ff95ac95e5e0fab32b93827c3c4855491f9d1283d9a792675ccf0242a3bc26faa815f883ca8b9fb45363e88215d70d51d86b0359d08f962ecbd302ef1fcdd8b49332669f1b861264e27e56485acbf55d6dbc0161259b4d59bcdf04ba6cc53761ca2d6dd2b4b05933711a6c6ecaa3fcb431764d94226218d7dc6f02df67ef5701ac114abad317f8daafa110c7844100a25808fc05f6a66df0c1a1061b7ff5bcb4ee5a98b85be6b58004f0512f2166c407870bd7abd2e332e7fdb60592ba5d413e0b1135ddbc56fcf5fc55f7984cbd1da8832b802d03d0cdd568a8029488c326c6e66f45fa47a04678f2a54a79d5314ee5155f4db936a21d0ea5e4038da417957b8316015738424b2ac4278e187701c3213983f5322a4a653ec6810237cb0278d2af00383856650a85e33a622f75cc6f53322f57437211da198af706773bea69ce42e8befd33ca7bd7651dc230af86568e2efc3d76e173037784ce05f1d5388404c750ae501c7fd0daa74f03840b575a63bdfd272a1bb13287741206092ebc01a2a2bc3f002f8c2aa524e395cb32350779fa3d9311096d166ecc2306f74a8a2e2fec3e8e852886d70030cd88f0a5098d4a046c9dda317ea84dd33e010722b99dc18c1b6a8f1e1f5634efa4ccb8d1537548df900b5a11573d74a42605198432cc394c7e158da5f4c892298efc70adc230b831542d783291e3072d9703571dc486b7b92b6f16880e8510e72c24c8ed6824fdcf965ba76cae7315ff9201787b9e3cfe7d00e2407846f2c06cc11b0e1d6cccfb9bcfd07761a9607d4e1203a8c20d8dd35411d5c5085d5ba86588641b29fbdf6523e2065b93190e43c2fc01f9963ac2b7103ef3ee962c2a7259da728928da9459ef77592278ead13bb3e8042f34b311a599a2281a6ba764686387f27c47652dfa018e07e26375628027ca01a4cb4f075613f3025a9d0359fad193d51b92bf846cc9b875792045de642c6e01840711c739502398c089da48cc7c37c76c4e2c24e9638bf3599628c6ff15bb02a3ecc3524eeacec5afeb4404de880c47b37f10377ddbf73ba815c2fbc1c21803634a9396d3b54ec71adbe01e28bdcea3d2bfbc98afc1fdc0c954978f8b27e3020a3b83164629cb78aec4755ed9e74a960a2247caeb484b63a4ffb3cc343e850571296be4e6b19232f99f9be44a027ffdcdc871d6c8e41d7b0e5994baeae753016ed6a4697af14d349efa6af8cfedbe9090887f088cf7b3d10c2295f69f4af308fae5bfd815379994dfc9ea85ad3c7c4ac52d3100000000000000000000000039dcfa73b87735c48868faf509de138bc895da120000000000000000000000004f206f73a5c015b0a2e7df569b755a9f6e9a5352000000000000000000000000f7565ee9703a38712c340720de044db01f826fa1000000000000000000000000f096c85571f42f9454cf1e95b546a95fc5c41c1d0000000000000000000000004a8e85e04012f2058bc2dcba48a637b78c540c1300000000000000000000000098c70510516c060dedc8cf6556f084ee03fe559e000000000000000000000000b17360f60fc90770fc1f590aa0291088d57d3e200000000000000000000000000a32f00835b5114fb40cb62c46f46afcfd556d5e00000000000000000000000056b99495c1b4520e4b5d99432b17bc7460af64e500000000000000000000000015fc0a8f99194ba997815468f2414a139345cf3a00000000000000000000000013c1526a203ed1aa2d5dafa667089f68312cd3ba000000000000000000000000f854d67df6a59f7603ee593104216a0179a7b08e000000000000000000000000f542871a6d3337ae49b2dd92f7dbb9e4cd3a460400000000000000000000000023600ef18ecbe2b4006663d2ce0241ca350a54b40000000000000000000000000066ec621e10e74bb9462a18b49e52cef3071449000000000000000000000000babbae77931de07ca8621804cf6b00b72a8c798b00000000000000000000000017d137728f716148e1346e85d91df7afc14aa54c0000000000000000000000009039a3cfe16ec563d5e884d2be4d144815730a440000000000000000000000009d09262b09a14633dd91e39e379b7da45404c23200000000000000000000000077621c9116eb261873b5d2ead8f5517597ecead8000000000000000000000000b9c1aa2ab34d0fa5073a86193d69c3d6ad7b1c3d000000000000000000000000fd094c0ae01eede51966f96a59187360fa763c1b0000000000000000000000001f610c960542892fb357f4ab57e74c14a1d42d0e000000000000000000000000dc432e567b4cd5a8a35f358fcc28a8b1fa303d84000000000000000000000000efd0095886461c5ae1cf992e65d133bd5694c7bc000000000000000000000000d0535a4c7239ea7a9aaba0c7751f1a19e6334e8d0000000000000000000000006064a1ed639ff3c37b16c9683041e23d5e37c452000000000000000000000000f4ec5107ad7a0d5a7e509510ae1eecc1f8816bbe0000000000000000000000001e3cce021e44aec3a3ac7b112eeeb2d5249d13f2000000000000000000000000c76bdb8f799f88096f3f4be5b327dffe6e6a1f3e00000000000000000000000087c353108b4d5a2294f48bc71680fdb4f1c24586000000000000000000000000c53ed57058c46ecea262a984394df2f416b9c069000000000000000000000000b121ffa4feb2915c66e297bedd876fdafca013c2000000000000000000000000d7e5b77362847fbcf55d112046c59828b6ab79220000000000000000000000006df6a9304a1443608478226a8fc42fdc4a4ea24a000000000000000000000000c590f19d9f9b2478fc6e8b91238d297633bf405c000000000000000000000000f683b67fa2609f74f67a3e3bbd534ea03d70ea650000000000000000000000008b014376cd2d286222cfd175c0e611973fca1c940000000000000000000000000d9991a130b01e23e8a7956c5bc92bd6501407d6000000000000000000000000b84942dadfaa0331d7af09a6cd0456e84cbd9dde000000000000000000000000842410c4db2782856b5b5c9a6d7543576b9f110a000000000000000000000000d089eb1c58ef7937687a7129fd4d5b44ca9cb65e000000000000000000000000afe68d7f6a3e5047a1944c27cfcffb22795ed1d60000000000000000000000009e6df8356c4b28f0f7464071151f2af5382c938a000000000000000000000000ea79e29bab7a7efda6af630c8bc026adb7f63edc00000000000000000000000025c08814539dde601e06905a904ddc3658310b4a0000000000000000000000003dc6b2294a26effa37af2eb7d171a05c9b4c0946000000000000000000000000c720cac1849681ce75e307682201557d424871b30000000000000000000000000bcc60baa83062f0df324a3544c10aaeeebc74830000000000000000000000008e24499f6518745410a195cb8759658b7454226b0000000000000000000000009293f19e2a428e1e327a96316523a3c55b4e62ba000000000000000000000000d0af95aae30ae3eae38b44e1bb2cdd3e2798e351000000000000000000000000fd1881088d6de52854b70b6b53277130e361813000000000000000000000000097a784deec67dfd84fed9669fe4bf84edfc304e1000000000000000000000000b92d8af2de23b7b482cdc4dd64be77a7ad4e973e000000000000000000000000eb6c7057ac92b57de9e7e362ce7670bf1e0f98c2000000000000000000000000e4c664122aacbc199d92fada904adff78c461315000000000000000000000000023e635a9bebdf7320fadf0378cfbd3c0f4b8bdf000000000000000000000000dae5ac9fba36fe12c47a356b05fe7daa3461f8d80000000000000000000000001f51616dedb9cabf0b50aba5f3813bfaa06414e000000000000000000000000019bcff9271d08fcb44a078d242879b51b13a8b58000000000000000000000000c9a03583a0ea24ce2042c194d6dd6061e18b53b6000000000000000000000000aa20ae3630ae867b936443a2d0dc930056dc4da6000000000000000000000000e42767281e51c8c67693a5232be62b6b64a5314d0000000000000000000000002d6184deffcd1d5c557762ff241220da4a280ae5000000000000000000000000f29949f9ccc29fb76227ba7087c97eb3d63ad27c000000000000000000000000fb0ba0cec748141d43835c539aae4dcfe40272060000000000000000000000009859e5aa878c9124cae410e625fb42bb933c22d300000000000000000000000025daf6f674990ecb76dde6376fcc189ffec81c2b0000000000000000000000006fcf0e71983b02f07c536f5578d05577dd76eb4f0000000000000000000000000e5fa567b20f0d83f5fd6af3de913ac1107c0a4800000000000000000000000008f6bb682c3d3f2f10e4bebdd8542f10f5b13f300000000000000000000000000267db37cbf31ae4ec11b729c0e17ab07eeaaf82000000000000000000000000dc8b5700f5d000ee8ed4dda988bd355670a11253000000000000000000000000ccb6197304d027234ace6544599679f9e4c15a7a000000000000000000000000940d6211abb4cb7c523eccebb8982d24fb7cdc78000000000000000000000000d22949a6f325e9148d74cc211dadad6519631de9000000000000000000000000db5ce10839eefa641341b9974362a531f5faedfc000000000000000000000000f6b71d5e9984f1deceeb75129feb61e0a5e45a5c00000000000000000000000022db04b2259be9054af1831093c6f42ba952c7f80000000000000000000000006e32876e757ce272162745419547224c134f60010000000000000000000000001c717b450d912192d61ca1db1109cf78f01b530b0000000000000000000000009e054b41bdc1b208491ab826e9a7388544a8d26a000000000000000000000000b853fe82f16cc585b2d0eb16dcf0181473e282cd000000000000000000000000a8a58e3e9d47527b14cdaf1b81bea85fe3c9c6c3000000000000000000000000de8590ded392d27e9b8e9000ffed09eb951ed5570000000000000000000000008960af9d702a4b9018173622b4afe48b50ce4d7d00000000000000000000000025c6c880e2da12cad1851481d1d0ea7598406cdc000000000000000000000000f0f3bde2263691641483418f88d1e8a77f7c7414000000000000000000000000faa2283986c37e748d51790a06f203385fbf075c000000000000000000000000a3c45e252f133cb403e4b076d9c95b14730c625d000000000000000000000000014dd479fc655e4e11377ccbf17616c375003d7700000000000000000000000014deb4d4b2232d731b5f0173c30b491da5b98ed3000000000000000000000000d61ca15245d63303d2792d7d26e686d59f9d5bcf000000000000000000000000ae969c1c47dc52715fa8c85d05770172b84f490f000000000000000000000000c7ab38171c8dcb2800748fc7d42946bd1d59d6e0000000000000000000000000a2be75eb81b883c47f51021f01a5b44ec073a8b20000000000000000000000002fb42ad5de23090eb082f36c0dfc4b6f62e9000e000000000000000000000000fe7059aac8105d6ddffd1cc1510afcc5309d3cbf0000000000000000000000006c854fae7bb3dcd92bc2e0e2127495ea66a283a40000000000000000000000000e62c018be1f4e54b9bb41895df221a138188f6a000000000000000000000000cf5243d72694833a319dd3eb7c488b07d2d6445f0000000000000000000000005021d1b0947e6be1d5e143dd52c3de6d426d234f0000000000000000000000008bfe58635d60c458e1798abfc4ef4879e5d0c326000000000000000000000000c664a0b376c19d3c040241cfbb7b39bf1f4722330000000000000000000000003ab4d7c8c94edb0349cf96c7273852b3a11ab7c2000000000000000000000000357bc31abf9617b32ae38f20c450c8168e5c238e00000000000000000000000054c3735176d13cb9905026e8d96e938a59cd4b2e000000000000000000000000c44b63b31ce0219983ee3f67462dbf6944c6caff0000000000000000000000005092eb9caed9998f5a17cef15224c431cbc5c668000000000000000000000000f37e94404fc4e7d052336f1cb7ca62ccf3ce41d5000000000000000000000000c25db36d95e66fcc20d185e2f0cdc6820dcca886000000000000000000000000ba0ca55651dd8d65eae830e944f74c100c219c030000000000000000000000008257d8d0e850178fb7f0193d629b2b6194b19f410000000000000000000000000103e84d16c14d3d4e04d9861debf558cd1b72be000000000000000000000000979b08d51ea7cdf0a88b3239ad1e59a91505729900000000000000000000000046680916b5dcc5dfdf8a511c03ad28e92d3866e60000000000000000000000007e02878d62ccd5c23c55f60e42ce4daa77ec9a79000000000000000000000000721894a7cb9222a1146faaa745f4f25dd8489f5c000000000000000000000000f2da95da524cd30e7f402d7425c0c6ed36f2061600000000000000000000000096cbd1232a18e3b0b4ce4a18e287f3a335260c0d00000000000000000000000063724faf5056c1909c67bf12824e559cddeb02ed000000000000000000000000f94d8913aa35a79266ee6787b43237a3a262961e0000000000000000000000001f9eeb454d801fef0dbdac7bd57b69965d0f004b00000000000000000000000081c86622b7ea975110295e3ab5a3abfe7f56e60f0000000000000000000000007baeaa132412ed81e00d580a61476ebac3a3bdfa0000000000000000000000003e4629cdce66e7edd392f81ced5dfc661b30da7e000000000000000000000000d4dcd9dcf0380efd23c211fe5c6f178c0e1f754d0000000000000000000000001f99dc9c3abf4cfd2f7b085b17a3d1925bae9ac40000000000000000000000002f7d26429ebca19187d447a0bd7877530c8c68c5000000000000000000000000287cd8ea04fc0d88fef857aec93198f86563115a000000000000000000000000266eaace0d388cd4a57fa7849043a35744634a500000000000000000000000004b86a06fcd95d0f0ee80d855647473521e35293d000000000000000000000000709725115564b75a34087b8c6078a6271b9a61bd0000000000000000000000005c5e4bc0fb1a0cd231bf88c602c98bc015bf92ce000000000000000000000000171ec4dfa944674b2c24142debca3ca8049d8c7100000000000000000000000085e3a39ca46f6c73e71b2c5f89939a9a58e88f6d000000000000000000000000aae2a31ae2b834004c4d887dfc64121d2994faef00000000000000000000000080afd0d3b6e568eef9e148e5075f36e7ba2f06700000000000000000000000003dfbe5a1688cef33a00ef5052279ad9484d977600000000000000000000000007df1a07008b526ae0c8728c4b5910ddc06e4f8e60000000000000000000000000e64c6af55c7969de9545fddce92611ca7a328b700000000000000000000000030a95f2e9a16b380fe02aacd0807048b6bed80510000000000000000000000001be9082527bc5c6fbdc5b191b8b730d33bf6f54200000000000000000000000024e94bffc81fb529bff4831b48fcba873658a4b2000000000000000000000000293df72a87ff0088ef26f6f2e631db54c6fe456400000000000000000000000094a7dd237987f3432747418a91e70f080de19ea1000000000000000000000000f2d560a02b7a5e117a35e67ddd9474529f29fe8c0000000000000000000000008ea51acb33dd89e4b03c98bc63982bbc07d9bc6a000000000000000000000000084bfbe8025560f7d808b5c1cce4c76ac303c9fd000000000000000000000000027dbe02d3f915a57a193350ffb850e3ff4b44bf000000000000000000000000d91ad817fd1686cbb21b76f13e6ab9b8d100dab80000000000000000000000000d57333bb4d3db1191f9fff1c65008864921e4790000000000000000000000002bfec1bd4d93ca40afe802a9a90f7cb7c539eee80000000000000000000000003ff92b64d6c973011bce4a423eef6e8d21220b56000000000000000000000000662b849e75f3d2e24194bb3b67e6678fe48d9e4a000000000000000000000000b85eeea0c6e0d7548dd50884909fab58010e7d43000000000000000000000000468220bca43afbb3bf3e2b8568bcb38547928fc1000000000000000000000000fcc0a4dcdf3d3757b24c2f5282fe9c4af5ff20890000000000000000000000001b743a7cafd418fb255266388b4c98a0655a49ef000000000000000000000000ea412637e7916090df5eebfbd8bd5aa2bebcb80200000000000000000000000092bfcd5964a06443eea3776e6c5b046419cdd32f0000000000000000000000000172d06dd7d6006b7e70d82430c8aee18ac0476f000000000000000000000000ff24d26826d31e330d27f355daacced770b71fc2000000000000000000000000a43fcb519b8785df5dc4fab93902bf7b892a2b440000000000000000000000005b153aa667fb1edd7ae099d6cc50b64a9c28d48a00000000000000000000000056a4c948cb162e494b7e97ed62e0b7c99d614192000000000000000000000000568c44a051741dff5b39ec363cee05af4fbeba5a000000000000000000000000646efcd706afa00e46b7cd980e4df0e1f8a2fe0a00000000000000000000000001ef86427089e2e92b9aeecec0b1f05914083184000000000000000000000000d3eb3fd20087dd778d32e161e826374b297d3225000000000000000000000000250134a0b80b8d2439efef402c2146051fce433e000000000000000000000000fa9151336b14fec477f050b56b9237386ba2b263000000000000000000000000e534c91b5de120a23a8b4732ad3832f7f9548b2d0000000000000000000000007fe5c663326a3383c16732d904ce7e864304203500000000000000000000000015b8f57577d71d39e6a34868cddc7782504c74a400000000000000000000000091b256a533a84cc3ee40cf6e6801ea61c92298a7000000000000000000000000b2385ac9599b9ccb879d9305480406c7507c211f00000000000000000000000073c86834a6a3c1946f0fa5bcd5ba2cfd81d68941000000000000000000000000afcfd20c056465e1803ae033c0ab8ab8a75308a20000000000000000000000006a15e871c95d9f679aa95599b30e9d1c54baa739000000000000000000000000b37638287f37de8994760bc3319437800e27bab200000000000000000000000075769a7d655adb9037d86cbe9803cb4c54031309000000000000000000000000c91817a38b996d44f319c1ee157e1680579b1588000000000000000000000000753c9f266afbf3a6b17087e759510cfdc7e6edfb00000000000000000000000053e57cda7af66191c4d473eea518ff299fdbf811000000000000000000000000391d04772298978438fee55d2140ec59330dbe2d000000000000000000000000322ebc78b05ee8e2f5bde4a175e55770a40d97d2000000000000000000000000d80c4148438d3a3c7dec30d3fb3f44a142a1bdb6000000000000000000000000e0d7f83fe6adf962e47c9633717407bba8c77a86000000000000000000000000d0cccb71b6c4af516af59551ebfe1243491d840c0000000000000000000000009cc5ea34e91f342c8a151b37e1c0ffd8db36cd1b000000000000000000000000fc81c03dbcfe4ac53274f460cd8f2242bc26d2300000000000000000000000007fc8ccec40a75628e75c5cf990f7d6f249f163460000000000000000000000009dcfbba888af99da9693c230d23be85062406f2c000000000000000000000000bd6536bfa480cb9b114f74324539084052b857bc000000000000000000000000e0fed31a68cb114bfed49fe91e6bd1c745eb7e43000000000000000000000000d86c3f30aadd80cb21b7577aac2df32c4ebaadbd00000000000000000000000090d20a782413b5ce9df4b25fcbaf6a94725f8ca8000000000000000000000000683ca6c0e74ffba5ef978efc53c1585e4c094f040000000000000000000000000c429da028a4c26c8f0401ca68ef5fd136d2f24e0000000000000000000000004413538011b57145eef29e372f8b7e73780202f7000000000000000000000000bfc24ee60403128dd5c4ef6e7863efb12e6bf375000000000000000000000000a8a578e69247721c750d6951e8346d1e158786df000000000000000000000000719d6c9931a5c3e23041480f72a29beb946f00a4000000000000000000000000813f5c2786a2a3c39cb00de637ae4050dad148e0000000000000000000000000f76108a374c7444e29cf464cfa79d746b9e0fe8200000000000000000000000071d95f129d590da0d2aba6120b2ad3043c0e1592000000000000000000000000ccf6ba3272dafcf87a72b2f32c9c12f966e95e25000000000000000000000000fc17317d9af6b8769ce257e3c12ac305717c9ef7000000000000000000000000a2232221f456f01931ff0f3ef6440d1cb9c2a8ba00000000000000000000000071e2228e3829cf3f0b461cbcacecb69954368412000000000000000000000000a6e4d5113dd8ae10850e66fc0def1afe54f47b9c000000000000000000000000a84956c4784d24c9b137c10f945395f0037b3bb2000000000000000000000000104eae8510724ad53015b689d862220033c33628000000000000000000000000088ce429744010a61600ccb33a3b5f53235bb31900000000000000000000000091ac045290b895f83f4c0c5bad637262df133246000000000000000000000000d9690b51fb3767a1d8fb794bf32ec8812025c16100000000000000000000000016fba363298d4b344bc78016d5a442d966b8c8a0000000000000000000000000e1862448fa34c7f42f966061d94192bd7c614caa00000000000000000000000002352196b8be75dbfd8e31209675b5a4a8d7ddb6000000000000000000000000ffaec6b1d425a6d4b521947d45f66e864aab9d310000000000000000000000000a55b58f5f33eca49cb5499ea90fee88ac61d71f00000000000000000000000005fceade942f83997ccd1360214de03f428ad966000000000000000000000000f7f9cd9fb11f0fe75822d2d0ce5258ef7fa17b96000000000000000000000000b4577a705467d880edeefed51136715572e8d9d90000000000000000000000001c90240ecc6f47779c0ee649f81baf4147d07bf5000000000000000000000000997c8f1d748a15189eae721a30ce62eedf3810f60000000000000000000000006c74e1e733e0b0ca3fd1f2b7b2e9b1a1207a3b9200000000000000000000000074376efe654da1bc33b21c76c34550c7d2bbc31a000000000000000000000000bf12af6ef5289b3b84edacbc8a29e92559e80220000000000000000000000000a53ff0515c2a444232f309d3c92dca400fe7d89b0000000000000000000000006213aac316815e10f9910355f9cca70a76aab5e800000000000000000000000001e5bd9bf6bdd99f3e19298d84a2be3f8f829f840000000000000000000000001267e826b639b9ff31a4d9b5bdac83937716f67f0000000000000000000000003f63c7b721c7627035567352a2ed8cc01de330b0000000000000000000000000dd475ea75e008ae00053060267bccb78296807e00000000000000000000000003a78fba291489fd444834bbae9124f312b83e34600000000000000000000000069d8b63d27cb0b477b4c9ef4f828039ecbe916fb000000000000000000000000843380f221d42d978b99153192a883d7c39810b1000000000000000000000000655fc95b81d8af387f0aa90db2590ae417f34471000000000000000000000000ccc425024f472142488fcba92ccd40b6f4a5d667000000000000000000000000ff7dda44104eb6a9c690201bead1c045c0ba069c0000000000000000000000008ec5af3c93a96f36c9a942fa8d1d81d2852645a4000000000000000000000000b13b17939cbbdc73daedd6d8775d5d76fce5d8ed0000000000000000000000009eb40358dc13d208130c6bf446c52193a73eaf1b000000000000000000000000e8dc502835d333a3a4a27c75d4e0b24992f84225000000000000000000000000ef15fa44ac3c28003c2ef1212c32c40d376430d80000000000000000000000003a2054e7d73c499bb579f7e65729512bb1a7034d000000000000000000000000c0aea0a993950c7f3814a40815ccc7dc7711cd72000000000000000000000000be6b3d39956cd2f2959a9b1af70d6622246a4f07000000000000000000000000a47b676cf2ee89b4dba0049b69a9d0ceb77882ac000000000000000000000000175975afa695b9fc68a4aeef2c5ecea172114cbc0000000000000000000000008b21412ae96bd5ed86231d354a525501a45ca811000000000000000000000000d7be5fbcc6b8fa4ce065f7b800eca525ccded7ca000000000000000000000000d60d497f2b054c6ceb098afbd2e19c4f9f770379000000000000000000000000759f778db7c0f5cfb1f8ae17a0d4849bfcf2f6fd0000000000000000000000000d01df80b5312b51c54a72fdfe9f7d4ecd9f68f90000000000000000000000009b9ca31457c3bbca39c2739c0af7283b57d6265d00000000000000000000000042216134d0aacc9f25294d8ce6d14d3f971e3670000000000000000000000000b99defa83ee553475a23feb1b536726791bfec9e000000000000000000000000290c2e952f1bb5d479f0b482f1e15348abf36bf50000000000000000000000002f3e596b110db1f3f9099f8ce13cc61c2de2c145000000000000000000000000447603984a72e346d8657b9636010efa97aa8c10000000000000000000000000d4fff94eee29a9965aa0aaf2c0fd6e6bdd6e5d0100000000000000000000000067b713a116096985982a6cb67d7b3d26fde4d1b8000000000000000000000000f39b400691bf6387f8dd23761ebdbd5c681339f900000000000000000000000078e19cbb1fe374ae9118024c900b5e41cf0d9d48000000000000000000000000d7d9c5e4f8e546e25b2d6febfafb0109d40fb1f4000000000000000000000000a1a28f93aabdb0b629be1bb05c18d6a67283583e00000000000000000000000096b33837ac9c0fec80ced9f1d75ba6f5d999a31c000000000000000000000000781c3787aa298f4f918343f482df21a2729e49a900000000000000000000000047ffe4d9d7e2a78e36170fd52283b7f8352af1c80000000000000000000000009b4a500ac6e2f8321f612bb8a1ef9766d07594e70000000000000000000000000729c6a6b5a47d6b6a4c5db1acf5ce443b1dfd534aeb5e7c728c2acae9cfe71301c0f1ab9ecdcd1939bed52ddb84d77d1d6a6b41791ab11a6a26f7968bed93740079a885f11be82c36ee81c478820ab50c2d0f2bd5b54adc4e4cb9dee3dc6056029f5556ac7cb16cf4354fe2f75bc8dcdc4c2ba8b436bd9d2bf15ee032e568ab05f311b9b45eb4bed0c6d942ca8502d01b95a65a7841317db69b015668ec1d3903585b58b1e7e9c449f262e689daa3b1f9205b715791dd4a47d7511b30d0587d030646c695f9ebfa03cd7f3115e2408944a70d1ba29ddf353a3386d4804e614c00b5c5c830b54b0c9b389caf9bd25b1e4264d2851c6e26cfbf10d6e8219fdb4d022b3b53829c886fabcd85b6b88399ee96b1789dbabb67c46aa69ff345a90510020bedd88585911aa611a456fa0a6fa7cfbc1eef2234a702df9ad5f0487cb3f2071912a9c81d7fa789e2e220560e96750d8973b4853013740570fab21a4c561f01b50f71daa27d41930a47080645d72390b4bee5c00f425e26aa04615202c4ce011727f40955a6a419821124bae4ecb4b646fa4817ab55dec89c22752a2e138e046399ac7e1674656e288c302f6f412bfa3053625a12dbdd2d02fa2d5173d1e603ba0dd2e6a3dfbfffe80837547462b5338dea8a2cd3b22efb5ae20f69da13140690da9b7fbdddd35ee8c14728bafb7f84c941185936198f191632cba50033ff05f1f146fee652a222415b96dd98921bddef0f46048a2897dc833125743f1bd0068fc16d4c85400c95e41fa813e8e064c1ad95178340718639e7b790274848d201ff1a43725c96349161acd7f54484a3caf6ca355c8555c8cafce716be816969034b7e5b3d23f8e5fff1ae533d66224e1564be3ebb3e3ee3724a351fe3f0666905fe616ae15c2e23c0ecc0b31551023143242e8bdcff2b77a235296c07a3d39b006b5ababfcd1ee6d56801f8b502b09880773c49ce66aa1acc16b1bb29fa4b6606c76164f18002d657563dea4ad90e7398d7503a87cf6d41a54f79ecd9c8a8fc076c287633e9bc56a7547234c8864cfd8e83b8099e3e4a9db7ad601fff7f66060704f9800f4e657e32953c9d22cbfc084febe16b359730923eebd85a1018c4580014bfeb3e0cd1d72e1a3704448cd97228396f6d56eafef0b70c3f538282174802a5e6d762c0303590760bff4cb9661f3cb67e3e977425a14fb8098ff7d7323605600ae5db11c9357139925686f024d280f925fbf678f5589b2c5d71c404ebac04134dea78fba920b07d73f64fd0b6a74db38305235ec55f4820e7db72a5b489059dc57cde4a6fe09f6e81f3584cb0f46581b7020e6adeadb378f10f6789f1a2f1ac4063b956d7ed7dc938a7fa9d4011c2836dce000000000000000000000000a30e1a1c8effa786f8d988b28114c599082dd4d40000000000000000000000009684e6014cc44f2de22d631a9c382e7392073c49000000000000000000000000a5bdfd1a57ce8d1257b15ded07342611734a3998000000000000000000000000feb3cd1bcae33cd0320596057c258157c4405256000000000000000000000000c03a2514407a7f485e86dd3b15989d3c2ac0380f000000000000000000000000872e3678b36667700369d2f92d7d500b5682d1ce000000000000000000000000d9010076455f84acb9dd2e093cd1782ea5443681000000000000000000000000cb27505a4457616947973c865f4e86f9db517dd000000000000000000000000032fcd9889b2c4af04f66c301f1808d2865c3d4ca00000000000000000000000048971fab417f06488ed5abc7d61dff54a2ec109d0000000000000000000000007931457457717c404080974ba7dbf42dd3b4f8ec000000000000000000000000bc879a0eb5b51cfdd170c9907d3a5f9b7d3782fc0000000000000000000000009982e690c6b4a7d155020b6a617b295c5ce6dffc000000000000000000000000b8c92432d80438aff718f827970bf7990eb910b00000000000000000000000000d2169629ce888daaa0279c7e8f05d129a38b58b000000000000000000000000c296a3555a20363940404653eeb3cebd1964ef20000000000000000000000000badcd1f119a9bc54c0c3f54e9203bdd9b7e326d3000000000000000000000000aff93be7621c1719c80252c03190ed2bec1b6856000000000000000000000000488761835bfbc0f5b765cc014acd1bbc3ff9fcd9000000000000000000000000aff81acc2b9e9bea1e46db9b2e855a86249ac19e0000000000000000000000008127f3ee25777097fb421d7597ea879bd3b0488d0000000000000000000000006beb06dc89b69b0beb287014a9efba0389fbfeac000000000000000000000000fc5e1d7f3066ae06699be0f4fec0853d9e28ae7400000000000000000000000063a1e45745741c607baa0ec70c2ecc9ed6831c3a000000000000000000000000bfa1b149229d581b97e97acdb6f7fbf7bcbc1bec000000000000000000000000493fb24cfc00f7f3d38897c07efb0a686a3b1ed7000000000000000000000000ff03cbc68dc6e05a63a807836184bd2378081c5f000000000000000000000000dee446e1a419c21007e249450b70cee68079c29c0000000000000000000000006035532d473baf340a20a4a9ee55c1bcb62248f4000000000000000000000000cf04dfca20f49fce74518902fc8394d51cc28e51000000000000000000000000d3f07b7e7d25b43fb93bdd3b9cae1a867a8b77f400000000000000000000000052f50aae48ef1477893d25c111afc9722cc587de000000000000000000000000503dd94a71cdfe02f8faab76fbc2e47f932b79f200000000000000000000000094e4e52009f2163d947e2ec0a75e73d0c4e9cd4e000000000000000000000000960fa51361110ee935b38a8331941c68c8a6ae250000000000000000000000009c5169757246fb07abad05cdd0d15d4036684a0b000000000000000000000000c00d5068bf239b3547a08c61482ceb7ea3206c4f0000000000000000000000009f100932fb6c6eb714ea6fcc1d55072aa5b3dfbf0000000000000000000000007249155db9e5ea06b648c74a5de7db8a0ac0fb4500000000000000000000000016cdb47244e7ad93a68a49f71ccdf6bb49b0dd7d000000000000000000000000e2bd2f3a9119fbbc7bfe95c0786e6a0efe07bd6a0000000000000000000000002eab9ba9b8f29bc82bbf5d4b1d54df05f95793b1000000000000000000000000831fb2dfa43ddff3d091948a261fd29f0ca239c300000000000000000000000003609b0c198e90fb9accd39a42ae92475c75d5090000000000000000000000004f74669225a70c97e20fcf56a4ab6e3ca38fd46f0000000000000000000000007cf665ae2c4ae48485c7d08f0c8a4e85e6f0ddd50000000000000000000000001fc5c370691eecbbe08f07b5111113d1017de4c8000000000000000000000000e9322d4fd290d6730eeea19aee5aa26a0a4645f0000000000000000000000000a8efab5cf736d5b6f5a3fcbdddfbc25c16c3a3d5000000000000000000000000dc4f93ca2c5b3857dcd81b4960101e25d2bd1de00000000000000000000000003cd5713ea97d15c160df0bb05d52baa82f90d7f50000000000000000000000000911c95863a662ba44d698178f877a25d645dd760000000000000000000000005f41ef14f66cb451acada365663033d8cc211986000000000000000000000000554c3747c33c9f880404938e687b645baa13a35f0000000000000000000000002a7ad43c3787523d229c7d2ee2474152f4c707f900000000000000000000000043e7e269fd3e63cb4b49ab67e92b77c29e563e6100000000000000000000000042999409c367184905a4e8b460ff6054b3ee6be40000000000000000000000008a02602676c08670f9c4e4d8e2f1abe42bcfbcb000000000000000000000000094444f3b682516b2421abddaced3c5c40a43a0ea000000000000000000000000ded78604b26e4c75e7afb061badebd2a113b10910000000000000000000000000660546156e9b2f36200f40edf1ef24353c490f300000000000000000000000028d69d28ba00c9da186f90e0bde6754738977f6f0000000000000000000000002075ce11978aef9d53f7b26a1f1640d378d8fab300000000000000000000000056563df7ab78658f9585f304bf0550f3fba82a05000000000000000000000000055224255e38b1141591990467b3bcc2eea10026000000000000000000000000ebe9a634307aeb6d676f9f2479a84ef67793af5b0000000000000000000000008f60c4b79207df6a45b89d9b7e50ab5c7093a0e10000000000000000000000007f285fc757127fa629675e809313eb356eee7649000000000000000000000000a8d0c465c25f2d6981368f8cb67da81cd855224f000000000000000000000000c99c319945b0630db1102ee71b4e3a42f0c640c00000000000000000000000006fa31075581dec1f70e0dd1ad3ada366c416d37b0000000000000000000000002ccffa40ab7f9e6a5d862a91bc35ca3d9a452b6a000000000000000000000000a9b2c0018c24a7f187788409691aee30ae3d2d9400000000000000000000000057f19a2c84609e6709925fed50ed289ecd3aa168000000000000000000000000e1fa1af37c8832997e5841847339407f9520da9d000000000000000000000000331a4fca370b111a06fa7c4deb3e8d8c6f21aa300000000000000000000000008db43d8bb0886034bd7c5c5341a145430c727c890000000000000000000000009f778ce15506be05c6600177f92bcbccad5ed099000000000000000000000000682bc2c84a2e8e99b8744b5f074f46ef77ab347f000000000000000000000000131374bf0e90c679b5641daf84f7dd31047237fe00000000000000000000000038118f515936f42fccf7bae65cc397fb2f8a17250000000000000000000000007b57b033f18fd8b7a1758ddaf7b7f232389cdc12000000000000000000000000d9ba3aac0696b7d3f06ef08059052483d55d277a00000000000000000000000037536e0913105491cb35cfc341e857195f5b62ba0000000000000000000000003e97b35e3222e9edf67c721f2d346a3b6be0c33c000000000000000000000000a80a622d05bcb9d3556ccfa0658b2119953aed4600000000000000000000000029ba7a3b513a6879f3e4e810632d3f5c715e390a000000000000000000000000efee25dce211b304fb53865937ab327265a96fd0000000000000000000000000bb325e95fd1932e1853b9277db472ef1e171bd7200000000000000000000000098fa627b355d5d7f7633483744b613ecb20789ba00000000000000000000000035ed0e7a7e5636cd8dde05ac1b1e60ecb4e39dc8000000000000000000000000322727f9aca0c6f4e993cf786751c70e2847cb1c000000000000000000000000b2a7557bbb44d73be494124c50b66dfd423b2b44000000000000000000000000826b9ae82d75e5b936de9e2f31305e2a6de68dd9000000000000000000000000e1e82e88ec0b24ffde100d1609958e2eab1f97e0000000000000000000000000153f4f92d31f7299cdf94bccfc10942cae07e9010000000000000000000000006ac25f312a2558a764aa023af3fe841a09b26bf2000000000000000000000000989cc528122ba7032d92c8643b06dc901f0fe112000000000000000000000000f30dd5269080fd2a0ccd2663f7172a64910e39b30000000000000000000000003ed001b071b0df71af592fa523855f69c051b9da0000000000000000000000002622870cdca3a80ca1bedac727370f17fa88ee1700000000000000000000000008af88e2c67f604af7827e67cceefae9d1437c7d0000000000000000000000000ff6ea63882c6f04ee02bb1bfead5d96e1444004000000000000000000000000a13c44cdb532f437b02535bf6c88a8417486cc860000000000000000000000000ba98a10dedad382b6f09239f8747fb925024643000000000000000000000000384cd2e03ab08bd46a59eb9fe5f1d7e35ce9a614000000000000000000000000e9746545e21dcd9fa50731637b07af3c647ee2520000000000000000000000005c52c4d5ead2f91ccba623f83cc64a17d8b61d2a000000000000000000000000cb03cd429811c952c9588dbe1e389fefc64794e3000000000000000000000000ccefec7c7c1d70850872d6446fc45be0bfee01750000000000000000000000006aa149fdfa86b2f62425c760334c0efb75b2ee6a000000000000000000000000ff1eddb1e0b8a026a4f9b5ddc70126928d6e189c00000000000000000000000081010722f1fc152d3f865e41acd05b84c052162f000000000000000000000000329fd600fc9709809cbee24360b908cadbaf497c000000000000000000000000c62dc4c003cd3f1f259b669c1df371d46349604d000000000000000000000000262593c3de539d474c927b2dd15a0e176c39773c000000000000000000000000eae2bfb84cc111be9933f2b95d659a0e9c20971200000000000000000000000074dab65c80a95664743cb1c4bdbdfda67fc5ed19000000000000000000000000438c633de732e713a3b23230087d4446deb859e40000000000000000000000000a09e817809f4cde3720a5a5a9110612457b629f000000000000000000000000f8490f35e5c7da64e1c7caa7f3f5207f5a393f4d00000000000000000000000001e803f550f83d3961bf2f78cfcd16b1c9be599d0000000000000000000000005600bc0a02b233af105cdcd2eb6df789b3729da4000000000000000000000000242bc269b1d6c596d6cc11c75f21304dd2bda1b00000000000000000000000005635ecad573516911c73d0c2b95ef16e604a13dd000000000000000000000000112ca38ac1d6a0b2451087962aaf11f752f41e5700000000000000000000000065315333c0cf3b84be4aab55ac96ca511f8b85b3000000000000000000000000ad4845361bcba85c7e148851aa4ea165e121ce5b000000000000000000000000081654eeb91ef493edb000a1e14a99dd26af566f000000000000000000000000d79e46a582b972f59898ba5ac8d8e8cb9cf2ede500000000000000000000000027c75923f90bbdc536a9e332ac38e7e6a78e2fc8000000000000000000000000811702622a7729f0976a5bbfb0271ca4d8a93ad3000000000000000000000000525f9e1fc318b6a209073794e1faaffc806216c9000000000000000000000000db3028e28c2f4b069cf7b7ed7390e4ae495c1520000000000000000000000000a49524c17c1f14f1859df98208ef1944332ffbff00000000000000000000000087ba0f444623eca803e40e5caa94a43c465044d100000000000000000000000073234c303d30c08da24cd44253ea4f6a559c0822000000000000000000000000dd9a25caee5c1dfeab4b7cae04464d8abbeff082000000000000000000000000b723a48684e22bf8174b5211ff556d39c4f657b9000000000000000000000000367bb285044a616d8d56a0fc4ccec558f243b03c0000000000000000000000002ee899b3bd317f5fe4b875c983f24a6804a582a60000000000000000000000001e2ca38c3f44c7046aeecadeea451bf42067ed37000000000000000000000000cf60596a39ff8e09a9f043858f727d8b7cf96e0800000000000000000000000043856dc447454d038c05a8ccf9853f5e9d24288a00000000000000000000000011634da381c4c0d5b4d773acdf863b7a50484ff70000000000000000000000008b38f1f75b5fd4a8fcdaa2dbad8d2ff97ecb797d00000000000000000000000014e8802db136821729b0557ba763d2553def984a000000000000000000000000f889d0f4b3c834ecae0c400b728df07fd3e526df0000000000000000000000003ca44f64955d3bd602d22ba49f14dad28890ae2e000000000000000000000000e7adc8808f49593de2eb51402cea9283ef20b04100000000000000000000000042dc49afa27d584701a85affe16df01e8d7e746f00000000000000000000000020e10c4fecb3a920aeb8812760192d1510bfcaba000000000000000000000000aef34fddec94ba0aa363060153627221597dc92b00000000000000000000000018965eb460880c6365192b09760c539c6094b89f00000000000000000000000004bea635c476d9c309a1d9f561af9f260566366d000000000000000000000000ac26c2f0ad4c29f6ac62bf715b30ee6888ce77a500000000000000000000000018b51c247b2adae48f94b5d85870764bd507cf68000000000000000000000000a27cac46fd525e5f6c60065cb58f95029b80e3e2000000000000000000000000682d298eee08b05300cdc44bd89144cbc43a9f3700000000000000000000000014158f553942dbb69e94eddff30aee1c2ed9a9fb0000000000000000000000002acc0fa186d28ba89c38609ac248ac05d6b500970000000000000000000000004f00e1b43dc3531bc9a7968414b43339f3f4a443000000000000000000000000cdae6a73660a37ddd28762886091832d93b7df890000000000000000000000007c20c8ee14f1bbc53ec7bce8c60e983b558f4e6d000000000000000000000000f6985820b7d2417bcaaee94da737f5d199e4e0be0000000000000000000000003892f30a7afdd1c25d79cf3e6fa1d4bcaf142635000000000000000000000000ad9818566760f870c46ced3cb3f29661ebf63d7400000000000000000000000003f13f6c85ffd92f3d9ca0882d5eef04c05f36d100000000000000000000000013a046e9a0864757736c8173e16d6dd4a982372b000000000000000000000000544d9439be9a8edd1ae87f8d36115102515b8b0f00000000000000000000000023c88edab889826b9a553d8490defb171b825faf000000000000000000000000c0eb568af3dd819007effa0c933c669da8bc049300000000000000000000000010812be2ea05935b8c0f9373dae9f9fede8d05c4000000000000000000000000fcb9e231465c85aea30a28136efad29956c5b467000000000000000000000000465fdb0e1bbcd954c00d2c0bc018d3e538312aa7000000000000000000000000c66adf2248967b7f5279face10a571ad487782ab000000000000000000000000a3718c58ff6dd52f59bc75838bec1bd8cee335f60000000000000000000000007b2fb49187be43fa3a499c25d589c4d9fe7ec97a0000000000000000000000009041d0a80b5107ac41fb8e74ad3001e864b41644000000000000000000000000771a6262c361ed68669de0534f449cb15dd8ccc10000000000000000000000008fed236543742f021def62ab16269ed54e1ff32e000000000000000000000000e450ca05d2833cffc7ad0a71b6ee6b9ae4636f910000000000000000000000009ab1a36a040b50ecbb9087f8323ceced1574f913000000000000000000000000e86600f43247c39ce3b82b40af29eaa6148367ff00000000000000000000000040e8027c4805ae4a2d9a3fab4ad88ba0ec110fd5000000000000000000000000d284a4a479faf953165e89d9edbe902fbfed2149000000000000000000000000ca3f1289732c5a9fee341d6336c0b58c933846920000000000000000000000005c4f877a58ff1b097a8406591639b27cfdbfa627000000000000000000000000e326485ef5fbcbc9402ed7822b42ccee8b499f59000000000000000000000000683fe7e1a6fd9c6b63fe74cd865129d823be5a84000000000000000000000000c2e5e5019bfadbe4baded9b162768e2f83452e610000000000000000000000004a94a1a29dd9f76267286cd19a02b647be7e4d630000000000000000000000006476f56c61d5b833a2fa76a76d7ab0001755a2d20000000000000000000000007994f493f36009faea6f012adbc5b99b64e08a040000000000000000000000005f234add537e78176c925e3b0e63c336c538b251000000000000000000000000a049e6c54aa422246c07f732c97aa2c85ab8851a0000000000000000000000001f8a256b1c49a41fc25fe1d1072bb44f8827a766000000000000000000000000f8a9d8d15df1c22184e54ef5c2e113e63d2065a70000000000000000000000009fdc0eb602224389d944c02544f24bec4c2ec369000000000000000000000000d9c8198224dda591a18e2e9b535466a23644716a0000000000000000000000009e7f9ece6f6dee6aa2f3346f41581fa2bac21860000000000000000000000000c6dac935b16267ff989819169aa894b9752aa24a0000000000000000000000008d0cda46e1abebfed441283815f7e30237e20a760000000000000000000000008722a05a3e28b5eaf62143f45f8e0a0a32f1b729000000000000000000000000974990d7f9d1061a7c09da244723dc769706043e000000000000000000000000c579322f2980da8c46a9a7fac2720a8e21f2c08b000000000000000000000000670266086f8164357107218e720e5e535d30941a00000000000000000000000053142c3f70a7700862a5114ae1354182b060d93e000000000000000000000000c6280ed7c5d97b774b932e3f60ab3bb16e035d870000000000000000000000004d8e0d81d1ffd40a1dbc4e0a59aa857d040300840000000000000000000000000d65f6b3a0e5267bf18674238a3a1357e2faa1a900000000000000000000000045442f1b62da0ec452216d45129a8bef2acd52df000000000000000000000000579ea5485d514adf23e51afa6b64cb72d3edf5b900000000000000000000000014211d6ecd09fa545e2e13ffd3301656b04172ec000000000000000000000000aaf1b526bbcfd82decbb818a1ff275318d4c3fdc0000000000000000000000006cdbcdb9e904d5b60d474e58efab7616b827557800000000000000000000000054413078c179102153826e9a4821bc6c1ec01ca400000000000000000000000088371602e5a98eeea070843c05e96ce7743e98c7000000000000000000000000c44817fd7606e820dd3bfa9ee1bacd85eaaa6514000000000000000000000000d00b6d04760d341d69eddae8674c61b7bc1c950e0000000000000000000000000cb49ba8e64dae655e4b2f98935dc1b95113d6b80000000000000000000000005383176cea11e75d105de675578b20d81752f3f4000000000000000000000000ea7c39b69e485ed24154961189b2a864a123c677000000000000000000000000e33381b70564b9d5b4a47e62bd6fbada83447e04000000000000000000000000e93cc6e55fe6ad7ea2c6c807c5fcf578cdf1dc420000000000000000000000005ab3adb5a3e6bb2d03dd9a8173545ece66f418eb00000000000000000000000018e631a9bdc79f6b4070f342429290e1ca1e25b600000000000000000000000056b1f3b1b6c0915ca54563cb58f3e574d78626660000000000000000000000009140f21435017e0f9327373ef7b7499cbfd5d6da000000000000000000000000049a5606d0dc1f4a39491d7bd05ae94eaf4caa070000000000000000000000005fde61aa782dc4d361d62d37c51ba8d008abf324000000000000000000000000aef534502fd809279b1157a52715e99e1defc78600000000000000000000000087770a2e03da38438e1e68166952bc86a6d56a04000000000000000000000000766f937c04d4a535d6feca9efc78f58fe05b93f000000000000000000000000008443a0ccc038ebc307bf95ed3cc1d8b47fb0b8d000000000000000000000000bf14930cf148fba5cd3b2a15532054c4483ed0a00000000000000000000000002b3083b1105904a5ea24e929872795dfd42e70c0000000000000000000000000a8f25fb0a3b7927506519e531bb1656d3365cbb40000000000000000000000002f6f0a8054d58103485bc8e710eee6fade03da3e00000000000000000000000063b89ee077c2ee47f6e388afea04fbc3836eec05000000000000000000000000e036ee6729f15e036464ffdd972d80ea4ff2bc6f000000000000000000000000f07f88b7a076d6b5e0fce04cd9e53c14a315c2820000000000000000000000007356ac1054e25e916da1012f427cfd3d5614fb42000000000000000000000000eca72063f90477976bc58c9f6cd0bb9c1be70f50000000000000000000000000e4b19291a6e9d50a305714333e95f20376a0a05e000000000000000000000000d9277d08c9fd9281d458a778b617a91997bc12ca000000000000000000000000ba34bcfeda57a255d1b8b144b0427e82a9623ee1000000000000000000000000b7628b86c0df3dd957bfde1bcecd2a1725b410cf0000000000000000000000009a3578cdcea9565af09aa893abaee0560bc8974d0000000000000000000000008bf321e2e5a982bbe01ceab404631d12908ca412000000000000000000000000fdbf253e59624d8d5f9face2459cd09e636059f40000000000000000000000004ee34a14a985bf8ede4667e89bb580c913482c3d000000000000000000000000d0ff0573e6b2ee33219a38b7fe25801bc6171f36000000000000000000000000940f34d675f6c563716eb4b2cc5f010080d62bce0000000000000000000000006cc5162280518ee02db19f97adfbdf6c71de48c30000000000000000000000004f7d86d9298344343e6e544a59785dc6256376d0000000000000000000000000447d94a61e5400bf5bd48e50ad322aedb052c85600000000000000000000000010c07933ea904ff89722b028a54fc7a8fd762fe4000000000000000000000000c95227214183546fd00d8823a7fc5fdd60f381b200000000000000000000000086d4419474c6024e7d8f3168a115be64a0205c41000000000000000000000000ff3abd02d76253eb9635b0c05cb4dc89e72611b0000000000000000000000000a0196f578cd390446b7989b6f7b1da064cd356a30000000000000000000000003f6e4b88e6a1ec9e99244a400e2c1c39b21fd90d000000000000000000000000ed2dee027f02670d69bf85a84356d9e090a935350000000000000000000000007895f5ca5f46a60bd6d48a6b448279f4593be6680000000000000000000000003c0c09d6e0a8056a186c68b68f76345d1678898900000000000000000000000049e51010b0cd59e295376e5f0737d7295b984bbc000000000000000000000000900921938837f611190f819f49be016275453928000000000000000000000000600890e9fecd98d4cc44ca5d449beed9412aecdd0000000000000000000000003303aff57be2e7de016aab7b7d806eec1eb232b80000000000000000000000005f52c013a1fd7d946da1a2631e9278d9f9a908220000000000000000000000006823b6614b3524afb09b1c585b1ad1bd8fd7ebfb00000000000000000000000008abe21f86c53fca2f5a786c809c81a61edec7e800000000000000000000000060c520575d498c73f2a5bc186a8dabef697628a7000000000000000000000000024db7e1f4d2576de6bcb240c2cb309e36b80967075de658854309a3ca68967c07f19ad250bfb2f3931ba11d2804e741542bc6e3ab310066154cfd34b379df0b06bfeff349de3e39668d37fdde608ee373148146927d760d2935acd2dd99d1fa05dd20ee35c84514d241628c7932998c58e32562a9002cd2d6390a70a12e7d2200b24514f33db85d06e3f5922f68109f2d925b5f39d509a80102c41f76f16b700245334919200405741fd48b23cbb890669d8c4c45fe458c26834977d0882b9c02d1383afab547fe1877700a4375e2726cb68763a3442de83ce3d1ba5c2e7d4f03b800747a0b1d396d15ae76780e44e0fee63062850a81eca33da633ebf337b5052f9845d5da193a38ce849bb5cd66d9cb1a3c82d5fb143bbba5d2e45d144f3b0158861707ed958b847ec66de4f9af8a531c725f05371e875d0b67d9c8ee501e070c440297528723370fcf922b8770f6868d790fe2f81e6d7b5b2713b0064f750777a8d17ce5005936918dc78ed911b2d94255ffbf5c2aa5cb31bdf5be9ecfe300c536ca89c8a3402b3572c3b9c455f581434fc82cadfa21122dfda843cdf3ae0294f908fbd92367a58868cf35e3f6d294076004c20f7239e013fd6d86c276f20478f723aa7928240fc6fb250f3ae14e9537cc3d9c8ca4f4f3d7246dc311a52903d50a9990a22a6daea95bec7875b4fc5b435aa431e48bd0be56286473d3c65805e3f4874e98b307442214467928c853ab62b0afca7351d16d5f6edc9edd2e2f054484d9aa4e30af96270e1aa8c45b30afeed712c5bffa4ef81d9dab9b71be210459750a84deaac7f3de3349d6d72430104741db9beb3dc7f87159716f07fdbd05bee1e0225a633d52cc63d676f3562502c51be55684c1ad4870ca507a1409a004d2cf1ebc4f3d54462da437f75396d33862f139dceaf4e1be22165f5fb25a63041ca1c29750e4cc7a384c848ca457ad54140242b18eb68ef95f6498bf7aa448014de47856833d115593fe8e28d636a2615b76adfeea0dbe13810f2856169974079d5e65f8f6031892cca07a1714d15f7e22b6a0ccab5b760c576c69de8b4674012cdd4476f145c5ee0b1f22b515c86f09362c2baa6e3ff8ca85cd782e28c04000b5c51a8a93db5a0ca58d08ecba437c5e61c96b98e9ff90978d2eb7a98f6c6b06dd0bf4545e3591f14840155b4fe86a2836d26dc07d76851c76ed789ad1ff7502f07a6885e995138b36df1d58363d274e8b62e332413dccdca57603cf7148d60741b1a9451a520b5e1715ed8ce99db34cf6d869872d8ffb569ba2c8d087832106b5e2291ccd65f0554ce736309786f7b5cf50b4de707545f8fd0ddb1670c03b0492e1b00892dc956c89b2010aac2f3f38dd555acf9de11aa9209b956f79c3ea0295c21ab2586232c6a76e15659527cf433eb9a5f85a734e4f8b2d1c0d4522140533e2d5609d3370072d514200cafdca6dde37ebe47229ab0db65cc20b861151050f9615ad39a6433bc7b7386757e2d207cdc0101930532476e17b5e4625015b06987aafb248639cbdcf4c9cde8905d4307f7f2677329d3eec2df759b578cd3500b5b775ff97bbb1f4b453a7f3a40a494cd1d87a8b7ca7d49e584c61d8bf0e3e014f563be197f0a90105d255c9ab999896e1c43e2605840bc034e3dc9530d38200294465b4f171562928875b459c4894a6e6d2211e3680e73aeecc805165ba1f02749e207416c6c5ae029744d8cfabccc4bf11aa5fc39b3eb0403cdee3c8d08c06f42dc37b188904facf3aa04658178b34c584a70d34c4ecc212ef9197a7e2a603b87c4041c257333576c450057b96da0762d61ab2268326dd96e6e179ba02ba0271179ead039ae871df315e859a47fec4910e24f861847e0db5b98a48952be001347395ad073eda8277a07fb193e50334d6445771717c705f55f65f525816c007a9794c4cb188c24d960c15d3e222f1a82dfdc7aa11e8bf8310d82d3e3b2fe9024fc3879585feeec5d289d9b1dfee47119a1f555fcbe0005fa8e4e712d89ecc01b811601e37441ab29b7ccff4d88f0f64465d74257d02c69166e824dcfacf2e00ccfcf515c935df32b900950daf9b8afbdcaaecdefec41a2abcd0624113e2f0073469597ed31541914efc66d76eb5ad7fc9fad74bcf0cc9688151abf5be16220152ea8b865d0b11622eafcc9520302bbed2d67f53aa9139beb3a03eaf1bc9ab040e3a1ca30f136e567f4f139ef3b7f102ab91defdaadf86ad8b0088ed2bfc5c028d30a7b0e182fa3b6642a2e263f11570eb41042806e139e4becbd92a336a9201203e7e135e2c1053a0fa4410f542e7eb0ed2e8ea0a40c3c6358d66467458d307a580aa3c669f0430f311d8da507d1a42a5ea200c53289292b5309d58da970f02e8c246e3e69ce563bf10ae117c823f72518e1a56cf36b990df59063925a7d406fb1514f0fcb8c01a3c1056151c8ef89717fd58053a2e19aa48bf3e2b33d78403ccb24fd9bee85e3697bf5d43b385cb12fb088e96cbc7d9c5640b87c53a29a3043c7bef8082e4c262d357150beed65ef34de34c0172e262a327e1ed8edcb509054b85bdad00dc1a51229eab89e1d996658d4cac4a75b39437ef83f46ab8c9110459a6435e90d99def5da411b8c353b3792c667b2e37a117595061ff56fceeb806a55660ec1708028e34cb0351eadbfcee1230b53a0ef9b14952a7e9f22f9fe101e376fcc04673bb03407ce6dd73987129ceedcdc606f284ac629535bd49f45e06a80c9fe201a6c02ddb45fb453efa99a41b05a0a2418b9bddc6e63f9b44746f026d4c44cf792955ae60084e36f4c739e53769a45667635d40dba29d82bf59bc068cd2fe66cb93b11debd86986e53f99b3496ae79f09ba6022e3c6a71198015306a4a6d7b304e10ce9f1ced3f2caa233302043e20be75abec39eb5096e208cc302ec5ef22bfd0a5360c24d9cbcc805770f04f089927d2eec57d0c20ef4a08a8b03a1d6553d81c1c446092e296ac907adffea9061909daf670e5f98ddaa86f7f60187a52731046c64317dbc613bba9f558bbb3aad2a381f6c5f4b6e7e98e2c58504d41cd76bb6cda4e247c800d0f371419ee451cf2a983bd3fbefa8eb899615d902608daf985df803fe237f19682fc91698539c62e8c14bb414b9ccfda2cb4726029fc04d24305f975b4e2156c8d33d9150d517b943468bf0873d33c8261f1ba40351fa2b854a40149e603bfa78699a339c6d029b7fc3c491938547b4c0313005005f01067cf02cbadd000d57783c89e0512ba2bf3997dd2fecb04fa72a31cc23065a1bd1b0ecd6b5c82c90b63ab11ab36631e6a79f2feac513944b462718e4ae0143d7d88b0d5ddd2439ee4e4bc5a70eccc50320492c9b718ae8a7a5a23c8c3e01153cd7398166b97dcc999c6581935d1ce7267020430ac805e5b2872d6a3ba7028acfc56ad12456b78ad084c906a4e28214279778ad806e07a1de3a1a15683c023f5b4360a250dcc2d7d1eeba86799e4cc4bbd8e66f086044443546868a69ea06f037ae9c906d108398f920198f84f53437168b380c4fd2de46787316c15be505f49a6199f45048eac907882ff5f29cf49246fa3ef51c98b4cf81a002c697c6073546cd5a679f29e7502bfb11116c51983df356aaa664594ae5e52eb401835c01e4b960b2657b189b0f871c7122982b05e7094991bed68770b447cf30050d560141eb3e803e57d1894c2985b91927070e9eb322527392d6148df9ae69b84ba2055727352b932829b06f8d3a49ebad0c92daea5106c125ff85ff29cd6e2a8c68046450362519c10da12d3413f5047b341d36ca5d21fc6df23748e940df6eb16807c7539b5fcb7645a0e6e5f8b732b21d0763949e2d170144967d825e4a2668db0242469c160d248b1dd62c6fe6f9aed883bb98f57b4cf08b0eefc13143db9fb602e6d22fabf494c67d419caa04be576cbf0844ea2a0a44445589938e679fd63003626f668d6d894f0eda399797411d9a3e8c1023b4762918a4721c41b9d79e9c006a67f66801210b7417fb31bc7de450724ceb564ba848ee20e35ac650b65f0207bfe94a34cae992ab9851ab6fe97e78a0c6763131779af2163ff098525058f405267b1110be8bd2f237221b69e65f0787e598d05e84625d34eff4aefd127db200be3b5bf07de221fa75dfa188e256bc1331e925b9f69bdb7380b04cdf86e71e041bfc114f15bc67eb0b74790896c24695185174078324c21c26dad818dec4d702ab20fa7d86452e33f0a55e697cde58509e3e87d0ab93465b69c6865d491238032eeb3f9c7b1d4cde3fd5375c9d2b25cadc16f948667497e0c1cc650d96a392072b920760ce0d5b4fe69f24f91bf0fda34a1a251fda64a33a103d434f5ec88c02025a1358998aeacf2bfab6f0ee7cbaf4c4bfbb730e1f19790d4966285664de0177613310b8c85eee2c125f2da584b2c4e7fac484a06dcb42754969bf25582c02b8c18d96f8373c99736f9c8ab4d9598b95b95ca418190ae2b80477918c875f07448e24e96f580358bbb8f084970741a092828474a09b7c38a363ff86889a60044b33034c0aa3e7bfd7d5d46eac0b160d8bd9ae785a51eea3b20776c8267b250411148d3415f21e70086b86a8bcd6ce5345295f0d8ad67cccca1775552cda1604a76cf9c2a6dcd9079c79f8d29f1062ea2c5209f07e35d1c583fac557287a840746f8cb5fe779dc093cf38e6b766376d9dc626bcabaeafd053288320b610ccfaf74d53e4970490efbb955aae1793b78045df6bc000000000000000000000000536fc9aefd9b2ecb90c9d84a8257e8ae28cdff1100000000000000000000000077959553f19fd05c7c79fd2c473018cda94519c4000000000000000000000000c0a1c24bc9d1c88ae95fc166fb7e478ce315e1ab0000000000000000000000009606a39a55d585871decdaa9dcfd0950a1614da3000000000000000000000000e2dd6f57ea3a8b8f3c11e5e7841be18b589133780000000000000000000000001f1cfb56725c536c19c50c58886747519f891e800000000000000000000000006e1a8475a8d725d241c03e750b81f4e18ec8de370000000000000000000000002a502e7e80c6bdeff48eabc234a5896bf673fa0b0000000000000000000000009bd84eba772cd906bcb7d703c00b6e9a53531bbc00000000000000000000000059b522ca75c6df4b02883b38e818fbf28c81c74200000000000000000000000083f2b79eeb077379c8d9a5e5ee592cd8dea56def000000000000000000000000ee0af3f291a86dc997a0e496feac140ff19d4ca80000000000000000000000001f66e92f42382bbf0a22c3ba9c013d62edf048630000000000000000000000000a734bb1db1b91c818ad26315f13b0077799195f000000000000000000000000e218c7ddd27bc7ea317106a7f04ffae2862e617100000000000000000000000007ae2d5c2fea56f5f4dfc4c6da3010739473fc3a000000000000000000000000d77ca18c5596396224001ddd122177b29238caa4000000000000000000000000f782cfd03ad1571553f9210d6ed7eba41b51d7ab0000000000000000000000001c2a6bef0a66cf28b9315221b499776fa3b27ef3000000000000000000000000d1b16694a2d51e2fdaca54fc29c4303fce91d000000000000000000000000000411a09edb5c56f4f764a99f35627fe07cf0087850000000000000000000000001d296d744038f4b44225c80922054aa2c9501a3b0000000000000000000000007452c0cf59aec72caf21b25b456fa8a2127eff94000000000000000000000000e47d49d690560745c10f5bb86658763b789caf02000000000000000000000000dde87a43ae6a2650586359bd9848b66886ddd7d9000000000000000000000000fb91b47fd4bcd18e80065c8c198ca06231fbd565000000000000000000000000ebc817fbb9fe2c4bea5f38070be1b131c47317bb0000000000000000000000001e4490f52da8da05508a732626fdc83df6ec2fdb000000000000000000000000620bcb64664f63c116da751777c19e1868741f1a000000000000000000000000cdf4d45dbbf95c2b2fe3cb685ab9f80dd32edfee000000000000000000000000a3fca106e5a07938493b8c1282d015ff639266eb0000000000000000000000001021b5b780a0bdce9616691c7800f9067b8f0699000000000000000000000000385f4fd5cac04a47f3f67f455300a8b0a226d658000000000000000000000000f25c7e0827095fdb5f4cba5d2fb69541c52988490000000000000000000000000241b91496e87bdbd2a3feff512066ddd973da56000000000000000000000000f45767de6e7efc28f1b77431b1a76d7828d84c6e000000000000000000000000da9039e5516c045cf494c0d7a73546a990b666090000000000000000000000001ab5711ce9891bdab24b03b30ef894144f5af4f000000000000000000000000019bd066711177a9fbc94cdf2b731066578164379000000000000000000000000ad66b6dcec32ad9ebfdaa2e9cde9b398e00d328f000000000000000000000000f4c3297dec6f3ce40e9986ae66c71ff3640730b10000000000000000000000009472b5559ce6d2d128a78e6a78c4a9020fc5628f000000000000000000000000b1958032d09ebe10ec9443953e932726ea4e2e3b0000000000000000000000001e578976eb05a81f584fec227ccb5fd80afe13bf000000000000000000000000ce209bc9086aece6cbe2e67c64b43bc210ebf2c3000000000000000000000000ee97b9323e01139ade34cfeb1ee72a2fe2c045cb000000000000000000000000416ed73be43b551932dbbd12b67cd3fe867187ee0000000000000000000000000a5d4361e50b9fb413715ab0413449c65ea73aaa0000000000000000000000002e6284176d407dfb1ea27e959609c721006b32c200000000000000000000000075573b0d9781aa17f0cee6a3fc11068566276cd9000000000000000000000000a08503905e89049f9c7e399936197c52845a76d6000000000000000000000000a12731d04df73bfb276ee28e74f9d8a71754e7840000000000000000000000008dad26825c891c963e1014e181e6a1d4056efd5800000000000000000000000012f64fb4816154223be8d6d47a3a8b91faafb831000000000000000000000000768a63c06b02c21dcca60714cda5bd8364543b2b000000000000000000000000ba0f54c80c152a7ebcfd48df671a09723fd2a5c9000000000000000000000000bbb4ece8f53b5e401da85257f2c8a5099c008e950000000000000000000000009881040f2f316a3397c86c89df3502bc6b4b43ea000000000000000000000000bbd991f9fcdcbabbf8652ff18edbe7366ee33c2a0000000000000000000000006f384efb59ef60d4327dfe5e8e376caaf80e24800000000000000000000000006b828c11d5203dc2b816598ef520dd233094d097000000000000000000000000dbaa31698059be6a5078ebc69d2de2d029d9c272000000000000000000000000cf4c33d2b231f6e0914dcb27169d626b1e39334e00000000000000000000000081fd8c9cc8932432e421fb40d6aba364f03e8aed0000000000000000000000001916ef2301d60faba48f4c3afd1e57460707db8800000000000000000000000071c4a5419b675c8460923de87be742fc57d5be0f0000000000000000000000008cf93d13076743e9b2f87016447021103f49e95c0000000000000000000000000feb3fc85fc54b40dc6fb3318c82b129e7b2931800000000000000000000000018230e14df57180410d449bb8497009129a1baa80000000000000000000000004cba6cf3a6271386867bf78aaebd161713a37ab80000000000000000000000004ab844a26c98041e1756a3cd185018c9b03a2fd400000000000000000000000079c1a27fa59d58004ff897e915297895ddee8d6d00000000000000000000000064f60a2c71f38dcd0aebc9c0101e7e6f99aa44d100000000000000000000000070a3a989ad6f0fd9eb4abe47f8330868019d0f3f0000000000000000000000003bb089b3771ec07123df48ae092b72cf1b395b73000000000000000000000000d6016437f6cbf51e02a9035e9087fbddd13670e0000000000000000000000000aa391a0b987fcd8958653677e642831ca7fa489a000000000000000000000000addf41f03aa6c4815f70c37115787efe4eae3a4a0000000000000000000000004201152d4170e197530bdaddea7982d33f5f49e5000000000000000000000000bedd3c5a4dd53d03a8fe439db67d4bb74cfbc4f4000000000000000000000000ba05c2aa30f63f886f8d6e7ac1e2f99ef78731c4000000000000000000000000be9ba19a509cc0394276509f831ec5b49e146b1b0000000000000000000000005ffa6728852538c79e08f3aa6a7895d6af93c1870000000000000000000000005989d855cbc3655e866acb30494dda282f52daab000000000000000000000000292ce40d51ba51d8492267bb5117a235980691aa000000000000000000000000de8d984bbdba867b5ec14e9b6e945210afe2fa3f00000000000000000000000082975662fdea4f7c09a9b5d97aaa272284c918220000000000000000000000005e6c4749be5f5d887e511f48ca7f67bd4277ee18000000000000000000000000c3dccf54451d10eab84b4e9e53ff1be470655e270000000000000000000000005327ddabe47eba445f0274ae8987abd72063e2600000000000000000000000007e575ccd0e2c1609127601fd4d4e88e57d6b1f62000000000000000000000000fd6fdce4d47a3e80f200ef341fa43f3f8fc167690000000000000000000000000e56bef70b8bf24584a4de9ad9e1cb10a8736f670000000000000000000000009e5f94bad72b82533051228db1a5cfdf8f322a73000000000000000000000000c0bea97fe39bf84e95919c1dce3f2704baf29dd60000000000000000000000003b82b4c2c64e1243c5dd2b4504d6449ee4c1eaec0000000000000000000000009cab88fddb2acfb6c26c09f3fb96b36699c4015a00000000000000000000000010f89af695c0cb05c8cd04446c0dc2fa5c345b4a000000000000000000000000705402b0690e6db6ef3f0faa6369c0d60deec733000000000000000000000000b1a101a1d1e882847630b9e0350cd4c0bbcb7c49000000000000000000000000dcd6f6edf814ef6cf5561c170a7f2ace5d9745320000000000000000000000009be64ce36765b9ebcb1798e57999e735e38ce63f000000000000000000000000181a9d3c82214cf546b43e4ea9d8c2ff1d68c8880000000000000000000000005c8c9f06d626c72af81004a18e432e74b6143a27000000000000000000000000c0c56b0ea324ecdf46cc03a652572a4a42c3b4e300000000000000000000000028c5b0710a30101f8feed7f7ae3fdf40a3a33b400000000000000000000000008c24566e2e62dfc81c1392cc8ba75a9bbf3ae9f5000000000000000000000000a46df1406145b8b447ba4eae7c69d21311d5ded50000000000000000000000002e1a0ea14a11c2d85f59f15c74eb663e02f9ab9b0000000000000000000000002ceb70dfeb4339ef850c1429b10dfa94c79a15010000000000000000000000006469444a443fdc73656e7ccc55bee4cc91ee18950000000000000000000000003a8642c14d5acf63c8a3bd59e919781439e70382000000000000000000000000f7ed1d370ff03d6e1dc625f1f58b26491f9c24e2000000000000000000000000da8c5eb1322a188f35cb572b21f50b02fdf0ca93000000000000000000000000d952b8daafdd019c995af15224d25595bb326572000000000000000000000000fe551f4762b0d34d014bf032e9b100d9cdc1a4ee000000000000000000000000e00ffc08203e17be8f1eb0cade032aec9e5e460a000000000000000000000000a6c298f0283e0f1f8048ec385e474e59d98b90c30000000000000000000000009dd19b454797f1392f2805d62bf71d20ca512f21000000000000000000000000b9c7fb04219619a61326410112f6fda8d61f9fea000000000000000000000000d0b10804fe79925dc50d54680a7f508e97b0751d000000000000000000000000e9856576441a6a01a4593d78c02b6b1e33552c140000000000000000000000003f2323c25f99511732232dc7ba2d7cada312b23d000000000000000000000000f2e2097d19088add6f760de40803c52b43dcfa2c0000000000000000000000007104cf7d6a2f90e053f67779c22d145fd933aa710000000000000000000000004fa3258c060e4c7648dd2c34c116cdc6e32eff5e00000000000000000000000020c204d445cae23e3049e29b895498b17599d361000000000000000000000000d6c4621febe41d96291e7327c934de135e80c405000000000000000000000000ec2243524a8c6586e240a9ad84817ac1268a0edb0000000000000000000000004de1d00414511e2d7dbf7dffb42b3d0a3f9660d0000000000000000000000000599db688ed9312d8e893247369532bcb9e4082260000000000000000000000007deabba986c58e2e9b6487ab235e0691fa06a227000000000000000000000000d50b25845a3c2a55ff56f4483a980783ad0d3c5f000000000000000000000000a8ad06908babed5b78257a518cb5e416d4dcb17b0000000000000000000000004914de52deb2e623438e62aa65137e9c6dd3d39b000000000000000000000000843fde05c8cb2c75872bcfef49a8f06c74911be9000000000000000000000000ebd5fd425aa5c38ae5ba4aa3bb1e0eeefbd89d2e000000000000000000000000c84170c5d4444715754bf95808111e2bf223cc9600000000000000000000000041cc5f5036da43442eb4749d00c6a3145f50fc89000000000000000000000000cde1b006f3336cde1b617cbad9cc7d52dc4e3b6b0000000000000000000000007941013f048892b669ae9f024e4db717981021e4000000000000000000000000fd7263b328702112146b1f3047e63d08e69b3afd0000000000000000000000008fdb35273c6b76c15efe35a0985a00d0146fc76e000000000000000000000000e0b725f118118f4d6a6412db0ea594e02e0022860000000000000000000000002b94e34f3802555b2a17b362f76d8c96f3e4e2fa000000000000000000000000a061440cc55c724a082615325a5d92de31d4dddb00000000000000000000000044e32ada153bbc7c959a92ca80898e162b3674140000000000000000000000009ae9e02fe0bdd323a3ae55e90b97a4118fe31a0d0000000000000000000000000ca8573b6ea8bd37cc57e0e117bc3537d97da008000000000000000000000000158e28026702b53a9fb2b276ec7441a19c9f9ade00000000000000000000000032dbcd7816663e30dddb7a9f14d2743061bc2a0b00000000000000000000000095b4805d93bda0265f789b9b08f9ec0051cb440d0000000000000000000000001a1015a616d3002f855b506899b0d6a89e60648f0000000000000000000000008cfcfe3f66e06ef758831b2ab498e8ff71d6dd590000000000000000000000009d21bffe520e834eb913a114fa27537548a61b8d0000000000000000000000007345573bceea39f35fa55b7e16be46bd38696a5e0000000000000000000000006c5ef7bc3f085afea19091719757c0987e9e3e2a00000000000000000000000019e530a6917c65ff13d4e0db8a32695192190056000000000000000000000000f094f61f7d1e4ab10eebd78620a586aa706feb2c0000000000000000000000000f4564ffcb268d80642e53a29da117885ad86dda000000000000000000000000a4f6806bac43d4459302a70e1436479eba0584120000000000000000000000000f855e15cbbbc2220e7e9603cfb619260641acf00000000000000000000000007e49eea1a9f30a989e848ecac1e072cfb3e066be0000000000000000000000001502b9b379c34eb1df797aa5408968612d03f233000000000000000000000000d98fa8ef2dd60e96f0c165514787ff44fcbc19420000000000000000000000007de202abd2b7a1e99a62746fd357b6eae45c8cea0000000000000000000000008e75b33d901c884096ce396b3e3876e3f27dbd590000000000000000000000006dcc18b8d87b85523ac205c4fae62e49d037dfff0000000000000000000000003a965f6af8acab1b844f123f60a39116c66972fc000000000000000000000000d7b7ed2d839a25eb92b2d34a1daa4138011fc2b200000000000000000000000024d0b765929eb6c7926f66e016606aec15fada8200000000000000000000000013cbec4769fb2a8d8dd2af3d273d43ea2dd1130b000000000000000000000000f1513857d92e5cacb687c9baee1a78f0f0653641000000000000000000000000964f9b49ba9434947c1433fd700451264f5c5bde0000000000000000000000005d4828c5efc5282ea8837ec5743c26c4e39ae35c0000000000000000000000003fdf133094122dc00fc20b0ebdfa38e4f906368c000000000000000000000000762cc4d2e90e701f601b4f040fc01ab6de3fb7580000000000000000000000009dce0aef210e0bcece7ee0c76f10c32f421a14c1000000000000000000000000b9ec3dc5bb7000490ad5f8a894cb46270cc57e2000000000000000000000000074d0d253ce69faaa9daf973251b8ee9a4d778ad6000000000000000000000000d8bc58e2867fa0b616e05a1fd20f1e1803be5051000000000000000000000000b453eec5a1cb07897026aaff1503db06530763d8000000000000000000000000ec1329ea34cec869bfe0422ece9c13c2e37457a900000000000000000000000093dfa6332baa317fe1e5e07d0cf95c2ad8b220a40000000000000000000000009bb20340e801f9211a0dcdb0524756e0fa3785940000000000000000000000009b51fa95e2509e93684dd6acf42a653e05ee00e60000000000000000000000006c2ff7db8bd476c8def4f7934144b9919bc988c90000000000000000000000005a1a8414b34a95b57b3592ff9d3fee898a7a8dea000000000000000000000000ef56413df432e22d5fa8207a298e6b9b35350fb100000000000000000000000090e6dd33054fb89b9c348a92c0ba211ac11259440000000000000000000000001f137142637c940a41ded7d7775224d296f9bd83000000000000000000000000310a0403d2a8f0853b5afe0aa8fc5144809f32290000000000000000000000008ac9661a713cf5c9c63c73780a3be085bfca0136000000000000000000000000f2b44d1d09b137fab51386315df8e1c2803f254200000000000000000000000074ad8f1e516945c46fce684688e008ffee873919000000000000000000000000984de49bb7814123d8cac8640f3265fe6bf00520000000000000000000000000995c01d7795420f98676d0d6fa265443b0c269460000000000000000000000001bdcd228e30a4c86ee9d94d288726867fe06cd5c0000000000000000000000005212770d6385f68cf1f49aa86b863851d6dff8c50000000000000000000000007a003b326e2620fceafb48924223fd58468b4b68000000000000000000000000fb25c83e51777528df468acf39aaf7d5273ce26f0000000000000000000000007eb048589a2a71f268c304d9798f30b03e4ed0a0000000000000000000000000862817e761d5f1621c67635866f23b408b76403e000000000000000000000000e15346c51ea5fdd406113bcca515cc342ebb2e81000000000000000000000000f2a02a6069b82c573a0f7272947d185698a1f357000000000000000000000000e9170c6598ad535bb7aa7307d974e52877c745b2000000000000000000000000de9d372bc17372da355a8818eaa89b47e05c436d0000000000000000000000003cacb59bd552c0aa0aa8f45c4e2ca231ab96fd93000000000000000000000000e69ca947a7d1018ec85daf1e579e7af98df0d939000000000000000000000000b7ea06df338d316ecd9a8033d71fa9ebcbff0fd90000000000000000000000006fd71c7d33f67c3c17f41dbaa330e346231be5d10000000000000000000000003b693f3170e05729fe746021aa022b1422fa51b20000000000000000000000005535c105ea57086001a316295ce8b172852b40fd00000000000000000000000014c2cdde834e3e15f4efd0919d09a93cc00b6dc40000000000000000000000008dc89a2ab7e251b5a35505271cb3df90ce56bc20000000000000000000000000b7923c5a25b01e351268748bf22839a0313034d50000000000000000000000003909fa7c983a63f48d8f728eb41f31b886e9fa36000000000000000000000000c3633cd5268e76545cf2b54344f642e7d00bf441000000000000000000000000b78effb6c0ae6970065f3717777194f28989c9180000000000000000000000009f89f79ac288cc90000f57d692872f0f74c3dbef00000000000000000000000047f3682b3a95c17b2266544a7d778b5e1c10bd9a00000000000000000000000079b96490e5220b064d48b3f0164d64c608475cf6000000000000000000000000dd94488c6c4cc5054594c33043960514d11938ab000000000000000000000000b1bc71c2523ed4a97b84d12afcfd61fc289ad4c5000000000000000000000000ab78ee33cf87807603abb0569c4885ad946986c7000000000000000000000000883b0d7460379976a9ef934da891a304e6a7b24a000000000000000000000000e0af8b51bd5614501de5505e50ba8d9dbb1f01b500000000000000000000000072aadb281211e4c896371ae2385a58078f3bcf0c0000000000000000000000001dc3ced07cf812138060e52dec58700b6497548a000000000000000000000000001664fd389e236b3b1bb4aeb65fc8b406f16dc44691d27f6486a22b3b6d9b7c05bf281246b4cadf8dfeeffb0a63986e7306b4ec0233a755f4a0e6f319252882072b2d31042d0b3df4c88c8af59cc0e87ad8b8db59261e02dc0bcb770b7ee00503168bdae1146a5353ffda6c1fee0d5bbec994b327154ea50bc7563c33be570100e5efbc289586b6b7d0d7750a00d15950296c5f8a2e99f40c1f575a1f3cc6be03421f21b6ca2f6a254a28c9a71389cf8a462f5b78e551e253eea47e98d9e94303339e7c5a7928de4c049407b32c789af2fbd9fc57fae5cd1ed48557bbecf5f5043ab2adedf4d4173626bb2716959e0ec6850ca3ded28918b38bc27e5f3a1afa04f03b9d4cd29af5626b6ef2b98c79c1a7be4a74a00f900af4f56e55c0f465bb06c3ad53134ebf4ff01f1ba6c1bdbecb4f5062a6159b6c52c2f5596e82bf8bc300e39c5d9580b384763c3cb53e3c34817247ad8326bf398f1518bc47eb6b092001cf5205c955b8231b6848af7b64f36949ef00fb0fbb7142135411bfba3d1b4d00c3ac89c7c802aac7916c3afef32e75d6f4920da4850c94a26947121025a6ab01e6d97ecb201e7a1064b7b936ea7541fdedda0cab523c1e961ce7a4c624c4c103e2c4bfef08ce168bbdf4ae0dd112d4c030672746a05ca2e4057819ee4af494016cc4aa6861602b4808f63ecd5991422fbce5fb7e4dfd9bedc5d7d876c1abc30618b1e64396cc660fb02da1d5df13515fdb712c62195223db289f71b8288452047cdb9b8b698db4b3d67fe8070b2257a6632345cb31a37bebc7c53700dbe56100b85a96efbd8b643a62d5e2f46f58b7d0a26feb08dbceb4ae3976d6b3d7d93d04f30f4acb92b47faffb098bb4ec071edb45570dc6796e6128825b0b7dd763f904a5de177fa6ab71cc138327f2fc815b974b185c26dc2ac11954c17c4582511e00c30cad2dad2daf2956b1cef6bb3081c00af493af75b95c45e6e3482060f74102f10db79f538b1bba715a27572c49a95d29fa38dc8113c3b928e9de081d72e207948e6f86f1dda316ed33515e37cb7470ffed3d2dffc43ff5b81265a15782d602a285302e5cb6154898eaa9815980d7f7ec12cedea06727271493e127522fbd00f5b27a3e6790a3575c53b9898cfa6ca81ffc9333c71121cc71e97328cecb2c0418f46a356374ba72c17839bec3be18ec11e5aa3941f34473788f4391d595f307bc9e054775862c4622c8b6e66bcf82e8c92c1500a558a0cb4083ae7850aebe0403d4f75cbe832890fa205dcfc5c5eca44e21953fd627fcaff35fe3312822cc075511d5bd1a80fd6739e832d18d7f0e10b2cf2a6ea106ad5e91dc4b95f5993104b46323c3bb097cafa40c8e3dd6319c0dbdd7b642b33342f30260f5e1084d9902a2c258a481957a73045fd92d8c5c669da3939bba28944ad5114561c2e98c6f0695233cf22fcf34eba4cb154aeda2d0d8be307de661154037894b4b2f9c365b04e4bca3264112be60467a3badc7f35b4c3c11c90597b02fca1565b83fa53b600649ac6ec3e7821fae67964be4ffad9a18ab4a734e3eb6d2cef3334bcb2627e803671ce7cd79d0960d9b73f88c936adf1f2fb78fac0c17ca1a6605b0bd0eadb0071da87cb3e4001f86e9c10a6443580505884273d401a017c4f0ad24c916dd8101c7a7e61d29354c75c668cc5a4af4b6289013e6629c7e497dfed44439dc4e2f04993328cc6752593215ac414d82ab36aca5b74ebe65cacd14174cbeb85c2845057878668a0a2e073927565e5fc1317a977495837a9576a8578c2746c9f9377b008e68b2a882609140ca0d6dbf90f0e99a53df59f93f24f95b3fdd7f9d310e16075cf14104466934addf8041f528e4e2b79668de4ec5581fc52160335086322c006f0a1440441467197bf351d459b0b6dbbd99316c0fc13408d7d266866af6fa023d36a2e0353f310da62562a965fb26d398834b5d9f94d85c25296f9d83495802a79335607cd475e504d722b920cdc7cb7c1b07b4c658552febdfde9be728ba01b56452f9d5753f7aa8224288e6784c3bcc6f54285ef7166f4334babcb7190a062acae026f21456a9447f23ee2ffb860d0997cbdcee0fa12f748f49e62d62510166742bc6b88818646a6c2edd7f1971988633ad60a9034f154223da6aef72d0079738081094c35711c278ea4ccf9afc594dc00e7f1a72c1f49f0f676c203e6a068ba6d55169a496a5df0007fdcdc6b45c8b3f139285db757940a82276bc7da201055080fdb67cb798ef0af75855784eef76d82036cd3a0ca327936472cc834f06fc04a9bf57c0a93f1a7cb69d121a4e6ea8e557e4a536d3c4b3b77bde92341802280bb7affe8ddb93e4cdd755e6b0bdb43aedfd0e04c6efac51a1761bfb0fb20370f7bdd267d9df82b71ecb728cc3a228c5e81666fffcd868c7beaeed9f016b00086aaf33d8961cf621da9159b48375f484aad62bd475c01f621584f491ea9901af1d1c34324fbf7edea40a5731c0c89b470c6fa44e5112b50edcbcdcbd0c1305c42811a27f2ee90cb5ab37c3f60c8a628ec451571e4d1fb6ec25f3c1cd435403f465a3a7f55141be65095fa4005591d36167607fb4654ecf07db701b39170e07ca556f05fe6903694bc900f7086c003cabcfb90b0f741bb59769cb651326f000285753fe7c72fbe9bff7471b8c40c7bffb3b1202aeb14042fbc8c833759adf003d29f5045b99051e49fd4c68afff3c19be715185b0a7e352c4becc4694be68047e96a48156905aacd0e7d2b8ba7e74212353214792b4f81663486b71fe6a1007b08e6d448473451fb4f0a6847243f946162a20d017a3fb6a3c51de6cd45f7e051571b68b460db558f9a15b05f554b68699e391222375831b5f327872e9428b0106ec8c8e5b7c76e6a119b5858071d0049036e39fbc7024f10539d5c5d18e2d02da57d3914f7118cb31552215e80e969c272100cf2dc0c3586e789af289bbac03977117b11897efd9060eaebc92b1c1877a924736d1212c9f4afb7beb1b2bd2074aa01b1e781b80fc9fba8d380d060af8bb0f189543a782e64170b72b81bec1017e4528e18c152153ebbf33133cad4e6dccf9566872a7163160e68a962427a407449ef41fdde83021e565807297507e9a7ef76e5e927980678a69e21a98a68f03f72a7d18753c1796c97962489b534131cb14db2f278997102c5cb58c6446fa015ccf3e21b91111bbd31f1d259fb3f1d89a0d21756ee3bc6c07f4a8f00e131f00b33468b339e384ebf16b4719a7a98f8e3c061574082db80cdd21dbbb19a95d03d0b860bc9652048d592bb8e7a6bb379bb7a892dbed6cbcc10f37c83ea41e310116be45506d7689adf6609076d96da0c942867fe18da1004d5e1752b613927a02131ad241b24d8b1db3fcecac68788238ab1e8a2b03a13faf5c2e721d564eb70357a0c64a30e844fb992ad397459ae160a46a0aa3e354c8ae73594169c3bade013eca753e65d11fcd49695bdf3342ede7ca89f03faa065b7b3653e924b49adc0144ad1c69fdec14ac93f2e3d49eac69d630979c08add2bc2df3025fed34f0e7062515a6362b33267bd7803619217fc4731315723270a43921e4cf621a8f4087002003398d290fef0b4563963e6db4897db40974d28c47b1756c263aabae64150290dff8f51c664116fe4d78c67ca691becd736bafc9ad182c42759a0ed5c27603dd13c39ab2943ad6d849754d4bf42a3964621b94ed453c3caac7453c0c232006c05d881fc3c88d2277f2b7d7260c8a5237180db81bc73585699faf231b8f9a0079cd28682d233b94b1ef40b8a6ee1d0a36d5c9e234ed8e13bd481a05e59ec7013238c6f4cd2a4a6ef0cd14933e6f7dffdc10620a6857b68037c974d25d5b0f04097336008c3e87bf6a602987b572cfaa73a885bc8b9a696b411df17f34e0a9079ee32a90a736729cd3e3209113c14224f45197075afd772b71b59cda286eea076a3bb01fd6cc0e2bac5e4f03d44edb274ff912b0830ae850bf4e39d2c02f2f05d2671e407abbdd9af13fc9b970af4cdc17e33eb3b0486aa464d320f9406356071348b2f08071e2adc06bc1086676d899712b708913d37f7c5260a0d95976a707e85e44e75680d050606074a6bec1d76f03a6f0df8dbec322c3639c8ac1f341065c02dda5a8e2c9abfb39f56bea938a019943ccac84aba9c83328e67aca3653079edba5b6d9fab655ea3053511ed62439e28709d4f533e5cd28f9f482c61f7f06b72893bbe5d18b75e2d51cfffbc014d47e2b1c43decfed6ce614055aa7f4fc04811dddfdad70f1f1f41b5985206288ff15a38b9c0a42cb5a97ecd36be2b15b02256458b496713f4ad27d61123f307fa9215dde9295934d6e039d54698973b702ecd3f642bb4950cecdba547afbfd0ae64e9e29263ff1fb9c5d4252f6eb52e102bead535377e0d42356aeea08476b610de712879e049a46611f586a648343ea01a20563abe08d25eb40ac4efeffe0847d9d19ad122e11757498bb623e84cc6d06b921eb7582373b8bc0104ee75fd78eecdd962080485f1f833d23ecc0544c9a05bd703a0de8294d690edd7b194bf8dcc68735a60c88b7970f5741ef3ea9de4a00d4de0f28be40c3690cd119bb13bae3c019a9c52497dff1806b38ca52331939000418238adfd835c7316eb16c01effb1c76c5152e6456d3d8f1e192611a75470580d97531e8a204771a609d3e490427ebf171027781af7b41ca9e2c9bbad033a8a9cf5f2da99ebf1a80b34c7077dd5cd5dbba32000000000000000000000000bd449f01b7636779597d9111a9ca7bb4a33b36c8000000000000000000000000848575cf29bf02c836af54b3f1da89f08a435b5600000000000000000000000096c78b79e7a11fc99d674dd309a7eb55d16da07000000000000000000000000052e9cd229f3cd982cd41c7ed0add6fe2121c19ee00000000000000000000000073cd8ad8d32d15609c2e8d721613f9c32e88f8870000000000000000000000005196ca96da8f3d622154031bc9100b9dec9d5fed000000000000000000000000b1de56893a91a126d417f395b3b6a2913981d896000000000000000000000000a2fa4faebc6fa5e4f9062b12fb657bc1c0cae110000000000000000000000000f500251bfa440b2ccc8e6c57559c4a3c0eabebf6000000000000000000000000bdb4dfeb8f27f69457cbe49102b736824c556e3800000000000000000000000075df71348a252d7d94abc86220aa1ad2124a8960000000000000000000000000c14671dc8989e020f091b4230366188c4ca4a7630000000000000000000000003d7a2d801a0b15d03d6db1a200e76f39dcd06963000000000000000000000000598bc7c95083c287f36b5344054b2f70a74229ce000000000000000000000000c267d5069fef2f49f20071eac1dd77396c0f48ae0000000000000000000000005c34387165c8d0aab0d16b3c6aee2dbd9d95002200000000000000000000000018e939f02aa4354486c087c1b6adb0b9a9528b3900000000000000000000000010c45e9b8f8dff0d5eb65f0c5f9f3250acc61dfd000000000000000000000000f565904a434e99aa3cca0bb7c0bf4d47f86a403b0000000000000000000000008c310d6e8a48be523f197b0669e1a7ccaae69c5d0000000000000000000000007bc362dcfbe56bf4218a6f6c48824570ed6f0415000000000000000000000000869d1d8a9c9f861cab93ac2142175162ee6471a7000000000000000000000000557f09224370c5233ec7e790e3108224bd635e5100000000000000000000000050071a8e63f258c451da0f893766b563cd68eeb10000000000000000000000008aa988062583cdb48eba43bf8b8928aee3b6255f0000000000000000000000002a5777073a1c072ddfb4e6caae3a69f07442b666000000000000000000000000f9af0a842ef3e68ef8c087aa51aeb0fe076f2eb7000000000000000000000000c425b3b1315636dda26c9b5a7f99fd50119350140000000000000000000000006a971945105e5edeaa133092328140ec93d9b6c300000000000000000000000077a21d5b863743cf1b38613a339bdac8db3b03b3000000000000000000000000a87f1ed8fe08b7589a63fc0d222213c27e6bb17d0000000000000000000000005f1471773f4e524bef4fada921c52217311289b30000000000000000000000003917e7684231ced89ad0f5b0c182b2e04a4f63be0000000000000000000000006a6552d9b29eb0b6a16233eed242722dd232df8d0000000000000000000000000b0283677b8f70dc20f4cb40078bd9b806b305620000000000000000000000009a500e16878da04cf0ba5d7da92d37b7e2e67dd70000000000000000000000006c93c747bd6cc48dfd5a60f33fa5b3aa497f971a000000000000000000000000148794d31da0dd5d52b3897d5ff2249a19b74031000000000000000000000000e5520be4f7a0c7c2a891d2dff16986548259d79e00000000000000000000000003119c23b46c66217c99474ab5566dd98f46474b000000000000000000000000bb724c85172aef893333cf9db6e2dff636f7e58a00000000000000000000000082cb7eb17e8b976cd9a85a81cfad3d8c7817bdd9000000000000000000000000daa83fca1175d620b619b0fc3979ffafb65175e2000000000000000000000000b3322d52d9e83ec76b6b4cb156a6b88e7200bd150000000000000000000000002405784dd77cffd539d3ed06eaa8ef3f76da2920000000000000000000000000f30d0de7cb5077e4a7c57eab8de01c4da6870813000000000000000000000000941cf8654ece2b3ecf0d1584128afffe1b97af3c000000000000000000000000d56a431d25a270f4c467b042a2a37363b43a143300000000000000000000000029167fec77f43abd00fa687aa245283bd70ca51c0000000000000000000000007f3064881513bc0b6e25c032fa6e0a84fbed8b0700000000000000000000000013686eda9ebba8649bce54ed1a4469b00599c2780000000000000000000000002d727e5329d06696fe924d1859ebd42a3b299d100000000000000000000000009f480a8088f8ca7e66fdac632b5ed8760aad58ef000000000000000000000000ab6abe363d6a0237c1c8ced00dc9a51121578ffa000000000000000000000000ba9e13429645f0e8311301d820c4e146b7d2af7c000000000000000000000000bb65629e9e3c9ca7112a713794eedfd4deb474380000000000000000000000003d0fe63f5f401f47d1a6a545b200e26e8bab5f78000000000000000000000000cce1262abaf25ea4c27e91b6b957221d244d0aff00000000000000000000000043b896538c83799b3225b9ede0d43151ef2227b40000000000000000000000005a3a8fed0e18849ee0529b8e327cf0c45fb63ad8000000000000000000000000b5d851b6faefa09b465110ab179c655323dafc3e000000000000000000000000d1a21da67b5a28e68e77e0f3f3b061146a99aafa000000000000000000000000e39339c8f2b9ea7265a43684de665a38d04621da00000000000000000000000062155db2986616534642362224e4970b530ca87a0000000000000000000000006d585b17918fd589f4689a26e45795e4e19bb219000000000000000000000000d76288cc50c970efc752cd6287a058e06704b648000000000000000000000000c0c65b4271b7f49065c1f2ed4c60a2fee75e21fd000000000000000000000000a3c8117181a0345e2cb435cd3fa2281fdb10fd4b000000000000000000000000117a0be665ec9441053d468bb93fb4c26c24134100000000000000000000000094ced3ac35a2794060008ae56db0751e181732220000000000000000000000003bf408beb6b3863969bdfdcf8e4ccee3199f7cf80000000000000000000000002edebe55704bac6113a5e89325c544614debd293000000000000000000000000d5bd257f53ea67db54c026ce27f75cada884dc2a000000000000000000000000a8896491732d028954bcb20c59d2e75e64663a70000000000000000000000000d28d5a81942fe09ac69281ec8e0c84bafab12a7d000000000000000000000000433a25a4d2f7f007401a4ed896878c93598e2f9f00000000000000000000000074c61897fed4624e78fe5c04a7b3caf486d28e2a000000000000000000000000448ad483c48c4273008fb804628e88a2c587817200000000000000000000000030b583184bfd7d5f9c8dad377f12b495e30d162f000000000000000000000000842d9bbb97cedd8e87b200e9d88388a00a06787c0000000000000000000000002ee4c2990a060ad66a33741e8ba4cb08791cdecc00000000000000000000000072b736b36c21a48bf798fe1c7df43c90c7cd4b34000000000000000000000000961a94e727ab1352af5459a2ee5dabcee046b6e60000000000000000000000002be89ed9032bb3f0a6c6d0e10db5b359be7396600000000000000000000000006d216eeacb9c8fc9069f71866dfb4dd2b0f323a0000000000000000000000000c84b7a349c3be14238723aefc6bf9a1807469403000000000000000000000000a773ff98f23094f7ea17155dfaa63538dfcd6a520000000000000000000000003c717a01fb5f6566516e11b07f5a164f2256c25a0000000000000000000000000a503a28d98c36d46a87662b38bee3964cfe5e250000000000000000000000004c2a214d1de14183af0ce05b42431bec94ec14b500000000000000000000000061b933f208de2a6e8d2e5b65ae71a0ab5ca0bc240000000000000000000000002a22dc3fa6ac4089c233be05adfa326fe76c39dc00000000000000000000000012d0a1fe8a99b7ce1b7556336f5e1f136ebb7e4100000000000000000000000052d375e6d36a82be4edd635a768ac91a2dc25d8f000000000000000000000000f14844e404c993e7cb125375e2e579a0a61e7b6b000000000000000000000000ade3c10d6ba38d38af7dfdfe1ec217f55a08646f0000000000000000000000009fc065de970ccd4f47439237bf6a3351c6902b71000000000000000000000000d9468dddd55087f543683379fd6e456622a10cbf0000000000000000000000003b6fa9d63d0e77d99f2ae8e6277cdffa9be6f43c0000000000000000000000007fddf0a5f3156e686f911b6c5eb303f2c5acde1700000000000000000000000038ff842c5a977151d707bac1be099931e41c5f98000000000000000000000000c99018f351769eaf3af8ab5a3306c45fe57aad5000000000000000000000000049121adb843d3cc322955b213c885cdbde5c2aee000000000000000000000000d4e9b6ed9b1b93b50749ae412ae0e38c54cbfd240000000000000000000000004a020e6748f9c38e57aa50245938de218ba6c9fb00000000000000000000000090acbe6a46cf3fb66f448833fe60da399b86b4a300000000000000000000000060a50e8feb2871204732bdfc525592b31df2f696000000000000000000000000cb6dbcedde35d89cd83b77e6bece9a897d56316900000000000000000000000059b18a051b901383735162da635d7b85e9f0ee3e000000000000000000000000175d7ce21562969c7a45643d392fd0838c1650e40000000000000000000000003d8a301f6153a0e08666a869798cf40c94c3d44e0000000000000000000000005d036811184df86fdcfbd3207011092d52177b3c000000000000000000000000ce8ae9cb65f7dd5ef1119c0465ffcab4db45c7c30000000000000000000000002c74dc95ac397a96ac17ba63f41250f890024abe0000000000000000000000000570fee6b9b396b8fa5ab4a7f782b75fc5a497cf0000000000000000000000009caab7202a8ee8324ed0a26c6326b20f4a5cdee9000000000000000000000000e39d392ae4451df6c892a9aa313a678ccc0ad742000000000000000000000000982ed54b097f4f7759d039b43410848ba2f0041a0000000000000000000000004c5e712a9802fb96dd54d3929a87dab39660a0ec000000000000000000000000721f30bb8298ec977f8f42efc4205c0f2cd78fda00000000000000000000000014da69be028848e37eb222fa44993f652a162a180000000000000000000000003c81e848fbd5aad783b14ac491699dd467f774cb0000000000000000000000001879098daa3a57b263d210a4df1de21ae846db820000000000000000000000004eff4e7e2928be6f3f7d53893a34a069e1f3147f0000000000000000000000003db2f55052724219c4887cc4ce8871ffe5459d590000000000000000000000003c78d689d998cfdf9481b22774bc6513c358f0ab0000000000000000000000003a1f0a9a68debe30afb56ec445f17c11ce5369a70000000000000000000000003277bc61bb7ee546506a3cd85445ae85897866d7000000000000000000000000a8f2529d98435f7085cef8d44f022c635d60e954000000000000000000000000c9d9e048856bebb8e91e917f2fe9eddff8541e0e000000000000000000000000fc9eccdd666db24f16010cf888274247ecf6086a000000000000000000000000c8600bc9b60dfdd66a109d4bff36465f0948fba70000000000000000000000002b36a494d34a407b90083bfbdb44b275d4f54786000000000000000000000000318d9ccdcbe5556cf8e76cae9d2e484db15ed197000000000000000000000000016307ce7151fb254df7949925e949df55a288e800000000000000000000000009268af94f7f1be9cc2c2b142ed963ae65dca0d6000000000000000000000000bd8ac67abbd51ae1365dedd5d7128eba471cb60f0000000000000000000000006ea99754c67edaba189bb5eec91075770e61f0f20000000000000000000000009132aba7b9911848613b16a40b36e90a6237182400000000000000000000000024bec7083bb55613e1f9830d9c18e9141f86cdfe000000000000000000000000d8f9805ca237f5103210ed568555ebbbf9ba079e000000000000000000000000efc5fe3635ea9a9f94b9dded6e377b0fb28be0d4000000000000000000000000e49d1632c0e1a0ee2685456b65304d309383ea45000000000000000000000000cab35575af3e1b00a9d20f96950a32fd952735040000000000000000000000009a92c2fd786916a93d093842f77e578093f31d62000000000000000000000000505d4ce8a87ae5bf9cd31675fc5f9561ac9a9d9500000000000000000000000038abc71f9d0e9135a2697077f56fbc4c8fccdb920000000000000000000000004f6118afc70e3c82e49f7775bc4301b89d3749ca000000000000000000000000612fd2664348aced060c901345f82a45fc37ae7f000000000000000000000000231e6882aa652669ab4882914be7190c94f7171700000000000000000000000054c65ae1f609db9395658d817503d13e849af586000000000000000000000000c0b92aa16504f0efad3363dd8e6fc171bcabc0e8000000000000000000000000c58c7fe46927fc07e2bf994f4dc8d7cdb742b0c600000000000000000000000080ad66e14f31c6e469f37e515ffd23e90029e6d40000000000000000000000005c63952676b399e26f2721dbdab0d062b3c54cdb000000000000000000000000cd7c4dba794c7bedbac5b1519c22359e35cbe58500000000000000000000000060d1131788a31e2fbf200d7da65978f38c70c3b8000000000000000000000000bb35b06528f8e63f9cded3dcf650975efc6010a00000000000000000000000008f59351f172830f81fee023f853d01abad0b99040000000000000000000000002e728a66720faceafd6f4456ba7bcdc76c7d0165000000000000000000000000d3c390da72824c39db58b014870597f096a0d9a10000000000000000000000007328ead403e4ec1ab9e17a23ac6b65ed8fb47a000000000000000000000000009a55a86ad6dc9dba6aa53a8d7943e6ba390380c70000000000000000000000006d9a4a87d1daa0c9d02bcde01db66f6a8049dc590000000000000000000000002c39123755a6d1bbed786c4ba33b3c4ea9cb0d63000000000000000000000000ace297f7a0b3ef7d26103c34f59d4622a4f380be000000000000000000000000bae0855c61ba63cf302b27f70021f3f96e6778b60000000000000000000000003bf0876d1241299a8ee49dcef78c6b9da274cdbf000000000000000000000000893706f5d1a549d5d0e2b98adf53720312b853d70000000000000000000000007c11d533902a198332cf2bb49a532ccf7765e5010000000000000000000000002f86d0b2890c50d2433f26f3e57e76b203a8e30a00000000000000000000000088ffaad4b09d5bd603b3740b84bfab50019b88df000000000000000000000000f1234835f13b372e0f578c8aa60934d106ed4bf50000000000000000000000005ff41a6d5a4ce9fa89f8b7f28479ea9fc44430dd000000000000000000000000a1c72ad5c6ea8700c8a85b0e6587464e408ba5780000000000000000000000009f403f39d8c9a586a97bd0cf1354de0f5f4a9fba000000000000000000000000a9a48db0347874dac7aecfc65a2c9f342fe1b51100000000000000000000000055116e24235c0018c891dfedeeffa415b28ca01c0000000000000000000000006c96da14baea66df00d3191a3a0af1e465ce3ecf000000000000000000000000420de8ccb12ae0452bfd77c3f15e3f428777de8f000000000000000000000000b4b979a21ca29235a3fcd99adb56ff5b4da03709000000000000000000000000788937895ca255a9f68e3fd11bae842f5cfe2f230000000000000000000000006d407f16ff70007c77582429ab491d183993b4c90000000000000000000000002f8b2ba8a494c7f0bece1e07fc102d488492ff6e00000000000000000000000005cf2977fb565df482f23d7b9d4d68a016796244e674c966befcd9b403e95fe706187217e7ed1fd2759ae819e9c7b2930597f3c5c12ab7ca9b7b9c84f57a353c07ab161f9aeab42f63d65d5be358f9d1cfe4e3fb1ee46171dc5f0aa8dc6a96ad02ac7e169f6d41ffb219d242080f2d12445986e0e6629179aecaf552e126eff807decb4b8b860be4e7d52810a8302e39c98dd471cefa7fb6094df95bcd614e9b071f3ef4f5f4ac93cbe25f13c7d885169ab2030dece7c9ab7a70acf1cc726108000ba9e36980b5a28f2d790fcbcd60744d30679a305383cbb19928349681d23504ec726dcb992819305dbc10a5d7ddb893d9f0f339dcb415d136cb8f159c41de0505f392175daaaf1b375fba98ee01f0dbebb0c0a1a8c58fb76da249cea80d1f03be8ee07d02efef71864cfabe8df752ae175985d277bf508aeefeb4935e5d9c077f81ef04b8c9632e70ea5f7a40f221b089d24893b70471088c9e5f06a6608b02b14fedd1e458bf483ca3bcce6104f8cf0b988cede6bb384519573918d3c8c7073b1de259f9f2d8f4e18adcf2cce1cdf40ad1d837dd1e8a7bfc29bebd35cbb4071b180c10589e5a6fd7754715e9a78eb5bb1f79c1ab8d65198f04bae1cc535c0562a2a12634ab4515319fc304be8820b0449227ab532aa80d74a86e055f146005fb404374f82a676f59ec2f53666c0ab50b2465b3175fba117143b4ba3a8914021fab173ada43153ab2dfef08aa5788314f56ea720b68ac0b25cf433e5ef56c04a37576539e6a89cac9127c1f05b04b6f03ff1c2ce6b6071af9f662088b49ea012f884b2c941f1ef2c2a70e7847071c27c65d021d3a441b7936986dfc36779107bb8908bc875bd439d94be5473bcad5577b7355136e2d8db42faad09d3b6d43041739e5a3422f1d332b60dc504f3cb357e66c6d9c3eee5e0bb61080c5d158fd074da56b222edab3bf88e2f1c1ca2fc07f570393c9adb96bcce6fad2ee4802e90078c783b1e108246c4771fce699211ebe2646c52140a71583dd45132fefc6b804f52bbb0dd395869a5d98b9ba5eca1fb4c09100fc49a42f4999cdeec909a20506fde531b83000566187512260ee1b6e60521badf957aebd6b5c5cdbbdbac4260747dc7c15d880af949bc4c0981899137a4bfcc5c3cd7c4e6c618672155bc8c100fdcff9ec664fd9092ac70a2e34bb94bf82c8e427de9cf1721728a982eaec3700f235fd4316b01fb893c8ce3987517c855e8920c6f623a20b8d58c5b20c825701b982d3bd11aea5f12e93b8dc0b332ddc5c0b16b750c437fc700a4a41c38182041cdc7878ca0fe210d18b4eb93ce97d4605497c516f749a9e9829fc47b09e0707c8e95b87fc44687b176d60b966cc5578268a8fda7c94cb81034ec6971e846c07c2839e2dcb10825f8dbb1d1be95b46446f7c317be33e2f55dd91cfb24f9e5a05bbb29bbb2290f12eddfb119379f74da7ca69df7b1429b8681ad4270c7ed0da0319a388a82affb06c0d4a40037bcd5d17f72a41e8ff00c99c3fce90e7bee8f800e70bfb83360d478f9c33af1daa843ea4a0e770c97e1003021ceccf4747838b02c32636a1051206c09e7068e83fefcda1f92620a2a93e1890294c4d6719507b037c770d05036214d661114ac98842ccfce7e3f16cf7a964d18db755774063130295995104848c9ed6faf151e95f175e7e5cc4abd7e8a53b0e27c19504335ad805a7751d4fecc897a678d4bbb55f4a3ba597a479c6f1d9ebcbb78241f9fb6a9700a027a31452b7f5afd7fd3cbe032b5254762f60b9176db9f72737b233283ca9056fd51a9d9150cd3e7101f0abfacad4123549160cb54b3cfaa52574f8d8d11902d79fda530aa8e366eea7f78d43e70556dad579d26bab58f495708f02b747dd06c6dec8aa73a44759a5cb29a96bddc841dcb3aad44462b5a6fc3472540064220785f2ad310239f56bbd3b98ee00633e77daf8f42b9021dcd6721c21c22fd90707d522db19f0620d07dd6e0a6f8d97e39a16b20ff6c8856017c136d33017cc4b040bd61d559cfdf47800242f2b8abc29d64cb9023ab18c95a250244b1db3524600c529547669b46e863f83b67cc7c1a8436e71a67126e715da5e03bd87f88e6907063b62104a8f1336b26c79aa592bc4448857aad216dda88d59c4d3f81127a402385ca0f671d24969152dbeb03e9ebc715b2f97d9100f0abd357dca77b1746907c4b02cb2db232361bf3ad84d788ebf98cd1d740b2993591a3b48b55f7c1f8c042136f7d920cbc16f0a732cf56d51af46130bbe0f2abfd2fb2dfad04232c89a015bd6f1ec1c8d9013705de3be780e89a9da6791664d70bca4dff5fab91c98fd022ba579a03b994903cc910e0630fda89c9e54820ff9d5ca68983dc5dd9c051b0092bc7579d92b0281aa7b09fd8518f65ec94b54c4860616ad4d70f8b0d2450601c0f07fb02d0b47aa94360ba826bb2b93f16127a90f48bbe6066deae8d0e7eb04638a43a539d6f7318a8524fbc3c751b516b879a6e07283f4f74015ae095b25001ee0405df447b257deb849dc875e9ccb46812349d069329f3a38989577d3b101b7b470f186ade72284c5d3db18ec9d04119094f133e5a7667f01c98ed133680242164ac6cc0769fbe3a5712a9a51fb6633841ed78b0dbc17b2ba8b40502902052ac37246753ee38cc71a66c41c706b7155c47a40150fdf0d4d563d9dadae7f05969bbe5ceda206d95b6cff13272225712a345263b7c11e0809ab10f6a1aaa30226ff7bc6f548f72f12192806854306bc1d2d6722f308bc74548c5be44f671805aca2634faf6e5a44dc3ed8c97e4aa0d29f5cd08696d1211df71906c78e9271003a8c95d317f244342b004b7d31e430e6793d87d268b78a076940265eb7eb900522d1793ae9b5d5f2805f378f96a1c87e61da67d4ec205216ac85a9bcc6c38c0004bce46190b0da8f3465a2ff397ae2038c5e87a76ed7f8dd6ca22eed650e8e054b4773ec4e7772935875557bbef6083d9ef01b41e7ac11c08bff27ebbf16210195eac3404d4f85ca0f6b21c67467024d08ebc113e5e124d11bcf416287f358018157268c8d3b28976bab399103f9fe946b6fdf8aae5b7be451078cc58db15d00d3978de806f399bfe0ba8af28b4f2fd93e9865b705ca65c93b34ca7a96a13703c187f0bb6a5eae37abe2114ff81fa5d71204ab8453230786e1910d64c7f05a0742a5cc46d06122cfdef0171a212069393bda8fb88a3f02a0dffc63d8f11f44075f931b9abf8a4cece8b52ab78697fefc2f38015137cafa721e8b8c0215d9fb00d218ab324e9522489ac616bd90937d95ad1319a0f3a362f9b2a7f44efdfa66013071976e57cc5e4828704a58b938136990ec4dbf04920fdf150bed1ee4b33c00638274bb1b4560d43a1c41c33ada8ae3e73b4acac077bd54d5af22fef2c69303a1c41b6285e4973a661c8b30ae0d5eff602162c22fcf50304bb37a8746c9c000049a1aa6b190a28b0ee1e4ba0db5a179bc255ed093363449103ac8dc89026905e38e6a5a595b30937db7b0eb7b4539f53d408fd3e0fbdf6d399534e790672304e72cf831da2ba8f05b1cf6bcd0d772cb14b97087a2f89ce1fccad54a9b98a204ecf4d2dbe1a8e12d72a8d4262afb3ec066e529674b2bb4e0c330d0e4ab9995035d56476f55c47e79ad32d9584e7294071b0a87437dd3192d8a0438a255e8d6072a0e50510841c586c9787aeb85151de987a415e76777bb4b1fa87e7e95bafa056dbaf47108e441c41f1119dc088a732a2981feb0ee7a1e1d9f985ecdc95b0103ef090508708c6df2568200e8a1f6005a9037fb1f8421f7fd9602f39857d85c01bc5490e9da66fd63e77346187c5c1cdfdcc79a0a01f355889b9634e4bf5e6a033795499847f8d4cb89486a9d67d41bf7d17651b916ee1df3a0d8f18a6b111c05d36606304501bc2da25767284b619cb10213641adc3c5c7436c07e37d70a9006c3859bc1f3c7f5c949d2958f0ce2d4e09a5ed963bc7b8d9454e87a33ba54ff0076e08d434ccd30e5ba787fa053070e7f5046cc16c9b0c72d89cedf1353f55b06064b54af061e74284044e453fd0a402b79e30baa6d874435fe93817cd5c22201851d7b225a5de88c8d75014c070690d08e92759579f3a7306af33eacbf721000acee375b70c83582457aa3f2e8cb51b2a5c8a63d7ff01f4d09658e020ce8d602cea5dd731ea209df23757bc3f39d08d6076ea11b15b068b0af3b40d7d55e8402f84011949bef0fbb1782b713a54e7edc316b48e59576b8763dfe833379f25104b43f84673cb2c09d2e98a1ba8c3e89293b9e7188352283bb816586c4137041021a8fb94bc12448ae5e510695af12d3d3f3c292f8a8318a6c8a8cf8efb9194d03b77c4c8ed047bbe8f6052cf77274cc9b75246e751eb3c47f4285d3039b4ce805f8e3b57c976daeaff2507a0fe7a8b232749b5e3b1b176eeaae752c03c1315905e74ad84adf39411b7ccfe75b376b30dedbefe3676990edeb2697b6e06dcdbc022ee3ff7c6180f1bb98ec07ba29a504fefc5003d90a9ba53a597ba8dcfd1da007b27994dd894985dcdbfbfcf9933bc90123755657512b1a36622d06fdce8d3402d31ba102645a7b53cf95fec14c800c5b21fd763cb8ce9e2b7860862ba92b3900aba02c5ed55dc5d29b217e797bf601f0e04f59ce66b34915255829976a4a6b057c2a0e36c2a75cdf4c25becaedd8fca127629cdce88b55a0d66d8e865e41400f3ec345653daf1212544bb4c0d7a23f49a46e7600000000000000000000000018b1c3e3d7c85d74e01f866f30dd32b2a57db2cf0000000000000000000000009b91166b028b4873c54f2d4dcdc3e63f07ba6377000000000000000000000000dd600f9c13e98bef83fe4255407c74ed01448b3c000000000000000000000000f39095630fca3b4859dd92a1bd4995867590159f000000000000000000000000b1e7a73d1adf88df390a69e308405a2577fec6f20000000000000000000000002bc129ca178217ec5bf19fea8d7797188a917f22000000000000000000000000fc283a3d702c4e3813d33cbe8121908e968ad7b60000000000000000000000007ed01f520b66894a93b52837deba99057667379400000000000000000000000076491be113edc810e8cce7f4d63e14f9c4a1e8950000000000000000000000001ec4cda48b6cb461faee32ed49743360ec2b5977000000000000000000000000615ebf11265b52f584167dcf670a61a79bb0344400000000000000000000000018c89d000d5bf5a6faf45823378c7fa2d1e7447a0000000000000000000000000fc49091773266e9033b360405209668c3be6adf000000000000000000000000089d6c88aabbc0faeebb4c1f6a326e6584932304000000000000000000000000f9afa45e21806f5c19f443d91217aef4ac67ec270000000000000000000000009d0c0e8582688ae31d91ef06b74fd9a3a2c83990000000000000000000000000786564ca9cf0dbb3798f9c3042892ea67bb94cff000000000000000000000000b63e9472247a4e836b80b6982e69ca8b81f8a3fb00000000000000000000000033232cf044a9ad0892589fbfd445abdae5b0e6cb000000000000000000000000a359f39ca46f23bfb4cec1af3d5bb87dc2648c39000000000000000000000000ea6f10ec99058dfa7f47f98edda81e3ba683e5b2000000000000000000000000ba543bc0168ca06ea355b6d534c5e5bed888fb09000000000000000000000000c77ed813fc8f8b6c3530bc72cc7f997ffa6e5dca00000000000000000000000035b96ae855f17d7f164fe890a6b68e0c4574c5e2000000000000000000000000140178042b676aceb32582480faa30e7384002e6000000000000000000000000de5ae1837c8459170ca0a4da7b8da1ed24c5b8b900000000000000000000000076ef67eccf5eefdfebc0d2370f9d80eae083ec4200000000000000000000000065a3f51a320c44785b7830e6b955c8c836be68d2000000000000000000000000181131313ae8aa972e2a7fd43f4cbeb33d71da450000000000000000000000005c94c2065033c049042327cc6202be88dd98cbe30000000000000000000000007f3d0e1a040127f1eab252a932ac3a0f299e9d30000000000000000000000000d84b2311f4836a9c3ed878354a4bcad3e81d3353000000000000000000000000cc23ffd7f16ca1c2b8bf4eeb2845f57c82bed1bd0000000000000000000000003a86d71788ff5467c44e167c505d6ca939d855540000000000000000000000008368a2a56817322d5387ddaec212d089fb945f440000000000000000000000000120167e723e213b756dd49a1b6a2b9110b1c9be000000000000000000000000b1b5fbe77cbf3f0dbb988cfaf68582a0af482a5d000000000000000000000000a26408d3139f4578d8263a0468743b090f44a92e000000000000000000000000aa355023c7ca903a09b5addbcb94a11376847c46000000000000000000000000ff0dc053f4a67f8faccdfecf2846dd85491114430000000000000000000000001c8b685416133efb6471ff6a87c96d67afe6d63e000000000000000000000000348ab066c23fa9ac371983b9f52cffcc063bf5410000000000000000000000003b9289aa9c92bc3ca9bf622a4f145f82e7a0c66b0000000000000000000000009c3dc7a9204b360fb12f5dbb82843fcb3a37e202000000000000000000000000cb729e0e83c1b327a576ca2ac51d7154c5ec9b75000000000000000000000000bcc833fb6b54e63138cb73ac1b35a43c61bc210a0000000000000000000000009835c8aed688c7c545629ba72f8b552907ffd63f000000000000000000000000e42d1a37ae1b821b35a29e716363876bef2bd6360000000000000000000000005298d564aaa908d4664c1c3962a6a63aed076e2a000000000000000000000000fd038dd2978ca375457f4bad202827dea6cffd1b00000000000000000000000052c8fb0ffce94886e1f1cab74f1b49d4ff2f5c83000000000000000000000000359c4de4d9eee2f931d0f92419b3c1d07d8d42140000000000000000000000009fe51eda676184563868e09b4146a19da628773600000000000000000000000045a8167c13d05aaeea17c56b3832c88334a3fcdd0000000000000000000000009e4c881c5bd99ac0670b6b7813f0be3ac57a2a69000000000000000000000000799314abb0b06f951bef0d4ec9abe322fecdb3240000000000000000000000005a18ec4249f4b50dfee9605210d7837b088a4be1000000000000000000000000e8f2cd75b059ab32a0931aa8fa918df2b1fb7e02000000000000000000000000160c4758e421de8a66bda42697dd42e1ef086e9500000000000000000000000004feec51df951b3b754490c93631f92e43fad6660000000000000000000000009687823a40c4c797710013257fc6f9de95248b07000000000000000000000000fc6ee7ad302026d0f5082d4ff99f2f4d70c03373000000000000000000000000c9ad970327ee7c81498f5e58964d7d52db7166ec000000000000000000000000ab46ddf30683538363b84e6ac4950b681d7d873f000000000000000000000000670f6bba4b2f8361aa93023b0a111dbc51b7666e000000000000000000000000d61f5074809c41621d046e965ebbb3fdef271c9300000000000000000000000086b3015fd58f1b3c1077d4ddfded627ac4bb924a000000000000000000000000b9004c10795e8fa7d8572ae5837f37ab5e83e038000000000000000000000000eeab0d56e0c9c6eafde72f9082b51449f07d84060000000000000000000000004c497f7aebc0ea85a1a21ce5fb7abc490ffb56440000000000000000000000000b664be342a556fc055a402dc0b59107d0b6af15000000000000000000000000c5ec321f7a7a0b21aaf1dcad9a6277d0714d06d000000000000000000000000024a5ebfbce31432f570792c9e790be7c69c80da000000000000000000000000067da05a443db45a2863de39701987b847a16970d00000000000000000000000059a223e7e140dcbf881409913135b57919a57a1700000000000000000000000053ec892c1256e6827687af13cb8786cd6ab679b4000000000000000000000000b638ea4724158e4a1406a48a1b8821c0c7f73af400000000000000000000000034c5cfcc610b558d22adaa4b643ea0ca38a290a8000000000000000000000000936fa967541d9c599fc2289e1bfb3857ca5296e1000000000000000000000000a8333db825e515813f6e9c232f951517082ff006000000000000000000000000a2bc0a8edd10de053daab557e7d6db525d1327b400000000000000000000000096a42d89f84a974123dfd5ef4fe898926c3585a20000000000000000000000007f3647a28925da77c177a5b58bb921260e6f19fa000000000000000000000000e15a02d225deb910afe5471b2459fb9cccf32da7000000000000000000000000ce5f7e90a61ec58e03f7a74b6201155ab3a55f5d0000000000000000000000001e33321f57a3b21417a2a569468328cfcbee58dc0000000000000000000000002b40c3c22087292c2dbcd4e5d0c47856b7088ad6000000000000000000000000593b0772b2c356bae079b78ed3fcc8371e664eb20000000000000000000000007ef727d904e25d1558300d4d94feabd198cd3821000000000000000000000000ef8cae5c0012d0499810cbe3cca1063d290c16cf000000000000000000000000111499d0a173c9aba91c05f7a4b59a1c922d3059000000000000000000000000cbeebad3a42668278148b00a8a96cd9aee8be21400000000000000000000000059550ed9962e0d61a352aad0fefb396784083651000000000000000000000000656eab2d4318104974b911e00f719fafff660f18000000000000000000000000e986741fed5cd95daa2b8d0bea2841211bcfd2260000000000000000000000004fe7ca5106d49fbdbf0daaf1383c8390792e592c000000000000000000000000c6269a865de70f62974dbac2919039df05d900070000000000000000000000008ac554557641b2846546fdadd11bf18dd8fac19e000000000000000000000000c929984f970db1135c72e399a96542025f3dc67800000000000000000000000063d16c97cbf0364939fe0f7313a3e001b73648420000000000000000000000004eec06c1047a17c4aa6182ba85f74380cd66c73c000000000000000000000000a20528e69298ae009480b49bbef481468906502c000000000000000000000000b745d8ba0b989148f1ff6f85f76822a41b34096a000000000000000000000000166a4d337495d937f8871be14acaf8be57fd2779000000000000000000000000eaedbf36e6954243361d072189d6a4343e1277330000000000000000000000004e87c98dbeec5879c77ccffccecb78aa7b6a48d200000000000000000000000097a372b3358d2677877d29005a87fea1c280c7760000000000000000000000004fa077123b492df33801d22645f5010326cb2b65000000000000000000000000dee78a4cf5922b697bb9951c1fb93ed772058d3c0000000000000000000000001bb21e47be63a11b0ec5dfa3c1ce20e1531f32ab0000000000000000000000000d7a3a1c72ed708674393009a86604999c3bc45100000000000000000000000012596f3b4d08aa9217e1be17eb9512ee7802e3a20000000000000000000000001cf120a052a8b46aa0ceefe6fb393416753246fc00000000000000000000000011bae8377a9c067e641641f4750e840d1a040980000000000000000000000000b790b5d22371c5f2874ca4bc439ce8b242f376f5000000000000000000000000563ce5072927ac8e078c910b27650902b3afe0280000000000000000000000003f0d8471c2aa89d6e85b135efab364261b8fa20c0000000000000000000000002b65cfb313879e6aa12c9f938282209b564415e1000000000000000000000000e41b444b4ec851fbc197922a881b6a8f39d38bff00000000000000000000000091510293828bc626f87b0c0c6c501cd017dda38e000000000000000000000000e879c61d7f4260f8994535421d2631d8b5c91e230000000000000000000000004ecf8214fe7ba171d9c12e505b826c6cbbca591300000000000000000000000061ce46ce65b2cbaaa9390861777194fac61ad230000000000000000000000000eb34627dfcc9f326561f4030c2aaa411bc0b635600000000000000000000000058242dd3c7fe8763a9b3c88d87cb80781c6bf6c100000000000000000000000093d7fa29cd9a83f01166413e4709d50059a6d624000000000000000000000000a2eb61d90f10fd4ba02e46f59ffed98fcacecadd00000000000000000000000070f8c01e1a0b5b5470e863ab5715532dd5bb70f6000000000000000000000000271c75113c386b1fee5e077420ee1cba11324a8e000000000000000000000000202c3a155a7e8d379cdc0e35f8dd82283d25ac16000000000000000000000000dd5ef7fca4008f2ec7d4e6237b6ae7dfb9295b2d000000000000000000000000c45ee92ee696ccf0b46d82263e5170422015954000000000000000000000000047cb49c25697f2a8615150c094e27941714eaaad000000000000000000000000a5394f7d8e968b32c9eb20c25ff31ca917756fd200000000000000000000000090a73e3684cee2109d77a8f2ebe7cca1b09e67200000000000000000000000004ed4be550283e8c81166ec542a21861b498e33a60000000000000000000000008c4bf54b0af47312a9d84fa82788fabd7ba359f8000000000000000000000000c914073f6bbddbe8cd061b416d5f3b163bde5db900000000000000000000000037ef6bc069ed6af0ec8007f7b2057c4199309ea0000000000000000000000000046df2f470302aac8f6a5076329abee24621cdd893b3aef7fc3b1071c8edb81005273164319f2469604e01165ea08b46d440cee20761a1884e60877dd5410f7f04f722d34145dd0041eae65752e842d017afb8133d63040ff475a06bf74be1c3067ae2368861e69ac7410c3de5e535d72fcab192aa2cf6fc11a0c006eb8661e3048c74b559090ee5bf6afece17a1b0d52b9d2834995581600bb24e4b0afdd2f307a2f1d440b47a2c7deb1b7b2491e51a8b4796ede6714cf51faa2e898ac277a0061152427b7a89a5e9e677f2ce816b54424591f5206d201bb86eabff125f016400d184a60c1987df7fb81df2a556c5cbe8b36afed910ac03eda63b3829027f39054863a82184ae8693843814e30095669caae8648958ccd0fe0e6286aa9c1fc407fda09526e2424b9111e9338f84bea82d66d5a0d1ac76ad65da827e867200ab05684632e7c03440d04d5e9dafeabd2e77f6f6ba6756e77493339c82b21267ae06fefac225c8364a35b18871b56db62c51f04c149c9d1e13aee46d28816e84100796899506a217b06925d76a1ab111d87e272c7e4791fc8517b60d981a5e9c890737bfb198e0f08ad7d1ccffef6f842aa3a9df78bac31a2625768fef854b90c201a12b85c5b579ccc38abdb4afe8cb4fdc90f673a2abb7ff89291855213775a500929544fc0bfc00f7bf6982a79c30214866066f46d5bf9e51e0f092239d7a0d01b161371e6870f2d2c8db997ac3a4bcd4cf8069432a6e98c99bc6cf99d299aa02a841840c3e7fc43e4a18dc7509583e5048d412237f83d5159bcb7c0f8b3de2031b3689ef35f228f7087bf7368fddfd3f446426e13711a51b15ea1553ae81ac042b448afefd551f915759621ca13b0461bd628f28fb415c0f0344344b36d6c304b7d7ad115a192e2fdcc71647e51f23a60baee638f28f2a12d29841ef9a9b06071d04b3fab192b86cfcca2ef4e47f1fec57b5e2d1fed5a0cd77ba9f4e6be13304e48e3e1c4dda77ff42ff0b578571366077d115d6d488846623d387133be65300c76401696a205cd72e9acea8c9a417c8c60779a425ef4fa63f68ab9e323eeb0527ab7097a19b70997fa5aeb2dd2623865aa067c070e675493b29d54dbb5fa10388b82420ec02886625eca2b1c13cd069f931b78ec0027f583db10e51a7356c022683ccb1ebbfe4375c5c6b422966acc5d06a76e6284ed739440c490acfa49a0226317830b447197305a4b79d31431de9fd49400e5a183be0e1f3dc527682e304debf8a00a703c6b50144799ae52dfa6aee324ae567114c5a429804a038c0cd018ec56363e52f8f8ee5721608f272dc1b94ab6de5fc7d64e973eee80f3efff0022e3dea985b04a135b065dd8f7286d66526495d4678cdd1b5002225adf0821703683fd1a0461c0db4f4f577024fd5c567a87068385a33baab282b9d3bc648a40775139aac18b574943aadcc259db90d79121419fd2bf9f54b8e9350fe67421e00a2bcdb31ad21ddc22464a38ead7697bef6797a2a7dc7e8f63e42eeb4dbe88e04d502574442b760f23388f0341b13791adc5a415fa40874645724ac89cb158203cd310e526bd07846aff18ad9dca6078ab7a71e80745f93f9459e19e6c6fb7e02e907f53511b75b7a8034d559eb70f4ea5f5cbfdd15b1d56fc99a208644b02a03f81f07ad0e770c0ee235c44a5a3e9e9ad5efcccbe5c2282d5ffb8c59c9bedd039f4ce715dcb2c1283b7eb4e4ef167424168c72f4d4de09e20b660d9be3b68305b44c567cba6b595477bf678fd816f8c4a1b8e5fda3098a1a6118dc8e3e06dd07e6ac4459d654c0366d64b6c9afe1b78da530232ee49dde3a6d8e392b39e24e05d2eabcaff3aef6c495e22e143d42d64573e50268d0e67b71c4a278d8301d2001c3973b0c7c405ef4d8253cd40ec02114d6ffae8059331462031df563f26f6a02c9056837af50e083da011691e45a3ed7219d6ee7b76f06f976cf5781a3e86206a2829cd838f04929211a1e91dc26469f720fd583a16ff75ca2f0dfaa6154d10713ef2fbfbab584a4186f66aaf21ccb6a5f6a832daa6d816190ef646235a3860053c5b42d7c81ef28bbe987a16f286b05125f9f292cf70fa196d81f29ed719004b6f55f9c6cb229a7d816568ab795b66d9cd0348da16d0f5a378ef1efcfb4e302ec59b1ba5756b707a5bac9bba4a50489acc4491f684ae35479f96d1f9ef853046b423de04b4f60c0276ad2ac870697d23692282309a94b1d16d30f2092aa4f06e7b3e185a443aef415942a6751f399e3af637beb938ac248bf2b8dc88ad92404b4ddf569b4eb182e325734e10a4500f30e331f5d199d04af0071db06a0a2580170d34b8e6050a2c5338e7a5eb17e5cba5e80970b89f337ef6cf1f932aa3b7903dbdcb35108241e0f16247d5eb29279eb0279ce919b63f70ec8a66b6b6d813e061c229d5eefb94d6f6d89e071e90e9fb9ecc1e1e034f50d6b1ed35f816a1b6e018079e795ed08534637f1bca51517c06d3e5249fede39409f480a89e3055a0a008c95b3c6c13995d7c654921805e06254da9561dbe20174f5d4b7470199d12705f8e179a7e32aed4983bdb9364da8c1c91094345b85f2eb632faf0bd065fc8d04c96d46b2a894fffbfca7bb08136e7f6bd43cdd007d6ac1b5953b2a1639b2e20245cd096d6ebe0b11823a3b2e8a2537757eadc15959db2fe4ff1249ed37c793079227b13e33dd3812a4362256712958662f693c026fec14c6b964658c48c837039df116d300adb6d3fa79138f4795d0c89382d301b6978314989b2fa0cbd15a047d5becf4071f98c1555099505eab491a2ff02d51f90d1f16f7f3e69f83238906e6c36f3989d13ceeb7af97f4230e314a9acc3dc18776158bf5785763f1484302baaf38dc6fd178a0551d67264c41705599b016110f1134f00254952249857707d728a571443fa761de4ecc26e04a965a0ab4a502ec246fff110456b842cdc901b63e2619ca8b7a3b434787b914cabe20501b9ab74bf359a9bdf51df119c7b7074e4c92426875f3754ce85277ea3988985eb9a663f87f51008fb1256a64230a02a66e4853ae8cefcf07b25e494ed62e2e63e1ba2aa17472a6fb4feb114a3a460143398918e8862b718dd51615722f9cfcd6bda22f6ea7168fc4f646b52ccb1702071736a8cf51c4c5a0b85f85df2d404a57c288529a45071405cc551405ec1d028e1f569f49ec340751a58d4e1f069ee0cfd61e2ff6ec7dcd89c836ca29df1e0271c73ff83c76f5f2a743f0580f79a7f8a7c854b1ad3e75f7894c5359b120db0188528400ebab96a5d41bdade0a91ff347767ce8dd4e00452d49f684245a73a037949d4dac61f1f81efa35e8b5a05c1b810222c600079980d168832ac5c53d8004296988694494e4228166f3156b722e5a66258ecc29e5e18fa2e94436daed00094b2e5c00792d11d957c675f759ea358341f636973f9866e2ca5a1a48e603b02ce3791305a102db0812e0346b11a02cf77357a3fcbcfcc4b227246306727f903cb31905cb5955fe1e70dd8fee4e40279b6a2c9f0ebf58ceb609f6ba889fb8c068c645c7d14194e21ebacc3eeee14bc17187932a77873551c2dd4ed755f3d8d04c2de6502d8fd98d71282aaf142e93ecf10f7ea71f955595d00aa3cb2d2aa99069c90dcde5db9e91840e0ca8785ffd95dd1fd6476de7b52ffb13ca03ce90efb008bd70675c1e2bd4cf4f654dd359f9e2c37fd5c3b9ce9ff267a7d1c4cc72c0406bef734d5461625cb8bbd9d857e48a98a94a3cdb52d2624333d694a2578048a013fa9c5cbdeda444739c1d607e907ea624c389055bc9202a9fc1b207cd110f90770fc92b512ec904ad243ceff89151b78fa9bafd8fe9a6f0e73c47714eca287003035fec3adcb001d7ddc64a1e0acbee785a45e9b0ff9981d0f643937ab952c078a5c81c1d996488133b48580b78215d43a1967b9d78998aa879cf441c926da009ed43e0859e2937a33e6d8090a912ce393376a553ebff4134b5a123e4b813c01f3669ad75c097f11e3a7cdeee5829632565685d977dcf3268539e8fe0f16c0023dcd0e10efa4e3be17a9f14158641bef28db8ebae569b5b80303fa8fa1959701e55f5a87379b65fefe4822e512f824d7dc6d91eefa2ba0abfc4fe59fd9f4cd04b18fa7dd4cfe6df77f4e6afc2cfdaf24c72b26f5430659acf5f077b30b680507af4b536984106dcdcc0e21cc2ac64262ca399fe222b0e70fbaf1ac6300c330055fe64c0205eaba6714b9bea6cec4ce2e52e63088a76a9edccb31c18eb0438c042d3464fab0d6c303ff099698d6bb97d589d38b06d3ab688e1e7130cf9f9bd103c4199d244ec028766772d65c25b5affd7a6beb104b1560b36e5d6623e30f6c069bae64247d222650680451e4acbdaa899b98a45f8290434f2fad96aefc0b9f07a50bf09ddd169053c367a297562a612c82560170cf36a921770e5ce73432d5029e3ce925b9c625fe3b48ce3f34cfcaf4def5347481417cb0db395bf62daa2003faf8756a21c9fb863399d3aea49975b19fc9e6024c333be206b6bf838e4cc30614f83b4f10833903e2f4310698f9d2e28a141594ef3f01dd8599ff8d498fa70699ca737b3872345709b6d388e2ff41438e83b152465385645aa14e26a9636d07d0dd1eb859bff236024ebba01967e5e25dc621451a8e199d67508be0551f5404b7e47d2a2175e754c26dc88a98d1482a6d5baa8b85b26ab5e46a26a8197efb8e5cae0f18009d5ea8102738fe6f477af4b96fcf00000000000000000000000020bc59e5f3f9caadf5f05d8a035abf36da713525000000000000000000000000745a11640e24e9a1cbdfd44875c68b3871feacd90000000000000000000000005e0ed0fd0cebc324d5f47f13ab1dc911aa01278a00000000000000000000000001130902ba5ce382e120d176914056fd660d5c67000000000000000000000000da631eb0bdb9211661c13147a8cb474efdf237640000000000000000000000007caddc8d6c82ef0657b1b5aa5c6caf0848aa04200000000000000000000000009554686bd21b7c50dbc388705afe2e4e62468d98000000000000000000000000a5e9ea90f78ffa2196bc2417fd82629cb912c68100000000000000000000000077a818ad004d5a9b1924ec834306b86074df979e0000000000000000000000002a9e44e7e93d746e30c25e4c23d568e38cbd872e000000000000000000000000f1263627574a903d8a3ad6f70a782e4ad5c5cf2c00000000000000000000000054eacf4ee700548103f032b8a7348ab651f70e13000000000000000000000000e3d274c3f4a0eb458a55dfac18f116f3b39d2a390000000000000000000000000af3a89bd73224b4593854047e5cec2738e9c315000000000000000000000000b342e6df2058ea8e3a31860fc7cb78924f6d4cf300000000000000000000000011e9d45510a3dbbadc87949aa8d4bc6be2497316000000000000000000000000c2fe1cada44388647ba629fc9e97fbd92b92819a0000000000000000000000000731a6550cb6194c370686d4757c8123dbe00b3f0000000000000000000000003fb16977172110b4736e114f10ab6504df047c61000000000000000000000000d9ebb6142808ce7b1b24a50fe31eb82601f49ca60000000000000000000000003d35ada3dc2162991b3ab96c1386643d3c16f847000000000000000000000000d535e48eb54ef5d731b5b181228c671e096868490000000000000000000000000511a3248d6c59294ff1c900e5a77eefecba48df000000000000000000000000f328330254177242a6a09a5cb64bae4577cd471b00000000000000000000000087999f13d1b0655c50cd9c8512a21777653e8cf8000000000000000000000000823c565e88e78507da8558909f9f13e912794ced000000000000000000000000b6d7fb244a0dd232196fe8e7a6b37198bb6ca4da0000000000000000000000003db14e8dc714f46343921274f481110a4e380e05000000000000000000000000906682d8aa4e7c669131faafe36b24ef7ad20424000000000000000000000000cde55bc04d7bbda4bf8c989ecabda7bb7611b557000000000000000000000000a8dabbda2d385b7be20a4e5d88115c0291b1192f000000000000000000000000cd729f057337d5b4f1e094ac8da001d3c6fcb6610000000000000000000000001fbd445da6f139b0209d0c08c63d890880e29da5000000000000000000000000f3a6938f7b1022ced063763d2fd2a46cdc68b7fd00000000000000000000000051a94aba83de867cdfb65663a31a7703423dfa63000000000000000000000000bd73f9a3a1281b5f185335ed680bcd7186b82c7300000000000000000000000092a2faed9ae31f2fc22e6ef653dd1bbf7ac40ba0000000000000000000000000b974f0687dc0e7e22efbf28ae572618ac42a61710000000000000000000000004beeb67d729bea3e860c66a3a1a00af8d478e500000000000000000000000000d1bd0fbe4ee7470411f909fd8c716e4a03b266b2000000000000000000000000f5e6c71c1866d0a5d7d3c30312ebf17ce7e3c9140000000000000000000000001619cf25d03b678141a4599f243cd4580cb5cf30000000000000000000000000803c21974bda54547bd62768f76707c580e09874000000000000000000000000f4d4ec06f5225613e674f615fe4ba412d97ab19500000000000000000000000078c426a2730fd3c55394312f60f36aa2ba0198e10000000000000000000000002be5463b919af7bea4b7a74de9c9b24d8a7809ed0000000000000000000000004375855091c87dc13fe59c4079205b0da8fd0f66000000000000000000000000acdbd55dd04cd5a6b46437be0ecd75a03255a9100000000000000000000000008c196c1cf8a18275e1b893540903df043d19a51f0000000000000000000000006dfccd333fa8c1bff53beff776a51a2f3a6af23a00000000000000000000000079c009a8954b6f71a2cf6c3c75a6553024a9216f000000000000000000000000731db3f0ea17e4682fbfbaeff9655b814208f983000000000000000000000000116e53b5ca439837874022554e296b2836486d82000000000000000000000000cfc69261a03f934acc2e650e0bdb69d90ae74aa200000000000000000000000079135486147fa8a4b9b5e06d3965a63a6b6b4a5d000000000000000000000000dcc4aff3147176f0d39c4f2083ce8c526792cf07000000000000000000000000e98621ce90ba18cb754f0d64522ef45aee10317a000000000000000000000000520b8e150dc3825214324997eab14c1819875b420000000000000000000000001d2b26322c1e37b5de33bed3974ab3080f9a72f1000000000000000000000000d3d8396c692af83c986d64d1ef65fc0aa20598e8000000000000000000000000f8c55aa929d8b93539675a7a627a6c3e17a74a60000000000000000000000000620045471713a8b95afc4c9fc1e0d447e499be1a000000000000000000000000c2b7ef75b5639c3d1fee72a36daf5b8c24fcb6b5000000000000000000000000aab7af3882c96d4aa802e60083c0b671e80adc3200000000000000000000000002518026ddf624ca1a134ffc3c17eb5a8676bf7b0000000000000000000000004313950c7a45b557267f2a710648423e481662140000000000000000000000006380c3d21ed612f6f92f2669c77060612e357ee20000000000000000000000008ab87f12a697dd066f452e1f5d79d0d8e3148e4c000000000000000000000000e188f0e4527bfc35c3738f170669f208c70d801000000000000000000000000010f33a573e444468e723b146656a27e290f6dc070000000000000000000000006969104b37d942b630745d532430a83ff02449c50000000000000000000000009d1036262823f56eeecbcaa0760713c0453c7dd8000000000000000000000000d0494db284c0198da862f59772776bdab9bf3c750000000000000000000000007cba203611f9160611b5d7aadcebeb18c7d96866000000000000000000000000282d72ed7cec0153e801caddd2e452bd4d2c11b9000000000000000000000000a758538c3ebcba2c951ed2e269d1ee70ddb2f883000000000000000000000000c13524936c92388fd72bd26e3a4a138ecc40ad4700000000000000000000000084a69688b2b0ac7c99b23e87e811dd12bc3ae7c9000000000000000000000000627dfbdee2402d2417bb2a839ab0d7cb1a410f9b000000000000000000000000b2d79e2e3b742c4aac4f5a5c6b2d3d8cbd63cce10000000000000000000000002f163db740ea1c364962c5fff6b228e8bdd77077000000000000000000000000b3169bcfefd94fc3dfab6bd2fde068e81b074844000000000000000000000000ecc146c118d8c0a53a5898c32931a86ff14db4340000000000000000000000001940404ebc91b6fcc3699668ddc9eb8c2020f48f0000000000000000000000003635a61e630c3ac2befbfcb7fb4811c185cb9b180000000000000000000000007cbef9c2f39ae5ba7905444465f0f07af778feba00000000000000000000000076b1194e45e27811e0a03c2e1d9c5d487100f993000000000000000000000000f0e4765d90046054828481a32193b41b8b0e94a50000000000000000000000006da61bec4e28f0f289ac087e352d60acf1eb644b00000000000000000000000010a892fd05c1c7e59dee75f0606e1077979cee4200000000000000000000000065ba284e4882eb323cbd887d8e910e592bf0e8d1000000000000000000000000128544b01c22e44cf9d4f5810fc499219a18deb10000000000000000000000001ceddf7e4ff3bff22037475f5b7d0b9d1b101f51000000000000000000000000037ef08bff97447f57833ce7e5814dabbe015d3b000000000000000000000000", + "proof_parameters": { + "channel_hash": "blake256", + "commitment_hash": "blake256_masked160", + "field": "PrimeField0", + "n_verifier_friendly_commitment_layers": 0, + "stark": { + "fri": { + "fri_step_list": [ + 0, + 3, + 3, + 3, + 3 + ], + "last_layer_degree_bound": 128, + "n_queries": 15, + "proof_of_work_bits": 20 + }, + "log_n_cosets": 4 + }, + "statement": { + "page_hash": "pedersen" + }, + "use_extension_field": false, + "verifier_friendly_commitment_hash": "blake256_masked160" + }, + "prover_config": { + "cached_lde_config": { + "store_full_lde": false, + "use_fft_for_eval": false + }, + "constraint_polynomial_task_size": 256, + "n_out_of_memory_merkle_layers": 1, + "table_prover_n_tasks_per_segment": 32 + }, + "public_input": { + "layout": "recursive", + "layout_params": null, + "memory_segments": { + "bitwise": { + "begin_addr": 4669, + "stop_ptr": 4679 + }, + "execution": { + "begin_addr": 128, + "stop_ptr": 184 + }, + "keccak": { + "begin_addr": 14909, + "stop_ptr": 14925 + }, + "output": { + "begin_addr": 184, + "stop_ptr": 189 + }, + "pedersen": { + "begin_addr": 189, + "stop_ptr": 192 + }, + "program": { + "begin_addr": 1, + "stop_ptr": 5 + }, + "range_check": { + "begin_addr": 573, + "stop_ptr": 574 + } + }, + "n_steps": 32768, + "public_memory": [ + { + "address": 1, + "page": 0, + "value": "0x40780017fff7fff" + }, + { + "address": 2, + "page": 0, + "value": "0x5" + }, + { + "address": 3, + "page": 0, + "value": "0x1104800180018000" + }, + { + "address": 4, + "page": 0, + "value": "0x10" + }, + { + "address": 5, + "page": 0, + "value": "0x10780017fff7fff" + }, + { + "address": 6, + "page": 0, + "value": "0x0" + }, + { + "address": 7, + "page": 0, + "value": "0x400380007ffb7ffc" + }, + { + "address": 8, + "page": 0, + "value": "0x400380017ffb7ffd" + }, + { + "address": 9, + "page": 0, + "value": "0x482680017ffb8000" + }, + { + "address": 10, + "page": 0, + "value": "0x5" + }, + { + "address": 11, + "page": 0, + "value": "0x480280027ffb8000" + }, + { + "address": 12, + "page": 0, + "value": "0x208b7fff7fff7ffe" + }, + { + "address": 13, + "page": 0, + "value": "0x400380007ffb7ffc" + }, + { + "address": 14, + "page": 0, + "value": "0x400380017ffb7ffd" + }, + { + "address": 15, + "page": 0, + "value": "0x482680017ffb8000" + }, + { + "address": 16, + "page": 0, + "value": "0x5" + }, + { + "address": 17, + "page": 0, + "value": "0x480280037ffb8000" + }, + { + "address": 18, + "page": 0, + "value": "0x208b7fff7fff7ffe" + }, + { + "address": 19, + "page": 0, + "value": "0x40780017fff7fff" + }, + { + "address": 20, + "page": 0, + "value": "0x1" + }, + { + "address": 21, + "page": 0, + "value": "0x4003800080007ff9" + }, + { + "address": 22, + "page": 0, + "value": "0x400680017fff8000" + }, + { + "address": 23, + "page": 0, + "value": "0x7b" + }, + { + "address": 24, + "page": 0, + "value": "0x480280007ffa8000" + }, + { + "address": 25, + "page": 0, + "value": "0x400680017fff8000" + }, + { + "address": 26, + "page": 0, + "value": "0x1c8" + }, + { + "address": 27, + "page": 0, + "value": "0x480280017ffa8000" + }, + { + "address": 28, + "page": 0, + "value": "0x480280027ffa8000" + }, + { + "address": 29, + "page": 0, + "value": "0x400280007ff97fff" + }, + { + "address": 30, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 31, + "page": 0, + "value": "0x4d2" + }, + { + "address": 32, + "page": 0, + "value": "0x400280017ff97fff" + }, + { + "address": 33, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 34, + "page": 0, + "value": "0x10e1" + }, + { + "address": 35, + "page": 0, + "value": "0x400280027ff97fff" + }, + { + "address": 36, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 37, + "page": 0, + "value": "0x3e8" + }, + { + "address": 38, + "page": 0, + "value": "0x400280037ff97fff" + }, + { + "address": 39, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 40, + "page": 0, + "value": "0x7d0" + }, + { + "address": 41, + "page": 0, + "value": "0x400280047ff97fff" + }, + { + "address": 42, + "page": 0, + "value": "0x400680017fff8000" + }, + { + "address": 43, + "page": 0, + "value": "0x7fff800780077ffb7ffe7ffe80027ffb" + }, + { + "address": 44, + "page": 0, + "value": "0x480280007ffb8000" + }, + { + "address": 45, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 46, + "page": 0, + "value": "0x19" + }, + { + "address": 47, + "page": 0, + "value": "0x4850800080007fff" + }, + { + "address": 48, + "page": 0, + "value": "0x40780017fff7fff" + }, + { + "address": 49, + "page": 0, + "value": "0x3" + }, + { + "address": 50, + "page": 0, + "value": "0x480a7ffc7fff8000" + }, + { + "address": 51, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 52, + "page": 0, + "value": "0x6" + }, + { + "address": 53, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 54, + "page": 0, + "value": "0xa" + }, + { + "address": 55, + "page": 0, + "value": "0x1104800180018000" + }, + { + "address": 56, + "page": 0, + "value": "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd1" + }, + { + "address": 57, + "page": 0, + "value": "0x48127ffe7fff8000" + }, + { + "address": 58, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 59, + "page": 0, + "value": "0x3" + }, + { + "address": 60, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 61, + "page": 0, + "value": "0x5" + }, + { + "address": 62, + "page": 0, + "value": "0x1104800180018000" + }, + { + "address": 63, + "page": 0, + "value": "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffd0" + }, + { + "address": 64, + "page": 0, + "value": "0x400680017fff7fff" + }, + { + "address": 65, + "page": 0, + "value": "0x6" + }, + { + "address": 66, + "page": 0, + "value": "0x400680017fff7ff8" + }, + { + "address": 67, + "page": 0, + "value": "0x2" + }, + { + "address": 68, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 69, + "page": 0, + "value": "0x0" + }, + { + "address": 70, + "page": 0, + "value": "0x400280007ffd7fff" + }, + { + "address": 71, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 72, + "page": 0, + "value": "0x1" + }, + { + "address": 73, + "page": 0, + "value": "0x400280017ffd7fff" + }, + { + "address": 74, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 75, + "page": 0, + "value": "0x2" + }, + { + "address": 76, + "page": 0, + "value": "0x400280027ffd7fff" + }, + { + "address": 77, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 78, + "page": 0, + "value": "0x3" + }, + { + "address": 79, + "page": 0, + "value": "0x400280037ffd7fff" + }, + { + "address": 80, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 81, + "page": 0, + "value": "0x4" + }, + { + "address": 82, + "page": 0, + "value": "0x400280047ffd7fff" + }, + { + "address": 83, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 84, + "page": 0, + "value": "0x5" + }, + { + "address": 85, + "page": 0, + "value": "0x400280057ffd7fff" + }, + { + "address": 86, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 87, + "page": 0, + "value": "0x6" + }, + { + "address": 88, + "page": 0, + "value": "0x400280067ffd7fff" + }, + { + "address": 89, + "page": 0, + "value": "0x480680017fff8000" + }, + { + "address": 90, + "page": 0, + "value": "0x7" + }, + { + "address": 91, + "page": 0, + "value": "0x400280077ffd7fff" + }, + { + "address": 92, + "page": 0, + "value": "0x480280087ffd8000" + }, + { + "address": 93, + "page": 0, + "value": "0x480280097ffd8000" + }, + { + "address": 94, + "page": 0, + "value": "0x4802800a7ffd8000" + }, + { + "address": 95, + "page": 0, + "value": "0x4802800b7ffd8000" + }, + { + "address": 96, + "page": 0, + "value": "0x4802800c7ffd8000" + }, + { + "address": 97, + "page": 0, + "value": "0x4802800d7ffd8000" + }, + { + "address": 98, + "page": 0, + "value": "0x4802800e7ffd8000" + }, + { + "address": 99, + "page": 0, + "value": "0x4802800f7ffd8000" + }, + { + "address": 100, + "page": 0, + "value": "0x400680017fff7ff8" + }, + { + "address": 101, + "page": 0, + "value": "0x39d703c98a1b2e1a2ddf0c93810df2d39b6dfecdee6832188d" + }, + { + "address": 102, + "page": 0, + "value": "0x400680017fff7ff9" + }, + { + "address": 103, + "page": 0, + "value": "0x541c4683d434a407a3525e2f20fa9431b65cd58e995379146d" + }, + { + "address": 104, + "page": 0, + "value": "0x400680017fff7ffa" + }, + { + "address": 105, + "page": 0, + "value": "0x66f2b6f9585469eef0f16447a1bc76adc5f3b602a698dfdc42" + }, + { + "address": 106, + "page": 0, + "value": "0x400680017fff7ffb" + }, + { + "address": 107, + "page": 0, + "value": "0x16f13d5794d8770f73a01aa7e00accde43f4fa6a208a7f03a5" + }, + { + "address": 108, + "page": 0, + "value": "0x400680017fff7ffc" + }, + { + "address": 109, + "page": 0, + "value": "0xfdf1ac3b6b45fdeee26ff23d7a5318a94dabb4efbba7ad35a1" + }, + { + "address": 110, + "page": 0, + "value": "0x400680017fff7ffd" + }, + { + "address": 111, + "page": 0, + "value": "0x639b68738d3ebd70e1181f43ccfbfc0e5ba26fb99251069ae2" + }, + { + "address": 112, + "page": 0, + "value": "0x400680017fff7ffe" + }, + { + "address": 113, + "page": 0, + "value": "0x50c5875966fe759e96419d03d1ff8c66e868d68a052651260d" + }, + { + "address": 114, + "page": 0, + "value": "0x400680017fff7fff" + }, + { + "address": 115, + "page": 0, + "value": "0x51611748d0540c05bd45cd46cdb6cdcdce7402d755893da7e0" + }, + { + "address": 116, + "page": 0, + "value": "0x482680017ff98000" + }, + { + "address": 117, + "page": 0, + "value": "0x5" + }, + { + "address": 118, + "page": 0, + "value": "0x482680017ffa8000" + }, + { + "address": 119, + "page": 0, + "value": "0x3" + }, + { + "address": 120, + "page": 0, + "value": "0x482680017ffb8000" + }, + { + "address": 121, + "page": 0, + "value": "0x1" + }, + { + "address": 122, + "page": 0, + "value": "0x48127feb7fff8000" + }, + { + "address": 123, + "page": 0, + "value": "0x482680017ffd8000" + }, + { + "address": 124, + "page": 0, + "value": "0x10" + }, + { + "address": 125, + "page": 0, + "value": "0x208b7fff7fff7ffe" + }, + { + "address": 126, + "page": 0, + "value": "0x80" + }, + { + "address": 127, + "page": 0, + "value": "0x0" + }, + { + "address": 128, + "page": 0, + "value": "0xb8" + }, + { + "address": 129, + "page": 0, + "value": "0xbd" + }, + { + "address": 130, + "page": 0, + "value": "0x23d" + }, + { + "address": 131, + "page": 0, + "value": "0x123d" + }, + { + "address": 132, + "page": 0, + "value": "0x3a3d" + }, + { + "address": 179, + "page": 0, + "value": "0xbd" + }, + { + "address": 180, + "page": 0, + "value": "0xc0" + }, + { + "address": 181, + "page": 0, + "value": "0x23e" + }, + { + "address": 182, + "page": 0, + "value": "0x1247" + }, + { + "address": 183, + "page": 0, + "value": "0x3a4d" + }, + { + "address": 184, + "page": 0, + "value": "0x5c9d88a1de4e8a88f3a14ee67d10cc244cf6eb630751faf26a6c83a86205e0" + }, + { + "address": 185, + "page": 1, + "value": "0x4d2" + }, + { + "address": 186, + "page": 1, + "value": "0x10e1" + }, + { + "address": 187, + "page": 2, + "value": "0x3e8" + }, + { + "address": 188, + "page": 2, + "value": "0x7d0" + } + ], + "rc_max": 32783, + "rc_min": 32747 + }, + "version": { + "proof_hash": "22d6d7ddd29c88ad7b201895319e1d42f3eab748fd7bbe12d79912f6bc5d5b36", + "statement_name": "cpu_air" + }, + "extra_annotations": [ + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 8528601: Hash(0x9c908cb4ec69f4e4d9283d726a5b0aafbd88f2c8000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 9491784: Hash(0x557cb76392e7c37b621051051e6d2b6c58b0f850000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10223145: Hash(0xf89fda6f01d0f84429cfe4649b4081848506febd000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10460047: Hash(0x44118543bfae25a377a0676c494e43fb3d0c3cf8000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10499482: Hash(0x10c692922c2e56b551a659b92cd5ce06066ab1be000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10618912: Hash(0x9374a08c17e35854f4df6228afada7412f970fda000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10673204: Hash(0xf5f736019ad2d61ffdc1a842b118bb31a19a8713000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 10684022: Hash(0x190a690b101d96043ad0304000777a12b171d4ec000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 11045206: Hash(0xd0024261f90d03f31b338dd2900fc1d519c495e1000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 11902330: Hash(0x3be369b668719e5a8ebb1805277212dd21753c67000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 13020201: Hash(0xef24e53f373328a84063d839693c581bc728f99c000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 13844313: Hash(0x872439f16e679fc3be0d08f2120698e09453e57d000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 14747702: Hash(0x8bfb31d4d2899f54e2ec3ea122ace1d4e11f39b4000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 15156639: Hash(0xf9b9267d46647b7123aaf1f354f76e8cbe3ed118000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0: For node 16503938: Hash(0x5754bbcdaec97ade3040784f412c39b28933ae26000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 8528601: Hash(0xd54a6b696c582fa8a4282fdc059f4cb4f9b88bd3000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 9491784: Hash(0x415f58e0b12489b326b749a6474a7808610bc58c000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10223145: Hash(0x769e87cd226f7a646b67cd9ea81f3e34ddb21245000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10460047: Hash(0xdc0d2e5f4b5d402a38cbd94b8c1d2e84dd848945000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10499482: Hash(0x725636663fa19760a31868ca000373c1ff1bc92d000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10618912: Hash(0x7736a600339a67ca18643db04b1affd63d38c7da000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10673204: Hash(0x99327dd550105e2030d370d97a5d55cbc0e26486000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 10684022: Hash(0x974164db18c2d0d131a6c767db9291219030690b000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 11045206: Hash(0x4362775be0f35fe489b1ed03c5ec201d18dc6e35000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 11902330: Hash(0xa38365ce7e543aae89ca9090bb8c50f1637ff371000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 13020201: Hash(0x507827279a9eabf71bb353a6272adb3eaa6c1a2b000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 13844313: Hash(0x48f1a962c644e9a56c9a6e216b60cd65324a5ffe000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 14747702: Hash(0xf17e9e363c972e77b220934d16707192dcc97827000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 15156639: Hash(0xfc2cb00feda1c06027d78687059387243d412235000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1: For node 16503938: Hash(0x3d66484b7f5207c9456bf7a8852fedbdf5e198e1000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 8528601: Hash(0xc5722560849aa4a72b8ebf53713e47fd0c78ffe4000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 9491784: Hash(0x2d827424328390768b399a0db674c8cf7edab784000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10223145: Hash(0xccd74f047b23ba615457beb12731bca20ae9c24a000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10460047: Hash(0x542e0c39904e6756e28b74d133af5aff9458c07d000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10499482: Hash(0x87e74b041c742e8ccd5bec6012f9914d82c7ee17000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10618912: Hash(0xb0ecb9634fa2425143a350a9b5862ffc479c73ae000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10673204: Hash(0xff19e454f2bcb96213afd7a0c905aaf950d5343c000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 10684022: Hash(0xe60cc102d78d71031f32f03eac6f283fd029f207000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 11045206: Hash(0xfa23d0af643ac3b874f27623fbc7e7d453e097f0000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 11902330: Hash(0x680550909b70986c871ef03d4f0bec474efbf39b000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 13020201: Hash(0x12807263c78437a97023848299dc7fcc97dc7c6a000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 13844313: Hash(0x6c14c62476a3f3c7467e8fd3a2702cf3b1ae1de0000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 14747702: Hash(0xad2a60646f9630ec5dcb6548f46714f12536fd74000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 15156639: Hash(0x875e0cf539a896e26dc68074099620510ed19d0c000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2: For node 16503938: Hash(0xa5818742a58214af655e6187f2c84f2305fa31f3000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 17499, Column 1: Field Element(0x4a8578ab21c9c5d50f2f0fc6d34809d00abb22d28965326799c7ddfe9566dcb)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 139993: Field Element(0x465d9f7284b06e3392e9ae6c3ba02e60ece0e77e16562855a92f7d520bf7375)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 137897, Column 0: Field Element(0x6916668fa541d84643662727566cec26b196371bc08cfb298b4482704bba65d)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 1103176: Field Element(0x481bada8adb9d454dd999f8b82abdd045e8af963bed30c5b7de05326b103030)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 229317, Column 1: Field Element(0x7f8bde1d6a37d0af060f7863da4e2acf8d50d7b17ebada74f3e432a6a101f4c)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 1834537: Field Element(0xdd8a5a901f2555f315bea8aec00da7d3632c6140a3984141f2c64abefe5add)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 258929, Column 7: Field Element(0x53b83d7349e2f4120467f0fd27d1f37414953fc83c616cde1667cb0e2768167)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 2071439: Field Element(0x5f7522fc6a751d1467fd6247e0180b2e0cf1c55edd05d8a4ae87aeb553afc29)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 263859, Column 2: Field Element(0x4573b26b75a915b82aa46b0103ed316ce775c6d14a3b10f62ab63bccf4aa509)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 2110874: Field Element(0x65bc572abf590dbeaf32b381cc8ac788d8f962f683580abec7f5806917e31bb)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 278788, Column 0: Field Element(0x15df309d8f8e130901be1517483866e5ebf18de61f928463b65f397e08f8a57)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 2230304: Field Element(0x13069b180626a24da96486e8953caf7da2e9d74c4de0f90481435181b1fb7df)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 285574, Column 4: Field Element(0x39701b5e887cff17e1b90830971151e812bbfae2fe04b698ce4ad22d67b26fc)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 2284596: Field Element(0x72cfd710f9487e39468ee7ef44423ce1fbbcc3cab30a14f7658e0aad81d6510)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 286926, Column 6: Field Element(0x6597f95b2608de44e6aa163d9111a14433a9a1cd967218bc0a21a795c0b5fa1)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 2295414: Field Element(0x30a1d74a5c76ff891549da60630ef63e64aa71a0385462e0ae3238f0d620aa4)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 332074, Column 6: Field Element(0x3937ed2999225e8aa1041f23c62240e08d6335be2967bc2d1179777eb3ca0d8)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 2656598: Field Element(0x6292ed6ed0898df2294f7b0f3f392e54e58b8410bd1b4255ae4ca1a91bce6c)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 439215, Column 2: Field Element(0x4708f2983975c13a0e21f8a48bb8880f6cccadc52832f8cd8caff1df8bdbd51)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 3513722: Field Element(0x1cc1f1bca045037aa1d876bb3ff7e54e1351009d3ccd15540550715c7648345)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 578949, Column 1: Field Element(0x22b382ab1c26488ebdf495524ecf4aeb8603dae41fa018142b3d87bb4d3243f)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 4631593: Field Element(0x5fe119ed41665d93ace56f27bb544fe98ed53ae4c4a8f19a7085b5a0d53424)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 681963, Column 1: Field Element(0x5a7e746b31a9115c57108e325d7f97436cc9bb58ae68e6188bf7420b7975ad5)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 5455705: Field Element(0x7fb8c9c9e3bacfc6aa56a0c222ab302a6dc6a6ab7fdaa3d5303d4d540c3ba8d)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 794886, Column 6: Field Element(0x53ac047a682d28fdb3f965fa25231d2eda242bdf00f54ace2f1675cc142d06b)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 6359094: Field Element(0x340247e24b2dc0051dfea32328b0a8fd2ecb85ea595bcc1b557e2660526a206)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 846003, Column 7: Field Element(0x7f6fd86102b9297224a1067ad70ca7a1bc795f08cd9256968ea83dd6e7f7652)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 6768031: Field Element(0x19ccf138f9f628d37f1d9255af8f3edfe1b47280703a1b97855538210b18dbf)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: Row 1014416, Column 2: Field Element(0x677eef4617222390fe446a192944ec61114bd359aa0340dfded2b9b730aa741)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: xInv for index 8115330: Field Element(0x36eb918b2e20a0af38df998e94cf626e7f63e0914d5db79a2b6dcb04274c564)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1066075: Hash(0x231c335763da4475c45cc1409708bc9bf2c71fef000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1186473: Hash(0xb306dd53c19724310bd1f3e6b16ca27487d97428000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1277893: Hash(0x3721948df8f84b11be6234c35fd8b1c4d2a66e20000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1307505: Hash(0x6df3ec8af6a9d78688cf5c9193cadb1114058879000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1312435: Hash(0x4c07659ac80db914116c07f424c5932430081877000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1327364: Hash(0x1689b02625f1e39d8b91b965f67e6a532907feed000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1334150: Hash(0xedb5c0ff37595d62b8acfe6f75004b5b8239b6b7000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1335502: Hash(0xf0d8a97ccf96031bbb3d5de18aba409b61d22361000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1380650: Hash(0x71ccf96f109dee8b652b33328fa5cbcdd2a3a294000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1487791: Hash(0xa75dd1a3f42396a21ac53e60fb11fb3843f27f56000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1627525: Hash(0x3160f0cd835430036a6c26fe0502bbf12acc731b000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1730539: Hash(0xba70049ef77323010641b92f369920eac15de3ea000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1843462: Hash(0x652bb4dca05de2ba51f41adf9b4aef932daabac1000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 1894579: Hash(0x2f709251b1af294b71c9bc2be36569dcef3021bf000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 1: For node 2062992: Hash(0xdbe86a217e8c3ecce25ed3b98ce2fc3c5021c836000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 2187, Column 3: Field Element(0x203879df67330904489098b0b44517680f502ffd4624d60aedd4c1df781945f)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 17499: Field Element(0x69f69f2b99401c2cf5186e2c543bc5a9afec1f2b0c3e2f8057290ec738e1fab)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 17237, Column 1: Field Element(0x7932f9df54d556886a3ca27eb3da1d6bf4971837263f2f6d4b6b4ad0dee3edc)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 137897: Field Element(0x699e9042687b142f77d1f32f0b9f8e168a4dbd42eaed8443713d07100a34053)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 28664, Column 5: Field Element(0x26774b04769e5920f8380b1659d45eae9c1e14e9360c9aed6740c7e563d2e8b)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 229317: Field Element(0x7d2cb58d16c25c6a61eb61da70ab7ddbe1a81b5407e3621ec69206b9bd28f82)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 32366, Column 1: Field Element(0x198e5f95f3958fd6abf67e15a8e696972e6c71bb544ac6cfbc4cc5d069fbf6c)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 258929: Field Element(0x32d65f8e17eeba86c932924e17513b2074ab631420f7e51fc1c11a02469bc55)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 32982, Column 3: Field Element(0x307963227cf5660e50cc582db9da2921df687bb4dfcc9a7ae39feaffac49b53)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 263859: Field Element(0x2d383eedce1cdfbb5c675e4fe029a0013a70a84443d67e6d433d7d6466e1c88)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 34848, Column 4: Field Element(0x35e886097a88b58190a6f94bc92d8ad79decd965f2f4cc16c0c0b1fb9ceb1ae)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 278788: Field Element(0x48b312c4be5ab89b3f1308647d4b24a3e138977e61aa4b8ae1bfaed7b58a569)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 35696, Column 6: Field Element(0x257fb912f48d12afbf144695300042e3b0de460f072e7c567cac6fe88dc03d6)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 285574: Field Element(0x3125e48d9a429d2a20aedb4dd921baa5f2f6350b5ef76b7c0645a6eb31183ba)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 35865, Column 6: Field Element(0x7a646cce7c1af68877052a7e36227f6ad1008949779093a7de0cb25460f6a78)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 286926: Field Element(0x387584269cfc0e8e14283c7708590eacb6ee1f0308ff9c5d925a343cdff91e2)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 41509, Column 2: Field Element(0x6cd09540fcb5b95717e5fd90751a5213427e15e3b914b75d576310a6751c1cb)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 332074: Field Element(0x1c6abe5545fc1057730225f6bcaa457c9a30daef853889826a9a53f60bfa94d)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 54901, Column 7: Field Element(0x6681e3579b007c7c52b0591e261f7f3612f49c981e0c1a39b909c95ea99b9ac)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 439215: Field Element(0xebe26e28ed130525beddd5a8384103acfd01a5fbb65540b741e46ced254304)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 72368, Column 5: Field Element(0x7d19398f80c43d452985f289dc713801c2354569b636ec37a31fee002f6b96c)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 578949: Field Element(0x6453191e954b6040b06880aaa09819003104d71cf21609ba6806da8ad963f83)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 85245, Column 3: Field Element(0x578b2b3923429ec231733e65c03aaaa12a6e2cf1372401e6d0828180502db16)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 681963: Field Element(0x9889c6f0ad9a83f4f7ed662850e5e63fbb590816632495d085c6b7a5741b68)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 99360, Column 6: Field Element(0x69120be5b30c48fe44b624ff4e7ba35d63827f1ee152c84ff70a90570bf985f)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 794886: Field Element(0x6ad942cd8a0545a63e12ece24fd5837e295bcf65a6dccde65b1104654b514b8)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 105750, Column 3: Field Element(0x38695c6c20b047d62dda1f55c95d62edef2e5584ff52184adf01833e55cfe15)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 846003: Field Element(0x74796a15f3450a087ff0f2da4f023b07706f17201ec4d9f86bafd7307446d31)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: Row 126802, Column 0: Field Element(0x5328c33e2c5320100be7516af02a869c9a4689d1c5fc5bc5ca855e5e5f8cf8b)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: xInv for index 1014416: Field Element(0x6a280d99180f64d960fa29ce864619b643cf336e784b3246daf2e68b728a637)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 133259: Hash(0xd5fe1fe07999d9ba28233d2d38e5b7e31efb11b9000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 148309: Hash(0xfd9a5eaaceeeaced3b1d8033b0597536d71eb7c3000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 159736: Hash(0x2ab57fdfd531e9749972c92db2186953bfc8f6f0000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 163438: Hash(0xc255137e8f7a659b24f3ec5e659dc7db982768a8000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 164054: Hash(0xe5792d82399a710499da69f802c13d347437372d000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 165920: Hash(0x6321c35f57ce6b77f68ded58d3462a146f0ed7ae000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 166768: Hash(0xe435f8292da9cc093bcc8cbe4e0f4dfdd675a239000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 166937: Hash(0xa002ff4533aace19b7ec954f8bb0465dfe486e8a000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 172581: Hash(0x6ca1d996fcc9068231ce57a7fbbfb03fb41b32b4000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 185973: Hash(0xfc5bb539a79ed9591c0eadfd9fa34860216b0412000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 203440: Hash(0x7bdcd72475a20f9d5b2ff9e8879e8c4c994c544d000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 216317: Hash(0x3aaa166009f97adeb619869fca03b6d046260cc5000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 230432: Hash(0xc91241dc5c14b68ea28df2ec34cc7fbdfa118da1000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 236822: Hash(0x8a39ae7e0dec3408ccd89d31872be535ad040340000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 2: For node 257874: Hash(0xd24bf2345594817a0de1296e1d38c02742b20ccf000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 273, Column 3: Field Element(0x3388ff6b341aedc7e7ef0b9096ec77ea33fd7139919cb08547ee0a29c5f0aa8)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 2187: Field Element(0x26fd1b52bc1613c9deee9a3b111aa4f37b61fdf5e02fefe5f424053dc5b4551)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 2154, Column 5: Field Element(0x1ba30eaa57fc6e23f10b3fcefb1dea94193dab3af4eb8fb369bfca282d07ae8)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 17237: Field Element(0x196788ff83d75fb6e3ea40f6bb076ad7483b103b399b0ea7abf1440dafb605)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 3583, Column 0: Field Element(0x528413012e60db855d5fe05933c7c958423d3ac0b91c87e2314f78db7cfc7d7)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 28664: Field Element(0xddd48c5f2b51c9d3cfc0d306e8bb5aafa427c1bf24ae67fce39e292caa9570)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 4045, Column 6: Field Element(0x2b00e9d6bc5d5d84ef449678f3a448807fa6fb38714768d26f7f9061ce1e950)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 32366: Field Element(0x56061da8ffe4279d5f8d40132b3504497fca0c7f344f18c52a0f3b77b4297f2)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 4122, Column 6: Field Element(0x61b571900e80f7393dbf1eac36d627f0ee6363765b7543e94538fc1f33073d6)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 32982: Field Element(0x4fe49816c51eabe2f6edd143fca80d7bc708914bc5e49462bce38cc233d859e)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 4356, Column 0: Field Element(0x6624af243e1c8a6c95e51a5757702bf9a5e3bff127fc80cb863a50647060362)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 34848: Field Element(0x322cef363e1568f9542ef3160dbd84e43ebb576de26fa43e9c7bc087261a93)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 4462, Column 0: Field Element(0x32e258f13135d2d14d2b8ff8821e8e321f1e0471238f9c6c3b6bbe3468361c2)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 35696: Field Element(0x1c478743fc914e7151142b758fbe64dedef090ea16a2c2db35692a3019e81c0)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 4483, Column 1: Field Element(0x5229bf4590d12effed4e594bd8a0e243bae8782b2b370de468e11f5927e0e79)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 35865: Field Element(0x727bf8971296f8d18a42b17ef024af2e992ac1a6d060b078e9fef1235a57116)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 5188, Column 5: Field Element(0x6bc153c438a90f67793367bc4034283c4fc46d7c3e210763fc511a698b4376d)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 41509: Field Element(0x3f83b761a5b77638426c890e7483a1c858be2fc32d80e61d7ed033879f077c3)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 6862, Column 5: Field Element(0x444bcfdb1aa01ae44bcbbba02beeb44510c858fae83d5c596ed43bc78d66859)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 54901: Field Element(0x453277f291049d9f9addcfe3cecad7a01b93e3a32c0300f833171a516603bfa)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 9046, Column 0: Field Element(0x3099b597214e562a43c3d6ae4be2979bd36dada2292496f34fb4618859e5262)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 72368: Field Element(0x6a056b18c6904c6286156373520e52ef3255d8f3890a425ca6eb2505d639d)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 10655, Column 5: Field Element(0x5961a3ac9fa2c3a077cc162871c518f86dc8fca168e50e86f4ee5c898606cd0)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 85245: Field Element(0x284b3ad331d385973e7cb4b847652dbc5c961b14d7d7e44eae90adae54ed074)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 12420, Column 0: Field Element(0x1e676a756042fb1d6a99b9b16b65cde960bd8de4e8cccd253a2c2c5ffec4bd2)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 99360: Field Element(0x4ba700c0065c9ffe0668c4881811a24760c53ce89d59a1fe82706f74b82dce2)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 13218, Column 6: Field Element(0x3ad984a3a20e0c3e706d1d50128638a4f535e39227dd2a0b44310feac7eee9b)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 105750: Field Element(0x56eaba4a609759ab96741e4e79f16be116718b41c60b4142a61efbf0cdcc50b)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: Row 15850, Column 2: Field Element(0x172a0cfd32c2362e3260b58c90f2d0ea20f4b8415ca66760fd55a51e5ff2a6a)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: xInv for index 126802: Field Element(0x51a1cd433ab7d3cf281d1c634aa8c4ae00e71ca278b5013685179406e0b0ac7)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 16657: Hash(0x7d3fcaf4e46632eb98c53ad500edf34c9264ce32000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 18538: Hash(0x7fb720f457b20cfc7d11e9eb94a20550825bbd68000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 19967: Hash(0x6ac3caeef028cd5fad562f7dd4ff97622e057878000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 20429: Hash(0xde7181eaee6053cf539df903c8c659281c189f25000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 20506: Hash(0xe346bc31e882672786cb32fdfe2a14d7ed93b4ce000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 20740: Hash(0x9a70108682b38968880ff296b4ff139b8e004cf6000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 20846: Hash(0x5f235d0c367caac13781e677af004d5e080a49e6000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 20867: Hash(0xaa9af750b6972d92d8582ad78ae1dc1f08d9acfc000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 21572: Hash(0xbccbdec3d8f853fd6d1f98c1fef6c84f6902559b000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 23246: Hash(0xcce33c83e4b3bef8f499ea08bdd8ecd1cea07e5f000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 25430: Hash(0x435e831ece364a22f1cdb207a460a7666ac7c13a000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 27039: Hash(0x360568dd1ceb7159a15c7b06065831f155272c27000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 28804: Hash(0x6a398a273ef8d2b3de7ab82f6b32b5df903603f000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 29602: Hash(0x114368dfc0eb6360712731fd228db84ed46cb656000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 3: For node 32234: Hash(0x7a30b72115d3e2002e945015b7a46aaadaefebf6000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 34, Column 1: Field Element(0x310d3226b94f63e5a6eb1e0d51e5a589519b99bc8fc377f54e15a134b605f86)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 273: Field Element(0x21e3603c15d067f8e23010aba2c2bcf9b00a7bc339f0874ae95e277da9c9312)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 269, Column 2: Field Element(0x70eb3dd48b5c10dcb053672d778afdb0cff16c0f2ad4db04c62feb14716d8cd)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 2154: Field Element(0x3b2a729de106e8491df38237c73f6dbd57964cf73270d4960e6fabde5ac7586)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 447, Column 7: Field Element(0x4b86b682a6610c72ea25ba0329db020975a8dd89245b3787db6787bdf1eaa0e)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 3583: Field Element(0x3b7b6eb7f0897a9e67094637e56c928fb974f4e844b234dbd9ea108eb9c572d)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 505, Column 5: Field Element(0x4ffd1e522387f014f397562ab7bdd47fb5d3cb0e24598f9a57f628f0495117e)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 4045: Field Element(0x6d66256406f888fcecd4f835ca6807c978683971c88afc2858ca52eb8f665e4)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 515, Column 2: Field Element(0x4fff3f8474142bb5778896dbbb528820faf5e5bea9fcde0efe55f5b210517ea)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 4122: Field Element(0x4f75798794616ce02999ca1aeccc315d42486ef5202c5d398f9118dc68017c1)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 544, Column 4: Field Element(0x1e6b74556cc679b4ce4efadd20fa2c7361c4897a424b9ceeb695056a5074d15)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 4356: Field Element(0x9cdefc991ec30c7beb2d4ebe2e7d2d59ff70dfec9f99a4e795ef82d5a7ed46)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 557, Column 6: Field Element(0x2f47997c1b41009ba7bebfe34950d6457a8bccc4bebbcbb972a656a92f3bc3a)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 4462: Field Element(0x17f7d49cd7f02782435c40c3a9e5403453977e24c83ef32097a18dd2bf804c6)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 560, Column 3: Field Element(0x5482c857f8aec157caefcb940513d3354abf9807b4f3354f86f929cecabf14a)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 4483: Field Element(0x34d8c228bb486d10fc203b5487011cb4c42211435a449704a68763ee657aa4)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 648, Column 4: Field Element(0x53af63d31f557596fe5751765d989de78d822c62a953017ae8ee02f505014fe)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 5188: Field Element(0x7fdb61ce84f83573534982f79d608ac8c309c9791ff1df636ea518f335dfb68)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 857, Column 6: Field Element(0x3f1f1564359e9397451da0bbfc13a5a1bb78417fc608d9c9dd4e81259e40d51)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 6862: Field Element(0x2d584c2712e176e422b194fd74b6b5849e1d1cfd7ad9668f477d7edf19d08a4)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 1130, Column 6: Field Element(0x36b509265c681e3cc2af98e6b6114213fd92e74bc893cc12f5238733b53c67e)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 9046: Field Element(0x393b8b722fd4b6abde7fe8890d103774449c425036e2dd0b337c4b100bbc960)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 1331, Column 7: Field Element(0x39f5bb250e36aa2d941102a5ac376ffa2a141bfba7fba4bbd90988f95b36f1c)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 10655: Field Element(0x3087061859d7c587e1418d37499864c26c438b9069329aeaf17b6a522c336a7)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 1552, Column 4: Field Element(0x701a50fbbc1040fb3c0bc791f5fe90d56d514c500de868b0fbc26e286bb02b1)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 12420: Field Element(0x4edc715210e6ab65c5ed44a83758cd74e238e50aa4750255e66f8c20b899e6f)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 1652, Column 2: Field Element(0x70e655a424b4534bc659b5c7bb57937b6fca5015b14bd70fd1cf0632898f4d4)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 13218: Field Element(0x43e0e923d8c79a885d4d938d7dea790810859c621cff1f88568bed3f4ae4788)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: Row 1981, Column 2: Field Element(0x4d10822146d2f3279051cf8e6deec7bac0fa349741f865e5880957f13f74bf8)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: xInv for index 15850: Field Element(0x2cae2e5fbd5401db87ce0923fdd18458ecde747ad8c487a4cfb2a094e0b1e5a)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2082: Hash(0xa04a77d0234a8d3e3359a6e989db44822d6eda1a000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2317: Hash(0x1e15bd3c5eb94399fec3b4ca9a8a292b1805bb3f000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2495: Hash(0x6b2b36f5c5a57d461c3f3741d5bdffc66ad5003b000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2553: Hash(0x29e56490a6e0190e2a135607cd40849bc6efd4a4000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2563: Hash(0x895ced5ab45eb7ca0d154b1642620f555be8cb66000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2592: Hash(0x3d58ed54d8dd01e94aaaaf42e84000f9e01a0322000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2605: Hash(0x228361957e1ade3db0969055b80283d640d7ba87000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2608: Hash(0xa7968bb080dbfef4aa3c12782651c90a33cbb265000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2696: Hash(0x91e7722834752b721ed74b79e96e4ce0981ac1f7000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 2905: Hash(0xb710da41166b021ddf3ee3f24b62c4f9ec7f1795000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 3178: Hash(0x9f63759eae8b92d1e1db8992fd6e004480b285cd000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 3379: Hash(0x4a81ed72c72fbb9e2b72d6db88bacdf0393a7a0a000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 3600: Hash(0xf478889adce1d6f5a322350ef3fe4fe8a8051eca000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 3700: Hash(0x7ac549a9493bba54d9d87d7c19ca3f9ce64ce7b6000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Layer 4: For node 4029: Hash(0x18e0295dc5f72f4d35fdbe2a095186e26e59942c000000000000000000000000)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 34, Column 0: Field Element(0xf358d2ac897faee6b904203e73c88144cccafe2b3670d5552406cc6d6a71a8)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 34: Field Element(0x279c4487a6611e3af5550024c7cd477b6c5f135c5788c66e39626c3860dcacd)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 269, Column 0: Field Element(0x1c96bdc10906217ffb588e3329e7d7c006dd1933a2242a72b28e2a02b1532dc)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 269: Field Element(0x76bde7d753d7111f9b1445d460d5311c82ee6d029399f4923f5ca447e4185ef)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 447, Column 0: Field Element(0x58528f7c2372729d558b9ee278e02c0b8e7b5fe9384c7639c42896e04317a20)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 447: Field Element(0x158f67929f154ade2fa131f5f997e1a89dcc75fc93ddeaf2dd16eca50c0fa7f)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 505, Column 0: Field Element(0x61951a00e9a6e02827e9c0cd6036c628e5bcf79f27814b859f9cb34ee3dacda)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 505: Field Element(0x750f8ecb921cfe700c9280dc3f607ef5d0ee403b6f5433dbd91d06201bbc5e3)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 515, Column 0: Field Element(0x6f8e91fc59858b381bfca9d8ee2b2aac72152f806d61994881495cd2ab2e356)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 515: Field Element(0x70be4632cdc4d1823fecca876c04a30b8a201482b1c63863a71ce0f5ec1a304)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 544, Column 0: Field Element(0x539c9d1e84b49d3230a7b35a3cc6c532da38cdacb8d20dacea89c994bd16735)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 544: Field Element(0x380868d0bfbbf3e3a56cece80b334d0035c1553db4578d2639c2a8b033702c7)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 557, Column 0: Field Element(0x621d82791ddda52127c252d477e44f754a50de843a96d1e4cea7d87e448d9e2)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 557: Field Element(0x5dacc1dcafa46859dbe7a91ccd7f61dafd8dc7add0a3372e455c233be3de537)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 560, Column 0: Field Element(0x1514f66431cc3dc98ce368af7b14ca32e80ca8257a05e0f9ef28a6507b9a77c)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 560: Field Element(0x2d5c3e5376e616d0fc17c89f1183c450358e7388ffa91cc0ca37e990e1648ca)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 648, Column 0: Field Element(0x263371ecc95e9c590e8e93240541d52b02a07857d4aba3e65d07cfd6cd8865b)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 648: Field Element(0x71e145114cf389af66e8f8a58bd50dedbd26c08327714c254956146ef826172)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 857, Column 0: Field Element(0x1f8ea5910d42c52eddfce140fcddd89a82f442f84c727bb4c6065315703b56d)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 857: Field Element(0x2bfed58be929abf59f299448d03d26cdf00b6678e738f8afdfb1e8546d2794c)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 1130, Column 0: Field Element(0x2eb854e7f981c298533a8d6e972cfe041296cf221b76e37f921b8ee4c821125)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 1130: Field Element(0x1a8ca94569145afc967aebe3b9b81f999e69d3990d1ad466dc27dd099c913bc)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 1331, Column 0: Field Element(0x73551094c78c14a8bcb9b02abf76eaeb44170f37c36ee38ed9116fd082c56c4)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 1331: Field Element(0x1e15437c8fbac9aee56107957823fa2ce6e3ea7998b22e7c2bf01cae06c11c5)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 1552, Column 0: Field Element(0x184aa3d4e483f14b23158a9d73d0fe01333dd1daed50f721bafd6ab983da5ae)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 1552: Field Element(0x50470389d3c5fd6ea8efe26adeb1005df6c63a880a98a54ebc9007ac22a51b7)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 1652, Column 0: Field Element(0x2d0dab921efcaca7ceefd4068595772ae0aa2901b4109001c322e33ac0ef96)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 1652: Field Element(0x290db5a36283db5ce5cbfd1859cbf3bcdf17207e8c53e985b81079b8f804fe0)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: Row 1981, Column 0: Field Element(0x1b30da9906387799e9074e6c2eef42d521e90f6a23389841ffb0c1deb5032be)", + "/cpu air/STARK/FRI/Decommitment/Last Layer: xInv for index 1981: Field Element(0x3620cc2c83cce948fda248d1b601c0de349245ba1a5dc8853c5dec77d35bb25)" + ] +} diff --git a/src/starkware/cairo/stark_verifier/air/layout.cairo b/src/starkware/cairo/stark_verifier/air/layout.cairo new file mode 100644 index 00000000..b9916dab --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layout.cairo @@ -0,0 +1,32 @@ +from starkware.cairo.stark_verifier.core.air_interface import AirInstance + +struct Layout { + // Virtual functions. + // Each should be a pointer to a function with the same interface as the function in this file. + eval_oods_polynomial: felt*, + // Constants. + n_original_columns: felt, + n_interaction_columns: felt, + n_interaction_elements: felt, +} + +struct AirWithLayout { + air: AirInstance, + layout: Layout, +} + +struct OodsGlobalValues { +} + +func eval_oods_polynomial{range_check_ptr}( + layout: Layout*, + column_values: felt*, + oods_values: felt*, + constraint_coefficients: felt*, + point: felt, + oods_point: felt, + trace_generator: felt, + global_values: OodsGlobalValues*, +) -> (res: felt) { + jmp abs layout.eval_oods_polynomial; +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/CMakeLists.txt b/src/starkware/cairo/stark_verifier/air/layouts/CMakeLists.txt new file mode 100644 index 00000000..74d36169 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/CMakeLists.txt @@ -0,0 +1,21 @@ +function(stark_cairo_verifier_layout LAYOUT_NAME) + python_lib(starkware_cairo_stark_verifier_air_${LAYOUT_NAME}_lib + PREFIX starkware/cairo/stark_verifier/air/layouts + + FILES + ${LAYOUT_NAME}/autogenerated.cairo + ${LAYOUT_NAME}/composition.cairo + ${LAYOUT_NAME}/global_values.cairo + ${LAYOUT_NAME}/periodic_columns.cairo + ${LAYOUT_NAME}/public_verify.cairo + ${LAYOUT_NAME}/verify.cairo + + LIBS + starkware_cairo_stark_verifier_core_stark_lib + ) +endfunction() + +stark_cairo_verifier_layout(bitwise) +stark_cairo_verifier_layout(dex) +stark_cairo_verifier_layout(perpetual_with_bitwise) +stark_cairo_verifier_layout(recursive) diff --git a/src/starkware/cairo/stark_verifier/air/layouts/bitwise/autogenerated.cairo b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/autogenerated.cairo new file mode 100644 index 00000000..307deaa8 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/autogenerated.cairo @@ -0,0 +1,1559 @@ +from starkware.cairo.stark_verifier.air.layouts.bitwise.global_values import GlobalValues +from starkware.cairo.stark_verifier.air.oods import OodsGlobalValues +from starkware.cairo.common.pow import pow + +const N_CONSTRAINTS = 134; +const MASK_SIZE = 174; +const N_ORIGINAL_COLUMNS = 7; +const N_INTERACTION_COLUMNS = 3; +const PUBLIC_MEMORY_STEP = 16; +const HAS_DILUTED_POOL = 1; +const DILUTED_SPACING = 4; +const DILUTED_N_BITS = 16; +const PEDERSEN_BUILTIN_RATIO = 256; +const PEDERSEN_BUILTIN_REPETITIONS = 1; +const RC_BUILTIN_RATIO = 8; +const RC_N_PARTS = 8; +const ECDSA_BUILTIN_RATIO = 1024; +const ECDSA_BUILTIN_REPETITIONS = 1; +const ECDSA_ELEMENT_BITS = 251; +const ECDSA_ELEMENT_HEIGHT = 256; +const BITWISE__RATIO = 8; +const BITWISE__TOTAL_N_BITS = 251; +const HAS_OUTPUT_BUILTIN = 1; +const HAS_PEDERSEN_BUILTIN = 1; +const HAS_RANGE_CHECK_BUILTIN = 1; +const HAS_ECDSA_BUILTIN = 1; +const HAS_BITWISE_BUILTIN = 1; +const HAS_KECCAK_BUILTIN = 0; +const HAS_EC_OP_BUILTIN = 0; +const LAYOUT_CODE = 0x62697477697365; +const CONSTRAINT_DEGREE = 2; +const CPU_COMPONENT_HEIGHT = 16; +const LOG_CPU_COMPONENT_HEIGHT = 4; +const MEMORY_STEP = 2; +const IS_DYNAMIC_AIR = 0; + +func eval_composition_polynomial{range_check_ptr}( + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_generator: felt, + global_values: GlobalValues*, +) -> (res: felt) { + alloc_locals; + + // Compute powers. + let (local pow0) = pow(point, global_values.trace_length / 16384); + local pow1 = pow0 * pow0; + local pow2 = pow1 * pow1; + local pow3 = pow2 * pow2; + let (local pow4) = pow(point, global_values.trace_length / 128); + local pow5 = pow4 * pow4; + local pow6 = pow5 * pow5; + local pow7 = pow6 * pow6; + local pow8 = pow7 * pow7; + local pow9 = pow8 * pow8; + local pow10 = pow9 * pow9; + local pow11 = pow10 * pow10; + let (local pow12) = pow(trace_generator, global_values.trace_length / 64); + local pow13 = pow12 * pow12; + local pow14 = pow12 * pow13; + local pow15 = pow12 * pow14; + local pow16 = pow12 * pow15; + local pow17 = pow12 * pow16; + local pow18 = pow12 * pow17; + local pow19 = pow12 * pow18; + local pow20 = pow12 * pow19; + local pow21 = pow12 * pow20; + local pow22 = pow12 * pow21; + local pow23 = pow12 * pow22; + local pow24 = pow12 * pow23; + local pow25 = pow12 * pow24; + local pow26 = pow12 * pow25; + let (local pow27) = pow(trace_generator, global_values.trace_length / 2); + let (local pow28) = pow(trace_generator, 3 * global_values.trace_length / 4); + local pow29 = pow23 * pow28; + let (local pow30) = pow(trace_generator, 251 * global_values.trace_length / 256); + local pow31 = pow14 * pow29; + local pow32 = pow12 * pow30; + let (local pow33) = pow(trace_generator, 16 * (global_values.trace_length / 16 - 1)); + let (local pow34) = pow(trace_generator, 2 * (global_values.trace_length / 2 - 1)); + let (local pow35) = pow(trace_generator, 4 * (global_values.trace_length / 4 - 1)); + let (local pow36) = pow(trace_generator, global_values.trace_length - 1); + let (local pow37) = pow(trace_generator, 4096 * (global_values.trace_length / 4096 - 1)); + let (local pow38) = pow(trace_generator, 128 * (global_values.trace_length / 128 - 1)); + let (local pow39) = pow(trace_generator, 16384 * (global_values.trace_length / 16384 - 1)); + + // Compute domains. + tempvar domain0 = pow11 - 1; + tempvar domain1 = pow10 - 1; + tempvar domain2 = pow9 - 1; + tempvar domain3 = pow8 - 1; + tempvar domain4 = pow7 - pow29; + tempvar domain5 = pow7 - 1; + tempvar domain6 = pow6 - 1; + tempvar domain7 = pow5 - 1; + tempvar domain8 = pow4 - 1; + tempvar domain9 = pow4 - pow28; + tempvar domain10 = pow4 - pow12; + tempvar domain10 = domain10 * (pow4 - pow13); + tempvar domain10 = domain10 * (pow4 - pow14); + tempvar domain10 = domain10 * (pow4 - pow15); + tempvar domain10 = domain10 * (pow4 - pow16); + tempvar domain10 = domain10 * (pow4 - pow17); + tempvar domain10 = domain10 * (pow4 - pow18); + tempvar domain10 = domain10 * (pow4 - pow19); + tempvar domain10 = domain10 * (pow4 - pow20); + tempvar domain10 = domain10 * (pow4 - pow21); + tempvar domain10 = domain10 * (pow4 - pow22); + tempvar domain10 = domain10 * (pow4 - pow23); + tempvar domain10 = domain10 * (pow4 - pow24); + tempvar domain10 = domain10 * (pow4 - pow25); + tempvar domain10 = domain10 * (pow4 - pow26); + tempvar domain10 = domain10 * (domain8); + tempvar domain11 = pow3 - 1; + tempvar domain12 = pow3 - pow32; + tempvar domain13 = pow3 - pow31; + tempvar domain14 = pow2 - pow27; + tempvar domain15 = pow2 - 1; + tempvar domain16 = pow1 - pow32; + tempvar domain17 = pow1 - pow30; + tempvar domain18 = pow1 - 1; + tempvar domain19 = pow0 - pow32; + tempvar domain20 = pow0 - pow30; + tempvar domain21 = pow0 - 1; + tempvar domain22 = point - pow33; + tempvar domain23 = point - 1; + tempvar domain24 = point - pow34; + tempvar domain25 = point - pow35; + tempvar domain26 = point - pow36; + tempvar domain27 = point - pow37; + tempvar domain28 = point - pow38; + tempvar domain29 = point - pow39; + + // Fetch mask variables. + tempvar column0_row0 = mask_values[0]; + tempvar column0_row1 = mask_values[1]; + tempvar column0_row2 = mask_values[2]; + tempvar column0_row3 = mask_values[3]; + tempvar column0_row4 = mask_values[4]; + tempvar column0_row5 = mask_values[5]; + tempvar column0_row6 = mask_values[6]; + tempvar column0_row7 = mask_values[7]; + tempvar column0_row8 = mask_values[8]; + tempvar column0_row9 = mask_values[9]; + tempvar column0_row10 = mask_values[10]; + tempvar column0_row11 = mask_values[11]; + tempvar column0_row12 = mask_values[12]; + tempvar column0_row13 = mask_values[13]; + tempvar column0_row14 = mask_values[14]; + tempvar column0_row15 = mask_values[15]; + tempvar column1_row0 = mask_values[16]; + tempvar column1_row1 = mask_values[17]; + tempvar column1_row2 = mask_values[18]; + tempvar column1_row4 = mask_values[19]; + tempvar column1_row6 = mask_values[20]; + tempvar column1_row8 = mask_values[21]; + tempvar column1_row10 = mask_values[22]; + tempvar column1_row12 = mask_values[23]; + tempvar column1_row14 = mask_values[24]; + tempvar column1_row16 = mask_values[25]; + tempvar column1_row18 = mask_values[26]; + tempvar column1_row20 = mask_values[27]; + tempvar column1_row22 = mask_values[28]; + tempvar column1_row24 = mask_values[29]; + tempvar column1_row26 = mask_values[30]; + tempvar column1_row28 = mask_values[31]; + tempvar column1_row30 = mask_values[32]; + tempvar column1_row32 = mask_values[33]; + tempvar column1_row33 = mask_values[34]; + tempvar column1_row64 = mask_values[35]; + tempvar column1_row65 = mask_values[36]; + tempvar column1_row88 = mask_values[37]; + tempvar column1_row90 = mask_values[38]; + tempvar column1_row92 = mask_values[39]; + tempvar column1_row94 = mask_values[40]; + tempvar column1_row96 = mask_values[41]; + tempvar column1_row97 = mask_values[42]; + tempvar column1_row120 = mask_values[43]; + tempvar column1_row122 = mask_values[44]; + tempvar column1_row124 = mask_values[45]; + tempvar column1_row126 = mask_values[46]; + tempvar column2_row0 = mask_values[47]; + tempvar column2_row1 = mask_values[48]; + tempvar column3_row0 = mask_values[49]; + tempvar column3_row1 = mask_values[50]; + tempvar column3_row2 = mask_values[51]; + tempvar column3_row3 = mask_values[52]; + tempvar column3_row4 = mask_values[53]; + tempvar column3_row5 = mask_values[54]; + tempvar column3_row8 = mask_values[55]; + tempvar column3_row9 = mask_values[56]; + tempvar column3_row10 = mask_values[57]; + tempvar column3_row11 = mask_values[58]; + tempvar column3_row12 = mask_values[59]; + tempvar column3_row13 = mask_values[60]; + tempvar column3_row16 = mask_values[61]; + tempvar column3_row26 = mask_values[62]; + tempvar column3_row27 = mask_values[63]; + tempvar column3_row42 = mask_values[64]; + tempvar column3_row43 = mask_values[65]; + tempvar column3_row58 = mask_values[66]; + tempvar column3_row74 = mask_values[67]; + tempvar column3_row75 = mask_values[68]; + tempvar column3_row91 = mask_values[69]; + tempvar column3_row122 = mask_values[70]; + tempvar column3_row123 = mask_values[71]; + tempvar column3_row154 = mask_values[72]; + tempvar column3_row202 = mask_values[73]; + tempvar column3_row1034 = mask_values[74]; + tempvar column3_row1035 = mask_values[75]; + tempvar column3_row2058 = mask_values[76]; + tempvar column3_row2059 = mask_values[77]; + tempvar column3_row3082 = mask_values[78]; + tempvar column3_row3083 = mask_values[79]; + tempvar column3_row4106 = mask_values[80]; + tempvar column3_row11274 = mask_values[81]; + tempvar column3_row11275 = mask_values[82]; + tempvar column3_row19466 = mask_values[83]; + tempvar column4_row0 = mask_values[84]; + tempvar column4_row1 = mask_values[85]; + tempvar column4_row2 = mask_values[86]; + tempvar column4_row3 = mask_values[87]; + tempvar column5_row0 = mask_values[88]; + tempvar column5_row1 = mask_values[89]; + tempvar column5_row2 = mask_values[90]; + tempvar column5_row3 = mask_values[91]; + tempvar column5_row4 = mask_values[92]; + tempvar column5_row5 = mask_values[93]; + tempvar column5_row6 = mask_values[94]; + tempvar column5_row7 = mask_values[95]; + tempvar column5_row8 = mask_values[96]; + tempvar column5_row9 = mask_values[97]; + tempvar column5_row11 = mask_values[98]; + tempvar column5_row12 = mask_values[99]; + tempvar column5_row13 = mask_values[100]; + tempvar column5_row28 = mask_values[101]; + tempvar column5_row44 = mask_values[102]; + tempvar column5_row60 = mask_values[103]; + tempvar column5_row76 = mask_values[104]; + tempvar column5_row92 = mask_values[105]; + tempvar column5_row108 = mask_values[106]; + tempvar column5_row124 = mask_values[107]; + tempvar column5_row1539 = mask_values[108]; + tempvar column5_row1547 = mask_values[109]; + tempvar column5_row1571 = mask_values[110]; + tempvar column5_row1579 = mask_values[111]; + tempvar column5_row2011 = mask_values[112]; + tempvar column5_row2019 = mask_values[113]; + tempvar column5_row2041 = mask_values[114]; + tempvar column5_row2045 = mask_values[115]; + tempvar column5_row2047 = mask_values[116]; + tempvar column5_row2049 = mask_values[117]; + tempvar column5_row2051 = mask_values[118]; + tempvar column5_row2053 = mask_values[119]; + tempvar column5_row4089 = mask_values[120]; + tempvar column6_row0 = mask_values[121]; + tempvar column6_row1 = mask_values[122]; + tempvar column6_row2 = mask_values[123]; + tempvar column6_row4 = mask_values[124]; + tempvar column6_row5 = mask_values[125]; + tempvar column6_row6 = mask_values[126]; + tempvar column6_row8 = mask_values[127]; + tempvar column6_row9 = mask_values[128]; + tempvar column6_row10 = mask_values[129]; + tempvar column6_row12 = mask_values[130]; + tempvar column6_row13 = mask_values[131]; + tempvar column6_row14 = mask_values[132]; + tempvar column6_row16 = mask_values[133]; + tempvar column6_row17 = mask_values[134]; + tempvar column6_row21 = mask_values[135]; + tempvar column6_row22 = mask_values[136]; + tempvar column6_row24 = mask_values[137]; + tempvar column6_row25 = mask_values[138]; + tempvar column6_row30 = mask_values[139]; + tempvar column6_row33 = mask_values[140]; + tempvar column6_row37 = mask_values[141]; + tempvar column6_row38 = mask_values[142]; + tempvar column6_row45 = mask_values[143]; + tempvar column6_row46 = mask_values[144]; + tempvar column6_row53 = mask_values[145]; + tempvar column6_row54 = mask_values[146]; + tempvar column6_row62 = mask_values[147]; + tempvar column6_row69 = mask_values[148]; + tempvar column6_row85 = mask_values[149]; + tempvar column6_row101 = mask_values[150]; + tempvar column6_row8169 = mask_values[151]; + tempvar column6_row8174 = mask_values[152]; + tempvar column6_row8177 = mask_values[153]; + tempvar column6_row8185 = mask_values[154]; + tempvar column6_row8190 = mask_values[155]; + tempvar column6_row8198 = mask_values[156]; + tempvar column6_row8214 = mask_values[157]; + tempvar column6_row16325 = mask_values[158]; + tempvar column6_row16333 = mask_values[159]; + tempvar column6_row16357 = mask_values[160]; + tempvar column6_row16361 = mask_values[161]; + tempvar column6_row16366 = mask_values[162]; + tempvar column6_row16373 = mask_values[163]; + tempvar column6_row16377 = mask_values[164]; + tempvar column6_row16382 = mask_values[165]; + tempvar column7_inter1_row0 = mask_values[166]; + tempvar column7_inter1_row1 = mask_values[167]; + tempvar column8_inter1_row0 = mask_values[168]; + tempvar column8_inter1_row1 = mask_values[169]; + tempvar column9_inter1_row0 = mask_values[170]; + tempvar column9_inter1_row1 = mask_values[171]; + tempvar column9_inter1_row2 = mask_values[172]; + tempvar column9_inter1_row5 = mask_values[173]; + + // Compute intermediate values. + tempvar cpu__decode__opcode_rc__bit_0 = column0_row0 - (column0_row1 + column0_row1); + tempvar cpu__decode__opcode_rc__bit_2 = column0_row2 - (column0_row3 + column0_row3); + tempvar cpu__decode__opcode_rc__bit_4 = column0_row4 - (column0_row5 + column0_row5); + tempvar cpu__decode__opcode_rc__bit_3 = column0_row3 - (column0_row4 + column0_row4); + tempvar cpu__decode__flag_op1_base_op0_0 = 1 - (cpu__decode__opcode_rc__bit_2 + cpu__decode__opcode_rc__bit_4 + cpu__decode__opcode_rc__bit_3); + tempvar cpu__decode__opcode_rc__bit_5 = column0_row5 - (column0_row6 + column0_row6); + tempvar cpu__decode__opcode_rc__bit_6 = column0_row6 - (column0_row7 + column0_row7); + tempvar cpu__decode__opcode_rc__bit_9 = column0_row9 - (column0_row10 + column0_row10); + tempvar cpu__decode__flag_res_op1_0 = 1 - (cpu__decode__opcode_rc__bit_5 + cpu__decode__opcode_rc__bit_6 + cpu__decode__opcode_rc__bit_9); + tempvar cpu__decode__opcode_rc__bit_7 = column0_row7 - (column0_row8 + column0_row8); + tempvar cpu__decode__opcode_rc__bit_8 = column0_row8 - (column0_row9 + column0_row9); + tempvar cpu__decode__flag_pc_update_regular_0 = 1 - (cpu__decode__opcode_rc__bit_7 + cpu__decode__opcode_rc__bit_8 + cpu__decode__opcode_rc__bit_9); + tempvar cpu__decode__opcode_rc__bit_12 = column0_row12 - (column0_row13 + column0_row13); + tempvar cpu__decode__opcode_rc__bit_13 = column0_row13 - (column0_row14 + column0_row14); + tempvar cpu__decode__fp_update_regular_0 = 1 - (cpu__decode__opcode_rc__bit_12 + cpu__decode__opcode_rc__bit_13); + tempvar cpu__decode__opcode_rc__bit_1 = column0_row1 - (column0_row2 + column0_row2); + tempvar npc_reg_0 = column3_row0 + cpu__decode__opcode_rc__bit_2 + 1; + tempvar cpu__decode__opcode_rc__bit_10 = column0_row10 - (column0_row11 + column0_row11); + tempvar cpu__decode__opcode_rc__bit_11 = column0_row11 - (column0_row12 + column0_row12); + tempvar cpu__decode__opcode_rc__bit_14 = column0_row14 - (column0_row15 + column0_row15); + tempvar memory__address_diff_0 = column4_row2 - column4_row0; + tempvar rc16__diff_0 = column5_row6 - column5_row2; + tempvar pedersen__hash0__ec_subset_sum__bit_0 = column5_row3 - (column5_row11 + column5_row11); + tempvar pedersen__hash0__ec_subset_sum__bit_neg_0 = 1 - pedersen__hash0__ec_subset_sum__bit_0; + tempvar rc_builtin__value0_0 = column5_row12; + tempvar rc_builtin__value1_0 = rc_builtin__value0_0 * global_values.offset_size + column5_row28; + tempvar rc_builtin__value2_0 = rc_builtin__value1_0 * global_values.offset_size + column5_row44; + tempvar rc_builtin__value3_0 = rc_builtin__value2_0 * global_values.offset_size + column5_row60; + tempvar rc_builtin__value4_0 = rc_builtin__value3_0 * global_values.offset_size + column5_row76; + tempvar rc_builtin__value5_0 = rc_builtin__value4_0 * global_values.offset_size + column5_row92; + tempvar rc_builtin__value6_0 = rc_builtin__value5_0 * global_values.offset_size + column5_row108; + tempvar rc_builtin__value7_0 = rc_builtin__value6_0 * global_values.offset_size + column5_row124; + tempvar ecdsa__signature0__doubling_key__x_squared = column6_row6 * column6_row6; + tempvar ecdsa__signature0__exponentiate_generator__bit_0 = column6_row21 - (column6_row85 + column6_row85); + tempvar ecdsa__signature0__exponentiate_generator__bit_neg_0 = 1 - ecdsa__signature0__exponentiate_generator__bit_0; + tempvar ecdsa__signature0__exponentiate_key__bit_0 = column6_row1 - (column6_row33 + column6_row33); + tempvar ecdsa__signature0__exponentiate_key__bit_neg_0 = 1 - ecdsa__signature0__exponentiate_key__bit_0; + tempvar bitwise__sum_var_0_0 = column1_row0 + column1_row2 * 2 + column1_row4 * 4 + column1_row6 * 8 + column1_row8 * 18446744073709551616 + column1_row10 * 36893488147419103232 + column1_row12 * 73786976294838206464 + column1_row14 * 147573952589676412928; + tempvar bitwise__sum_var_8_0 = column1_row16 * 340282366920938463463374607431768211456 + column1_row18 * 680564733841876926926749214863536422912 + column1_row20 * 1361129467683753853853498429727072845824 + column1_row22 * 2722258935367507707706996859454145691648 + column1_row24 * 6277101735386680763835789423207666416102355444464034512896 + column1_row26 * 12554203470773361527671578846415332832204710888928069025792 + column1_row28 * 25108406941546723055343157692830665664409421777856138051584 + column1_row30 * 50216813883093446110686315385661331328818843555712276103168; + + // Sum constraints. + tempvar total_sum = 0; + + // Constraint: cpu/decode/opcode_rc/bit. + tempvar value = (cpu__decode__opcode_rc__bit_0 * cpu__decode__opcode_rc__bit_0 - cpu__decode__opcode_rc__bit_0) * domain4 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[0] * value; + + // Constraint: cpu/decode/opcode_rc/zero. + tempvar value = (column0_row0) / domain4; + tempvar total_sum = total_sum + constraint_coefficients[1] * value; + + // Constraint: cpu/decode/opcode_rc_input. + tempvar value = (column3_row1 - (((column0_row0 * global_values.offset_size + column5_row4) * global_values.offset_size + column5_row8) * global_values.offset_size + column5_row0)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[2] * value; + + // Constraint: cpu/decode/flag_op1_base_op0_bit. + tempvar value = (cpu__decode__flag_op1_base_op0_0 * cpu__decode__flag_op1_base_op0_0 - cpu__decode__flag_op1_base_op0_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[3] * value; + + // Constraint: cpu/decode/flag_res_op1_bit. + tempvar value = (cpu__decode__flag_res_op1_0 * cpu__decode__flag_res_op1_0 - cpu__decode__flag_res_op1_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[4] * value; + + // Constraint: cpu/decode/flag_pc_update_regular_bit. + tempvar value = (cpu__decode__flag_pc_update_regular_0 * cpu__decode__flag_pc_update_regular_0 - cpu__decode__flag_pc_update_regular_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[5] * value; + + // Constraint: cpu/decode/fp_update_regular_bit. + tempvar value = (cpu__decode__fp_update_regular_0 * cpu__decode__fp_update_regular_0 - cpu__decode__fp_update_regular_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[6] * value; + + // Constraint: cpu/operands/mem_dst_addr. + tempvar value = (column3_row8 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_0 * column6_row8 + (1 - cpu__decode__opcode_rc__bit_0) * column6_row0 + column5_row0)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[7] * value; + + // Constraint: cpu/operands/mem0_addr. + tempvar value = (column3_row4 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_1 * column6_row8 + (1 - cpu__decode__opcode_rc__bit_1) * column6_row0 + column5_row8)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[8] * value; + + // Constraint: cpu/operands/mem1_addr. + tempvar value = (column3_row12 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_2 * column3_row0 + cpu__decode__opcode_rc__bit_4 * column6_row0 + cpu__decode__opcode_rc__bit_3 * column6_row8 + cpu__decode__flag_op1_base_op0_0 * column3_row5 + column5_row4)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[9] * value; + + // Constraint: cpu/operands/ops_mul. + tempvar value = (column6_row4 - column3_row5 * column3_row13) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[10] * value; + + // Constraint: cpu/operands/res. + tempvar value = ((1 - cpu__decode__opcode_rc__bit_9) * column6_row12 - (cpu__decode__opcode_rc__bit_5 * (column3_row5 + column3_row13) + cpu__decode__opcode_rc__bit_6 * column6_row4 + cpu__decode__flag_res_op1_0 * column3_row13)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[11] * value; + + // Constraint: cpu/update_registers/update_pc/tmp0. + tempvar value = (column6_row2 - cpu__decode__opcode_rc__bit_9 * column3_row9) * domain22 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[12] * value; + + // Constraint: cpu/update_registers/update_pc/tmp1. + tempvar value = (column6_row10 - column6_row2 * column6_row12) * domain22 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[13] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_negative. + tempvar value = ((1 - cpu__decode__opcode_rc__bit_9) * column3_row16 + column6_row2 * (column3_row16 - (column3_row0 + column3_row13)) - (cpu__decode__flag_pc_update_regular_0 * npc_reg_0 + cpu__decode__opcode_rc__bit_7 * column6_row12 + cpu__decode__opcode_rc__bit_8 * (column3_row0 + column6_row12))) * domain22 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[14] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_positive. + tempvar value = ((column6_row10 - cpu__decode__opcode_rc__bit_9) * (column3_row16 - npc_reg_0)) * domain22 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[15] * value; + + // Constraint: cpu/update_registers/update_ap/ap_update. + tempvar value = (column6_row16 - (column6_row0 + cpu__decode__opcode_rc__bit_10 * column6_row12 + cpu__decode__opcode_rc__bit_11 + cpu__decode__opcode_rc__bit_12 * 2)) * domain22 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[16] * value; + + // Constraint: cpu/update_registers/update_fp/fp_update. + tempvar value = (column6_row24 - (cpu__decode__fp_update_regular_0 * column6_row8 + cpu__decode__opcode_rc__bit_13 * column3_row9 + cpu__decode__opcode_rc__bit_12 * (column6_row0 + 2))) * domain22 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[17] * value; + + // Constraint: cpu/opcodes/call/push_fp. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column3_row9 - column6_row8)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[18] * value; + + // Constraint: cpu/opcodes/call/push_pc. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column3_row5 - (column3_row0 + cpu__decode__opcode_rc__bit_2 + 1))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[19] * value; + + // Constraint: cpu/opcodes/call/off0. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column5_row0 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[20] * value; + + // Constraint: cpu/opcodes/call/off1. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column5_row8 - (global_values.half_offset_size + 1))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[21] * value; + + // Constraint: cpu/opcodes/call/flags. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (cpu__decode__opcode_rc__bit_12 + cpu__decode__opcode_rc__bit_12 + 1 + 1 - (cpu__decode__opcode_rc__bit_0 + cpu__decode__opcode_rc__bit_1 + 4))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[22] * value; + + // Constraint: cpu/opcodes/ret/off0. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (column5_row0 + 2 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[23] * value; + + // Constraint: cpu/opcodes/ret/off2. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (column5_row4 + 1 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[24] * value; + + // Constraint: cpu/opcodes/ret/flags. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (cpu__decode__opcode_rc__bit_7 + cpu__decode__opcode_rc__bit_0 + cpu__decode__opcode_rc__bit_3 + cpu__decode__flag_res_op1_0 - 4)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[25] * value; + + // Constraint: cpu/opcodes/assert_eq/assert_eq. + tempvar value = (cpu__decode__opcode_rc__bit_14 * (column3_row9 - column6_row12)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[26] * value; + + // Constraint: initial_ap. + tempvar value = (column6_row0 - global_values.initial_ap) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[27] * value; + + // Constraint: initial_fp. + tempvar value = (column6_row8 - global_values.initial_ap) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[28] * value; + + // Constraint: initial_pc. + tempvar value = (column3_row0 - global_values.initial_pc) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[29] * value; + + // Constraint: final_ap. + tempvar value = (column6_row0 - global_values.final_ap) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[30] * value; + + // Constraint: final_fp. + tempvar value = (column6_row8 - global_values.initial_ap) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[31] * value; + + // Constraint: final_pc. + tempvar value = (column3_row0 - global_values.final_pc) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[32] * value; + + // Constraint: memory/multi_column_perm/perm/init0. + tempvar value = ((global_values.memory__multi_column_perm__perm__interaction_elm - (column4_row0 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column4_row1)) * column9_inter1_row0 + column3_row0 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column3_row1 - global_values.memory__multi_column_perm__perm__interaction_elm) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[33] * value; + + // Constraint: memory/multi_column_perm/perm/step0. + tempvar value = ((global_values.memory__multi_column_perm__perm__interaction_elm - (column4_row2 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column4_row3)) * column9_inter1_row2 - (global_values.memory__multi_column_perm__perm__interaction_elm - (column3_row2 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column3_row3)) * column9_inter1_row0) * domain24 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[34] * value; + + // Constraint: memory/multi_column_perm/perm/last. + tempvar value = (column9_inter1_row0 - global_values.memory__multi_column_perm__perm__public_memory_prod) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[35] * value; + + // Constraint: memory/diff_is_bit. + tempvar value = (memory__address_diff_0 * memory__address_diff_0 - memory__address_diff_0) * domain24 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[36] * value; + + // Constraint: memory/is_func. + tempvar value = ((memory__address_diff_0 - 1) * (column4_row1 - column4_row3)) * domain24 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[37] * value; + + // Constraint: memory/initial_addr. + tempvar value = (column4_row0 - 1) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[38] * value; + + // Constraint: public_memory_addr_zero. + tempvar value = (column3_row2) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[39] * value; + + // Constraint: public_memory_value_zero. + tempvar value = (column3_row3) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[40] * value; + + // Constraint: rc16/perm/init0. + tempvar value = ((global_values.rc16__perm__interaction_elm - column5_row2) * column9_inter1_row1 + column5_row0 - global_values.rc16__perm__interaction_elm) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[41] * value; + + // Constraint: rc16/perm/step0. + tempvar value = ((global_values.rc16__perm__interaction_elm - column5_row6) * column9_inter1_row5 - (global_values.rc16__perm__interaction_elm - column5_row4) * column9_inter1_row1) * domain25 / domain2; + tempvar total_sum = total_sum + constraint_coefficients[42] * value; + + // Constraint: rc16/perm/last. + tempvar value = (column9_inter1_row1 - global_values.rc16__perm__public_memory_prod) / domain25; + tempvar total_sum = total_sum + constraint_coefficients[43] * value; + + // Constraint: rc16/diff_is_bit. + tempvar value = (rc16__diff_0 * rc16__diff_0 - rc16__diff_0) * domain25 / domain2; + tempvar total_sum = total_sum + constraint_coefficients[44] * value; + + // Constraint: rc16/minimum. + tempvar value = (column5_row2 - global_values.rc_min) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[45] * value; + + // Constraint: rc16/maximum. + tempvar value = (column5_row2 - global_values.rc_max) / domain25; + tempvar total_sum = total_sum + constraint_coefficients[46] * value; + + // Constraint: diluted_check/permutation/init0. + tempvar value = ((global_values.diluted_check__permutation__interaction_elm - column2_row0) * column8_inter1_row0 + column1_row0 - global_values.diluted_check__permutation__interaction_elm) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[47] * value; + + // Constraint: diluted_check/permutation/step0. + tempvar value = ((global_values.diluted_check__permutation__interaction_elm - column2_row1) * column8_inter1_row1 - (global_values.diluted_check__permutation__interaction_elm - column1_row1) * column8_inter1_row0) * domain26 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[48] * value; + + // Constraint: diluted_check/permutation/last. + tempvar value = (column8_inter1_row0 - global_values.diluted_check__permutation__public_memory_prod) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[49] * value; + + // Constraint: diluted_check/init. + tempvar value = (column7_inter1_row0 - 1) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[50] * value; + + // Constraint: diluted_check/first_element. + tempvar value = (column2_row0 - global_values.diluted_check__first_elm) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[51] * value; + + // Constraint: diluted_check/step. + tempvar value = (column7_inter1_row1 - (column7_inter1_row0 * (1 + global_values.diluted_check__interaction_z * (column2_row1 - column2_row0)) + global_values.diluted_check__interaction_alpha * (column2_row1 - column2_row0) * (column2_row1 - column2_row0))) * domain26 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[52] * value; + + // Constraint: diluted_check/last. + tempvar value = (column7_inter1_row0 - global_values.diluted_check__final_cum_val) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[53] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/last_one_is_zero. + tempvar value = (column6_row45 * (column5_row3 - (column5_row11 + column5_row11))) / domain11; + tempvar total_sum = total_sum + constraint_coefficients[54] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + tempvar value = (column6_row45 * (column5_row11 - 3138550867693340381917894711603833208051177722232017256448 * column5_row1539)) / domain11; + tempvar total_sum = total_sum + constraint_coefficients[55] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit192. + tempvar value = (column6_row45 - column5_row2047 * (column5_row1539 - (column5_row1547 + column5_row1547))) / domain11; + tempvar total_sum = total_sum + constraint_coefficients[56] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + tempvar value = (column5_row2047 * (column5_row1547 - 8 * column5_row1571)) / domain11; + tempvar total_sum = total_sum + constraint_coefficients[57] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit196. + tempvar value = (column5_row2047 - (column5_row2011 - (column5_row2019 + column5_row2019)) * (column5_row1571 - (column5_row1579 + column5_row1579))) / domain11; + tempvar total_sum = total_sum + constraint_coefficients[58] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + tempvar value = ((column5_row2011 - (column5_row2019 + column5_row2019)) * (column5_row1579 - 18014398509481984 * column5_row2011)) / domain11; + tempvar total_sum = total_sum + constraint_coefficients[59] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/booleanity_test. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (pedersen__hash0__ec_subset_sum__bit_0 - 1)) * domain12 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[60] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_extraction_end. + tempvar value = (column5_row3) / domain13; + tempvar total_sum = total_sum + constraint_coefficients[61] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/zeros_tail. + tempvar value = (column5_row3) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[62] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/slope. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (column5_row5 - global_values.pedersen__points__y) - column5_row7 * (column5_row1 - global_values.pedersen__points__x)) * domain12 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[63] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/x. + tempvar value = (column5_row7 * column5_row7 - pedersen__hash0__ec_subset_sum__bit_0 * (column5_row1 + global_values.pedersen__points__x + column5_row9)) * domain12 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[64] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/y. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (column5_row5 + column5_row13) - column5_row7 * (column5_row1 - column5_row9)) * domain12 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[65] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/x. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_neg_0 * (column5_row9 - column5_row1)) * domain12 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[66] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/y. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_neg_0 * (column5_row13 - column5_row5)) * domain12 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[67] * value; + + // Constraint: pedersen/hash0/copy_point/x. + tempvar value = (column5_row2049 - column5_row2041) * domain14 / domain11; + tempvar total_sum = total_sum + constraint_coefficients[68] * value; + + // Constraint: pedersen/hash0/copy_point/y. + tempvar value = (column5_row2053 - column5_row2045) * domain14 / domain11; + tempvar total_sum = total_sum + constraint_coefficients[69] * value; + + // Constraint: pedersen/hash0/init/x. + tempvar value = (column5_row1 - global_values.pedersen__shift_point.x) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[70] * value; + + // Constraint: pedersen/hash0/init/y. + tempvar value = (column5_row5 - global_values.pedersen__shift_point.y) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[71] * value; + + // Constraint: pedersen/input0_value0. + tempvar value = (column3_row11 - column5_row3) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[72] * value; + + // Constraint: pedersen/input0_addr. + tempvar value = (column3_row4106 - (column3_row1034 + 1)) * domain27 / domain15; + tempvar total_sum = total_sum + constraint_coefficients[73] * value; + + // Constraint: pedersen/init_addr. + tempvar value = (column3_row10 - global_values.initial_pedersen_addr) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[74] * value; + + // Constraint: pedersen/input1_value0. + tempvar value = (column3_row2059 - column5_row2051) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[75] * value; + + // Constraint: pedersen/input1_addr. + tempvar value = (column3_row2058 - (column3_row10 + 1)) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[76] * value; + + // Constraint: pedersen/output_value0. + tempvar value = (column3_row1035 - column5_row4089) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[77] * value; + + // Constraint: pedersen/output_addr. + tempvar value = (column3_row1034 - (column3_row2058 + 1)) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[78] * value; + + // Constraint: rc_builtin/value. + tempvar value = (rc_builtin__value7_0 - column3_row75) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[79] * value; + + // Constraint: rc_builtin/addr_step. + tempvar value = (column3_row202 - (column3_row74 + 1)) * domain28 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[80] * value; + + // Constraint: rc_builtin/init_addr. + tempvar value = (column3_row74 - global_values.initial_rc_addr) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[81] * value; + + // Constraint: ecdsa/signature0/doubling_key/slope. + tempvar value = (ecdsa__signature0__doubling_key__x_squared + ecdsa__signature0__doubling_key__x_squared + ecdsa__signature0__doubling_key__x_squared + global_values.ecdsa__sig_config.alpha - (column6_row22 + column6_row22) * column6_row17) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[82] * value; + + // Constraint: ecdsa/signature0/doubling_key/x. + tempvar value = (column6_row17 * column6_row17 - (column6_row6 + column6_row6 + column6_row38)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[83] * value; + + // Constraint: ecdsa/signature0/doubling_key/y. + tempvar value = (column6_row22 + column6_row54 - column6_row17 * (column6_row6 - column6_row38)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[84] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/booleanity_test. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (ecdsa__signature0__exponentiate_generator__bit_0 - 1)) * domain19 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[85] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/bit_extraction_end. + tempvar value = (column6_row21) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[86] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/zeros_tail. + tempvar value = (column6_row21) / domain19; + tempvar total_sum = total_sum + constraint_coefficients[87] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/slope. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (column6_row37 - global_values.ecdsa__generator_points__y) - column6_row53 * (column6_row5 - global_values.ecdsa__generator_points__x)) * domain19 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[88] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/x. + tempvar value = (column6_row53 * column6_row53 - ecdsa__signature0__exponentiate_generator__bit_0 * (column6_row5 + global_values.ecdsa__generator_points__x + column6_row69)) * domain19 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[89] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/y. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (column6_row37 + column6_row101) - column6_row53 * (column6_row5 - column6_row69)) * domain19 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[90] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/x_diff_inv. + tempvar value = (column6_row13 * (column6_row5 - global_values.ecdsa__generator_points__x) - 1) * domain19 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[91] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/copy_point/x. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_neg_0 * (column6_row69 - column6_row5)) * domain19 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[92] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/copy_point/y. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_neg_0 * (column6_row101 - column6_row37)) * domain19 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[93] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/booleanity_test. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (ecdsa__signature0__exponentiate_key__bit_0 - 1)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[94] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/bit_extraction_end. + tempvar value = (column6_row1) / domain17; + tempvar total_sum = total_sum + constraint_coefficients[95] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/zeros_tail. + tempvar value = (column6_row1) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[96] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/slope. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (column6_row30 - column6_row22) - column6_row9 * (column6_row14 - column6_row6)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[97] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/x. + tempvar value = (column6_row9 * column6_row9 - ecdsa__signature0__exponentiate_key__bit_0 * (column6_row14 + column6_row6 + column6_row46)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[98] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/y. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (column6_row30 + column6_row62) - column6_row9 * (column6_row14 - column6_row46)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[99] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/x_diff_inv. + tempvar value = (column6_row25 * (column6_row14 - column6_row6) - 1) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[100] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/copy_point/x. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_neg_0 * (column6_row46 - column6_row14)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[101] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/copy_point/y. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_neg_0 * (column6_row62 - column6_row30)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[102] * value; + + // Constraint: ecdsa/signature0/init_gen/x. + tempvar value = (column6_row5 - global_values.ecdsa__sig_config.shift_point.x) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[103] * value; + + // Constraint: ecdsa/signature0/init_gen/y. + tempvar value = (column6_row37 + global_values.ecdsa__sig_config.shift_point.y) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[104] * value; + + // Constraint: ecdsa/signature0/init_key/x. + tempvar value = (column6_row14 - global_values.ecdsa__sig_config.shift_point.x) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[105] * value; + + // Constraint: ecdsa/signature0/init_key/y. + tempvar value = (column6_row30 - global_values.ecdsa__sig_config.shift_point.y) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[106] * value; + + // Constraint: ecdsa/signature0/add_results/slope. + tempvar value = (column6_row16357 - (column6_row8190 + column6_row16373 * (column6_row16325 - column6_row8174))) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[107] * value; + + // Constraint: ecdsa/signature0/add_results/x. + tempvar value = (column6_row16373 * column6_row16373 - (column6_row16325 + column6_row8174 + column6_row8198)) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[108] * value; + + // Constraint: ecdsa/signature0/add_results/y. + tempvar value = (column6_row16357 + column6_row8214 - column6_row16373 * (column6_row16325 - column6_row8198)) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[109] * value; + + // Constraint: ecdsa/signature0/add_results/x_diff_inv. + tempvar value = (column6_row16333 * (column6_row16325 - column6_row8174) - 1) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[110] * value; + + // Constraint: ecdsa/signature0/extract_r/slope. + tempvar value = (column6_row16382 + global_values.ecdsa__sig_config.shift_point.y - column6_row8169 * (column6_row16366 - global_values.ecdsa__sig_config.shift_point.x)) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[111] * value; + + // Constraint: ecdsa/signature0/extract_r/x. + tempvar value = (column6_row8169 * column6_row8169 - (column6_row16366 + global_values.ecdsa__sig_config.shift_point.x + column6_row1)) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[112] * value; + + // Constraint: ecdsa/signature0/extract_r/x_diff_inv. + tempvar value = (column6_row16361 * (column6_row16366 - global_values.ecdsa__sig_config.shift_point.x) - 1) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[113] * value; + + // Constraint: ecdsa/signature0/z_nonzero. + tempvar value = (column6_row21 * column6_row8185 - 1) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[114] * value; + + // Constraint: ecdsa/signature0/r_and_w_nonzero. + tempvar value = (column6_row1 * column6_row8177 - 1) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[115] * value; + + // Constraint: ecdsa/signature0/q_on_curve/x_squared. + tempvar value = (column6_row16377 - column6_row6 * column6_row6) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[116] * value; + + // Constraint: ecdsa/signature0/q_on_curve/on_curve. + tempvar value = (column6_row22 * column6_row22 - (column6_row6 * column6_row16377 + global_values.ecdsa__sig_config.alpha * column6_row6 + global_values.ecdsa__sig_config.beta)) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[117] * value; + + // Constraint: ecdsa/init_addr. + tempvar value = (column3_row3082 - global_values.initial_ecdsa_addr) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[118] * value; + + // Constraint: ecdsa/message_addr. + tempvar value = (column3_row11274 - (column3_row3082 + 1)) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[119] * value; + + // Constraint: ecdsa/pubkey_addr. + tempvar value = (column3_row19466 - (column3_row11274 + 1)) * domain29 / domain21; + tempvar total_sum = total_sum + constraint_coefficients[120] * value; + + // Constraint: ecdsa/message_value0. + tempvar value = (column3_row11275 - column6_row21) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[121] * value; + + // Constraint: ecdsa/pubkey_value0. + tempvar value = (column3_row3083 - column6_row6) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[122] * value; + + // Constraint: bitwise/init_var_pool_addr. + tempvar value = (column3_row26 - global_values.initial_bitwise_addr) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[123] * value; + + // Constraint: bitwise/step_var_pool_addr. + tempvar value = (column3_row58 - (column3_row26 + 1)) * domain9 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[124] * value; + + // Constraint: bitwise/x_or_y_addr. + tempvar value = (column3_row42 - (column3_row122 + 1)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[125] * value; + + // Constraint: bitwise/next_var_pool_addr. + tempvar value = (column3_row154 - (column3_row42 + 1)) * domain28 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[126] * value; + + // Constraint: bitwise/partition. + tempvar value = (bitwise__sum_var_0_0 + bitwise__sum_var_8_0 - column3_row27) / domain6; + tempvar total_sum = total_sum + constraint_coefficients[127] * value; + + // Constraint: bitwise/or_is_and_plus_xor. + tempvar value = (column3_row43 - (column3_row91 + column3_row123)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[128] * value; + + // Constraint: bitwise/addition_is_xor_with_and. + tempvar value = (column1_row0 + column1_row32 - (column1_row96 + column1_row64 + column1_row64)) / domain10; + tempvar total_sum = total_sum + constraint_coefficients[129] * value; + + // Constraint: bitwise/unique_unpacking192. + tempvar value = ((column1_row88 + column1_row120) * 16 - column1_row1) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[130] * value; + + // Constraint: bitwise/unique_unpacking193. + tempvar value = ((column1_row90 + column1_row122) * 16 - column1_row65) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[131] * value; + + // Constraint: bitwise/unique_unpacking194. + tempvar value = ((column1_row92 + column1_row124) * 16 - column1_row33) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[132] * value; + + // Constraint: bitwise/unique_unpacking195. + tempvar value = ((column1_row94 + column1_row126) * 256 - column1_row97) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[133] * value; + + return (res=total_sum); +} + +func eval_oods_polynomial{range_check_ptr}( + self: felt*, + column_values: felt*, + oods_values: felt*, + constraint_coefficients: felt*, + point: felt, + oods_point: felt, + trace_generator: felt, + global_values: OodsGlobalValues*, +) -> (res: felt) { + alloc_locals; + + // Compute powers. + let (local pow0) = pow(trace_generator, 0); + let (local pow1) = pow(trace_generator, 1); + local pow2 = pow1 * pow1; + local pow3 = pow1 * pow2; + local pow4 = pow1 * pow3; + local pow5 = pow1 * pow4; + local pow6 = pow1 * pow5; + local pow7 = pow1 * pow6; + local pow8 = pow1 * pow7; + local pow9 = pow1 * pow8; + local pow10 = pow1 * pow9; + local pow11 = pow1 * pow10; + local pow12 = pow1 * pow11; + local pow13 = pow1 * pow12; + local pow14 = pow1 * pow13; + local pow15 = pow1 * pow14; + local pow16 = pow1 * pow15; + local pow17 = pow1 * pow16; + local pow18 = pow1 * pow17; + local pow19 = pow2 * pow18; + local pow20 = pow1 * pow19; + local pow21 = pow1 * pow20; + local pow22 = pow2 * pow21; + local pow23 = pow1 * pow22; + local pow24 = pow1 * pow23; + local pow25 = pow1 * pow24; + local pow26 = pow1 * pow25; + local pow27 = pow2 * pow26; + local pow28 = pow2 * pow27; + local pow29 = pow1 * pow28; + local pow30 = pow4 * pow29; + local pow31 = pow1 * pow30; + local pow32 = pow4 * pow31; + local pow33 = pow1 * pow32; + local pow34 = pow1 * pow33; + local pow35 = pow1 * pow34; + local pow36 = pow1 * pow35; + local pow37 = pow7 * pow36; + local pow38 = pow1 * pow37; + local pow39 = pow4 * pow38; + local pow40 = pow2 * pow39; + local pow41 = pow2 * pow40; + local pow42 = pow2 * pow41; + local pow43 = pow1 * pow42; + local pow44 = pow4 * pow43; + local pow45 = pow5 * pow44; + local pow46 = pow1 * pow45; + local pow47 = pow1 * pow46; + local pow48 = pow9 * pow47; + local pow49 = pow3 * pow48; + local pow50 = pow2 * pow49; + local pow51 = pow1 * pow50; + local pow52 = pow1 * pow51; + local pow53 = pow2 * pow52; + local pow54 = pow2 * pow53; + local pow55 = pow1 * pow54; + local pow56 = pow4 * pow55; + local pow57 = pow7 * pow56; + local pow58 = pow12 * pow57; + local pow59 = pow2 * pow58; + local pow60 = pow1 * pow59; + local pow61 = pow1 * pow60; + local pow62 = pow2 * pow61; + local pow63 = pow26 * pow62; + local pow64 = pow47 * pow62; + let (local pow65) = pow(trace_generator, 1034); + local pow66 = pow1 * pow65; + let (local pow67) = pow(trace_generator, 1539); + local pow68 = pow8 * pow67; + local pow69 = pow22 * pow68; + local pow70 = pow8 * pow69; + let (local pow71) = pow(trace_generator, 2011); + local pow72 = pow8 * pow71; + local pow73 = pow21 * pow72; + local pow74 = pow4 * pow73; + local pow75 = pow2 * pow74; + local pow76 = pow2 * pow75; + local pow77 = pow2 * pow76; + local pow78 = pow2 * pow77; + local pow79 = pow5 * pow78; + local pow80 = pow1 * pow79; + local pow81 = pow66 * pow75; + local pow82 = pow1 * pow81; + let (local pow83) = pow(trace_generator, 4089); + local pow84 = pow17 * pow83; + let (local pow85) = pow(trace_generator, 8169); + local pow86 = pow5 * pow85; + local pow87 = pow3 * pow86; + local pow88 = pow8 * pow87; + local pow89 = pow5 * pow88; + local pow90 = pow8 * pow89; + local pow91 = pow16 * pow90; + let (local pow92) = pow(trace_generator, 11274); + local pow93 = pow1 * pow92; + let (local pow94) = pow(trace_generator, 16325); + local pow95 = pow8 * pow94; + local pow96 = pow22 * pow95; + local pow97 = pow4 * pow96; + local pow98 = pow5 * pow97; + local pow99 = pow7 * pow98; + local pow100 = pow4 * pow99; + local pow101 = pow5 * pow100; + let (local pow102) = pow(trace_generator, 19466); + + // Fetch columns. + tempvar column0 = column_values[0]; + tempvar column1 = column_values[1]; + tempvar column2 = column_values[2]; + tempvar column3 = column_values[3]; + tempvar column4 = column_values[4]; + tempvar column5 = column_values[5]; + tempvar column6 = column_values[6]; + tempvar column7 = column_values[7]; + tempvar column8 = column_values[8]; + tempvar column9 = column_values[9]; + + // Sum the OODS constraints on the trace polynomials. + tempvar total_sum = 0; + + tempvar value = (column0 - oods_values[0]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[0] * value; + + tempvar value = (column0 - oods_values[1]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[1] * value; + + tempvar value = (column0 - oods_values[2]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[2] * value; + + tempvar value = (column0 - oods_values[3]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[3] * value; + + tempvar value = (column0 - oods_values[4]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[4] * value; + + tempvar value = (column0 - oods_values[5]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[5] * value; + + tempvar value = (column0 - oods_values[6]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[6] * value; + + tempvar value = (column0 - oods_values[7]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[7] * value; + + tempvar value = (column0 - oods_values[8]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[8] * value; + + tempvar value = (column0 - oods_values[9]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[9] * value; + + tempvar value = (column0 - oods_values[10]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[10] * value; + + tempvar value = (column0 - oods_values[11]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[11] * value; + + tempvar value = (column0 - oods_values[12]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[12] * value; + + tempvar value = (column0 - oods_values[13]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[13] * value; + + tempvar value = (column0 - oods_values[14]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[14] * value; + + tempvar value = (column0 - oods_values[15]) / (point - pow15 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[15] * value; + + tempvar value = (column1 - oods_values[16]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[16] * value; + + tempvar value = (column1 - oods_values[17]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[17] * value; + + tempvar value = (column1 - oods_values[18]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[18] * value; + + tempvar value = (column1 - oods_values[19]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[19] * value; + + tempvar value = (column1 - oods_values[20]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[20] * value; + + tempvar value = (column1 - oods_values[21]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[21] * value; + + tempvar value = (column1 - oods_values[22]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[22] * value; + + tempvar value = (column1 - oods_values[23]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[23] * value; + + tempvar value = (column1 - oods_values[24]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[24] * value; + + tempvar value = (column1 - oods_values[25]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[25] * value; + + tempvar value = (column1 - oods_values[26]) / (point - pow18 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[26] * value; + + tempvar value = (column1 - oods_values[27]) / (point - pow19 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[27] * value; + + tempvar value = (column1 - oods_values[28]) / (point - pow21 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[28] * value; + + tempvar value = (column1 - oods_values[29]) / (point - pow22 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[29] * value; + + tempvar value = (column1 - oods_values[30]) / (point - pow24 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[30] * value; + + tempvar value = (column1 - oods_values[31]) / (point - pow26 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[31] * value; + + tempvar value = (column1 - oods_values[32]) / (point - pow27 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[32] * value; + + tempvar value = (column1 - oods_values[33]) / (point - pow28 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[33] * value; + + tempvar value = (column1 - oods_values[34]) / (point - pow29 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[34] * value; + + tempvar value = (column1 - oods_values[35]) / (point - pow42 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[35] * value; + + tempvar value = (column1 - oods_values[36]) / (point - pow43 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[36] * value; + + tempvar value = (column1 - oods_values[37]) / (point - pow49 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[37] * value; + + tempvar value = (column1 - oods_values[38]) / (point - pow50 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[38] * value; + + tempvar value = (column1 - oods_values[39]) / (point - pow52 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[39] * value; + + tempvar value = (column1 - oods_values[40]) / (point - pow53 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[40] * value; + + tempvar value = (column1 - oods_values[41]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[41] * value; + + tempvar value = (column1 - oods_values[42]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[42] * value; + + tempvar value = (column1 - oods_values[43]) / (point - pow58 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[43] * value; + + tempvar value = (column1 - oods_values[44]) / (point - pow59 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[44] * value; + + tempvar value = (column1 - oods_values[45]) / (point - pow61 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[45] * value; + + tempvar value = (column1 - oods_values[46]) / (point - pow62 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[46] * value; + + tempvar value = (column2 - oods_values[47]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[47] * value; + + tempvar value = (column2 - oods_values[48]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[48] * value; + + tempvar value = (column3 - oods_values[49]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[49] * value; + + tempvar value = (column3 - oods_values[50]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[50] * value; + + tempvar value = (column3 - oods_values[51]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[51] * value; + + tempvar value = (column3 - oods_values[52]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[52] * value; + + tempvar value = (column3 - oods_values[53]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[53] * value; + + tempvar value = (column3 - oods_values[54]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[54] * value; + + tempvar value = (column3 - oods_values[55]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[55] * value; + + tempvar value = (column3 - oods_values[56]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[56] * value; + + tempvar value = (column3 - oods_values[57]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[57] * value; + + tempvar value = (column3 - oods_values[58]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[58] * value; + + tempvar value = (column3 - oods_values[59]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[59] * value; + + tempvar value = (column3 - oods_values[60]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[60] * value; + + tempvar value = (column3 - oods_values[61]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[61] * value; + + tempvar value = (column3 - oods_values[62]) / (point - pow24 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[62] * value; + + tempvar value = (column3 - oods_values[63]) / (point - pow25 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[63] * value; + + tempvar value = (column3 - oods_values[64]) / (point - pow32 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[64] * value; + + tempvar value = (column3 - oods_values[65]) / (point - pow33 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[65] * value; + + tempvar value = (column3 - oods_values[66]) / (point - pow39 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[66] * value; + + tempvar value = (column3 - oods_values[67]) / (point - pow45 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[67] * value; + + tempvar value = (column3 - oods_values[68]) / (point - pow46 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[68] * value; + + tempvar value = (column3 - oods_values[69]) / (point - pow51 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[69] * value; + + tempvar value = (column3 - oods_values[70]) / (point - pow59 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[70] * value; + + tempvar value = (column3 - oods_values[71]) / (point - pow60 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[71] * value; + + tempvar value = (column3 - oods_values[72]) / (point - pow63 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[72] * value; + + tempvar value = (column3 - oods_values[73]) / (point - pow64 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[73] * value; + + tempvar value = (column3 - oods_values[74]) / (point - pow65 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[74] * value; + + tempvar value = (column3 - oods_values[75]) / (point - pow66 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[75] * value; + + tempvar value = (column3 - oods_values[76]) / (point - pow79 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[76] * value; + + tempvar value = (column3 - oods_values[77]) / (point - pow80 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[77] * value; + + tempvar value = (column3 - oods_values[78]) / (point - pow81 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[78] * value; + + tempvar value = (column3 - oods_values[79]) / (point - pow82 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[79] * value; + + tempvar value = (column3 - oods_values[80]) / (point - pow84 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[80] * value; + + tempvar value = (column3 - oods_values[81]) / (point - pow92 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[81] * value; + + tempvar value = (column3 - oods_values[82]) / (point - pow93 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[82] * value; + + tempvar value = (column3 - oods_values[83]) / (point - pow102 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[83] * value; + + tempvar value = (column4 - oods_values[84]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[84] * value; + + tempvar value = (column4 - oods_values[85]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[85] * value; + + tempvar value = (column4 - oods_values[86]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[86] * value; + + tempvar value = (column4 - oods_values[87]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[87] * value; + + tempvar value = (column5 - oods_values[88]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[88] * value; + + tempvar value = (column5 - oods_values[89]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[89] * value; + + tempvar value = (column5 - oods_values[90]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[90] * value; + + tempvar value = (column5 - oods_values[91]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[91] * value; + + tempvar value = (column5 - oods_values[92]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[92] * value; + + tempvar value = (column5 - oods_values[93]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[93] * value; + + tempvar value = (column5 - oods_values[94]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[94] * value; + + tempvar value = (column5 - oods_values[95]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[95] * value; + + tempvar value = (column5 - oods_values[96]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[96] * value; + + tempvar value = (column5 - oods_values[97]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[97] * value; + + tempvar value = (column5 - oods_values[98]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[98] * value; + + tempvar value = (column5 - oods_values[99]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[99] * value; + + tempvar value = (column5 - oods_values[100]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[100] * value; + + tempvar value = (column5 - oods_values[101]) / (point - pow26 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[101] * value; + + tempvar value = (column5 - oods_values[102]) / (point - pow34 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[102] * value; + + tempvar value = (column5 - oods_values[103]) / (point - pow40 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[103] * value; + + tempvar value = (column5 - oods_values[104]) / (point - pow47 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[104] * value; + + tempvar value = (column5 - oods_values[105]) / (point - pow52 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[105] * value; + + tempvar value = (column5 - oods_values[106]) / (point - pow57 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[106] * value; + + tempvar value = (column5 - oods_values[107]) / (point - pow61 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[107] * value; + + tempvar value = (column5 - oods_values[108]) / (point - pow67 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[108] * value; + + tempvar value = (column5 - oods_values[109]) / (point - pow68 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[109] * value; + + tempvar value = (column5 - oods_values[110]) / (point - pow69 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[110] * value; + + tempvar value = (column5 - oods_values[111]) / (point - pow70 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[111] * value; + + tempvar value = (column5 - oods_values[112]) / (point - pow71 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[112] * value; + + tempvar value = (column5 - oods_values[113]) / (point - pow72 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[113] * value; + + tempvar value = (column5 - oods_values[114]) / (point - pow73 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[114] * value; + + tempvar value = (column5 - oods_values[115]) / (point - pow74 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[115] * value; + + tempvar value = (column5 - oods_values[116]) / (point - pow75 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[116] * value; + + tempvar value = (column5 - oods_values[117]) / (point - pow76 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[117] * value; + + tempvar value = (column5 - oods_values[118]) / (point - pow77 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[118] * value; + + tempvar value = (column5 - oods_values[119]) / (point - pow78 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[119] * value; + + tempvar value = (column5 - oods_values[120]) / (point - pow83 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[120] * value; + + tempvar value = (column6 - oods_values[121]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[121] * value; + + tempvar value = (column6 - oods_values[122]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[122] * value; + + tempvar value = (column6 - oods_values[123]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[123] * value; + + tempvar value = (column6 - oods_values[124]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[124] * value; + + tempvar value = (column6 - oods_values[125]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[125] * value; + + tempvar value = (column6 - oods_values[126]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[126] * value; + + tempvar value = (column6 - oods_values[127]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[127] * value; + + tempvar value = (column6 - oods_values[128]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[128] * value; + + tempvar value = (column6 - oods_values[129]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[129] * value; + + tempvar value = (column6 - oods_values[130]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[130] * value; + + tempvar value = (column6 - oods_values[131]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[131] * value; + + tempvar value = (column6 - oods_values[132]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[132] * value; + + tempvar value = (column6 - oods_values[133]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[133] * value; + + tempvar value = (column6 - oods_values[134]) / (point - pow17 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[134] * value; + + tempvar value = (column6 - oods_values[135]) / (point - pow20 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[135] * value; + + tempvar value = (column6 - oods_values[136]) / (point - pow21 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[136] * value; + + tempvar value = (column6 - oods_values[137]) / (point - pow22 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[137] * value; + + tempvar value = (column6 - oods_values[138]) / (point - pow23 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[138] * value; + + tempvar value = (column6 - oods_values[139]) / (point - pow27 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[139] * value; + + tempvar value = (column6 - oods_values[140]) / (point - pow29 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[140] * value; + + tempvar value = (column6 - oods_values[141]) / (point - pow30 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[141] * value; + + tempvar value = (column6 - oods_values[142]) / (point - pow31 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[142] * value; + + tempvar value = (column6 - oods_values[143]) / (point - pow35 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[143] * value; + + tempvar value = (column6 - oods_values[144]) / (point - pow36 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[144] * value; + + tempvar value = (column6 - oods_values[145]) / (point - pow37 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[145] * value; + + tempvar value = (column6 - oods_values[146]) / (point - pow38 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[146] * value; + + tempvar value = (column6 - oods_values[147]) / (point - pow41 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[147] * value; + + tempvar value = (column6 - oods_values[148]) / (point - pow44 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[148] * value; + + tempvar value = (column6 - oods_values[149]) / (point - pow48 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[149] * value; + + tempvar value = (column6 - oods_values[150]) / (point - pow56 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[150] * value; + + tempvar value = (column6 - oods_values[151]) / (point - pow85 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[151] * value; + + tempvar value = (column6 - oods_values[152]) / (point - pow86 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[152] * value; + + tempvar value = (column6 - oods_values[153]) / (point - pow87 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[153] * value; + + tempvar value = (column6 - oods_values[154]) / (point - pow88 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[154] * value; + + tempvar value = (column6 - oods_values[155]) / (point - pow89 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[155] * value; + + tempvar value = (column6 - oods_values[156]) / (point - pow90 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[156] * value; + + tempvar value = (column6 - oods_values[157]) / (point - pow91 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[157] * value; + + tempvar value = (column6 - oods_values[158]) / (point - pow94 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[158] * value; + + tempvar value = (column6 - oods_values[159]) / (point - pow95 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[159] * value; + + tempvar value = (column6 - oods_values[160]) / (point - pow96 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[160] * value; + + tempvar value = (column6 - oods_values[161]) / (point - pow97 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[161] * value; + + tempvar value = (column6 - oods_values[162]) / (point - pow98 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[162] * value; + + tempvar value = (column6 - oods_values[163]) / (point - pow99 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[163] * value; + + tempvar value = (column6 - oods_values[164]) / (point - pow100 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[164] * value; + + tempvar value = (column6 - oods_values[165]) / (point - pow101 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[165] * value; + + tempvar value = (column7 - oods_values[166]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[166] * value; + + tempvar value = (column7 - oods_values[167]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[167] * value; + + tempvar value = (column8 - oods_values[168]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[168] * value; + + tempvar value = (column8 - oods_values[169]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[169] * value; + + tempvar value = (column9 - oods_values[170]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[170] * value; + + tempvar value = (column9 - oods_values[171]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[171] * value; + + tempvar value = (column9 - oods_values[172]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[172] * value; + + tempvar value = (column9 - oods_values[173]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[173] * value; + + // Sum the OODS boundary constraints on the composition polynomials. + let (oods_point_to_deg) = pow(oods_point, CONSTRAINT_DEGREE); + + tempvar value = (column_values[10] - oods_values[174]) / (point - oods_point_to_deg); + tempvar total_sum = total_sum + constraint_coefficients[174] * value; + + tempvar value = (column_values[11] - oods_values[175]) / (point - oods_point_to_deg); + tempvar total_sum = total_sum + constraint_coefficients[175] * value; + + static_assert 176 == MASK_SIZE + CONSTRAINT_DEGREE; + return (res=total_sum); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/bitwise/composition.cairo b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/composition.cairo new file mode 100644 index 00000000..1c453561 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/composition.cairo @@ -0,0 +1,136 @@ +from starkware.cairo.common.ec import StarkCurve +from starkware.cairo.common.math import assert_nn +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_fp_and_pc +from starkware.cairo.stark_verifier.air.diluted import get_diluted_prod +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.air.layouts.bitwise.autogenerated import ( + CONSTRAINT_DEGREE, + DILUTED_N_BITS, + DILUTED_SPACING, + ECDSA_BUILTIN_RATIO, + ECDSA_BUILTIN_REPETITIONS, + MASK_SIZE, + N_CONSTRAINTS, + PEDERSEN_BUILTIN_RATIO, + PEDERSEN_BUILTIN_REPETITIONS, + PUBLIC_MEMORY_STEP, + eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.bitwise.global_values import ( + EcdsaSigConfig, + EcPoint, + GlobalValues, + InteractionElements, +) +from starkware.cairo.stark_verifier.air.layouts.bitwise.periodic_columns import ( + eval_ecdsa_x, + eval_ecdsa_y, + eval_pedersen_x, + eval_pedersen_y, +) +from starkware.cairo.stark_verifier.air.layouts.bitwise.public_verify import segments +from starkware.cairo.stark_verifier.air.public_input import get_public_memory_product_ratio +from starkware.cairo.stark_verifier.air.traces import TracesCommitment + +// Constants. +const SHIFT_POINT_X = 0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804; +const SHIFT_POINT_Y = 0x3ca0cfe4b3bc6ddf346d49d06ea0ed34e621062c0e056c1d0405d266e10268a; + +// Evaluates the composition polynomial at a point, given the mask_values and the constraint +// coefficients. +func traces_eval_composition_polynomial{range_check_ptr}( + air: AirWithLayout*, + commitment: TracesCommitment*, + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_domain_size: felt, + trace_generator: felt, +) -> (res: felt) { + alloc_locals; + + tempvar interaction_elements = cast(commitment.interaction_elements, InteractionElements*); + tempvar public_input = commitment.public_input; + let (__fp__, _) = get_fp_and_pc(); + + // Public memory. + let memory_z = interaction_elements.memory__multi_column_perm__perm__interaction_elm; + let memory_alpha = interaction_elements.memory__multi_column_perm__hash_interaction_elm0; + tempvar public_memory_column_size = trace_domain_size / PUBLIC_MEMORY_STEP; + assert_nn(public_memory_column_size); + let (public_memory_prod_ratio) = get_public_memory_product_ratio( + public_input=public_input, + z=memory_z, + alpha=memory_alpha, + public_memory_column_size=public_memory_column_size, + ); + + // Diluted. + let diluted_z = interaction_elements.diluted_check__interaction_z; + let diluted_alpha = interaction_elements.diluted_check__interaction_alpha; + let (diluted_prod) = get_diluted_prod( + n_bits=DILUTED_N_BITS, spacing=DILUTED_SPACING, z=diluted_z, alpha=diluted_alpha + ); + + // Periodic columns. + let (n_steps) = pow(2, public_input.log_n_steps); + tempvar n_pedersen_hash_copies = n_steps / ( + PEDERSEN_BUILTIN_RATIO * PEDERSEN_BUILTIN_REPETITIONS); + assert_nn(n_pedersen_hash_copies); + let (pedersen_point) = pow(point, n_pedersen_hash_copies); + let (pedersen__points__x) = eval_pedersen_x(pedersen_point); + let (pedersen__points__y) = eval_pedersen_y(pedersen_point); + + tempvar n_ecdsa_signature_copies = n_steps / ( + ECDSA_BUILTIN_RATIO * ECDSA_BUILTIN_REPETITIONS); + assert_nn(n_ecdsa_signature_copies); + let (ecdsa_point) = pow(point, n_ecdsa_signature_copies); + let (ecdsa__generator_points__x) = eval_ecdsa_x(ecdsa_point); + let (ecdsa__generator_points__y) = eval_ecdsa_y(ecdsa_point); + + // Global values. + local global_values: GlobalValues = GlobalValues( + trace_length=trace_domain_size, + initial_pc=public_input.segments[segments.PROGRAM].begin_addr, + final_pc=public_input.segments[segments.PROGRAM].stop_ptr, + initial_ap=public_input.segments[segments.EXECUTION].begin_addr, + final_ap=public_input.segments[segments.EXECUTION].stop_ptr, + initial_pedersen_addr=public_input.segments[segments.PEDERSEN].begin_addr, + initial_rc_addr=public_input.segments[segments.RANGE_CHECK].begin_addr, + initial_ecdsa_addr=public_input.segments[segments.ECDSA].begin_addr, + initial_bitwise_addr=public_input.segments[segments.BITWISE].begin_addr, + rc_min=public_input.rc_min, + rc_max=public_input.rc_max, + offset_size=2 ** 16, + half_offset_size=2 ** 15, + pedersen__shift_point=EcPoint(x=SHIFT_POINT_X, y=SHIFT_POINT_Y), + ecdsa__sig_config=EcdsaSigConfig( + alpha=StarkCurve.ALPHA, + beta=StarkCurve.BETA, + shift_point=EcPoint(x=SHIFT_POINT_X, y=SHIFT_POINT_Y)), + pedersen__points__x=pedersen__points__x, + pedersen__points__y=pedersen__points__y, + ecdsa__generator_points__x=ecdsa__generator_points__x, + ecdsa__generator_points__y=ecdsa__generator_points__y, + memory__multi_column_perm__perm__interaction_elm=memory_z, + memory__multi_column_perm__hash_interaction_elm0=memory_alpha, + rc16__perm__interaction_elm=interaction_elements.rc16__perm__interaction_elm, + diluted_check__permutation__interaction_elm=( + interaction_elements.diluted_check__permutation__interaction_elm), + diluted_check__interaction_z=diluted_z, + diluted_check__interaction_alpha=diluted_alpha, + memory__multi_column_perm__perm__public_memory_prod=public_memory_prod_ratio, + rc16__perm__public_memory_prod=1, + diluted_check__first_elm=0, + diluted_check__permutation__public_memory_prod=1, + diluted_check__final_cum_val=diluted_prod); + + return eval_composition_polynomial( + mask_values=mask_values, + constraint_coefficients=constraint_coefficients, + point=point, + trace_generator=trace_generator, + global_values=&global_values, + ); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/bitwise/global_values.cairo b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/global_values.cairo new file mode 100644 index 00000000..e7d4e1ca --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/global_values.cairo @@ -0,0 +1,64 @@ +struct EcPoint { + x: felt, + y: felt, +} + +struct EcdsaSigConfig { + alpha: felt, + beta: felt, + shift_point: EcPoint, +} + +// Accumulation of member expressions for auto generated composition polynomial code. +struct GlobalValues { + // Public input. + trace_length: felt, + initial_pc: felt, + final_pc: felt, + initial_ap: felt, + final_ap: felt, + initial_pedersen_addr: felt, + initial_rc_addr: felt, + initial_ecdsa_addr: felt, + initial_bitwise_addr: felt, + rc_min: felt, + rc_max: felt, + + // Constants. + offset_size: felt, + half_offset_size: felt, + pedersen__shift_point: EcPoint, + ecdsa__sig_config: EcdsaSigConfig, + + // Periodic columns. + pedersen__points__x: felt, + pedersen__points__y: felt, + ecdsa__generator_points__x: felt, + ecdsa__generator_points__y: felt, + + // Interaction elements. + memory__multi_column_perm__perm__interaction_elm: felt, + memory__multi_column_perm__hash_interaction_elm0: felt, + rc16__perm__interaction_elm: felt, + diluted_check__permutation__interaction_elm: felt, + diluted_check__interaction_z: felt, + diluted_check__interaction_alpha: felt, + + // Permutation products. + memory__multi_column_perm__perm__public_memory_prod: felt, + rc16__perm__public_memory_prod: felt, + diluted_check__first_elm: felt, + diluted_check__permutation__public_memory_prod: felt, + diluted_check__final_cum_val: felt, +} + +// Elements that are sent from the prover after the commitment on the original trace. +// Used for components after the first interaction, e.g., memory and range check. +struct InteractionElements { + memory__multi_column_perm__perm__interaction_elm: felt, + memory__multi_column_perm__hash_interaction_elm0: felt, + rc16__perm__interaction_elm: felt, + diluted_check__permutation__interaction_elm: felt, + diluted_check__interaction_z: felt, + diluted_check__interaction_alpha: felt, +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/bitwise/periodic_columns.cairo b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/periodic_columns.cairo new file mode 100644 index 00000000..46218847 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/periodic_columns.cairo @@ -0,0 +1,1571 @@ +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_pedersen_x(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x43869b387c2d0eab20661ebdfaca58b4b23feac014e1e1d9413164312e77da); + tempvar res = res * point + (0x4cec4cd52fab6da76b4ab7a41ffd844aad8981917d2295273ff6ab2cce622d8); + tempvar res = res * point + (0x295046a010dd6757176414b0fd144c1d2517fc463df01a12c0ab58bbbac26ea); + tempvar res = res * point + (0x60105b3cb5aab151ce615173eaecbe94014ff5d72e884addcd4b9d973fed9fd); + tempvar res = res * point + (0x233eff8cfcc744de79d412f724898d13c0e53b1132046ee45db7a101242a73f); + tempvar res = res * point + (0x6f753527f0dec9b713d52f08e4556a3963a2f7e5e282b2e97ffde3e12569b76); + tempvar res = res * point + (0x549a83d43c90aaf1a28c445c81abc883cb61e4353a84ea0fcb15ccee6d6482f); + tempvar res = res * point + (0x4259be645aaf0a661e7877276fa5559ed7d04349f577595702efed3050402c5); + tempvar res = res * point + (0x71e67bd6a0b1b8518cb06837a78b92ab3dec98c4989f946285042655ffe516e); + tempvar res = res * point + (0x19b7924c29a944ecb61165a663d76d84e5ce44b4617fdbca8ff02fbdea6deba); + tempvar res = res * point + (0x70454f9541d96fc1552f984330389ff616cf80eaf699ba2e82b77f43fd163a); + tempvar res = res * point + (0x479c09d33c38f1c8f73247aace507da354ae87ca5cd4aa096bd3a6229e3006d); + tempvar res = res * point + (0x6fcf0e32e3e99f51d8cdac9c19cc25179eb97f2757844fa0c72e7c3bf453e4); + tempvar res = res * point + (0x4ccee6b6ecd4ea8733198e95935d13474d34cf54d7631fde59720e40378e1eb); + tempvar res = res * point + (0x627cb37206e5ee9da20c04a92cc765e3bd3f3d4e42ad4de0d709f366d446d8e); + tempvar res = res * point + (0x4183c04ef7d778f11e57b44c1a7f354c4497f1e3d420d3fa9f9c27c4bb58759); + tempvar res = res * point + (0x1e2c5c3fb2b47ea8cf33099c610f6132a5dd7099d29b02f4a041fe5947ff53b); + tempvar res = res * point + (0x4d44944716e0e13728fa8b84fde421f0f66a120ed2b7cfcf59f5ff6718b8b6c); + tempvar res = res * point + (0x394d0eed011068acc2f55f541c4d113a9c0afe7269cd7d9711aa7e8be661a60); + tempvar res = res * point + (0x52b5bdbcf28603ba60abcbf52bd4f7b4988ce0b4e2346e4875a3f117d4143b4); + tempvar res = res * point + (0x5975b93cee7a147a93cc98aabbb713f151924c4ede3306bb5e14e5e4d5d5c05); + tempvar res = res * point + (0x787053fc3649b17965b9e6ef5e05e024cdc188e90aef1cbf13ba78542a0407d); + tempvar res = res * point + (0x7cbef72611c8e1e08e52ca202382a8545bc7fe124ec080058988e45771e3b40); + tempvar res = res * point + (0x32bd55700baf7283995407f470139326a670d60a5d5428904596584629a053d); + tempvar res = res * point + (0x3485ad12aa365fac51a6296931abdcb54fa848c587cfbfe5bdbad2d6f6d3bd3); + tempvar res = res * point + (0x7f9850620a3435695ec7a6d9378cfe218ab0e5fa674cdc572fb9c197b0dbd25); + tempvar res = res * point + (0x1c7c40b6e4cd3d473e8f84b8fa63610ac6c7e3f4f0017f3ed84eae8f042bf15); + tempvar res = res * point + (0x1e3e1d970342085c482175cf60d93e1cc2cf96dec12f1d839b9b829cc957b7d); + tempvar res = res * point + (0x2d1547488e174e0a8662decd2cf020dd40718f070c84cf36bfa261aa90f814); + tempvar res = res * point + (0x31b8dd40040d22aae383c1e628e427f7aa4a7b0c3a83f815fd7ae2b36864af0); + tempvar res = res * point + (0x5efc7dfab3ad0b3f01e313c50ced95363d8dbaa9f91f801d6f1f00869467a16); + tempvar res = res * point + (0x724a3072c9f315cba63e5d99034b3218ff29a9bbf04155060ebdd6c848a652); + tempvar res = res * point + (0x2a0c1eade4037c10729bdc8a8f38bb5bf359078eedba633047377a09b6cde4d); + tempvar res = res * point + (0x6aacb14e31ebb5066e78eb597842812d7ad137880a6dd0d065c4acee231b7c3); + tempvar res = res * point + (0x468b88ba32ca1eac6c8d3196eea0561e25770818221ed0da3ae749e2a302e); + tempvar res = res * point + (0x5b52f487f8c3d78fb6ea4be227325a7386c7e95cd5f9b72710cfcc870cbba59); + tempvar res = res * point + (0x2bec10dd6a541c12555ff040b5949407713b4227867f53a435e80847b7932f0); + tempvar res = res * point + (0x41e1c8870eea4b7f4308e8173f97482d80afd055f07b1a058f182a775aef593); + tempvar res = res * point + (0x126a03f3c5cbe523484111d915d6d7eab5edad02a327a383171be09597336b4); + tempvar res = res * point + (0xa8db86341624832893780e36fe1f60490da5768f9aeb2a5803240f29ec5a2); + tempvar res = res * point + (0x751a8c7382e8fc0141b4ec5bf37fa457ab8301640b58cfc3b6a0b8d1a12bec2); + tempvar res = res * point + (0x5e56f3654b68256095b54a7868763aa3ff60a98ea3508039def82d2098d8a6d); + tempvar res = res * point + (0x60a9a4ccb72bde44d8a6c5f1d7b9303cc32013ef621bce1b8af413f00e77ef2); + tempvar res = res * point + (0x4efe82f8cacf9761cac9fefb6c13c1afdaed68ee650c37684bfce323070e480); + tempvar res = res * point + (0x40c43992a86359c71f5b8051d84d1fd6971eb36ab486f321a1fc50a52a02a44); + tempvar res = res * point + (0x538392c6ca2c04b5096aa69392b76ff109aabe165df488f3d1a8e5c4022db64); + tempvar res = res * point + (0x2b783063fa1948abfa91d79d225d52ed2ddd11bf20fc388b1ec00fdb5867921); + tempvar res = res * point + (0x1ec66f3f326120e659b78867bdfd7dac4dd3f1a92ffeaf46d39725de341afd4); + tempvar res = res * point + (0x5f4ed6b86202d76686a0b4c1efdfc93c46dce1b843c7181d1db1f8cd4d6dfb); + tempvar res = res * point + (0x34b9f6e8d5debbb4aea334310dc8d8075f896e7eb9f1c09788c7ec62ccb6116); + tempvar res = res * point + (0x4e57c6677d3bd56b425a3b3a92517344d4875e1710667e3dee1954395269af); + tempvar res = res * point + (0x1c5110241881e087e201d211da338d8377dd228afbd84850b76f3e5dfeb9361); + tempvar res = res * point + (0xa64b536ff29309d613af1c27c7229c3f6c583471c6b589b25026db08d3767a); + tempvar res = res * point + (0x3f6f9a9c3f6e175b59fd8e4268a6ae5734034fb1d7c43f97ef474b75ba80cc8); + tempvar res = res * point + (0x775ad15685181f15e34a6b0036c16fc8d1a9860ced1cc5ece39d19a6add939b); + tempvar res = res * point + (0x7775ec7b0ee9812c8df83957c5b46c316fdac82a2d736d4a6eea6124abc5849); + tempvar res = res * point + (0x41f320f863037e381ff83f2c9f1a8ae2802fc22cfea674d9cfd10171da6dea8); + tempvar res = res * point + (0x67649ac75ea692acb3aa4432d48de15aacfa347a37afdf489cc7e954e4ab100); + tempvar res = res * point + (0x7fd8c6108133b8109f4058192bd614b5de2c50afe7ac08a7bb0e0b12ef04e4f); + tempvar res = res * point + (0x57f8ef270683ea78b167dcbe5bb122a79ba760c95f8103dc4c6e7788fb1ac9c); + tempvar res = res * point + (0x6dc0d996fc95036c8cfa408fb12793bf8a4773d698f55085c2ccbc906c6d2d0); + tempvar res = res * point + (0x6713ddde3f2da61b676f5e4c52177bfc8c1576bc97ab3c48f08ff02d26cc03e); + tempvar res = res * point + (0x16b450dd2bb4712f6412b35603aaa02e7345124e5fd13e919c269f3874970f9); + tempvar res = res * point + (0x5f81b087ad750a0ebddd5239bb3682c84d88326b4679a24890f5fec98df45a); + tempvar res = res * point + (0x33f4151b710663772765df7f95b3710c3e8e81bacdbe3729b0a43b6d19e428c); + tempvar res = res * point + (0x5d122cd95f43fb6fc2373ef7e66072140f0f20d552f186faff2622b55a3e063); + tempvar res = res * point + (0x9b478a0767cca2c6f9b4268bffc9e907eb69b32f8ff7b43fc24edd38a88ec2); + tempvar res = res * point + (0x597cee65bc7c6f0faa3e0aa1958897acf7fd4e4e69569f5d18254b0b8c09aab); + tempvar res = res * point + (0x218bc11c668ef7ae5f04a16dc9933c5bc41c194a439d0af802568e598c54630); + tempvar res = res * point + (0x3394eac0b3787b323686cddaef3af972d7fbbd75940bf7f682b8fe3676cd46b); + tempvar res = res * point + (0x4aeb3836ccb2a9ebf9f1c5b6ee3c42f66c8059cc55188335a47a3583d986018); + tempvar res = res * point + (0x5db68a5c4527fff0ebf61fe064888b0fb6e277cfecca6d206986293256f31f); + tempvar res = res * point + (0x63372394d373e7a2f2fa6405509da05fe9cb546ea2742ac0716bccf50ad9227); + tempvar res = res * point + (0x22d4ed1a29943bc16343e01eab25e45adf74b6a7072e4e26aa8d141f2cac5ca); + tempvar res = res * point + (0xf8ea3b2c0b72747301b2778cc071cb9d2e09bbdd7a386b7931582ab412dbd1); + tempvar res = res * point + (0xf78d4b72e0f5f55913884d0714674dd6f534b211ec5dcdba419347828c7c35); + tempvar res = res * point + (0x5142430fc3f872dd6fefb7e9804e3e63714f71a2f43b155cebc53671f964af); + tempvar res = res * point + (0x72fe5010e70102306b21cc388b7f2ab8b0324b84654cf98032b83a81099e72e); + tempvar res = res * point + (0xfd959b09bb704fe63c73e2331f8e76dc1fbf85c2dc9dcaa0e8108664f7f988); + tempvar res = res * point + (0x4180556f79a47df725eca2c2f65389e27281443847a7d9e84640e6d589182f7); + tempvar res = res * point + (0x2dc12726f7f06ef1adfb10747e5d4ef8052e4e57bad9bb10529d7994ef91035); + tempvar res = res * point + (0x3c62720cac42a262b58765d7c0588231c5c2c9ce9d48f0fd547575289ede8c8); + tempvar res = res * point + (0x5744178090cdd56ae12fdd51b74bc097f23f735b7ca16e415a1854597b1caf8); + tempvar res = res * point + (0x597cbefb648f47e763b9b1be8c3f815a0e8b65d0101e11b5bedc380c10e9f4); + tempvar res = res * point + (0x78e66ae8b3ef57289d92561dbe4ef72f4ee551d5cad363720a78d104a89163); + tempvar res = res * point + (0x3cb89319d8172da012c036c40116fd325d65af69f80a1df8f56ec890e920592); + tempvar res = res * point + (0x29d152196b7ea7446182efe778a2db796f5fab17286405953476ac97f94a96a); + tempvar res = res * point + (0x6348748d43d48acafb8ce688f25a1245df86dd20c3a96c5c85cfc0960ca2fa7); + tempvar res = res * point + (0x3609fff81e15da2a88036d1c2d28814035ce829430fabcc3986c08acdc2d44); + tempvar res = res * point + (0x3241fcabfd99b666b151970558fb59fdfca47ded4caf2af4b15839767edb190); + tempvar res = res * point + (0x3f61241934753ca9c4f4210885b87863abdc8637d4dafe5da4bfa5e0206988e); + tempvar res = res * point + (0x6a16c0b648c72c8d718d53099cb11725ee09fe1b49487d8f55f307a6a265920); + tempvar res = res * point + (0x43ef0fbc56a0a46c7099f5e6d6550a77e1ac023e2201f01bde0a3f5fb0f16a5); + tempvar res = res * point + (0x1f6bf768424619cc2d34c01cbf4e137b6cc33a4a5a3db0bc704f790f86ad67c); + tempvar res = res * point + (0x49eac48d453d5de07fe3f4bdb5aac21e7fe69858afedfbeb0daf175459dd9d7); + tempvar res = res * point + (0x2a390a6737563e9edc22b0b0cce94a67adc10db18d6f978c826f24b8848c6df); + tempvar res = res * point + (0x23e127bf290465acfb7500962d426be5241f0e8c6f844d25aa8e262df6e70cb); + tempvar res = res * point + (0x5e51a00b7437caee2acdb81781212bc3d1c397b477ec784d1a7b304c9f8c687); + tempvar res = res * point + (0x6e52308f62433fe92ca9064e06aa17d793d3ad7bedb9590c8bb9edd3272fbae); + tempvar res = res * point + (0x7aa1d2348e13a031dc4fa20d453fcd59eead9adbccc3ea64997d09a0f58216b); + tempvar res = res * point + (0x1c02d3ffc30c7172a132ac604ad28e89466845c139dba509b896c997ee4ce8a); + tempvar res = res * point + (0x3ea018d81f9118cb5cf251d6c795b4ca4aeeb28d6ea5464fb4807d219453728); + tempvar res = res * point + (0x62c2fa993dee607ef195fb6620051b4df127d933de3a417d21de3b0c6dfdc95); + tempvar res = res * point + (0x2fd6fab5c4d0e6bd5bf5b950632e2dfc3be19c9a80e3bf8934e878003b0816a); + tempvar res = res * point + (0x12f2b0b280b64cb9f6bd77cd5103b7668ae42e5d40ae156607c69043b4da5a9); + tempvar res = res * point + (0x51a3ba83e3f68b2df85f3b9e770b5294312fd634fa48ace215a029fdb5593); + tempvar res = res * point + (0x56f19df91009289c7f5304026cf6d2c26541cd4caf867b2d2ea8a954560ed7b); + tempvar res = res * point + (0x362dd19b8207511079a352fad991df9582315ca2539ed4da5cbb5b82e414fc5); + tempvar res = res * point + (0x2dd7ddf328b439b3047a93c6fff6ef901946438cbb55a4c1fa1848f80baf2ce); + tempvar res = res * point + (0x2120274511adcc680703d33146477a31c42684b5163a628eb3f84258ae78786); + tempvar res = res * point + (0x11076126b67298371103d89e76ec2fbe30b28c5de422e61d3fade2e190450a4); + tempvar res = res * point + (0x1868ebbc59cb1c69b32ea2b3a7ce3f87b680731b96a42403878df0a0e4bb3e2); + tempvar res = res * point + (0x5b7abf66fda1917e0e1d44924cb73d713b5fc16b3a64bd4857d089adfd6a814); + tempvar res = res * point + (0x13df9c113e40f246d806089e437629de52f8a247ece912785004efcafd4ea94); + tempvar res = res * point + (0xbdcc31feec5ca8cfbf7227269d1e120132c51307ec03cc2d59c471e2510a24); + tempvar res = res * point + (0x3b2efe16624d8d0a1beeb037b02f0a4f7e11eb3859852cea1f83ab1752a4099); + tempvar res = res * point + (0x596104fc8bded038e39f0de5e80a2f2b65fd39fa4ab7b3453bbe8a40e06a317); + tempvar res = res * point + (0x5fec9e8e9ad35ec1091706f4f39c0e8a610f58be6c987c2327ce0794af7cb7c); + tempvar res = res * point + (0x5fb45888a7861e18a320bff7b0baee50ef9cbe1b06c78a5a16a6fbda3c6b77f); + tempvar res = res * point + (0x2c15afc87ef81cb58ec29c7dd81b4cfe291e5d33a7b36126289a8ebc1af4eb4); + tempvar res = res * point + (0x1f90c3eb7ed36bec79f803ab1884e5455581110ab713139cdb5207561a89a34); + tempvar res = res * point + (0x7c537f749e37ed15d7e5d5d0f88686c5d02242b6c487ae2c5606d2c7de986b6); + tempvar res = res * point + (0x4db0795b76ed3b5cf3cbc23bc47d20abe9b9f76a2731f2774e6dd5ecd6eea05); + tempvar res = res * point + (0x3a7ada56cb16708c6eee7af3688765728c706a16baf61d0582186a3717ef552); + tempvar res = res * point + (0x4c9b9f2c154c6a8cb1fbf50793787d215f2857d042b21c6f5e2740732cca567); + tempvar res = res * point + (0xdf2e87cea7f46ab09a5011d8afca4e7cb962e008fc991ea16d85c472dcf3ef); + tempvar res = res * point + (0x4df83db997cffc8598b838a9c8373bfff5e109d71ee3bf2a18dc0e621e93d2d); + tempvar res = res * point + (0x17eb7ae4a950bce2abe1e7165594eaa60be7b75cefd8007425a735264a1371a); + tempvar res = res * point + (0x6c8258350c092e7b5cf658a6bed95d620afe0563482911a1435a93bcb0d5beb); + tempvar res = res * point + (0x554563c23e6ec8a4497d670e81940a92ddad53c27e7bbc18de74d2b3734d824); + tempvar res = res * point + (0x6c9568c4a9f64874e71c88cc80576e4083f6d0649f66929612a9bb99bd958e1); + tempvar res = res * point + (0x14e46f8471beb6479fadac1286dc86683c659bf1c77dc96bcb303d48c115d7e); + tempvar res = res * point + (0x5eb4774b76a39af609243ea0ca61eaf03255a02d90be9a83901debf64875f0b); + tempvar res = res * point + (0x3317e8a32e8f82246423237d2a4039eba358a76adb8065751b6d7939fadb85c); + tempvar res = res * point + (0x6cfe464b2a4d4e77c09e0beceb4e368bd93aae5efaddbb92e003afc508fcb33); + tempvar res = res * point + (0x3b69a8579df2cea96435a07c81ae1d9f8a5e0e52433335c3e7ad81b76789788); + tempvar res = res * point + (0x3f26981ddcd3549baf47e3f1242b0bb90d6b7f426ba71d2ce628ceb801f3734); + tempvar res = res * point + (0x40d8fb43bbc7e5c35e4b57fef4e8351ffb118c9d92346f97ff7cb48b0170eff); + tempvar res = res * point + (0x19eec9d276c006f19cfa904a4e2ead857e99000d16e897dc8dc955c57615d54); + tempvar res = res * point + (0xcfff274a78e56ec27e29d01f2e900bd226cdb493a83358f9b807235c9aa407); + tempvar res = res * point + (0x13d4454abb9515f00c3daa6034ed3759ea722a953679c4f857511141b87da93); + tempvar res = res * point + (0x2ea5039159478e68762063624b0f396cb7f1bbfe8c1a159f65f0f663f219136); + tempvar res = res * point + (0x40508ab9b5b8d885f85750bb659071d6cc04639f43070b94a802d41723bd0f3); + tempvar res = res * point + (0x40a9f47d93280a641e7f903b1e608cb443ed5d59f24cde6b92c6631cab1e009); + tempvar res = res * point + (0x5a5085cb551c472af264b5de50ebb7b4bb04539c9afac1339f903b943578eea); + tempvar res = res * point + (0xa89bb9df4a46c56f2f40748d826d50285082118f8995f5e7638a05ec117c47); + tempvar res = res * point + (0x5950e4370508dbfa764621025e9341994a3ac21848f3e39d02370b193ba6937); + tempvar res = res * point + (0x6f20da2f1a25f1fab33e7856067226784ad992f8bb53249ee7bb17e86c82070); + tempvar res = res * point + (0x42271e06f205c1bfc9f9d9411bf835f43941c88aa3dc75f044a0143faa4d5cc); + tempvar res = res * point + (0x411f9def562556de87d47af60354512d9a1261152e7f4636038699d468fc2bb); + tempvar res = res * point + (0x66490371a5dfa3fb85bf3f088b89614b5e56cafc263eec39dc4a1bb39e03433); + tempvar res = res * point + (0x6d49bd35b4e4aa46b7098d306632014b4fbfd84892d6997b58d9463a0ea2c05); + tempvar res = res * point + (0xa9c2bf87d58d3f72d985b4b1129f0a1664caac1ee26a15675d1a5086de3a79); + tempvar res = res * point + (0x46df5faa750270394a4253e63ba3e437550ee216ebf8ddbbd7304940c85ad02); + tempvar res = res * point + (0x6e5bf767f3b0646dc16377f3bb7c17db6069555e100dd2215eb20c4d29fb1c3); + tempvar res = res * point + (0x5d9acf8582d4ccc017af36a8a9863e4383b63893d3fb5d81f7fabf4ba3d1023); + tempvar res = res * point + (0x6933ce3f88628188f7a1b1be5b0506dedadd9559c4766be0e7db1ace3adb592); + tempvar res = res * point + (0x40ba0e2f504aa0e9972018d91be21f56bde16361282915563796c750f8936b7); + tempvar res = res * point + (0x6fd73eabd21a86dd8094dd0ebb5924b1aab0753a0d251571ea93f83ab4bd519); + tempvar res = res * point + (0x2761e32194ddef695d1837c8a3f48a3773ae392b5633bfa0c1451e51e33b69b); + tempvar res = res * point + (0x5519091c464bab5646294ae41d087ddcef8bd0508a94a07890fa07220bdaad3); + tempvar res = res * point + (0x3b160cef807b72e95938852093a3a633e72b61e0afad5099201885b54be4098); + tempvar res = res * point + (0x7692b996dcfecd35db6aa22de10144724c478f85a328ab893c6fbadf43d7a9e); + tempvar res = res * point + (0x3512eb8a3bbded6fad1c19190d857629efc56f93fb4aa527e2958dfcce12153); + tempvar res = res * point + (0x591ad3fb7ab83f8d9fcf184ab793baf3db128cda0de1618932851108771cf0d); + tempvar res = res * point + (0x5f7da39edb0781ca1f96af191cf4c70fe0c121b7b2c92f09b49503bb070dc99); + tempvar res = res * point + (0x4a94669a4901cb5527124a2dc7ff6c278d540da41a95e819d0ca10269f7b380); + tempvar res = res * point + (0x20a06257ccfa90a74adf9bb1130a8385b8c91bc61e18acc30843463e5abaa2); + tempvar res = res * point + (0x7e3c052c620ef7fcf180898d28e39348e96e92ed0634dcae3f5fc64be5094a6); + tempvar res = res * point + (0x578dfc700a95a564b41ba8f33b885ad04209bf5169a4046f603a3d84f792d6d); + tempvar res = res * point + (0x796c9b073e2c56f55601eb1f6147d028553275e9fb792f0b76007c9710459c7); + tempvar res = res * point + (0x8c2c75a2fe00432f77ef57e906f264ea76c439e0c4cb19e87867a6ebb34d0a); + tempvar res = res * point + (0x525fee2e2cdb7a293f50f630a840d5cf5f29a158eadd6fa9d0159951712d19a); + tempvar res = res * point + (0x7991462c103abfc3bc31427227b1fb82f7fdf2be1b39316f46e3baef2fcf588); + tempvar res = res * point + (0x46d1e806178137e82ea97c54d8c15dd45c2a9a0082b18aeb9f849158ffc0ee5); + tempvar res = res * point + (0x25a127bbf961fe2b5bd9facbda706223206c40acff003152cbb3b28e9668030); + tempvar res = res * point + (0x1e3d7c65a8f40b6f8aab1635e3b78d0f798746532f08771267a9b6149632a5a); + tempvar res = res * point + (0x25fc8ba8ab421b6dacf2ce03263e037374e4d61c6ce26422fbcb2e755c0d9c4); + tempvar res = res * point + (0x48294f41052135cca94fcf88cf236437b8a55370c3de81fb0d781aa7b0f8eca); + tempvar res = res * point + (0x8c5762a12210a7fdc96a7d3aa966476d3b28650e7c49fc90f95e49a80d4324); + tempvar res = res * point + (0x4ffe8275d3344b4ae2f7d9992d68598e50f365c0b8a721d723841485fc25c0d); + tempvar res = res * point + (0x2959a6947bc4eee0135bbd0a6f2053b62317a1718bcceecbd507417d31e8806); + tempvar res = res * point + (0x77efd8893058f8e00863205582a5e274c344b9af63b9c40ddd92c97c33b52ea); + tempvar res = res * point + (0x73796a0ce0fe851bc22b99faded48a24a21745bb62603e750f78b854d7c32c7); + tempvar res = res * point + (0x2d2e43c0ad60d4265774479258211274ae32b5e151aacf6f8ac1b7708076f09); + tempvar res = res * point + (0x22b5eab11c9e1e6b8d64d5db4b12502fdf0899497f72ee1a27c8797b617f76d); + tempvar res = res * point + (0x703c768145191a10344e5ca400be8fd249e653d564015d46fcd7096cb723a0); + tempvar res = res * point + (0x4159f8056bde7fd4f72615f7bdd0bb6408256b8b216ca52fee253113d9d007c); + tempvar res = res * point + (0x5fde2cdf0d23d5649e3aead1b2b90ca0309715a029654e8984e43de7bde7b06); + tempvar res = res * point + (0x50372d2aff2ebc566505a564d971c6491095e009d9887899aee0b5017fcb877); + tempvar res = res * point + (0x3333c3d925d8c58b9e4e533531e93046039577cf0e57d011c7ce87c6ef1a835); + tempvar res = res * point + (0x575fb11a4d7e3876ae4c86b80b4b9530e0d3e9db218f4d5644f612348f8f002); + tempvar res = res * point + (0x3481879ec47fc8cfabf38ffaa75311c787b7006e7f9def35e96454263bba4aa); + tempvar res = res * point + (0x5c1e733995aad208f0697e4d2a6e28bec9fddc3e30bd033f2f50a83927baef1); + tempvar res = res * point + (0x2edf44b1f59efb0f36c0fce5edbb7576c89cb9f191300fc5e0240def1b88b9d); + tempvar res = res * point + (0x1d46036b736e06016c817d2b51a0918189881a4f1b7c71d556db583df762d37); + tempvar res = res * point + (0x258ef77b90879282ccc2ffcea5052cad266d77b75db36b7996e5fe7638e9b00); + tempvar res = res * point + (0x4219a0a13e09662f3ec712da51b36967947f6d5a09d8044e3005a7f0ab45915); + tempvar res = res * point + (0x18d0f552fd62f81b6076265c7a3a0b81f6bd37152a2f16c71210021ecf68468); + tempvar res = res * point + (0x31abb6310a44d65ac8c308011d4afab938fdacfbaec14c62b808452310b799b); + tempvar res = res * point + (0x1765a9eca4f4551f177b35089f8befc808613bbcd971a47d485b1c220d0bbb4); + tempvar res = res * point + (0x7fd44af0ef24f061aa7dd5bbde15098dfc3721790ee9bac2caa71cca714ebf0); + tempvar res = res * point + (0x566edfbe3c59cbd43838ee245edfebe292c7163f79b1454b03ef3cf8af23c10); + tempvar res = res * point + (0x14d01a0c81aa61c5a238243e78afe80e5d0d7bf528c3d05a343d0f4470d2b0a); + tempvar res = res * point + (0x38445d5f2de7993c48c9da8e77a87dbe289dc0428b1e4ca87e30b2376535543); + tempvar res = res * point + (0x324db878e3842c25a78e94453c98434c54b41955db62234b0ec5ddde6641556); + tempvar res = res * point + (0x184f23c10c726d4a7036c39466db02c4fe7c3d40bade571fe07acaa282f4c07); + tempvar res = res * point + (0x7fb1cbd7a48f2d44a148bd4d17ccd47c438f4f1b45a02945cf4312afa0d6f95); + tempvar res = res * point + (0x20d2002cba899acc7d333031e0977d8df94557ca0749bef6c38b72dbcd462f); + tempvar res = res * point + (0x75bd5b63008c2e005df64ca189ecce11c060f0df6903011a3d95cf9f7b48878); + tempvar res = res * point + (0x548724b5683cd6427513b4c4f84a6d888b9a03843bc0dbdc501b8752d99ada1); + tempvar res = res * point + (0x38441dfe93fd3133faf52208f3263d4ecaca0643bf9c9d4bc952c86cf280f7a); + tempvar res = res * point + (0x182e50e36b753ff5f95f2bc47a6aac8c6f2e5c3975476252a7c29250eefb056); + tempvar res = res * point + (0x2593b010eb6fe0f64833e4f22f6854c063085e0dd393226e6b5fb20ea7f432d); + tempvar res = res * point + (0xcc060a8b007b2dd0efa786afa5edcb512d83ddcba8ed69c27ccef5769deb23); + tempvar res = res * point + (0x672717b74bc3dca9e53494681a5ffa02edbb0290de1c5209843a16964df7a3); + tempvar res = res * point + (0x53774852c8f84d21eec107e1da7a2ab3f4b5ceba6479d1f902ad404e7dde329); + tempvar res = res * point + (0x96de7b9a7eac739df4d13902971804aaf40f5559d18593be0daac0ff86c636); + tempvar res = res * point + (0x725601ed4fcfdaa392b91e8ea982fc57f1874378ab8d6b55301b3d4b6efd802); + tempvar res = res * point + (0x7bc4fea0ea687295d72735a62a19c1a160a1b9a19342717b527f94770aca77); + tempvar res = res * point + (0x3dfab578cfc7a1581212074e0969db9accb619a043dd7194a253af67ef3698); + tempvar res = res * point + (0x44090861421dbb6b4a325a6832e02986be80f7ea475313ae01a3215c3510346); + tempvar res = res * point + (0x7384363b4495aacafd81d0a139a66afd3243309395e3444fb3f1496832240a9); + tempvar res = res * point + (0x4f6ea70b9090971f8de7071f27b0d036b112211403e0547fb7b7903704f295b); + tempvar res = res * point + (0xd55dad93e837d31e8f120398e09b83ca68f160c16043e1c65d033a19adbc30); + tempvar res = res * point + (0x6cc09dc2faf0903dbf5121b97ef058300b18efcc30c25f55de752d395b568a9); + tempvar res = res * point + (0x2b2091e41b10140bea196a1cc28d7f6db6ae1b55d1f115d882c321221a32eb4); + tempvar res = res * point + (0x11b19b3abd2b297728768027b1370566bd845bfb6f49197a76255c1d8c661f); + tempvar res = res * point + (0x3236ab2e0e0b1b013c2100283e36fe75521bd50091f1c73deb165e86616d80a); + tempvar res = res * point + (0x7351448e92ce6914278e73ceeb080e280c146dbcc21cb35af8d2c7e5560aa7d); + tempvar res = res * point + (0x100a89bccb889f183c2a6ced12bab8ef86403230ae6b23def0b784f73ff296f); + tempvar res = res * point + (0x31e49312e1d59acae36bf3562443259500039a7a77d9a57a44cbbb4a80932e3); + tempvar res = res * point + (0x273647256f95d2e5f98bd7830191abd89dc4ab241fc7fa12b27e16a6bd423c3); + tempvar res = res * point + (0x424396bedfddf4192963ef0f87b3989a99f277fe2c60756a4a60fae4d6dfa31); + tempvar res = res * point + (0x6e3a0355459b8b7c35837f3f19f0d8954907326cb08d7d084f2ed0f4b2af8f5); + tempvar res = res * point + (0x2d88caa65f47db103fb1ca354bf50c93f24bca5001598f716b6c9e5c51d1d2); + tempvar res = res * point + (0x2dca037a615e8cf99f8614f437e953c5625b9b57d95f16c174f63346e31c5da); + tempvar res = res * point + (0x5800bf15808a39f1acfbb193af1ab0c22f18d9738753bd3cd2aeea81982409e); + tempvar res = res * point + (0x4ad97a9b0ab95abc1b8fcff31a48e18fb2391ac95baaacc62125bd87fd75e13); + tempvar res = res * point + (0x5ba49d41f62b6d6903fc455bf02bca54becb6ee7f39650fcd0b717ac396159c); + tempvar res = res * point + (0x959c7bf3885d75ab3ca9480101ff64d62c9f138d35f63c137009c1b3eb39f3); + tempvar res = res * point + (0x6da06ce868c140c8ff9ec1eb0323fe2c8b35b46c8d4f5a27727450e87ebd906); + tempvar res = res * point + (0x1bf01c19527dd1d9094c44e3acee4d1ec8c4192026b6f996776294cc9dbc4a8); + tempvar res = res * point + (0x40d1ae7e7bcddc520ed8c0fd736e9b5147d278ed1b720abf76439377023abea); + tempvar res = res * point + (0x2f26fb29017b5ab80328de8488db547e47c44c0d56f30e330354d5b980e50ad); + tempvar res = res * point + (0x72bcdfbdd09f13eeb0c01565dc6a79999a9642dbcb0c570e3e7621ca94df215); + tempvar res = res * point + (0x140ed138dfc5b5417b25a4512bb991f3fd04cf750e082fd4fb82cc15b645835); + tempvar res = res * point + (0x40ffb20c2a3dba0a0d8b6aa51ccaa1b690aa08670ceee556d76053cd671d522); + tempvar res = res * point + (0x283c74c8066141911634401af10106c29dd77458d059ff3b2dd7aa796b2a559); + tempvar res = res * point + (0x593df80dd238cbdc6398146502310a5cb459b0e7d79fa9bee5cc389385c95b3); + tempvar res = res * point + (0x669bfada09faa64c005321d60752662598d69c517e9ffa462dc1b1af42228d1); + tempvar res = res * point + (0x70cc78b821b198e72f8feeb8f31d81e5a4854de3575a62909e0bb51cee921d0); + tempvar res = res * point + (0x68539d0ccd1737a8b2e540f9165638f86f6c4e44943455d311999b0b3684b7d); + tempvar res = res * point + (0xbb867c323532bde3d5b0e08b1b7531a95a2a1706132dcd8ebb7063cd1b1bbb); + tempvar res = res * point + (0x751a2c218f4feffc61e90939c4d2672a263d3b33528c7c6eb40042640f45146); + tempvar res = res * point + (0x6473d78fc37e48379ef8a9d57e3e92cf4fdad3a1bcc170dd177dbc51c4dc62c); + tempvar res = res * point + (0x7218f86344ea46cdcc372a22a14663105eef03bb0de9da9bfcd10818d36ba28); + tempvar res = res * point + (0xaa17b17cdb757833dd4b1670371ef55345debfb2c1b6bdfae64d8759e04349); + tempvar res = res * point + (0x38cb4173a2b057da41d5d30b55f6d11f25effdc69c14843cc43a9ab269630f0); + tempvar res = res * point + (0x4350a29d7b4b242b20b68f6eabd75b758d8631c192b7da5032181b71740b96b); + tempvar res = res * point + (0x42518069a18922e90fa2fa8fe9bf5e2371a40ea88c25d247e6a73a007105dd9); + tempvar res = res * point + (0x7f43f7128a1b46f8ab168a06df9d0cade82a3193eec2d51e2b83f4f0c7fabd9); + tempvar res = res * point + (0x6e694d9385207d7cc8a7cdbf90eb4ed3be49cabc0e6b8d0e69172d73f4a5c11); + tempvar res = res * point + (0x2782ab60e8e9c6cccd40f438a2d2814ef39f50f02bbeb790bc6df78d75af42b); + tempvar res = res * point + (0x259f8eeaf6cbdabd37b9de029661bdcb219245a7599207d3df08c7cc452a13d); + tempvar res = res * point + (0x9345d2e4fc86ae78c4879ecc3adf9e6c482044052bc3738618247b60f069ad); + tempvar res = res * point + (0x4419f27879dacd62144bde4f904890c6d5b312282335a57cf1b04b403bddbea); + tempvar res = res * point + (0x581755fd25823d2f3b07ac5d8dd1bd5b26eab362cec3f9e03573a2b03f62ab9); + tempvar res = res * point + (0x37622de79f6252ff6bb76900db06504434856faf33c59a1b2e39a4fa60ed143); + tempvar res = res * point + (0x2c4ffe18ae93ab53ff6d7d01a7b5bdc5b08dc8d144e0b917f47e60e3cf723f3); + tempvar res = res * point + (0x42ca1f8224d317275c78ca7762a78e6c51978afe1abcbf535da6d299c799c1); + tempvar res = res * point + (0x6403910df189d75aca61c604de3b0802a4ec2ffadb0ff60f1a01f363d66ea67); + tempvar res = res * point + (0x44094080f29bf84d3d5849f264713647289e9af1534ec38d1a7c3d2d2f1ab64); + tempvar res = res * point + (0x3dd2900899d2219ea16fc41413af028057f0c2a674e1cc65032fe4dcb062d4d); + tempvar res = res * point + (0x5a612887264b1ff8e5239b3e04143dc30d0a80cef1c880fe52ee2d5009092b1); + tempvar res = res * point + (0x5ca2e5676dde96127ca85ff6ac82a8fb35b45651b88bcdbfab7ae5298d427c8); + tempvar res = res * point + (0x4b135ec421e9138d09c709a5d92ba70e6944cd44a7eb7f705ab3612de315ac); + tempvar res = res * point + (0x152b3265b01fa9ce0cdf58c17cd14c2cf3e3fafba140db9e27da4fdde7d3c0d); + tempvar res = res * point + (0x55554f904554d2f262d1db49d7c515414870717c829b73d6c439260a8bba3da); + tempvar res = res * point + (0x3e2b9e4151827bb0d04858df547978536215dc06143674d0d2e788dcdc9c36); + tempvar res = res * point + (0x2c30d5e07853079c9f11624e2431795e2bd8b4bebd8cac92f158306b45b0549); + tempvar res = res * point + (0x4e922a3c7df1c668f86b866cf0c07ee4658e7754f6fc0fb62cb297bb6960320); + tempvar res = res * point + (0x35b787fb9889163a9fb5ab831838f19092aa4ef8d8dabb299045740959573d4); + tempvar res = res * point + (0x2d847968e995dcfcecc6ef98ab27f9f1db36b14ce3ba81b80cc92cf19750f88); + tempvar res = res * point + (0x6785d833096c9d9d06034ba4d7f8d71481d4b680b63693d9fa24ea10d3511cf); + tempvar res = res * point + (0x5617f72f8d0da5d7cafeef9269395ee34f921f5cc8d1a4f4c0292a83cb0b9bb); + tempvar res = res * point + (0x6a1373cca7777e3cfacc6502ca9bc645678445d98acf3d6f5ca6c82cab53174); + tempvar res = res * point + (0x5b07a69abcc274ea09eb67f2f6036b492db1f9b7e0a3497d8f3920de22b3b4); + tempvar res = res * point + (0x74399a1effe3a13a8effe952dd57142c254ebe807a56f13521da38984a0b55d); + tempvar res = res * point + (0x6a399f5bede4f507c7251a7ccd110e21173729f5f9a57eb16a27203d3c5e731); + tempvar res = res * point + (0x13102ce3fef387b552a6b8967f788cc8f8502ef0f2ec293d2b872328f78b6c9); + tempvar res = res * point + (0x2233376db0eee71ed0bc6ec0de23782ca9e244a06b8e515b2855b522259eda4); + tempvar res = res * point + (0x6319176edd9fe726efbcc70108b516e26152cb56329b842a1e14adc2a3e47b2); + tempvar res = res * point + (0x12e828f63839dc0dd62bc23385c0bdd5b11e7b6de2cddeccc47f85027c9862f); + tempvar res = res * point + (0x1b5bfb21e549706eaf5c771448f91d1ce03498029ff4159d8cd11f4b6d523a8); + tempvar res = res * point + (0x223b2c9fcd5a1d4b0f7decaab98bdf87e5083865ef9b6562a261fc75009e725); + tempvar res = res * point + (0x6856abcc37696eadf09ac823f589a05b034ef8f86e41d2c6222f039707017fb); + tempvar res = res * point + (0xabbe74553aa10ee20ec6f0f49f73281124ca34d0b71c2e80160f37d3ae0345); + tempvar res = res * point + (0xf7043785f78a94a68b669cb366c00538eafb8e87b5380c68518d4e23922d6f); + tempvar res = res * point + (0x43a4dbc140986d44a7099720e13ec46817f0131dd109a48fbbcf190671f35d6); + tempvar res = res * point + (0x7fb8438581e1ae31877119b91ef1ea28181ba8c0a89eb356313c8a910295d7c); + tempvar res = res * point + (0x125399adcf39aaf7962e3be41c6f9c7691e45c2c31b937e26257d94b5454985); + tempvar res = res * point + (0x3a3c97667e93fa5cc0531c8a2f6d9f84c4f683133b8941fe1382ca8f6f2fe0d); + tempvar res = res * point + (0x253548b05c44cb4d8f2d97641773cf812f709663fe8f492f5a77bfbc8477d79); + tempvar res = res * point + (0x3e828a46091dc07cbbbb0dcbf390e4b5cc44d086b0ba74051fff237f7d6a74a); + tempvar res = res * point + (0x74a80f191573d77481059c14f56764dd2c11571b2736d355efa299c400f0377); + tempvar res = res * point + (0x76169700b631b19086b8b1737e23f1c59cf1428075904c80db724383d3c6b5e); + tempvar res = res * point + (0x7febfa3ce41434e03eccb6be0099dc31d90e36558dfb6f9d21b3e0be41472b4); + tempvar res = res * point + (0xaee16ac845b8bdb7d9c1c85ca7b0e749a7c47229ba24ba097b4b6b8151cc4d); + tempvar res = res * point + (0x31cac8c51732d8aad5bc41c9a6440d482c2c4967e75a571c31b2d9aaaa64068); + tempvar res = res * point + (0x203db741e5e80c19c2bea387e3091420b918fe1142bcf2bc13ae7e098282fda); + tempvar res = res * point + (0x2449d2be3af1fcd8984a9f857309ab5e0e5c010680e33b03a194c6e902a553c); + tempvar res = res * point + (0x40246dcd91afc0098ab9568a5c97d54e09065c551bc9d26ba0ab6a00089bec); + tempvar res = res * point + (0x50cdaac85b8d8bbf55a920bf8d213e333eba5f2bd92e92c61f3946617222ade); + tempvar res = res * point + (0x65dbe95ea2b7d1894854b235f2cc66e910fd2791ff09b92366c7685c652a8c7); + tempvar res = res * point + (0x18f3259c8451dc5007e94efcc6e90c6951543474925fd28ff35e56890bfb66); + tempvar res = res * point + (0x69021f5cefc75ce473977c2ceae2e7c66a84bb3d734eebf4bf497e56eb69959); + tempvar res = res * point + (0x4ded7eedcfca4ee336fa075aef6a017beab322cf7ddf83bccfba05f1c93cad); + tempvar res = res * point + (0xdcc0df28639fd96570d93a6d1df1cb1dcf6db8a259ab092b34cdb411895aa2); + tempvar res = res * point + (0x2333165fa7f9414f082253b8451638fe1e9da3ba8c1246723dbf9995e49d017); + tempvar res = res * point + (0xc8b65a737b5605606028a064d168ccf32d8d87fcb55c6c853fd95ae0961410); + tempvar res = res * point + (0x71d72b0c23e31d703f0210ecb2b28994ad828417531a15a17a1fd401daca2cf); + tempvar res = res * point + (0x211c3e223a3c9c4a024b490a819254ee133ef9740a4026eb3a036bb9e5c6581); + tempvar res = res * point + (0x621692ad7ad27517f4de4e528e1271719cf5b344d463c86b9cd8424a4fc274f); + tempvar res = res * point + (0x5ab65084f4ee8261bfd290e2d5608fde744be92da2eadd5f2fb909ac3d14818); + tempvar res = res * point + (0x5896811c73c991f479c7af6238b51252178dcf4371c297326bcceeb8ee454e2); + tempvar res = res * point + (0x453705ada0d5db6b0afb289b29db6c9acedb01e742cb0d68705d07f8dfcfaae); + tempvar res = res * point + (0x168f97539fdebde7280f4d33f7d5b469cca77495efd4660f31b7d8018f7f89e); + tempvar res = res * point + (0x7829c898e33552459e8fff13c01f1e0d9f5b098f0de7161cbf97da52914bc38); + tempvar res = res * point + (0x5b23dd8ead53bea28246af5a3a63daabf41e7987fe61255d97f2a57bb6d14eb); + tempvar res = res * point + (0x7b631dfaa76643b5f46a069b8c40038f77f088374320add0ac3c9924a12f153); + tempvar res = res * point + (0x2408fff139dae5eb756ea03ef15a2484f582f7ab27ccaa09fa8154f3bf0024b); + tempvar res = res * point + (0x28aa32bfd8c8d7ffcb0b5dadfcfd1b6bbd69b02de9ac1bee786da98ce76c8e1); + tempvar res = res * point + (0x33eb39eae1db6ea48126be6b300b31f6bbe275845822f9eb293e9f7ac38a777); + tempvar res = res * point + (0x3e549a3d3849a09d8f1c50f84f7caa4aa0a5b8ef6f957dafcd13c7c90e4ea11); + tempvar res = res * point + (0x2f5e865731de5068f289b616b39c2294284c111540abfdbb33a39780eb0bceb); + tempvar res = res * point + (0x4e51def182a5bd5672ced3106f19ecd94b760dcfc68e66a3656d0b5db19165f); + tempvar res = res * point + (0x42f46c19b87a82522476372ae65817f8d53f263674a040531bb37935b289893); + tempvar res = res * point + (0xf0bd4817ef6ef818a35ca3678f88abb078678a1364539bd7886dad527cb28d); + tempvar res = res * point + (0x501f0235f18b49889497cf7c91fe0a1f81d74da8cb1e88bcfca9127392aabfd); + tempvar res = res * point + (0xc11cd155f0a514a5a419d10ffa72405817256ffc8d580b9d3ab002f596b2ff); + tempvar res = res * point + (0x9f712ae0384a87901ad44f53eee9e7c39544893d10b891a92e87e4d78e8374); + tempvar res = res * point + (0x2d511bed457c57d7354252189efd19e4f5c3496c1dbe1f1408ff79c8cb97025); + tempvar res = res * point + (0x6c8d7abe5c83db80647ff904bdbf25bd0e979607d2310ffbefaa1edb7ae1bb9); + tempvar res = res * point + (0x46e747695d9d234e15781125d05b85ce3cb01d676ef8fc45a939d5e6d4e2e56); + tempvar res = res * point + (0x21c86da8be11246b29f17d5f7f3566c20712711e03eba57f0ecace8c4355418); + tempvar res = res * point + (0x7b851f4004fd9f20561e3755d7c89528ddefddbbbcbaa9293e416c0dfbb95d1); + tempvar res = res * point + (0x31587ae13086228663118a1fbfad6d65bb9741d5682abfb43c7524cc6c240e6); + tempvar res = res * point + (0x2ef1cb499e790f2de6129225457520b560c1c3120457e742957d1148bb934ca); + tempvar res = res * point + (0x781fe3d95c096c6df1c9ced110914917e26d0860da4bd769e4682a17540768b); + tempvar res = res * point + (0x7cf92bf7e933187b6ea01019ed1c2d9936e53a9ea89724e00e36672dca1e36); + tempvar res = res * point + (0x290b573a86b30d59fd1301b7985a68fd9bf9dfca5451179bcd13d10eee988aa); + tempvar res = res * point + (0x4d3987a0850d8159f9290a8ae8cf99a0ece9961d22135b584d8fc742d42c15f); + tempvar res = res * point + (0x6247162754e5af6a0efa837daba678811cd749e92d91acf35d732aaf4bfb4f3); + tempvar res = res * point + (0x1e3df9ca8b80529441770e007a27cda52e54307e4f3370a83705e0f3ffc86fc); + tempvar res = res * point + (0x25579cd0082839ce295d9bdb24140a8f2fe19f7d582a4993a88639a0347a522); + tempvar res = res * point + (0x70181ba88ba8d19c0220225ca0112845e23ed7609ffa4f2aea3cd40a40eef30); + tempvar res = res * point + (0x481c8091e40139c67f7e69737f83a6c868e582526afd50b548bcfa5ec2e83f9); + tempvar res = res * point + (0x1a758f2faad6702cac573f8ee11d83977ca75744f52d650a6dff79bd6c5caf3); + tempvar res = res * point + (0x5a87e6f4731da56e8b078bdea4cc3f1fa2059943de95ba404ab38addce3d6db); + tempvar res = res * point + (0x62a78aa9e73bc6da0a8536da8dd43311ccfb52829e89e9e94f3b413efb8ff93); + tempvar res = res * point + (0x4cb8044c471e8cdc896ac725744d1a6942bcb26d50b3641e2a95f57b0e7dddf); + tempvar res = res * point + (0x57d63baf011722f5c5a9c4c60899bd918c3287302c97e91fc6f9f8ba089cb97); + tempvar res = res * point + (0x60de66fa4cc5d53fcd9d027cc06945a96de2f9b4f7d0c81c53a7567fde886dc); + tempvar res = res * point + (0x794e6f83556e5ffee6d83daf40a067363b22e157cdd970366757d5d6a02dbc9); + tempvar res = res * point + (0x1dcd10514fdded828639c9c21d0c8064647947e9ced01014ba8943b1d81bd12); + tempvar res = res * point + (0x7cf749a9a9177ecfa46b901ce91a8ebe103f8920d83713df80efb7fc8868346); + tempvar res = res * point + (0x1ecd644cdd8b92b3c042932407033c073c7da5f3a8726210a443f10af466ff5); + tempvar res = res * point + (0x55b74b3af769611aa4c4fc71b1abed4396b218a9d5884844c937bc38b30bf8e); + tempvar res = res * point + (0x4fc4e265c8471510fe6f0dc99d7be1108eab6200b0845dab07c5a126c79919b); + tempvar res = res * point + (0x37edf969a82e9364a741858bfca74b30e86b1b69b4f33bb4a31666f4b2e7c10); + tempvar res = res * point + (0x2a3ca69d295e5e750b4db8367227f9cb347b3693251ba9761a22d411de1c41c); + tempvar res = res * point + (0x7e9f729b710f0fb173b36a6ee9611a9d309a9dc69a776c08dfe63c64c528a45); + tempvar res = res * point + (0x1e2c3057002cdd12b80fb157887fc066b41436bbb71e328bf79ed2799947c49); + tempvar res = res * point + (0x32124f76e477a3c6f5f4346f8abc19cd481b6f43088ccd1c3e8c634bd90cf); + tempvar res = res * point + (0x5007d334256950aba31d4bedb5decc0ba6ab62a09c41baa8ab8d0eb4cdc170d); + tempvar res = res * point + (0x3a06f0e39b3afd46934c41a79a317f220c6321664cbe236ffe1c191ee0b2c85); + tempvar res = res * point + (0x18db208640b40e1acf69b256f0cf86c76f381ee79fa0bbea47fed2c95b5467c); + tempvar res = res * point + (0xa0c5ba0b916bdf79b70c0d23013443f65bd087aaca62088b0d1f7009dd2d70); + tempvar res = res * point + (0x5dd2afd2e8b09f86360d183e2700f71a4fb5e458c61823ece1a4e60200b82f3); + tempvar res = res * point + (0x5b3102b46125dd26f3ae75c22cb8be10a3c98f269a2e91ce7d595d25c77e6aa); + tempvar res = res * point + (0x2c489389378216a8f4a24999efae5d41af3bf123b10601d2efb419999f329e9); + tempvar res = res * point + (0x28bb7956a08b64ed0ed089f0219b05b282eb25c107731d88867f7a78c3e387e); + tempvar res = res * point + (0x450e38572d5b45eba95a4368d52056640cc18213b3065bb7b373a05561cd44f); + tempvar res = res * point + (0x6931414c4f1e51dd287a8273a71ff946d1502d29539815c6652e6b71c95d013); + tempvar res = res * point + (0x48fdfbe3980d1df8db00fd59b4b529abb0569c82a25c6b23186de11aee23a40); + tempvar res = res * point + (0x680f30c7e737040028b548f49d2110d8889aa8dec6afe1de989e3f1f0c1c84b); + tempvar res = res * point + (0x8955f2b26c2c91645402ea61e0b3bd091758afa740b4478e3fd2d97b7d5729); + tempvar res = res * point + (0x62796f07255aabe16df1ca5ebe7f7be4eb1e9b688defe3044b1fb8eb56765a3); + tempvar res = res * point + (0x29f85ec8df7c753f09bd36309e6d7d65f5d5c327d4c80ca33eca932da5eea0c); + tempvar res = res * point + (0x40f21a24062575a80e5a6b6fa209f04178fce24323888c3fc9a083c6cfffe71); + tempvar res = res * point + (0x29eeec3cf3ff9267792e170045fcbc1358ad5b9c28b97db6f4cb5a131dd1e57); + tempvar res = res * point + (0x6d82291b429009057a7d89082c7c3ffeade1cbb4598b6bd1322c2e2d3c6819f); + tempvar res = res * point + (0x78ffe33137f03476882656c458a984b78bfe509d0ed005657860541fdd16506); + tempvar res = res * point + (0x13f6d5bd19a25ef48bb5a89c64894e9351380c31e98fcb8404c490081665acf); + tempvar res = res * point + (0x36d9f7e5746b465ccd284ac21d5cec14258587d22189b4f85ea87f9b4d7c2ef); + tempvar res = res * point + (0x54730884e1c5c7ff5bff889e8e5846f7e552f07beedb27035c0eaebfe676023); + tempvar res = res * point + (0x7344cd22ecc8029fc605bc46e5f2f60c2910130290257210f9db71f26dfbdcf); + tempvar res = res * point + (0x6a60ae65aaae41d02d6ad44360c269051a870c66a87e430eabd1c2c5dd8261f); + tempvar res = res * point + (0x639a281c19217bb79dde39d86549ffeaa0694283fa876ab39fa6b663869ac9); + tempvar res = res * point + (0x48a07a1f3adb4348f65ca07f7e1ad0b70a6024c4934df5724c35f1930befc90); + tempvar res = res * point + (0x527d59fcf4e21663d7e921cf93b705e95fca41d9d2f88720800586e03bdc283); + tempvar res = res * point + (0x1b07576ead1fa791e38995e423ee788587adb512c1bda749fc0869ac6b40c6b); + tempvar res = res * point + (0x7b59c1f0252efd3b471c3047a2060ccb98cb86148c1b1893af4f86384821b04); + tempvar res = res * point + (0x56e48833c5707aaa1e38a0d644765251c038ac3f89ed4d58fc3b24d03a83e77); + tempvar res = res * point + (0x14d1da51db79b82ff5fc48e18ad84a98b1390d8e61e1580ef5c6100d49da80a); + tempvar res = res * point + (0x6ade2f8ff114a1c0a0f108286f0f0e820073e7fee989a85fe11a97b972f077e); + tempvar res = res * point + (0x20268b11ea1f54c737a14073b8bd83a6151aa30b0d51182446adc72aa2bef83); + tempvar res = res * point + (0x937368e9df8289ef2d93e806914cc9ac730750d1ecc6ccf6c4aa6e6788d35c); + tempvar res = res * point + (0x297d16ecee6310efbcf8a2946e1f03e23ce1eaf88fa6279dced371db9dbc299); + tempvar res = res * point + (0x74d40da7c08b8fbd488137dcb60906f2004a26faf06e6ee4dbe1feceb94d98a); + tempvar res = res * point + (0x5669aa7f25c6cefb4a3e1f5491dc50af7c44ca9f8405864906b353c4c3529b6); + tempvar res = res * point + (0x4a5077d73c41429dcb66a5557cd392c5e8b64f4f93507e5e7b8f1cbe29a309a); + tempvar res = res * point + (0x5974550418ba46ba346cb87069b6c17f9a6d57ce7554827c8191072b4ff8357); + tempvar res = res * point + (0x6fb7a7f6c760b606b4f7cefa186540604099bd229b954096179a12ccd50e323); + tempvar res = res * point + (0x4fe2139f7019584c7f395a18bfca2f5ea89a9300bf208b9dc73686c76e724d6); + tempvar res = res * point + (0x4b45d3cd223171c9e2e8030a3983c2e4b6ed61a560db3a8da8a2bf1da05ae2a); + tempvar res = res * point + (0x223dbf6f82e6f2b2dce8397a7a6d00c8fe38fdd8463fe7612c1a90bb76a16c9); + tempvar res = res * point + (0x13e7cbf6809b1c282b1716db08a549825b9e1f24479288cf615c6557249f675); + tempvar res = res * point + (0x13b2e8b26fec1c97c5fac659532830270b08cc6861df86b3f3b4894175551d9); + tempvar res = res * point + (0x34a45f657061a57b808e337faed21f722e6298262a2df69d6bd34ecf2e29243); + tempvar res = res * point + (0x372a448e249504e459982c7d114b3c79270419467208096cfa6a96f3e5de755); + tempvar res = res * point + (0x5d62087a11238dba183191a31e686ffea34bd393310e7a2b11c75d63ec340); + tempvar res = res * point + (0x5f25fb2b70ae9e334bd288d6768a7b3b6b2f4672cb671f6b0ebd781134609d3); + tempvar res = res * point + (0x1025bf3b6ef4dc8e3637f4dd1cda0ea30ebba8c30ce5638b5f9b5291faa0036); + tempvar res = res * point + (0x7d2b1bf76ecca560b7409dee16ead5b2b3691ff75ef8fe5a844306a7e29b252); + tempvar res = res * point + (0x7cb9fc14dc4bbad427efdb3f5821fc9dd10fe8595577e39645ab9f62e6fa50); + tempvar res = res * point + (0x6f61949d4cbc8298879b470d1fa9aec82261a8099c448dfa4379a597ab01d03); + tempvar res = res * point + (0x336d1ccaccbef10084bc4a18f8c86f699642878a2b5d5af3a3fbe7a773e6904); + tempvar res = res * point + (0x354e8d015485a06adadbf43a6bad63e9330c4070fbf2a704c166e1d278c8d4c); + tempvar res = res * point + (0x45526e767c14a531fbc10f287b2a4203e18daad8a4883a1900a63dccc1a18f6); + tempvar res = res * point + (0x688bfd9b23436077dd139ccf0a7286444429f3a2457ce7e2cc939be2172921e); + tempvar res = res * point + (0x5dd26663ad2931b249bcf054211723be60b5b46de16a61928c0a9326874f3e0); + tempvar res = res * point + (0xaeb2689fd195377c86c55bb52ba2ee27c7c5395d8163355a3c04135b43333a); + tempvar res = res * point + (0x73ce15dc2409ac614aba33d14c4ad294a3a8136eec69e8b34b0b14b92eb240f); + tempvar res = res * point + (0x73a3905fdf4a2f53d66ca4cb99ca729e776ce66d9a474fd71da35b3fa949d34); + tempvar res = res * point + (0x1d60249bd6492637249efa94de232264fa23d62153d7a36e99aaede0be5d842); + tempvar res = res * point + (0x728595451b9c3918b04e7ce1637804c1df21495ad8f188eb46a5f1796e2e3c1); + tempvar res = res * point + (0x5dc73d8837d2fd0c754ecd371e94f0af344396efdb4337a8c7c2a0755838f46); + tempvar res = res * point + (0x7dd917167308b602914680880c9c8c8519f34be930ccafbaca3d126a30c4a45); + tempvar res = res * point + (0x1950cc259cc77027d5c86ea77f51a34cd30ad768676d77a0503f36f797eb4af); + tempvar res = res * point + (0x4d5df514fa9a8bd7515039e59bea7a1a1381a76f475a7dea23549106a7df8e2); + tempvar res = res * point + (0x1d74577e412af12fd886706cdce3c238f2761d096043a084c20d2bd087ad4e6); + tempvar res = res * point + (0x7871f7217ff1c7b739678e28908c4222f492ebf866cbcc410148ad1d143de0f); + tempvar res = res * point + (0x59a88072f92b384925c9091497269ba9f8226c24f740e928e410ae0bfb9350e); + tempvar res = res * point + (0x19c90daa3645b62f461545c7c38ce5bf8b5cdad399f417e0abbaf2b2df0ca64); + tempvar res = res * point + (0x53b86dc3cb8ef3d5920ea35c40e2d05496e45245eca4e0d058e2a0e2d583dfb); + tempvar res = res * point + (0xe00c78bcfc271dcc6556cb1cf6501e16d20b188c7412681c0b2ae0f2cbae05); + tempvar res = res * point + (0x36ac6cfd4f2ef6be5b1e83cf9e36e894b2575a8f4690c14484a17c222ec3c00); + tempvar res = res * point + (0x32cad92232ea7886b829887e6ca4ae084800803277076107b1078feb66e95bf); + tempvar res = res * point + (0x38269de0c80a2d8f4bef1d5e76805d1e412fef7b18886279e98c57a0fe64627); + tempvar res = res * point + (0x217df85b26b6b3bfc67bec919866b6e146621c30685a31e8c93eaa27d5dbaf5); + tempvar res = res * point + (0x4ee32b2ff29b0918618f173c4e5dc3b606a1ca2e0eb989257e0bf78dd2e9589); + tempvar res = res * point + (0x2d51937feb119772693523625e23756d172e996d1cfb82a258580bd51c15e33); + tempvar res = res * point + (0x7c2468c14a7ea994c89e2e4ddd6d2d624b67a96e7ccec4f27a5e0122531291c); + tempvar res = res * point + (0x602aca232b11ad63241b5f401c368acb1e9cfd4e5fc8ae699491d9c51b4db18); + tempvar res = res * point + (0x39c92f0c55d99aa6b082d21129a9402e6b0fe38a639a8140d76ebee9dc45877); + tempvar res = res * point + (0x4fff8b45f7ede0580424c4e2c75213c4c42ec6c68266c8d5d750a2863bd474a); + tempvar res = res * point + (0x3ba2c93d59d6a361b9ac28d93e54d775b040bd7fca9ac72339ea4388c533dda); + tempvar res = res * point + (0x6d567c1dbb663fb2fd92140cf66ea33a19cda580d18c10fe56a62e5bd3f47b1); + tempvar res = res * point + (0x2781266a2070c9d3f045010a32c98ce3e0765446e3ee20eacd73a0dc0c7c2c2); + tempvar res = res * point + (0x7dcfd5001e21e030b006d54c7fe0f7ca97a2c18d4e00ba92c005705a4f0563d); + tempvar res = res * point + (0x2fe4c112d7bfd4ad5f81ecdc4b30cf73aa51df4e4ba6d255a0e3eee283aff46); + tempvar res = res * point + (0x2433d40f2b8f9461b5368cb396f7604999a735414d3537ed6f1451f1fe93cb3); + tempvar res = res * point + (0x72f959288185bd36ca4e23472ed7a2577f8e5f0ef0c0d5df6f63e60f40ba307); + tempvar res = res * point + (0x4c5592288cc342232d76c80e858c08ecbfde64b747637ccc9a2734e90f85264); + tempvar res = res * point + (0x48ed57151b6dc68b039dc327f79bc2c26db62ff957809c5538360facc04d9c3); + tempvar res = res * point + (0x5ebd9b268cc66bb85a5e67a6b9d5fdbeba8b3672491068ef43b688a3a043a33); + tempvar res = res * point + (0xdf6c1013f3076e6044f0a7032e0bf80833f3c7d9eb0c3eb1f3c2a37314d19a); + tempvar res = res * point + (0x5f0cb66613216a1339c1cd15239b7f03c1d4b9098a931f65ae50b877f861880); + tempvar res = res * point + (0x5d5fbd560f7bf1e97190f888fa43b32db1e8070f046d6016b536b94d1473a57); + tempvar res = res * point + (0x33381003a653f0327cbdd8a11252ffe714e1061ee214329cb99e667c835af97); + tempvar res = res * point + (0x7b86849a979796096f7d7b46eebaf00913a082c638c5b2bfdedbcd78c480272); + tempvar res = res * point + (0x5f27bcacc10845ad41cb26244112faa8b91d46d97024445f50ced796ac5a93e); + tempvar res = res * point + (0x31cdca47c96b32e99077a96aa5cd73ec9c4da04212667805c82dff3e498f4ed); + tempvar res = res * point + (0x66a032c182ae70dd4487897d0c79dd860a25d21c61e3aeef8b9fa45349dee89); + tempvar res = res * point + (0x148523eabde5554538a1114351f3d8730d4a4d003311c7b57ce9e709afeeca5); + tempvar res = res * point + (0x62ea67803c421a4bbdc672d556bca219fd24e7145cb3e9113a625eeb4459254); + tempvar res = res * point + (0x2c2c70075ac99cfe68a7354ed29842c5207bbdbd09dbbd225ea93d0c07fd9f6); + tempvar res = res * point + (0x48b0cc6241c99407bb346db57db9cf82b2e66d1fcc1d756889a4f4b4bb8b396); + tempvar res = res * point + (0x506f990d7037060dea08ed53c5b17483ca8a7c58f94ba5e64fae258be4c78ed); + tempvar res = res * point + (0x777be5852ea7798899d4750e9decd1430bdad6a8b0d1827a7a89ce6f1afd89a); + tempvar res = res * point + (0x689fb22cd95d6f1868a4e3cd6ef1bba9f974931f76153e73038ff5ae7d09018); + tempvar res = res * point + (0x560fef0ed77bc94e16b9d9a21bec0ceadf81b26fe683b9c74b31e2d72a4c92e); + tempvar res = res * point + (0x28c74f03f409c942d16a773fde01b3f0bec544b42c1d46944db6253561e1ac2); + tempvar res = res * point + (0x4d62e1ef04cb039a58dd8cb8c37dceb78b10fd84bbec6302c964b899a957d02); + tempvar res = res * point + (0x44094c265809e3d5765071826547999dce8ba7058a7c1b1301294d8291949c); + tempvar res = res * point + (0x4e0f90743d3df3d3c4aeb80e7f6db457620430ff28475c6194c757f81927dc5); + tempvar res = res * point + (0x2cde734d2a82619ba69ca4f5ca5035f699a1e34b47560d761780546c9b04d44); + tempvar res = res * point + (0xf09069dc6a2745587b447ae03ebd6524aa9757f1090a92dc5e7ce8db848195); + tempvar res = res * point + (0x5522f48902001bf41de34be900783ac957fd867cca0f35666ca491ea89d8fb3); + tempvar res = res * point + (0x5b4be8af83915fd955ba32de729f6f2aef6c76501d82ee325d72d620bce8b7b); + tempvar res = res * point + (0x78e74ffaf944c363f3fc42cedaea8a9a450ebaac98bf1327590a11e064bd76a); + tempvar res = res * point + (0x6ade7c482d201c23145e3890086b22ab0d43495f5c83b1672316c10ca52af0b); + tempvar res = res * point + (0x79c066efe4c22c6e9e097e84401e183d3c45c645d986ed640a8faf8fd4dd096); + tempvar res = res * point + (0x21d59ca7451d83d78ab4d9d17a662367ac84b555866ae92d036d71de22872bf); + tempvar res = res * point + (0x6d100d3db14939bb442e5f5ce6a05939f201837007331536440a57c2bf2b609); + tempvar res = res * point + (0x7e5bc177982061f124cbe521c713c24438aa021fe6928d82452e44f6cdcd631); + tempvar res = res * point + (0x179e4b1e4817460085d47376a1971fdcb0287408cc7d11fb62cc3785772249c); + tempvar res = res * point + (0x2a7cd1fb12f896bff4d3db49ee74a51e970e3e386c2c8e7622412a6156a300d); + tempvar res = res * point + (0x3c5581c15733dcc4d548aa0a6e648e075e9be412680a76a556f91ae5f01e44e); + tempvar res = res * point + (0x4a4eb8f57c99e931a666de76c20173adcde82ff59fd8ecaf8b8c05e29b63fc9); + tempvar res = res * point + (0x58fa31f9a4a7e8b238898eb1296ec55e3e2000a48a2edc8e65d260d31bfd7bf); + tempvar res = res * point + (0x2c37f85ac7b1aab52ce3d28bfc65c65b7d4ffd000757c07fc493d183b7bb582); + tempvar res = res * point + (0x461b788a24347588e4f8d4f2d66640f31d6b580223a21919ccef9480987db1f); + tempvar res = res * point + (0x47c3222376f8f18dc6e82eebaab03fcf4c425acd901a7bf9841a3aba54b82a6); + tempvar res = res * point + (0xbece573771924d045b75bb992a87b26ab067a0f2dba4d1a9efbe5029963533); + tempvar res = res * point + (0x67c2a0e19b59921666716fe2b3f9c7f59c4da17d993956eb87eece7ef542269); + tempvar res = res * point + (0x8940bc9dc45fd06ce4046337963c849324bbe5f82632b94972c0ccb205480d); + tempvar res = res * point + (0x38bff358ccfd92418537a9b9858df499d2c44404c1886b109edb14c897e74fa); + tempvar res = res * point + (0x533a5a2ebd098297604e96118f2007ddd12af50edd525e9e5a0b154e620b2e5); + tempvar res = res * point + (0x312411292b7fe7eee015fcfaab65b611bc2b9f9498489fc3c1452862902bbf); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_pedersen_y(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x62b07622f501888a668440d9b856be4b0c3bf12a401fc2bebaeab4a7e1684ad); + tempvar res = res * point + (0x75a127d817aee244517479bab5c4bfc2a0035d43d673badaf64d8adf94353bd); + tempvar res = res * point + (0x14f3359ce0d2891d1bc2b6f4d2d6dd71fe22925b8a09f66147db095a9d4983); + tempvar res = res * point + (0x2d6129632b4fc43e4142abf55fe2d1f3e79dfa01c73d8fb56a465dbd07a9682); + tempvar res = res * point + (0x5115ade709c058be5dc6f406794062642086e431bab03c9a86d53c79aa83db4); + tempvar res = res * point + (0x29f6aa5fc92eab8b8b9871c8449c1f617b808ea9860717f3e5e1678672ec565); + tempvar res = res * point + (0x7e08f9d222cc0764fb5ca69e51ad4cdb7f1b612058568a142bc7a4cdd0e39c4); + tempvar res = res * point + (0x54c5dff0aed23c07edcd958ee3690e617011b87a5fec541725237d4ebf34382); + tempvar res = res * point + (0x2b7d501bedc4e7c604b0e55dd2d8166fa39a541efc24d81d8464fabfef3fa37); + tempvar res = res * point + (0x68e1d50b4d0570e357eac7bc742ec26dac1edc5b179989c7ae8d31791639103); + tempvar res = res * point + (0x707c572424682b685a1ba90dfd7e56f86254862d86e20b5a2d3ca85fe0017ad); + tempvar res = res * point + (0x2cd9a093ece61e554b2bdde3ec474900e4412775ad25456e5be6e11df7b9fff); + tempvar res = res * point + (0x7492aa940f34a027f8fb3700f29cf628c1d05d1675cb7865509f20617a90b2f); + tempvar res = res * point + (0x55e928ba557ed7fe0ecde6d1fbb83d112e6b06a087b4013b9c425fa36eb0415); + tempvar res = res * point + (0x3cdb28a913a41d597915de055aecc59f2b13079d3d8b33ab0a075eeddb1bf8e); + tempvar res = res * point + (0xfd48fb35400aaaf57d130b6143b241db8af174cada72ede8f2fac4ec6688d2); + tempvar res = res * point + (0x133b6505a6afd2e5fada0e53ea51c012e4935ea6d2d02caaa15ffc50a45079b); + tempvar res = res * point + (0x2d2d27711772cafff2cad828dd78d8b213e317e8939cf79164ae64dea577d61); + tempvar res = res * point + (0x60ac57e328ff6938a17d43e6137a55399b95459be60fe980ed8960edaeee10d); + tempvar res = res * point + (0x7b056cb6f172b25e3555d6b1422ff769fd4c07258fa16b03609f0e374012ed4); + tempvar res = res * point + (0xd21afb1901f1b3ad66587a7fb97ee06662edc3bc8c8d32b48625a135ba23a9); + tempvar res = res * point + (0x7784c2e140072fd26e95911df38f9a337107750a72b9ce05a21a0f781b92dba); + tempvar res = res * point + (0x7c1667b8d44d288c4f5150d01c5206d4d5868497630745b6916466c8a5b1228); + tempvar res = res * point + (0x491c2243a95c44528b86167a4418ff9d93a04bde8dd7a5d2b19ea579d295312); + tempvar res = res * point + (0x6aebd7a9279eba43cb1c0b14bb723dde464a86cac92518ca16ae27a8684d9cf); + tempvar res = res * point + (0x709be747b0a69a9523680ff69e6bfea4637bd570ce5c45256b39ff695557da6); + tempvar res = res * point + (0x47275cd67ff3b7637ed55ced299a6142a821ab466a897f1eecfc8bca557269); + tempvar res = res * point + (0x58ccfd44df4e339c65e1423eaad47210f2e16aa6530d3d51f38b70e5eb3a623); + tempvar res = res * point + (0x28218a1bc7586b71ec1989082b8f7ab0efba14569c6f6e5d7aeee1964ab6d70); + tempvar res = res * point + (0x660bd8049bd301d093aab9ae530bedc37467d4ff0a12c89d689d61ef9b9546a); + tempvar res = res * point + (0x4dd38543d129d0a71b1836c6e2eae47fde5d572e32ee9a5791f7ee823eab4db); + tempvar res = res * point + (0x8509234000e130c8828328ae4997d5116117716cca9490e6e63f30b7df699); + tempvar res = res * point + (0x62ad4d764ed0072a7649425270e2b210421c77d3ce98e2587ea5440a591ecc0); + tempvar res = res * point + (0x66c5222dc133e37dfa0566c49d107852d978eb7454489d3b2ada8de022125d8); + tempvar res = res * point + (0xe4d1f1f1f9b379bea473f76bc8f3c4d530335e2d6bd782b42324872767b628); + tempvar res = res * point + (0x6ac2f92bc4c04fd50ebd3e336b53b866e790ace39838aa96a4b791011455b29); + tempvar res = res * point + (0x59d753a23735a336c50466f5ccaab3671230fbdaf55101530e5f562a5efcaf5); + tempvar res = res * point + (0x166b26359c51d067955874f5612eb70806d7b8d5de4d8e0a75e0d57b39b1846); + tempvar res = res * point + (0x2dd27ce7910e44ee00ec3335bd79429846a70d92d482adf81b36a9ff1aaa30a); + tempvar res = res * point + (0x45970c86c25bc9a68f2e2a34969faa2134c95b19230fcfe7436c98f537539eb); + tempvar res = res * point + (0x539cd2c1a28df263709cf0eadef73a600f563ab3d82c27692b1424814cc3e15); + tempvar res = res * point + (0x31eb3b57e6844e3efc1e3975ea393476d8aace5f43ca62b09314c90b8ae9688); + tempvar res = res * point + (0x47359c8dd2b86e4f634a9a50950abde25942877bc5db93d62bf43d2886692e4); + tempvar res = res * point + (0x2d8ae7b28c8c3acc8bef3d4c2a9f5ef1323748de693a9a1ad3ff8601116b165); + tempvar res = res * point + (0x4538fc863186b4babe3b424b4111251bb1e20ba5516be54160cd560ec0d5a3); + tempvar res = res * point + (0x559548517b1025ad61020be3e252b6ddbf1d5d53043231f8850c0da52b8268a); + tempvar res = res * point + (0x3132d42e4a928c08a972e17b2c3b500dbcadbe6190b2e7f5b58300a0c8a38c6); + tempvar res = res * point + (0x5b02adb78afd4e219642a1fc38b2ef9f63926841ccfda072ac17326d3d50f3c); + tempvar res = res * point + (0x75971517855ffbc9657dab30657ed1e3797307bbec1ffe136cb0d8a64ed6eea); + tempvar res = res * point + (0x174a4710688db61da7559255caebf641a268b4df53d45de5e8156d36b4b2ab0); + tempvar res = res * point + (0x295fb60eec46a40a33b1a9532427b42e224c0ac6c50e3c1c5d17c2c16651a25); + tempvar res = res * point + (0x2037a7d08a1c4fa4d5d4f53436a252302840007c09163026637e9cdddc958f0); + tempvar res = res * point + (0x7e9e1c3d4bd3231686c235a495f737a9ec3d633331a95d85e17e90f99a08af5); + tempvar res = res * point + (0x218da336adf8608530fdf8320c4edc00631d36c8726430732038a369548cf56); + tempvar res = res * point + (0x78c7b0512cae47833eb6bf01c1075aafca19eef9b32e37f4f9a9eff315637c7); + tempvar res = res * point + (0x628226c46fe0bfa8aa36074ed0785cb16461ee2945ecee9deaa6399bba2742c); + tempvar res = res * point + (0x2eb6bd70a00ec26418d347df1a444f7ba0972416103f00c771e0f3d50bd8e5); + tempvar res = res * point + (0xdf82eebd6cde9b50958606c6ff83c855c43ce9613fec366c7792cb456ea913); + tempvar res = res * point + (0x4221572cf29651f508bab9eb82545b17cf6f9efd0416b65262e5491ad408e39); + tempvar res = res * point + (0x1d5fc46deed0eb9b56cba1d2bf8075227504aaf6ab1330b346cc3cb84a07cc8); + tempvar res = res * point + (0x55ee57d4096ccf0260baa2a1a2639978d965a786e4fc917cb2426f8a99591d2); + tempvar res = res * point + (0x21706619a453a544bee0ccaceda9fe69f860c894b36bc9cb7ea4455dd88a9ca); + tempvar res = res * point + (0x76ea16625d0cf0c04f096ac7d6eacafd00809ef1d1a3cf5e37dc2a13a02d303); + tempvar res = res * point + (0x6d0d885e8d2530c7a324f7b2ef47db35aa8162289a4420a54f13a82b871d850); + tempvar res = res * point + (0x471bb97187c83c0e7b51ab70022147e8d8ebe25d4081907e7d1bee8d6c6581f); + tempvar res = res * point + (0x12b9157240a237f319beefb6019bf0de1897b9e2d8e5536e3a21d8f9fd689e7); + tempvar res = res * point + (0x2ef7f1dfebad70ef549da1a143c838cea27749807efcb1a0a29cfab16420928); + tempvar res = res * point + (0x519de0df91b17442a8f60b512297d69a1b516f70f67d76eb9c287f06e37c55c); + tempvar res = res * point + (0x2a45de0b79a4e9c53d47f6126d35b1d050775d5fb17f3c3dc22c7b6476608c0); + tempvar res = res * point + (0x27e3cfc87448bc0392a0d6c1b1aa06626636fc703bbcf3717fbe6f0759c4855); + tempvar res = res * point + (0x77a45066995089dbd4072d6817397ce0c7e92b53d19338e9bd7549e954bd961); + tempvar res = res * point + (0x3139ae970d95891aa70cbbf6f172223e07eb521a5149b7e0c9202793f6dbdb); + tempvar res = res * point + (0x25dd21ff92e6f1075df6b5ddb2b774ff963b1b84a985261b1e94ca9eedaa49d); + tempvar res = res * point + (0x13eb9f5362c087af5ee758bf0b589c0e34af337b3c06c788573534e96de30b7); + tempvar res = res * point + (0x6a39a27be962632e0bfb245f65a4d70912d1572e39003d63def5f45bbcc8f7); + tempvar res = res * point + (0x2c11fa8c0ba68518942f1c686dafd32aa26545886d28cdedae00071360df674); + tempvar res = res * point + (0x7ce49a9b8d374e1174ae6ccea7cae8d743404552253f7ec854317722a5efffe); + tempvar res = res * point + (0x6bf518769635f9fa39c1258844d4f62e5fc00b70792944da0a939990492313b); + tempvar res = res * point + (0x6123efb57144c151864b4f717a44cecc667fb2ebc47bf24bda4f7d0ef8f550f); + tempvar res = res * point + (0x2c29d0056cfe7325567a9f2d09d917b37a45aa3cefe20b78c4bda2942af59bd); + tempvar res = res * point + (0x76914b565dab13e76053b7a74c24c005b0930011e48ab26db44b6b49a1e7ae5); + tempvar res = res * point + (0x648c35904fdb8bbf9c0bc9288319c248e17974fbb6616a70acdac004878bb9); + tempvar res = res * point + (0x1cc7ec07c4e1e6626b5263044071687d0ad34ad4d08996a213380e9b728585b); + tempvar res = res * point + (0x154a5ad294d41caedd8d927eac226dea1e2b78f6ed0a6901a00e45ae0ad78f6); + tempvar res = res * point + (0xbd5fd7dcc1ce2bcd7f7415a22115f0c846d16ac7458e6c531e7e44dc664962); + tempvar res = res * point + (0x2b2b08bfc4c3d5941538b2eda43b3cd009656cf83b6b23be56b3041df3dbb0b); + tempvar res = res * point + (0x5e48cfc304417473eb4e587942a76921fb007d8b11ce648d36828e8cbb5d595); + tempvar res = res * point + (0x79c11c262fc2efc9aceafe4a5886713151352e60c4db45826e0e343cc5919a9); + tempvar res = res * point + (0xe2acacfba8f832e4e3cffb6ecf4675df678403610fe91363172229444ac0c0); + tempvar res = res * point + (0x6dbd918c7623bb07b05ca515146ddd7193373250e0836062fd1c430e2b7894a); + tempvar res = res * point + (0x61b210c04a0899fe2a3dc53348507d6f53d4cd3831644e4630eb40564ee5b47); + tempvar res = res * point + (0x1e3816f2a6a4900b65d140d144225a8a81cb3ea22f56de3cbcfe3944fc0e898); + tempvar res = res * point + (0x3c99839cb11fecd878ab9efd1d2ed2a718f6e0df4caac1a070de06ddf1a6091); + tempvar res = res * point + (0x567205f3e5ec69ce7962918c41ed0309c3ddfd85fc92702ce1c207b282f17c2); + tempvar res = res * point + (0x10382fdec78a18047041629179e18ec7dd067bed125bf5fe83f13d637a8ff67); + tempvar res = res * point + (0x43aeb91e6f453d372353d9814a85c21617e6c934c694a0b06100e1e9aec4087); + tempvar res = res * point + (0x2b6a2e9d453e19e3d766f24cb7c6753f84adca0f75f7a871092688bb5ba0d37); + tempvar res = res * point + (0x1f3e3e61713ab64544b28dfcaf4da25b64e625048ca55cc783dff614f5796d0); + tempvar res = res * point + (0x364cf25e248a3f2fc2106025945389328c0ef37848a59ff2afdc685c0854822); + tempvar res = res * point + (0xf9762bf5620ec90d711f12cbe600f29906fcdcdea4f17cf51ffad2e07887e2); + tempvar res = res * point + (0x78e4cf312ec50466bfea965b655e9514d9d69bf0bae566fc88187fe730f70); + tempvar res = res * point + (0x8981cc99962f20f8814162568d9d7edb7fcc637fc6907a98b1d1eece9811c6); + tempvar res = res * point + (0x4e28bfd662fc5e09399fc49a49a622a7e845631244b9472df8c91c4a703321a); + tempvar res = res * point + (0x3085800be446839854dfb7bd9ea67ff139267fb5268faaf153db26b00368630); + tempvar res = res * point + (0x787a6c80d5a23f91cb91d2508633cce6125da76e797ed460256933a4e6a24b7); + tempvar res = res * point + (0x5ad768a2e70b4018e505bb5f6f44d249d9f5ba5f126106cde9be7726cf5c0a3); + tempvar res = res * point + (0x58afefb8e3180356e33794e20db869aba4bd4e5dfc795f8089d6f123025179b); + tempvar res = res * point + (0x4f62f4d968964e4908d16fb9412f8d10eb82e14e83f3e094a02470f27eae006); + tempvar res = res * point + (0x5ffa0d51bff335ad53cfe99165aa64f5ac1b01c360bd0101856537fb03da5ed); + tempvar res = res * point + (0x43fa3aa05db6331941265719fc1ee057d9f3dc81704f81c2ce7faece0fe86c6); + tempvar res = res * point + (0x1e836012f5509ea2f3dfdd474e9e4a96f6924e6619924ee4c6870a5294e26a9); + tempvar res = res * point + (0x41052d90f803f015bee5bd1a5f6e2f78f30439ecbe39861cdaebaa8f7c56371); + tempvar res = res * point + (0x16f6ec82023f48ea80196121afab584b9bce7f01e9515d0a3b489d68df3e2a9); + tempvar res = res * point + (0x4b7236fb7f8b72b2d369effbee5b4bebe7d2205ed72f9831b41c711680cbbf2); + tempvar res = res * point + (0x6620ec871e8a2c03933d0621b13e7f357b7349ea16bb549e7e15e2652692252); + tempvar res = res * point + (0x5b553a6606a3f01d862af22a3309a6df0aadec753fd1e0321b0eb08504c1f12); + tempvar res = res * point + (0x17a1bf17777a3b56a76df412810d05c9e222027aca604791694d3b020ea40cc); + tempvar res = res * point + (0x64fecb621f4dc18fa1b66152f28bdd15b7b12d495c496e77016bf3b979e4b1b); + tempvar res = res * point + (0x7e31ce22d2a3d776ad90e008ce82c594dab9ff2c42708f4f0676000cd86891a); + tempvar res = res * point + (0x43530eaa364a9df353dcfc154bae168e0fa9b51a3362c6cb351d47bb7f6b829); + tempvar res = res * point + (0x35fea15e2101714f172da73da6ddc2077ebd42ada067e7879bba8c2ee1d9db1); + tempvar res = res * point + (0x4509575b94136d744c8679c3028b0db514688db5338c4bcc9f50ccd7d15c95f); + tempvar res = res * point + (0xf8bd8807280892ca46c092b74f845d90f3a6b61b197a0594fa30686ca41a5f); + tempvar res = res * point + (0x51443fc9bbe11d787df4afc59f4366629cfb3a14c80cda1caa1ce6107fd063f); + tempvar res = res * point + (0x22cf3cd9fc0103158f7de369046ac0cff77c44c3f9c6ca942616fe7d59d6231); + tempvar res = res * point + (0x14714592154025f15704e279d2db4c70f545137269ccbd82c11fba275bacc85); + tempvar res = res * point + (0x1d44a3f67a1142e7922f4329f775fec5f8bd2d32ef8ab41a00821e76fbaa89f); + tempvar res = res * point + (0x2d9f309e84716b322c26aa86a3fe3cb6ff230e0968dfc58b869268c751e510d); + tempvar res = res * point + (0x64ff5a81d9e22197bb59e8cb340a0f44e22e226fed168f8b125d850bd727b7b); + tempvar res = res * point + (0x2cf1eefdbf254a549ddf4069288ea075d9aae074aac7853005b57c37c2039e5); + tempvar res = res * point + (0x20d846afc1a11dae8646d542770f294b9c9f21f1196fba567f2f74d058ebc25); + tempvar res = res * point + (0x4ce9244cd3966ce1a6fd7f8b85fb1c8751e35aa53032f8063535665ac3a69f6); + tempvar res = res * point + (0x203ddf8cbfae2898d2d2f183cd0efd1c3f7db1b84b8e96e38f2b87b4bdad1bb); + tempvar res = res * point + (0x37b40695420e59161b338e413a72daa6909f0e4f6f85426f8eeb6bd0dc3a1b5); + tempvar res = res * point + (0x8554877281326c1c7e1f3a2f5e81341554ecea862c2677fa67ab2f88b3b03f); + tempvar res = res * point + (0x619cb05e71db22ca1ef274bd0a7cdaf4fb79b3015b96f44814b490f048d2af0); + tempvar res = res * point + (0x66af1f51f840c438b502c2a5ab689f9b38c2c96df36988710951bf185cb8501); + tempvar res = res * point + (0x5486125e0ed23fdc42a4f8c96cb08d934b6f3b429c4af5f8396618e978e9811); + tempvar res = res * point + (0x41d785e118be2d27a159ed5216de66a84873e1f62088726d9607c6443a14090); + tempvar res = res * point + (0xa6117e45c1c561307d63895569d34fd7e3f2b2ea088dec37dc3a5527deffd4); + tempvar res = res * point + (0x3bfe2f1e8df44829fa27a78c46c223c7e64bda85be60d8a3a5d0e7d36c20e29); + tempvar res = res * point + (0x3daea06a4a96480c4f7fff1082d95836964b63c14281ef942fa9a9890d8754c); + tempvar res = res * point + (0x3678ebeaffc3e64d76141f41be973ff36e8398a6aa0385eddaa0c4183e3646); + tempvar res = res * point + (0x5cc1da57cf1059231e195a26b1323599c95f98e4b302d6e6f4bd41180b56d35); + tempvar res = res * point + (0x4f4cd7f9fd5b694cc5ea6154d0738cdbac3978ce74a7314bcafea3dbc1da61d); + tempvar res = res * point + (0x77bdb42e999e93273fa3cbb7ae7160522231680eccc4d38c1b8a83d2a0420a7); + tempvar res = res * point + (0x4e1cdd107e3116b4ff22720938a201eed2ea0b499bfde301562f5e39a42b066); + tempvar res = res * point + (0x513bd3eda9403f4167249972ce4947f3ac9e9da03a7b9ef557a65645b9616be); + tempvar res = res * point + (0x23d7ed01587af3b9aefeae8a627c6401d36245cafa9367631036d2bd7c47e26); + tempvar res = res * point + (0x1ec8c3c39ec4705944ffa8b3b9b61f73c9ad759cb79a107dd93a125685f5119); + tempvar res = res * point + (0x4d0db05514a8c0f152a8664579c004fb738cd3790214984bc3f21f31d494361); + tempvar res = res * point + (0x2bc791bd7e68342116218ed9bb657b8b54e550022e39af11ce55b29ae49218b); + tempvar res = res * point + (0x7ea13011e0dce5c917be4cd36c8931f5969852109a16d7c5142e8fb3c8b7650); + tempvar res = res * point + (0x11a9029a5c07557ec347592ba7181acafbaf0f0c5c9e81d7e995a4de57fe566); + tempvar res = res * point + (0x359506efbff0e2b81d91cd6a5f808a6c65255e1bf06cc03dbaba94758b3acfd); + tempvar res = res * point + (0x491899cb7600abb42ac8cd91f2c775ec410469573f57c1030ed1582327eedb8); + tempvar res = res * point + (0x7a42c4e98f014e50dba6b25fc32401b7695fadb7bf271fe0a763712ee545c2); + tempvar res = res * point + (0x2f7d26f183c54146bd83514f5459bfd95ac635649d74225c2168a8e7baec082); + tempvar res = res * point + (0x3ab952be650de0c679ddc0a35bac2907a6e58303059d4edb914e74c67d05226); + tempvar res = res * point + (0x2b7f9df93ba787a9a5a7a0a3b5daba02e2ce65df16ada37575735697eda6c1d); + tempvar res = res * point + (0xb04ac19a9f1483b8ee3b763be73814c9621fb3d23e6d874d9093d999d3d4eb); + tempvar res = res * point + (0x4f4df07e55d3ebf0ed955bd9f7c34de001f09a92c1ead17b0c1a485d48a4329); + tempvar res = res * point + (0x1522043741ba933948d7298114b71322258a3d4e7cf2496590c35683dbe2a7c); + tempvar res = res * point + (0xb489643a1aa2c181b4739d45582e2576a6f9bd51c81d300ebdc3a58b79bb2); + tempvar res = res * point + (0x4db70c63a1dac4e5ddde15e3626d009683aa8ea14face2c3fdb6ec97c8a86a); + tempvar res = res * point + (0x309bca858a0f9fc5a468a57981c9c6b7c79636b1f31284938d1c6a21f006a33); + tempvar res = res * point + (0x625a1fce22a9fb7717107b137a0f5ea4ca059008f5cc6fdfb5cb5bb1734bd17); + tempvar res = res * point + (0x6ae2e00f7827692b0d20f483d3c71594f61d50846b52abfee39f6697513c0d0); + tempvar res = res * point + (0x4b5acbaa0f7e360885677439654649256829cdd6d4a6c7ffa904a0683fb5fe7); + tempvar res = res * point + (0x66a63b8ed2255586855fb30333ce0e2ff4eb2b4cd5d2125d8d20cd3fcfc1d04); + tempvar res = res * point + (0x55351e9d60f58241736330de978242e4e40c4209a7879d7ae3823c148abd82a); + tempvar res = res * point + (0x588747248358bf8bdbd990996cb43468c89909cad0f8230cc939538b9b331df); + tempvar res = res * point + (0x67801dffe217a1a64e0b12f405157af52025266fcc391fddaebf3b6c7ab79a9); + tempvar res = res * point + (0x411556b9c89186a2f9f79e55d045295790b28af97fab64e77777e3828532be5); + tempvar res = res * point + (0x5c01501e6a113ccca7cc9c723b1fad6ba60ec5b0a85b7d09c72120d3f733bd5); + tempvar res = res * point + (0x5b0d578cb7aa59ba02b0bb894848b745440c0cf562c2e635312c9bfc305e169); + tempvar res = res * point + (0x3013a9c6094ab0086b1397621f93ac07bf45574ea26b09d3e4587afffe995ca); + tempvar res = res * point + (0x7d9c679179dfab605ca04e1993b37ddff490c440665005698a47c442a1cc10c); + tempvar res = res * point + (0x4f6e24500755d20ec5f28480a41a0cf23baa1aa24202382e9f4ec8ec6d7596); + tempvar res = res * point + (0x4e0a6e0c26f85c74373782bd2924f3bc0f6b4a2914c4f7f8850a79eab580566); + tempvar res = res * point + (0x6caac68bec6ce4eff4f74c1f33dbc027165cc02cec8f69e9470ff99c0b132c3); + tempvar res = res * point + (0x1c867fa9ae031469be012c4f201ed3ad56573a22891351012ad1f7d300361f0); + tempvar res = res * point + (0x1761abb092f6c4e3eda770480fb4ab095e786bc3f1b1f960bc4c95232308b3a); + tempvar res = res * point + (0x4a35c4582c91999a39b553248bf2a39ae5825204085a9e98bd6ddab3bfcc0a4); + tempvar res = res * point + (0x6a4efc048a81614dede6c4f6181253e84f20d4a4f95f973147ee3fcd72077fa); + tempvar res = res * point + (0x65c14f7de75359a40c5f244f78b2920b61087fdbbf59aa507644d94f5bd210); + tempvar res = res * point + (0x9be8b219ca1684dfbef720a3e9f034b319e2d233aed85063924fc60aedf20e); + tempvar res = res * point + (0x7352e8793ed3f6283e492544b2944d6fea715980d8884f6821574d36868b0c7); + tempvar res = res * point + (0x65c04013accf25a2cd1d9eb98689d71694ffb20dced009df5b9af167602b4c2); + tempvar res = res * point + (0x679bf3101f8b2112eefab47d7372f0297507511c7cceb4478f2baf0541740f5); + tempvar res = res * point + (0x162e6e8431b7280f8401ca08922c5452c7237132efe3a481a71b5c97183e9d0); + tempvar res = res * point + (0xd9da926adbb5ffa493c54223f97fa1b0d141129d8736bc4f5768426c7e82a2); + tempvar res = res * point + (0x711628cee8d673863e18f058cf82551ca8351486b9b210873b4e18447e11408); + tempvar res = res * point + (0x6f6131c193cd7b3fdb4d0848df70474ba9e80529097311cd7c13e322205a1c0); + tempvar res = res * point + (0x2512f776d1b3d212be7c2adce1cfa083d1b2b9af1c6f3cc424b266bfa19aa06); + tempvar res = res * point + (0x400330fb079fb4cc8671ea9a996de8f5442f20b9b9a3bc9df8b81e01506c5ad); + tempvar res = res * point + (0x40cfb729788e16fa80b7d937f0088157d18ff2cf7c79b748d0e150c896d348f); + tempvar res = res * point + (0x59786091e2d824242c7aa5dde34ffbac99f6a9a1aa5ecc8a395aa13e8aa55af); + tempvar res = res * point + (0x4adf53e64235d5327822ee3e584674af053e496c5d92a6c8c43e1e8e7d327fb); + tempvar res = res * point + (0xfe9d827d7e6387c7228d92f78574add4ceddddac1fbe71dec1258220c08402); + tempvar res = res * point + (0x37f1342e071f8a087c1405692443305d28d4c11b84d92bd7dedc563fc3ad329); + tempvar res = res * point + (0x74a39339d1d708a9ea407f03d8b0e5ab103c3251596258b78be1bd97ad06915); + tempvar res = res * point + (0x152c16cce8c1c782287b8908a790014fe3c51c57cefaef63e2c8dae5a7a5daa); + tempvar res = res * point + (0x5b32dadeb15d554f39f227de4ad20600eea4b763fa4c90ffa1a41812ae43479); + tempvar res = res * point + (0x3b4b0f9b88e16446a2de79c1d8c34865d5d6e581f08bbbc652ce67d8ac1d952); + tempvar res = res * point + (0x44041800e20fa7a15dd9274ea8283b09c30a0d900d9c165217004e669b39d99); + tempvar res = res * point + (0x5609324fa7ef5213591c8d36c59dd42df8f5f26f84468bb84f843707a5c9c48); + tempvar res = res * point + (0x6235547369b594514d2fa1ca9b06fd25f9d2764fe8b099c7d9671f542a01d46); + tempvar res = res * point + (0x614509129cebd380f416c4c9c7127ee7b53d878860905f047ad722a82147236); + tempvar res = res * point + (0x4f847058896f8e2727ef3b4577e62d5f6a729696b8705fe217b97c73fd1afee); + tempvar res = res * point + (0xfee20b19c4437f06eeffccb05b88c4e236d18f8e3518ba124ab4eec844c496); + tempvar res = res * point + (0x5897638208b8e9509d1128c29af87cf30c57942d47016819435b373c0a309d7); + tempvar res = res * point + (0x1fb19890707fa2e617de7dcea9ad35ce9960009f1e38aa2629c66fa5b8d5d19); + tempvar res = res * point + (0x45fb29b3ac673e9f525332c8bad73d76521985406fc09398078b30339c857b5); + tempvar res = res * point + (0x528d041bf152aa3a0205430412a196619b68c81d7a706fea0fc090e0cc6a105); + tempvar res = res * point + (0x1e149d42cd477212ab7f01fe40f76858f09ce2bdfc397df635ed8a453714e7e); + tempvar res = res * point + (0x75f781602ada44803c0ca4bc8c1bd5064700762d18c309a2b9059dcd8c3dcca); + tempvar res = res * point + (0x1571843ced13a8d342b63c63abc4b83d357eb286af04380edd1eaefcef3f1f8); + tempvar res = res * point + (0x304103a8d35f43cf87d50682e86e473fffd71d13e0c783e596a59a62b06402d); + tempvar res = res * point + (0x2849ac77a2f5398eef51aeb8312dcef8b347b690728d4eb835bf4670301e6e7); + tempvar res = res * point + (0x52a36a173c7ebc96cfc55bda4bbc73bc349657d39ebe096725e9cc4bff01def); + tempvar res = res * point + (0x43e371660fff35e52cd5dc08c9c347d8f7c64a116375d0e6e3ad3512d85a99a); + tempvar res = res * point + (0x76594f29261e2aa9cf4a90b58b0f79c2aaa99d63c4ff64b4806cb8cfb0df316); + tempvar res = res * point + (0x4cbae4979c7a1313c2d0f68b21f5734ec83f9e1a88c78b3976a6ef84a1b6dbd); + tempvar res = res * point + (0x76702a08064b5768ae2979aca07322782191172276f1bcfbc14cbaa3e758dc); + tempvar res = res * point + (0x64f8c462b308a1337bca235add2482fdc3607507b2c9c0f91b9187f5676303); + tempvar res = res * point + (0x2ef5951aae064a7357b1e4ed49f05f17f778f2e8735f8d17b5cfb82faf3b848); + tempvar res = res * point + (0x66e2651e6f5758c334d1c1451d563b2df07b424b5d0125c739ada959479890e); + tempvar res = res * point + (0xb3dd17f46d6b12bf4e5db184d6962c156bef94f9f73861e34d88503fbc517a); + tempvar res = res * point + (0x19412ccd078bf5665579cbd16035a251e08f40722eca4452eedb31732488468); + tempvar res = res * point + (0x719df2a50d9c3f2eb3f0336665f2980e432191e21fc49f488854b8352fd94fe); + tempvar res = res * point + (0x459f095ba3b70f76e493c6afe2d4b6eebd21343f74bfe3390868612fc250fdc); + tempvar res = res * point + (0xdef6a0b2b71d97a59c674c052fe23f7d000a334e180b0793b6974fe29a64c3); + tempvar res = res * point + (0x74e503d57e49daf6939077c0b4a4d68e66bc2425ce53b01b48f146295476401); + tempvar res = res * point + (0xd49f196e60ebea0eb13d85f05cffedff32477e83129bad30bd9dd555755429); + tempvar res = res * point + (0x298215f335fb63a11d31958d950d95c909bb94e144c113cc4ecc08488469097); + tempvar res = res * point + (0x6232d26f420f9b4f119e64762927b5e8a21192575b200081b0545ad4e9a2c25); + tempvar res = res * point + (0x2b51d7f94ec71f3a8e3e20d766a4a7f13d08d758a686ff86dbda48026c7ec3d); + tempvar res = res * point + (0x45fb08bc21969d5ca9b1ec473cc92a4ad911de8b0607ddc12b9ee98c286d37f); + tempvar res = res * point + (0x70c0f7da90cd889d8df06f9774de8a9a20c88e86753506c7afd0e1f6ef15e76); + tempvar res = res * point + (0x1b16d94e84ffd3ad61286f5a79d5a6f7b5b5dd6442aea9013ad21467bf1281d); + tempvar res = res * point + (0x6a81925732161d4e5dc61ed6a10726027fa66d892aabbf46a477f4455072c02); + tempvar res = res * point + (0x13ed29a84c4875ac188521bc40e9258e03d83c9ceb8716c6fbeed065a5df73b); + tempvar res = res * point + (0x184ee38f80fa532983fa248c14c0220c2a5691836e899a5c9b83c975b03608f); + tempvar res = res * point + (0x65f4a97d2b1c90582859966540e839ac2d62ad2ea960aa2af36776b2d07ce34); + tempvar res = res * point + (0xe00ac968fe5a147fef45fbd626c540a194ec3dfb2c1cca7938e037349d4f34); + tempvar res = res * point + (0x96935be4e41797417259166181bb646a619ef95cc8978ffeca81d141d062f7); + tempvar res = res * point + (0x61c61341c83517cb7d112a76864271492473e04130ce4ce23331f7300bd8c89); + tempvar res = res * point + (0x73eba0e9e52c3a93ab6dce26d5858b2d699d8401b2c43253616b5701aa803c5); + tempvar res = res * point + (0x77434256511acfd027b41e03a571a9f56b0442dc675c139a2e1476fe716102c); + tempvar res = res * point + (0x325f10662fc8bd38e591b0e8caa47b3fff46703656b2c5863d39c150d298fc8); + tempvar res = res * point + (0x3c835256339330b1c94cad78cfefda36a949b9c8553d918f3d8547cd1805ac5); + tempvar res = res * point + (0x7340540d0c9f9dd2c1142f03f408ab977afc7371934c62259fdd29f0652f8d0); + tempvar res = res * point + (0x17d8ab17e403b1925b40206c11f8a6a29ed08217e1ef303906ecb354fdda1f3); + tempvar res = res * point + (0x78562cbfb984ebea085472a1b004dbf86e7d99f4809a5020969246a84a9d165); + tempvar res = res * point + (0x60c93d3dac2628ad796e1dc80bc0796d054c991ea23094d699bffb43a630add); + tempvar res = res * point + (0x72bafd4641e6928ca65cb48e8001ee077944201f70d5bed524c69b709410d3e); + tempvar res = res * point + (0x6321e76192ba31cc63bf7c526c8ebbf4df5b705f01e4151068ee3dd658aa674); + tempvar res = res * point + (0x7caaf4f7b073af26c036d8bab5c74fc3f752f9ecc01041787e9ddf773596189); + tempvar res = res * point + (0x66ada08fe725f364ca32c1055e1ab1216967856d6cd8762dd4ea915c2ed40e9); + tempvar res = res * point + (0x5b6477413bac2f0d370c0cdcdec4cea10fd322fbcd7b202d4ccbeb0581fd34f); + tempvar res = res * point + (0x35c99bed31baaf7833ca759a9bea792965a87b42171259ac51b00d872d581fb); + tempvar res = res * point + (0x7ce96f5a3261a977f04ff70ef416a3d5c165100d19f551a6ac514e4d00fb18e); + tempvar res = res * point + (0x1c933d3449f6241d0f9d547db9e708fc2ee3e0598be5f87b675fb6736a15c39); + tempvar res = res * point + (0x687aac173963fe1e01f9e0d50eba0e95e1e8783eb21c0f6c1f45cd42408198d); + tempvar res = res * point + (0x2f2f5447e274a20d9d60615f83a18b2a4db300d5e199d7c8c6c6cfb754e8cbf); + tempvar res = res * point + (0x91cd6c3b8ddd8954a44e8a9cf6f7f183af8e6226849f05e6e6ebda2409e042); + tempvar res = res * point + (0x282ad11848887c771898b5a32ac6ca14cc2510830454aa8e194975e308fe042); + tempvar res = res * point + (0x5455d2de2d7570fbeeb431a9a21187ecc049874b64a227bb543aab4af16e27b); + tempvar res = res * point + (0x2fcabf82bfd2529eac169a520cbdb2a0f8c205c5a9b1f1ac69bd3a44b25faa9); + tempvar res = res * point + (0x33d4fbf9dae7a87cc13db3c95ed3976b50113f072e56a13e675e4af241bb864); + tempvar res = res * point + (0x3cbf28927ecbda443555c9d51f40c294fb6688a17812cb0c85fb6501cdc0709); + tempvar res = res * point + (0x4fefb86cfccbbea031f15d85033f10f92f2b6b689153e305bfa8821935979c3); + tempvar res = res * point + (0x63f4ad31c4d59ee741b1b0ac99e022959df079b5b033ec7a1ecd3b4797f94d9); + tempvar res = res * point + (0x6c74e3b74559e12949b8c3b55369b2d275b2920b4442c536d63f91debd61499); + tempvar res = res * point + (0x45a5b88744e83d901f33da0d0de869381e7a125a6d8bd104cf72ded013ea4c6); + tempvar res = res * point + (0x11243de8b4214dc3220693acfaa6b626cfc3b8c812140779af9b72dfb1b92f1); + tempvar res = res * point + (0x123f50f65a68168d6b43c464270479801376ff6979b94f60252a47d9d7d34d2); + tempvar res = res * point + (0x25446fd382a1b0f5350b91290b2dc35a6dabaf215d53cbb32d1732fc6ebfffb); + tempvar res = res * point + (0x160d7d587f3a17673bf04189e0062c7bab764fb54ebd0f042fec72f953a91da); + tempvar res = res * point + (0x1e0fcefcc1d1c5a69e81c4fdfe7de04d95b53c162a3b64b5956df8e59e1b93b); + tempvar res = res * point + (0x1925470cee5111eb991ccc8b0412be603c0b8df342d7b186a3aaeddae103bf3); + tempvar res = res * point + (0x2848af5bb20ab624881dc9244ea18b1d6939e14270714253a896e57cb0f63ea); + tempvar res = res * point + (0x6c2a98464d6eb4038d55b57632bb283ab091eac255fd6797df41612cfe3ea1b); + tempvar res = res * point + (0x31563499de399383464854a8679e0b073513c5bc46cdcc2a2107f00677e6356); + tempvar res = res * point + (0x6da4d6fb1e6b2f1b42910a9dcc4702912002d7d36ac7100e19c7f298c7948a8); + tempvar res = res * point + (0x3d368784067d457e43cb63b3f526e721fab153949b090a99a128c5744fab4a2); + tempvar res = res * point + (0x266b63657dbde655f034c014a8fb73b77138b52eb0e17eacbf402bb90305f10); + tempvar res = res * point + (0x179f2a40de3db251b95a60431e7cfe2dfa48dc8654bbf81add938e9f2f6725c); + tempvar res = res * point + (0x1118c09adef545b07e209d88b0a645673a103c9e71e8f671e74c84abf1a2a2d); + tempvar res = res * point + (0x6ebb7c4ee2d4212e6d7cea8c16f97c935f3bbbc2f400c9a738f1ebd37eec6ee); + tempvar res = res * point + (0x41d1ca4f756c80f197ba1635314a3dc756f9d8d9406af16538643d3e1021bd7); + tempvar res = res * point + (0x3129daa367a01a45fe3f0ccde215371f59c5643bfad33f4269a6478c8c8b7f8); + tempvar res = res * point + (0x1fefe6ebd886640df863e5f5c25e9b42fbc10adfa7ef07d1fda0eabafa60a6e); + tempvar res = res * point + (0x37e79bd72d714d3de7ed2b1ba79e345f75646bf67efd8ea3050ddb357802a3c); + tempvar res = res * point + (0x24eb6fb4dbac687e35d4168b970db6e7dc76c4c886dce0d4bad2e6544b8e6c6); + tempvar res = res * point + (0x6508b5fcc13191197f91407d5b1b21d321b7f311e55ede9ab8a6975308dcee); + tempvar res = res * point + (0x43e46c5f1cf3b5cac9722eeee991cbcf53af25a4a355a91ea9b8a4d4754d908); + tempvar res = res * point + (0x7393709fd08807a84ca44526a2b8ec97bce5aad1adf00560d04110de6d9eda8); + tempvar res = res * point + (0x690c8328ca161c48f3f8f37570e42095d1a0d9e101b3ec0ddc91426fc22facb); + tempvar res = res * point + (0x41354bad5cbef57b0e7eacebef8f0176f3b70992ea5a418f502242acbc4a1ff); + tempvar res = res * point + (0x3475f32b5bea9dbd19ec199ef34e531b696cac0461e644ffb41a5e99d0735fb); + tempvar res = res * point + (0x33cfe02e240929353f193c6d3387f1117d04f116889f38d9a196abdf986e48a); + tempvar res = res * point + (0x33e7ba5f7e56065e3f8b091578e8e7a7b118116de47237fa5a97e44e97b7f69); + tempvar res = res * point + (0x5526001b8a8c2c6209e40b5d380836bcf63db4ef85c25fd5b72d749b0bd36de); + tempvar res = res * point + (0x64028a3945aa2866db68b304dd0d83d75ed0ba5c2f9d0b47e80d11d8da6526d); + tempvar res = res * point + (0x378113f110b2404e7d185e920249519ded728cb1027fa8cc2843a588886a7ed); + tempvar res = res * point + (0x5f4fd7854cf7b89a3983da1a39839d85c7331c3353b0a8cd218f7f4e1f780c); + tempvar res = res * point + (0x6467afeee167ea95feb4a85c48fabb2c7067de57acd5098692855189e21c57e); + tempvar res = res * point + (0x1e4bf5029043367487394808d7ee7df5ad1ad1da2c4710a1b2444ffde106f2a); + tempvar res = res * point + (0x684a30c1084e8edf34a77bf8848fd2098459f5461bdf3352faf9c8801435b6); + tempvar res = res * point + (0xe3f2bdc2de2b623c56390eb0044adb980766ae1a58d775e003c39724d1d6f7); + tempvar res = res * point + (0x62dae59d425684ef78c1829e0454cd5e76f5d322ea8cb5ae5e911f545beeee1); + tempvar res = res * point + (0x5761ff2e0a250691a66dc36d372afbd6a8016726efe0c418d7899d60d26bde6); + tempvar res = res * point + (0x4dc27c76881bb820eb74814d1b69825e9048b1a3b064e603cca4bd4814b2243); + tempvar res = res * point + (0x5a15d718a45959d16dd6e0b98badbb086e2a9741ac04086f078bc6951506e05); + tempvar res = res * point + (0x23cf69cfd7730dd096fd485b2d8bdfcd89ca6004689bcbcacbeff288f18ff9b); + tempvar res = res * point + (0x4d6c233f7bf3ade219a8e3a89e12d05beb7faccbfa811ebd930c391523f7b4); + tempvar res = res * point + (0x5a347e7937c7a178952905f499babbeda500a820ccfdf7f3a99589687a623e7); + tempvar res = res * point + (0x43394095e27ddb7825c0671833a6ac9784f31626914c902c225f05ce42bbd9f); + tempvar res = res * point + (0x66d91bcc591c880303ee4695475e8a8e402926f0c01ade8880c7b03c76998ee); + tempvar res = res * point + (0x3348152349370ec1c4d753735ef255b50e54aa9a432f48a121c39b8887827e0); + tempvar res = res * point + (0xfa17235a82497674de45bfa59e61a329b2d0e63eb18ab9b74aa46783e04c81); + tempvar res = res * point + (0x45ffc1ad229bf52b2531afadd1c5ba120c57b34def87149880d1e5cb6c5391c); + tempvar res = res * point + (0x37f5f6b25ee428e91e886127b961856d9ebc52740ceb763baa7e71371b84364); + tempvar res = res * point + (0x58281d625ddb432caef06e485bc2b74cc077aea9ba5072198e76542f0c69dd0); + tempvar res = res * point + (0x3e35aebb590266ea1fdd8198cf3c23c77731dddd95d488a9d9f9837e3bd0f6f); + tempvar res = res * point + (0x2850977abc89355540e8abb804da7805ef88b12f40cbd9158ef330b767901eb); + tempvar res = res * point + (0x72fb3298da88c470a2f93a391063810be01078c8375183b57a024c223f2f428); + tempvar res = res * point + (0x53f792c81d26c122898d70ed7fcfd8f02a8f5a9ec8b9868fc4490d3a46b4e8e); + tempvar res = res * point + (0xa7da81afc9f3c93366b6e161b1fc7a497d6c770fb140bf4b64e5fc707cd3d3); + tempvar res = res * point + (0x26601a459facdd83458b56099975d2b7dbbc431d41b53f5dd6ca2901dfaacfe); + tempvar res = res * point + (0x4a048ce90e3a1eeedd4932ff37760fd8b1dc995aff7107bd66318652efd1032); + tempvar res = res * point + (0x287fed27ab81e5f721d2bd5aab0e69f53e94ce5dccc35c2dcc88e12465fadc2); + tempvar res = res * point + (0x414215fbcef7f5af60f320e67a845e4a17b0a0eca39b4e18ba89fbe8a189491); + tempvar res = res * point + (0x208f0c2f5a114b2342f51e919e4fe44c2a42cd06382d9edc4ef58939b249bab); + tempvar res = res * point + (0x5726e3dee7bbc5e5b4f3ad65f0fb17699efb5936d50ad380785f2b10fe8953b); + tempvar res = res * point + (0x6fa8562db8de26797e9c9905aa769e4881304b4f20cb64d718d271c182f44fc); + tempvar res = res * point + (0x2a60396cf912573be2837653283a23702037f614e33e1c6fe2834eee9a1c7a6); + tempvar res = res * point + (0x5b6b3213744858ad659c4c07c9220380d63c01f680986191c8776eb703661c3); + tempvar res = res * point + (0x709a47e72cda4fdf428bb9784f02f77c700086755d4bdb5b229d1b80a2ea4e5); + tempvar res = res * point + (0x75e9c821cdd2e754759306283aa4af8bdbb0ed31f4e978dc550141fd10da6be); + tempvar res = res * point + (0x2adfa41f72ba3b61b9dfa6f017b19682b0b0f8cd86be3d37374aba3ce990a55); + tempvar res = res * point + (0x6e313bf82c34d3af1e7fc14d811dde163ca6e57accbe476875e4a967da00b8); + tempvar res = res * point + (0x78516acc9d32f4e54f8925865c91f70b210f4ebc7533fc624685b3d5daa7b18); + tempvar res = res * point + (0x3b8cca1c3fb2b26b7e206802d52d2ed1c725b8f95407e3ef295a7dd9ee0d45e); + tempvar res = res * point + (0x287ef69d6f69ab853e4f0d24b22e4c15169d12c41706dbeede9fb49c61179c4); + tempvar res = res * point + (0x7c84837e6872bea4f0448183cecd6bb24a8574456ab91173b04b9423be8a64b); + tempvar res = res * point + (0x78f890541865c12169233143f47a056a91dbd18222c5d31bfb2db19162c204c); + tempvar res = res * point + (0x46cbc37eff4616daaa86160d5690f5473e24171441e29705ae564223a351c23); + tempvar res = res * point + (0x309f9698e38823c05e56d073d83ea551bfa80ace08e749aa4c83031a22360c2); + tempvar res = res * point + (0x1a2cd41155bbb7ceee94dbd01bd876140b1698f03b2ff8f8de3ba45b4ea14e); + tempvar res = res * point + (0x10699899068f86fa3843b06693288630b9ac4b87be7b3726fdba32b41caac2b); + tempvar res = res * point + (0x2762878a5f6665bee609c26e750cd886e239c31caf1508d5a2a185b58576b77); + tempvar res = res * point + (0x57f7a737e643bd859d8a53e1b621c09be89fcca7b96f8e42333e46426f26a20); + tempvar res = res * point + (0x7239c3b89513196e3cae91f8df8bd79f08033061ba63c089bd764644907479e); + tempvar res = res * point + (0x38cb4f77410e9a33306f8a4b92b6f76bf239ba44e0ef45dab0bfcb75dfe4141); + tempvar res = res * point + (0x382114ce9d712af864a253d29471a436b83ee4f7b8ae3fe19ec3ab315e18d8a); + tempvar res = res * point + (0x51ceb130c1908fdcfa6896756241fca8f74ab172d98c76facb7b8b931fa8812); + tempvar res = res * point + (0x4f6b918e40f8022d2bda8d53214e8fd84743bc2280231d3ae772844bbcd1aac); + tempvar res = res * point + (0x2d9af4ef0d50851ae1b0cdab3587a71728eaaa4e56e67803c5ff9126e722696); + tempvar res = res * point + (0x4640cb2cbc73d7c9fd2a1783122cb5ee8c68e7c04b0b647d43a35cd4961e4ca); + tempvar res = res * point + (0x1b3104591a23f262051182209c0f73caa30e8631fc4413a5bf97c9d51a70abb); + tempvar res = res * point + (0x2103ea7ff918748c4325a992c561b551b70fa9d97e48a52b3c157799d213693); + tempvar res = res * point + (0x69fb58adef701279dddeff71e1832aea01ae10a5128a9f744a5a945b5fff200); + tempvar res = res * point + (0x375e99f4993200342e6f6ad713711052d518e5dac24681b3999878bbad627d); + tempvar res = res * point + (0xe051fab79733dd773d13f5bec04b1c20252df512d937f6b7352e4c4fa49cb); + tempvar res = res * point + (0x5d72a87fe662c05530c3ec822f925a10c121a44c4adecf24850fa2442cb4abb); + tempvar res = res * point + (0x6f2a9f716b1fa27c35675a57273feb79ffce02286bcb1e253a8e126c2cea357); + tempvar res = res * point + (0x9b419422a2083bf174263351640e009b56d6e2278552f9e7ee6a6004d45524); + tempvar res = res * point + (0x3dee84f905f6a06940783bc3f322a0fc22a984dd244d00a85ea3a4295558377); + tempvar res = res * point + (0x3dbd68c7c5945f48515d975002a1caf1c491c6743f151df31f95c5870c90fb3); + tempvar res = res * point + (0x7d52bb08c1d72a66c3e5c60f6742675ac788ec8b4f2178ff9990a04d22c076e); + tempvar res = res * point + (0x107c8fc81a96a3c13d1ddf04b8bcce0450610c2ee6c127e0f47ce2ed2fa0613); + tempvar res = res * point + (0x6d8f39b47e79d44503aa87a3fdf101b055f89c663bd7ec377d175280f3f8db9); + tempvar res = res * point + (0x6d5a755e91ed732dcf8afd32eac3b4875843bb116430a966ef88f17aad54c16); + tempvar res = res * point + (0x64035ce25716c9c7675ecce40d3cfb65ce3121439e10367fe29f2742cc02d85); + tempvar res = res * point + (0x3e44a162d501fc521774c75994f4b55eb85878f5e867cacb75c7ff0b7efe941); + tempvar res = res * point + (0x1b2441db55dbd9b87c45b1afba238ed28d1f2dfe9725d9a4cae3a45e3d59b63); + tempvar res = res * point + (0x8b54ed775cf8f3dd5b54fcdea07e2bcefae323f6212b8f54877a60e1f8026f); + tempvar res = res * point + (0x338c001d0c722d793cc14219415d61c52de28d33ab8bfe5dd31674784f2b568); + tempvar res = res * point + (0x4ea62ac09b98dcc34b5437f6bdb4fb9a681dac12d1ca7090011c73259dcef4b); + tempvar res = res * point + (0x6a226b1dabca8ff2fbb52f0adcf4267a47e0eed089774157f318b507361a0b8); + tempvar res = res * point + (0x6ba0329f670df105c31eb665f3b6f243ab5de7ed8aa59ce9b0683e6bdfd9019); + tempvar res = res * point + (0x77f62cb2f9db71ba7a9913be0a434ca045a26704681af5353b7c7860be6e774); + tempvar res = res * point + (0x770018fe3435297b82b391a3bd2d09151dd3949545d0ef111cdf9fece9f389c); + tempvar res = res * point + (0x4279b49402fada9fcb602f909bc138c3547baf384dfef9594e2fa488cfdf8b8); + tempvar res = res * point + (0x4dabf5afe371cde17b9fa6c54c1b38d603f345c58d4f66e06fedd8948b402b0); + tempvar res = res * point + (0x15296a7d071a85f1358bb157d5e62b18a11e189415c16f594a18be7276ed2c7); + tempvar res = res * point + (0x79708fbce6bbe1c862e988648dd25347d60c9e0981540dd81ccaf78054a12f8); + tempvar res = res * point + (0x209866f9b8d946508db2df8eb9d30f65ede2c99ec8deb2e5a1b7093e9a62416); + tempvar res = res * point + (0x4ab0da9c66ca2588350bdb85cc745b4c5e7226cf7c4fb69708cddf6e8145f29); + tempvar res = res * point + (0x54578b117a58f5beb0d511ba42110c4696f4fec165acfbbde208a4705045fc0); + tempvar res = res * point + (0x55c9e37b0208bfbbb61e5e0e05c72111421b24b45ea53d3ddfad1cdfd243ff0); + tempvar res = res * point + (0x5889b4a99416f2f954450c60492129c5f7a36f875a56dde5188318e88d6032a); + tempvar res = res * point + (0x5919f2392a53f9b230145d1b5e6da28165dd1d8cc7d28d3310a805ebee721fd); + tempvar res = res * point + (0x43e49d0d9bfd165776eeab9118ea672c24a055a700e35a04426abe1b236506b); + tempvar res = res * point + (0x40e394412097f7c06183ae2997707604273b0a4ec1add0030bd7e115c20ca70); + tempvar res = res * point + (0x6337d741eb226911e37cc48087126cdd89f00941523cda2fa5e965dc4fa25e4); + tempvar res = res * point + (0x64592b7d9a6a922f5cf5f74c56e167ec000436a6b3caec299bcefea25e5fdd1); + tempvar res = res * point + (0x1d608ffab983d8aa17db9385433abb0025c77e27357285448c4ff6a8438570a); + tempvar res = res * point + (0x333793406d06dad0406a859ea2c203aff33e3cd906d6f04aabb0dffbabbc9c); + tempvar res = res * point + (0x3b5f2338d066753b2507a39884bddc2d0c5bef88e4bc3e79288331afe9a6234); + tempvar res = res * point + (0x3fa0ff20cc486bd0b43f96826c66b070a6f6e3df3359ebd2970661f9c679e2e); + tempvar res = res * point + (0x62cea6c83442875da8b98083d8bb18bce5d3d431a3301afc635600578b33506); + tempvar res = res * point + (0x4835c753d4b5059c1b4186516851f562e63e348f8810714cc393be9810a1de8); + tempvar res = res * point + (0xc230c4af49117fa614b1d4d74ef462211a5d55537ac71564ace080dd4b325); + tempvar res = res * point + (0x1917c10cc63bc9f43116c3688542cd867e1a84ce0d3e58dfb0c11c4b0828748); + tempvar res = res * point + (0x13c6580dce66b35fd24183e1635fb6008a6deb6cb507bf48d531273d5b4c2e9); + tempvar res = res * point + (0x6c6dbd58b8657f8588bae8a4d990e6f9b0525af4eabe87512c5f6a655c92028); + tempvar res = res * point + (0x59daeadc724e9c227258a56b000c6a613db617da41bbeb694521c86323c93b); + tempvar res = res * point + (0xead9e7eac2f6c388de28561955e6009f9f1ed098f70516f2bda28597c9ee03); + tempvar res = res * point + (0x54600ac31d014f7241c14e5aedefdc72b839cb0e98b84aa13f031316af48648); + tempvar res = res * point + (0x5370b38ea84ca67c75ab50a4cb8f23f4017175a98b23df9e1c92f92c279e169); + tempvar res = res * point + (0x23ae2f35a2da5ff92426d59ce066e29a525ee1207de1c370023975b4403ac6d); + tempvar res = res * point + (0x5952b292edb661874ff2d3482fb968149f09982bd7a194d2b502ee3dd32927b); + tempvar res = res * point + (0x30c7ab8fe6b61574f49c3d76b3173f76816f31beb33097d425a94beab6caaa2); + tempvar res = res * point + (0x4dbc9ceabbf1c8d5c679cf80d9bfc26ab696135792e83061e98b9c36ae6a4a0); + tempvar res = res * point + (0x3f1908469233dcf5c433790cb3574261ed6debca41fb55b912be7cf34adc187); + tempvar res = res * point + (0x51778c6b175ce13e994dc1604dac3b901990cbae0246b2cec2aecbe96dd2006); + tempvar res = res * point + (0x6a91b3677713dc15cd110c71cb8e174c8ebd8d7df1a1b4120bb4b6b1683ad5c); + tempvar res = res * point + (0x3cfdc71122fdfc7807b2efe35fb6c7691985d2727401eb8a8132d0e0df3cdd6); + tempvar res = res * point + (0x5099f832fdec91fd27af0d221e009ed6770227d63bcee6e1802cdd122751260); + tempvar res = res * point + (0x1793fa490096ddd67530e29cb3e8e9632d1885815be3f9d96375aa5946f511); + tempvar res = res * point + (0x6d4bd8c4aa4a530d965180c18062d6bc440e6e70cbf0836d6af11235c7fde2d); + tempvar res = res * point + (0x3d7587a79c4ae9c24934a10a9c1398c04f3915fb6889b72b361505a85db2b69); + tempvar res = res * point + (0x39007630deec4a6eaf806518c109f4aff9cbfb8826d86f301e562ec560ff89); + tempvar res = res * point + (0x51e4a728ecd68dc30e4a1b5867a1022af5808edafc3cb12d26d43b495528f18); + tempvar res = res * point + (0x7f921548c686f600b302290f692a66e9ececa142f691f9129c7d8bd2a06803f); + tempvar res = res * point + (0x42cdd4f6ecbfd891fedb9ecb6d320f6adafdb274ee15cc11ef4c0436a4e9afb); + tempvar res = res * point + (0x755d64434e4e4233388c34a90438764c568353cfde4311021b45e0f369b0db3); + tempvar res = res * point + (0x4b5e107dbcd02c0dbef4d3a77d66386a864d31109d0d0392847c8919d926fbe); + tempvar res = res * point + (0x373a1f2fbe36dae9a5f2c2b35febe59b53869e1678c8da23bd9e92c3c2ac0a7); + tempvar res = res * point + (0x53bad76d22e1525dcec248b73438d6f444caf75794c26144e26803fe2bc7736); + tempvar res = res * point + (0xaeb135e456ad66bb5bb2b91a4aa429915f6f9951aa15bba78576744a698016); + tempvar res = res * point + (0x111d440a13cab69043e1072b61c1736cf3901941b4c57d7602b8effa7e74b3c); + tempvar res = res * point + (0x5fb8d87e82c3547e32ce316e4439d1aaf3723e4a906c91533ba8dd9631f1661); + tempvar res = res * point + (0x1426a2050d240104b5c07a9cdaf7fce03c2accadb0ce98344ecb4942c434db); + tempvar res = res * point + (0x929eaf221c110efdaa57970581428d66d5866fb9547aab76e89e8971efc91b); + tempvar res = res * point + (0xcb3220da969b95193a25d1d4d76d1cd1ec596040a7b31da7f64164809bdc4); + tempvar res = res * point + (0x3c3ea2cbc8ce544c6c98ad9053cb2c35326f4e502214e5f72c7951474b5a84c); + tempvar res = res * point + (0x68892b41018bc73b541800d91f0bb2a8cd9fcfee8be13bacbaf7dff7aecdcd4); + tempvar res = res * point + (0x2a652d2592f5cc1197a206db79d06e3b74a55b1d4ec03c516a6957e87345cbf); + tempvar res = res * point + (0x1e0c96f0b836d1e2df4e4063d56b78f38f2ad16040d61855b0f664c066d130c); + tempvar res = res * point + (0x65d167bcce20a40b78583e4dcf7e3f44663e0c595e18f48f83ea4230b207047); + tempvar res = res * point + (0x1668b919fcdf512b5683880ed048853e00f456adde728427fcde63ac9f59611); + tempvar res = res * point + (0x1489d6012d4c9701b63f3610034fb5bfca185c7b01222907781eb104e031097); + tempvar res = res * point + (0x57ad5370b26ea1478f3fa0346d2e390e90feda8022c9820813d9ddd0f36e7ba); + tempvar res = res * point + (0x522f83a59f717f37b235c05338a02630ad83c3ed307838f6e795f9705cbc849); + tempvar res = res * point + (0xb6bca44a12ba7914e575f83cf8b9b8bcd4780622806901dcb9530ff9a454f8); + tempvar res = res * point + (0x6fb8324456f1dc4b423220d18d40de524a27dc4f35e4c780a042f6edc95f97d); + tempvar res = res * point + (0x2039c72c1c7c134fb300e82b104394f54a5b7ffe6f7f00e7c3e4ca6640841a9); + tempvar res = res * point + (0x614a280377b9dc732773d969da5ddd8cc125262313eb7b2bd38b7668cdf00b4); + tempvar res = res * point + (0x243a084aa8c82348102320b0ad19ede41b6bd7ffb3a7041339a13f34f6b5671); + tempvar res = res * point + (0x73e8c35fa646fce6bf10c33168dcf3d2e40af17ced70b1929826d0ca4ba2e99); + tempvar res = res * point + (0x64f6f50e51b19d5a90e6d2c9cfc3486dbf2b37c7f949cc4f8ac4dd988e5bdff); + tempvar res = res * point + (0x1365aaaf8c72d7e9b250bd91ee2c2264362e87679abcf2df2b7a4e1eda1575f); + tempvar res = res * point + (0x24a083b7cf164138ea0c468f33317d89c97b69378c906d918123f3ed5a02cf7); + tempvar res = res * point + (0x25ea89f2d7ad620296fda2be181b5a6be626eade8974facd81e53df842c125b); + tempvar res = res * point + (0x2d32dd179cf74693057ede607e0054fbc3e4194efd6415156f3ec909c37ead2); + tempvar res = res * point + (0x3b74f537f03a28e72bae3bf1810f1a2fde1711eacd6bc64bf55f37b3bd9940b); + tempvar res = res * point + (0x575b929bc0caa43939bfae95a6d5cd8d4082be7fe0934be4c08f7fd3cbe89c5); + tempvar res = res * point + (0x7ab2a5ce120c251b658bfe532880535e93cbf88aa60a1b384017195e6715706); + tempvar res = res * point + (0x7a7d5ce80c8498175cdd4408e08cea457517e37dcba08d0a6cd2a4defcce34d); + tempvar res = res * point + (0x6475aad2a1631a6103b238548fe8a03934779ecadeaead2bc20a677c0c71c); + tempvar res = res * point + (0x547ddf1021a2cbacc8081cbe3a5c89b8ae808942513cd6f6ad166b0306cee66); + tempvar res = res * point + (0x653405343098520984b06f707cee84ea765ecc932783cca87058b88d0f2bbe9); + tempvar res = res * point + (0x3f22422d66d77bda123b47b7f5bffe5527f95d331346f6a545c66887ad75ab9); + tempvar res = res * point + (0x1b18b73effab8a483156d16e87be4dfce1250333eafc784d76c6ee145978c48); + tempvar res = res * point + (0x2843bf3d789d84faebdd6ceb0eed3ec0acd959732178b00b4242eb5cff0ef3a); + tempvar res = res * point + (0x592d2fbca1f86935e587f6cfdacd0a221237bd378e2d1cbadc3d168c7a1756c); + tempvar res = res * point + (0x4c35c95cf7170d2ab6b9b6e3c1be66dba2de170638f27975fb5ec12c36a45d); + tempvar res = res * point + (0x405f9011670f0f202814795cdf0251b665e8f39991dfe2282a1dd2acdbaccb1); + tempvar res = res * point + (0x43b4be816239e45b4d22123c840717fe3e8f6ce53238fad4ad56e27c85f3e9); + tempvar res = res * point + (0x3a2c1769a49e0632c149dc9d3f30306f9d9cc00cdb426d58b2741c804c51af4); + tempvar res = res * point + (0x422c03b47f25f698d3dfbb02556367c97b7d8e2657af2e45ebc61845aa2c52b); + tempvar res = res * point + (0x5a47f80b2d6e8c8e89f08c23e4eee09ae23882290a4dbdc5d0b09e713297124); + tempvar res = res * point + (0x2059b2385d435959cedebbb68ab5c484441832a20d67889ff9974057cdbf874); + tempvar res = res * point + (0x6b735de6be3ab4aa1425c328c838ba09dec586718729f1e172554cac036483b); + tempvar res = res * point + (0x3c05c93a63aad66725d8d25e62f76199a1e9f5743577777caa05832f4e79acc); + tempvar res = res * point + (0x4245e03d0378593b2d4230b945a2a147b36ebfdf368f0dd5fc22e3b31ac1186); + tempvar res = res * point + (0x4de104ea20937d5d6cb02c4ab4d7c4d03ab2eb16d1b837ccf0c2a05ea2873b1); + tempvar res = res * point + (0x48876d457eaebe03383add02eb4c0c49a09923757428595a4f3ad6299d69cba); + tempvar res = res * point + (0x6d6ed610ff1347a9252bf835af9666acc415b28796d968ab76353cdc1181733); + tempvar res = res * point + (0x1da9b14257c5c5cbc1a97aff87690dfa51e82af9a11eaf5cb2538f595ea2105); + tempvar res = res * point + (0x416057baac3a1780d7d25b192188b9b3981bdcab0e2dffb2fd95456a5313201); + tempvar res = res * point + (0x1706af2f962881d86f167571fcbb909b6f1e4fa386fca8d87b674335196f44b); + tempvar res = res * point + (0x6d9c76938c974418e62166285ade6564712e6a263357e11d70f3e1f2ae531e8); + tempvar res = res * point + (0x771fefe011becb392f5c379dc9e902c41be8f1069ae3c5e0bf6016b7b1b3f55); + tempvar res = res * point + (0x40cbcae9364d8af8b767a72b260793922cf1ba2a03fedfc60d4eab1d5f00042); + tempvar res = res * point + (0x274b54e6342ced28b28c62edbc8a6cdb44d1530e0fba56e4940e55d806f437f); + tempvar res = res * point + (0x77273f7030b86a46aee79ed44f0968feb0ffccfa0964ffff141e693fd0fb6d1); + tempvar res = res * point + (0x4dbe5188f23eedad88bab99323be5ac9bf747525c23d4c0665334dafd1f0c6); + tempvar res = res * point + (0x3410d8b91297b00cf8d438bea18b9ebd55ae441a2f6bac6623a15e43ad64d4d); + tempvar res = res * point + (0x4195cb2f46ca4e1ef5d93ab3a5decbdc9e74d0bb81d56abcf59304ecf79863c); + tempvar res = res * point + (0x6581a70ec64b4268a4741b4f7de866050d31b69005c782630f4bdc51a1650b2); + tempvar res = res * point + (0x754535ea8702292678b57fbde36c97454994bed59e0d0e13cf8a6c3ef7a0324); + tempvar res = res * point + (0x71034c062fdc1b61e812617b037c5dd1e80d158a92bdae7ccaec162fff4edd3); + tempvar res = res * point + (0x297d52739d69b228b057588496920930df6ada28e5e2a431b65502750a5bad7); + tempvar res = res * point + (0x446d7e2595a1940ab7f6dec4c9f78953de9c0f4c67a130b55f1894779e73ac3); + tempvar res = res * point + (0x5b0a8465067d8f43cac5dbc1145110e1e79e0f32ba1d59d2514405a0a806860); + tempvar res = res * point + (0x5bdc50def36283e003e9ccf2f1bed188326bec8bed554815f9e49062ed6da4a); + tempvar res = res * point + (0x3b591c6de6700576abbe4b4544de71cd3266a5dbb70740762d0c16a863bead8); + tempvar res = res * point + (0x7fe75f49544ac3cf237a17e58179851f5b3e7420330e5861ec505291d9a0380); + tempvar res = res * point + (0xe09e3870dab755cabbeac23076891b510207da569b75bf32d3f63c8ce08460); + tempvar res = res * point + (0x66bb11e034bb55410211b7cd410cf076db77f008bd93f0dc938f089e853f0ee); + tempvar res = res * point + (0x630cb6b8bcbe79e58025a699d489116a875f287fef6f1677b497b8702c3777d); + tempvar res = res * point + (0x46ebc0bdf94c2f85023a0c1b29d229ef7a23e173d310b814f72c73904f6a5f9); + tempvar res = res * point + (0x3fdf21da099da6c005b076001c5a95f2fe26aeff47e2cb9e8e52166a22b643e); + tempvar res = res * point + (0x6c647f1e5e8e93fda4bc0ae5d513cb60558e2b44bf885484161bbfb5e093969); + tempvar res = res * point + (0x688dbf5c443560c219afd8c54a0b26bdc9284925f2cc0adc889c1de024d6ecd); + tempvar res = res * point + (0x3c782f4a1a6d94adf1448fd7feef975f47af9c79bbf7e2d74940673704b828a); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_ecdsa_x(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x22aac295d2c9dd7e94269a4a72b2fb3c3af04a0cb42ed1f66cfd446fc505ee2); + tempvar res = res * point + (0x2bc4092c868bab2802fe0ba3cffdb1eed98b88a2a35d8c9b94a75f695bd3323); + tempvar res = res * point + (0xf685b119593168b5dc2b7887e7f1720165a1bd180b86185590ba3393987935); + tempvar res = res * point + (0x5febf85978de1a675512012a9a5d5c89590284d93ae486a94b7bd8df0032421); + tempvar res = res * point + (0x4e1b2bc38487c21db3fcea13aaf850884b9aafee1e3a9e045f204f24f4ed900); + tempvar res = res * point + (0x324182d53af0aa949e3b5ef1cda6d56bed021853be8bcef83bf87df8b308b5a); + tempvar res = res * point + (0x5d4c38bd21ee4c36da189b6114280570d274811852ed6788ba0570f2414a914); + tempvar res = res * point + (0x529414d56e9f6bf4ce8be38c8f79ffab78b185da61d606c411098f981f139a); + tempvar res = res * point + (0x66d15398bbd83688bda1d5372e048536a27d011f0f54a6311971822f55f9c07); + tempvar res = res * point + (0x52e5e75be2c96802a958af156a9e171dc7d5cfa7f586d90ed45027e57c5fe92); + tempvar res = res * point + (0xb0e39f10e5433b2341ecef312e79ed95d5c8fe5a2e571490dd789dad41a2b9); + tempvar res = res * point + (0x703dcca99c0a4f2b2b7f1b653dbbf907dd1958c248de5dcb35be82031f7d170); + tempvar res = res * point + (0x749e86688f11d3d0ef67e4f55535c715a475ceec08547c81d11de8884436d8d); + tempvar res = res * point + (0x44a14e5af0c3454a97df201eb3e4c91b5925d06da6741c055504c10ea8a534d); + tempvar res = res * point + (0x6cd537aebc479350e63acbcf7b9da84f4b06c6c26a571d3a7dd416a94a956ca); + tempvar res = res * point + (0x5e2909b1136e1d6608663e5cbabb616b28d2fd6f5dfb7cd03c4a7e719b7c53f); + tempvar res = res * point + (0x51170abac6896de6a5b478741dd56f52b1d2a1feea59b1f26d060e09ed98b32); + tempvar res = res * point + (0x1d0f94ce5d9d3beaa42ebed05a2f172aa2227e9a9fee0bf43a3fb068c1ac345); + tempvar res = res * point + (0x785dc572a88712cb4eddcc8a167bb1b62f9a79282f21ee92a0374af76169344); + tempvar res = res * point + (0x39d9d83e0ac884a5ee0f2d227f9eda71724a55002a41938458e45251e121308); + tempvar res = res * point + (0x7fdc637318ea00385719f9ce50848d13cc955eef9f36a90b87e646dac85e3aa); + tempvar res = res * point + (0x72d82458ba49cd6c638f89d2e3a68e49944f486cdfb7d2848e51aa9f99292a4); + tempvar res = res * point + (0x4c484b2cc04747d8d812180ec716f779302231983fa17971b575274c0a9c378); + tempvar res = res * point + (0x62773dee1773834dbb324c4c0d48dcdf9bbf0511547feb1b2ab0f7af7fa2dc2); + tempvar res = res * point + (0x5b0343972ee9e17afaf76adc54e6797d54e6e47a7ea1167654ce076e3c6c360); + tempvar res = res * point + (0x3ca8d84242dd2bd2a5d6e644fa1dc9f5082ee6131b6f0db8fd7d4f87109098b); + tempvar res = res * point + (0x6f4ab1f3bccea47669a4c93da36db05bd6f5197945b5ab29191a703312ed3a8); + tempvar res = res * point + (0x2d626ebcfae2d3618e350c190fc636495fbb04dd4a4e563680fb961a3d30d8); + tempvar res = res * point + (0x42f0a74ce045e8194b7a5cac4e882b1f1a9face49c38fb3383cfd3d960806c); + tempvar res = res * point + (0x34b7ebee71c5876183407c57610a0a8a33d3138ccd6ae416651cd505e5761d9); + tempvar res = res * point + (0x150c633a21f3cfa157978e9561161f3953e180b9588347a0c819e4173afcfa8); + tempvar res = res * point + (0x4f8cecab5f743c7227a63fa7f320930ffa7cc52b0fff6c351d3e9d4c22f9f9a); + tempvar res = res * point + (0x98ad9c2080ba0663fb302025e6224cff41d1d30c5c9101ad77a48a71d8ac); + tempvar res = res * point + (0x58a6d8229d82c192f190e55d28489f621cbcc64e4ef10c1ec5663c5384e60f); + tempvar res = res * point + (0x7850ac1ef437d1b99c026a910b2437c1b877242e605c8f31a456f10e2f78743); + tempvar res = res * point + (0x337092590652e19c23b48de3629ae0bd4157a5a72ecd3fcd17bb93f05814716); + tempvar res = res * point + (0x95fd265a2a87c42af5a20a199e6730ee3f0e3352a38a5e7e84ef46c621903d); + tempvar res = res * point + (0x38ada3df52cd03154d66b7da4a8a01835a461e61a76ac9576649d8c00013610); + tempvar res = res * point + (0xc1bbae3cf2d414dc12119a0c746e3c10e148f8b522d574eff757d44d8b3a14); + tempvar res = res * point + (0x7122e4b28d4ee35902b7f7b8ad5f525b6c70a2f2bb6b4ee4b9f0008845ffacf); + tempvar res = res * point + (0x75275c33b919425b271966642fabd9ea7c917e70e96eda669040935b1d49db6); + tempvar res = res * point + (0x70af32c484244d3435bb65b0ed076f48d06abb45b7765de9c6f26c1c8e9156d); + tempvar res = res * point + (0x47c78a993a13204796a2fca3b20c0f02c0601e7cc59f84570fa026c65796dc9); + tempvar res = res * point + (0x55713c4cc9f91e9f158f70683238853d0bb7cbd8358ff72b01fb60808b5c1de); + tempvar res = res * point + (0x412fcd2551c0516392f685a62b54fb82b9a73bcffd42abecea4482b65aeea47); + tempvar res = res * point + (0x6925415cd4dbae0ea5e9f41edcb503ff6f668da1cb13ec73eab6a99cd96752a); + tempvar res = res * point + (0x3a2a902a0e43ab33c19459984fe116fb215796cb40c48e254de6126b55e9c3); + tempvar res = res * point + (0x552e18bfefab6c3362cec587f0a7433a914f1359e5767b4fe883f1ad902dd13); + tempvar res = res * point + (0x5643c5a69044bb8e86d10d3248ea3f50f8598732b0c517b256fe108294e09f3); + tempvar res = res * point + (0x542f931640d9010e906b7e1e375cd0481740157eb51500ea1e10afe77f26265); + tempvar res = res * point + (0x2a2811098d68a747bebe9ca2eae06b604bb307e5f51a9bdac1636f380feabb5); + tempvar res = res * point + (0x57d53073d66a528c88f24e40011321f74ce5bdbecd6ca319e5e770ae29b21da); + tempvar res = res * point + (0x1a4393bce3924d765902469c715fedeea69adca566859b4c8c412b7d7cb566d); + tempvar res = res * point + (0x6dfc1fb08b981f73911dc43811caa0ed99749c2f0903f87f389c9a0e2a88126); + tempvar res = res * point + (0x224fe4f546c8f999947a5864ed0dbcd64fcac6f774ebce11667c2bbb7d8603); + tempvar res = res * point + (0x1f7d548c5a6f2bc70ff6f8ee47f38221ae25dcb4f9b068054ee66227494f87); + tempvar res = res * point + (0x735f4476c2b51acb4f0dd9dbc4306108e37543538b2cd3cd2327ae5377a2e5d); + tempvar res = res * point + (0x66ec70c796374a71b6aec5520467ebed547f645d1670b990dfa680a1b415cd); + tempvar res = res * point + (0x14ac38a4b82b4c65e4993726b58f32c74988997b8e8f7729fe9032cf187896d); + tempvar res = res * point + (0x27092905558602aec9af09947b70bb974caa3dd7cb1cb991810e15d75194aa6); + tempvar res = res * point + (0x44e3645cc1b135410b2a52a5b92bcb454985033615453a51ac46377885c4309); + tempvar res = res * point + (0x352b933e5d853527d2a4317db613d07117fad8115948957515bc07d72e161f5); + tempvar res = res * point + (0x268c1e10f6f9969291b1d2f54289371a2f40a14cc67b3736e04eb891c1824ed); + tempvar res = res * point + (0xaa81707e389769aeb31cc8b45276af0370dd702ac79461bae0a4078cefb5df); + tempvar res = res * point + (0x67dec5ad6ddb1761ec61d2820533f7a2bb56d66f2fb8ecff9cbe28218990061); + tempvar res = res * point + (0x106911de08ef437acabf58d178db7c81ff4d7de25f3ef5cd2582f44176d449e); + tempvar res = res * point + (0x356591a80d5c2e14c3d8a180c030a9529a8580a4f3be00a5a9eea83d0d585f0); + tempvar res = res * point + (0x40a3ea8c4059a1b9138884234381d6d383e66dd48eac1bf05f5fcddd593c881); + tempvar res = res * point + (0x699e679a8f38a1ecb14c6695a2848c6abbab8a05003e43aa5cf4a9c6e6058f2); + tempvar res = res * point + (0x6b86f825e41b2c9934f71cc2cb08787d1bd4f2eefd2be9c44e37bf387b35940); + tempvar res = res * point + (0x4eb2786b11bc602bbf773564eb9b057d7dc02daaf4359c015295d97b74e72bb); + tempvar res = res * point + (0x7b0ed28b968689517aaa216c0203e57f1cf56b22ff1213561499ae140d37fa2); + tempvar res = res * point + (0x367ea925556a875faedf4d61bd2a95a31067bde6e682c50035bb3310cc54b03); + tempvar res = res * point + (0x781cf0ea1c0ba9cf908656aa2c5a9403d54c26c8ece401a2c13be8d3090f9c1); + tempvar res = res * point + (0x20ffc2b4c6c318bee0cdfdca40b2c10f2c629d3b52472b17c1bfd909cb7b85a); + tempvar res = res * point + (0xe5e89fde76daa211fadf1178785f0c25a94d47a468cda257a895b871a928c2); + tempvar res = res * point + (0x164344bae5b9dca8f384612e7351fecde28adee3d245c98dc2f65509b181d8e); + tempvar res = res * point + (0x4063a6202df9488fe5384aaf7be7610b3e88a9c01486c1b88767ca36355340); + tempvar res = res * point + (0x546f65cf3367a004f10e9a4e47d71f6ec80086cb2be19d7b225825e01eb323); + tempvar res = res * point + (0x72c11bd84cd54152607e4c6e558a28e480a6487e374b865682c167484f8c29b); + tempvar res = res * point + (0x7a5d11f284ee7db72bed2338784d6467e05cae85f333e05c5610c018a57c2a7); + tempvar res = res * point + (0x64c71feb673d2655bb1865f9c4bdfb16b1bcd0f278a911363056674dacb812f); + tempvar res = res * point + (0x62334e7d6094be4431aeebefc420f7e656459d6fc2cb10455123ede054f4cdf); + tempvar res = res * point + (0x5dd4b3dd252fa7eda7b46674369a2f8c5b00a891cf01ada0ea5aada8bfbf6d4); + tempvar res = res * point + (0x3373dcd7d0f0f8bb31ec396e1ec67e1f121121356dba549bce9fd4d3bbfbaad); + tempvar res = res * point + (0x42a6c571001e263b1ec8168805bf4d6cb65935cd0687c696ae3a6968fd28378); + tempvar res = res * point + (0x16f35b8d34d425a85fe48e66632d3e4af27d5d65cb180cb99047fdc2b908ea6); + tempvar res = res * point + (0x24327b5849aaae0d313870c10e8010a115b70a99cf6b92925f51d2f05686287); + tempvar res = res * point + (0x45ba7e524d75c65ab27b57a6e0b90458c9b0eb651935f84898a5d3cd0db9b8e); + tempvar res = res * point + (0x767d8839373a2e97b7e3de1be6f4c18df648806920e92fcc4da9ab6bd8525ce); + tempvar res = res * point + (0x741b0f4e1bf8ed4d6318f5dc5ebba8529089f5ef4a84cd727564c60cc11a96f); + tempvar res = res * point + (0x68682814e1b4dd639cf396a9f60efe5ca035c6ccd75054b8911e8a15230efa7); + tempvar res = res * point + (0x68edfc809bfa6534b583624db421a2cb885d2ce888e6f95eae85ad9cb38249d); + tempvar res = res * point + (0x5d6575134d1b37e610f25e65bc8b0b1ad7fd0cdcaa56fe573142a09707640b5); + tempvar res = res * point + (0x327bd35b3ec38fb121c039f777669426d3d60df3922e688a408a06d4e7ee3a1); + tempvar res = res * point + (0x29a66c93ef1fa5ac4b6f96ed329810085b294a7ab8e16c61b1e225fd7406236); + tempvar res = res * point + (0xac01d3129d24fe9b9209df8bfeb2526bc27e9c27d78f69eac16ce151b13540); + tempvar res = res * point + (0x3a967c407600baaac716275b8fa16a08c22e928d895c762b2843d00496b3390); + tempvar res = res * point + (0x4d111629c799fb16f602183ae372aee382e0b401312951eefe77a1674575242); + tempvar res = res * point + (0xa8a00bb9874fbb44ee3411814dfb9d4d6048f5e3af6f7f09fff4e9f0263901); + tempvar res = res * point + (0x3abd943152451107f59aa81194e7bbbe37c4a86a6b41e20a02f8145dd32fa87); + tempvar res = res * point + (0x580bd7107af3afc93d0cfd1f0bd39f78f06ebe3a900f5d79943c25e980e5653); + tempvar res = res * point + (0x7a615360e826e937db0c91cc1c9196086a3fd608cb01d20186ba1ce856904ed); + tempvar res = res * point + (0x21df6648e6f783b7361a20191b8d399a4373dcbcc83f6b4a9a40bf11956219c); + tempvar res = res * point + (0x2c82b2a99d198138ca2c4229a1929d044b113c1b0f693659712318ca7e7f804); + tempvar res = res * point + (0x6dd74321080cc46d816a963c8a6f5dac42cb11e66c79831efba77433cce0d23); + tempvar res = res * point + (0x1e54c3a5a3beca7932090ff58784aa43261075950feaab0e2a840f3801b81b9); + tempvar res = res * point + (0x3360af40b57c0a951da3219025643a76516f85119dfbb05f61874eb3b56b130); + tempvar res = res * point + (0x164d44fb88efb41e301934bf2c61a20e41c9bcb3f8e784ac5857063b4fc3d5a); + tempvar res = res * point + (0x46efbcd0bd7f06d59a430ddeb9f239d66a24ce1fa72f5dbcc2bab48b707b2dd); + tempvar res = res * point + (0x5ae517bdefe7b6785680842685de0b5cd972a22dae9ceb50a6ea3665feb06f0); + tempvar res = res * point + (0x51f4698c121db3db4a5244334c5180cfba256dc80a59689e2c0f1f8d946e6c); + tempvar res = res * point + (0x67d2681fae96c0b4bf22d10a73a1882c5bf4a5440f8d0458394d514ff7bd18b); + tempvar res = res * point + (0x3dab30754623b91aec7a165cc167e9003269ebab3e551781e4c8cfb73402de7); + tempvar res = res * point + (0x44be18892438118a0b3fc099da7489a89cffd4206678abfd37b1e649ad19178); + tempvar res = res * point + (0xdb0ad3bd8a33b8daf1d53ff8604bbe5259b6620e3b547d5c6f392dbc10ccd5); + tempvar res = res * point + (0x1a36f20817da4dc0c2e8b62fa08ce15cd3cb50419acf5211d6948bd6b28c8ce); + tempvar res = res * point + (0x5fa6f7f2a7a527880a5b58911dd7f3a491fc702f481cee30e67c4980092f851); + tempvar res = res * point + (0x6f682eebabbcbfa3e7084b47b2a01acb693865749df222b4b8dee0ec41903cb); + tempvar res = res * point + (0x1fd7088411b30cb5762147b1d6749942485b36c68ea32f60ab83fdcbe987d83); + tempvar res = res * point + (0x7172b43d0c88348e5453b0b26d54d4a7ad7e99e6b0c4b787341c8d89936197e); + tempvar res = res * point + (0x34369f479f013d44dd5bb0d79d8a9effdb2ca36ce8b3d7e759bf707233c5bbe); + tempvar res = res * point + (0x3054d35b59baf5b0a2078c23322de031b383033837cd6b978b6c060120b7fb3); + tempvar res = res * point + (0x23f0124cd1c3f3605fa1ec36dc4d6cb6e229f8ba8998b138a44595f96f3bf21); + tempvar res = res * point + (0x2300892e3f3c180333d091901ba99ab9e23c7947309b9e88ad47025847ec3a0); + tempvar res = res * point + (0x4182bea2ea16dcacb0194876cd5fe8c79e1a55836aff8aa6074d235af5f7b29); + tempvar res = res * point + (0x50f3e383aaf3533fc91b9633386542798abd69b79af893f47f6603d3cc35ea4); + tempvar res = res * point + (0xc37f91c81a7006d6681cb511dab2e4d83928ccb78d1dc72c4c556e4cd72db8); + tempvar res = res * point + (0x2693f31fd4bb5a1ef9cacdc4f2b33c3d6d965b76e7bf289020ab1b6c6660d70); + tempvar res = res * point + (0x2bebc90c59dc0e37e28c7c7d8254520ce08894637bf1a089aed26012690d119); + tempvar res = res * point + (0x17626d3869adf0fdd3fedd48e9fe1266bb33419bfe9046df43c6409b440980e); + tempvar res = res * point + (0x734438bc30566591da45df9366f936415d29eaeaeab392488bcccb9acf0edcf); + tempvar res = res * point + (0x22a7b1c897f54da39a1db61b345b234969e36ef6ba0ea02f8d8b3e83b5c6242); + tempvar res = res * point + (0x22eef827b9d0b57649233c5d527b4641decab31df78347a20da21c705df093b); + tempvar res = res * point + (0x193185be6e02dc0a07c0dced4ed031bf0a406219cce325e76408123406c318b); + tempvar res = res * point + (0xb10494024548b14df121b738abc7babe56c12acc0490699443426a52f3a4f9); + tempvar res = res * point + (0x375ce3766894524209e2043a150f10ad0bf4f726e3dc5453c3c757e56943a51); + tempvar res = res * point + (0x1b1c82e5c561dc42f8c9c2a9f7db6bacd729b2646892a8ecfae9ead9a338aa6); + tempvar res = res * point + (0x4b540d0085be455b24f014bf51dc7d0eceb8c93bb644a5208fa02dc58c718ae); + tempvar res = res * point + (0x17f2709d2719458a9bf72a2b04463f0a6529fd9368a47715c628ba4e006cea); + tempvar res = res * point + (0x20e468bb2828fb774d5ab538ff7f93ada201c2e392936e05cec29cd5a7a462d); + tempvar res = res * point + (0x29cc816e6be353f6ad5e2c390f37ed3940b0dd67610a7eeb0bcded94bdcf920); + tempvar res = res * point + (0x4d3b0654fd74862a92aa716af33b5ad5ac20dc0460c724d95ca94fe6d8a9d7e); + tempvar res = res * point + (0x7ba5194da963f8224987db2720f16baa604ff62351e66a63c0c9dba00fbc7c4); + tempvar res = res * point + (0x31d335bd885c9cdf2adc68ab45b8eecd2d3588cf85b93206896b2626eb1e369); + tempvar res = res * point + (0x4efcba706a8b7868e32f363efac2696ad0625d046a3ef97917c710515016386); + tempvar res = res * point + (0x56017977a273ad0e91c7c26a702ae4508343e97968295b08447b3cc7f20522f); + tempvar res = res * point + (0x16416cc193a5ced6ff213fc18c86bd6f08d17c576f26b9ebd00d2653bbd6444); + tempvar res = res * point + (0x4237c41364975eb79919303fc0a381b934befe871fdbd72c18f97627292923e); + tempvar res = res * point + (0x1b389d976c22a3bfb42424896c9b135a3794048724c729968f81e04ce414194); + tempvar res = res * point + (0x62fc206aa283139f7451e54cdac873fe86b6e7e89214a3c0318fbcaf6016fa4); + tempvar res = res * point + (0x88f6e5a835dfda9fa2e2ff248d9378352f4a89b6bf5935700da390baebadb7); + tempvar res = res * point + (0x4f9e975176d3aacd79c322d013c854c4b8829d1e469c9b242461f35e8dc6fed); + tempvar res = res * point + (0x6e1143b147dd1bcc56dd43e6a3616c9a4016d6887cf0009ebf9f9796efc944a); + tempvar res = res * point + (0x284c547c04ca83fdb01020cfc797eb362838317f09e5d25e1e4eef353ab7a7f); + tempvar res = res * point + (0x60c327ef73c8468805ecace45a33ccc375fc91ffbf01b4b10a01ffd4b7aaefe); + tempvar res = res * point + (0x59cd87f8751437900e984a009c63fdf7461b177067760f30d4f648ab271660a); + tempvar res = res * point + (0xdaf5a68420fa7ad811f6dc75c5b4e92173a5d89255dc75accb8cec80a9cd91); + tempvar res = res * point + (0x1f573af6e3ad146eeaa582f540de6a8db237ff2f28423660de998a4275bf4d0); + tempvar res = res * point + (0x2830a6edb344b7fa86506557a0b2b0bd900429218fb35e7990951fe4fe869c6); + tempvar res = res * point + (0x58f2e18613b3b25529935a623e7d5c8318ca9ff3fb180f16f7454ca9e348e35); + tempvar res = res * point + (0x42c8f0b5507417eb48ffeb1a7df8808633f193c27df8e2f44ee7bd62cb2c3bf); + tempvar res = res * point + (0x50d603bf9c2a456b828ae476092affde072ecd878877ec3f99ba8f574d263a2); + tempvar res = res * point + (0x413fda31150aa8462deae8a6043fc5624599fb7f638c4d5c5f89472e1223c28); + tempvar res = res * point + (0x13fe84c8ecc2e3fd289560c0ada7a251fdd5fba24c076be4be465feec4262e6); + tempvar res = res * point + (0x2b2a0768e9a5f59e7f33ea449690794c8b409bacd1c808f7ee8065ed9d8648c); + tempvar res = res * point + (0x3030332e9cf430f72159914e59ab9af532bdfdafedc1be39691256c8084954e); + tempvar res = res * point + (0x16617a52bfe5d2fd0eedb0d6411f5fafeb14a4ac17da0cc828c914acb500ce9); + tempvar res = res * point + (0x553f8ab49053432bab53835480b6f4c416eeffb3470fb6bcf122741cac3d71d); + tempvar res = res * point + (0x3939ef0e572dcc3b67f0cb819fffc521df26e50814281621fa6982b1465f786); + tempvar res = res * point + (0x520b18e79de342aa7095ffe56be6222b0d2e44fc3c676a5c994f24e427b45e2); + tempvar res = res * point + (0x3f3ae3871460ac578f5030d925e91c138f3290f8f3cb6d4b560b4b16fbacd64); + tempvar res = res * point + (0xbffb0e4f7ccfff0cee519edd1004eefbc47024f92c4409bbdf688c133ad285); + tempvar res = res * point + (0x62d6874b6dcb1c4dc8ed797b9158da4359c6c49f27af4851a12908ecad2092e); + tempvar res = res * point + (0x511c0ad7c0bfdcfcfaf925895a8ef5e8c5e0d147e29c9cdae45fbc998fce346); + tempvar res = res * point + (0x25199c11f7193e07191cd9b9108aa8b440ce1972dd1cbe5f0cc33b7783203a8); + tempvar res = res * point + (0x3cf3b95ba351a72019ed1bcadab32116adcf079e72800a9d88f15244e7743e0); + tempvar res = res * point + (0x19cf240d04f4859941f9b6af4a7088729aa10307cd08aa75f01cb22e872543d); + tempvar res = res * point + (0x1cd528d070930aef19e0f928fc744e79ff57e227b6aa1bbfce15a79166aefd8); + tempvar res = res * point + (0x475f8af086f7aa4ec3739f754f7dd291dc50decc7c7fb03de8aee3cf06824f); + tempvar res = res * point + (0x28f86fe2d71f9410e14c17195ae19c2c5e623c525c979f4f74dec3ef8848eb5); + tempvar res = res * point + (0x508243aa19e23cdb8ca0154055c05130462908c6a2691ae522e37ab9d6168f2); + tempvar res = res * point + (0x37cf9640e321e7bccf1926d5fea92918d6888c5805e27193722995233a4adc5); + tempvar res = res * point + (0x66336e2e2eeb939818f861fa4aa9b2576936470f511786f8fa3417850a6c2d); + tempvar res = res * point + (0x19a0ff21908842e412addb744b0ca384a54bdde819f6337c4c672f682fea9cb); + tempvar res = res * point + (0x44147236daf669f8a94b7ea353c3dd7e64312ece01ccc1d4dad67916591d50b); + tempvar res = res * point + (0x1d6cb5a655919a581078aa2f8a21d300425026ccd7d047302443d78dbc67abd); + tempvar res = res * point + (0x4d8d9b92b38a45147bc9c87c071672edd93cbf5bdc8d85e608f26f1d82d172b); + tempvar res = res * point + (0x4acd125e74056ca611a1b07369166eb5c02af7a4cbf387b2bd584a362fa9e60); + tempvar res = res * point + (0x3b4fdc8d965de1761e445ee88cb406f707f9d0b1ea3c069d12084c0ccba9b44); + tempvar res = res * point + (0x1f27c20f47daaf01d4627d5e9bee0e9bd2aa5b75807064cd60ed87e307f677a); + tempvar res = res * point + (0x4758304a75f149e24563c2b22459151389b86d36108f5dfe11ea1fc7a64fd7); + tempvar res = res * point + (0x1c1216fe648d287c2645dfc5152e171f25483df5ef112b745c2e59b5d9ee07c); + tempvar res = res * point + (0x24adf288d61c113e28d9a298d2642eb67586019adcb952abf274ebe1d30e24a); + tempvar res = res * point + (0x3e09706cb43c83143c9dc46f97e0e1ab4327de19ced69badaa8b2c80f68fb9b); + tempvar res = res * point + (0x589a2e11637d0c90fe91bb9f4d55a80cd1a2df7f3431e8b8bdce8fe7d35126c); + tempvar res = res * point + (0x5f506aaae7ce6d94712c9e0ab02bd2a4ae09600608d54a8ca381b8e96222cf7); + tempvar res = res * point + (0x3f64b3a307276c6a7169c54297bb12aaeebadec98df6ba1184492a82effe353); + tempvar res = res * point + (0xc3e0400cbde1da659381240d9c84b977eef3cd70e3e4a1a8763a05e682eb3b); + tempvar res = res * point + (0x1fdb038204ac50e87e3e7239d8c1c0572893ba98e031c982e545e6de64cb8e0); + tempvar res = res * point + (0xe0b21e37008355c35f7aee295a8b2b72465866b2bd68e72d36f032c34b38a0); + tempvar res = res * point + (0x2cc90219912af16cf9a39f57f8b8c514f797dd5d49dfed5eabdc278e31106a2); + tempvar res = res * point + (0xab2147a23a826d5f7c6fea5bf889eaafb5531721f31ee0a9f02fd58f09f65c); + tempvar res = res * point + (0xa5d4606609371577b0d17fadcd85ce659885b00245a67b038f902176d99a7c); + tempvar res = res * point + (0xfc76b77f717a5b3ecafafadf29e7f886c8ae67a3a2bb30467c440472349953); + tempvar res = res * point + (0x40fb948f8a4a10d2b2e928a5d77b481f8d3068b47fa388a3ee65609aade1a41); + tempvar res = res * point + (0x13d322a0ecbe1e785921a7aa6f4d1135e0798e72f4c055226205314b8348144); + tempvar res = res * point + (0x20096a7aa30c6c42f1d5f1ed88de275d1d1610f2548711a75fbbd72d373a50e); + tempvar res = res * point + (0x18f9cfeaf2c33e21d7c6fd9e15a3601a2fb3905588868167566e8c1f1dd30fa); + tempvar res = res * point + (0x3e3aa48bb5db9e2b0dc6d294009ecd5d4ff6255dfcdde3f5b4e545032ea9b68); + tempvar res = res * point + (0x425b03b0356b92e66ca816869a76110d68862a0d8ad76f950fdb1d5c03279d1); + tempvar res = res * point + (0x7cdb723061223f33289237c7476e737ef0bbc5e2c1ed9a70566511fc2036ba5); + tempvar res = res * point + (0x18b8b8d0f393950c9a2e674052150a328d214618049c7e2f58cbad76adbfbd5); + tempvar res = res * point + (0xf19faf3accc43b56369dccdec35dc7b49c5b8f8976764886bd16dd2e155f92); + tempvar res = res * point + (0xe08853aabc9eb934b4470bb4ae1dbbe90c61d2093516df998ca7adc98afe10); + tempvar res = res * point + (0x7736291268c775a82caea06004d53edb829be2566fc7c4053b1d850a8116cac); + tempvar res = res * point + (0x1bc1186238f0d39e1c56185a8d2bf00c90c9c89647917d60a5b762932856524); + tempvar res = res * point + (0x6cf772fa8050ad8eb87bc8f0c8fc511622b416fdb084cbc93b79501c96b0bda); + tempvar res = res * point + (0x7417da24519b4c55ec0d698ecaceeb49711aa1e7f7d907102351e73388a0fa5); + tempvar res = res * point + (0x66e1e25d1bcea87acd136f2c33498e3223fbf78bc6cc816ad6aaf68e961da0d); + tempvar res = res * point + (0x60db5bf6f060d82c169a1c4ed6c548d5e8cdb6cfd2e3257c155bf11f48ca609); + tempvar res = res * point + (0x2d5447623584d3a19e9993814622d6369248bc61813f067c4825c9b0a81551f); + tempvar res = res * point + (0xac068a1aae938e26e125b35c88a87130044bf3637bf1acd797103e7388b33a); + tempvar res = res * point + (0x3ab2d353537697d4de9c5c4c0bc31e5e776cb93181029144f6c6d4b5ea4317b); + tempvar res = res * point + (0x6ca2dd473297a2852e68ea2b83faf8f71e5cb471adcc74a858132c6a823f0c0); + tempvar res = res * point + (0x1ec5264a5287f1c6de79b3df3adbfa157e8430e594078c3fba7002a077db447); + tempvar res = res * point + (0x50ee695deb5a4e63c5dd6de35621d1c0c5a496bf41fecbaa929b2b3e23f174a); + tempvar res = res * point + (0x36f446f7e5a51114cbdd3b460431bacb5a42cd61f4690cf5e9d9f13e488318d); + tempvar res = res * point + (0x195f98a85cfe403a7d229a6eb4533a1fea641c331db75a5807711fdf1e27dac); + tempvar res = res * point + (0x63d4964faab567e795024a17032ec564ff221a421bd2e42632d3770c73dbba1); + tempvar res = res * point + (0x68d729620eca6b4d904198a0e6d241953b9b8c874a10b5ede5596146d560979); + tempvar res = res * point + (0x1137975bab819ce0cbc73714305030fcd4a185f71d46c169908460390d56d18); + tempvar res = res * point + (0xf639bcd7777c1ffd41a693ac9f5a051bd124b7edce3d568f14304c9fd90a67); + tempvar res = res * point + (0x2322f8d96071356feee538e0c53d857b1924134b94377af20ed5d0e8b3925b); + tempvar res = res * point + (0x22cf65c6bbbf76765555748cc1ae91c83ea93ca2c8b34a59332567b5b3b0cd2); + tempvar res = res * point + (0xd62eb553de83e5d51f78ddd9480d65870dc426f61153e732eb6cd62cee09cd); + tempvar res = res * point + (0x6afb39d46d5a846e9d58a6ae27e6cdd83bee29c72754cd4cd3d3cae423f5c9d); + tempvar res = res * point + (0x364889e46da58b66c827835a0c2807338eeb4431f2099f490d13bbad0777a01); + tempvar res = res * point + (0xaea6f7f915e4aec612029a9d02316baa3f6297ea4cfd38897f4c9859ec485e); + tempvar res = res * point + (0x5c180e2fbb2b51e053941d0e1611424fe60ced6d439115dd98530c8d79cca4a); + tempvar res = res * point + (0x1ab93f16e576b6a54598582eff5e2cfc33baeeb607826579680636b05046d16); + tempvar res = res * point + (0x4de47e973af27fde9ad29f812de8a04855110118eb73fcdb46865390486a287); + tempvar res = res * point + (0x50be25e516e30f96d8b420a7c494506d2cd21d64f4d5ecb67d58c2ae99bf5e0); + tempvar res = res * point + (0x2aa45ec320ea12beb804e35af3684dc981324dc9bd044592d1c408c052a4322); + tempvar res = res * point + (0x26701dfe3cc76754a4ab893fef59886a43013ea6ba648efd82fd03941fa2910); + tempvar res = res * point + (0x1773ba95dbeaab6e5e9fc79ac153d46be1e57828e92287d698a3f4f87ef4984); + tempvar res = res * point + (0x4e92d5f575fcaac9adedb4e0c3549dc18f61bc40e3752e3506f3761c32c6e3); + tempvar res = res * point + (0x580f9d95c2bd746c9210a87b0f9ed275afee1dde7a41d9ad5e69861ec0e43f6); + tempvar res = res * point + (0x3e2dbef5f162784e13b5ff4c33bcbc444ad1546922b293d6783b5de5c5aba78); + tempvar res = res * point + (0x596f89b6ca79194eb6a87c17692aa491f5b014da3cc7e5f05caf4fc1779c2dc); + tempvar res = res * point + (0x7e84842d5fff1666e01505f62661bcc822dd3fa530ebd1e4089230a4045a04f); + tempvar res = res * point + (0x5626d2ae9581d1d335bfc3863a4eaf3568ec8e70fcdae93f50a15b0cf601b6b); + tempvar res = res * point + (0x68371fc7cb3e0670a73eb3a7e773ddb63f231c26bf25bb1fc1fe6e93a7e3bd0); + tempvar res = res * point + (0x4d215dd42f87632a9cce2cb95081dc731e36796c3d2847dc96a3554231c6aef); + tempvar res = res * point + (0x421fac0e48da8e6355c07f6a64bcea96384848e8ea9a7113ab45f15b1dd15aa); + tempvar res = res * point + (0x679061e5f453c8bb1855dce8f7d61f2cb64b15d2c4e70b969ec4ead3fc6a226); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_ecdsa_y(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x23a2994e807cd40717d68f37e1d765f4354a81b12374c82f481f09f9faff31a); + tempvar res = res * point + (0x49d16d6e3720b63f7d1e74ed7fd8ea759132735c094c112c0e9dd8cc4653820); + tempvar res = res * point + (0x6c930134c99ac7200d41939eb29fb4f4e380b3f2a11437dd01d12fd9ebe8909); + tempvar res = res * point + (0x347dfb13aea22cacbef33972ad3017a5a9bab04c296295d5d372bad5e076a80); + tempvar res = res * point + (0x62e62fafc55013ee6450e33e81f6ba8524e37558ea7df7c06785f3784a3d9a8); + tempvar res = res * point + (0x23b940cd5c4f2e13c6df782f88cce6294315a1b406fda6137ed4a330bd80e37); + tempvar res = res * point + (0xf524ffcb160c3dfcc72d40b12754e2dc26433a37b8207934f489a203628137); + tempvar res = res * point + (0x603e3a8698c5c3a0b0b40a79ba0fdff25e5971f0ef0d3242ead1d1a413e443b); + tempvar res = res * point + (0xa401d8071183f0c7b4801d57de9ba6cda7bd67d7941b4507eab5a851a51b09); + tempvar res = res * point + (0x37d720cf4c846de254d76df8b6f92e93b839ee34bf528d059c3112d87080a38); + tempvar res = res * point + (0x5057b804cff6566354ca744df3686abec58eda846cafdc361a7757f58bd336e); + tempvar res = res * point + (0x76b4883fd523dff46e4e330a3dd140c3eded71524a67a56a75bd51d01d6b6ca); + tempvar res = res * point + (0x1058ff85f121d7902521abfa5f3f5c953fee83e0f58e069545f2fc0f4eda1ba); + tempvar res = res * point + (0x4eac8ffa98cdea2259f5c8ad87a797b29c9dccc28996aed0b545c075c17ebe1); + tempvar res = res * point + (0x6e7240c4a94fa3e10de72070fd2bf611af5429b7e83d53cfe1a758dee7d2a79); + tempvar res = res * point + (0x59fef071cf1eeff5303f28f4fe10b16471a2230766915d70b525d62871f6bc6); + tempvar res = res * point + (0x480d06bb4222e222e39ab600b8aadf591db4c70bae30fe756b61564eec6c7e); + tempvar res = res * point + (0x7d2292c8660492e8a1ce3db5c80b743d60cdaac7f438b6feab02f8e2aade260); + tempvar res = res * point + (0x5a593d928542a100c16f3dc5344734c9ef474609bd7099257675cef0392fab8); + tempvar res = res * point + (0x761717d47600662a250116e2403b5115f4071de6e26e8dc231840eeb4484ec3); + tempvar res = res * point + (0x4b74b468c4ef808ddcc6e582393940111941abece8a285da201171dc50525c7); + tempvar res = res * point + (0x14ef999212f88ca277747cc57dca607a1e7049232becedf47e98aca47c1d3fe); + tempvar res = res * point + (0x47b2a5ef58d331c30cfcd098ee011aaeae87781fd8ce2d7427c6b859229c523); + tempvar res = res * point + (0x59bd7fe1c9553495b493f875799d79fc86d0c26e794cce09c659c397c5c4778); + tempvar res = res * point + (0x3ede75d46d49ceb580d53f8f0553a2e370138eb76ac5e734b39a55b958c847d); + tempvar res = res * point + (0x6e0bed1b41ee1cf8667c2924ebd460772a0cd97d68eaea63c6fa77bf73f9a9e); + tempvar res = res * point + (0x739edb8cdd16692deaba7fb1bb03f55dd417891bacb39c7927969551f29cb37); + tempvar res = res * point + (0x247573f2f3fbd5386eac2d26851f9512cd57ad19773b8ca119d20852b9b6538); + tempvar res = res * point + (0x2f6efb89f27d2c0a86ec1e6f231b225caf2af9be01aca173a15fa02b11fdf24); + tempvar res = res * point + (0x75a0f99a4dec1988f19db3f8b29eeef87836eb0c3d8493913b7502cfedcef28); + tempvar res = res * point + (0x278a7c68986adbe634d44c882a1242147e276fee7962d4c69ca4c8747b3e497); + tempvar res = res * point + (0x675532b80f5aaa605219de7fe8650e24fee1c3b0d36cdf4fb605f6215afacee); + tempvar res = res * point + (0x5599e790bd325b322395d63d96cd0bd1494d4648e3d1991d54c23d24a714342); + tempvar res = res * point + (0x43545892bb5a364c0b9acd28e36371bede7fd05e59a9dcd875c44ff68275b2b); + tempvar res = res * point + (0x38db61aa2a2b03053f5c51b155bc757b0634ce89baace113391369682fc1f74); + tempvar res = res * point + (0x71b2b6b03e8cc0365ac26c4dbf71e8d426167d79f8bd1af44738890c563062a); + tempvar res = res * point + (0x3a663fc27ec3ad56da89d407089bcec0971cebcb3edf0c393112501919643d7); + tempvar res = res * point + (0x1030d58878296e14b1c5bcafe7e817ebe4aa1039aa96b9d0dd7fc915b23f42a); + tempvar res = res * point + (0xcb3335374cc2a2350fe53d2389f04952c4d634f489031742dfccca17be2e09); + tempvar res = res * point + (0x6ae3ee97ea5dcfbb7c36cffd89665baf114fae391c0367be688db09861a8ca1); + tempvar res = res * point + (0x7b16c33c4a8ffcecbd83f382469e1d00a340ceab5e7d9c0bd4fd010b83f4310); + tempvar res = res * point + (0x10f236430f20aafda49d1c3e3759c510fdf0c0c19f89df6d5d71deac88b547b); + tempvar res = res * point + (0x104b04e96151f5103118c4eb556cd79899148fd6656e73cb62f41b41d65e4d8); + tempvar res = res * point + (0x253bf2869135f4bda4029cae2819b2f468ae88530f3ea771090b2727814c494); + tempvar res = res * point + (0x65d50aa3c1d84a3deee14057eec98656a1296cdcbe32250bfdaa50ffac4c5dc); + tempvar res = res * point + (0x76323f8567119897f10d58e1552c98f5a62f03a16d3737e20fc2b0a31a3a843); + tempvar res = res * point + (0xdaee1c7b34ecb34717b7313dc4a299dd1a161447e2e0249426a6fc33a72289); + tempvar res = res * point + (0x2bfd1294f111a5a90842d19cffb97481aefbc09ab6c47d7dcf91ba228019c07); + tempvar res = res * point + (0x4f63db02e10fbe428a5dda8d9093feef46cc19568a3c8ad2fce7e7519004095); + tempvar res = res * point + (0x761a240cd8aa2f135daf0760bfc2c9d5e896e93a45426571cdad9118722e2b0); + tempvar res = res * point + (0x30a2e8ac9e6605fd722dffb4caca8c06dd4a8968a7bf41a5371cb1a07d11c00); + tempvar res = res * point + (0x5ba89e0eb3830039d0f8a9ca00acef15db22374c965b01abc49dee46270a7d); + tempvar res = res * point + (0x7e8659c39d7a102a198f0e7c3814060926ec0410330dd1a13dfadeab4e74593); + tempvar res = res * point + (0x5a00feeb391114d7b976654ab16ddf8360f05671b34d4a97da278c0aef34d76); + tempvar res = res * point + (0x33ff2d848bf237f536524da818598ae0f2516ebee526b77957448973eefacd3); + tempvar res = res * point + (0x4e0a5dd802deed7cb8d06527beb15dad32547bae77141c32473f4c8148912e3); + tempvar res = res * point + (0x776459dfedbbdfcef7a31e0f60c6480fc0676b280fdb6290859fe586d6e6106); + tempvar res = res * point + (0x59d0d8ca9ecda81081dfcae7580ab3c08a72195438c1556000c0c1dbdc08174); + tempvar res = res * point + (0x6eb66d366da57e4ae717307dfc3351579fe857c51aa82b95044473c9ed14377); + tempvar res = res * point + (0xa758a70ba6a0cbcbc65abfeca51359904f790752c3df55d42707253d8dea70); + tempvar res = res * point + (0x2046e1b4fd4c108e8f832f5bcc4dd46abf0d19ef0237beaec29d6c12fb9832e); + tempvar res = res * point + (0x472d99d1a6e1a6aef339eab1af3d53af7a8326e4d0a6bac73c3a159031c3686); + tempvar res = res * point + (0x1b0fa36439192f135c239918bf47ad14b55ced699f4582d929a60dd227b34ff); + tempvar res = res * point + (0x728dd423dbf134972cbc7c934407424743843dd438e0f229afbcca6ce34d07d); + tempvar res = res * point + (0x4e42531395d8b35bf28ccc6fab19ea1f63c635e5a3683ac9147306c1640e887); + tempvar res = res * point + (0x1ea9bd78c80641dbf20eddd35786028691180ddcf8df7c87552dee1525368ba); + tempvar res = res * point + (0x68a8c6f86a8c1ebaeb6aa72acef7fb5357b40700af043ce66d3dccee116510a); + tempvar res = res * point + (0x25c5f348c260177cd57b483694290574a936a4d585ea7cf55d114a8005b17d0); + tempvar res = res * point + (0x339b405bffb6dbb25bc0432e9c726b7f94e18cf1332ec7adfeb613345e935ab); + tempvar res = res * point + (0x23590dabe53e4ef12cba4a89b4741fcfaa232b7713d89df162031c8a627011e); + tempvar res = res * point + (0x534a4f3cf71c93023e473f12e407558b6c24b712204fd59ddc18c7bcddd571e); + tempvar res = res * point + (0x2e1b2a3c32aebc0be30addd8929c01714783aaf01be8a1d35e830646e8a54f0); + tempvar res = res * point + (0x605a244f646a825602891bf9ddffef80525010517b32625759b0bf5a7f2c386); + tempvar res = res * point + (0x4f81a946bb92416d212e4d54f2be5fa8043be6fa482b417d772bfa90be4e273); + tempvar res = res * point + (0x655038ca08eba87484bc562e7fd50ce0584363278f9d716e31c650ee6989a2b); + tempvar res = res * point + (0x44938959c2e944eb6e5c52fc4ee40b34df37905fa348fa109f6875c1aa18000); + tempvar res = res * point + (0x30b11c32e8aab0c5908651a8d445395de52d5ce6a1efe75f2ad5e2c8c854a30); + tempvar res = res * point + (0x4a92733a733f225226a3d7f69297e7ff378b62c8a369e1bbf0accfd7fb0977e); + tempvar res = res * point + (0x1345876a6ab567477c15bf37cc95b4ec39ac287887b4407593203d76f853334); + tempvar res = res * point + (0x580550e76557c8ff3368e6578a0e3bed0bac53b88fefdde88f00d7089bc175d); + tempvar res = res * point + (0x7d7faca17be1da74cf132dda889a05fce6e710af72897a941625ea07caa8b01); + tempvar res = res * point + (0x62be425458d26cfedf8ec23961cdfd9f4abeb21f1debbe87bd51469013358fe); + tempvar res = res * point + (0xd77a8e8eed7ce4931a6d2a4774c21864e2c9f468d080af9aba6756433a1a8d); + tempvar res = res * point + (0x3e850e31c0345726c1ace38537dd88a50c85d6819ae98add1bbd62b618f7a1c); + tempvar res = res * point + (0x375a5d9b11c83d06a04dc9f1908b8183adc6f04e5b2ceeaa23d3b68c973ee77); + tempvar res = res * point + (0x76640613af9ed1a125624e0c38252bee457ce87badb24fc4f961e55883d9077); + tempvar res = res * point + (0x5428ff423f2bbabcb5f54aafa03d99a320b4b255115351f50b229eae5522178); + tempvar res = res * point + (0x6dcfc3a99563a5ba4368ac4f11f43e830c5b620a7273330e841bedec0bfb5a); + tempvar res = res * point + (0x2652523cbbec2f84fae1a17397dac1965127650479e1d5ccfc6bfbfcbb67996); + tempvar res = res * point + (0xa737d6916aa6a869252d8ff294a55706e95e0844e6b047755704e37d978e09); + tempvar res = res * point + (0x2833391a62030808228d14437d6f91b31c0038c14988a23742b45e16f9b84b5); + tempvar res = res * point + (0x284f7815a7eabc1dcf56da511f7d739f1a199f8ffaf3474f645d2fc93327dc); + tempvar res = res * point + (0x1e141c5429a369996563573bf61d7f713cb7d25baadff636ba2756c65a910ee); + tempvar res = res * point + (0x60bdb98c079bd5cef216803b056afce03f6ea41934275c965d6e196240fb953); + tempvar res = res * point + (0x7f2abefac9e7f8109b0a2d25d0bd297059e45dd66798ac8b299f0a3e442dd2c); + tempvar res = res * point + (0x41776c662b44a36c7075097c14b6010cb321591a4eca2866d58252eaf9471ac); + tempvar res = res * point + (0x573b13b32161c11c9b16eff7cf93fa770a3ef667547a27503e39092aeabf73e); + tempvar res = res * point + (0x327319fcc0d34a0d64f5acab00244b43674a60bef754844fb2920c87c90cff0); + tempvar res = res * point + (0x755f0e4c374e2fa4aa7eda10041e2139a4a7793eea44f415c73ad4fcba1758); + tempvar res = res * point + (0x7b9cd3b277f00a75a17961d2d8e46e6a1838c8500c569cdcad08bd4e0cbae84); + tempvar res = res * point + (0x21f5ea8660d290f28b9300e02ed84e110d7338a74503b369ad144a11cf79f63); + tempvar res = res * point + (0x5e4b0ecc6a6c15ed16c1c04e96538880785ff9b5bff350f37e83b6fed446f14); + tempvar res = res * point + (0x3d8506e792fa9ac86ac9739d3d5bf63cfc13c456a99c8581adf590c8d9b72eb); + tempvar res = res * point + (0x1e3b6498f0daba2fd99c2ac65461c3fa519cb738b53cd6f002e97199fa4161c); + tempvar res = res * point + (0x70930735d913d54915fba20c97f07cba8f33eb8f4f81fd869699a10e83264cd); + tempvar res = res * point + (0x16a36769ee50227c564bebce3d9cd7c4ca55702a7c7ccf403075f68f05a0c2); + tempvar res = res * point + (0x3aa748723229eb8b33354e0901f50ad052b6c1006916790c979133c4442be90); + tempvar res = res * point + (0x5db8c52b6adb520496f9edd7105c92df67e8605ff4e0cc59992c3eb651ac7a4); + tempvar res = res * point + (0x4b2222d0aee638c7e5efd8ada791638ac155a01b78f3b532283574653998bb2); + tempvar res = res * point + (0x26a4b2a61f40c1ad77737b99cb27d2f3118622be64f0120907e2589d2f25ebf); + tempvar res = res * point + (0x5820792f23a13d58ddef0607950d422598bb1f21888dace88929fbe7d4828c4); + tempvar res = res * point + (0x3678de28b6896959edf5c9dc0caec59b02dfbbf54811f87939b32d0523f58bb); + tempvar res = res * point + (0x3cd13f84bb7ae6eeccc1012837d2f3e017f069e66cf047172bc70371f5aed38); + tempvar res = res * point + (0x7af8995e2ceed8841e34d44365c7ca14f5980a6a5c67b9813fa7bfd74a9c1b1); + tempvar res = res * point + (0x6d7af6524127a117184a0c12a6ff30d28b14933a4e96bb3b738d2a36db72e84); + tempvar res = res * point + (0x73200d12e733294b5cbb8ffe7fb3977088135d0b0e335135f9076d04a653c58); + tempvar res = res * point + (0x229d7fc2a1bcfbe00d5773f8dadd70a2641d8578fa73e66263b3512d3e40491); + tempvar res = res * point + (0x29889daac66c404d6491ec3a435d810a2877d885df1a3a193697b79b4af39c4); + tempvar res = res * point + (0x171f0638dedf0b69655fa9930bcbc91b257e299a6717bd8ea23ef550c8faff5); + tempvar res = res * point + (0xded0f75cd0a6a5401a954d26880eaf12050ce6458d3254c9dd6354bf66278); + tempvar res = res * point + (0x7fc7d854c9d0b3bfbf826c384b3521af0f29f975613e8ea6dc14f37d8beb54c); + tempvar res = res * point + (0x6d1c3edcf1de16a4e0ad7d8aa099a31fa2cfbf81f6d1a5798bd1ef93ff906af); + tempvar res = res * point + (0x3444c0f008988c8f600270b365ff926f016e49a54ab35bac4f3b3a42a5879b1); + tempvar res = res * point + (0x2a48058c77edcd75dd4323d9bb9eccb854009b1184fd716a8202f8627bb5447); + tempvar res = res * point + (0x56cbe248ebbc2f57ca8b943b219ba245791592f687815293a4499ef598fa9b7); + tempvar res = res * point + (0x658160ea7b654d786dc624b258c691f594e080610c2d41d6ebea0d8e3396849); + tempvar res = res * point + (0x6fcc261ded0ba97b4defc7c9bcd32b5dac89e4c08cb55cef98c6b50f5a3a289); + tempvar res = res * point + (0x7b74edd15d97b289da4040272cfc573f69a8c9a8b36d05e3e50b598508b7f9d); + tempvar res = res * point + (0x19637a12aa8b822c4a3f3551ef6c538043371a12a962de1dc25d67e0a5ee561); + tempvar res = res * point + (0x4c05a7abaaf08f21d93b2257d4f4a3ab2b44f4ac44ce0444418c864ca18470b); + tempvar res = res * point + (0x657060a10db73c4a9b6aa6288dd6164e0b50a4e6efbc2ee599a0cf4fda33b81); + tempvar res = res * point + (0x688c61ee887c1497ffcef82163f1a81bf7778f2c314ffbd325627bf0b25dc5a); + tempvar res = res * point + (0x54ab13ae1984dcc7d38c867a47f4a8cf786079ee07cc94ab5ec1962c21f638b); + tempvar res = res * point + (0xccee381472bb7dcae008316038c87a44fd9295f730e389eff14e86442c41b8); + tempvar res = res * point + (0x610bf9b7ea4557d72411ec90fb677f9a2ccb84c76f003954da4e7f439c9a84c); + tempvar res = res * point + (0x51d6322f7d582892421e977464b49c4e6e64af2438da9a7f21a061c77712dc); + tempvar res = res * point + (0x7d92a463e2aec09eb86f4647dc9ec241904135b5eb53ea272e809e58c0a271e); + tempvar res = res * point + (0x17ab90241b58bd3bd90b8a5c7f30aa9e5afeedbe1c31f21ca86c46c497b573c); + tempvar res = res * point + (0x199d80ad30b4b330fc8a063d1e87307993e1d98822a1729488ba8a586045691); + tempvar res = res * point + (0x601a139ed75acbecf557cd6513171385a119087585111c30bbc1b65cd6d30d); + tempvar res = res * point + (0x77b10e23b08892ab18cc6b14dfda6f4be5c2fec94a12e3622622376edd0d6a8); + tempvar res = res * point + (0x2a17a5c34f9f598deb5bec334fde606eaa5601df908eb5825ecf70f9cecec3f); + tempvar res = res * point + (0x7e176a66dcfd58e240c4546cd760b7e5ad02e4f0265c6a2f38d710bbdf99d55); + tempvar res = res * point + (0x27e76848780aba5b12061bffefff1710995586618a2f32792d62771d31ed519); + tempvar res = res * point + (0x43f51dfe0f1cf290c9a522e2a5e734f79d220be80348438c676295c3d429e); + tempvar res = res * point + (0xf1f93c3d919653f02fba06fcba1ab89497fff53eceff6a7d129887d5a9e3b); + tempvar res = res * point + (0x79fd6f5f9b042ece36af6b10eae2eef9de9c9dd18752eb66868a0c301015dd9); + tempvar res = res * point + (0x1958435eb08883bd69b6a56a8f3103c22f8ae206a3d4deaf4a04118b4dd6a6c); + tempvar res = res * point + (0x329230075f64ffbf631eb0c40b97d71b4dc38a08bd18b638f57e5644680068c); + tempvar res = res * point + (0x219557f1604be8622e697e986c03d2a49e40cce558a264bf4f1ebe06493eceb); + tempvar res = res * point + (0x7238f034b8c57c8b59b0f744ababf9da8229152a051d4f3b3c4995233ac1111); + tempvar res = res * point + (0x201019c76d9aa29a00e6b18a4eeac7b1322b44285c57cf4c0b68a87120b1d31); + tempvar res = res * point + (0x69d95f3c7892a1cf65b45c324be2294c4c5459e05e0feaa0b8bb98cd8bc958f); + tempvar res = res * point + (0x78aafbe80fa5ee9a846e991bf35b81567a6dcbb1b190e7ee47e53fc66422e84); + tempvar res = res * point + (0x15ba3c5a882d4dfe3e23db18368ade6b2d10ef52e34f12ce0d62e7183c10f7e); + tempvar res = res * point + (0x1a4bdaf2bff969eff8cef73e762b6346492b8d0f17b2e42956c526f625241ea); + tempvar res = res * point + (0x4adaabee9ab3c6ee7fc67a2ddc09c5185755dcc76cc3b814a6b71aa7ae542ea); + tempvar res = res * point + (0x2f47cde744314dc0502faffb0387a2e765e4354b0516ee9ab0b97a1b6c33ec2); + tempvar res = res * point + (0x90b2b18b3fc2919a55b71ad6d6fa67dda752bd02c985b59e6554f557fe4a2e); + tempvar res = res * point + (0x6eba866251e1dca38a21c8b3fad0aa3c22a45dd89884c4c68bd7ef67de64f52); + tempvar res = res * point + (0xb8dd33ef8726747fb368aedf80c2f4a720bc1b5220f4a3f0e56e2fafb7e243); + tempvar res = res * point + (0x1fac2f441d05a3b483675200cb1ebc6f4ca6ecc5ae60118fe8745f95217bf8b); + tempvar res = res * point + (0x6d28879c6f75c4ede18e1b94ffff964d08c79038fd9ba2e7873cbefb5f323db); + tempvar res = res * point + (0x28b38e0334fc06af4c94ec4f9434923d4149cc51817526597423fd4692c59ad); + tempvar res = res * point + (0x84add7269e2e41ea57aaed996f4c012ba7003ea2b994670cc0d554b7a8bd2a); + tempvar res = res * point + (0x64d672ca00300ddd5e9c9d2db433d7623bb54c8eb2db51b235a07616f1517e5); + tempvar res = res * point + (0x7f71cb5526600d15d3413ec971ee3b133718224b3cbdc68171a53d7c8684382); + tempvar res = res * point + (0x38e5702bb10256e1856a5bfb03a06b231b89a36e2f84af80bcd2d027153d847); + tempvar res = res * point + (0x1a8d4b2044b8e03b325c353f3f92283013920b92f479064b6e93159d2ed3ba0); + tempvar res = res * point + (0x68384718bd3bb23f32999f1edcb2dbddd8136259e676c4492d0cafe80ffd856); + tempvar res = res * point + (0x31a77aa370bb597dbdd0422612a7dd947aae09a5b0b17d1996f13a85103d150); + tempvar res = res * point + (0x40a9cea0394d15ef057c2923d4185f290fe2347e00529d92f927ef506e3b5e7); + tempvar res = res * point + (0x2a427d70a34b6b5237894f065ef5d60a9872ba444d47d98648b080b8ddb2a68); + tempvar res = res * point + (0xe505592d606917f898c54a7afc45b328be3cd48121aee2e8f05185a3e23e5f); + tempvar res = res * point + (0x45b4e74f19b293bc3d3d172a101e344558fcf4ccfe5eecefe31f45a45614df7); + tempvar res = res * point + (0x68486394265c9dc8fae42c8fd39605d3179c981cb44cbe33740a3deb907bc59); + tempvar res = res * point + (0x2868a08eae382c069047152ee964ac5ebd242b44267e97e578802440ef764f5); + tempvar res = res * point + (0x3159144c85f2c515eb806e5aedd908553057b69c556d226adc6e4511a35423c); + tempvar res = res * point + (0x4387edee6899d4a85883d2f8524978a4634ff82779f150b7b0c861bb315ed3f); + tempvar res = res * point + (0x68c5830832f6270a189b074d7675fcbc1d1c5cc06ce9c478bf8f4d5ac1bf40); + tempvar res = res * point + (0x399c00b8ebb398248bb1f52528d5241e7366b73c2d89f57a11dc82c530cc57c); + tempvar res = res * point + (0x3238aeb8f6bea8bcaaa1bdd5b4f917ccfad8eab031785ccdc648b47d7ea4be8); + tempvar res = res * point + (0x357bf5d87c973292381fa4320114551a837a1d6cb6e2bb0eeba534fb2e01742); + tempvar res = res * point + (0x360274f27df6eeec0b7b65fbb227a8214ac3e55cb37b1970e18489ef5b574e1); + tempvar res = res * point + (0x1cb6e2fba23730f5bf9d8e726569b6e8bf6b5ffe8520339503c5469cc3713a2); + tempvar res = res * point + (0x3924324af1994280f87f289fdae0b9a2d8cb9914ec37d319c18daf029211815); + tempvar res = res * point + (0x3c4ad04a5a057e4411487858dbe16af8e3fc065ef7400749ffdc248bdb25bc5); + tempvar res = res * point + (0x50c92b3e6848a21001be2a268615e1e26cb4918ecb09640efaaf1d8b71568fb); + tempvar res = res * point + (0x47d21828025d0cbab84084965a49dd14c7833aac562b55de808a94777df2ea3); + tempvar res = res * point + (0x6207c6a2fd70c19a10430566c9efaad95eab8cbddf308f0057c81f3155a25a0); + tempvar res = res * point + (0x2d4acebd804035257147ad8d8419a5f5762b4b543c4846ef9acf41856e672ee); + tempvar res = res * point + (0x78f49c214872b5cce18ead0207a165fb741ea818a69cfe9647737323f70f4f5); + tempvar res = res * point + (0x22aa8c5c5ff26f9a0edc768ae32ff4f71a71205b4e83cfa0cc687a1e02566ba); + tempvar res = res * point + (0x5dd2e0680c7eff25211f31d3c30a9f454500d6eb09d46d87a75a42b190203cb); + tempvar res = res * point + (0x5ac4bcdb9c14634ab83c13a30822ddbabc54248cf1177b11cc2aed24d2d32f5); + tempvar res = res * point + (0x77dee5f03389585fad0d1f2a8accfa4cb985344891b8befaee42f3462cb48a); + tempvar res = res * point + (0x737dba18eb055a12d842bfae32fd146dcd2d7bb932a2591aa864458d6d652); + tempvar res = res * point + (0x23bf372b0b59abf250463697ef4b2096eb1c9674613918b4d0c79aa10d9fd59); + tempvar res = res * point + (0x73724274fdd351c378e597da1615dc51058e14994464cb7b318766199ac2a35); + tempvar res = res * point + (0x2e14e83be58cde3ed5f3fec8ba6462493a4a2f0f7d6c846006220eccd49ef25); + tempvar res = res * point + (0x4846d310812d81ffda3731e8289005e2f0e05411e76b1c84332c3ee9e831afb); + tempvar res = res * point + (0x160abeb38bc4f22af5fe618c19c77c39903007900722bdbdeaee059f31544c8); + tempvar res = res * point + (0x264a535ae10091157ed59b04955dff66897af74cae20456bb830336b803ae47); + tempvar res = res * point + (0x316ce6b23e720b8302e2d4bd968c0f140f69930e46a54784a7cee7e0b8a0c8); + tempvar res = res * point + (0x775d95a0beb287c98663a3f9a9c577ffc67c1fe6fbe2db5b08829a2c3eac922); + tempvar res = res * point + (0x2353c4a418bdc1e461be162140cc69c26eb9d99f08924991f85058f87f6df41); + tempvar res = res * point + (0x181ef9cde124459dc0e2aaf93512abd49a10328fb93dfc4d49ab671db64bbc4); + tempvar res = res * point + (0x7ff76956e0cd2b490b47a0a0497df5f874cf47f54c45f08101256429b48460); + tempvar res = res * point + (0x318e5a52d685eaa06e0f39159a344b3d97b52688b671d133954aeff0bc17707); + tempvar res = res * point + (0x7616cfc6834643d4b95ed1cfec036f816a7c3d3b9800f301f98ddf341712ebf); + tempvar res = res * point + (0x59869515fb57ea7733567e5d849bcaa00c00e0f86f4ebbd2c7a6f4c0c77692b); + tempvar res = res * point + (0xb806f4e19770279fab5427b8eaf5bc68bf984d6ccea1e878a7aaf32c9975d9); + tempvar res = res * point + (0x4fb0c93fe30da048576fe5e839483636218dfdda3d05f1d68847a4c0167597f); + tempvar res = res * point + (0x685af2d7bbf30cd0c5c3d41c430a8657eeafeeb4596165faaa73d802087ad80); + tempvar res = res * point + (0x6f617dce150ea148cb8c7488fe4caa920b2000bc8122cce1891e4b76cddc9d4); + tempvar res = res * point + (0x47f02fc512b153462379f4f793c7cab9e659bfdb07d3439d29039f566b7236d); + tempvar res = res * point + (0x4ce0a14a5a9c30a38062eb8870eeb4ff3562db743c0f3eede2e3d3862a2eb7c); + tempvar res = res * point + (0x7b077d27c7007656025224fa4e528b4c4261f43c3da1e42bd1349403af55cbb); + tempvar res = res * point + (0x50f5f6adbf0b9abc6e231b855018f4ec806a4f199cc511bed5c423ebef298e4); + tempvar res = res * point + (0x5fcfeb78685abb1ce610e516ab7e2aa210fd90844c8d1c89cd798f3d71bbcb3); + tempvar res = res * point + (0x4255a568f4597862e1dfe0c391b97059d179d7eb4d868f61364835e5028f9dd); + tempvar res = res * point + (0x206d7f23d0fe1b1c0967486ebb792d7fdf5b1691d2c2f9306e211d3b849526b); + tempvar res = res * point + (0xc61c74cc988663ee09f4c725d5b1f04549bd342d3550ce17427ac75592b637); + tempvar res = res * point + (0x175a904681c7a91856bf7fcf8410d2c19eb8705267914489664a1ea2af5b8fe); + tempvar res = res * point + (0x1bd842a4ec97e1489ceb542bd3161e5a00ce431547bfadfbced954d993b0a11); + tempvar res = res * point + (0x14899e0f97aac917d46ce5e9ddf11194fb846d2c52726af4085f27c570a98a9); + tempvar res = res * point + (0x842955243a56778a332ba9be0b22b2af62efaa50068d3078675fb76c225e76); + tempvar res = res * point + (0x6dff267c3bbce68474294da908df4f5cf2a4160c638f7cb45c098057e968f44); + tempvar res = res * point + (0x72c0dd24a576b47a84cdd1a20227773b5621f85b781c288625e3368e1cf738a); + tempvar res = res * point + (0x728771890334d0c9b0f400543bdc13ea6890497bc87c509a04f8014916c13a5); + tempvar res = res * point + (0x30632b3865a272a1a00270430744ee90b40ff16e1fc44515876ce8e36215ca0); + tempvar res = res * point + (0x76d656560dac569683063278ea2dee47d935501c2195ff53b741efe81509892); + tempvar res = res * point + (0x1dbdc2ea2e555309578eeb2352fbc47c8fd5ed77cc09903b577700f9a4d1be1); + tempvar res = res * point + (0x119bcf6402ad9953851bac8e318d50af699b0cc75e2597aff0a2cc521975aa4); + tempvar res = res * point + (0x7c3234094dff9a45064a5b9abd0667c04dd76c62722984f7f8475e7cc344c06); + tempvar res = res * point + (0x1495d40cf3f13c5fc90653c2b2f02e0b833790c07576286d3127f745ea920ae); + tempvar res = res * point + (0x40f019a18b8097235264cb8efee7d149321a199ccd32ffac43b5a778dfadda1); + tempvar res = res * point + (0x4e23809ce49747990e43b2d976083dc84d67e75cf22e5a76ad5b7a2dca50b3d); + tempvar res = res * point + (0x7f0a3bec1d34f2fd632993a3d9c6432401cec25ad9d6196b909f3672980bd05); + tempvar res = res * point + (0x9460aa25f77fc10cfcc4579e2011e39ce477a32a768aa553201e556ed2bbe1); + tempvar res = res * point + (0x611384709c407d85c93256b6aff04c4ac515450c70cf507994165abfe2347b); + tempvar res = res * point + (0x2065bc7a4aa38d5fe86f9b593ccd060f8d4a5a19a9ca8b182c32199a4bd27be); + tempvar res = res * point + (0x9969a08d753e885857a5696d1cafd39f62bb193acc99089df76c240acd2fc0); + tempvar res = res * point + (0x6df73a948c95439f3230282814ba7e26203cfdc725901e4971ad9cff4db4396); + tempvar res = res * point + (0x1cdf0446663046f35c26d51e45a5233a93c51f4f7f1985dfe130dd67addefa3); + tempvar res = res * point + (0x59cbe680183d1dc3161ee7f945f38ab9461a5293748b2b7be84899e62c9860b); + tempvar res = res * point + (0x5030fda0c29a929e6cd634b9f3d1bf975c363012cfb439cae13495f8ce10225); + tempvar res = res * point + (0x49aadcf98ef59c0e5d2097845949988862b96194abc8c5453f056f232482892); + tempvar res = res * point + (0x319c68159cdf104c2543486ff784860f302187d77effb9a5fefe4e16f0ddc2c); + tempvar res = res * point + (0x575531b404cdba72a63dbbd17aef7d9ae00f73eca7c6dcdaf5e0778c921be41); + tempvar res = res * point + (0x35ca7fa56aa38486833a976804899ba3c97fdaa0a23056cd2dc9bfdbcdd2e31); + tempvar res = res * point + (0x47dc0e209ee8d0b67f63d9e63837ff2ab462c4839bc14a1a3e802327ff0e31f); + tempvar res = res * point + (0x744bdf0c2894072564f6eca2d26efc03ef001bc6e78b34bf6be3a1a91fd90fc); + tempvar res = res * point + (0x73c57ecea0c64a9bc087e50a97a28df974b294c52a0ef5854f53f69ef6773af); + tempvar res = res * point + (0x7dd14b0299ff6064a96fe97e086df3f64a4c7e8b4a58a5bd5fe1b9cf7c61e7c); + tempvar res = res * point + (0x562f636b49796e469dfe9e6748c4468f340e8f69e3f79cfe6925a261198dbb3); + return (res=res); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/bitwise/public_verify.cairo b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/public_verify.cairo new file mode 100644 index 00000000..41b2dfa4 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/public_verify.cairo @@ -0,0 +1,115 @@ +from starkware.cairo.common.math import assert_le, assert_nn, assert_nn_le +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.air.layouts.bitwise.autogenerated import ( + BITWISE__RATIO, + CPU_COMPONENT_HEIGHT, + ECDSA_BUILTIN_RATIO, + LAYOUT_CODE, + PEDERSEN_BUILTIN_RATIO, + RC_BUILTIN_RATIO, +) +from starkware.cairo.stark_verifier.air.public_input import PublicInput, SegmentInfo +from starkware.cairo.stark_verifier.air.public_memory import AddrValue +from starkware.cairo.stark_verifier.core.domains import StarkDomains + +const MAX_LOG_N_STEPS = 50; +const MAX_RANGE_CHECK = 2 ** 16 - 1; + +namespace segments { + const PROGRAM = 0; + const EXECUTION = 1; + const OUTPUT = 2; + const PEDERSEN = 3; + const RANGE_CHECK = 4; + const ECDSA = 5; + const BITWISE = 6; + const N_SEGMENTS = 7; +} + +const INITIAL_PC = 1; +const FINAL_PC = INITIAL_PC + 4; + +// Returns a zero-terminated list of builtins supported by this layout. +func get_layout_builtins() -> (n_builtins: felt, builtins: felt*) { + let (builtins_address) = get_label_location(data); + let n_builtins = 5; + assert builtins_address[n_builtins] = 0; + return (n_builtins=n_builtins, builtins=builtins_address); + + data: + dw 'output'; + dw 'pedersen'; + dw 'range_check'; + dw 'ecdsa'; + dw 'bitwise'; + dw 0; +} + +// Verifies that the public input represents a valid Cairo statement: there exists a memory +// assignment and a valid corresponding program trace satisfying the public memory requirements. +// +// This function verifies that: +// * The 16-bit range-checks are properly configured (0 <= rc_min <= rc_max < 2^16). +// * The layout is valid. +// * The segments for the builtins do not exceed their maximum length (thus, +// when these builtins are properly used in the program, they will function correctly). +// +// This function DOES NOT verify anything regarding the public memory. This should be verified +// by the user. In particular, it is not validated that: +// * [initial_fp - 2] = initial_fp, which is required to guarantee the "safe call" +// feature (that is, all "call" instructions will return, even if the called function is +// malicious). It guarantees that it's not possible to create a cycle in the call stack. +// * the arguments and return values for main() are properly set (e.g., the segment +// pointers). +// * the requested program is loaded, starting from initial_pc. +// * final_pc points to the end of the program. +// * program output is valid in any sense. +// * The continuous pages are consistent. See public_memory.cairo. +func public_input_validate{range_check_ptr}( + air: AirWithLayout*, public_input: PublicInput*, stark_domains: StarkDomains* +) { + assert_nn_le(public_input.log_n_steps, MAX_LOG_N_STEPS); + let (n_steps) = pow(2, public_input.log_n_steps); + assert n_steps * CPU_COMPONENT_HEIGHT = stark_domains.trace_domain_size; + + assert_le(0, public_input.rc_min); + assert_le(public_input.rc_min, public_input.rc_max); + assert_le(public_input.rc_max, MAX_RANGE_CHECK); + + assert public_input.layout = LAYOUT_CODE; + + // Segments. + tempvar n_output_uses = ( + public_input.segments[segments.OUTPUT].stop_ptr - + public_input.segments[segments.OUTPUT].begin_addr); + assert_nn(n_output_uses); + + assert public_input.n_segments = segments.N_SEGMENTS; + tempvar n_pedersen_copies = n_steps / PEDERSEN_BUILTIN_RATIO; + tempvar n_pedersen_uses = ( + public_input.segments[segments.PEDERSEN].stop_ptr - + public_input.segments[segments.PEDERSEN].begin_addr) / 3; + // Note that the following call implies that n_steps is divisible by PEDERSEN_BUILTIN_RATIO. + assert_nn_le(n_pedersen_uses, n_pedersen_copies); + + tempvar n_range_check_copies = n_steps / RC_BUILTIN_RATIO; + tempvar n_range_check_uses = ( + public_input.segments[segments.RANGE_CHECK].stop_ptr - + public_input.segments[segments.RANGE_CHECK].begin_addr); + assert_nn_le(n_range_check_uses, n_range_check_copies); + + tempvar n_ecdsa_copies = n_steps / ECDSA_BUILTIN_RATIO; + tempvar n_ecdsa_uses = ( + public_input.segments[segments.ECDSA].stop_ptr - + public_input.segments[segments.ECDSA].begin_addr) / 2; + assert_nn_le(n_ecdsa_uses, n_ecdsa_copies); + + tempvar n_bitwise_copies = n_steps / BITWISE__RATIO; + tempvar n_bitwise_uses = ( + public_input.segments[segments.BITWISE].stop_ptr - + public_input.segments[segments.BITWISE].begin_addr) / 5; + assert_nn_le(n_bitwise_uses, n_bitwise_copies); + return (); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/bitwise/verify.cairo b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/verify.cairo new file mode 100644 index 00000000..8a40fc20 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/bitwise/verify.cairo @@ -0,0 +1,71 @@ +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.hash import HashBuiltin +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layout import AirWithLayout, Layout +from starkware.cairo.stark_verifier.air.layouts.bitwise.autogenerated import ( + CONSTRAINT_DEGREE, + MASK_SIZE, + N_CONSTRAINTS, + N_INTERACTION_COLUMNS, + N_ORIGINAL_COLUMNS, + eval_oods_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.bitwise.composition import ( + traces_eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.bitwise.global_values import InteractionElements +from starkware.cairo.stark_verifier.air.layouts.bitwise.public_verify import public_input_validate +from starkware.cairo.stark_verifier.air.oods import eval_oods_boundary_poly_at_points +from starkware.cairo.stark_verifier.air.public_input import public_input_hash +from starkware.cairo.stark_verifier.air.traces import ( + traces_commit, + traces_config_validate, + traces_decommit, +) +from starkware.cairo.stark_verifier.core.air_interface import AirInstance +from starkware.cairo.stark_verifier.core.stark import StarkProof, verify_stark_proof + +// Builds an AirInstance object to use for STARK verification. See AirInstance at +// air_interface.cairo. +func build_air() -> (air: AirWithLayout*) { + let (arg_public_input_hash) = get_label_location(public_input_hash); + let (arg_public_input_validate) = get_label_location(public_input_validate); + let (arg_traces_config_validate) = get_label_location(traces_config_validate); + let (arg_traces_commit) = get_label_location(traces_commit); + let (arg_traces_decommit) = get_label_location(traces_decommit); + let (arg_traces_eval_composition_polynomial) = get_label_location( + traces_eval_composition_polynomial + ); + let (arg_eval_oods_boundary_poly_at_points) = get_label_location( + eval_oods_boundary_poly_at_points + ); + let (arg_eval_oods_polynomial) = get_label_location(eval_oods_polynomial); + + tempvar air = new AirWithLayout(air=AirInstance( + public_input_hash=arg_public_input_hash, + public_input_validate=arg_public_input_validate, + traces_config_validate=arg_traces_config_validate, + traces_commit=arg_traces_commit, + traces_decommit=arg_traces_decommit, + traces_eval_composition_polynomial=arg_traces_eval_composition_polynomial, + eval_oods_boundary_poly_at_points=arg_eval_oods_boundary_poly_at_points, + n_constraints=N_CONSTRAINTS, + constraint_degree=CONSTRAINT_DEGREE, + mask_size=MASK_SIZE, + ), + layout=Layout( + eval_oods_polynomial=arg_eval_oods_polynomial, + n_original_columns=N_ORIGINAL_COLUMNS, + n_interaction_columns=N_INTERACTION_COLUMNS, + n_interaction_elements=InteractionElements.SIZE, + ), + ); + return (air=air); +} + +func verify_proof{range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*}( + proof: StarkProof*, security_bits: felt +) -> () { + let (air) = build_air(); + return verify_stark_proof(air=&air.air, proof=proof, security_bits=security_bits); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/dex/autogenerated.cairo b/src/starkware/cairo/stark_verifier/air/layouts/dex/autogenerated.cairo new file mode 100644 index 00000000..f28387f7 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/dex/autogenerated.cairo @@ -0,0 +1,1794 @@ +from starkware.cairo.stark_verifier.air.layouts.dex.global_values import GlobalValues +from starkware.cairo.stark_verifier.air.oods import OodsGlobalValues +from starkware.cairo.common.pow import pow + +const N_CONSTRAINTS = 179; +const MASK_SIZE = 200; +const N_ORIGINAL_COLUMNS = 21; +const N_INTERACTION_COLUMNS = 1; +const PUBLIC_MEMORY_STEP = 8; +const HAS_DILUTED_POOL = 0; +const PEDERSEN_BUILTIN_RATIO = 8; +const PEDERSEN_BUILTIN_REPETITIONS = 4; +const RC_BUILTIN_RATIO = 8; +const RC_N_PARTS = 8; +const ECDSA_BUILTIN_RATIO = 512; +const ECDSA_BUILTIN_REPETITIONS = 1; +const ECDSA_ELEMENT_BITS = 251; +const ECDSA_ELEMENT_HEIGHT = 256; +const HAS_OUTPUT_BUILTIN = 1; +const HAS_PEDERSEN_BUILTIN = 1; +const HAS_RANGE_CHECK_BUILTIN = 1; +const HAS_ECDSA_BUILTIN = 1; +const HAS_BITWISE_BUILTIN = 0; +const HAS_KECCAK_BUILTIN = 0; +const HAS_EC_OP_BUILTIN = 0; +const LAYOUT_CODE = 0x646578; +const CONSTRAINT_DEGREE = 2; +const CPU_COMPONENT_HEIGHT = 16; +const LOG_CPU_COMPONENT_HEIGHT = 4; +const MEMORY_STEP = 2; +const IS_DYNAMIC_AIR = 0; + +func eval_composition_polynomial{range_check_ptr}( + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_generator: felt, + global_values: GlobalValues*, +) -> (res: felt) { + alloc_locals; + + // Compute powers. + let (local pow0) = pow(point, global_values.trace_length / 8192); + local pow1 = pow0 * pow0; + let (local pow2) = pow(point, global_values.trace_length / 512); + local pow3 = pow2 * pow2; + local pow4 = pow3 * pow3; + let (local pow5) = pow(point, global_values.trace_length / 32); + local pow6 = pow5 * pow5; + local pow7 = pow6 * pow6; + local pow8 = pow7 * pow7; + local pow9 = pow8 * pow8; + local pow10 = pow9 * pow9; + let (local pow11) = pow(trace_generator, global_values.trace_length / 2); + let (local pow12) = pow(trace_generator, 15 * global_values.trace_length / 16); + let (local pow13) = pow(trace_generator, 251 * global_values.trace_length / 256); + let (local pow14) = pow(trace_generator, 63 * global_values.trace_length / 64); + let (local pow15) = pow(trace_generator, 255 * global_values.trace_length / 256); + let (local pow16) = pow(trace_generator, 16 * (global_values.trace_length / 16 - 1)); + let (local pow17) = pow(trace_generator, 2 * (global_values.trace_length / 2 - 1)); + let (local pow18) = pow(trace_generator, 4 * (global_values.trace_length / 4 - 1)); + let (local pow19) = pow(trace_generator, 128 * (global_values.trace_length / 128 - 1)); + let (local pow20) = pow(trace_generator, 8192 * (global_values.trace_length / 8192 - 1)); + + // Compute domains. + tempvar domain0 = pow10 - 1; + tempvar domain1 = pow9 - 1; + tempvar domain2 = pow8 - 1; + tempvar domain3 = pow7 - 1; + tempvar domain4 = pow6 - pow12; + tempvar domain5 = pow6 - 1; + tempvar domain6 = pow5 - 1; + tempvar domain7 = pow4 - 1; + tempvar domain8 = pow3 - 1; + tempvar domain9 = pow3 - pow15; + tempvar domain10 = pow3 - pow14; + tempvar domain11 = pow2 - pow11; + tempvar domain12 = pow2 - 1; + tempvar domain13 = pow1 - pow15; + tempvar domain14 = pow1 - pow13; + tempvar domain15 = pow1 - 1; + tempvar domain16 = pow0 - pow15; + tempvar domain17 = pow0 - pow13; + tempvar domain18 = pow0 - 1; + tempvar domain19 = point - pow16; + tempvar domain20 = point - 1; + tempvar domain21 = point - pow17; + tempvar domain22 = point - pow18; + tempvar domain23 = point - pow19; + tempvar domain24 = point - pow20; + + // Fetch mask variables. + tempvar column0_row0 = mask_values[0]; + tempvar column0_row1 = mask_values[1]; + tempvar column0_row2 = mask_values[2]; + tempvar column0_row3 = mask_values[3]; + tempvar column0_row4 = mask_values[4]; + tempvar column0_row5 = mask_values[5]; + tempvar column0_row6 = mask_values[6]; + tempvar column0_row7 = mask_values[7]; + tempvar column0_row8 = mask_values[8]; + tempvar column0_row9 = mask_values[9]; + tempvar column0_row10 = mask_values[10]; + tempvar column0_row11 = mask_values[11]; + tempvar column0_row12 = mask_values[12]; + tempvar column0_row13 = mask_values[13]; + tempvar column0_row14 = mask_values[14]; + tempvar column0_row15 = mask_values[15]; + tempvar column1_row0 = mask_values[16]; + tempvar column1_row1 = mask_values[17]; + tempvar column1_row255 = mask_values[18]; + tempvar column1_row256 = mask_values[19]; + tempvar column1_row511 = mask_values[20]; + tempvar column2_row0 = mask_values[21]; + tempvar column2_row1 = mask_values[22]; + tempvar column2_row255 = mask_values[23]; + tempvar column2_row256 = mask_values[24]; + tempvar column3_row0 = mask_values[25]; + tempvar column3_row1 = mask_values[26]; + tempvar column3_row192 = mask_values[27]; + tempvar column3_row193 = mask_values[28]; + tempvar column3_row196 = mask_values[29]; + tempvar column3_row197 = mask_values[30]; + tempvar column3_row251 = mask_values[31]; + tempvar column3_row252 = mask_values[32]; + tempvar column3_row256 = mask_values[33]; + tempvar column4_row0 = mask_values[34]; + tempvar column4_row1 = mask_values[35]; + tempvar column4_row255 = mask_values[36]; + tempvar column4_row256 = mask_values[37]; + tempvar column4_row511 = mask_values[38]; + tempvar column5_row0 = mask_values[39]; + tempvar column5_row1 = mask_values[40]; + tempvar column5_row255 = mask_values[41]; + tempvar column5_row256 = mask_values[42]; + tempvar column6_row0 = mask_values[43]; + tempvar column6_row1 = mask_values[44]; + tempvar column6_row192 = mask_values[45]; + tempvar column6_row193 = mask_values[46]; + tempvar column6_row196 = mask_values[47]; + tempvar column6_row197 = mask_values[48]; + tempvar column6_row251 = mask_values[49]; + tempvar column6_row252 = mask_values[50]; + tempvar column6_row256 = mask_values[51]; + tempvar column7_row0 = mask_values[52]; + tempvar column7_row1 = mask_values[53]; + tempvar column7_row255 = mask_values[54]; + tempvar column7_row256 = mask_values[55]; + tempvar column7_row511 = mask_values[56]; + tempvar column8_row0 = mask_values[57]; + tempvar column8_row1 = mask_values[58]; + tempvar column8_row255 = mask_values[59]; + tempvar column8_row256 = mask_values[60]; + tempvar column9_row0 = mask_values[61]; + tempvar column9_row1 = mask_values[62]; + tempvar column9_row192 = mask_values[63]; + tempvar column9_row193 = mask_values[64]; + tempvar column9_row196 = mask_values[65]; + tempvar column9_row197 = mask_values[66]; + tempvar column9_row251 = mask_values[67]; + tempvar column9_row252 = mask_values[68]; + tempvar column9_row256 = mask_values[69]; + tempvar column10_row0 = mask_values[70]; + tempvar column10_row1 = mask_values[71]; + tempvar column10_row255 = mask_values[72]; + tempvar column10_row256 = mask_values[73]; + tempvar column10_row511 = mask_values[74]; + tempvar column11_row0 = mask_values[75]; + tempvar column11_row1 = mask_values[76]; + tempvar column11_row255 = mask_values[77]; + tempvar column11_row256 = mask_values[78]; + tempvar column12_row0 = mask_values[79]; + tempvar column12_row1 = mask_values[80]; + tempvar column12_row192 = mask_values[81]; + tempvar column12_row193 = mask_values[82]; + tempvar column12_row196 = mask_values[83]; + tempvar column12_row197 = mask_values[84]; + tempvar column12_row251 = mask_values[85]; + tempvar column12_row252 = mask_values[86]; + tempvar column12_row256 = mask_values[87]; + tempvar column13_row0 = mask_values[88]; + tempvar column13_row255 = mask_values[89]; + tempvar column14_row0 = mask_values[90]; + tempvar column14_row255 = mask_values[91]; + tempvar column15_row0 = mask_values[92]; + tempvar column15_row255 = mask_values[93]; + tempvar column16_row0 = mask_values[94]; + tempvar column16_row255 = mask_values[95]; + tempvar column17_row0 = mask_values[96]; + tempvar column17_row1 = mask_values[97]; + tempvar column17_row2 = mask_values[98]; + tempvar column17_row3 = mask_values[99]; + tempvar column17_row4 = mask_values[100]; + tempvar column17_row5 = mask_values[101]; + tempvar column17_row6 = mask_values[102]; + tempvar column17_row7 = mask_values[103]; + tempvar column17_row8 = mask_values[104]; + tempvar column17_row9 = mask_values[105]; + tempvar column17_row12 = mask_values[106]; + tempvar column17_row13 = mask_values[107]; + tempvar column17_row16 = mask_values[108]; + tempvar column17_row22 = mask_values[109]; + tempvar column17_row23 = mask_values[110]; + tempvar column17_row38 = mask_values[111]; + tempvar column17_row39 = mask_values[112]; + tempvar column17_row70 = mask_values[113]; + tempvar column17_row71 = mask_values[114]; + tempvar column17_row102 = mask_values[115]; + tempvar column17_row103 = mask_values[116]; + tempvar column17_row134 = mask_values[117]; + tempvar column17_row135 = mask_values[118]; + tempvar column17_row167 = mask_values[119]; + tempvar column17_row199 = mask_values[120]; + tempvar column17_row230 = mask_values[121]; + tempvar column17_row263 = mask_values[122]; + tempvar column17_row295 = mask_values[123]; + tempvar column17_row327 = mask_values[124]; + tempvar column17_row391 = mask_values[125]; + tempvar column17_row423 = mask_values[126]; + tempvar column17_row455 = mask_values[127]; + tempvar column17_row4118 = mask_values[128]; + tempvar column17_row4119 = mask_values[129]; + tempvar column17_row8214 = mask_values[130]; + tempvar column18_row0 = mask_values[131]; + tempvar column18_row1 = mask_values[132]; + tempvar column18_row2 = mask_values[133]; + tempvar column18_row3 = mask_values[134]; + tempvar column19_row0 = mask_values[135]; + tempvar column19_row1 = mask_values[136]; + tempvar column19_row2 = mask_values[137]; + tempvar column19_row3 = mask_values[138]; + tempvar column19_row4 = mask_values[139]; + tempvar column19_row5 = mask_values[140]; + tempvar column19_row6 = mask_values[141]; + tempvar column19_row7 = mask_values[142]; + tempvar column19_row8 = mask_values[143]; + tempvar column19_row9 = mask_values[144]; + tempvar column19_row11 = mask_values[145]; + tempvar column19_row12 = mask_values[146]; + tempvar column19_row13 = mask_values[147]; + tempvar column19_row15 = mask_values[148]; + tempvar column19_row17 = mask_values[149]; + tempvar column19_row23 = mask_values[150]; + tempvar column19_row25 = mask_values[151]; + tempvar column19_row28 = mask_values[152]; + tempvar column19_row31 = mask_values[153]; + tempvar column19_row44 = mask_values[154]; + tempvar column19_row60 = mask_values[155]; + tempvar column19_row76 = mask_values[156]; + tempvar column19_row92 = mask_values[157]; + tempvar column19_row108 = mask_values[158]; + tempvar column19_row124 = mask_values[159]; + tempvar column19_row4103 = mask_values[160]; + tempvar column19_row4111 = mask_values[161]; + tempvar column20_row0 = mask_values[162]; + tempvar column20_row1 = mask_values[163]; + tempvar column20_row2 = mask_values[164]; + tempvar column20_row4 = mask_values[165]; + tempvar column20_row6 = mask_values[166]; + tempvar column20_row8 = mask_values[167]; + tempvar column20_row10 = mask_values[168]; + tempvar column20_row12 = mask_values[169]; + tempvar column20_row14 = mask_values[170]; + tempvar column20_row16 = mask_values[171]; + tempvar column20_row17 = mask_values[172]; + tempvar column20_row20 = mask_values[173]; + tempvar column20_row22 = mask_values[174]; + tempvar column20_row24 = mask_values[175]; + tempvar column20_row30 = mask_values[176]; + tempvar column20_row38 = mask_values[177]; + tempvar column20_row46 = mask_values[178]; + tempvar column20_row54 = mask_values[179]; + tempvar column20_row81 = mask_values[180]; + tempvar column20_row145 = mask_values[181]; + tempvar column20_row209 = mask_values[182]; + tempvar column20_row4080 = mask_values[183]; + tempvar column20_row4082 = mask_values[184]; + tempvar column20_row4088 = mask_values[185]; + tempvar column20_row4090 = mask_values[186]; + tempvar column20_row4092 = mask_values[187]; + tempvar column20_row8161 = mask_values[188]; + tempvar column20_row8166 = mask_values[189]; + tempvar column20_row8176 = mask_values[190]; + tempvar column20_row8178 = mask_values[191]; + tempvar column20_row8182 = mask_values[192]; + tempvar column20_row8184 = mask_values[193]; + tempvar column20_row8186 = mask_values[194]; + tempvar column20_row8190 = mask_values[195]; + tempvar column21_inter1_row0 = mask_values[196]; + tempvar column21_inter1_row1 = mask_values[197]; + tempvar column21_inter1_row2 = mask_values[198]; + tempvar column21_inter1_row5 = mask_values[199]; + + // Compute intermediate values. + tempvar cpu__decode__opcode_rc__bit_0 = column0_row0 - (column0_row1 + column0_row1); + tempvar cpu__decode__opcode_rc__bit_2 = column0_row2 - (column0_row3 + column0_row3); + tempvar cpu__decode__opcode_rc__bit_4 = column0_row4 - (column0_row5 + column0_row5); + tempvar cpu__decode__opcode_rc__bit_3 = column0_row3 - (column0_row4 + column0_row4); + tempvar cpu__decode__flag_op1_base_op0_0 = 1 - (cpu__decode__opcode_rc__bit_2 + cpu__decode__opcode_rc__bit_4 + cpu__decode__opcode_rc__bit_3); + tempvar cpu__decode__opcode_rc__bit_5 = column0_row5 - (column0_row6 + column0_row6); + tempvar cpu__decode__opcode_rc__bit_6 = column0_row6 - (column0_row7 + column0_row7); + tempvar cpu__decode__opcode_rc__bit_9 = column0_row9 - (column0_row10 + column0_row10); + tempvar cpu__decode__flag_res_op1_0 = 1 - (cpu__decode__opcode_rc__bit_5 + cpu__decode__opcode_rc__bit_6 + cpu__decode__opcode_rc__bit_9); + tempvar cpu__decode__opcode_rc__bit_7 = column0_row7 - (column0_row8 + column0_row8); + tempvar cpu__decode__opcode_rc__bit_8 = column0_row8 - (column0_row9 + column0_row9); + tempvar cpu__decode__flag_pc_update_regular_0 = 1 - (cpu__decode__opcode_rc__bit_7 + cpu__decode__opcode_rc__bit_8 + cpu__decode__opcode_rc__bit_9); + tempvar cpu__decode__opcode_rc__bit_12 = column0_row12 - (column0_row13 + column0_row13); + tempvar cpu__decode__opcode_rc__bit_13 = column0_row13 - (column0_row14 + column0_row14); + tempvar cpu__decode__fp_update_regular_0 = 1 - (cpu__decode__opcode_rc__bit_12 + cpu__decode__opcode_rc__bit_13); + tempvar cpu__decode__opcode_rc__bit_1 = column0_row1 - (column0_row2 + column0_row2); + tempvar npc_reg_0 = column17_row0 + cpu__decode__opcode_rc__bit_2 + 1; + tempvar cpu__decode__opcode_rc__bit_10 = column0_row10 - (column0_row11 + column0_row11); + tempvar cpu__decode__opcode_rc__bit_11 = column0_row11 - (column0_row12 + column0_row12); + tempvar cpu__decode__opcode_rc__bit_14 = column0_row14 - (column0_row15 + column0_row15); + tempvar memory__address_diff_0 = column18_row2 - column18_row0; + tempvar rc16__diff_0 = column19_row6 - column19_row2; + tempvar pedersen__hash0__ec_subset_sum__bit_0 = column3_row0 - (column3_row1 + column3_row1); + tempvar pedersen__hash0__ec_subset_sum__bit_neg_0 = 1 - pedersen__hash0__ec_subset_sum__bit_0; + tempvar pedersen__hash1__ec_subset_sum__bit_0 = column6_row0 - (column6_row1 + column6_row1); + tempvar pedersen__hash1__ec_subset_sum__bit_neg_0 = 1 - pedersen__hash1__ec_subset_sum__bit_0; + tempvar pedersen__hash2__ec_subset_sum__bit_0 = column9_row0 - (column9_row1 + column9_row1); + tempvar pedersen__hash2__ec_subset_sum__bit_neg_0 = 1 - pedersen__hash2__ec_subset_sum__bit_0; + tempvar pedersen__hash3__ec_subset_sum__bit_0 = column12_row0 - (column12_row1 + column12_row1); + tempvar pedersen__hash3__ec_subset_sum__bit_neg_0 = 1 - pedersen__hash3__ec_subset_sum__bit_0; + tempvar rc_builtin__value0_0 = column19_row12; + tempvar rc_builtin__value1_0 = rc_builtin__value0_0 * global_values.offset_size + column19_row28; + tempvar rc_builtin__value2_0 = rc_builtin__value1_0 * global_values.offset_size + column19_row44; + tempvar rc_builtin__value3_0 = rc_builtin__value2_0 * global_values.offset_size + column19_row60; + tempvar rc_builtin__value4_0 = rc_builtin__value3_0 * global_values.offset_size + column19_row76; + tempvar rc_builtin__value5_0 = rc_builtin__value4_0 * global_values.offset_size + column19_row92; + tempvar rc_builtin__value6_0 = rc_builtin__value5_0 * global_values.offset_size + column19_row108; + tempvar rc_builtin__value7_0 = rc_builtin__value6_0 * global_values.offset_size + column19_row124; + tempvar ecdsa__signature0__doubling_key__x_squared = column19_row7 * column19_row7; + tempvar ecdsa__signature0__exponentiate_generator__bit_0 = column20_row14 - (column20_row46 + column20_row46); + tempvar ecdsa__signature0__exponentiate_generator__bit_neg_0 = 1 - ecdsa__signature0__exponentiate_generator__bit_0; + tempvar ecdsa__signature0__exponentiate_key__bit_0 = column20_row4 - (column20_row20 + column20_row20); + tempvar ecdsa__signature0__exponentiate_key__bit_neg_0 = 1 - ecdsa__signature0__exponentiate_key__bit_0; + + // Sum constraints. + tempvar total_sum = 0; + + // Constraint: cpu/decode/opcode_rc/bit. + tempvar value = (cpu__decode__opcode_rc__bit_0 * cpu__decode__opcode_rc__bit_0 - cpu__decode__opcode_rc__bit_0) * domain4 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[0] * value; + + // Constraint: cpu/decode/opcode_rc/zero. + tempvar value = (column0_row0) / domain4; + tempvar total_sum = total_sum + constraint_coefficients[1] * value; + + // Constraint: cpu/decode/opcode_rc_input. + tempvar value = (column17_row1 - (((column0_row0 * global_values.offset_size + column19_row4) * global_values.offset_size + column19_row8) * global_values.offset_size + column19_row0)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[2] * value; + + // Constraint: cpu/decode/flag_op1_base_op0_bit. + tempvar value = (cpu__decode__flag_op1_base_op0_0 * cpu__decode__flag_op1_base_op0_0 - cpu__decode__flag_op1_base_op0_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[3] * value; + + // Constraint: cpu/decode/flag_res_op1_bit. + tempvar value = (cpu__decode__flag_res_op1_0 * cpu__decode__flag_res_op1_0 - cpu__decode__flag_res_op1_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[4] * value; + + // Constraint: cpu/decode/flag_pc_update_regular_bit. + tempvar value = (cpu__decode__flag_pc_update_regular_0 * cpu__decode__flag_pc_update_regular_0 - cpu__decode__flag_pc_update_regular_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[5] * value; + + // Constraint: cpu/decode/fp_update_regular_bit. + tempvar value = (cpu__decode__fp_update_regular_0 * cpu__decode__fp_update_regular_0 - cpu__decode__fp_update_regular_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[6] * value; + + // Constraint: cpu/operands/mem_dst_addr. + tempvar value = (column17_row8 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_0 * column19_row9 + (1 - cpu__decode__opcode_rc__bit_0) * column19_row1 + column19_row0)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[7] * value; + + // Constraint: cpu/operands/mem0_addr. + tempvar value = (column17_row4 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_1 * column19_row9 + (1 - cpu__decode__opcode_rc__bit_1) * column19_row1 + column19_row8)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[8] * value; + + // Constraint: cpu/operands/mem1_addr. + tempvar value = (column17_row12 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_2 * column17_row0 + cpu__decode__opcode_rc__bit_4 * column19_row1 + cpu__decode__opcode_rc__bit_3 * column19_row9 + cpu__decode__flag_op1_base_op0_0 * column17_row5 + column19_row4)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[9] * value; + + // Constraint: cpu/operands/ops_mul. + tempvar value = (column19_row5 - column17_row5 * column17_row13) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[10] * value; + + // Constraint: cpu/operands/res. + tempvar value = ((1 - cpu__decode__opcode_rc__bit_9) * column19_row13 - (cpu__decode__opcode_rc__bit_5 * (column17_row5 + column17_row13) + cpu__decode__opcode_rc__bit_6 * column19_row5 + cpu__decode__flag_res_op1_0 * column17_row13)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[11] * value; + + // Constraint: cpu/update_registers/update_pc/tmp0. + tempvar value = (column19_row3 - cpu__decode__opcode_rc__bit_9 * column17_row9) * domain19 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[12] * value; + + // Constraint: cpu/update_registers/update_pc/tmp1. + tempvar value = (column19_row11 - column19_row3 * column19_row13) * domain19 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[13] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_negative. + tempvar value = ((1 - cpu__decode__opcode_rc__bit_9) * column17_row16 + column19_row3 * (column17_row16 - (column17_row0 + column17_row13)) - (cpu__decode__flag_pc_update_regular_0 * npc_reg_0 + cpu__decode__opcode_rc__bit_7 * column19_row13 + cpu__decode__opcode_rc__bit_8 * (column17_row0 + column19_row13))) * domain19 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[14] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_positive. + tempvar value = ((column19_row11 - cpu__decode__opcode_rc__bit_9) * (column17_row16 - npc_reg_0)) * domain19 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[15] * value; + + // Constraint: cpu/update_registers/update_ap/ap_update. + tempvar value = (column19_row17 - (column19_row1 + cpu__decode__opcode_rc__bit_10 * column19_row13 + cpu__decode__opcode_rc__bit_11 + cpu__decode__opcode_rc__bit_12 * 2)) * domain19 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[16] * value; + + // Constraint: cpu/update_registers/update_fp/fp_update. + tempvar value = (column19_row25 - (cpu__decode__fp_update_regular_0 * column19_row9 + cpu__decode__opcode_rc__bit_13 * column17_row9 + cpu__decode__opcode_rc__bit_12 * (column19_row1 + 2))) * domain19 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[17] * value; + + // Constraint: cpu/opcodes/call/push_fp. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column17_row9 - column19_row9)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[18] * value; + + // Constraint: cpu/opcodes/call/push_pc. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column17_row5 - (column17_row0 + cpu__decode__opcode_rc__bit_2 + 1))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[19] * value; + + // Constraint: cpu/opcodes/call/off0. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column19_row0 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[20] * value; + + // Constraint: cpu/opcodes/call/off1. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column19_row8 - (global_values.half_offset_size + 1))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[21] * value; + + // Constraint: cpu/opcodes/call/flags. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (cpu__decode__opcode_rc__bit_12 + cpu__decode__opcode_rc__bit_12 + 1 + 1 - (cpu__decode__opcode_rc__bit_0 + cpu__decode__opcode_rc__bit_1 + 4))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[22] * value; + + // Constraint: cpu/opcodes/ret/off0. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (column19_row0 + 2 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[23] * value; + + // Constraint: cpu/opcodes/ret/off2. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (column19_row4 + 1 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[24] * value; + + // Constraint: cpu/opcodes/ret/flags. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (cpu__decode__opcode_rc__bit_7 + cpu__decode__opcode_rc__bit_0 + cpu__decode__opcode_rc__bit_3 + cpu__decode__flag_res_op1_0 - 4)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[25] * value; + + // Constraint: cpu/opcodes/assert_eq/assert_eq. + tempvar value = (cpu__decode__opcode_rc__bit_14 * (column17_row9 - column19_row13)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[26] * value; + + // Constraint: initial_ap. + tempvar value = (column19_row1 - global_values.initial_ap) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[27] * value; + + // Constraint: initial_fp. + tempvar value = (column19_row9 - global_values.initial_ap) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[28] * value; + + // Constraint: initial_pc. + tempvar value = (column17_row0 - global_values.initial_pc) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[29] * value; + + // Constraint: final_ap. + tempvar value = (column19_row1 - global_values.final_ap) / domain19; + tempvar total_sum = total_sum + constraint_coefficients[30] * value; + + // Constraint: final_fp. + tempvar value = (column19_row9 - global_values.initial_ap) / domain19; + tempvar total_sum = total_sum + constraint_coefficients[31] * value; + + // Constraint: final_pc. + tempvar value = (column17_row0 - global_values.final_pc) / domain19; + tempvar total_sum = total_sum + constraint_coefficients[32] * value; + + // Constraint: memory/multi_column_perm/perm/init0. + tempvar value = ((global_values.memory__multi_column_perm__perm__interaction_elm - (column18_row0 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column18_row1)) * column21_inter1_row0 + column17_row0 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column17_row1 - global_values.memory__multi_column_perm__perm__interaction_elm) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[33] * value; + + // Constraint: memory/multi_column_perm/perm/step0. + tempvar value = ((global_values.memory__multi_column_perm__perm__interaction_elm - (column18_row2 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column18_row3)) * column21_inter1_row2 - (global_values.memory__multi_column_perm__perm__interaction_elm - (column17_row2 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column17_row3)) * column21_inter1_row0) * domain21 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[34] * value; + + // Constraint: memory/multi_column_perm/perm/last. + tempvar value = (column21_inter1_row0 - global_values.memory__multi_column_perm__perm__public_memory_prod) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[35] * value; + + // Constraint: memory/diff_is_bit. + tempvar value = (memory__address_diff_0 * memory__address_diff_0 - memory__address_diff_0) * domain21 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[36] * value; + + // Constraint: memory/is_func. + tempvar value = ((memory__address_diff_0 - 1) * (column18_row1 - column18_row3)) * domain21 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[37] * value; + + // Constraint: memory/initial_addr. + tempvar value = (column18_row0 - 1) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[38] * value; + + // Constraint: public_memory_addr_zero. + tempvar value = (column17_row2) / domain3; + tempvar total_sum = total_sum + constraint_coefficients[39] * value; + + // Constraint: public_memory_value_zero. + tempvar value = (column17_row3) / domain3; + tempvar total_sum = total_sum + constraint_coefficients[40] * value; + + // Constraint: rc16/perm/init0. + tempvar value = ((global_values.rc16__perm__interaction_elm - column19_row2) * column21_inter1_row1 + column19_row0 - global_values.rc16__perm__interaction_elm) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[41] * value; + + // Constraint: rc16/perm/step0. + tempvar value = ((global_values.rc16__perm__interaction_elm - column19_row6) * column21_inter1_row5 - (global_values.rc16__perm__interaction_elm - column19_row4) * column21_inter1_row1) * domain22 / domain2; + tempvar total_sum = total_sum + constraint_coefficients[42] * value; + + // Constraint: rc16/perm/last. + tempvar value = (column21_inter1_row1 - global_values.rc16__perm__public_memory_prod) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[43] * value; + + // Constraint: rc16/diff_is_bit. + tempvar value = (rc16__diff_0 * rc16__diff_0 - rc16__diff_0) * domain22 / domain2; + tempvar total_sum = total_sum + constraint_coefficients[44] * value; + + // Constraint: rc16/minimum. + tempvar value = (column19_row2 - global_values.rc_min) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[45] * value; + + // Constraint: rc16/maximum. + tempvar value = (column19_row2 - global_values.rc_max) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[46] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/last_one_is_zero. + tempvar value = (column14_row255 * (column3_row0 - (column3_row1 + column3_row1))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[47] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + tempvar value = (column14_row255 * (column3_row1 - 3138550867693340381917894711603833208051177722232017256448 * column3_row192)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[48] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit192. + tempvar value = (column14_row255 - column13_row255 * (column3_row192 - (column3_row193 + column3_row193))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[49] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + tempvar value = (column13_row255 * (column3_row193 - 8 * column3_row196)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[50] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit196. + tempvar value = (column13_row255 - (column3_row251 - (column3_row252 + column3_row252)) * (column3_row196 - (column3_row197 + column3_row197))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[51] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + tempvar value = ((column3_row251 - (column3_row252 + column3_row252)) * (column3_row197 - 18014398509481984 * column3_row251)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[52] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/booleanity_test. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (pedersen__hash0__ec_subset_sum__bit_0 - 1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[53] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_extraction_end. + tempvar value = (column3_row0) / domain10; + tempvar total_sum = total_sum + constraint_coefficients[54] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/zeros_tail. + tempvar value = (column3_row0) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[55] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/slope. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (column2_row0 - global_values.pedersen__points__y) - column13_row0 * (column1_row0 - global_values.pedersen__points__x)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[56] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/x. + tempvar value = (column13_row0 * column13_row0 - pedersen__hash0__ec_subset_sum__bit_0 * (column1_row0 + global_values.pedersen__points__x + column1_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[57] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/y. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (column2_row0 + column2_row1) - column13_row0 * (column1_row0 - column1_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[58] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/x. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_neg_0 * (column1_row1 - column1_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[59] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/y. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_neg_0 * (column2_row1 - column2_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[60] * value; + + // Constraint: pedersen/hash0/copy_point/x. + tempvar value = (column1_row256 - column1_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[61] * value; + + // Constraint: pedersen/hash0/copy_point/y. + tempvar value = (column2_row256 - column2_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[62] * value; + + // Constraint: pedersen/hash0/init/x. + tempvar value = (column1_row0 - global_values.pedersen__shift_point.x) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[63] * value; + + // Constraint: pedersen/hash0/init/y. + tempvar value = (column2_row0 - global_values.pedersen__shift_point.y) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[64] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/bit_unpacking/last_one_is_zero. + tempvar value = (column16_row255 * (column6_row0 - (column6_row1 + column6_row1))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[65] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + tempvar value = (column16_row255 * (column6_row1 - 3138550867693340381917894711603833208051177722232017256448 * column6_row192)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[66] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/bit_unpacking/cumulative_bit192. + tempvar value = (column16_row255 - column15_row255 * (column6_row192 - (column6_row193 + column6_row193))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[67] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + tempvar value = (column15_row255 * (column6_row193 - 8 * column6_row196)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[68] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/bit_unpacking/cumulative_bit196. + tempvar value = (column15_row255 - (column6_row251 - (column6_row252 + column6_row252)) * (column6_row196 - (column6_row197 + column6_row197))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[69] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + tempvar value = ((column6_row251 - (column6_row252 + column6_row252)) * (column6_row197 - 18014398509481984 * column6_row251)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[70] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/booleanity_test. + tempvar value = (pedersen__hash1__ec_subset_sum__bit_0 * (pedersen__hash1__ec_subset_sum__bit_0 - 1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[71] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/bit_extraction_end. + tempvar value = (column6_row0) / domain10; + tempvar total_sum = total_sum + constraint_coefficients[72] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/zeros_tail. + tempvar value = (column6_row0) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[73] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/add_points/slope. + tempvar value = (pedersen__hash1__ec_subset_sum__bit_0 * (column5_row0 - global_values.pedersen__points__y) - column14_row0 * (column4_row0 - global_values.pedersen__points__x)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[74] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/add_points/x. + tempvar value = (column14_row0 * column14_row0 - pedersen__hash1__ec_subset_sum__bit_0 * (column4_row0 + global_values.pedersen__points__x + column4_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[75] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/add_points/y. + tempvar value = (pedersen__hash1__ec_subset_sum__bit_0 * (column5_row0 + column5_row1) - column14_row0 * (column4_row0 - column4_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[76] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/copy_point/x. + tempvar value = (pedersen__hash1__ec_subset_sum__bit_neg_0 * (column4_row1 - column4_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[77] * value; + + // Constraint: pedersen/hash1/ec_subset_sum/copy_point/y. + tempvar value = (pedersen__hash1__ec_subset_sum__bit_neg_0 * (column5_row1 - column5_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[78] * value; + + // Constraint: pedersen/hash1/copy_point/x. + tempvar value = (column4_row256 - column4_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[79] * value; + + // Constraint: pedersen/hash1/copy_point/y. + tempvar value = (column5_row256 - column5_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[80] * value; + + // Constraint: pedersen/hash1/init/x. + tempvar value = (column4_row0 - global_values.pedersen__shift_point.x) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[81] * value; + + // Constraint: pedersen/hash1/init/y. + tempvar value = (column5_row0 - global_values.pedersen__shift_point.y) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[82] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/bit_unpacking/last_one_is_zero. + tempvar value = (column20_row145 * (column9_row0 - (column9_row1 + column9_row1))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[83] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + tempvar value = (column20_row145 * (column9_row1 - 3138550867693340381917894711603833208051177722232017256448 * column9_row192)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[84] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/bit_unpacking/cumulative_bit192. + tempvar value = (column20_row145 - column20_row17 * (column9_row192 - (column9_row193 + column9_row193))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[85] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + tempvar value = (column20_row17 * (column9_row193 - 8 * column9_row196)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[86] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/bit_unpacking/cumulative_bit196. + tempvar value = (column20_row17 - (column9_row251 - (column9_row252 + column9_row252)) * (column9_row196 - (column9_row197 + column9_row197))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[87] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + tempvar value = ((column9_row251 - (column9_row252 + column9_row252)) * (column9_row197 - 18014398509481984 * column9_row251)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[88] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/booleanity_test. + tempvar value = (pedersen__hash2__ec_subset_sum__bit_0 * (pedersen__hash2__ec_subset_sum__bit_0 - 1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[89] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/bit_extraction_end. + tempvar value = (column9_row0) / domain10; + tempvar total_sum = total_sum + constraint_coefficients[90] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/zeros_tail. + tempvar value = (column9_row0) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[91] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/add_points/slope. + tempvar value = (pedersen__hash2__ec_subset_sum__bit_0 * (column8_row0 - global_values.pedersen__points__y) - column15_row0 * (column7_row0 - global_values.pedersen__points__x)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[92] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/add_points/x. + tempvar value = (column15_row0 * column15_row0 - pedersen__hash2__ec_subset_sum__bit_0 * (column7_row0 + global_values.pedersen__points__x + column7_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[93] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/add_points/y. + tempvar value = (pedersen__hash2__ec_subset_sum__bit_0 * (column8_row0 + column8_row1) - column15_row0 * (column7_row0 - column7_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[94] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/copy_point/x. + tempvar value = (pedersen__hash2__ec_subset_sum__bit_neg_0 * (column7_row1 - column7_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[95] * value; + + // Constraint: pedersen/hash2/ec_subset_sum/copy_point/y. + tempvar value = (pedersen__hash2__ec_subset_sum__bit_neg_0 * (column8_row1 - column8_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[96] * value; + + // Constraint: pedersen/hash2/copy_point/x. + tempvar value = (column7_row256 - column7_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[97] * value; + + // Constraint: pedersen/hash2/copy_point/y. + tempvar value = (column8_row256 - column8_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[98] * value; + + // Constraint: pedersen/hash2/init/x. + tempvar value = (column7_row0 - global_values.pedersen__shift_point.x) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[99] * value; + + // Constraint: pedersen/hash2/init/y. + tempvar value = (column8_row0 - global_values.pedersen__shift_point.y) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[100] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/bit_unpacking/last_one_is_zero. + tempvar value = (column20_row209 * (column12_row0 - (column12_row1 + column12_row1))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[101] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + tempvar value = (column20_row209 * (column12_row1 - 3138550867693340381917894711603833208051177722232017256448 * column12_row192)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[102] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/bit_unpacking/cumulative_bit192. + tempvar value = (column20_row209 - column20_row81 * (column12_row192 - (column12_row193 + column12_row193))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[103] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + tempvar value = (column20_row81 * (column12_row193 - 8 * column12_row196)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[104] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/bit_unpacking/cumulative_bit196. + tempvar value = (column20_row81 - (column12_row251 - (column12_row252 + column12_row252)) * (column12_row196 - (column12_row197 + column12_row197))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[105] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + tempvar value = ((column12_row251 - (column12_row252 + column12_row252)) * (column12_row197 - 18014398509481984 * column12_row251)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[106] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/booleanity_test. + tempvar value = (pedersen__hash3__ec_subset_sum__bit_0 * (pedersen__hash3__ec_subset_sum__bit_0 - 1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[107] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/bit_extraction_end. + tempvar value = (column12_row0) / domain10; + tempvar total_sum = total_sum + constraint_coefficients[108] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/zeros_tail. + tempvar value = (column12_row0) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[109] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/add_points/slope. + tempvar value = (pedersen__hash3__ec_subset_sum__bit_0 * (column11_row0 - global_values.pedersen__points__y) - column16_row0 * (column10_row0 - global_values.pedersen__points__x)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[110] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/add_points/x. + tempvar value = (column16_row0 * column16_row0 - pedersen__hash3__ec_subset_sum__bit_0 * (column10_row0 + global_values.pedersen__points__x + column10_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[111] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/add_points/y. + tempvar value = (pedersen__hash3__ec_subset_sum__bit_0 * (column11_row0 + column11_row1) - column16_row0 * (column10_row0 - column10_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[112] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/copy_point/x. + tempvar value = (pedersen__hash3__ec_subset_sum__bit_neg_0 * (column10_row1 - column10_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[113] * value; + + // Constraint: pedersen/hash3/ec_subset_sum/copy_point/y. + tempvar value = (pedersen__hash3__ec_subset_sum__bit_neg_0 * (column11_row1 - column11_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[114] * value; + + // Constraint: pedersen/hash3/copy_point/x. + tempvar value = (column10_row256 - column10_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[115] * value; + + // Constraint: pedersen/hash3/copy_point/y. + tempvar value = (column11_row256 - column11_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[116] * value; + + // Constraint: pedersen/hash3/init/x. + tempvar value = (column10_row0 - global_values.pedersen__shift_point.x) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[117] * value; + + // Constraint: pedersen/hash3/init/y. + tempvar value = (column11_row0 - global_values.pedersen__shift_point.y) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[118] * value; + + // Constraint: pedersen/input0_value0. + tempvar value = (column17_row7 - column3_row0) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[119] * value; + + // Constraint: pedersen/input0_value1. + tempvar value = (column17_row135 - column6_row0) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[120] * value; + + // Constraint: pedersen/input0_value2. + tempvar value = (column17_row263 - column9_row0) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[121] * value; + + // Constraint: pedersen/input0_value3. + tempvar value = (column17_row391 - column12_row0) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[122] * value; + + // Constraint: pedersen/input0_addr. + tempvar value = (column17_row134 - (column17_row38 + 1)) * domain23 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[123] * value; + + // Constraint: pedersen/init_addr. + tempvar value = (column17_row6 - global_values.initial_pedersen_addr) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[124] * value; + + // Constraint: pedersen/input1_value0. + tempvar value = (column17_row71 - column3_row256) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[125] * value; + + // Constraint: pedersen/input1_value1. + tempvar value = (column17_row199 - column6_row256) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[126] * value; + + // Constraint: pedersen/input1_value2. + tempvar value = (column17_row327 - column9_row256) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[127] * value; + + // Constraint: pedersen/input1_value3. + tempvar value = (column17_row455 - column12_row256) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[128] * value; + + // Constraint: pedersen/input1_addr. + tempvar value = (column17_row70 - (column17_row6 + 1)) / domain7; + tempvar total_sum = total_sum + constraint_coefficients[129] * value; + + // Constraint: pedersen/output_value0. + tempvar value = (column17_row39 - column1_row511) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[130] * value; + + // Constraint: pedersen/output_value1. + tempvar value = (column17_row167 - column4_row511) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[131] * value; + + // Constraint: pedersen/output_value2. + tempvar value = (column17_row295 - column7_row511) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[132] * value; + + // Constraint: pedersen/output_value3. + tempvar value = (column17_row423 - column10_row511) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[133] * value; + + // Constraint: pedersen/output_addr. + tempvar value = (column17_row38 - (column17_row70 + 1)) / domain7; + tempvar total_sum = total_sum + constraint_coefficients[134] * value; + + // Constraint: rc_builtin/value. + tempvar value = (rc_builtin__value7_0 - column17_row103) / domain7; + tempvar total_sum = total_sum + constraint_coefficients[135] * value; + + // Constraint: rc_builtin/addr_step. + tempvar value = (column17_row230 - (column17_row102 + 1)) * domain23 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[136] * value; + + // Constraint: rc_builtin/init_addr. + tempvar value = (column17_row102 - global_values.initial_rc_addr) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[137] * value; + + // Constraint: ecdsa/signature0/doubling_key/slope. + tempvar value = (ecdsa__signature0__doubling_key__x_squared + ecdsa__signature0__doubling_key__x_squared + ecdsa__signature0__doubling_key__x_squared + global_values.ecdsa__sig_config.alpha - (column19_row15 + column19_row15) * column20_row12) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[138] * value; + + // Constraint: ecdsa/signature0/doubling_key/x. + tempvar value = (column20_row12 * column20_row12 - (column19_row7 + column19_row7 + column19_row23)) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[139] * value; + + // Constraint: ecdsa/signature0/doubling_key/y. + tempvar value = (column19_row15 + column19_row31 - column20_row12 * (column19_row7 - column19_row23)) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[140] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/booleanity_test. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (ecdsa__signature0__exponentiate_generator__bit_0 - 1)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[141] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/bit_extraction_end. + tempvar value = (column20_row14) / domain17; + tempvar total_sum = total_sum + constraint_coefficients[142] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/zeros_tail. + tempvar value = (column20_row14) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[143] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/slope. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (column20_row22 - global_values.ecdsa__generator_points__y) - column20_row30 * (column20_row6 - global_values.ecdsa__generator_points__x)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[144] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/x. + tempvar value = (column20_row30 * column20_row30 - ecdsa__signature0__exponentiate_generator__bit_0 * (column20_row6 + global_values.ecdsa__generator_points__x + column20_row38)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[145] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/y. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (column20_row22 + column20_row54) - column20_row30 * (column20_row6 - column20_row38)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[146] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/x_diff_inv. + tempvar value = (column20_row1 * (column20_row6 - global_values.ecdsa__generator_points__x) - 1) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[147] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/copy_point/x. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_neg_0 * (column20_row38 - column20_row6)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[148] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/copy_point/y. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_neg_0 * (column20_row54 - column20_row22)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[149] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/booleanity_test. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (ecdsa__signature0__exponentiate_key__bit_0 - 1)) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[150] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/bit_extraction_end. + tempvar value = (column20_row4) / domain14; + tempvar total_sum = total_sum + constraint_coefficients[151] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/zeros_tail. + tempvar value = (column20_row4) / domain13; + tempvar total_sum = total_sum + constraint_coefficients[152] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/slope. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (column20_row8 - column19_row15) - column20_row2 * (column20_row0 - column19_row7)) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[153] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/x. + tempvar value = (column20_row2 * column20_row2 - ecdsa__signature0__exponentiate_key__bit_0 * (column20_row0 + column19_row7 + column20_row16)) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[154] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/y. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (column20_row8 + column20_row24) - column20_row2 * (column20_row0 - column20_row16)) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[155] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/x_diff_inv. + tempvar value = (column20_row10 * (column20_row0 - column19_row7) - 1) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[156] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/copy_point/x. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_neg_0 * (column20_row16 - column20_row0)) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[157] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/copy_point/y. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_neg_0 * (column20_row24 - column20_row8)) * domain13 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[158] * value; + + // Constraint: ecdsa/signature0/init_gen/x. + tempvar value = (column20_row6 - global_values.ecdsa__sig_config.shift_point.x) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[159] * value; + + // Constraint: ecdsa/signature0/init_gen/y. + tempvar value = (column20_row22 + global_values.ecdsa__sig_config.shift_point.y) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[160] * value; + + // Constraint: ecdsa/signature0/init_key/x. + tempvar value = (column20_row0 - global_values.ecdsa__sig_config.shift_point.x) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[161] * value; + + // Constraint: ecdsa/signature0/init_key/y. + tempvar value = (column20_row8 - global_values.ecdsa__sig_config.shift_point.y) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[162] * value; + + // Constraint: ecdsa/signature0/add_results/slope. + tempvar value = (column20_row8182 - (column20_row4088 + column20_row8190 * (column20_row8166 - column20_row4080))) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[163] * value; + + // Constraint: ecdsa/signature0/add_results/x. + tempvar value = (column20_row8190 * column20_row8190 - (column20_row8166 + column20_row4080 + column19_row4103)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[164] * value; + + // Constraint: ecdsa/signature0/add_results/y. + tempvar value = (column20_row8182 + column19_row4111 - column20_row8190 * (column20_row8166 - column19_row4103)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[165] * value; + + // Constraint: ecdsa/signature0/add_results/x_diff_inv. + tempvar value = (column20_row8161 * (column20_row8166 - column20_row4080) - 1) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[166] * value; + + // Constraint: ecdsa/signature0/extract_r/slope. + tempvar value = (column20_row8184 + global_values.ecdsa__sig_config.shift_point.y - column20_row4082 * (column20_row8176 - global_values.ecdsa__sig_config.shift_point.x)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[167] * value; + + // Constraint: ecdsa/signature0/extract_r/x. + tempvar value = (column20_row4082 * column20_row4082 - (column20_row8176 + global_values.ecdsa__sig_config.shift_point.x + column20_row4)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[168] * value; + + // Constraint: ecdsa/signature0/extract_r/x_diff_inv. + tempvar value = (column20_row8178 * (column20_row8176 - global_values.ecdsa__sig_config.shift_point.x) - 1) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[169] * value; + + // Constraint: ecdsa/signature0/z_nonzero. + tempvar value = (column20_row14 * column20_row4090 - 1) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[170] * value; + + // Constraint: ecdsa/signature0/r_and_w_nonzero. + tempvar value = (column20_row4 * column20_row4092 - 1) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[171] * value; + + // Constraint: ecdsa/signature0/q_on_curve/x_squared. + tempvar value = (column20_row8186 - column19_row7 * column19_row7) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[172] * value; + + // Constraint: ecdsa/signature0/q_on_curve/on_curve. + tempvar value = (column19_row15 * column19_row15 - (column19_row7 * column20_row8186 + global_values.ecdsa__sig_config.alpha * column19_row7 + global_values.ecdsa__sig_config.beta)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[173] * value; + + // Constraint: ecdsa/init_addr. + tempvar value = (column17_row22 - global_values.initial_ecdsa_addr) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[174] * value; + + // Constraint: ecdsa/message_addr. + tempvar value = (column17_row4118 - (column17_row22 + 1)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[175] * value; + + // Constraint: ecdsa/pubkey_addr. + tempvar value = (column17_row8214 - (column17_row4118 + 1)) * domain24 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[176] * value; + + // Constraint: ecdsa/message_value0. + tempvar value = (column17_row4119 - column20_row14) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[177] * value; + + // Constraint: ecdsa/pubkey_value0. + tempvar value = (column17_row23 - column19_row7) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[178] * value; + + return (res=total_sum); +} + +func eval_oods_polynomial{range_check_ptr}( + self: felt*, + column_values: felt*, + oods_values: felt*, + constraint_coefficients: felt*, + point: felt, + oods_point: felt, + trace_generator: felt, + global_values: OodsGlobalValues*, +) -> (res: felt) { + alloc_locals; + + // Compute powers. + let (local pow0) = pow(trace_generator, 0); + let (local pow1) = pow(trace_generator, 1); + local pow2 = pow1 * pow1; + local pow3 = pow1 * pow2; + local pow4 = pow1 * pow3; + local pow5 = pow1 * pow4; + local pow6 = pow1 * pow5; + local pow7 = pow1 * pow6; + local pow8 = pow1 * pow7; + local pow9 = pow1 * pow8; + local pow10 = pow1 * pow9; + local pow11 = pow1 * pow10; + local pow12 = pow1 * pow11; + local pow13 = pow1 * pow12; + local pow14 = pow1 * pow13; + local pow15 = pow1 * pow14; + local pow16 = pow1 * pow15; + local pow17 = pow1 * pow16; + local pow18 = pow3 * pow17; + local pow19 = pow2 * pow18; + local pow20 = pow1 * pow19; + local pow21 = pow1 * pow20; + local pow22 = pow1 * pow21; + local pow23 = pow3 * pow22; + local pow24 = pow2 * pow23; + local pow25 = pow1 * pow24; + local pow26 = pow7 * pow25; + local pow27 = pow1 * pow26; + local pow28 = pow5 * pow27; + local pow29 = pow2 * pow28; + local pow30 = pow8 * pow29; + local pow31 = pow6 * pow30; + local pow32 = pow10 * pow31; + local pow33 = pow1 * pow32; + local pow34 = pow5 * pow33; + local pow35 = pow5 * pow34; + local pow36 = pow11 * pow35; + local pow37 = pow10 * pow36; + local pow38 = pow1 * pow37; + local pow39 = pow5 * pow38; + local pow40 = pow16 * pow39; + local pow41 = pow10 * pow40; + local pow42 = pow1 * pow41; + local pow43 = pow10 * pow42; + local pow44 = pow19 * pow43; + local pow45 = pow22 * pow44; + local pow46 = pow1 * pow45; + local pow47 = pow3 * pow46; + local pow48 = pow1 * pow47; + local pow49 = pow2 * pow48; + local pow50 = pow10 * pow49; + local pow51 = pow25 * pow49; + local pow52 = pow30 * pow48; + local pow53 = pow1 * pow52; + local pow54 = pow3 * pow53; + local pow55 = pow1 * pow54; + local pow56 = pow7 * pow55; + local pow57 = pow27 * pow55; + local pow58 = pow33 * pow55; + local pow59 = pow42 * pow55; + local pow60 = pow44 * pow55; + local pow61 = pow45 * pow56; + local pow62 = pow54 * pow55; + let (local pow63) = pow(trace_generator, 4080); + local pow64 = pow2 * pow63; + local pow65 = pow6 * pow64; + local pow66 = pow2 * pow65; + local pow67 = pow2 * pow66; + local pow68 = pow11 * pow67; + local pow69 = pow8 * pow68; + local pow70 = pow7 * pow69; + local pow71 = pow1 * pow70; + let (local pow72) = pow(trace_generator, 8161); + local pow73 = pow5 * pow72; + local pow74 = pow10 * pow73; + local pow75 = pow2 * pow74; + local pow76 = pow4 * pow75; + local pow77 = pow2 * pow76; + local pow78 = pow2 * pow77; + local pow79 = pow4 * pow78; + local pow80 = pow21 * pow79; + + // Fetch columns. + tempvar column0 = column_values[0]; + tempvar column1 = column_values[1]; + tempvar column2 = column_values[2]; + tempvar column3 = column_values[3]; + tempvar column4 = column_values[4]; + tempvar column5 = column_values[5]; + tempvar column6 = column_values[6]; + tempvar column7 = column_values[7]; + tempvar column8 = column_values[8]; + tempvar column9 = column_values[9]; + tempvar column10 = column_values[10]; + tempvar column11 = column_values[11]; + tempvar column12 = column_values[12]; + tempvar column13 = column_values[13]; + tempvar column14 = column_values[14]; + tempvar column15 = column_values[15]; + tempvar column16 = column_values[16]; + tempvar column17 = column_values[17]; + tempvar column18 = column_values[18]; + tempvar column19 = column_values[19]; + tempvar column20 = column_values[20]; + tempvar column21 = column_values[21]; + + // Sum the OODS constraints on the trace polynomials. + tempvar total_sum = 0; + + tempvar value = (column0 - oods_values[0]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[0] * value; + + tempvar value = (column0 - oods_values[1]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[1] * value; + + tempvar value = (column0 - oods_values[2]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[2] * value; + + tempvar value = (column0 - oods_values[3]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[3] * value; + + tempvar value = (column0 - oods_values[4]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[4] * value; + + tempvar value = (column0 - oods_values[5]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[5] * value; + + tempvar value = (column0 - oods_values[6]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[6] * value; + + tempvar value = (column0 - oods_values[7]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[7] * value; + + tempvar value = (column0 - oods_values[8]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[8] * value; + + tempvar value = (column0 - oods_values[9]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[9] * value; + + tempvar value = (column0 - oods_values[10]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[10] * value; + + tempvar value = (column0 - oods_values[11]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[11] * value; + + tempvar value = (column0 - oods_values[12]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[12] * value; + + tempvar value = (column0 - oods_values[13]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[13] * value; + + tempvar value = (column0 - oods_values[14]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[14] * value; + + tempvar value = (column0 - oods_values[15]) / (point - pow15 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[15] * value; + + tempvar value = (column1 - oods_values[16]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[16] * value; + + tempvar value = (column1 - oods_values[17]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[17] * value; + + tempvar value = (column1 - oods_values[18]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[18] * value; + + tempvar value = (column1 - oods_values[19]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[19] * value; + + tempvar value = (column1 - oods_values[20]) / (point - pow62 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[20] * value; + + tempvar value = (column2 - oods_values[21]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[21] * value; + + tempvar value = (column2 - oods_values[22]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[22] * value; + + tempvar value = (column2 - oods_values[23]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[23] * value; + + tempvar value = (column2 - oods_values[24]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[24] * value; + + tempvar value = (column3 - oods_values[25]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[25] * value; + + tempvar value = (column3 - oods_values[26]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[26] * value; + + tempvar value = (column3 - oods_values[27]) / (point - pow45 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[27] * value; + + tempvar value = (column3 - oods_values[28]) / (point - pow46 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[28] * value; + + tempvar value = (column3 - oods_values[29]) / (point - pow47 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[29] * value; + + tempvar value = (column3 - oods_values[30]) / (point - pow48 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[30] * value; + + tempvar value = (column3 - oods_values[31]) / (point - pow52 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[31] * value; + + tempvar value = (column3 - oods_values[32]) / (point - pow53 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[32] * value; + + tempvar value = (column3 - oods_values[33]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[33] * value; + + tempvar value = (column4 - oods_values[34]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[34] * value; + + tempvar value = (column4 - oods_values[35]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[35] * value; + + tempvar value = (column4 - oods_values[36]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[36] * value; + + tempvar value = (column4 - oods_values[37]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[37] * value; + + tempvar value = (column4 - oods_values[38]) / (point - pow62 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[38] * value; + + tempvar value = (column5 - oods_values[39]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[39] * value; + + tempvar value = (column5 - oods_values[40]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[40] * value; + + tempvar value = (column5 - oods_values[41]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[41] * value; + + tempvar value = (column5 - oods_values[42]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[42] * value; + + tempvar value = (column6 - oods_values[43]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[43] * value; + + tempvar value = (column6 - oods_values[44]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[44] * value; + + tempvar value = (column6 - oods_values[45]) / (point - pow45 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[45] * value; + + tempvar value = (column6 - oods_values[46]) / (point - pow46 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[46] * value; + + tempvar value = (column6 - oods_values[47]) / (point - pow47 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[47] * value; + + tempvar value = (column6 - oods_values[48]) / (point - pow48 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[48] * value; + + tempvar value = (column6 - oods_values[49]) / (point - pow52 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[49] * value; + + tempvar value = (column6 - oods_values[50]) / (point - pow53 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[50] * value; + + tempvar value = (column6 - oods_values[51]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[51] * value; + + tempvar value = (column7 - oods_values[52]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[52] * value; + + tempvar value = (column7 - oods_values[53]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[53] * value; + + tempvar value = (column7 - oods_values[54]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[54] * value; + + tempvar value = (column7 - oods_values[55]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[55] * value; + + tempvar value = (column7 - oods_values[56]) / (point - pow62 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[56] * value; + + tempvar value = (column8 - oods_values[57]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[57] * value; + + tempvar value = (column8 - oods_values[58]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[58] * value; + + tempvar value = (column8 - oods_values[59]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[59] * value; + + tempvar value = (column8 - oods_values[60]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[60] * value; + + tempvar value = (column9 - oods_values[61]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[61] * value; + + tempvar value = (column9 - oods_values[62]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[62] * value; + + tempvar value = (column9 - oods_values[63]) / (point - pow45 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[63] * value; + + tempvar value = (column9 - oods_values[64]) / (point - pow46 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[64] * value; + + tempvar value = (column9 - oods_values[65]) / (point - pow47 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[65] * value; + + tempvar value = (column9 - oods_values[66]) / (point - pow48 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[66] * value; + + tempvar value = (column9 - oods_values[67]) / (point - pow52 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[67] * value; + + tempvar value = (column9 - oods_values[68]) / (point - pow53 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[68] * value; + + tempvar value = (column9 - oods_values[69]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[69] * value; + + tempvar value = (column10 - oods_values[70]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[70] * value; + + tempvar value = (column10 - oods_values[71]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[71] * value; + + tempvar value = (column10 - oods_values[72]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[72] * value; + + tempvar value = (column10 - oods_values[73]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[73] * value; + + tempvar value = (column10 - oods_values[74]) / (point - pow62 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[74] * value; + + tempvar value = (column11 - oods_values[75]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[75] * value; + + tempvar value = (column11 - oods_values[76]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[76] * value; + + tempvar value = (column11 - oods_values[77]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[77] * value; + + tempvar value = (column11 - oods_values[78]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[78] * value; + + tempvar value = (column12 - oods_values[79]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[79] * value; + + tempvar value = (column12 - oods_values[80]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[80] * value; + + tempvar value = (column12 - oods_values[81]) / (point - pow45 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[81] * value; + + tempvar value = (column12 - oods_values[82]) / (point - pow46 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[82] * value; + + tempvar value = (column12 - oods_values[83]) / (point - pow47 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[83] * value; + + tempvar value = (column12 - oods_values[84]) / (point - pow48 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[84] * value; + + tempvar value = (column12 - oods_values[85]) / (point - pow52 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[85] * value; + + tempvar value = (column12 - oods_values[86]) / (point - pow53 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[86] * value; + + tempvar value = (column12 - oods_values[87]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[87] * value; + + tempvar value = (column13 - oods_values[88]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[88] * value; + + tempvar value = (column13 - oods_values[89]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[89] * value; + + tempvar value = (column14 - oods_values[90]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[90] * value; + + tempvar value = (column14 - oods_values[91]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[91] * value; + + tempvar value = (column15 - oods_values[92]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[92] * value; + + tempvar value = (column15 - oods_values[93]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[93] * value; + + tempvar value = (column16 - oods_values[94]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[94] * value; + + tempvar value = (column16 - oods_values[95]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[95] * value; + + tempvar value = (column17 - oods_values[96]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[96] * value; + + tempvar value = (column17 - oods_values[97]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[97] * value; + + tempvar value = (column17 - oods_values[98]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[98] * value; + + tempvar value = (column17 - oods_values[99]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[99] * value; + + tempvar value = (column17 - oods_values[100]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[100] * value; + + tempvar value = (column17 - oods_values[101]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[101] * value; + + tempvar value = (column17 - oods_values[102]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[102] * value; + + tempvar value = (column17 - oods_values[103]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[103] * value; + + tempvar value = (column17 - oods_values[104]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[104] * value; + + tempvar value = (column17 - oods_values[105]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[105] * value; + + tempvar value = (column17 - oods_values[106]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[106] * value; + + tempvar value = (column17 - oods_values[107]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[107] * value; + + tempvar value = (column17 - oods_values[108]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[108] * value; + + tempvar value = (column17 - oods_values[109]) / (point - pow19 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[109] * value; + + tempvar value = (column17 - oods_values[110]) / (point - pow20 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[110] * value; + + tempvar value = (column17 - oods_values[111]) / (point - pow26 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[111] * value; + + tempvar value = (column17 - oods_values[112]) / (point - pow27 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[112] * value; + + tempvar value = (column17 - oods_values[113]) / (point - pow32 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[113] * value; + + tempvar value = (column17 - oods_values[114]) / (point - pow33 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[114] * value; + + tempvar value = (column17 - oods_values[115]) / (point - pow37 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[115] * value; + + tempvar value = (column17 - oods_values[116]) / (point - pow38 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[116] * value; + + tempvar value = (column17 - oods_values[117]) / (point - pow41 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[117] * value; + + tempvar value = (column17 - oods_values[118]) / (point - pow42 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[118] * value; + + tempvar value = (column17 - oods_values[119]) / (point - pow44 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[119] * value; + + tempvar value = (column17 - oods_values[120]) / (point - pow49 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[120] * value; + + tempvar value = (column17 - oods_values[121]) / (point - pow51 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[121] * value; + + tempvar value = (column17 - oods_values[122]) / (point - pow56 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[122] * value; + + tempvar value = (column17 - oods_values[123]) / (point - pow57 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[123] * value; + + tempvar value = (column17 - oods_values[124]) / (point - pow58 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[124] * value; + + tempvar value = (column17 - oods_values[125]) / (point - pow59 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[125] * value; + + tempvar value = (column17 - oods_values[126]) / (point - pow60 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[126] * value; + + tempvar value = (column17 - oods_values[127]) / (point - pow61 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[127] * value; + + tempvar value = (column17 - oods_values[128]) / (point - pow70 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[128] * value; + + tempvar value = (column17 - oods_values[129]) / (point - pow71 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[129] * value; + + tempvar value = (column17 - oods_values[130]) / (point - pow80 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[130] * value; + + tempvar value = (column18 - oods_values[131]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[131] * value; + + tempvar value = (column18 - oods_values[132]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[132] * value; + + tempvar value = (column18 - oods_values[133]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[133] * value; + + tempvar value = (column18 - oods_values[134]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[134] * value; + + tempvar value = (column19 - oods_values[135]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[135] * value; + + tempvar value = (column19 - oods_values[136]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[136] * value; + + tempvar value = (column19 - oods_values[137]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[137] * value; + + tempvar value = (column19 - oods_values[138]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[138] * value; + + tempvar value = (column19 - oods_values[139]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[139] * value; + + tempvar value = (column19 - oods_values[140]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[140] * value; + + tempvar value = (column19 - oods_values[141]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[141] * value; + + tempvar value = (column19 - oods_values[142]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[142] * value; + + tempvar value = (column19 - oods_values[143]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[143] * value; + + tempvar value = (column19 - oods_values[144]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[144] * value; + + tempvar value = (column19 - oods_values[145]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[145] * value; + + tempvar value = (column19 - oods_values[146]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[146] * value; + + tempvar value = (column19 - oods_values[147]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[147] * value; + + tempvar value = (column19 - oods_values[148]) / (point - pow15 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[148] * value; + + tempvar value = (column19 - oods_values[149]) / (point - pow17 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[149] * value; + + tempvar value = (column19 - oods_values[150]) / (point - pow20 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[150] * value; + + tempvar value = (column19 - oods_values[151]) / (point - pow22 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[151] * value; + + tempvar value = (column19 - oods_values[152]) / (point - pow23 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[152] * value; + + tempvar value = (column19 - oods_values[153]) / (point - pow25 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[153] * value; + + tempvar value = (column19 - oods_values[154]) / (point - pow28 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[154] * value; + + tempvar value = (column19 - oods_values[155]) / (point - pow31 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[155] * value; + + tempvar value = (column19 - oods_values[156]) / (point - pow34 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[156] * value; + + tempvar value = (column19 - oods_values[157]) / (point - pow36 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[157] * value; + + tempvar value = (column19 - oods_values[158]) / (point - pow39 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[158] * value; + + tempvar value = (column19 - oods_values[159]) / (point - pow40 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[159] * value; + + tempvar value = (column19 - oods_values[160]) / (point - pow68 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[160] * value; + + tempvar value = (column19 - oods_values[161]) / (point - pow69 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[161] * value; + + tempvar value = (column20 - oods_values[162]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[162] * value; + + tempvar value = (column20 - oods_values[163]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[163] * value; + + tempvar value = (column20 - oods_values[164]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[164] * value; + + tempvar value = (column20 - oods_values[165]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[165] * value; + + tempvar value = (column20 - oods_values[166]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[166] * value; + + tempvar value = (column20 - oods_values[167]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[167] * value; + + tempvar value = (column20 - oods_values[168]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[168] * value; + + tempvar value = (column20 - oods_values[169]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[169] * value; + + tempvar value = (column20 - oods_values[170]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[170] * value; + + tempvar value = (column20 - oods_values[171]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[171] * value; + + tempvar value = (column20 - oods_values[172]) / (point - pow17 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[172] * value; + + tempvar value = (column20 - oods_values[173]) / (point - pow18 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[173] * value; + + tempvar value = (column20 - oods_values[174]) / (point - pow19 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[174] * value; + + tempvar value = (column20 - oods_values[175]) / (point - pow21 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[175] * value; + + tempvar value = (column20 - oods_values[176]) / (point - pow24 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[176] * value; + + tempvar value = (column20 - oods_values[177]) / (point - pow26 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[177] * value; + + tempvar value = (column20 - oods_values[178]) / (point - pow29 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[178] * value; + + tempvar value = (column20 - oods_values[179]) / (point - pow30 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[179] * value; + + tempvar value = (column20 - oods_values[180]) / (point - pow35 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[180] * value; + + tempvar value = (column20 - oods_values[181]) / (point - pow43 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[181] * value; + + tempvar value = (column20 - oods_values[182]) / (point - pow50 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[182] * value; + + tempvar value = (column20 - oods_values[183]) / (point - pow63 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[183] * value; + + tempvar value = (column20 - oods_values[184]) / (point - pow64 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[184] * value; + + tempvar value = (column20 - oods_values[185]) / (point - pow65 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[185] * value; + + tempvar value = (column20 - oods_values[186]) / (point - pow66 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[186] * value; + + tempvar value = (column20 - oods_values[187]) / (point - pow67 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[187] * value; + + tempvar value = (column20 - oods_values[188]) / (point - pow72 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[188] * value; + + tempvar value = (column20 - oods_values[189]) / (point - pow73 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[189] * value; + + tempvar value = (column20 - oods_values[190]) / (point - pow74 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[190] * value; + + tempvar value = (column20 - oods_values[191]) / (point - pow75 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[191] * value; + + tempvar value = (column20 - oods_values[192]) / (point - pow76 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[192] * value; + + tempvar value = (column20 - oods_values[193]) / (point - pow77 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[193] * value; + + tempvar value = (column20 - oods_values[194]) / (point - pow78 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[194] * value; + + tempvar value = (column20 - oods_values[195]) / (point - pow79 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[195] * value; + + tempvar value = (column21 - oods_values[196]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[196] * value; + + tempvar value = (column21 - oods_values[197]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[197] * value; + + tempvar value = (column21 - oods_values[198]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[198] * value; + + tempvar value = (column21 - oods_values[199]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[199] * value; + + // Sum the OODS boundary constraints on the composition polynomials. + let (oods_point_to_deg) = pow(oods_point, CONSTRAINT_DEGREE); + + tempvar value = (column_values[22] - oods_values[200]) / (point - oods_point_to_deg); + tempvar total_sum = total_sum + constraint_coefficients[200] * value; + + tempvar value = (column_values[23] - oods_values[201]) / (point - oods_point_to_deg); + tempvar total_sum = total_sum + constraint_coefficients[201] * value; + + static_assert 202 == MASK_SIZE + CONSTRAINT_DEGREE; + return (res=total_sum); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/dex/composition.cairo b/src/starkware/cairo/stark_verifier/air/layouts/dex/composition.cairo new file mode 100644 index 00000000..30dae069 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/dex/composition.cairo @@ -0,0 +1,121 @@ +from starkware.cairo.common.ec import StarkCurve +from starkware.cairo.common.math import assert_nn +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_fp_and_pc +from starkware.cairo.stark_verifier.air.diluted import get_diluted_prod +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.air.layouts.dex.autogenerated import ( + CONSTRAINT_DEGREE, + ECDSA_BUILTIN_RATIO, + ECDSA_BUILTIN_REPETITIONS, + MASK_SIZE, + N_CONSTRAINTS, + PEDERSEN_BUILTIN_RATIO, + PEDERSEN_BUILTIN_REPETITIONS, + PUBLIC_MEMORY_STEP, + eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.dex.global_values import ( + EcdsaSigConfig, + EcPoint, + GlobalValues, + InteractionElements, +) +from starkware.cairo.stark_verifier.air.layouts.dex.periodic_columns import ( + eval_ecdsa_x, + eval_ecdsa_y, + eval_pedersen_x, + eval_pedersen_y, +) +from starkware.cairo.stark_verifier.air.layouts.dex.public_verify import segments +from starkware.cairo.stark_verifier.air.public_input import get_public_memory_product_ratio +from starkware.cairo.stark_verifier.air.traces import TracesCommitment + +// Constants. +const SHIFT_POINT_X = 0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804; +const SHIFT_POINT_Y = 0x3ca0cfe4b3bc6ddf346d49d06ea0ed34e621062c0e056c1d0405d266e10268a; + +// Evaluates the composition polynomial at a point, given the mask_values and the constraint +// coefficients. +func traces_eval_composition_polynomial{range_check_ptr}( + air: AirWithLayout*, + commitment: TracesCommitment*, + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_domain_size: felt, + trace_generator: felt, +) -> (res: felt) { + alloc_locals; + + tempvar interaction_elements: InteractionElements* = cast( + commitment.interaction_elements, InteractionElements*); + tempvar public_input = commitment.public_input; + let (__fp__, _) = get_fp_and_pc(); + + // Public memory. + let memory_z = interaction_elements.memory__multi_column_perm__perm__interaction_elm; + let memory_alpha = interaction_elements.memory__multi_column_perm__hash_interaction_elm0; + tempvar public_memory_column_size = trace_domain_size / PUBLIC_MEMORY_STEP; + assert_nn(public_memory_column_size); + let (public_memory_prod_ratio) = get_public_memory_product_ratio( + public_input=public_input, + z=memory_z, + alpha=memory_alpha, + public_memory_column_size=public_memory_column_size, + ); + + // Periodic columns. + let (n_steps) = pow(2, public_input.log_n_steps); + tempvar n_pedersen_hash_copies = n_steps / ( + PEDERSEN_BUILTIN_RATIO * PEDERSEN_BUILTIN_REPETITIONS); + assert_nn(n_pedersen_hash_copies); + let (pedersen_point) = pow(point, n_pedersen_hash_copies); + let (pedersen__points__x) = eval_pedersen_x(pedersen_point); + let (pedersen__points__y) = eval_pedersen_y(pedersen_point); + + tempvar n_ecdsa_signature_copies = n_steps / ( + ECDSA_BUILTIN_RATIO * ECDSA_BUILTIN_REPETITIONS); + assert_nn(n_ecdsa_signature_copies); + let (ecdsa_point) = pow(point, n_ecdsa_signature_copies); + let (ecdsa__generator_points__x) = eval_ecdsa_x(ecdsa_point); + let (ecdsa__generator_points__y) = eval_ecdsa_y(ecdsa_point); + + // Global values. + local global_values: GlobalValues = GlobalValues( + trace_length=trace_domain_size, + initial_pc=public_input.segments[segments.PROGRAM].begin_addr, + final_pc=public_input.segments[segments.PROGRAM].stop_ptr, + initial_ap=public_input.segments[segments.EXECUTION].begin_addr, + final_ap=public_input.segments[segments.EXECUTION].stop_ptr, + initial_pedersen_addr=public_input.segments[segments.PEDERSEN].begin_addr, + initial_rc_addr=public_input.segments[segments.RANGE_CHECK].begin_addr, + initial_ecdsa_addr=public_input.segments[segments.ECDSA].begin_addr, + rc_min=public_input.rc_min, + rc_max=public_input.rc_max, + offset_size=2 ** 16, + half_offset_size=2 ** 15, + pedersen__shift_point=EcPoint(x=SHIFT_POINT_X, y=SHIFT_POINT_Y), + ecdsa__sig_config=EcdsaSigConfig( + alpha=StarkCurve.ALPHA, + beta=StarkCurve.BETA, + shift_point=EcPoint(x=SHIFT_POINT_X, y=SHIFT_POINT_Y)), + pedersen__points__x=pedersen__points__x, + pedersen__points__y=pedersen__points__y, + ecdsa__generator_points__x=ecdsa__generator_points__x, + ecdsa__generator_points__y=ecdsa__generator_points__y, + memory__multi_column_perm__perm__interaction_elm=memory_z, + memory__multi_column_perm__hash_interaction_elm0=memory_alpha, + rc16__perm__interaction_elm=interaction_elements.rc16__perm__interaction_elm, + memory__multi_column_perm__perm__public_memory_prod=public_memory_prod_ratio, + rc16__perm__public_memory_prod=1, + ); + + return eval_composition_polynomial( + mask_values=mask_values, + constraint_coefficients=constraint_coefficients, + point=point, + trace_generator=trace_generator, + global_values=&global_values, + ); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/dex/global_values.cairo b/src/starkware/cairo/stark_verifier/air/layouts/dex/global_values.cairo new file mode 100644 index 00000000..6a90dd01 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/dex/global_values.cairo @@ -0,0 +1,54 @@ +struct EcPoint { + x: felt, + y: felt, +} + +struct EcdsaSigConfig { + alpha: felt, + beta: felt, + shift_point: EcPoint, +} + +// Accumulation of member expressions for auto generated composition polynomial code. +struct GlobalValues { + // Public input. + trace_length: felt, + initial_pc: felt, + final_pc: felt, + initial_ap: felt, + final_ap: felt, + initial_pedersen_addr: felt, + initial_rc_addr: felt, + initial_ecdsa_addr: felt, + rc_min: felt, + rc_max: felt, + + // Constants. + offset_size: felt, + half_offset_size: felt, + pedersen__shift_point: EcPoint, + ecdsa__sig_config: EcdsaSigConfig, + + // Periodic columns. + pedersen__points__x: felt, + pedersen__points__y: felt, + ecdsa__generator_points__x: felt, + ecdsa__generator_points__y: felt, + + // Interaction elements. + memory__multi_column_perm__perm__interaction_elm: felt, + memory__multi_column_perm__hash_interaction_elm0: felt, + rc16__perm__interaction_elm: felt, + + // Permutation products. + memory__multi_column_perm__perm__public_memory_prod: felt, + rc16__perm__public_memory_prod: felt, +} + +// Elements that are sent from the prover after the commitment on the original trace. +// Used for components after the first interaction, e.g., memory and range check. +struct InteractionElements { + memory__multi_column_perm__perm__interaction_elm: felt, + memory__multi_column_perm__hash_interaction_elm0: felt, + rc16__perm__interaction_elm: felt, +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/dex/periodic_columns.cairo b/src/starkware/cairo/stark_verifier/air/layouts/dex/periodic_columns.cairo new file mode 100644 index 00000000..46218847 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/dex/periodic_columns.cairo @@ -0,0 +1,1571 @@ +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_pedersen_x(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x43869b387c2d0eab20661ebdfaca58b4b23feac014e1e1d9413164312e77da); + tempvar res = res * point + (0x4cec4cd52fab6da76b4ab7a41ffd844aad8981917d2295273ff6ab2cce622d8); + tempvar res = res * point + (0x295046a010dd6757176414b0fd144c1d2517fc463df01a12c0ab58bbbac26ea); + tempvar res = res * point + (0x60105b3cb5aab151ce615173eaecbe94014ff5d72e884addcd4b9d973fed9fd); + tempvar res = res * point + (0x233eff8cfcc744de79d412f724898d13c0e53b1132046ee45db7a101242a73f); + tempvar res = res * point + (0x6f753527f0dec9b713d52f08e4556a3963a2f7e5e282b2e97ffde3e12569b76); + tempvar res = res * point + (0x549a83d43c90aaf1a28c445c81abc883cb61e4353a84ea0fcb15ccee6d6482f); + tempvar res = res * point + (0x4259be645aaf0a661e7877276fa5559ed7d04349f577595702efed3050402c5); + tempvar res = res * point + (0x71e67bd6a0b1b8518cb06837a78b92ab3dec98c4989f946285042655ffe516e); + tempvar res = res * point + (0x19b7924c29a944ecb61165a663d76d84e5ce44b4617fdbca8ff02fbdea6deba); + tempvar res = res * point + (0x70454f9541d96fc1552f984330389ff616cf80eaf699ba2e82b77f43fd163a); + tempvar res = res * point + (0x479c09d33c38f1c8f73247aace507da354ae87ca5cd4aa096bd3a6229e3006d); + tempvar res = res * point + (0x6fcf0e32e3e99f51d8cdac9c19cc25179eb97f2757844fa0c72e7c3bf453e4); + tempvar res = res * point + (0x4ccee6b6ecd4ea8733198e95935d13474d34cf54d7631fde59720e40378e1eb); + tempvar res = res * point + (0x627cb37206e5ee9da20c04a92cc765e3bd3f3d4e42ad4de0d709f366d446d8e); + tempvar res = res * point + (0x4183c04ef7d778f11e57b44c1a7f354c4497f1e3d420d3fa9f9c27c4bb58759); + tempvar res = res * point + (0x1e2c5c3fb2b47ea8cf33099c610f6132a5dd7099d29b02f4a041fe5947ff53b); + tempvar res = res * point + (0x4d44944716e0e13728fa8b84fde421f0f66a120ed2b7cfcf59f5ff6718b8b6c); + tempvar res = res * point + (0x394d0eed011068acc2f55f541c4d113a9c0afe7269cd7d9711aa7e8be661a60); + tempvar res = res * point + (0x52b5bdbcf28603ba60abcbf52bd4f7b4988ce0b4e2346e4875a3f117d4143b4); + tempvar res = res * point + (0x5975b93cee7a147a93cc98aabbb713f151924c4ede3306bb5e14e5e4d5d5c05); + tempvar res = res * point + (0x787053fc3649b17965b9e6ef5e05e024cdc188e90aef1cbf13ba78542a0407d); + tempvar res = res * point + (0x7cbef72611c8e1e08e52ca202382a8545bc7fe124ec080058988e45771e3b40); + tempvar res = res * point + (0x32bd55700baf7283995407f470139326a670d60a5d5428904596584629a053d); + tempvar res = res * point + (0x3485ad12aa365fac51a6296931abdcb54fa848c587cfbfe5bdbad2d6f6d3bd3); + tempvar res = res * point + (0x7f9850620a3435695ec7a6d9378cfe218ab0e5fa674cdc572fb9c197b0dbd25); + tempvar res = res * point + (0x1c7c40b6e4cd3d473e8f84b8fa63610ac6c7e3f4f0017f3ed84eae8f042bf15); + tempvar res = res * point + (0x1e3e1d970342085c482175cf60d93e1cc2cf96dec12f1d839b9b829cc957b7d); + tempvar res = res * point + (0x2d1547488e174e0a8662decd2cf020dd40718f070c84cf36bfa261aa90f814); + tempvar res = res * point + (0x31b8dd40040d22aae383c1e628e427f7aa4a7b0c3a83f815fd7ae2b36864af0); + tempvar res = res * point + (0x5efc7dfab3ad0b3f01e313c50ced95363d8dbaa9f91f801d6f1f00869467a16); + tempvar res = res * point + (0x724a3072c9f315cba63e5d99034b3218ff29a9bbf04155060ebdd6c848a652); + tempvar res = res * point + (0x2a0c1eade4037c10729bdc8a8f38bb5bf359078eedba633047377a09b6cde4d); + tempvar res = res * point + (0x6aacb14e31ebb5066e78eb597842812d7ad137880a6dd0d065c4acee231b7c3); + tempvar res = res * point + (0x468b88ba32ca1eac6c8d3196eea0561e25770818221ed0da3ae749e2a302e); + tempvar res = res * point + (0x5b52f487f8c3d78fb6ea4be227325a7386c7e95cd5f9b72710cfcc870cbba59); + tempvar res = res * point + (0x2bec10dd6a541c12555ff040b5949407713b4227867f53a435e80847b7932f0); + tempvar res = res * point + (0x41e1c8870eea4b7f4308e8173f97482d80afd055f07b1a058f182a775aef593); + tempvar res = res * point + (0x126a03f3c5cbe523484111d915d6d7eab5edad02a327a383171be09597336b4); + tempvar res = res * point + (0xa8db86341624832893780e36fe1f60490da5768f9aeb2a5803240f29ec5a2); + tempvar res = res * point + (0x751a8c7382e8fc0141b4ec5bf37fa457ab8301640b58cfc3b6a0b8d1a12bec2); + tempvar res = res * point + (0x5e56f3654b68256095b54a7868763aa3ff60a98ea3508039def82d2098d8a6d); + tempvar res = res * point + (0x60a9a4ccb72bde44d8a6c5f1d7b9303cc32013ef621bce1b8af413f00e77ef2); + tempvar res = res * point + (0x4efe82f8cacf9761cac9fefb6c13c1afdaed68ee650c37684bfce323070e480); + tempvar res = res * point + (0x40c43992a86359c71f5b8051d84d1fd6971eb36ab486f321a1fc50a52a02a44); + tempvar res = res * point + (0x538392c6ca2c04b5096aa69392b76ff109aabe165df488f3d1a8e5c4022db64); + tempvar res = res * point + (0x2b783063fa1948abfa91d79d225d52ed2ddd11bf20fc388b1ec00fdb5867921); + tempvar res = res * point + (0x1ec66f3f326120e659b78867bdfd7dac4dd3f1a92ffeaf46d39725de341afd4); + tempvar res = res * point + (0x5f4ed6b86202d76686a0b4c1efdfc93c46dce1b843c7181d1db1f8cd4d6dfb); + tempvar res = res * point + (0x34b9f6e8d5debbb4aea334310dc8d8075f896e7eb9f1c09788c7ec62ccb6116); + tempvar res = res * point + (0x4e57c6677d3bd56b425a3b3a92517344d4875e1710667e3dee1954395269af); + tempvar res = res * point + (0x1c5110241881e087e201d211da338d8377dd228afbd84850b76f3e5dfeb9361); + tempvar res = res * point + (0xa64b536ff29309d613af1c27c7229c3f6c583471c6b589b25026db08d3767a); + tempvar res = res * point + (0x3f6f9a9c3f6e175b59fd8e4268a6ae5734034fb1d7c43f97ef474b75ba80cc8); + tempvar res = res * point + (0x775ad15685181f15e34a6b0036c16fc8d1a9860ced1cc5ece39d19a6add939b); + tempvar res = res * point + (0x7775ec7b0ee9812c8df83957c5b46c316fdac82a2d736d4a6eea6124abc5849); + tempvar res = res * point + (0x41f320f863037e381ff83f2c9f1a8ae2802fc22cfea674d9cfd10171da6dea8); + tempvar res = res * point + (0x67649ac75ea692acb3aa4432d48de15aacfa347a37afdf489cc7e954e4ab100); + tempvar res = res * point + (0x7fd8c6108133b8109f4058192bd614b5de2c50afe7ac08a7bb0e0b12ef04e4f); + tempvar res = res * point + (0x57f8ef270683ea78b167dcbe5bb122a79ba760c95f8103dc4c6e7788fb1ac9c); + tempvar res = res * point + (0x6dc0d996fc95036c8cfa408fb12793bf8a4773d698f55085c2ccbc906c6d2d0); + tempvar res = res * point + (0x6713ddde3f2da61b676f5e4c52177bfc8c1576bc97ab3c48f08ff02d26cc03e); + tempvar res = res * point + (0x16b450dd2bb4712f6412b35603aaa02e7345124e5fd13e919c269f3874970f9); + tempvar res = res * point + (0x5f81b087ad750a0ebddd5239bb3682c84d88326b4679a24890f5fec98df45a); + tempvar res = res * point + (0x33f4151b710663772765df7f95b3710c3e8e81bacdbe3729b0a43b6d19e428c); + tempvar res = res * point + (0x5d122cd95f43fb6fc2373ef7e66072140f0f20d552f186faff2622b55a3e063); + tempvar res = res * point + (0x9b478a0767cca2c6f9b4268bffc9e907eb69b32f8ff7b43fc24edd38a88ec2); + tempvar res = res * point + (0x597cee65bc7c6f0faa3e0aa1958897acf7fd4e4e69569f5d18254b0b8c09aab); + tempvar res = res * point + (0x218bc11c668ef7ae5f04a16dc9933c5bc41c194a439d0af802568e598c54630); + tempvar res = res * point + (0x3394eac0b3787b323686cddaef3af972d7fbbd75940bf7f682b8fe3676cd46b); + tempvar res = res * point + (0x4aeb3836ccb2a9ebf9f1c5b6ee3c42f66c8059cc55188335a47a3583d986018); + tempvar res = res * point + (0x5db68a5c4527fff0ebf61fe064888b0fb6e277cfecca6d206986293256f31f); + tempvar res = res * point + (0x63372394d373e7a2f2fa6405509da05fe9cb546ea2742ac0716bccf50ad9227); + tempvar res = res * point + (0x22d4ed1a29943bc16343e01eab25e45adf74b6a7072e4e26aa8d141f2cac5ca); + tempvar res = res * point + (0xf8ea3b2c0b72747301b2778cc071cb9d2e09bbdd7a386b7931582ab412dbd1); + tempvar res = res * point + (0xf78d4b72e0f5f55913884d0714674dd6f534b211ec5dcdba419347828c7c35); + tempvar res = res * point + (0x5142430fc3f872dd6fefb7e9804e3e63714f71a2f43b155cebc53671f964af); + tempvar res = res * point + (0x72fe5010e70102306b21cc388b7f2ab8b0324b84654cf98032b83a81099e72e); + tempvar res = res * point + (0xfd959b09bb704fe63c73e2331f8e76dc1fbf85c2dc9dcaa0e8108664f7f988); + tempvar res = res * point + (0x4180556f79a47df725eca2c2f65389e27281443847a7d9e84640e6d589182f7); + tempvar res = res * point + (0x2dc12726f7f06ef1adfb10747e5d4ef8052e4e57bad9bb10529d7994ef91035); + tempvar res = res * point + (0x3c62720cac42a262b58765d7c0588231c5c2c9ce9d48f0fd547575289ede8c8); + tempvar res = res * point + (0x5744178090cdd56ae12fdd51b74bc097f23f735b7ca16e415a1854597b1caf8); + tempvar res = res * point + (0x597cbefb648f47e763b9b1be8c3f815a0e8b65d0101e11b5bedc380c10e9f4); + tempvar res = res * point + (0x78e66ae8b3ef57289d92561dbe4ef72f4ee551d5cad363720a78d104a89163); + tempvar res = res * point + (0x3cb89319d8172da012c036c40116fd325d65af69f80a1df8f56ec890e920592); + tempvar res = res * point + (0x29d152196b7ea7446182efe778a2db796f5fab17286405953476ac97f94a96a); + tempvar res = res * point + (0x6348748d43d48acafb8ce688f25a1245df86dd20c3a96c5c85cfc0960ca2fa7); + tempvar res = res * point + (0x3609fff81e15da2a88036d1c2d28814035ce829430fabcc3986c08acdc2d44); + tempvar res = res * point + (0x3241fcabfd99b666b151970558fb59fdfca47ded4caf2af4b15839767edb190); + tempvar res = res * point + (0x3f61241934753ca9c4f4210885b87863abdc8637d4dafe5da4bfa5e0206988e); + tempvar res = res * point + (0x6a16c0b648c72c8d718d53099cb11725ee09fe1b49487d8f55f307a6a265920); + tempvar res = res * point + (0x43ef0fbc56a0a46c7099f5e6d6550a77e1ac023e2201f01bde0a3f5fb0f16a5); + tempvar res = res * point + (0x1f6bf768424619cc2d34c01cbf4e137b6cc33a4a5a3db0bc704f790f86ad67c); + tempvar res = res * point + (0x49eac48d453d5de07fe3f4bdb5aac21e7fe69858afedfbeb0daf175459dd9d7); + tempvar res = res * point + (0x2a390a6737563e9edc22b0b0cce94a67adc10db18d6f978c826f24b8848c6df); + tempvar res = res * point + (0x23e127bf290465acfb7500962d426be5241f0e8c6f844d25aa8e262df6e70cb); + tempvar res = res * point + (0x5e51a00b7437caee2acdb81781212bc3d1c397b477ec784d1a7b304c9f8c687); + tempvar res = res * point + (0x6e52308f62433fe92ca9064e06aa17d793d3ad7bedb9590c8bb9edd3272fbae); + tempvar res = res * point + (0x7aa1d2348e13a031dc4fa20d453fcd59eead9adbccc3ea64997d09a0f58216b); + tempvar res = res * point + (0x1c02d3ffc30c7172a132ac604ad28e89466845c139dba509b896c997ee4ce8a); + tempvar res = res * point + (0x3ea018d81f9118cb5cf251d6c795b4ca4aeeb28d6ea5464fb4807d219453728); + tempvar res = res * point + (0x62c2fa993dee607ef195fb6620051b4df127d933de3a417d21de3b0c6dfdc95); + tempvar res = res * point + (0x2fd6fab5c4d0e6bd5bf5b950632e2dfc3be19c9a80e3bf8934e878003b0816a); + tempvar res = res * point + (0x12f2b0b280b64cb9f6bd77cd5103b7668ae42e5d40ae156607c69043b4da5a9); + tempvar res = res * point + (0x51a3ba83e3f68b2df85f3b9e770b5294312fd634fa48ace215a029fdb5593); + tempvar res = res * point + (0x56f19df91009289c7f5304026cf6d2c26541cd4caf867b2d2ea8a954560ed7b); + tempvar res = res * point + (0x362dd19b8207511079a352fad991df9582315ca2539ed4da5cbb5b82e414fc5); + tempvar res = res * point + (0x2dd7ddf328b439b3047a93c6fff6ef901946438cbb55a4c1fa1848f80baf2ce); + tempvar res = res * point + (0x2120274511adcc680703d33146477a31c42684b5163a628eb3f84258ae78786); + tempvar res = res * point + (0x11076126b67298371103d89e76ec2fbe30b28c5de422e61d3fade2e190450a4); + tempvar res = res * point + (0x1868ebbc59cb1c69b32ea2b3a7ce3f87b680731b96a42403878df0a0e4bb3e2); + tempvar res = res * point + (0x5b7abf66fda1917e0e1d44924cb73d713b5fc16b3a64bd4857d089adfd6a814); + tempvar res = res * point + (0x13df9c113e40f246d806089e437629de52f8a247ece912785004efcafd4ea94); + tempvar res = res * point + (0xbdcc31feec5ca8cfbf7227269d1e120132c51307ec03cc2d59c471e2510a24); + tempvar res = res * point + (0x3b2efe16624d8d0a1beeb037b02f0a4f7e11eb3859852cea1f83ab1752a4099); + tempvar res = res * point + (0x596104fc8bded038e39f0de5e80a2f2b65fd39fa4ab7b3453bbe8a40e06a317); + tempvar res = res * point + (0x5fec9e8e9ad35ec1091706f4f39c0e8a610f58be6c987c2327ce0794af7cb7c); + tempvar res = res * point + (0x5fb45888a7861e18a320bff7b0baee50ef9cbe1b06c78a5a16a6fbda3c6b77f); + tempvar res = res * point + (0x2c15afc87ef81cb58ec29c7dd81b4cfe291e5d33a7b36126289a8ebc1af4eb4); + tempvar res = res * point + (0x1f90c3eb7ed36bec79f803ab1884e5455581110ab713139cdb5207561a89a34); + tempvar res = res * point + (0x7c537f749e37ed15d7e5d5d0f88686c5d02242b6c487ae2c5606d2c7de986b6); + tempvar res = res * point + (0x4db0795b76ed3b5cf3cbc23bc47d20abe9b9f76a2731f2774e6dd5ecd6eea05); + tempvar res = res * point + (0x3a7ada56cb16708c6eee7af3688765728c706a16baf61d0582186a3717ef552); + tempvar res = res * point + (0x4c9b9f2c154c6a8cb1fbf50793787d215f2857d042b21c6f5e2740732cca567); + tempvar res = res * point + (0xdf2e87cea7f46ab09a5011d8afca4e7cb962e008fc991ea16d85c472dcf3ef); + tempvar res = res * point + (0x4df83db997cffc8598b838a9c8373bfff5e109d71ee3bf2a18dc0e621e93d2d); + tempvar res = res * point + (0x17eb7ae4a950bce2abe1e7165594eaa60be7b75cefd8007425a735264a1371a); + tempvar res = res * point + (0x6c8258350c092e7b5cf658a6bed95d620afe0563482911a1435a93bcb0d5beb); + tempvar res = res * point + (0x554563c23e6ec8a4497d670e81940a92ddad53c27e7bbc18de74d2b3734d824); + tempvar res = res * point + (0x6c9568c4a9f64874e71c88cc80576e4083f6d0649f66929612a9bb99bd958e1); + tempvar res = res * point + (0x14e46f8471beb6479fadac1286dc86683c659bf1c77dc96bcb303d48c115d7e); + tempvar res = res * point + (0x5eb4774b76a39af609243ea0ca61eaf03255a02d90be9a83901debf64875f0b); + tempvar res = res * point + (0x3317e8a32e8f82246423237d2a4039eba358a76adb8065751b6d7939fadb85c); + tempvar res = res * point + (0x6cfe464b2a4d4e77c09e0beceb4e368bd93aae5efaddbb92e003afc508fcb33); + tempvar res = res * point + (0x3b69a8579df2cea96435a07c81ae1d9f8a5e0e52433335c3e7ad81b76789788); + tempvar res = res * point + (0x3f26981ddcd3549baf47e3f1242b0bb90d6b7f426ba71d2ce628ceb801f3734); + tempvar res = res * point + (0x40d8fb43bbc7e5c35e4b57fef4e8351ffb118c9d92346f97ff7cb48b0170eff); + tempvar res = res * point + (0x19eec9d276c006f19cfa904a4e2ead857e99000d16e897dc8dc955c57615d54); + tempvar res = res * point + (0xcfff274a78e56ec27e29d01f2e900bd226cdb493a83358f9b807235c9aa407); + tempvar res = res * point + (0x13d4454abb9515f00c3daa6034ed3759ea722a953679c4f857511141b87da93); + tempvar res = res * point + (0x2ea5039159478e68762063624b0f396cb7f1bbfe8c1a159f65f0f663f219136); + tempvar res = res * point + (0x40508ab9b5b8d885f85750bb659071d6cc04639f43070b94a802d41723bd0f3); + tempvar res = res * point + (0x40a9f47d93280a641e7f903b1e608cb443ed5d59f24cde6b92c6631cab1e009); + tempvar res = res * point + (0x5a5085cb551c472af264b5de50ebb7b4bb04539c9afac1339f903b943578eea); + tempvar res = res * point + (0xa89bb9df4a46c56f2f40748d826d50285082118f8995f5e7638a05ec117c47); + tempvar res = res * point + (0x5950e4370508dbfa764621025e9341994a3ac21848f3e39d02370b193ba6937); + tempvar res = res * point + (0x6f20da2f1a25f1fab33e7856067226784ad992f8bb53249ee7bb17e86c82070); + tempvar res = res * point + (0x42271e06f205c1bfc9f9d9411bf835f43941c88aa3dc75f044a0143faa4d5cc); + tempvar res = res * point + (0x411f9def562556de87d47af60354512d9a1261152e7f4636038699d468fc2bb); + tempvar res = res * point + (0x66490371a5dfa3fb85bf3f088b89614b5e56cafc263eec39dc4a1bb39e03433); + tempvar res = res * point + (0x6d49bd35b4e4aa46b7098d306632014b4fbfd84892d6997b58d9463a0ea2c05); + tempvar res = res * point + (0xa9c2bf87d58d3f72d985b4b1129f0a1664caac1ee26a15675d1a5086de3a79); + tempvar res = res * point + (0x46df5faa750270394a4253e63ba3e437550ee216ebf8ddbbd7304940c85ad02); + tempvar res = res * point + (0x6e5bf767f3b0646dc16377f3bb7c17db6069555e100dd2215eb20c4d29fb1c3); + tempvar res = res * point + (0x5d9acf8582d4ccc017af36a8a9863e4383b63893d3fb5d81f7fabf4ba3d1023); + tempvar res = res * point + (0x6933ce3f88628188f7a1b1be5b0506dedadd9559c4766be0e7db1ace3adb592); + tempvar res = res * point + (0x40ba0e2f504aa0e9972018d91be21f56bde16361282915563796c750f8936b7); + tempvar res = res * point + (0x6fd73eabd21a86dd8094dd0ebb5924b1aab0753a0d251571ea93f83ab4bd519); + tempvar res = res * point + (0x2761e32194ddef695d1837c8a3f48a3773ae392b5633bfa0c1451e51e33b69b); + tempvar res = res * point + (0x5519091c464bab5646294ae41d087ddcef8bd0508a94a07890fa07220bdaad3); + tempvar res = res * point + (0x3b160cef807b72e95938852093a3a633e72b61e0afad5099201885b54be4098); + tempvar res = res * point + (0x7692b996dcfecd35db6aa22de10144724c478f85a328ab893c6fbadf43d7a9e); + tempvar res = res * point + (0x3512eb8a3bbded6fad1c19190d857629efc56f93fb4aa527e2958dfcce12153); + tempvar res = res * point + (0x591ad3fb7ab83f8d9fcf184ab793baf3db128cda0de1618932851108771cf0d); + tempvar res = res * point + (0x5f7da39edb0781ca1f96af191cf4c70fe0c121b7b2c92f09b49503bb070dc99); + tempvar res = res * point + (0x4a94669a4901cb5527124a2dc7ff6c278d540da41a95e819d0ca10269f7b380); + tempvar res = res * point + (0x20a06257ccfa90a74adf9bb1130a8385b8c91bc61e18acc30843463e5abaa2); + tempvar res = res * point + (0x7e3c052c620ef7fcf180898d28e39348e96e92ed0634dcae3f5fc64be5094a6); + tempvar res = res * point + (0x578dfc700a95a564b41ba8f33b885ad04209bf5169a4046f603a3d84f792d6d); + tempvar res = res * point + (0x796c9b073e2c56f55601eb1f6147d028553275e9fb792f0b76007c9710459c7); + tempvar res = res * point + (0x8c2c75a2fe00432f77ef57e906f264ea76c439e0c4cb19e87867a6ebb34d0a); + tempvar res = res * point + (0x525fee2e2cdb7a293f50f630a840d5cf5f29a158eadd6fa9d0159951712d19a); + tempvar res = res * point + (0x7991462c103abfc3bc31427227b1fb82f7fdf2be1b39316f46e3baef2fcf588); + tempvar res = res * point + (0x46d1e806178137e82ea97c54d8c15dd45c2a9a0082b18aeb9f849158ffc0ee5); + tempvar res = res * point + (0x25a127bbf961fe2b5bd9facbda706223206c40acff003152cbb3b28e9668030); + tempvar res = res * point + (0x1e3d7c65a8f40b6f8aab1635e3b78d0f798746532f08771267a9b6149632a5a); + tempvar res = res * point + (0x25fc8ba8ab421b6dacf2ce03263e037374e4d61c6ce26422fbcb2e755c0d9c4); + tempvar res = res * point + (0x48294f41052135cca94fcf88cf236437b8a55370c3de81fb0d781aa7b0f8eca); + tempvar res = res * point + (0x8c5762a12210a7fdc96a7d3aa966476d3b28650e7c49fc90f95e49a80d4324); + tempvar res = res * point + (0x4ffe8275d3344b4ae2f7d9992d68598e50f365c0b8a721d723841485fc25c0d); + tempvar res = res * point + (0x2959a6947bc4eee0135bbd0a6f2053b62317a1718bcceecbd507417d31e8806); + tempvar res = res * point + (0x77efd8893058f8e00863205582a5e274c344b9af63b9c40ddd92c97c33b52ea); + tempvar res = res * point + (0x73796a0ce0fe851bc22b99faded48a24a21745bb62603e750f78b854d7c32c7); + tempvar res = res * point + (0x2d2e43c0ad60d4265774479258211274ae32b5e151aacf6f8ac1b7708076f09); + tempvar res = res * point + (0x22b5eab11c9e1e6b8d64d5db4b12502fdf0899497f72ee1a27c8797b617f76d); + tempvar res = res * point + (0x703c768145191a10344e5ca400be8fd249e653d564015d46fcd7096cb723a0); + tempvar res = res * point + (0x4159f8056bde7fd4f72615f7bdd0bb6408256b8b216ca52fee253113d9d007c); + tempvar res = res * point + (0x5fde2cdf0d23d5649e3aead1b2b90ca0309715a029654e8984e43de7bde7b06); + tempvar res = res * point + (0x50372d2aff2ebc566505a564d971c6491095e009d9887899aee0b5017fcb877); + tempvar res = res * point + (0x3333c3d925d8c58b9e4e533531e93046039577cf0e57d011c7ce87c6ef1a835); + tempvar res = res * point + (0x575fb11a4d7e3876ae4c86b80b4b9530e0d3e9db218f4d5644f612348f8f002); + tempvar res = res * point + (0x3481879ec47fc8cfabf38ffaa75311c787b7006e7f9def35e96454263bba4aa); + tempvar res = res * point + (0x5c1e733995aad208f0697e4d2a6e28bec9fddc3e30bd033f2f50a83927baef1); + tempvar res = res * point + (0x2edf44b1f59efb0f36c0fce5edbb7576c89cb9f191300fc5e0240def1b88b9d); + tempvar res = res * point + (0x1d46036b736e06016c817d2b51a0918189881a4f1b7c71d556db583df762d37); + tempvar res = res * point + (0x258ef77b90879282ccc2ffcea5052cad266d77b75db36b7996e5fe7638e9b00); + tempvar res = res * point + (0x4219a0a13e09662f3ec712da51b36967947f6d5a09d8044e3005a7f0ab45915); + tempvar res = res * point + (0x18d0f552fd62f81b6076265c7a3a0b81f6bd37152a2f16c71210021ecf68468); + tempvar res = res * point + (0x31abb6310a44d65ac8c308011d4afab938fdacfbaec14c62b808452310b799b); + tempvar res = res * point + (0x1765a9eca4f4551f177b35089f8befc808613bbcd971a47d485b1c220d0bbb4); + tempvar res = res * point + (0x7fd44af0ef24f061aa7dd5bbde15098dfc3721790ee9bac2caa71cca714ebf0); + tempvar res = res * point + (0x566edfbe3c59cbd43838ee245edfebe292c7163f79b1454b03ef3cf8af23c10); + tempvar res = res * point + (0x14d01a0c81aa61c5a238243e78afe80e5d0d7bf528c3d05a343d0f4470d2b0a); + tempvar res = res * point + (0x38445d5f2de7993c48c9da8e77a87dbe289dc0428b1e4ca87e30b2376535543); + tempvar res = res * point + (0x324db878e3842c25a78e94453c98434c54b41955db62234b0ec5ddde6641556); + tempvar res = res * point + (0x184f23c10c726d4a7036c39466db02c4fe7c3d40bade571fe07acaa282f4c07); + tempvar res = res * point + (0x7fb1cbd7a48f2d44a148bd4d17ccd47c438f4f1b45a02945cf4312afa0d6f95); + tempvar res = res * point + (0x20d2002cba899acc7d333031e0977d8df94557ca0749bef6c38b72dbcd462f); + tempvar res = res * point + (0x75bd5b63008c2e005df64ca189ecce11c060f0df6903011a3d95cf9f7b48878); + tempvar res = res * point + (0x548724b5683cd6427513b4c4f84a6d888b9a03843bc0dbdc501b8752d99ada1); + tempvar res = res * point + (0x38441dfe93fd3133faf52208f3263d4ecaca0643bf9c9d4bc952c86cf280f7a); + tempvar res = res * point + (0x182e50e36b753ff5f95f2bc47a6aac8c6f2e5c3975476252a7c29250eefb056); + tempvar res = res * point + (0x2593b010eb6fe0f64833e4f22f6854c063085e0dd393226e6b5fb20ea7f432d); + tempvar res = res * point + (0xcc060a8b007b2dd0efa786afa5edcb512d83ddcba8ed69c27ccef5769deb23); + tempvar res = res * point + (0x672717b74bc3dca9e53494681a5ffa02edbb0290de1c5209843a16964df7a3); + tempvar res = res * point + (0x53774852c8f84d21eec107e1da7a2ab3f4b5ceba6479d1f902ad404e7dde329); + tempvar res = res * point + (0x96de7b9a7eac739df4d13902971804aaf40f5559d18593be0daac0ff86c636); + tempvar res = res * point + (0x725601ed4fcfdaa392b91e8ea982fc57f1874378ab8d6b55301b3d4b6efd802); + tempvar res = res * point + (0x7bc4fea0ea687295d72735a62a19c1a160a1b9a19342717b527f94770aca77); + tempvar res = res * point + (0x3dfab578cfc7a1581212074e0969db9accb619a043dd7194a253af67ef3698); + tempvar res = res * point + (0x44090861421dbb6b4a325a6832e02986be80f7ea475313ae01a3215c3510346); + tempvar res = res * point + (0x7384363b4495aacafd81d0a139a66afd3243309395e3444fb3f1496832240a9); + tempvar res = res * point + (0x4f6ea70b9090971f8de7071f27b0d036b112211403e0547fb7b7903704f295b); + tempvar res = res * point + (0xd55dad93e837d31e8f120398e09b83ca68f160c16043e1c65d033a19adbc30); + tempvar res = res * point + (0x6cc09dc2faf0903dbf5121b97ef058300b18efcc30c25f55de752d395b568a9); + tempvar res = res * point + (0x2b2091e41b10140bea196a1cc28d7f6db6ae1b55d1f115d882c321221a32eb4); + tempvar res = res * point + (0x11b19b3abd2b297728768027b1370566bd845bfb6f49197a76255c1d8c661f); + tempvar res = res * point + (0x3236ab2e0e0b1b013c2100283e36fe75521bd50091f1c73deb165e86616d80a); + tempvar res = res * point + (0x7351448e92ce6914278e73ceeb080e280c146dbcc21cb35af8d2c7e5560aa7d); + tempvar res = res * point + (0x100a89bccb889f183c2a6ced12bab8ef86403230ae6b23def0b784f73ff296f); + tempvar res = res * point + (0x31e49312e1d59acae36bf3562443259500039a7a77d9a57a44cbbb4a80932e3); + tempvar res = res * point + (0x273647256f95d2e5f98bd7830191abd89dc4ab241fc7fa12b27e16a6bd423c3); + tempvar res = res * point + (0x424396bedfddf4192963ef0f87b3989a99f277fe2c60756a4a60fae4d6dfa31); + tempvar res = res * point + (0x6e3a0355459b8b7c35837f3f19f0d8954907326cb08d7d084f2ed0f4b2af8f5); + tempvar res = res * point + (0x2d88caa65f47db103fb1ca354bf50c93f24bca5001598f716b6c9e5c51d1d2); + tempvar res = res * point + (0x2dca037a615e8cf99f8614f437e953c5625b9b57d95f16c174f63346e31c5da); + tempvar res = res * point + (0x5800bf15808a39f1acfbb193af1ab0c22f18d9738753bd3cd2aeea81982409e); + tempvar res = res * point + (0x4ad97a9b0ab95abc1b8fcff31a48e18fb2391ac95baaacc62125bd87fd75e13); + tempvar res = res * point + (0x5ba49d41f62b6d6903fc455bf02bca54becb6ee7f39650fcd0b717ac396159c); + tempvar res = res * point + (0x959c7bf3885d75ab3ca9480101ff64d62c9f138d35f63c137009c1b3eb39f3); + tempvar res = res * point + (0x6da06ce868c140c8ff9ec1eb0323fe2c8b35b46c8d4f5a27727450e87ebd906); + tempvar res = res * point + (0x1bf01c19527dd1d9094c44e3acee4d1ec8c4192026b6f996776294cc9dbc4a8); + tempvar res = res * point + (0x40d1ae7e7bcddc520ed8c0fd736e9b5147d278ed1b720abf76439377023abea); + tempvar res = res * point + (0x2f26fb29017b5ab80328de8488db547e47c44c0d56f30e330354d5b980e50ad); + tempvar res = res * point + (0x72bcdfbdd09f13eeb0c01565dc6a79999a9642dbcb0c570e3e7621ca94df215); + tempvar res = res * point + (0x140ed138dfc5b5417b25a4512bb991f3fd04cf750e082fd4fb82cc15b645835); + tempvar res = res * point + (0x40ffb20c2a3dba0a0d8b6aa51ccaa1b690aa08670ceee556d76053cd671d522); + tempvar res = res * point + (0x283c74c8066141911634401af10106c29dd77458d059ff3b2dd7aa796b2a559); + tempvar res = res * point + (0x593df80dd238cbdc6398146502310a5cb459b0e7d79fa9bee5cc389385c95b3); + tempvar res = res * point + (0x669bfada09faa64c005321d60752662598d69c517e9ffa462dc1b1af42228d1); + tempvar res = res * point + (0x70cc78b821b198e72f8feeb8f31d81e5a4854de3575a62909e0bb51cee921d0); + tempvar res = res * point + (0x68539d0ccd1737a8b2e540f9165638f86f6c4e44943455d311999b0b3684b7d); + tempvar res = res * point + (0xbb867c323532bde3d5b0e08b1b7531a95a2a1706132dcd8ebb7063cd1b1bbb); + tempvar res = res * point + (0x751a2c218f4feffc61e90939c4d2672a263d3b33528c7c6eb40042640f45146); + tempvar res = res * point + (0x6473d78fc37e48379ef8a9d57e3e92cf4fdad3a1bcc170dd177dbc51c4dc62c); + tempvar res = res * point + (0x7218f86344ea46cdcc372a22a14663105eef03bb0de9da9bfcd10818d36ba28); + tempvar res = res * point + (0xaa17b17cdb757833dd4b1670371ef55345debfb2c1b6bdfae64d8759e04349); + tempvar res = res * point + (0x38cb4173a2b057da41d5d30b55f6d11f25effdc69c14843cc43a9ab269630f0); + tempvar res = res * point + (0x4350a29d7b4b242b20b68f6eabd75b758d8631c192b7da5032181b71740b96b); + tempvar res = res * point + (0x42518069a18922e90fa2fa8fe9bf5e2371a40ea88c25d247e6a73a007105dd9); + tempvar res = res * point + (0x7f43f7128a1b46f8ab168a06df9d0cade82a3193eec2d51e2b83f4f0c7fabd9); + tempvar res = res * point + (0x6e694d9385207d7cc8a7cdbf90eb4ed3be49cabc0e6b8d0e69172d73f4a5c11); + tempvar res = res * point + (0x2782ab60e8e9c6cccd40f438a2d2814ef39f50f02bbeb790bc6df78d75af42b); + tempvar res = res * point + (0x259f8eeaf6cbdabd37b9de029661bdcb219245a7599207d3df08c7cc452a13d); + tempvar res = res * point + (0x9345d2e4fc86ae78c4879ecc3adf9e6c482044052bc3738618247b60f069ad); + tempvar res = res * point + (0x4419f27879dacd62144bde4f904890c6d5b312282335a57cf1b04b403bddbea); + tempvar res = res * point + (0x581755fd25823d2f3b07ac5d8dd1bd5b26eab362cec3f9e03573a2b03f62ab9); + tempvar res = res * point + (0x37622de79f6252ff6bb76900db06504434856faf33c59a1b2e39a4fa60ed143); + tempvar res = res * point + (0x2c4ffe18ae93ab53ff6d7d01a7b5bdc5b08dc8d144e0b917f47e60e3cf723f3); + tempvar res = res * point + (0x42ca1f8224d317275c78ca7762a78e6c51978afe1abcbf535da6d299c799c1); + tempvar res = res * point + (0x6403910df189d75aca61c604de3b0802a4ec2ffadb0ff60f1a01f363d66ea67); + tempvar res = res * point + (0x44094080f29bf84d3d5849f264713647289e9af1534ec38d1a7c3d2d2f1ab64); + tempvar res = res * point + (0x3dd2900899d2219ea16fc41413af028057f0c2a674e1cc65032fe4dcb062d4d); + tempvar res = res * point + (0x5a612887264b1ff8e5239b3e04143dc30d0a80cef1c880fe52ee2d5009092b1); + tempvar res = res * point + (0x5ca2e5676dde96127ca85ff6ac82a8fb35b45651b88bcdbfab7ae5298d427c8); + tempvar res = res * point + (0x4b135ec421e9138d09c709a5d92ba70e6944cd44a7eb7f705ab3612de315ac); + tempvar res = res * point + (0x152b3265b01fa9ce0cdf58c17cd14c2cf3e3fafba140db9e27da4fdde7d3c0d); + tempvar res = res * point + (0x55554f904554d2f262d1db49d7c515414870717c829b73d6c439260a8bba3da); + tempvar res = res * point + (0x3e2b9e4151827bb0d04858df547978536215dc06143674d0d2e788dcdc9c36); + tempvar res = res * point + (0x2c30d5e07853079c9f11624e2431795e2bd8b4bebd8cac92f158306b45b0549); + tempvar res = res * point + (0x4e922a3c7df1c668f86b866cf0c07ee4658e7754f6fc0fb62cb297bb6960320); + tempvar res = res * point + (0x35b787fb9889163a9fb5ab831838f19092aa4ef8d8dabb299045740959573d4); + tempvar res = res * point + (0x2d847968e995dcfcecc6ef98ab27f9f1db36b14ce3ba81b80cc92cf19750f88); + tempvar res = res * point + (0x6785d833096c9d9d06034ba4d7f8d71481d4b680b63693d9fa24ea10d3511cf); + tempvar res = res * point + (0x5617f72f8d0da5d7cafeef9269395ee34f921f5cc8d1a4f4c0292a83cb0b9bb); + tempvar res = res * point + (0x6a1373cca7777e3cfacc6502ca9bc645678445d98acf3d6f5ca6c82cab53174); + tempvar res = res * point + (0x5b07a69abcc274ea09eb67f2f6036b492db1f9b7e0a3497d8f3920de22b3b4); + tempvar res = res * point + (0x74399a1effe3a13a8effe952dd57142c254ebe807a56f13521da38984a0b55d); + tempvar res = res * point + (0x6a399f5bede4f507c7251a7ccd110e21173729f5f9a57eb16a27203d3c5e731); + tempvar res = res * point + (0x13102ce3fef387b552a6b8967f788cc8f8502ef0f2ec293d2b872328f78b6c9); + tempvar res = res * point + (0x2233376db0eee71ed0bc6ec0de23782ca9e244a06b8e515b2855b522259eda4); + tempvar res = res * point + (0x6319176edd9fe726efbcc70108b516e26152cb56329b842a1e14adc2a3e47b2); + tempvar res = res * point + (0x12e828f63839dc0dd62bc23385c0bdd5b11e7b6de2cddeccc47f85027c9862f); + tempvar res = res * point + (0x1b5bfb21e549706eaf5c771448f91d1ce03498029ff4159d8cd11f4b6d523a8); + tempvar res = res * point + (0x223b2c9fcd5a1d4b0f7decaab98bdf87e5083865ef9b6562a261fc75009e725); + tempvar res = res * point + (0x6856abcc37696eadf09ac823f589a05b034ef8f86e41d2c6222f039707017fb); + tempvar res = res * point + (0xabbe74553aa10ee20ec6f0f49f73281124ca34d0b71c2e80160f37d3ae0345); + tempvar res = res * point + (0xf7043785f78a94a68b669cb366c00538eafb8e87b5380c68518d4e23922d6f); + tempvar res = res * point + (0x43a4dbc140986d44a7099720e13ec46817f0131dd109a48fbbcf190671f35d6); + tempvar res = res * point + (0x7fb8438581e1ae31877119b91ef1ea28181ba8c0a89eb356313c8a910295d7c); + tempvar res = res * point + (0x125399adcf39aaf7962e3be41c6f9c7691e45c2c31b937e26257d94b5454985); + tempvar res = res * point + (0x3a3c97667e93fa5cc0531c8a2f6d9f84c4f683133b8941fe1382ca8f6f2fe0d); + tempvar res = res * point + (0x253548b05c44cb4d8f2d97641773cf812f709663fe8f492f5a77bfbc8477d79); + tempvar res = res * point + (0x3e828a46091dc07cbbbb0dcbf390e4b5cc44d086b0ba74051fff237f7d6a74a); + tempvar res = res * point + (0x74a80f191573d77481059c14f56764dd2c11571b2736d355efa299c400f0377); + tempvar res = res * point + (0x76169700b631b19086b8b1737e23f1c59cf1428075904c80db724383d3c6b5e); + tempvar res = res * point + (0x7febfa3ce41434e03eccb6be0099dc31d90e36558dfb6f9d21b3e0be41472b4); + tempvar res = res * point + (0xaee16ac845b8bdb7d9c1c85ca7b0e749a7c47229ba24ba097b4b6b8151cc4d); + tempvar res = res * point + (0x31cac8c51732d8aad5bc41c9a6440d482c2c4967e75a571c31b2d9aaaa64068); + tempvar res = res * point + (0x203db741e5e80c19c2bea387e3091420b918fe1142bcf2bc13ae7e098282fda); + tempvar res = res * point + (0x2449d2be3af1fcd8984a9f857309ab5e0e5c010680e33b03a194c6e902a553c); + tempvar res = res * point + (0x40246dcd91afc0098ab9568a5c97d54e09065c551bc9d26ba0ab6a00089bec); + tempvar res = res * point + (0x50cdaac85b8d8bbf55a920bf8d213e333eba5f2bd92e92c61f3946617222ade); + tempvar res = res * point + (0x65dbe95ea2b7d1894854b235f2cc66e910fd2791ff09b92366c7685c652a8c7); + tempvar res = res * point + (0x18f3259c8451dc5007e94efcc6e90c6951543474925fd28ff35e56890bfb66); + tempvar res = res * point + (0x69021f5cefc75ce473977c2ceae2e7c66a84bb3d734eebf4bf497e56eb69959); + tempvar res = res * point + (0x4ded7eedcfca4ee336fa075aef6a017beab322cf7ddf83bccfba05f1c93cad); + tempvar res = res * point + (0xdcc0df28639fd96570d93a6d1df1cb1dcf6db8a259ab092b34cdb411895aa2); + tempvar res = res * point + (0x2333165fa7f9414f082253b8451638fe1e9da3ba8c1246723dbf9995e49d017); + tempvar res = res * point + (0xc8b65a737b5605606028a064d168ccf32d8d87fcb55c6c853fd95ae0961410); + tempvar res = res * point + (0x71d72b0c23e31d703f0210ecb2b28994ad828417531a15a17a1fd401daca2cf); + tempvar res = res * point + (0x211c3e223a3c9c4a024b490a819254ee133ef9740a4026eb3a036bb9e5c6581); + tempvar res = res * point + (0x621692ad7ad27517f4de4e528e1271719cf5b344d463c86b9cd8424a4fc274f); + tempvar res = res * point + (0x5ab65084f4ee8261bfd290e2d5608fde744be92da2eadd5f2fb909ac3d14818); + tempvar res = res * point + (0x5896811c73c991f479c7af6238b51252178dcf4371c297326bcceeb8ee454e2); + tempvar res = res * point + (0x453705ada0d5db6b0afb289b29db6c9acedb01e742cb0d68705d07f8dfcfaae); + tempvar res = res * point + (0x168f97539fdebde7280f4d33f7d5b469cca77495efd4660f31b7d8018f7f89e); + tempvar res = res * point + (0x7829c898e33552459e8fff13c01f1e0d9f5b098f0de7161cbf97da52914bc38); + tempvar res = res * point + (0x5b23dd8ead53bea28246af5a3a63daabf41e7987fe61255d97f2a57bb6d14eb); + tempvar res = res * point + (0x7b631dfaa76643b5f46a069b8c40038f77f088374320add0ac3c9924a12f153); + tempvar res = res * point + (0x2408fff139dae5eb756ea03ef15a2484f582f7ab27ccaa09fa8154f3bf0024b); + tempvar res = res * point + (0x28aa32bfd8c8d7ffcb0b5dadfcfd1b6bbd69b02de9ac1bee786da98ce76c8e1); + tempvar res = res * point + (0x33eb39eae1db6ea48126be6b300b31f6bbe275845822f9eb293e9f7ac38a777); + tempvar res = res * point + (0x3e549a3d3849a09d8f1c50f84f7caa4aa0a5b8ef6f957dafcd13c7c90e4ea11); + tempvar res = res * point + (0x2f5e865731de5068f289b616b39c2294284c111540abfdbb33a39780eb0bceb); + tempvar res = res * point + (0x4e51def182a5bd5672ced3106f19ecd94b760dcfc68e66a3656d0b5db19165f); + tempvar res = res * point + (0x42f46c19b87a82522476372ae65817f8d53f263674a040531bb37935b289893); + tempvar res = res * point + (0xf0bd4817ef6ef818a35ca3678f88abb078678a1364539bd7886dad527cb28d); + tempvar res = res * point + (0x501f0235f18b49889497cf7c91fe0a1f81d74da8cb1e88bcfca9127392aabfd); + tempvar res = res * point + (0xc11cd155f0a514a5a419d10ffa72405817256ffc8d580b9d3ab002f596b2ff); + tempvar res = res * point + (0x9f712ae0384a87901ad44f53eee9e7c39544893d10b891a92e87e4d78e8374); + tempvar res = res * point + (0x2d511bed457c57d7354252189efd19e4f5c3496c1dbe1f1408ff79c8cb97025); + tempvar res = res * point + (0x6c8d7abe5c83db80647ff904bdbf25bd0e979607d2310ffbefaa1edb7ae1bb9); + tempvar res = res * point + (0x46e747695d9d234e15781125d05b85ce3cb01d676ef8fc45a939d5e6d4e2e56); + tempvar res = res * point + (0x21c86da8be11246b29f17d5f7f3566c20712711e03eba57f0ecace8c4355418); + tempvar res = res * point + (0x7b851f4004fd9f20561e3755d7c89528ddefddbbbcbaa9293e416c0dfbb95d1); + tempvar res = res * point + (0x31587ae13086228663118a1fbfad6d65bb9741d5682abfb43c7524cc6c240e6); + tempvar res = res * point + (0x2ef1cb499e790f2de6129225457520b560c1c3120457e742957d1148bb934ca); + tempvar res = res * point + (0x781fe3d95c096c6df1c9ced110914917e26d0860da4bd769e4682a17540768b); + tempvar res = res * point + (0x7cf92bf7e933187b6ea01019ed1c2d9936e53a9ea89724e00e36672dca1e36); + tempvar res = res * point + (0x290b573a86b30d59fd1301b7985a68fd9bf9dfca5451179bcd13d10eee988aa); + tempvar res = res * point + (0x4d3987a0850d8159f9290a8ae8cf99a0ece9961d22135b584d8fc742d42c15f); + tempvar res = res * point + (0x6247162754e5af6a0efa837daba678811cd749e92d91acf35d732aaf4bfb4f3); + tempvar res = res * point + (0x1e3df9ca8b80529441770e007a27cda52e54307e4f3370a83705e0f3ffc86fc); + tempvar res = res * point + (0x25579cd0082839ce295d9bdb24140a8f2fe19f7d582a4993a88639a0347a522); + tempvar res = res * point + (0x70181ba88ba8d19c0220225ca0112845e23ed7609ffa4f2aea3cd40a40eef30); + tempvar res = res * point + (0x481c8091e40139c67f7e69737f83a6c868e582526afd50b548bcfa5ec2e83f9); + tempvar res = res * point + (0x1a758f2faad6702cac573f8ee11d83977ca75744f52d650a6dff79bd6c5caf3); + tempvar res = res * point + (0x5a87e6f4731da56e8b078bdea4cc3f1fa2059943de95ba404ab38addce3d6db); + tempvar res = res * point + (0x62a78aa9e73bc6da0a8536da8dd43311ccfb52829e89e9e94f3b413efb8ff93); + tempvar res = res * point + (0x4cb8044c471e8cdc896ac725744d1a6942bcb26d50b3641e2a95f57b0e7dddf); + tempvar res = res * point + (0x57d63baf011722f5c5a9c4c60899bd918c3287302c97e91fc6f9f8ba089cb97); + tempvar res = res * point + (0x60de66fa4cc5d53fcd9d027cc06945a96de2f9b4f7d0c81c53a7567fde886dc); + tempvar res = res * point + (0x794e6f83556e5ffee6d83daf40a067363b22e157cdd970366757d5d6a02dbc9); + tempvar res = res * point + (0x1dcd10514fdded828639c9c21d0c8064647947e9ced01014ba8943b1d81bd12); + tempvar res = res * point + (0x7cf749a9a9177ecfa46b901ce91a8ebe103f8920d83713df80efb7fc8868346); + tempvar res = res * point + (0x1ecd644cdd8b92b3c042932407033c073c7da5f3a8726210a443f10af466ff5); + tempvar res = res * point + (0x55b74b3af769611aa4c4fc71b1abed4396b218a9d5884844c937bc38b30bf8e); + tempvar res = res * point + (0x4fc4e265c8471510fe6f0dc99d7be1108eab6200b0845dab07c5a126c79919b); + tempvar res = res * point + (0x37edf969a82e9364a741858bfca74b30e86b1b69b4f33bb4a31666f4b2e7c10); + tempvar res = res * point + (0x2a3ca69d295e5e750b4db8367227f9cb347b3693251ba9761a22d411de1c41c); + tempvar res = res * point + (0x7e9f729b710f0fb173b36a6ee9611a9d309a9dc69a776c08dfe63c64c528a45); + tempvar res = res * point + (0x1e2c3057002cdd12b80fb157887fc066b41436bbb71e328bf79ed2799947c49); + tempvar res = res * point + (0x32124f76e477a3c6f5f4346f8abc19cd481b6f43088ccd1c3e8c634bd90cf); + tempvar res = res * point + (0x5007d334256950aba31d4bedb5decc0ba6ab62a09c41baa8ab8d0eb4cdc170d); + tempvar res = res * point + (0x3a06f0e39b3afd46934c41a79a317f220c6321664cbe236ffe1c191ee0b2c85); + tempvar res = res * point + (0x18db208640b40e1acf69b256f0cf86c76f381ee79fa0bbea47fed2c95b5467c); + tempvar res = res * point + (0xa0c5ba0b916bdf79b70c0d23013443f65bd087aaca62088b0d1f7009dd2d70); + tempvar res = res * point + (0x5dd2afd2e8b09f86360d183e2700f71a4fb5e458c61823ece1a4e60200b82f3); + tempvar res = res * point + (0x5b3102b46125dd26f3ae75c22cb8be10a3c98f269a2e91ce7d595d25c77e6aa); + tempvar res = res * point + (0x2c489389378216a8f4a24999efae5d41af3bf123b10601d2efb419999f329e9); + tempvar res = res * point + (0x28bb7956a08b64ed0ed089f0219b05b282eb25c107731d88867f7a78c3e387e); + tempvar res = res * point + (0x450e38572d5b45eba95a4368d52056640cc18213b3065bb7b373a05561cd44f); + tempvar res = res * point + (0x6931414c4f1e51dd287a8273a71ff946d1502d29539815c6652e6b71c95d013); + tempvar res = res * point + (0x48fdfbe3980d1df8db00fd59b4b529abb0569c82a25c6b23186de11aee23a40); + tempvar res = res * point + (0x680f30c7e737040028b548f49d2110d8889aa8dec6afe1de989e3f1f0c1c84b); + tempvar res = res * point + (0x8955f2b26c2c91645402ea61e0b3bd091758afa740b4478e3fd2d97b7d5729); + tempvar res = res * point + (0x62796f07255aabe16df1ca5ebe7f7be4eb1e9b688defe3044b1fb8eb56765a3); + tempvar res = res * point + (0x29f85ec8df7c753f09bd36309e6d7d65f5d5c327d4c80ca33eca932da5eea0c); + tempvar res = res * point + (0x40f21a24062575a80e5a6b6fa209f04178fce24323888c3fc9a083c6cfffe71); + tempvar res = res * point + (0x29eeec3cf3ff9267792e170045fcbc1358ad5b9c28b97db6f4cb5a131dd1e57); + tempvar res = res * point + (0x6d82291b429009057a7d89082c7c3ffeade1cbb4598b6bd1322c2e2d3c6819f); + tempvar res = res * point + (0x78ffe33137f03476882656c458a984b78bfe509d0ed005657860541fdd16506); + tempvar res = res * point + (0x13f6d5bd19a25ef48bb5a89c64894e9351380c31e98fcb8404c490081665acf); + tempvar res = res * point + (0x36d9f7e5746b465ccd284ac21d5cec14258587d22189b4f85ea87f9b4d7c2ef); + tempvar res = res * point + (0x54730884e1c5c7ff5bff889e8e5846f7e552f07beedb27035c0eaebfe676023); + tempvar res = res * point + (0x7344cd22ecc8029fc605bc46e5f2f60c2910130290257210f9db71f26dfbdcf); + tempvar res = res * point + (0x6a60ae65aaae41d02d6ad44360c269051a870c66a87e430eabd1c2c5dd8261f); + tempvar res = res * point + (0x639a281c19217bb79dde39d86549ffeaa0694283fa876ab39fa6b663869ac9); + tempvar res = res * point + (0x48a07a1f3adb4348f65ca07f7e1ad0b70a6024c4934df5724c35f1930befc90); + tempvar res = res * point + (0x527d59fcf4e21663d7e921cf93b705e95fca41d9d2f88720800586e03bdc283); + tempvar res = res * point + (0x1b07576ead1fa791e38995e423ee788587adb512c1bda749fc0869ac6b40c6b); + tempvar res = res * point + (0x7b59c1f0252efd3b471c3047a2060ccb98cb86148c1b1893af4f86384821b04); + tempvar res = res * point + (0x56e48833c5707aaa1e38a0d644765251c038ac3f89ed4d58fc3b24d03a83e77); + tempvar res = res * point + (0x14d1da51db79b82ff5fc48e18ad84a98b1390d8e61e1580ef5c6100d49da80a); + tempvar res = res * point + (0x6ade2f8ff114a1c0a0f108286f0f0e820073e7fee989a85fe11a97b972f077e); + tempvar res = res * point + (0x20268b11ea1f54c737a14073b8bd83a6151aa30b0d51182446adc72aa2bef83); + tempvar res = res * point + (0x937368e9df8289ef2d93e806914cc9ac730750d1ecc6ccf6c4aa6e6788d35c); + tempvar res = res * point + (0x297d16ecee6310efbcf8a2946e1f03e23ce1eaf88fa6279dced371db9dbc299); + tempvar res = res * point + (0x74d40da7c08b8fbd488137dcb60906f2004a26faf06e6ee4dbe1feceb94d98a); + tempvar res = res * point + (0x5669aa7f25c6cefb4a3e1f5491dc50af7c44ca9f8405864906b353c4c3529b6); + tempvar res = res * point + (0x4a5077d73c41429dcb66a5557cd392c5e8b64f4f93507e5e7b8f1cbe29a309a); + tempvar res = res * point + (0x5974550418ba46ba346cb87069b6c17f9a6d57ce7554827c8191072b4ff8357); + tempvar res = res * point + (0x6fb7a7f6c760b606b4f7cefa186540604099bd229b954096179a12ccd50e323); + tempvar res = res * point + (0x4fe2139f7019584c7f395a18bfca2f5ea89a9300bf208b9dc73686c76e724d6); + tempvar res = res * point + (0x4b45d3cd223171c9e2e8030a3983c2e4b6ed61a560db3a8da8a2bf1da05ae2a); + tempvar res = res * point + (0x223dbf6f82e6f2b2dce8397a7a6d00c8fe38fdd8463fe7612c1a90bb76a16c9); + tempvar res = res * point + (0x13e7cbf6809b1c282b1716db08a549825b9e1f24479288cf615c6557249f675); + tempvar res = res * point + (0x13b2e8b26fec1c97c5fac659532830270b08cc6861df86b3f3b4894175551d9); + tempvar res = res * point + (0x34a45f657061a57b808e337faed21f722e6298262a2df69d6bd34ecf2e29243); + tempvar res = res * point + (0x372a448e249504e459982c7d114b3c79270419467208096cfa6a96f3e5de755); + tempvar res = res * point + (0x5d62087a11238dba183191a31e686ffea34bd393310e7a2b11c75d63ec340); + tempvar res = res * point + (0x5f25fb2b70ae9e334bd288d6768a7b3b6b2f4672cb671f6b0ebd781134609d3); + tempvar res = res * point + (0x1025bf3b6ef4dc8e3637f4dd1cda0ea30ebba8c30ce5638b5f9b5291faa0036); + tempvar res = res * point + (0x7d2b1bf76ecca560b7409dee16ead5b2b3691ff75ef8fe5a844306a7e29b252); + tempvar res = res * point + (0x7cb9fc14dc4bbad427efdb3f5821fc9dd10fe8595577e39645ab9f62e6fa50); + tempvar res = res * point + (0x6f61949d4cbc8298879b470d1fa9aec82261a8099c448dfa4379a597ab01d03); + tempvar res = res * point + (0x336d1ccaccbef10084bc4a18f8c86f699642878a2b5d5af3a3fbe7a773e6904); + tempvar res = res * point + (0x354e8d015485a06adadbf43a6bad63e9330c4070fbf2a704c166e1d278c8d4c); + tempvar res = res * point + (0x45526e767c14a531fbc10f287b2a4203e18daad8a4883a1900a63dccc1a18f6); + tempvar res = res * point + (0x688bfd9b23436077dd139ccf0a7286444429f3a2457ce7e2cc939be2172921e); + tempvar res = res * point + (0x5dd26663ad2931b249bcf054211723be60b5b46de16a61928c0a9326874f3e0); + tempvar res = res * point + (0xaeb2689fd195377c86c55bb52ba2ee27c7c5395d8163355a3c04135b43333a); + tempvar res = res * point + (0x73ce15dc2409ac614aba33d14c4ad294a3a8136eec69e8b34b0b14b92eb240f); + tempvar res = res * point + (0x73a3905fdf4a2f53d66ca4cb99ca729e776ce66d9a474fd71da35b3fa949d34); + tempvar res = res * point + (0x1d60249bd6492637249efa94de232264fa23d62153d7a36e99aaede0be5d842); + tempvar res = res * point + (0x728595451b9c3918b04e7ce1637804c1df21495ad8f188eb46a5f1796e2e3c1); + tempvar res = res * point + (0x5dc73d8837d2fd0c754ecd371e94f0af344396efdb4337a8c7c2a0755838f46); + tempvar res = res * point + (0x7dd917167308b602914680880c9c8c8519f34be930ccafbaca3d126a30c4a45); + tempvar res = res * point + (0x1950cc259cc77027d5c86ea77f51a34cd30ad768676d77a0503f36f797eb4af); + tempvar res = res * point + (0x4d5df514fa9a8bd7515039e59bea7a1a1381a76f475a7dea23549106a7df8e2); + tempvar res = res * point + (0x1d74577e412af12fd886706cdce3c238f2761d096043a084c20d2bd087ad4e6); + tempvar res = res * point + (0x7871f7217ff1c7b739678e28908c4222f492ebf866cbcc410148ad1d143de0f); + tempvar res = res * point + (0x59a88072f92b384925c9091497269ba9f8226c24f740e928e410ae0bfb9350e); + tempvar res = res * point + (0x19c90daa3645b62f461545c7c38ce5bf8b5cdad399f417e0abbaf2b2df0ca64); + tempvar res = res * point + (0x53b86dc3cb8ef3d5920ea35c40e2d05496e45245eca4e0d058e2a0e2d583dfb); + tempvar res = res * point + (0xe00c78bcfc271dcc6556cb1cf6501e16d20b188c7412681c0b2ae0f2cbae05); + tempvar res = res * point + (0x36ac6cfd4f2ef6be5b1e83cf9e36e894b2575a8f4690c14484a17c222ec3c00); + tempvar res = res * point + (0x32cad92232ea7886b829887e6ca4ae084800803277076107b1078feb66e95bf); + tempvar res = res * point + (0x38269de0c80a2d8f4bef1d5e76805d1e412fef7b18886279e98c57a0fe64627); + tempvar res = res * point + (0x217df85b26b6b3bfc67bec919866b6e146621c30685a31e8c93eaa27d5dbaf5); + tempvar res = res * point + (0x4ee32b2ff29b0918618f173c4e5dc3b606a1ca2e0eb989257e0bf78dd2e9589); + tempvar res = res * point + (0x2d51937feb119772693523625e23756d172e996d1cfb82a258580bd51c15e33); + tempvar res = res * point + (0x7c2468c14a7ea994c89e2e4ddd6d2d624b67a96e7ccec4f27a5e0122531291c); + tempvar res = res * point + (0x602aca232b11ad63241b5f401c368acb1e9cfd4e5fc8ae699491d9c51b4db18); + tempvar res = res * point + (0x39c92f0c55d99aa6b082d21129a9402e6b0fe38a639a8140d76ebee9dc45877); + tempvar res = res * point + (0x4fff8b45f7ede0580424c4e2c75213c4c42ec6c68266c8d5d750a2863bd474a); + tempvar res = res * point + (0x3ba2c93d59d6a361b9ac28d93e54d775b040bd7fca9ac72339ea4388c533dda); + tempvar res = res * point + (0x6d567c1dbb663fb2fd92140cf66ea33a19cda580d18c10fe56a62e5bd3f47b1); + tempvar res = res * point + (0x2781266a2070c9d3f045010a32c98ce3e0765446e3ee20eacd73a0dc0c7c2c2); + tempvar res = res * point + (0x7dcfd5001e21e030b006d54c7fe0f7ca97a2c18d4e00ba92c005705a4f0563d); + tempvar res = res * point + (0x2fe4c112d7bfd4ad5f81ecdc4b30cf73aa51df4e4ba6d255a0e3eee283aff46); + tempvar res = res * point + (0x2433d40f2b8f9461b5368cb396f7604999a735414d3537ed6f1451f1fe93cb3); + tempvar res = res * point + (0x72f959288185bd36ca4e23472ed7a2577f8e5f0ef0c0d5df6f63e60f40ba307); + tempvar res = res * point + (0x4c5592288cc342232d76c80e858c08ecbfde64b747637ccc9a2734e90f85264); + tempvar res = res * point + (0x48ed57151b6dc68b039dc327f79bc2c26db62ff957809c5538360facc04d9c3); + tempvar res = res * point + (0x5ebd9b268cc66bb85a5e67a6b9d5fdbeba8b3672491068ef43b688a3a043a33); + tempvar res = res * point + (0xdf6c1013f3076e6044f0a7032e0bf80833f3c7d9eb0c3eb1f3c2a37314d19a); + tempvar res = res * point + (0x5f0cb66613216a1339c1cd15239b7f03c1d4b9098a931f65ae50b877f861880); + tempvar res = res * point + (0x5d5fbd560f7bf1e97190f888fa43b32db1e8070f046d6016b536b94d1473a57); + tempvar res = res * point + (0x33381003a653f0327cbdd8a11252ffe714e1061ee214329cb99e667c835af97); + tempvar res = res * point + (0x7b86849a979796096f7d7b46eebaf00913a082c638c5b2bfdedbcd78c480272); + tempvar res = res * point + (0x5f27bcacc10845ad41cb26244112faa8b91d46d97024445f50ced796ac5a93e); + tempvar res = res * point + (0x31cdca47c96b32e99077a96aa5cd73ec9c4da04212667805c82dff3e498f4ed); + tempvar res = res * point + (0x66a032c182ae70dd4487897d0c79dd860a25d21c61e3aeef8b9fa45349dee89); + tempvar res = res * point + (0x148523eabde5554538a1114351f3d8730d4a4d003311c7b57ce9e709afeeca5); + tempvar res = res * point + (0x62ea67803c421a4bbdc672d556bca219fd24e7145cb3e9113a625eeb4459254); + tempvar res = res * point + (0x2c2c70075ac99cfe68a7354ed29842c5207bbdbd09dbbd225ea93d0c07fd9f6); + tempvar res = res * point + (0x48b0cc6241c99407bb346db57db9cf82b2e66d1fcc1d756889a4f4b4bb8b396); + tempvar res = res * point + (0x506f990d7037060dea08ed53c5b17483ca8a7c58f94ba5e64fae258be4c78ed); + tempvar res = res * point + (0x777be5852ea7798899d4750e9decd1430bdad6a8b0d1827a7a89ce6f1afd89a); + tempvar res = res * point + (0x689fb22cd95d6f1868a4e3cd6ef1bba9f974931f76153e73038ff5ae7d09018); + tempvar res = res * point + (0x560fef0ed77bc94e16b9d9a21bec0ceadf81b26fe683b9c74b31e2d72a4c92e); + tempvar res = res * point + (0x28c74f03f409c942d16a773fde01b3f0bec544b42c1d46944db6253561e1ac2); + tempvar res = res * point + (0x4d62e1ef04cb039a58dd8cb8c37dceb78b10fd84bbec6302c964b899a957d02); + tempvar res = res * point + (0x44094c265809e3d5765071826547999dce8ba7058a7c1b1301294d8291949c); + tempvar res = res * point + (0x4e0f90743d3df3d3c4aeb80e7f6db457620430ff28475c6194c757f81927dc5); + tempvar res = res * point + (0x2cde734d2a82619ba69ca4f5ca5035f699a1e34b47560d761780546c9b04d44); + tempvar res = res * point + (0xf09069dc6a2745587b447ae03ebd6524aa9757f1090a92dc5e7ce8db848195); + tempvar res = res * point + (0x5522f48902001bf41de34be900783ac957fd867cca0f35666ca491ea89d8fb3); + tempvar res = res * point + (0x5b4be8af83915fd955ba32de729f6f2aef6c76501d82ee325d72d620bce8b7b); + tempvar res = res * point + (0x78e74ffaf944c363f3fc42cedaea8a9a450ebaac98bf1327590a11e064bd76a); + tempvar res = res * point + (0x6ade7c482d201c23145e3890086b22ab0d43495f5c83b1672316c10ca52af0b); + tempvar res = res * point + (0x79c066efe4c22c6e9e097e84401e183d3c45c645d986ed640a8faf8fd4dd096); + tempvar res = res * point + (0x21d59ca7451d83d78ab4d9d17a662367ac84b555866ae92d036d71de22872bf); + tempvar res = res * point + (0x6d100d3db14939bb442e5f5ce6a05939f201837007331536440a57c2bf2b609); + tempvar res = res * point + (0x7e5bc177982061f124cbe521c713c24438aa021fe6928d82452e44f6cdcd631); + tempvar res = res * point + (0x179e4b1e4817460085d47376a1971fdcb0287408cc7d11fb62cc3785772249c); + tempvar res = res * point + (0x2a7cd1fb12f896bff4d3db49ee74a51e970e3e386c2c8e7622412a6156a300d); + tempvar res = res * point + (0x3c5581c15733dcc4d548aa0a6e648e075e9be412680a76a556f91ae5f01e44e); + tempvar res = res * point + (0x4a4eb8f57c99e931a666de76c20173adcde82ff59fd8ecaf8b8c05e29b63fc9); + tempvar res = res * point + (0x58fa31f9a4a7e8b238898eb1296ec55e3e2000a48a2edc8e65d260d31bfd7bf); + tempvar res = res * point + (0x2c37f85ac7b1aab52ce3d28bfc65c65b7d4ffd000757c07fc493d183b7bb582); + tempvar res = res * point + (0x461b788a24347588e4f8d4f2d66640f31d6b580223a21919ccef9480987db1f); + tempvar res = res * point + (0x47c3222376f8f18dc6e82eebaab03fcf4c425acd901a7bf9841a3aba54b82a6); + tempvar res = res * point + (0xbece573771924d045b75bb992a87b26ab067a0f2dba4d1a9efbe5029963533); + tempvar res = res * point + (0x67c2a0e19b59921666716fe2b3f9c7f59c4da17d993956eb87eece7ef542269); + tempvar res = res * point + (0x8940bc9dc45fd06ce4046337963c849324bbe5f82632b94972c0ccb205480d); + tempvar res = res * point + (0x38bff358ccfd92418537a9b9858df499d2c44404c1886b109edb14c897e74fa); + tempvar res = res * point + (0x533a5a2ebd098297604e96118f2007ddd12af50edd525e9e5a0b154e620b2e5); + tempvar res = res * point + (0x312411292b7fe7eee015fcfaab65b611bc2b9f9498489fc3c1452862902bbf); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_pedersen_y(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x62b07622f501888a668440d9b856be4b0c3bf12a401fc2bebaeab4a7e1684ad); + tempvar res = res * point + (0x75a127d817aee244517479bab5c4bfc2a0035d43d673badaf64d8adf94353bd); + tempvar res = res * point + (0x14f3359ce0d2891d1bc2b6f4d2d6dd71fe22925b8a09f66147db095a9d4983); + tempvar res = res * point + (0x2d6129632b4fc43e4142abf55fe2d1f3e79dfa01c73d8fb56a465dbd07a9682); + tempvar res = res * point + (0x5115ade709c058be5dc6f406794062642086e431bab03c9a86d53c79aa83db4); + tempvar res = res * point + (0x29f6aa5fc92eab8b8b9871c8449c1f617b808ea9860717f3e5e1678672ec565); + tempvar res = res * point + (0x7e08f9d222cc0764fb5ca69e51ad4cdb7f1b612058568a142bc7a4cdd0e39c4); + tempvar res = res * point + (0x54c5dff0aed23c07edcd958ee3690e617011b87a5fec541725237d4ebf34382); + tempvar res = res * point + (0x2b7d501bedc4e7c604b0e55dd2d8166fa39a541efc24d81d8464fabfef3fa37); + tempvar res = res * point + (0x68e1d50b4d0570e357eac7bc742ec26dac1edc5b179989c7ae8d31791639103); + tempvar res = res * point + (0x707c572424682b685a1ba90dfd7e56f86254862d86e20b5a2d3ca85fe0017ad); + tempvar res = res * point + (0x2cd9a093ece61e554b2bdde3ec474900e4412775ad25456e5be6e11df7b9fff); + tempvar res = res * point + (0x7492aa940f34a027f8fb3700f29cf628c1d05d1675cb7865509f20617a90b2f); + tempvar res = res * point + (0x55e928ba557ed7fe0ecde6d1fbb83d112e6b06a087b4013b9c425fa36eb0415); + tempvar res = res * point + (0x3cdb28a913a41d597915de055aecc59f2b13079d3d8b33ab0a075eeddb1bf8e); + tempvar res = res * point + (0xfd48fb35400aaaf57d130b6143b241db8af174cada72ede8f2fac4ec6688d2); + tempvar res = res * point + (0x133b6505a6afd2e5fada0e53ea51c012e4935ea6d2d02caaa15ffc50a45079b); + tempvar res = res * point + (0x2d2d27711772cafff2cad828dd78d8b213e317e8939cf79164ae64dea577d61); + tempvar res = res * point + (0x60ac57e328ff6938a17d43e6137a55399b95459be60fe980ed8960edaeee10d); + tempvar res = res * point + (0x7b056cb6f172b25e3555d6b1422ff769fd4c07258fa16b03609f0e374012ed4); + tempvar res = res * point + (0xd21afb1901f1b3ad66587a7fb97ee06662edc3bc8c8d32b48625a135ba23a9); + tempvar res = res * point + (0x7784c2e140072fd26e95911df38f9a337107750a72b9ce05a21a0f781b92dba); + tempvar res = res * point + (0x7c1667b8d44d288c4f5150d01c5206d4d5868497630745b6916466c8a5b1228); + tempvar res = res * point + (0x491c2243a95c44528b86167a4418ff9d93a04bde8dd7a5d2b19ea579d295312); + tempvar res = res * point + (0x6aebd7a9279eba43cb1c0b14bb723dde464a86cac92518ca16ae27a8684d9cf); + tempvar res = res * point + (0x709be747b0a69a9523680ff69e6bfea4637bd570ce5c45256b39ff695557da6); + tempvar res = res * point + (0x47275cd67ff3b7637ed55ced299a6142a821ab466a897f1eecfc8bca557269); + tempvar res = res * point + (0x58ccfd44df4e339c65e1423eaad47210f2e16aa6530d3d51f38b70e5eb3a623); + tempvar res = res * point + (0x28218a1bc7586b71ec1989082b8f7ab0efba14569c6f6e5d7aeee1964ab6d70); + tempvar res = res * point + (0x660bd8049bd301d093aab9ae530bedc37467d4ff0a12c89d689d61ef9b9546a); + tempvar res = res * point + (0x4dd38543d129d0a71b1836c6e2eae47fde5d572e32ee9a5791f7ee823eab4db); + tempvar res = res * point + (0x8509234000e130c8828328ae4997d5116117716cca9490e6e63f30b7df699); + tempvar res = res * point + (0x62ad4d764ed0072a7649425270e2b210421c77d3ce98e2587ea5440a591ecc0); + tempvar res = res * point + (0x66c5222dc133e37dfa0566c49d107852d978eb7454489d3b2ada8de022125d8); + tempvar res = res * point + (0xe4d1f1f1f9b379bea473f76bc8f3c4d530335e2d6bd782b42324872767b628); + tempvar res = res * point + (0x6ac2f92bc4c04fd50ebd3e336b53b866e790ace39838aa96a4b791011455b29); + tempvar res = res * point + (0x59d753a23735a336c50466f5ccaab3671230fbdaf55101530e5f562a5efcaf5); + tempvar res = res * point + (0x166b26359c51d067955874f5612eb70806d7b8d5de4d8e0a75e0d57b39b1846); + tempvar res = res * point + (0x2dd27ce7910e44ee00ec3335bd79429846a70d92d482adf81b36a9ff1aaa30a); + tempvar res = res * point + (0x45970c86c25bc9a68f2e2a34969faa2134c95b19230fcfe7436c98f537539eb); + tempvar res = res * point + (0x539cd2c1a28df263709cf0eadef73a600f563ab3d82c27692b1424814cc3e15); + tempvar res = res * point + (0x31eb3b57e6844e3efc1e3975ea393476d8aace5f43ca62b09314c90b8ae9688); + tempvar res = res * point + (0x47359c8dd2b86e4f634a9a50950abde25942877bc5db93d62bf43d2886692e4); + tempvar res = res * point + (0x2d8ae7b28c8c3acc8bef3d4c2a9f5ef1323748de693a9a1ad3ff8601116b165); + tempvar res = res * point + (0x4538fc863186b4babe3b424b4111251bb1e20ba5516be54160cd560ec0d5a3); + tempvar res = res * point + (0x559548517b1025ad61020be3e252b6ddbf1d5d53043231f8850c0da52b8268a); + tempvar res = res * point + (0x3132d42e4a928c08a972e17b2c3b500dbcadbe6190b2e7f5b58300a0c8a38c6); + tempvar res = res * point + (0x5b02adb78afd4e219642a1fc38b2ef9f63926841ccfda072ac17326d3d50f3c); + tempvar res = res * point + (0x75971517855ffbc9657dab30657ed1e3797307bbec1ffe136cb0d8a64ed6eea); + tempvar res = res * point + (0x174a4710688db61da7559255caebf641a268b4df53d45de5e8156d36b4b2ab0); + tempvar res = res * point + (0x295fb60eec46a40a33b1a9532427b42e224c0ac6c50e3c1c5d17c2c16651a25); + tempvar res = res * point + (0x2037a7d08a1c4fa4d5d4f53436a252302840007c09163026637e9cdddc958f0); + tempvar res = res * point + (0x7e9e1c3d4bd3231686c235a495f737a9ec3d633331a95d85e17e90f99a08af5); + tempvar res = res * point + (0x218da336adf8608530fdf8320c4edc00631d36c8726430732038a369548cf56); + tempvar res = res * point + (0x78c7b0512cae47833eb6bf01c1075aafca19eef9b32e37f4f9a9eff315637c7); + tempvar res = res * point + (0x628226c46fe0bfa8aa36074ed0785cb16461ee2945ecee9deaa6399bba2742c); + tempvar res = res * point + (0x2eb6bd70a00ec26418d347df1a444f7ba0972416103f00c771e0f3d50bd8e5); + tempvar res = res * point + (0xdf82eebd6cde9b50958606c6ff83c855c43ce9613fec366c7792cb456ea913); + tempvar res = res * point + (0x4221572cf29651f508bab9eb82545b17cf6f9efd0416b65262e5491ad408e39); + tempvar res = res * point + (0x1d5fc46deed0eb9b56cba1d2bf8075227504aaf6ab1330b346cc3cb84a07cc8); + tempvar res = res * point + (0x55ee57d4096ccf0260baa2a1a2639978d965a786e4fc917cb2426f8a99591d2); + tempvar res = res * point + (0x21706619a453a544bee0ccaceda9fe69f860c894b36bc9cb7ea4455dd88a9ca); + tempvar res = res * point + (0x76ea16625d0cf0c04f096ac7d6eacafd00809ef1d1a3cf5e37dc2a13a02d303); + tempvar res = res * point + (0x6d0d885e8d2530c7a324f7b2ef47db35aa8162289a4420a54f13a82b871d850); + tempvar res = res * point + (0x471bb97187c83c0e7b51ab70022147e8d8ebe25d4081907e7d1bee8d6c6581f); + tempvar res = res * point + (0x12b9157240a237f319beefb6019bf0de1897b9e2d8e5536e3a21d8f9fd689e7); + tempvar res = res * point + (0x2ef7f1dfebad70ef549da1a143c838cea27749807efcb1a0a29cfab16420928); + tempvar res = res * point + (0x519de0df91b17442a8f60b512297d69a1b516f70f67d76eb9c287f06e37c55c); + tempvar res = res * point + (0x2a45de0b79a4e9c53d47f6126d35b1d050775d5fb17f3c3dc22c7b6476608c0); + tempvar res = res * point + (0x27e3cfc87448bc0392a0d6c1b1aa06626636fc703bbcf3717fbe6f0759c4855); + tempvar res = res * point + (0x77a45066995089dbd4072d6817397ce0c7e92b53d19338e9bd7549e954bd961); + tempvar res = res * point + (0x3139ae970d95891aa70cbbf6f172223e07eb521a5149b7e0c9202793f6dbdb); + tempvar res = res * point + (0x25dd21ff92e6f1075df6b5ddb2b774ff963b1b84a985261b1e94ca9eedaa49d); + tempvar res = res * point + (0x13eb9f5362c087af5ee758bf0b589c0e34af337b3c06c788573534e96de30b7); + tempvar res = res * point + (0x6a39a27be962632e0bfb245f65a4d70912d1572e39003d63def5f45bbcc8f7); + tempvar res = res * point + (0x2c11fa8c0ba68518942f1c686dafd32aa26545886d28cdedae00071360df674); + tempvar res = res * point + (0x7ce49a9b8d374e1174ae6ccea7cae8d743404552253f7ec854317722a5efffe); + tempvar res = res * point + (0x6bf518769635f9fa39c1258844d4f62e5fc00b70792944da0a939990492313b); + tempvar res = res * point + (0x6123efb57144c151864b4f717a44cecc667fb2ebc47bf24bda4f7d0ef8f550f); + tempvar res = res * point + (0x2c29d0056cfe7325567a9f2d09d917b37a45aa3cefe20b78c4bda2942af59bd); + tempvar res = res * point + (0x76914b565dab13e76053b7a74c24c005b0930011e48ab26db44b6b49a1e7ae5); + tempvar res = res * point + (0x648c35904fdb8bbf9c0bc9288319c248e17974fbb6616a70acdac004878bb9); + tempvar res = res * point + (0x1cc7ec07c4e1e6626b5263044071687d0ad34ad4d08996a213380e9b728585b); + tempvar res = res * point + (0x154a5ad294d41caedd8d927eac226dea1e2b78f6ed0a6901a00e45ae0ad78f6); + tempvar res = res * point + (0xbd5fd7dcc1ce2bcd7f7415a22115f0c846d16ac7458e6c531e7e44dc664962); + tempvar res = res * point + (0x2b2b08bfc4c3d5941538b2eda43b3cd009656cf83b6b23be56b3041df3dbb0b); + tempvar res = res * point + (0x5e48cfc304417473eb4e587942a76921fb007d8b11ce648d36828e8cbb5d595); + tempvar res = res * point + (0x79c11c262fc2efc9aceafe4a5886713151352e60c4db45826e0e343cc5919a9); + tempvar res = res * point + (0xe2acacfba8f832e4e3cffb6ecf4675df678403610fe91363172229444ac0c0); + tempvar res = res * point + (0x6dbd918c7623bb07b05ca515146ddd7193373250e0836062fd1c430e2b7894a); + tempvar res = res * point + (0x61b210c04a0899fe2a3dc53348507d6f53d4cd3831644e4630eb40564ee5b47); + tempvar res = res * point + (0x1e3816f2a6a4900b65d140d144225a8a81cb3ea22f56de3cbcfe3944fc0e898); + tempvar res = res * point + (0x3c99839cb11fecd878ab9efd1d2ed2a718f6e0df4caac1a070de06ddf1a6091); + tempvar res = res * point + (0x567205f3e5ec69ce7962918c41ed0309c3ddfd85fc92702ce1c207b282f17c2); + tempvar res = res * point + (0x10382fdec78a18047041629179e18ec7dd067bed125bf5fe83f13d637a8ff67); + tempvar res = res * point + (0x43aeb91e6f453d372353d9814a85c21617e6c934c694a0b06100e1e9aec4087); + tempvar res = res * point + (0x2b6a2e9d453e19e3d766f24cb7c6753f84adca0f75f7a871092688bb5ba0d37); + tempvar res = res * point + (0x1f3e3e61713ab64544b28dfcaf4da25b64e625048ca55cc783dff614f5796d0); + tempvar res = res * point + (0x364cf25e248a3f2fc2106025945389328c0ef37848a59ff2afdc685c0854822); + tempvar res = res * point + (0xf9762bf5620ec90d711f12cbe600f29906fcdcdea4f17cf51ffad2e07887e2); + tempvar res = res * point + (0x78e4cf312ec50466bfea965b655e9514d9d69bf0bae566fc88187fe730f70); + tempvar res = res * point + (0x8981cc99962f20f8814162568d9d7edb7fcc637fc6907a98b1d1eece9811c6); + tempvar res = res * point + (0x4e28bfd662fc5e09399fc49a49a622a7e845631244b9472df8c91c4a703321a); + tempvar res = res * point + (0x3085800be446839854dfb7bd9ea67ff139267fb5268faaf153db26b00368630); + tempvar res = res * point + (0x787a6c80d5a23f91cb91d2508633cce6125da76e797ed460256933a4e6a24b7); + tempvar res = res * point + (0x5ad768a2e70b4018e505bb5f6f44d249d9f5ba5f126106cde9be7726cf5c0a3); + tempvar res = res * point + (0x58afefb8e3180356e33794e20db869aba4bd4e5dfc795f8089d6f123025179b); + tempvar res = res * point + (0x4f62f4d968964e4908d16fb9412f8d10eb82e14e83f3e094a02470f27eae006); + tempvar res = res * point + (0x5ffa0d51bff335ad53cfe99165aa64f5ac1b01c360bd0101856537fb03da5ed); + tempvar res = res * point + (0x43fa3aa05db6331941265719fc1ee057d9f3dc81704f81c2ce7faece0fe86c6); + tempvar res = res * point + (0x1e836012f5509ea2f3dfdd474e9e4a96f6924e6619924ee4c6870a5294e26a9); + tempvar res = res * point + (0x41052d90f803f015bee5bd1a5f6e2f78f30439ecbe39861cdaebaa8f7c56371); + tempvar res = res * point + (0x16f6ec82023f48ea80196121afab584b9bce7f01e9515d0a3b489d68df3e2a9); + tempvar res = res * point + (0x4b7236fb7f8b72b2d369effbee5b4bebe7d2205ed72f9831b41c711680cbbf2); + tempvar res = res * point + (0x6620ec871e8a2c03933d0621b13e7f357b7349ea16bb549e7e15e2652692252); + tempvar res = res * point + (0x5b553a6606a3f01d862af22a3309a6df0aadec753fd1e0321b0eb08504c1f12); + tempvar res = res * point + (0x17a1bf17777a3b56a76df412810d05c9e222027aca604791694d3b020ea40cc); + tempvar res = res * point + (0x64fecb621f4dc18fa1b66152f28bdd15b7b12d495c496e77016bf3b979e4b1b); + tempvar res = res * point + (0x7e31ce22d2a3d776ad90e008ce82c594dab9ff2c42708f4f0676000cd86891a); + tempvar res = res * point + (0x43530eaa364a9df353dcfc154bae168e0fa9b51a3362c6cb351d47bb7f6b829); + tempvar res = res * point + (0x35fea15e2101714f172da73da6ddc2077ebd42ada067e7879bba8c2ee1d9db1); + tempvar res = res * point + (0x4509575b94136d744c8679c3028b0db514688db5338c4bcc9f50ccd7d15c95f); + tempvar res = res * point + (0xf8bd8807280892ca46c092b74f845d90f3a6b61b197a0594fa30686ca41a5f); + tempvar res = res * point + (0x51443fc9bbe11d787df4afc59f4366629cfb3a14c80cda1caa1ce6107fd063f); + tempvar res = res * point + (0x22cf3cd9fc0103158f7de369046ac0cff77c44c3f9c6ca942616fe7d59d6231); + tempvar res = res * point + (0x14714592154025f15704e279d2db4c70f545137269ccbd82c11fba275bacc85); + tempvar res = res * point + (0x1d44a3f67a1142e7922f4329f775fec5f8bd2d32ef8ab41a00821e76fbaa89f); + tempvar res = res * point + (0x2d9f309e84716b322c26aa86a3fe3cb6ff230e0968dfc58b869268c751e510d); + tempvar res = res * point + (0x64ff5a81d9e22197bb59e8cb340a0f44e22e226fed168f8b125d850bd727b7b); + tempvar res = res * point + (0x2cf1eefdbf254a549ddf4069288ea075d9aae074aac7853005b57c37c2039e5); + tempvar res = res * point + (0x20d846afc1a11dae8646d542770f294b9c9f21f1196fba567f2f74d058ebc25); + tempvar res = res * point + (0x4ce9244cd3966ce1a6fd7f8b85fb1c8751e35aa53032f8063535665ac3a69f6); + tempvar res = res * point + (0x203ddf8cbfae2898d2d2f183cd0efd1c3f7db1b84b8e96e38f2b87b4bdad1bb); + tempvar res = res * point + (0x37b40695420e59161b338e413a72daa6909f0e4f6f85426f8eeb6bd0dc3a1b5); + tempvar res = res * point + (0x8554877281326c1c7e1f3a2f5e81341554ecea862c2677fa67ab2f88b3b03f); + tempvar res = res * point + (0x619cb05e71db22ca1ef274bd0a7cdaf4fb79b3015b96f44814b490f048d2af0); + tempvar res = res * point + (0x66af1f51f840c438b502c2a5ab689f9b38c2c96df36988710951bf185cb8501); + tempvar res = res * point + (0x5486125e0ed23fdc42a4f8c96cb08d934b6f3b429c4af5f8396618e978e9811); + tempvar res = res * point + (0x41d785e118be2d27a159ed5216de66a84873e1f62088726d9607c6443a14090); + tempvar res = res * point + (0xa6117e45c1c561307d63895569d34fd7e3f2b2ea088dec37dc3a5527deffd4); + tempvar res = res * point + (0x3bfe2f1e8df44829fa27a78c46c223c7e64bda85be60d8a3a5d0e7d36c20e29); + tempvar res = res * point + (0x3daea06a4a96480c4f7fff1082d95836964b63c14281ef942fa9a9890d8754c); + tempvar res = res * point + (0x3678ebeaffc3e64d76141f41be973ff36e8398a6aa0385eddaa0c4183e3646); + tempvar res = res * point + (0x5cc1da57cf1059231e195a26b1323599c95f98e4b302d6e6f4bd41180b56d35); + tempvar res = res * point + (0x4f4cd7f9fd5b694cc5ea6154d0738cdbac3978ce74a7314bcafea3dbc1da61d); + tempvar res = res * point + (0x77bdb42e999e93273fa3cbb7ae7160522231680eccc4d38c1b8a83d2a0420a7); + tempvar res = res * point + (0x4e1cdd107e3116b4ff22720938a201eed2ea0b499bfde301562f5e39a42b066); + tempvar res = res * point + (0x513bd3eda9403f4167249972ce4947f3ac9e9da03a7b9ef557a65645b9616be); + tempvar res = res * point + (0x23d7ed01587af3b9aefeae8a627c6401d36245cafa9367631036d2bd7c47e26); + tempvar res = res * point + (0x1ec8c3c39ec4705944ffa8b3b9b61f73c9ad759cb79a107dd93a125685f5119); + tempvar res = res * point + (0x4d0db05514a8c0f152a8664579c004fb738cd3790214984bc3f21f31d494361); + tempvar res = res * point + (0x2bc791bd7e68342116218ed9bb657b8b54e550022e39af11ce55b29ae49218b); + tempvar res = res * point + (0x7ea13011e0dce5c917be4cd36c8931f5969852109a16d7c5142e8fb3c8b7650); + tempvar res = res * point + (0x11a9029a5c07557ec347592ba7181acafbaf0f0c5c9e81d7e995a4de57fe566); + tempvar res = res * point + (0x359506efbff0e2b81d91cd6a5f808a6c65255e1bf06cc03dbaba94758b3acfd); + tempvar res = res * point + (0x491899cb7600abb42ac8cd91f2c775ec410469573f57c1030ed1582327eedb8); + tempvar res = res * point + (0x7a42c4e98f014e50dba6b25fc32401b7695fadb7bf271fe0a763712ee545c2); + tempvar res = res * point + (0x2f7d26f183c54146bd83514f5459bfd95ac635649d74225c2168a8e7baec082); + tempvar res = res * point + (0x3ab952be650de0c679ddc0a35bac2907a6e58303059d4edb914e74c67d05226); + tempvar res = res * point + (0x2b7f9df93ba787a9a5a7a0a3b5daba02e2ce65df16ada37575735697eda6c1d); + tempvar res = res * point + (0xb04ac19a9f1483b8ee3b763be73814c9621fb3d23e6d874d9093d999d3d4eb); + tempvar res = res * point + (0x4f4df07e55d3ebf0ed955bd9f7c34de001f09a92c1ead17b0c1a485d48a4329); + tempvar res = res * point + (0x1522043741ba933948d7298114b71322258a3d4e7cf2496590c35683dbe2a7c); + tempvar res = res * point + (0xb489643a1aa2c181b4739d45582e2576a6f9bd51c81d300ebdc3a58b79bb2); + tempvar res = res * point + (0x4db70c63a1dac4e5ddde15e3626d009683aa8ea14face2c3fdb6ec97c8a86a); + tempvar res = res * point + (0x309bca858a0f9fc5a468a57981c9c6b7c79636b1f31284938d1c6a21f006a33); + tempvar res = res * point + (0x625a1fce22a9fb7717107b137a0f5ea4ca059008f5cc6fdfb5cb5bb1734bd17); + tempvar res = res * point + (0x6ae2e00f7827692b0d20f483d3c71594f61d50846b52abfee39f6697513c0d0); + tempvar res = res * point + (0x4b5acbaa0f7e360885677439654649256829cdd6d4a6c7ffa904a0683fb5fe7); + tempvar res = res * point + (0x66a63b8ed2255586855fb30333ce0e2ff4eb2b4cd5d2125d8d20cd3fcfc1d04); + tempvar res = res * point + (0x55351e9d60f58241736330de978242e4e40c4209a7879d7ae3823c148abd82a); + tempvar res = res * point + (0x588747248358bf8bdbd990996cb43468c89909cad0f8230cc939538b9b331df); + tempvar res = res * point + (0x67801dffe217a1a64e0b12f405157af52025266fcc391fddaebf3b6c7ab79a9); + tempvar res = res * point + (0x411556b9c89186a2f9f79e55d045295790b28af97fab64e77777e3828532be5); + tempvar res = res * point + (0x5c01501e6a113ccca7cc9c723b1fad6ba60ec5b0a85b7d09c72120d3f733bd5); + tempvar res = res * point + (0x5b0d578cb7aa59ba02b0bb894848b745440c0cf562c2e635312c9bfc305e169); + tempvar res = res * point + (0x3013a9c6094ab0086b1397621f93ac07bf45574ea26b09d3e4587afffe995ca); + tempvar res = res * point + (0x7d9c679179dfab605ca04e1993b37ddff490c440665005698a47c442a1cc10c); + tempvar res = res * point + (0x4f6e24500755d20ec5f28480a41a0cf23baa1aa24202382e9f4ec8ec6d7596); + tempvar res = res * point + (0x4e0a6e0c26f85c74373782bd2924f3bc0f6b4a2914c4f7f8850a79eab580566); + tempvar res = res * point + (0x6caac68bec6ce4eff4f74c1f33dbc027165cc02cec8f69e9470ff99c0b132c3); + tempvar res = res * point + (0x1c867fa9ae031469be012c4f201ed3ad56573a22891351012ad1f7d300361f0); + tempvar res = res * point + (0x1761abb092f6c4e3eda770480fb4ab095e786bc3f1b1f960bc4c95232308b3a); + tempvar res = res * point + (0x4a35c4582c91999a39b553248bf2a39ae5825204085a9e98bd6ddab3bfcc0a4); + tempvar res = res * point + (0x6a4efc048a81614dede6c4f6181253e84f20d4a4f95f973147ee3fcd72077fa); + tempvar res = res * point + (0x65c14f7de75359a40c5f244f78b2920b61087fdbbf59aa507644d94f5bd210); + tempvar res = res * point + (0x9be8b219ca1684dfbef720a3e9f034b319e2d233aed85063924fc60aedf20e); + tempvar res = res * point + (0x7352e8793ed3f6283e492544b2944d6fea715980d8884f6821574d36868b0c7); + tempvar res = res * point + (0x65c04013accf25a2cd1d9eb98689d71694ffb20dced009df5b9af167602b4c2); + tempvar res = res * point + (0x679bf3101f8b2112eefab47d7372f0297507511c7cceb4478f2baf0541740f5); + tempvar res = res * point + (0x162e6e8431b7280f8401ca08922c5452c7237132efe3a481a71b5c97183e9d0); + tempvar res = res * point + (0xd9da926adbb5ffa493c54223f97fa1b0d141129d8736bc4f5768426c7e82a2); + tempvar res = res * point + (0x711628cee8d673863e18f058cf82551ca8351486b9b210873b4e18447e11408); + tempvar res = res * point + (0x6f6131c193cd7b3fdb4d0848df70474ba9e80529097311cd7c13e322205a1c0); + tempvar res = res * point + (0x2512f776d1b3d212be7c2adce1cfa083d1b2b9af1c6f3cc424b266bfa19aa06); + tempvar res = res * point + (0x400330fb079fb4cc8671ea9a996de8f5442f20b9b9a3bc9df8b81e01506c5ad); + tempvar res = res * point + (0x40cfb729788e16fa80b7d937f0088157d18ff2cf7c79b748d0e150c896d348f); + tempvar res = res * point + (0x59786091e2d824242c7aa5dde34ffbac99f6a9a1aa5ecc8a395aa13e8aa55af); + tempvar res = res * point + (0x4adf53e64235d5327822ee3e584674af053e496c5d92a6c8c43e1e8e7d327fb); + tempvar res = res * point + (0xfe9d827d7e6387c7228d92f78574add4ceddddac1fbe71dec1258220c08402); + tempvar res = res * point + (0x37f1342e071f8a087c1405692443305d28d4c11b84d92bd7dedc563fc3ad329); + tempvar res = res * point + (0x74a39339d1d708a9ea407f03d8b0e5ab103c3251596258b78be1bd97ad06915); + tempvar res = res * point + (0x152c16cce8c1c782287b8908a790014fe3c51c57cefaef63e2c8dae5a7a5daa); + tempvar res = res * point + (0x5b32dadeb15d554f39f227de4ad20600eea4b763fa4c90ffa1a41812ae43479); + tempvar res = res * point + (0x3b4b0f9b88e16446a2de79c1d8c34865d5d6e581f08bbbc652ce67d8ac1d952); + tempvar res = res * point + (0x44041800e20fa7a15dd9274ea8283b09c30a0d900d9c165217004e669b39d99); + tempvar res = res * point + (0x5609324fa7ef5213591c8d36c59dd42df8f5f26f84468bb84f843707a5c9c48); + tempvar res = res * point + (0x6235547369b594514d2fa1ca9b06fd25f9d2764fe8b099c7d9671f542a01d46); + tempvar res = res * point + (0x614509129cebd380f416c4c9c7127ee7b53d878860905f047ad722a82147236); + tempvar res = res * point + (0x4f847058896f8e2727ef3b4577e62d5f6a729696b8705fe217b97c73fd1afee); + tempvar res = res * point + (0xfee20b19c4437f06eeffccb05b88c4e236d18f8e3518ba124ab4eec844c496); + tempvar res = res * point + (0x5897638208b8e9509d1128c29af87cf30c57942d47016819435b373c0a309d7); + tempvar res = res * point + (0x1fb19890707fa2e617de7dcea9ad35ce9960009f1e38aa2629c66fa5b8d5d19); + tempvar res = res * point + (0x45fb29b3ac673e9f525332c8bad73d76521985406fc09398078b30339c857b5); + tempvar res = res * point + (0x528d041bf152aa3a0205430412a196619b68c81d7a706fea0fc090e0cc6a105); + tempvar res = res * point + (0x1e149d42cd477212ab7f01fe40f76858f09ce2bdfc397df635ed8a453714e7e); + tempvar res = res * point + (0x75f781602ada44803c0ca4bc8c1bd5064700762d18c309a2b9059dcd8c3dcca); + tempvar res = res * point + (0x1571843ced13a8d342b63c63abc4b83d357eb286af04380edd1eaefcef3f1f8); + tempvar res = res * point + (0x304103a8d35f43cf87d50682e86e473fffd71d13e0c783e596a59a62b06402d); + tempvar res = res * point + (0x2849ac77a2f5398eef51aeb8312dcef8b347b690728d4eb835bf4670301e6e7); + tempvar res = res * point + (0x52a36a173c7ebc96cfc55bda4bbc73bc349657d39ebe096725e9cc4bff01def); + tempvar res = res * point + (0x43e371660fff35e52cd5dc08c9c347d8f7c64a116375d0e6e3ad3512d85a99a); + tempvar res = res * point + (0x76594f29261e2aa9cf4a90b58b0f79c2aaa99d63c4ff64b4806cb8cfb0df316); + tempvar res = res * point + (0x4cbae4979c7a1313c2d0f68b21f5734ec83f9e1a88c78b3976a6ef84a1b6dbd); + tempvar res = res * point + (0x76702a08064b5768ae2979aca07322782191172276f1bcfbc14cbaa3e758dc); + tempvar res = res * point + (0x64f8c462b308a1337bca235add2482fdc3607507b2c9c0f91b9187f5676303); + tempvar res = res * point + (0x2ef5951aae064a7357b1e4ed49f05f17f778f2e8735f8d17b5cfb82faf3b848); + tempvar res = res * point + (0x66e2651e6f5758c334d1c1451d563b2df07b424b5d0125c739ada959479890e); + tempvar res = res * point + (0xb3dd17f46d6b12bf4e5db184d6962c156bef94f9f73861e34d88503fbc517a); + tempvar res = res * point + (0x19412ccd078bf5665579cbd16035a251e08f40722eca4452eedb31732488468); + tempvar res = res * point + (0x719df2a50d9c3f2eb3f0336665f2980e432191e21fc49f488854b8352fd94fe); + tempvar res = res * point + (0x459f095ba3b70f76e493c6afe2d4b6eebd21343f74bfe3390868612fc250fdc); + tempvar res = res * point + (0xdef6a0b2b71d97a59c674c052fe23f7d000a334e180b0793b6974fe29a64c3); + tempvar res = res * point + (0x74e503d57e49daf6939077c0b4a4d68e66bc2425ce53b01b48f146295476401); + tempvar res = res * point + (0xd49f196e60ebea0eb13d85f05cffedff32477e83129bad30bd9dd555755429); + tempvar res = res * point + (0x298215f335fb63a11d31958d950d95c909bb94e144c113cc4ecc08488469097); + tempvar res = res * point + (0x6232d26f420f9b4f119e64762927b5e8a21192575b200081b0545ad4e9a2c25); + tempvar res = res * point + (0x2b51d7f94ec71f3a8e3e20d766a4a7f13d08d758a686ff86dbda48026c7ec3d); + tempvar res = res * point + (0x45fb08bc21969d5ca9b1ec473cc92a4ad911de8b0607ddc12b9ee98c286d37f); + tempvar res = res * point + (0x70c0f7da90cd889d8df06f9774de8a9a20c88e86753506c7afd0e1f6ef15e76); + tempvar res = res * point + (0x1b16d94e84ffd3ad61286f5a79d5a6f7b5b5dd6442aea9013ad21467bf1281d); + tempvar res = res * point + (0x6a81925732161d4e5dc61ed6a10726027fa66d892aabbf46a477f4455072c02); + tempvar res = res * point + (0x13ed29a84c4875ac188521bc40e9258e03d83c9ceb8716c6fbeed065a5df73b); + tempvar res = res * point + (0x184ee38f80fa532983fa248c14c0220c2a5691836e899a5c9b83c975b03608f); + tempvar res = res * point + (0x65f4a97d2b1c90582859966540e839ac2d62ad2ea960aa2af36776b2d07ce34); + tempvar res = res * point + (0xe00ac968fe5a147fef45fbd626c540a194ec3dfb2c1cca7938e037349d4f34); + tempvar res = res * point + (0x96935be4e41797417259166181bb646a619ef95cc8978ffeca81d141d062f7); + tempvar res = res * point + (0x61c61341c83517cb7d112a76864271492473e04130ce4ce23331f7300bd8c89); + tempvar res = res * point + (0x73eba0e9e52c3a93ab6dce26d5858b2d699d8401b2c43253616b5701aa803c5); + tempvar res = res * point + (0x77434256511acfd027b41e03a571a9f56b0442dc675c139a2e1476fe716102c); + tempvar res = res * point + (0x325f10662fc8bd38e591b0e8caa47b3fff46703656b2c5863d39c150d298fc8); + tempvar res = res * point + (0x3c835256339330b1c94cad78cfefda36a949b9c8553d918f3d8547cd1805ac5); + tempvar res = res * point + (0x7340540d0c9f9dd2c1142f03f408ab977afc7371934c62259fdd29f0652f8d0); + tempvar res = res * point + (0x17d8ab17e403b1925b40206c11f8a6a29ed08217e1ef303906ecb354fdda1f3); + tempvar res = res * point + (0x78562cbfb984ebea085472a1b004dbf86e7d99f4809a5020969246a84a9d165); + tempvar res = res * point + (0x60c93d3dac2628ad796e1dc80bc0796d054c991ea23094d699bffb43a630add); + tempvar res = res * point + (0x72bafd4641e6928ca65cb48e8001ee077944201f70d5bed524c69b709410d3e); + tempvar res = res * point + (0x6321e76192ba31cc63bf7c526c8ebbf4df5b705f01e4151068ee3dd658aa674); + tempvar res = res * point + (0x7caaf4f7b073af26c036d8bab5c74fc3f752f9ecc01041787e9ddf773596189); + tempvar res = res * point + (0x66ada08fe725f364ca32c1055e1ab1216967856d6cd8762dd4ea915c2ed40e9); + tempvar res = res * point + (0x5b6477413bac2f0d370c0cdcdec4cea10fd322fbcd7b202d4ccbeb0581fd34f); + tempvar res = res * point + (0x35c99bed31baaf7833ca759a9bea792965a87b42171259ac51b00d872d581fb); + tempvar res = res * point + (0x7ce96f5a3261a977f04ff70ef416a3d5c165100d19f551a6ac514e4d00fb18e); + tempvar res = res * point + (0x1c933d3449f6241d0f9d547db9e708fc2ee3e0598be5f87b675fb6736a15c39); + tempvar res = res * point + (0x687aac173963fe1e01f9e0d50eba0e95e1e8783eb21c0f6c1f45cd42408198d); + tempvar res = res * point + (0x2f2f5447e274a20d9d60615f83a18b2a4db300d5e199d7c8c6c6cfb754e8cbf); + tempvar res = res * point + (0x91cd6c3b8ddd8954a44e8a9cf6f7f183af8e6226849f05e6e6ebda2409e042); + tempvar res = res * point + (0x282ad11848887c771898b5a32ac6ca14cc2510830454aa8e194975e308fe042); + tempvar res = res * point + (0x5455d2de2d7570fbeeb431a9a21187ecc049874b64a227bb543aab4af16e27b); + tempvar res = res * point + (0x2fcabf82bfd2529eac169a520cbdb2a0f8c205c5a9b1f1ac69bd3a44b25faa9); + tempvar res = res * point + (0x33d4fbf9dae7a87cc13db3c95ed3976b50113f072e56a13e675e4af241bb864); + tempvar res = res * point + (0x3cbf28927ecbda443555c9d51f40c294fb6688a17812cb0c85fb6501cdc0709); + tempvar res = res * point + (0x4fefb86cfccbbea031f15d85033f10f92f2b6b689153e305bfa8821935979c3); + tempvar res = res * point + (0x63f4ad31c4d59ee741b1b0ac99e022959df079b5b033ec7a1ecd3b4797f94d9); + tempvar res = res * point + (0x6c74e3b74559e12949b8c3b55369b2d275b2920b4442c536d63f91debd61499); + tempvar res = res * point + (0x45a5b88744e83d901f33da0d0de869381e7a125a6d8bd104cf72ded013ea4c6); + tempvar res = res * point + (0x11243de8b4214dc3220693acfaa6b626cfc3b8c812140779af9b72dfb1b92f1); + tempvar res = res * point + (0x123f50f65a68168d6b43c464270479801376ff6979b94f60252a47d9d7d34d2); + tempvar res = res * point + (0x25446fd382a1b0f5350b91290b2dc35a6dabaf215d53cbb32d1732fc6ebfffb); + tempvar res = res * point + (0x160d7d587f3a17673bf04189e0062c7bab764fb54ebd0f042fec72f953a91da); + tempvar res = res * point + (0x1e0fcefcc1d1c5a69e81c4fdfe7de04d95b53c162a3b64b5956df8e59e1b93b); + tempvar res = res * point + (0x1925470cee5111eb991ccc8b0412be603c0b8df342d7b186a3aaeddae103bf3); + tempvar res = res * point + (0x2848af5bb20ab624881dc9244ea18b1d6939e14270714253a896e57cb0f63ea); + tempvar res = res * point + (0x6c2a98464d6eb4038d55b57632bb283ab091eac255fd6797df41612cfe3ea1b); + tempvar res = res * point + (0x31563499de399383464854a8679e0b073513c5bc46cdcc2a2107f00677e6356); + tempvar res = res * point + (0x6da4d6fb1e6b2f1b42910a9dcc4702912002d7d36ac7100e19c7f298c7948a8); + tempvar res = res * point + (0x3d368784067d457e43cb63b3f526e721fab153949b090a99a128c5744fab4a2); + tempvar res = res * point + (0x266b63657dbde655f034c014a8fb73b77138b52eb0e17eacbf402bb90305f10); + tempvar res = res * point + (0x179f2a40de3db251b95a60431e7cfe2dfa48dc8654bbf81add938e9f2f6725c); + tempvar res = res * point + (0x1118c09adef545b07e209d88b0a645673a103c9e71e8f671e74c84abf1a2a2d); + tempvar res = res * point + (0x6ebb7c4ee2d4212e6d7cea8c16f97c935f3bbbc2f400c9a738f1ebd37eec6ee); + tempvar res = res * point + (0x41d1ca4f756c80f197ba1635314a3dc756f9d8d9406af16538643d3e1021bd7); + tempvar res = res * point + (0x3129daa367a01a45fe3f0ccde215371f59c5643bfad33f4269a6478c8c8b7f8); + tempvar res = res * point + (0x1fefe6ebd886640df863e5f5c25e9b42fbc10adfa7ef07d1fda0eabafa60a6e); + tempvar res = res * point + (0x37e79bd72d714d3de7ed2b1ba79e345f75646bf67efd8ea3050ddb357802a3c); + tempvar res = res * point + (0x24eb6fb4dbac687e35d4168b970db6e7dc76c4c886dce0d4bad2e6544b8e6c6); + tempvar res = res * point + (0x6508b5fcc13191197f91407d5b1b21d321b7f311e55ede9ab8a6975308dcee); + tempvar res = res * point + (0x43e46c5f1cf3b5cac9722eeee991cbcf53af25a4a355a91ea9b8a4d4754d908); + tempvar res = res * point + (0x7393709fd08807a84ca44526a2b8ec97bce5aad1adf00560d04110de6d9eda8); + tempvar res = res * point + (0x690c8328ca161c48f3f8f37570e42095d1a0d9e101b3ec0ddc91426fc22facb); + tempvar res = res * point + (0x41354bad5cbef57b0e7eacebef8f0176f3b70992ea5a418f502242acbc4a1ff); + tempvar res = res * point + (0x3475f32b5bea9dbd19ec199ef34e531b696cac0461e644ffb41a5e99d0735fb); + tempvar res = res * point + (0x33cfe02e240929353f193c6d3387f1117d04f116889f38d9a196abdf986e48a); + tempvar res = res * point + (0x33e7ba5f7e56065e3f8b091578e8e7a7b118116de47237fa5a97e44e97b7f69); + tempvar res = res * point + (0x5526001b8a8c2c6209e40b5d380836bcf63db4ef85c25fd5b72d749b0bd36de); + tempvar res = res * point + (0x64028a3945aa2866db68b304dd0d83d75ed0ba5c2f9d0b47e80d11d8da6526d); + tempvar res = res * point + (0x378113f110b2404e7d185e920249519ded728cb1027fa8cc2843a588886a7ed); + tempvar res = res * point + (0x5f4fd7854cf7b89a3983da1a39839d85c7331c3353b0a8cd218f7f4e1f780c); + tempvar res = res * point + (0x6467afeee167ea95feb4a85c48fabb2c7067de57acd5098692855189e21c57e); + tempvar res = res * point + (0x1e4bf5029043367487394808d7ee7df5ad1ad1da2c4710a1b2444ffde106f2a); + tempvar res = res * point + (0x684a30c1084e8edf34a77bf8848fd2098459f5461bdf3352faf9c8801435b6); + tempvar res = res * point + (0xe3f2bdc2de2b623c56390eb0044adb980766ae1a58d775e003c39724d1d6f7); + tempvar res = res * point + (0x62dae59d425684ef78c1829e0454cd5e76f5d322ea8cb5ae5e911f545beeee1); + tempvar res = res * point + (0x5761ff2e0a250691a66dc36d372afbd6a8016726efe0c418d7899d60d26bde6); + tempvar res = res * point + (0x4dc27c76881bb820eb74814d1b69825e9048b1a3b064e603cca4bd4814b2243); + tempvar res = res * point + (0x5a15d718a45959d16dd6e0b98badbb086e2a9741ac04086f078bc6951506e05); + tempvar res = res * point + (0x23cf69cfd7730dd096fd485b2d8bdfcd89ca6004689bcbcacbeff288f18ff9b); + tempvar res = res * point + (0x4d6c233f7bf3ade219a8e3a89e12d05beb7faccbfa811ebd930c391523f7b4); + tempvar res = res * point + (0x5a347e7937c7a178952905f499babbeda500a820ccfdf7f3a99589687a623e7); + tempvar res = res * point + (0x43394095e27ddb7825c0671833a6ac9784f31626914c902c225f05ce42bbd9f); + tempvar res = res * point + (0x66d91bcc591c880303ee4695475e8a8e402926f0c01ade8880c7b03c76998ee); + tempvar res = res * point + (0x3348152349370ec1c4d753735ef255b50e54aa9a432f48a121c39b8887827e0); + tempvar res = res * point + (0xfa17235a82497674de45bfa59e61a329b2d0e63eb18ab9b74aa46783e04c81); + tempvar res = res * point + (0x45ffc1ad229bf52b2531afadd1c5ba120c57b34def87149880d1e5cb6c5391c); + tempvar res = res * point + (0x37f5f6b25ee428e91e886127b961856d9ebc52740ceb763baa7e71371b84364); + tempvar res = res * point + (0x58281d625ddb432caef06e485bc2b74cc077aea9ba5072198e76542f0c69dd0); + tempvar res = res * point + (0x3e35aebb590266ea1fdd8198cf3c23c77731dddd95d488a9d9f9837e3bd0f6f); + tempvar res = res * point + (0x2850977abc89355540e8abb804da7805ef88b12f40cbd9158ef330b767901eb); + tempvar res = res * point + (0x72fb3298da88c470a2f93a391063810be01078c8375183b57a024c223f2f428); + tempvar res = res * point + (0x53f792c81d26c122898d70ed7fcfd8f02a8f5a9ec8b9868fc4490d3a46b4e8e); + tempvar res = res * point + (0xa7da81afc9f3c93366b6e161b1fc7a497d6c770fb140bf4b64e5fc707cd3d3); + tempvar res = res * point + (0x26601a459facdd83458b56099975d2b7dbbc431d41b53f5dd6ca2901dfaacfe); + tempvar res = res * point + (0x4a048ce90e3a1eeedd4932ff37760fd8b1dc995aff7107bd66318652efd1032); + tempvar res = res * point + (0x287fed27ab81e5f721d2bd5aab0e69f53e94ce5dccc35c2dcc88e12465fadc2); + tempvar res = res * point + (0x414215fbcef7f5af60f320e67a845e4a17b0a0eca39b4e18ba89fbe8a189491); + tempvar res = res * point + (0x208f0c2f5a114b2342f51e919e4fe44c2a42cd06382d9edc4ef58939b249bab); + tempvar res = res * point + (0x5726e3dee7bbc5e5b4f3ad65f0fb17699efb5936d50ad380785f2b10fe8953b); + tempvar res = res * point + (0x6fa8562db8de26797e9c9905aa769e4881304b4f20cb64d718d271c182f44fc); + tempvar res = res * point + (0x2a60396cf912573be2837653283a23702037f614e33e1c6fe2834eee9a1c7a6); + tempvar res = res * point + (0x5b6b3213744858ad659c4c07c9220380d63c01f680986191c8776eb703661c3); + tempvar res = res * point + (0x709a47e72cda4fdf428bb9784f02f77c700086755d4bdb5b229d1b80a2ea4e5); + tempvar res = res * point + (0x75e9c821cdd2e754759306283aa4af8bdbb0ed31f4e978dc550141fd10da6be); + tempvar res = res * point + (0x2adfa41f72ba3b61b9dfa6f017b19682b0b0f8cd86be3d37374aba3ce990a55); + tempvar res = res * point + (0x6e313bf82c34d3af1e7fc14d811dde163ca6e57accbe476875e4a967da00b8); + tempvar res = res * point + (0x78516acc9d32f4e54f8925865c91f70b210f4ebc7533fc624685b3d5daa7b18); + tempvar res = res * point + (0x3b8cca1c3fb2b26b7e206802d52d2ed1c725b8f95407e3ef295a7dd9ee0d45e); + tempvar res = res * point + (0x287ef69d6f69ab853e4f0d24b22e4c15169d12c41706dbeede9fb49c61179c4); + tempvar res = res * point + (0x7c84837e6872bea4f0448183cecd6bb24a8574456ab91173b04b9423be8a64b); + tempvar res = res * point + (0x78f890541865c12169233143f47a056a91dbd18222c5d31bfb2db19162c204c); + tempvar res = res * point + (0x46cbc37eff4616daaa86160d5690f5473e24171441e29705ae564223a351c23); + tempvar res = res * point + (0x309f9698e38823c05e56d073d83ea551bfa80ace08e749aa4c83031a22360c2); + tempvar res = res * point + (0x1a2cd41155bbb7ceee94dbd01bd876140b1698f03b2ff8f8de3ba45b4ea14e); + tempvar res = res * point + (0x10699899068f86fa3843b06693288630b9ac4b87be7b3726fdba32b41caac2b); + tempvar res = res * point + (0x2762878a5f6665bee609c26e750cd886e239c31caf1508d5a2a185b58576b77); + tempvar res = res * point + (0x57f7a737e643bd859d8a53e1b621c09be89fcca7b96f8e42333e46426f26a20); + tempvar res = res * point + (0x7239c3b89513196e3cae91f8df8bd79f08033061ba63c089bd764644907479e); + tempvar res = res * point + (0x38cb4f77410e9a33306f8a4b92b6f76bf239ba44e0ef45dab0bfcb75dfe4141); + tempvar res = res * point + (0x382114ce9d712af864a253d29471a436b83ee4f7b8ae3fe19ec3ab315e18d8a); + tempvar res = res * point + (0x51ceb130c1908fdcfa6896756241fca8f74ab172d98c76facb7b8b931fa8812); + tempvar res = res * point + (0x4f6b918e40f8022d2bda8d53214e8fd84743bc2280231d3ae772844bbcd1aac); + tempvar res = res * point + (0x2d9af4ef0d50851ae1b0cdab3587a71728eaaa4e56e67803c5ff9126e722696); + tempvar res = res * point + (0x4640cb2cbc73d7c9fd2a1783122cb5ee8c68e7c04b0b647d43a35cd4961e4ca); + tempvar res = res * point + (0x1b3104591a23f262051182209c0f73caa30e8631fc4413a5bf97c9d51a70abb); + tempvar res = res * point + (0x2103ea7ff918748c4325a992c561b551b70fa9d97e48a52b3c157799d213693); + tempvar res = res * point + (0x69fb58adef701279dddeff71e1832aea01ae10a5128a9f744a5a945b5fff200); + tempvar res = res * point + (0x375e99f4993200342e6f6ad713711052d518e5dac24681b3999878bbad627d); + tempvar res = res * point + (0xe051fab79733dd773d13f5bec04b1c20252df512d937f6b7352e4c4fa49cb); + tempvar res = res * point + (0x5d72a87fe662c05530c3ec822f925a10c121a44c4adecf24850fa2442cb4abb); + tempvar res = res * point + (0x6f2a9f716b1fa27c35675a57273feb79ffce02286bcb1e253a8e126c2cea357); + tempvar res = res * point + (0x9b419422a2083bf174263351640e009b56d6e2278552f9e7ee6a6004d45524); + tempvar res = res * point + (0x3dee84f905f6a06940783bc3f322a0fc22a984dd244d00a85ea3a4295558377); + tempvar res = res * point + (0x3dbd68c7c5945f48515d975002a1caf1c491c6743f151df31f95c5870c90fb3); + tempvar res = res * point + (0x7d52bb08c1d72a66c3e5c60f6742675ac788ec8b4f2178ff9990a04d22c076e); + tempvar res = res * point + (0x107c8fc81a96a3c13d1ddf04b8bcce0450610c2ee6c127e0f47ce2ed2fa0613); + tempvar res = res * point + (0x6d8f39b47e79d44503aa87a3fdf101b055f89c663bd7ec377d175280f3f8db9); + tempvar res = res * point + (0x6d5a755e91ed732dcf8afd32eac3b4875843bb116430a966ef88f17aad54c16); + tempvar res = res * point + (0x64035ce25716c9c7675ecce40d3cfb65ce3121439e10367fe29f2742cc02d85); + tempvar res = res * point + (0x3e44a162d501fc521774c75994f4b55eb85878f5e867cacb75c7ff0b7efe941); + tempvar res = res * point + (0x1b2441db55dbd9b87c45b1afba238ed28d1f2dfe9725d9a4cae3a45e3d59b63); + tempvar res = res * point + (0x8b54ed775cf8f3dd5b54fcdea07e2bcefae323f6212b8f54877a60e1f8026f); + tempvar res = res * point + (0x338c001d0c722d793cc14219415d61c52de28d33ab8bfe5dd31674784f2b568); + tempvar res = res * point + (0x4ea62ac09b98dcc34b5437f6bdb4fb9a681dac12d1ca7090011c73259dcef4b); + tempvar res = res * point + (0x6a226b1dabca8ff2fbb52f0adcf4267a47e0eed089774157f318b507361a0b8); + tempvar res = res * point + (0x6ba0329f670df105c31eb665f3b6f243ab5de7ed8aa59ce9b0683e6bdfd9019); + tempvar res = res * point + (0x77f62cb2f9db71ba7a9913be0a434ca045a26704681af5353b7c7860be6e774); + tempvar res = res * point + (0x770018fe3435297b82b391a3bd2d09151dd3949545d0ef111cdf9fece9f389c); + tempvar res = res * point + (0x4279b49402fada9fcb602f909bc138c3547baf384dfef9594e2fa488cfdf8b8); + tempvar res = res * point + (0x4dabf5afe371cde17b9fa6c54c1b38d603f345c58d4f66e06fedd8948b402b0); + tempvar res = res * point + (0x15296a7d071a85f1358bb157d5e62b18a11e189415c16f594a18be7276ed2c7); + tempvar res = res * point + (0x79708fbce6bbe1c862e988648dd25347d60c9e0981540dd81ccaf78054a12f8); + tempvar res = res * point + (0x209866f9b8d946508db2df8eb9d30f65ede2c99ec8deb2e5a1b7093e9a62416); + tempvar res = res * point + (0x4ab0da9c66ca2588350bdb85cc745b4c5e7226cf7c4fb69708cddf6e8145f29); + tempvar res = res * point + (0x54578b117a58f5beb0d511ba42110c4696f4fec165acfbbde208a4705045fc0); + tempvar res = res * point + (0x55c9e37b0208bfbbb61e5e0e05c72111421b24b45ea53d3ddfad1cdfd243ff0); + tempvar res = res * point + (0x5889b4a99416f2f954450c60492129c5f7a36f875a56dde5188318e88d6032a); + tempvar res = res * point + (0x5919f2392a53f9b230145d1b5e6da28165dd1d8cc7d28d3310a805ebee721fd); + tempvar res = res * point + (0x43e49d0d9bfd165776eeab9118ea672c24a055a700e35a04426abe1b236506b); + tempvar res = res * point + (0x40e394412097f7c06183ae2997707604273b0a4ec1add0030bd7e115c20ca70); + tempvar res = res * point + (0x6337d741eb226911e37cc48087126cdd89f00941523cda2fa5e965dc4fa25e4); + tempvar res = res * point + (0x64592b7d9a6a922f5cf5f74c56e167ec000436a6b3caec299bcefea25e5fdd1); + tempvar res = res * point + (0x1d608ffab983d8aa17db9385433abb0025c77e27357285448c4ff6a8438570a); + tempvar res = res * point + (0x333793406d06dad0406a859ea2c203aff33e3cd906d6f04aabb0dffbabbc9c); + tempvar res = res * point + (0x3b5f2338d066753b2507a39884bddc2d0c5bef88e4bc3e79288331afe9a6234); + tempvar res = res * point + (0x3fa0ff20cc486bd0b43f96826c66b070a6f6e3df3359ebd2970661f9c679e2e); + tempvar res = res * point + (0x62cea6c83442875da8b98083d8bb18bce5d3d431a3301afc635600578b33506); + tempvar res = res * point + (0x4835c753d4b5059c1b4186516851f562e63e348f8810714cc393be9810a1de8); + tempvar res = res * point + (0xc230c4af49117fa614b1d4d74ef462211a5d55537ac71564ace080dd4b325); + tempvar res = res * point + (0x1917c10cc63bc9f43116c3688542cd867e1a84ce0d3e58dfb0c11c4b0828748); + tempvar res = res * point + (0x13c6580dce66b35fd24183e1635fb6008a6deb6cb507bf48d531273d5b4c2e9); + tempvar res = res * point + (0x6c6dbd58b8657f8588bae8a4d990e6f9b0525af4eabe87512c5f6a655c92028); + tempvar res = res * point + (0x59daeadc724e9c227258a56b000c6a613db617da41bbeb694521c86323c93b); + tempvar res = res * point + (0xead9e7eac2f6c388de28561955e6009f9f1ed098f70516f2bda28597c9ee03); + tempvar res = res * point + (0x54600ac31d014f7241c14e5aedefdc72b839cb0e98b84aa13f031316af48648); + tempvar res = res * point + (0x5370b38ea84ca67c75ab50a4cb8f23f4017175a98b23df9e1c92f92c279e169); + tempvar res = res * point + (0x23ae2f35a2da5ff92426d59ce066e29a525ee1207de1c370023975b4403ac6d); + tempvar res = res * point + (0x5952b292edb661874ff2d3482fb968149f09982bd7a194d2b502ee3dd32927b); + tempvar res = res * point + (0x30c7ab8fe6b61574f49c3d76b3173f76816f31beb33097d425a94beab6caaa2); + tempvar res = res * point + (0x4dbc9ceabbf1c8d5c679cf80d9bfc26ab696135792e83061e98b9c36ae6a4a0); + tempvar res = res * point + (0x3f1908469233dcf5c433790cb3574261ed6debca41fb55b912be7cf34adc187); + tempvar res = res * point + (0x51778c6b175ce13e994dc1604dac3b901990cbae0246b2cec2aecbe96dd2006); + tempvar res = res * point + (0x6a91b3677713dc15cd110c71cb8e174c8ebd8d7df1a1b4120bb4b6b1683ad5c); + tempvar res = res * point + (0x3cfdc71122fdfc7807b2efe35fb6c7691985d2727401eb8a8132d0e0df3cdd6); + tempvar res = res * point + (0x5099f832fdec91fd27af0d221e009ed6770227d63bcee6e1802cdd122751260); + tempvar res = res * point + (0x1793fa490096ddd67530e29cb3e8e9632d1885815be3f9d96375aa5946f511); + tempvar res = res * point + (0x6d4bd8c4aa4a530d965180c18062d6bc440e6e70cbf0836d6af11235c7fde2d); + tempvar res = res * point + (0x3d7587a79c4ae9c24934a10a9c1398c04f3915fb6889b72b361505a85db2b69); + tempvar res = res * point + (0x39007630deec4a6eaf806518c109f4aff9cbfb8826d86f301e562ec560ff89); + tempvar res = res * point + (0x51e4a728ecd68dc30e4a1b5867a1022af5808edafc3cb12d26d43b495528f18); + tempvar res = res * point + (0x7f921548c686f600b302290f692a66e9ececa142f691f9129c7d8bd2a06803f); + tempvar res = res * point + (0x42cdd4f6ecbfd891fedb9ecb6d320f6adafdb274ee15cc11ef4c0436a4e9afb); + tempvar res = res * point + (0x755d64434e4e4233388c34a90438764c568353cfde4311021b45e0f369b0db3); + tempvar res = res * point + (0x4b5e107dbcd02c0dbef4d3a77d66386a864d31109d0d0392847c8919d926fbe); + tempvar res = res * point + (0x373a1f2fbe36dae9a5f2c2b35febe59b53869e1678c8da23bd9e92c3c2ac0a7); + tempvar res = res * point + (0x53bad76d22e1525dcec248b73438d6f444caf75794c26144e26803fe2bc7736); + tempvar res = res * point + (0xaeb135e456ad66bb5bb2b91a4aa429915f6f9951aa15bba78576744a698016); + tempvar res = res * point + (0x111d440a13cab69043e1072b61c1736cf3901941b4c57d7602b8effa7e74b3c); + tempvar res = res * point + (0x5fb8d87e82c3547e32ce316e4439d1aaf3723e4a906c91533ba8dd9631f1661); + tempvar res = res * point + (0x1426a2050d240104b5c07a9cdaf7fce03c2accadb0ce98344ecb4942c434db); + tempvar res = res * point + (0x929eaf221c110efdaa57970581428d66d5866fb9547aab76e89e8971efc91b); + tempvar res = res * point + (0xcb3220da969b95193a25d1d4d76d1cd1ec596040a7b31da7f64164809bdc4); + tempvar res = res * point + (0x3c3ea2cbc8ce544c6c98ad9053cb2c35326f4e502214e5f72c7951474b5a84c); + tempvar res = res * point + (0x68892b41018bc73b541800d91f0bb2a8cd9fcfee8be13bacbaf7dff7aecdcd4); + tempvar res = res * point + (0x2a652d2592f5cc1197a206db79d06e3b74a55b1d4ec03c516a6957e87345cbf); + tempvar res = res * point + (0x1e0c96f0b836d1e2df4e4063d56b78f38f2ad16040d61855b0f664c066d130c); + tempvar res = res * point + (0x65d167bcce20a40b78583e4dcf7e3f44663e0c595e18f48f83ea4230b207047); + tempvar res = res * point + (0x1668b919fcdf512b5683880ed048853e00f456adde728427fcde63ac9f59611); + tempvar res = res * point + (0x1489d6012d4c9701b63f3610034fb5bfca185c7b01222907781eb104e031097); + tempvar res = res * point + (0x57ad5370b26ea1478f3fa0346d2e390e90feda8022c9820813d9ddd0f36e7ba); + tempvar res = res * point + (0x522f83a59f717f37b235c05338a02630ad83c3ed307838f6e795f9705cbc849); + tempvar res = res * point + (0xb6bca44a12ba7914e575f83cf8b9b8bcd4780622806901dcb9530ff9a454f8); + tempvar res = res * point + (0x6fb8324456f1dc4b423220d18d40de524a27dc4f35e4c780a042f6edc95f97d); + tempvar res = res * point + (0x2039c72c1c7c134fb300e82b104394f54a5b7ffe6f7f00e7c3e4ca6640841a9); + tempvar res = res * point + (0x614a280377b9dc732773d969da5ddd8cc125262313eb7b2bd38b7668cdf00b4); + tempvar res = res * point + (0x243a084aa8c82348102320b0ad19ede41b6bd7ffb3a7041339a13f34f6b5671); + tempvar res = res * point + (0x73e8c35fa646fce6bf10c33168dcf3d2e40af17ced70b1929826d0ca4ba2e99); + tempvar res = res * point + (0x64f6f50e51b19d5a90e6d2c9cfc3486dbf2b37c7f949cc4f8ac4dd988e5bdff); + tempvar res = res * point + (0x1365aaaf8c72d7e9b250bd91ee2c2264362e87679abcf2df2b7a4e1eda1575f); + tempvar res = res * point + (0x24a083b7cf164138ea0c468f33317d89c97b69378c906d918123f3ed5a02cf7); + tempvar res = res * point + (0x25ea89f2d7ad620296fda2be181b5a6be626eade8974facd81e53df842c125b); + tempvar res = res * point + (0x2d32dd179cf74693057ede607e0054fbc3e4194efd6415156f3ec909c37ead2); + tempvar res = res * point + (0x3b74f537f03a28e72bae3bf1810f1a2fde1711eacd6bc64bf55f37b3bd9940b); + tempvar res = res * point + (0x575b929bc0caa43939bfae95a6d5cd8d4082be7fe0934be4c08f7fd3cbe89c5); + tempvar res = res * point + (0x7ab2a5ce120c251b658bfe532880535e93cbf88aa60a1b384017195e6715706); + tempvar res = res * point + (0x7a7d5ce80c8498175cdd4408e08cea457517e37dcba08d0a6cd2a4defcce34d); + tempvar res = res * point + (0x6475aad2a1631a6103b238548fe8a03934779ecadeaead2bc20a677c0c71c); + tempvar res = res * point + (0x547ddf1021a2cbacc8081cbe3a5c89b8ae808942513cd6f6ad166b0306cee66); + tempvar res = res * point + (0x653405343098520984b06f707cee84ea765ecc932783cca87058b88d0f2bbe9); + tempvar res = res * point + (0x3f22422d66d77bda123b47b7f5bffe5527f95d331346f6a545c66887ad75ab9); + tempvar res = res * point + (0x1b18b73effab8a483156d16e87be4dfce1250333eafc784d76c6ee145978c48); + tempvar res = res * point + (0x2843bf3d789d84faebdd6ceb0eed3ec0acd959732178b00b4242eb5cff0ef3a); + tempvar res = res * point + (0x592d2fbca1f86935e587f6cfdacd0a221237bd378e2d1cbadc3d168c7a1756c); + tempvar res = res * point + (0x4c35c95cf7170d2ab6b9b6e3c1be66dba2de170638f27975fb5ec12c36a45d); + tempvar res = res * point + (0x405f9011670f0f202814795cdf0251b665e8f39991dfe2282a1dd2acdbaccb1); + tempvar res = res * point + (0x43b4be816239e45b4d22123c840717fe3e8f6ce53238fad4ad56e27c85f3e9); + tempvar res = res * point + (0x3a2c1769a49e0632c149dc9d3f30306f9d9cc00cdb426d58b2741c804c51af4); + tempvar res = res * point + (0x422c03b47f25f698d3dfbb02556367c97b7d8e2657af2e45ebc61845aa2c52b); + tempvar res = res * point + (0x5a47f80b2d6e8c8e89f08c23e4eee09ae23882290a4dbdc5d0b09e713297124); + tempvar res = res * point + (0x2059b2385d435959cedebbb68ab5c484441832a20d67889ff9974057cdbf874); + tempvar res = res * point + (0x6b735de6be3ab4aa1425c328c838ba09dec586718729f1e172554cac036483b); + tempvar res = res * point + (0x3c05c93a63aad66725d8d25e62f76199a1e9f5743577777caa05832f4e79acc); + tempvar res = res * point + (0x4245e03d0378593b2d4230b945a2a147b36ebfdf368f0dd5fc22e3b31ac1186); + tempvar res = res * point + (0x4de104ea20937d5d6cb02c4ab4d7c4d03ab2eb16d1b837ccf0c2a05ea2873b1); + tempvar res = res * point + (0x48876d457eaebe03383add02eb4c0c49a09923757428595a4f3ad6299d69cba); + tempvar res = res * point + (0x6d6ed610ff1347a9252bf835af9666acc415b28796d968ab76353cdc1181733); + tempvar res = res * point + (0x1da9b14257c5c5cbc1a97aff87690dfa51e82af9a11eaf5cb2538f595ea2105); + tempvar res = res * point + (0x416057baac3a1780d7d25b192188b9b3981bdcab0e2dffb2fd95456a5313201); + tempvar res = res * point + (0x1706af2f962881d86f167571fcbb909b6f1e4fa386fca8d87b674335196f44b); + tempvar res = res * point + (0x6d9c76938c974418e62166285ade6564712e6a263357e11d70f3e1f2ae531e8); + tempvar res = res * point + (0x771fefe011becb392f5c379dc9e902c41be8f1069ae3c5e0bf6016b7b1b3f55); + tempvar res = res * point + (0x40cbcae9364d8af8b767a72b260793922cf1ba2a03fedfc60d4eab1d5f00042); + tempvar res = res * point + (0x274b54e6342ced28b28c62edbc8a6cdb44d1530e0fba56e4940e55d806f437f); + tempvar res = res * point + (0x77273f7030b86a46aee79ed44f0968feb0ffccfa0964ffff141e693fd0fb6d1); + tempvar res = res * point + (0x4dbe5188f23eedad88bab99323be5ac9bf747525c23d4c0665334dafd1f0c6); + tempvar res = res * point + (0x3410d8b91297b00cf8d438bea18b9ebd55ae441a2f6bac6623a15e43ad64d4d); + tempvar res = res * point + (0x4195cb2f46ca4e1ef5d93ab3a5decbdc9e74d0bb81d56abcf59304ecf79863c); + tempvar res = res * point + (0x6581a70ec64b4268a4741b4f7de866050d31b69005c782630f4bdc51a1650b2); + tempvar res = res * point + (0x754535ea8702292678b57fbde36c97454994bed59e0d0e13cf8a6c3ef7a0324); + tempvar res = res * point + (0x71034c062fdc1b61e812617b037c5dd1e80d158a92bdae7ccaec162fff4edd3); + tempvar res = res * point + (0x297d52739d69b228b057588496920930df6ada28e5e2a431b65502750a5bad7); + tempvar res = res * point + (0x446d7e2595a1940ab7f6dec4c9f78953de9c0f4c67a130b55f1894779e73ac3); + tempvar res = res * point + (0x5b0a8465067d8f43cac5dbc1145110e1e79e0f32ba1d59d2514405a0a806860); + tempvar res = res * point + (0x5bdc50def36283e003e9ccf2f1bed188326bec8bed554815f9e49062ed6da4a); + tempvar res = res * point + (0x3b591c6de6700576abbe4b4544de71cd3266a5dbb70740762d0c16a863bead8); + tempvar res = res * point + (0x7fe75f49544ac3cf237a17e58179851f5b3e7420330e5861ec505291d9a0380); + tempvar res = res * point + (0xe09e3870dab755cabbeac23076891b510207da569b75bf32d3f63c8ce08460); + tempvar res = res * point + (0x66bb11e034bb55410211b7cd410cf076db77f008bd93f0dc938f089e853f0ee); + tempvar res = res * point + (0x630cb6b8bcbe79e58025a699d489116a875f287fef6f1677b497b8702c3777d); + tempvar res = res * point + (0x46ebc0bdf94c2f85023a0c1b29d229ef7a23e173d310b814f72c73904f6a5f9); + tempvar res = res * point + (0x3fdf21da099da6c005b076001c5a95f2fe26aeff47e2cb9e8e52166a22b643e); + tempvar res = res * point + (0x6c647f1e5e8e93fda4bc0ae5d513cb60558e2b44bf885484161bbfb5e093969); + tempvar res = res * point + (0x688dbf5c443560c219afd8c54a0b26bdc9284925f2cc0adc889c1de024d6ecd); + tempvar res = res * point + (0x3c782f4a1a6d94adf1448fd7feef975f47af9c79bbf7e2d74940673704b828a); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_ecdsa_x(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x22aac295d2c9dd7e94269a4a72b2fb3c3af04a0cb42ed1f66cfd446fc505ee2); + tempvar res = res * point + (0x2bc4092c868bab2802fe0ba3cffdb1eed98b88a2a35d8c9b94a75f695bd3323); + tempvar res = res * point + (0xf685b119593168b5dc2b7887e7f1720165a1bd180b86185590ba3393987935); + tempvar res = res * point + (0x5febf85978de1a675512012a9a5d5c89590284d93ae486a94b7bd8df0032421); + tempvar res = res * point + (0x4e1b2bc38487c21db3fcea13aaf850884b9aafee1e3a9e045f204f24f4ed900); + tempvar res = res * point + (0x324182d53af0aa949e3b5ef1cda6d56bed021853be8bcef83bf87df8b308b5a); + tempvar res = res * point + (0x5d4c38bd21ee4c36da189b6114280570d274811852ed6788ba0570f2414a914); + tempvar res = res * point + (0x529414d56e9f6bf4ce8be38c8f79ffab78b185da61d606c411098f981f139a); + tempvar res = res * point + (0x66d15398bbd83688bda1d5372e048536a27d011f0f54a6311971822f55f9c07); + tempvar res = res * point + (0x52e5e75be2c96802a958af156a9e171dc7d5cfa7f586d90ed45027e57c5fe92); + tempvar res = res * point + (0xb0e39f10e5433b2341ecef312e79ed95d5c8fe5a2e571490dd789dad41a2b9); + tempvar res = res * point + (0x703dcca99c0a4f2b2b7f1b653dbbf907dd1958c248de5dcb35be82031f7d170); + tempvar res = res * point + (0x749e86688f11d3d0ef67e4f55535c715a475ceec08547c81d11de8884436d8d); + tempvar res = res * point + (0x44a14e5af0c3454a97df201eb3e4c91b5925d06da6741c055504c10ea8a534d); + tempvar res = res * point + (0x6cd537aebc479350e63acbcf7b9da84f4b06c6c26a571d3a7dd416a94a956ca); + tempvar res = res * point + (0x5e2909b1136e1d6608663e5cbabb616b28d2fd6f5dfb7cd03c4a7e719b7c53f); + tempvar res = res * point + (0x51170abac6896de6a5b478741dd56f52b1d2a1feea59b1f26d060e09ed98b32); + tempvar res = res * point + (0x1d0f94ce5d9d3beaa42ebed05a2f172aa2227e9a9fee0bf43a3fb068c1ac345); + tempvar res = res * point + (0x785dc572a88712cb4eddcc8a167bb1b62f9a79282f21ee92a0374af76169344); + tempvar res = res * point + (0x39d9d83e0ac884a5ee0f2d227f9eda71724a55002a41938458e45251e121308); + tempvar res = res * point + (0x7fdc637318ea00385719f9ce50848d13cc955eef9f36a90b87e646dac85e3aa); + tempvar res = res * point + (0x72d82458ba49cd6c638f89d2e3a68e49944f486cdfb7d2848e51aa9f99292a4); + tempvar res = res * point + (0x4c484b2cc04747d8d812180ec716f779302231983fa17971b575274c0a9c378); + tempvar res = res * point + (0x62773dee1773834dbb324c4c0d48dcdf9bbf0511547feb1b2ab0f7af7fa2dc2); + tempvar res = res * point + (0x5b0343972ee9e17afaf76adc54e6797d54e6e47a7ea1167654ce076e3c6c360); + tempvar res = res * point + (0x3ca8d84242dd2bd2a5d6e644fa1dc9f5082ee6131b6f0db8fd7d4f87109098b); + tempvar res = res * point + (0x6f4ab1f3bccea47669a4c93da36db05bd6f5197945b5ab29191a703312ed3a8); + tempvar res = res * point + (0x2d626ebcfae2d3618e350c190fc636495fbb04dd4a4e563680fb961a3d30d8); + tempvar res = res * point + (0x42f0a74ce045e8194b7a5cac4e882b1f1a9face49c38fb3383cfd3d960806c); + tempvar res = res * point + (0x34b7ebee71c5876183407c57610a0a8a33d3138ccd6ae416651cd505e5761d9); + tempvar res = res * point + (0x150c633a21f3cfa157978e9561161f3953e180b9588347a0c819e4173afcfa8); + tempvar res = res * point + (0x4f8cecab5f743c7227a63fa7f320930ffa7cc52b0fff6c351d3e9d4c22f9f9a); + tempvar res = res * point + (0x98ad9c2080ba0663fb302025e6224cff41d1d30c5c9101ad77a48a71d8ac); + tempvar res = res * point + (0x58a6d8229d82c192f190e55d28489f621cbcc64e4ef10c1ec5663c5384e60f); + tempvar res = res * point + (0x7850ac1ef437d1b99c026a910b2437c1b877242e605c8f31a456f10e2f78743); + tempvar res = res * point + (0x337092590652e19c23b48de3629ae0bd4157a5a72ecd3fcd17bb93f05814716); + tempvar res = res * point + (0x95fd265a2a87c42af5a20a199e6730ee3f0e3352a38a5e7e84ef46c621903d); + tempvar res = res * point + (0x38ada3df52cd03154d66b7da4a8a01835a461e61a76ac9576649d8c00013610); + tempvar res = res * point + (0xc1bbae3cf2d414dc12119a0c746e3c10e148f8b522d574eff757d44d8b3a14); + tempvar res = res * point + (0x7122e4b28d4ee35902b7f7b8ad5f525b6c70a2f2bb6b4ee4b9f0008845ffacf); + tempvar res = res * point + (0x75275c33b919425b271966642fabd9ea7c917e70e96eda669040935b1d49db6); + tempvar res = res * point + (0x70af32c484244d3435bb65b0ed076f48d06abb45b7765de9c6f26c1c8e9156d); + tempvar res = res * point + (0x47c78a993a13204796a2fca3b20c0f02c0601e7cc59f84570fa026c65796dc9); + tempvar res = res * point + (0x55713c4cc9f91e9f158f70683238853d0bb7cbd8358ff72b01fb60808b5c1de); + tempvar res = res * point + (0x412fcd2551c0516392f685a62b54fb82b9a73bcffd42abecea4482b65aeea47); + tempvar res = res * point + (0x6925415cd4dbae0ea5e9f41edcb503ff6f668da1cb13ec73eab6a99cd96752a); + tempvar res = res * point + (0x3a2a902a0e43ab33c19459984fe116fb215796cb40c48e254de6126b55e9c3); + tempvar res = res * point + (0x552e18bfefab6c3362cec587f0a7433a914f1359e5767b4fe883f1ad902dd13); + tempvar res = res * point + (0x5643c5a69044bb8e86d10d3248ea3f50f8598732b0c517b256fe108294e09f3); + tempvar res = res * point + (0x542f931640d9010e906b7e1e375cd0481740157eb51500ea1e10afe77f26265); + tempvar res = res * point + (0x2a2811098d68a747bebe9ca2eae06b604bb307e5f51a9bdac1636f380feabb5); + tempvar res = res * point + (0x57d53073d66a528c88f24e40011321f74ce5bdbecd6ca319e5e770ae29b21da); + tempvar res = res * point + (0x1a4393bce3924d765902469c715fedeea69adca566859b4c8c412b7d7cb566d); + tempvar res = res * point + (0x6dfc1fb08b981f73911dc43811caa0ed99749c2f0903f87f389c9a0e2a88126); + tempvar res = res * point + (0x224fe4f546c8f999947a5864ed0dbcd64fcac6f774ebce11667c2bbb7d8603); + tempvar res = res * point + (0x1f7d548c5a6f2bc70ff6f8ee47f38221ae25dcb4f9b068054ee66227494f87); + tempvar res = res * point + (0x735f4476c2b51acb4f0dd9dbc4306108e37543538b2cd3cd2327ae5377a2e5d); + tempvar res = res * point + (0x66ec70c796374a71b6aec5520467ebed547f645d1670b990dfa680a1b415cd); + tempvar res = res * point + (0x14ac38a4b82b4c65e4993726b58f32c74988997b8e8f7729fe9032cf187896d); + tempvar res = res * point + (0x27092905558602aec9af09947b70bb974caa3dd7cb1cb991810e15d75194aa6); + tempvar res = res * point + (0x44e3645cc1b135410b2a52a5b92bcb454985033615453a51ac46377885c4309); + tempvar res = res * point + (0x352b933e5d853527d2a4317db613d07117fad8115948957515bc07d72e161f5); + tempvar res = res * point + (0x268c1e10f6f9969291b1d2f54289371a2f40a14cc67b3736e04eb891c1824ed); + tempvar res = res * point + (0xaa81707e389769aeb31cc8b45276af0370dd702ac79461bae0a4078cefb5df); + tempvar res = res * point + (0x67dec5ad6ddb1761ec61d2820533f7a2bb56d66f2fb8ecff9cbe28218990061); + tempvar res = res * point + (0x106911de08ef437acabf58d178db7c81ff4d7de25f3ef5cd2582f44176d449e); + tempvar res = res * point + (0x356591a80d5c2e14c3d8a180c030a9529a8580a4f3be00a5a9eea83d0d585f0); + tempvar res = res * point + (0x40a3ea8c4059a1b9138884234381d6d383e66dd48eac1bf05f5fcddd593c881); + tempvar res = res * point + (0x699e679a8f38a1ecb14c6695a2848c6abbab8a05003e43aa5cf4a9c6e6058f2); + tempvar res = res * point + (0x6b86f825e41b2c9934f71cc2cb08787d1bd4f2eefd2be9c44e37bf387b35940); + tempvar res = res * point + (0x4eb2786b11bc602bbf773564eb9b057d7dc02daaf4359c015295d97b74e72bb); + tempvar res = res * point + (0x7b0ed28b968689517aaa216c0203e57f1cf56b22ff1213561499ae140d37fa2); + tempvar res = res * point + (0x367ea925556a875faedf4d61bd2a95a31067bde6e682c50035bb3310cc54b03); + tempvar res = res * point + (0x781cf0ea1c0ba9cf908656aa2c5a9403d54c26c8ece401a2c13be8d3090f9c1); + tempvar res = res * point + (0x20ffc2b4c6c318bee0cdfdca40b2c10f2c629d3b52472b17c1bfd909cb7b85a); + tempvar res = res * point + (0xe5e89fde76daa211fadf1178785f0c25a94d47a468cda257a895b871a928c2); + tempvar res = res * point + (0x164344bae5b9dca8f384612e7351fecde28adee3d245c98dc2f65509b181d8e); + tempvar res = res * point + (0x4063a6202df9488fe5384aaf7be7610b3e88a9c01486c1b88767ca36355340); + tempvar res = res * point + (0x546f65cf3367a004f10e9a4e47d71f6ec80086cb2be19d7b225825e01eb323); + tempvar res = res * point + (0x72c11bd84cd54152607e4c6e558a28e480a6487e374b865682c167484f8c29b); + tempvar res = res * point + (0x7a5d11f284ee7db72bed2338784d6467e05cae85f333e05c5610c018a57c2a7); + tempvar res = res * point + (0x64c71feb673d2655bb1865f9c4bdfb16b1bcd0f278a911363056674dacb812f); + tempvar res = res * point + (0x62334e7d6094be4431aeebefc420f7e656459d6fc2cb10455123ede054f4cdf); + tempvar res = res * point + (0x5dd4b3dd252fa7eda7b46674369a2f8c5b00a891cf01ada0ea5aada8bfbf6d4); + tempvar res = res * point + (0x3373dcd7d0f0f8bb31ec396e1ec67e1f121121356dba549bce9fd4d3bbfbaad); + tempvar res = res * point + (0x42a6c571001e263b1ec8168805bf4d6cb65935cd0687c696ae3a6968fd28378); + tempvar res = res * point + (0x16f35b8d34d425a85fe48e66632d3e4af27d5d65cb180cb99047fdc2b908ea6); + tempvar res = res * point + (0x24327b5849aaae0d313870c10e8010a115b70a99cf6b92925f51d2f05686287); + tempvar res = res * point + (0x45ba7e524d75c65ab27b57a6e0b90458c9b0eb651935f84898a5d3cd0db9b8e); + tempvar res = res * point + (0x767d8839373a2e97b7e3de1be6f4c18df648806920e92fcc4da9ab6bd8525ce); + tempvar res = res * point + (0x741b0f4e1bf8ed4d6318f5dc5ebba8529089f5ef4a84cd727564c60cc11a96f); + tempvar res = res * point + (0x68682814e1b4dd639cf396a9f60efe5ca035c6ccd75054b8911e8a15230efa7); + tempvar res = res * point + (0x68edfc809bfa6534b583624db421a2cb885d2ce888e6f95eae85ad9cb38249d); + tempvar res = res * point + (0x5d6575134d1b37e610f25e65bc8b0b1ad7fd0cdcaa56fe573142a09707640b5); + tempvar res = res * point + (0x327bd35b3ec38fb121c039f777669426d3d60df3922e688a408a06d4e7ee3a1); + tempvar res = res * point + (0x29a66c93ef1fa5ac4b6f96ed329810085b294a7ab8e16c61b1e225fd7406236); + tempvar res = res * point + (0xac01d3129d24fe9b9209df8bfeb2526bc27e9c27d78f69eac16ce151b13540); + tempvar res = res * point + (0x3a967c407600baaac716275b8fa16a08c22e928d895c762b2843d00496b3390); + tempvar res = res * point + (0x4d111629c799fb16f602183ae372aee382e0b401312951eefe77a1674575242); + tempvar res = res * point + (0xa8a00bb9874fbb44ee3411814dfb9d4d6048f5e3af6f7f09fff4e9f0263901); + tempvar res = res * point + (0x3abd943152451107f59aa81194e7bbbe37c4a86a6b41e20a02f8145dd32fa87); + tempvar res = res * point + (0x580bd7107af3afc93d0cfd1f0bd39f78f06ebe3a900f5d79943c25e980e5653); + tempvar res = res * point + (0x7a615360e826e937db0c91cc1c9196086a3fd608cb01d20186ba1ce856904ed); + tempvar res = res * point + (0x21df6648e6f783b7361a20191b8d399a4373dcbcc83f6b4a9a40bf11956219c); + tempvar res = res * point + (0x2c82b2a99d198138ca2c4229a1929d044b113c1b0f693659712318ca7e7f804); + tempvar res = res * point + (0x6dd74321080cc46d816a963c8a6f5dac42cb11e66c79831efba77433cce0d23); + tempvar res = res * point + (0x1e54c3a5a3beca7932090ff58784aa43261075950feaab0e2a840f3801b81b9); + tempvar res = res * point + (0x3360af40b57c0a951da3219025643a76516f85119dfbb05f61874eb3b56b130); + tempvar res = res * point + (0x164d44fb88efb41e301934bf2c61a20e41c9bcb3f8e784ac5857063b4fc3d5a); + tempvar res = res * point + (0x46efbcd0bd7f06d59a430ddeb9f239d66a24ce1fa72f5dbcc2bab48b707b2dd); + tempvar res = res * point + (0x5ae517bdefe7b6785680842685de0b5cd972a22dae9ceb50a6ea3665feb06f0); + tempvar res = res * point + (0x51f4698c121db3db4a5244334c5180cfba256dc80a59689e2c0f1f8d946e6c); + tempvar res = res * point + (0x67d2681fae96c0b4bf22d10a73a1882c5bf4a5440f8d0458394d514ff7bd18b); + tempvar res = res * point + (0x3dab30754623b91aec7a165cc167e9003269ebab3e551781e4c8cfb73402de7); + tempvar res = res * point + (0x44be18892438118a0b3fc099da7489a89cffd4206678abfd37b1e649ad19178); + tempvar res = res * point + (0xdb0ad3bd8a33b8daf1d53ff8604bbe5259b6620e3b547d5c6f392dbc10ccd5); + tempvar res = res * point + (0x1a36f20817da4dc0c2e8b62fa08ce15cd3cb50419acf5211d6948bd6b28c8ce); + tempvar res = res * point + (0x5fa6f7f2a7a527880a5b58911dd7f3a491fc702f481cee30e67c4980092f851); + tempvar res = res * point + (0x6f682eebabbcbfa3e7084b47b2a01acb693865749df222b4b8dee0ec41903cb); + tempvar res = res * point + (0x1fd7088411b30cb5762147b1d6749942485b36c68ea32f60ab83fdcbe987d83); + tempvar res = res * point + (0x7172b43d0c88348e5453b0b26d54d4a7ad7e99e6b0c4b787341c8d89936197e); + tempvar res = res * point + (0x34369f479f013d44dd5bb0d79d8a9effdb2ca36ce8b3d7e759bf707233c5bbe); + tempvar res = res * point + (0x3054d35b59baf5b0a2078c23322de031b383033837cd6b978b6c060120b7fb3); + tempvar res = res * point + (0x23f0124cd1c3f3605fa1ec36dc4d6cb6e229f8ba8998b138a44595f96f3bf21); + tempvar res = res * point + (0x2300892e3f3c180333d091901ba99ab9e23c7947309b9e88ad47025847ec3a0); + tempvar res = res * point + (0x4182bea2ea16dcacb0194876cd5fe8c79e1a55836aff8aa6074d235af5f7b29); + tempvar res = res * point + (0x50f3e383aaf3533fc91b9633386542798abd69b79af893f47f6603d3cc35ea4); + tempvar res = res * point + (0xc37f91c81a7006d6681cb511dab2e4d83928ccb78d1dc72c4c556e4cd72db8); + tempvar res = res * point + (0x2693f31fd4bb5a1ef9cacdc4f2b33c3d6d965b76e7bf289020ab1b6c6660d70); + tempvar res = res * point + (0x2bebc90c59dc0e37e28c7c7d8254520ce08894637bf1a089aed26012690d119); + tempvar res = res * point + (0x17626d3869adf0fdd3fedd48e9fe1266bb33419bfe9046df43c6409b440980e); + tempvar res = res * point + (0x734438bc30566591da45df9366f936415d29eaeaeab392488bcccb9acf0edcf); + tempvar res = res * point + (0x22a7b1c897f54da39a1db61b345b234969e36ef6ba0ea02f8d8b3e83b5c6242); + tempvar res = res * point + (0x22eef827b9d0b57649233c5d527b4641decab31df78347a20da21c705df093b); + tempvar res = res * point + (0x193185be6e02dc0a07c0dced4ed031bf0a406219cce325e76408123406c318b); + tempvar res = res * point + (0xb10494024548b14df121b738abc7babe56c12acc0490699443426a52f3a4f9); + tempvar res = res * point + (0x375ce3766894524209e2043a150f10ad0bf4f726e3dc5453c3c757e56943a51); + tempvar res = res * point + (0x1b1c82e5c561dc42f8c9c2a9f7db6bacd729b2646892a8ecfae9ead9a338aa6); + tempvar res = res * point + (0x4b540d0085be455b24f014bf51dc7d0eceb8c93bb644a5208fa02dc58c718ae); + tempvar res = res * point + (0x17f2709d2719458a9bf72a2b04463f0a6529fd9368a47715c628ba4e006cea); + tempvar res = res * point + (0x20e468bb2828fb774d5ab538ff7f93ada201c2e392936e05cec29cd5a7a462d); + tempvar res = res * point + (0x29cc816e6be353f6ad5e2c390f37ed3940b0dd67610a7eeb0bcded94bdcf920); + tempvar res = res * point + (0x4d3b0654fd74862a92aa716af33b5ad5ac20dc0460c724d95ca94fe6d8a9d7e); + tempvar res = res * point + (0x7ba5194da963f8224987db2720f16baa604ff62351e66a63c0c9dba00fbc7c4); + tempvar res = res * point + (0x31d335bd885c9cdf2adc68ab45b8eecd2d3588cf85b93206896b2626eb1e369); + tempvar res = res * point + (0x4efcba706a8b7868e32f363efac2696ad0625d046a3ef97917c710515016386); + tempvar res = res * point + (0x56017977a273ad0e91c7c26a702ae4508343e97968295b08447b3cc7f20522f); + tempvar res = res * point + (0x16416cc193a5ced6ff213fc18c86bd6f08d17c576f26b9ebd00d2653bbd6444); + tempvar res = res * point + (0x4237c41364975eb79919303fc0a381b934befe871fdbd72c18f97627292923e); + tempvar res = res * point + (0x1b389d976c22a3bfb42424896c9b135a3794048724c729968f81e04ce414194); + tempvar res = res * point + (0x62fc206aa283139f7451e54cdac873fe86b6e7e89214a3c0318fbcaf6016fa4); + tempvar res = res * point + (0x88f6e5a835dfda9fa2e2ff248d9378352f4a89b6bf5935700da390baebadb7); + tempvar res = res * point + (0x4f9e975176d3aacd79c322d013c854c4b8829d1e469c9b242461f35e8dc6fed); + tempvar res = res * point + (0x6e1143b147dd1bcc56dd43e6a3616c9a4016d6887cf0009ebf9f9796efc944a); + tempvar res = res * point + (0x284c547c04ca83fdb01020cfc797eb362838317f09e5d25e1e4eef353ab7a7f); + tempvar res = res * point + (0x60c327ef73c8468805ecace45a33ccc375fc91ffbf01b4b10a01ffd4b7aaefe); + tempvar res = res * point + (0x59cd87f8751437900e984a009c63fdf7461b177067760f30d4f648ab271660a); + tempvar res = res * point + (0xdaf5a68420fa7ad811f6dc75c5b4e92173a5d89255dc75accb8cec80a9cd91); + tempvar res = res * point + (0x1f573af6e3ad146eeaa582f540de6a8db237ff2f28423660de998a4275bf4d0); + tempvar res = res * point + (0x2830a6edb344b7fa86506557a0b2b0bd900429218fb35e7990951fe4fe869c6); + tempvar res = res * point + (0x58f2e18613b3b25529935a623e7d5c8318ca9ff3fb180f16f7454ca9e348e35); + tempvar res = res * point + (0x42c8f0b5507417eb48ffeb1a7df8808633f193c27df8e2f44ee7bd62cb2c3bf); + tempvar res = res * point + (0x50d603bf9c2a456b828ae476092affde072ecd878877ec3f99ba8f574d263a2); + tempvar res = res * point + (0x413fda31150aa8462deae8a6043fc5624599fb7f638c4d5c5f89472e1223c28); + tempvar res = res * point + (0x13fe84c8ecc2e3fd289560c0ada7a251fdd5fba24c076be4be465feec4262e6); + tempvar res = res * point + (0x2b2a0768e9a5f59e7f33ea449690794c8b409bacd1c808f7ee8065ed9d8648c); + tempvar res = res * point + (0x3030332e9cf430f72159914e59ab9af532bdfdafedc1be39691256c8084954e); + tempvar res = res * point + (0x16617a52bfe5d2fd0eedb0d6411f5fafeb14a4ac17da0cc828c914acb500ce9); + tempvar res = res * point + (0x553f8ab49053432bab53835480b6f4c416eeffb3470fb6bcf122741cac3d71d); + tempvar res = res * point + (0x3939ef0e572dcc3b67f0cb819fffc521df26e50814281621fa6982b1465f786); + tempvar res = res * point + (0x520b18e79de342aa7095ffe56be6222b0d2e44fc3c676a5c994f24e427b45e2); + tempvar res = res * point + (0x3f3ae3871460ac578f5030d925e91c138f3290f8f3cb6d4b560b4b16fbacd64); + tempvar res = res * point + (0xbffb0e4f7ccfff0cee519edd1004eefbc47024f92c4409bbdf688c133ad285); + tempvar res = res * point + (0x62d6874b6dcb1c4dc8ed797b9158da4359c6c49f27af4851a12908ecad2092e); + tempvar res = res * point + (0x511c0ad7c0bfdcfcfaf925895a8ef5e8c5e0d147e29c9cdae45fbc998fce346); + tempvar res = res * point + (0x25199c11f7193e07191cd9b9108aa8b440ce1972dd1cbe5f0cc33b7783203a8); + tempvar res = res * point + (0x3cf3b95ba351a72019ed1bcadab32116adcf079e72800a9d88f15244e7743e0); + tempvar res = res * point + (0x19cf240d04f4859941f9b6af4a7088729aa10307cd08aa75f01cb22e872543d); + tempvar res = res * point + (0x1cd528d070930aef19e0f928fc744e79ff57e227b6aa1bbfce15a79166aefd8); + tempvar res = res * point + (0x475f8af086f7aa4ec3739f754f7dd291dc50decc7c7fb03de8aee3cf06824f); + tempvar res = res * point + (0x28f86fe2d71f9410e14c17195ae19c2c5e623c525c979f4f74dec3ef8848eb5); + tempvar res = res * point + (0x508243aa19e23cdb8ca0154055c05130462908c6a2691ae522e37ab9d6168f2); + tempvar res = res * point + (0x37cf9640e321e7bccf1926d5fea92918d6888c5805e27193722995233a4adc5); + tempvar res = res * point + (0x66336e2e2eeb939818f861fa4aa9b2576936470f511786f8fa3417850a6c2d); + tempvar res = res * point + (0x19a0ff21908842e412addb744b0ca384a54bdde819f6337c4c672f682fea9cb); + tempvar res = res * point + (0x44147236daf669f8a94b7ea353c3dd7e64312ece01ccc1d4dad67916591d50b); + tempvar res = res * point + (0x1d6cb5a655919a581078aa2f8a21d300425026ccd7d047302443d78dbc67abd); + tempvar res = res * point + (0x4d8d9b92b38a45147bc9c87c071672edd93cbf5bdc8d85e608f26f1d82d172b); + tempvar res = res * point + (0x4acd125e74056ca611a1b07369166eb5c02af7a4cbf387b2bd584a362fa9e60); + tempvar res = res * point + (0x3b4fdc8d965de1761e445ee88cb406f707f9d0b1ea3c069d12084c0ccba9b44); + tempvar res = res * point + (0x1f27c20f47daaf01d4627d5e9bee0e9bd2aa5b75807064cd60ed87e307f677a); + tempvar res = res * point + (0x4758304a75f149e24563c2b22459151389b86d36108f5dfe11ea1fc7a64fd7); + tempvar res = res * point + (0x1c1216fe648d287c2645dfc5152e171f25483df5ef112b745c2e59b5d9ee07c); + tempvar res = res * point + (0x24adf288d61c113e28d9a298d2642eb67586019adcb952abf274ebe1d30e24a); + tempvar res = res * point + (0x3e09706cb43c83143c9dc46f97e0e1ab4327de19ced69badaa8b2c80f68fb9b); + tempvar res = res * point + (0x589a2e11637d0c90fe91bb9f4d55a80cd1a2df7f3431e8b8bdce8fe7d35126c); + tempvar res = res * point + (0x5f506aaae7ce6d94712c9e0ab02bd2a4ae09600608d54a8ca381b8e96222cf7); + tempvar res = res * point + (0x3f64b3a307276c6a7169c54297bb12aaeebadec98df6ba1184492a82effe353); + tempvar res = res * point + (0xc3e0400cbde1da659381240d9c84b977eef3cd70e3e4a1a8763a05e682eb3b); + tempvar res = res * point + (0x1fdb038204ac50e87e3e7239d8c1c0572893ba98e031c982e545e6de64cb8e0); + tempvar res = res * point + (0xe0b21e37008355c35f7aee295a8b2b72465866b2bd68e72d36f032c34b38a0); + tempvar res = res * point + (0x2cc90219912af16cf9a39f57f8b8c514f797dd5d49dfed5eabdc278e31106a2); + tempvar res = res * point + (0xab2147a23a826d5f7c6fea5bf889eaafb5531721f31ee0a9f02fd58f09f65c); + tempvar res = res * point + (0xa5d4606609371577b0d17fadcd85ce659885b00245a67b038f902176d99a7c); + tempvar res = res * point + (0xfc76b77f717a5b3ecafafadf29e7f886c8ae67a3a2bb30467c440472349953); + tempvar res = res * point + (0x40fb948f8a4a10d2b2e928a5d77b481f8d3068b47fa388a3ee65609aade1a41); + tempvar res = res * point + (0x13d322a0ecbe1e785921a7aa6f4d1135e0798e72f4c055226205314b8348144); + tempvar res = res * point + (0x20096a7aa30c6c42f1d5f1ed88de275d1d1610f2548711a75fbbd72d373a50e); + tempvar res = res * point + (0x18f9cfeaf2c33e21d7c6fd9e15a3601a2fb3905588868167566e8c1f1dd30fa); + tempvar res = res * point + (0x3e3aa48bb5db9e2b0dc6d294009ecd5d4ff6255dfcdde3f5b4e545032ea9b68); + tempvar res = res * point + (0x425b03b0356b92e66ca816869a76110d68862a0d8ad76f950fdb1d5c03279d1); + tempvar res = res * point + (0x7cdb723061223f33289237c7476e737ef0bbc5e2c1ed9a70566511fc2036ba5); + tempvar res = res * point + (0x18b8b8d0f393950c9a2e674052150a328d214618049c7e2f58cbad76adbfbd5); + tempvar res = res * point + (0xf19faf3accc43b56369dccdec35dc7b49c5b8f8976764886bd16dd2e155f92); + tempvar res = res * point + (0xe08853aabc9eb934b4470bb4ae1dbbe90c61d2093516df998ca7adc98afe10); + tempvar res = res * point + (0x7736291268c775a82caea06004d53edb829be2566fc7c4053b1d850a8116cac); + tempvar res = res * point + (0x1bc1186238f0d39e1c56185a8d2bf00c90c9c89647917d60a5b762932856524); + tempvar res = res * point + (0x6cf772fa8050ad8eb87bc8f0c8fc511622b416fdb084cbc93b79501c96b0bda); + tempvar res = res * point + (0x7417da24519b4c55ec0d698ecaceeb49711aa1e7f7d907102351e73388a0fa5); + tempvar res = res * point + (0x66e1e25d1bcea87acd136f2c33498e3223fbf78bc6cc816ad6aaf68e961da0d); + tempvar res = res * point + (0x60db5bf6f060d82c169a1c4ed6c548d5e8cdb6cfd2e3257c155bf11f48ca609); + tempvar res = res * point + (0x2d5447623584d3a19e9993814622d6369248bc61813f067c4825c9b0a81551f); + tempvar res = res * point + (0xac068a1aae938e26e125b35c88a87130044bf3637bf1acd797103e7388b33a); + tempvar res = res * point + (0x3ab2d353537697d4de9c5c4c0bc31e5e776cb93181029144f6c6d4b5ea4317b); + tempvar res = res * point + (0x6ca2dd473297a2852e68ea2b83faf8f71e5cb471adcc74a858132c6a823f0c0); + tempvar res = res * point + (0x1ec5264a5287f1c6de79b3df3adbfa157e8430e594078c3fba7002a077db447); + tempvar res = res * point + (0x50ee695deb5a4e63c5dd6de35621d1c0c5a496bf41fecbaa929b2b3e23f174a); + tempvar res = res * point + (0x36f446f7e5a51114cbdd3b460431bacb5a42cd61f4690cf5e9d9f13e488318d); + tempvar res = res * point + (0x195f98a85cfe403a7d229a6eb4533a1fea641c331db75a5807711fdf1e27dac); + tempvar res = res * point + (0x63d4964faab567e795024a17032ec564ff221a421bd2e42632d3770c73dbba1); + tempvar res = res * point + (0x68d729620eca6b4d904198a0e6d241953b9b8c874a10b5ede5596146d560979); + tempvar res = res * point + (0x1137975bab819ce0cbc73714305030fcd4a185f71d46c169908460390d56d18); + tempvar res = res * point + (0xf639bcd7777c1ffd41a693ac9f5a051bd124b7edce3d568f14304c9fd90a67); + tempvar res = res * point + (0x2322f8d96071356feee538e0c53d857b1924134b94377af20ed5d0e8b3925b); + tempvar res = res * point + (0x22cf65c6bbbf76765555748cc1ae91c83ea93ca2c8b34a59332567b5b3b0cd2); + tempvar res = res * point + (0xd62eb553de83e5d51f78ddd9480d65870dc426f61153e732eb6cd62cee09cd); + tempvar res = res * point + (0x6afb39d46d5a846e9d58a6ae27e6cdd83bee29c72754cd4cd3d3cae423f5c9d); + tempvar res = res * point + (0x364889e46da58b66c827835a0c2807338eeb4431f2099f490d13bbad0777a01); + tempvar res = res * point + (0xaea6f7f915e4aec612029a9d02316baa3f6297ea4cfd38897f4c9859ec485e); + tempvar res = res * point + (0x5c180e2fbb2b51e053941d0e1611424fe60ced6d439115dd98530c8d79cca4a); + tempvar res = res * point + (0x1ab93f16e576b6a54598582eff5e2cfc33baeeb607826579680636b05046d16); + tempvar res = res * point + (0x4de47e973af27fde9ad29f812de8a04855110118eb73fcdb46865390486a287); + tempvar res = res * point + (0x50be25e516e30f96d8b420a7c494506d2cd21d64f4d5ecb67d58c2ae99bf5e0); + tempvar res = res * point + (0x2aa45ec320ea12beb804e35af3684dc981324dc9bd044592d1c408c052a4322); + tempvar res = res * point + (0x26701dfe3cc76754a4ab893fef59886a43013ea6ba648efd82fd03941fa2910); + tempvar res = res * point + (0x1773ba95dbeaab6e5e9fc79ac153d46be1e57828e92287d698a3f4f87ef4984); + tempvar res = res * point + (0x4e92d5f575fcaac9adedb4e0c3549dc18f61bc40e3752e3506f3761c32c6e3); + tempvar res = res * point + (0x580f9d95c2bd746c9210a87b0f9ed275afee1dde7a41d9ad5e69861ec0e43f6); + tempvar res = res * point + (0x3e2dbef5f162784e13b5ff4c33bcbc444ad1546922b293d6783b5de5c5aba78); + tempvar res = res * point + (0x596f89b6ca79194eb6a87c17692aa491f5b014da3cc7e5f05caf4fc1779c2dc); + tempvar res = res * point + (0x7e84842d5fff1666e01505f62661bcc822dd3fa530ebd1e4089230a4045a04f); + tempvar res = res * point + (0x5626d2ae9581d1d335bfc3863a4eaf3568ec8e70fcdae93f50a15b0cf601b6b); + tempvar res = res * point + (0x68371fc7cb3e0670a73eb3a7e773ddb63f231c26bf25bb1fc1fe6e93a7e3bd0); + tempvar res = res * point + (0x4d215dd42f87632a9cce2cb95081dc731e36796c3d2847dc96a3554231c6aef); + tempvar res = res * point + (0x421fac0e48da8e6355c07f6a64bcea96384848e8ea9a7113ab45f15b1dd15aa); + tempvar res = res * point + (0x679061e5f453c8bb1855dce8f7d61f2cb64b15d2c4e70b969ec4ead3fc6a226); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_ecdsa_y(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x23a2994e807cd40717d68f37e1d765f4354a81b12374c82f481f09f9faff31a); + tempvar res = res * point + (0x49d16d6e3720b63f7d1e74ed7fd8ea759132735c094c112c0e9dd8cc4653820); + tempvar res = res * point + (0x6c930134c99ac7200d41939eb29fb4f4e380b3f2a11437dd01d12fd9ebe8909); + tempvar res = res * point + (0x347dfb13aea22cacbef33972ad3017a5a9bab04c296295d5d372bad5e076a80); + tempvar res = res * point + (0x62e62fafc55013ee6450e33e81f6ba8524e37558ea7df7c06785f3784a3d9a8); + tempvar res = res * point + (0x23b940cd5c4f2e13c6df782f88cce6294315a1b406fda6137ed4a330bd80e37); + tempvar res = res * point + (0xf524ffcb160c3dfcc72d40b12754e2dc26433a37b8207934f489a203628137); + tempvar res = res * point + (0x603e3a8698c5c3a0b0b40a79ba0fdff25e5971f0ef0d3242ead1d1a413e443b); + tempvar res = res * point + (0xa401d8071183f0c7b4801d57de9ba6cda7bd67d7941b4507eab5a851a51b09); + tempvar res = res * point + (0x37d720cf4c846de254d76df8b6f92e93b839ee34bf528d059c3112d87080a38); + tempvar res = res * point + (0x5057b804cff6566354ca744df3686abec58eda846cafdc361a7757f58bd336e); + tempvar res = res * point + (0x76b4883fd523dff46e4e330a3dd140c3eded71524a67a56a75bd51d01d6b6ca); + tempvar res = res * point + (0x1058ff85f121d7902521abfa5f3f5c953fee83e0f58e069545f2fc0f4eda1ba); + tempvar res = res * point + (0x4eac8ffa98cdea2259f5c8ad87a797b29c9dccc28996aed0b545c075c17ebe1); + tempvar res = res * point + (0x6e7240c4a94fa3e10de72070fd2bf611af5429b7e83d53cfe1a758dee7d2a79); + tempvar res = res * point + (0x59fef071cf1eeff5303f28f4fe10b16471a2230766915d70b525d62871f6bc6); + tempvar res = res * point + (0x480d06bb4222e222e39ab600b8aadf591db4c70bae30fe756b61564eec6c7e); + tempvar res = res * point + (0x7d2292c8660492e8a1ce3db5c80b743d60cdaac7f438b6feab02f8e2aade260); + tempvar res = res * point + (0x5a593d928542a100c16f3dc5344734c9ef474609bd7099257675cef0392fab8); + tempvar res = res * point + (0x761717d47600662a250116e2403b5115f4071de6e26e8dc231840eeb4484ec3); + tempvar res = res * point + (0x4b74b468c4ef808ddcc6e582393940111941abece8a285da201171dc50525c7); + tempvar res = res * point + (0x14ef999212f88ca277747cc57dca607a1e7049232becedf47e98aca47c1d3fe); + tempvar res = res * point + (0x47b2a5ef58d331c30cfcd098ee011aaeae87781fd8ce2d7427c6b859229c523); + tempvar res = res * point + (0x59bd7fe1c9553495b493f875799d79fc86d0c26e794cce09c659c397c5c4778); + tempvar res = res * point + (0x3ede75d46d49ceb580d53f8f0553a2e370138eb76ac5e734b39a55b958c847d); + tempvar res = res * point + (0x6e0bed1b41ee1cf8667c2924ebd460772a0cd97d68eaea63c6fa77bf73f9a9e); + tempvar res = res * point + (0x739edb8cdd16692deaba7fb1bb03f55dd417891bacb39c7927969551f29cb37); + tempvar res = res * point + (0x247573f2f3fbd5386eac2d26851f9512cd57ad19773b8ca119d20852b9b6538); + tempvar res = res * point + (0x2f6efb89f27d2c0a86ec1e6f231b225caf2af9be01aca173a15fa02b11fdf24); + tempvar res = res * point + (0x75a0f99a4dec1988f19db3f8b29eeef87836eb0c3d8493913b7502cfedcef28); + tempvar res = res * point + (0x278a7c68986adbe634d44c882a1242147e276fee7962d4c69ca4c8747b3e497); + tempvar res = res * point + (0x675532b80f5aaa605219de7fe8650e24fee1c3b0d36cdf4fb605f6215afacee); + tempvar res = res * point + (0x5599e790bd325b322395d63d96cd0bd1494d4648e3d1991d54c23d24a714342); + tempvar res = res * point + (0x43545892bb5a364c0b9acd28e36371bede7fd05e59a9dcd875c44ff68275b2b); + tempvar res = res * point + (0x38db61aa2a2b03053f5c51b155bc757b0634ce89baace113391369682fc1f74); + tempvar res = res * point + (0x71b2b6b03e8cc0365ac26c4dbf71e8d426167d79f8bd1af44738890c563062a); + tempvar res = res * point + (0x3a663fc27ec3ad56da89d407089bcec0971cebcb3edf0c393112501919643d7); + tempvar res = res * point + (0x1030d58878296e14b1c5bcafe7e817ebe4aa1039aa96b9d0dd7fc915b23f42a); + tempvar res = res * point + (0xcb3335374cc2a2350fe53d2389f04952c4d634f489031742dfccca17be2e09); + tempvar res = res * point + (0x6ae3ee97ea5dcfbb7c36cffd89665baf114fae391c0367be688db09861a8ca1); + tempvar res = res * point + (0x7b16c33c4a8ffcecbd83f382469e1d00a340ceab5e7d9c0bd4fd010b83f4310); + tempvar res = res * point + (0x10f236430f20aafda49d1c3e3759c510fdf0c0c19f89df6d5d71deac88b547b); + tempvar res = res * point + (0x104b04e96151f5103118c4eb556cd79899148fd6656e73cb62f41b41d65e4d8); + tempvar res = res * point + (0x253bf2869135f4bda4029cae2819b2f468ae88530f3ea771090b2727814c494); + tempvar res = res * point + (0x65d50aa3c1d84a3deee14057eec98656a1296cdcbe32250bfdaa50ffac4c5dc); + tempvar res = res * point + (0x76323f8567119897f10d58e1552c98f5a62f03a16d3737e20fc2b0a31a3a843); + tempvar res = res * point + (0xdaee1c7b34ecb34717b7313dc4a299dd1a161447e2e0249426a6fc33a72289); + tempvar res = res * point + (0x2bfd1294f111a5a90842d19cffb97481aefbc09ab6c47d7dcf91ba228019c07); + tempvar res = res * point + (0x4f63db02e10fbe428a5dda8d9093feef46cc19568a3c8ad2fce7e7519004095); + tempvar res = res * point + (0x761a240cd8aa2f135daf0760bfc2c9d5e896e93a45426571cdad9118722e2b0); + tempvar res = res * point + (0x30a2e8ac9e6605fd722dffb4caca8c06dd4a8968a7bf41a5371cb1a07d11c00); + tempvar res = res * point + (0x5ba89e0eb3830039d0f8a9ca00acef15db22374c965b01abc49dee46270a7d); + tempvar res = res * point + (0x7e8659c39d7a102a198f0e7c3814060926ec0410330dd1a13dfadeab4e74593); + tempvar res = res * point + (0x5a00feeb391114d7b976654ab16ddf8360f05671b34d4a97da278c0aef34d76); + tempvar res = res * point + (0x33ff2d848bf237f536524da818598ae0f2516ebee526b77957448973eefacd3); + tempvar res = res * point + (0x4e0a5dd802deed7cb8d06527beb15dad32547bae77141c32473f4c8148912e3); + tempvar res = res * point + (0x776459dfedbbdfcef7a31e0f60c6480fc0676b280fdb6290859fe586d6e6106); + tempvar res = res * point + (0x59d0d8ca9ecda81081dfcae7580ab3c08a72195438c1556000c0c1dbdc08174); + tempvar res = res * point + (0x6eb66d366da57e4ae717307dfc3351579fe857c51aa82b95044473c9ed14377); + tempvar res = res * point + (0xa758a70ba6a0cbcbc65abfeca51359904f790752c3df55d42707253d8dea70); + tempvar res = res * point + (0x2046e1b4fd4c108e8f832f5bcc4dd46abf0d19ef0237beaec29d6c12fb9832e); + tempvar res = res * point + (0x472d99d1a6e1a6aef339eab1af3d53af7a8326e4d0a6bac73c3a159031c3686); + tempvar res = res * point + (0x1b0fa36439192f135c239918bf47ad14b55ced699f4582d929a60dd227b34ff); + tempvar res = res * point + (0x728dd423dbf134972cbc7c934407424743843dd438e0f229afbcca6ce34d07d); + tempvar res = res * point + (0x4e42531395d8b35bf28ccc6fab19ea1f63c635e5a3683ac9147306c1640e887); + tempvar res = res * point + (0x1ea9bd78c80641dbf20eddd35786028691180ddcf8df7c87552dee1525368ba); + tempvar res = res * point + (0x68a8c6f86a8c1ebaeb6aa72acef7fb5357b40700af043ce66d3dccee116510a); + tempvar res = res * point + (0x25c5f348c260177cd57b483694290574a936a4d585ea7cf55d114a8005b17d0); + tempvar res = res * point + (0x339b405bffb6dbb25bc0432e9c726b7f94e18cf1332ec7adfeb613345e935ab); + tempvar res = res * point + (0x23590dabe53e4ef12cba4a89b4741fcfaa232b7713d89df162031c8a627011e); + tempvar res = res * point + (0x534a4f3cf71c93023e473f12e407558b6c24b712204fd59ddc18c7bcddd571e); + tempvar res = res * point + (0x2e1b2a3c32aebc0be30addd8929c01714783aaf01be8a1d35e830646e8a54f0); + tempvar res = res * point + (0x605a244f646a825602891bf9ddffef80525010517b32625759b0bf5a7f2c386); + tempvar res = res * point + (0x4f81a946bb92416d212e4d54f2be5fa8043be6fa482b417d772bfa90be4e273); + tempvar res = res * point + (0x655038ca08eba87484bc562e7fd50ce0584363278f9d716e31c650ee6989a2b); + tempvar res = res * point + (0x44938959c2e944eb6e5c52fc4ee40b34df37905fa348fa109f6875c1aa18000); + tempvar res = res * point + (0x30b11c32e8aab0c5908651a8d445395de52d5ce6a1efe75f2ad5e2c8c854a30); + tempvar res = res * point + (0x4a92733a733f225226a3d7f69297e7ff378b62c8a369e1bbf0accfd7fb0977e); + tempvar res = res * point + (0x1345876a6ab567477c15bf37cc95b4ec39ac287887b4407593203d76f853334); + tempvar res = res * point + (0x580550e76557c8ff3368e6578a0e3bed0bac53b88fefdde88f00d7089bc175d); + tempvar res = res * point + (0x7d7faca17be1da74cf132dda889a05fce6e710af72897a941625ea07caa8b01); + tempvar res = res * point + (0x62be425458d26cfedf8ec23961cdfd9f4abeb21f1debbe87bd51469013358fe); + tempvar res = res * point + (0xd77a8e8eed7ce4931a6d2a4774c21864e2c9f468d080af9aba6756433a1a8d); + tempvar res = res * point + (0x3e850e31c0345726c1ace38537dd88a50c85d6819ae98add1bbd62b618f7a1c); + tempvar res = res * point + (0x375a5d9b11c83d06a04dc9f1908b8183adc6f04e5b2ceeaa23d3b68c973ee77); + tempvar res = res * point + (0x76640613af9ed1a125624e0c38252bee457ce87badb24fc4f961e55883d9077); + tempvar res = res * point + (0x5428ff423f2bbabcb5f54aafa03d99a320b4b255115351f50b229eae5522178); + tempvar res = res * point + (0x6dcfc3a99563a5ba4368ac4f11f43e830c5b620a7273330e841bedec0bfb5a); + tempvar res = res * point + (0x2652523cbbec2f84fae1a17397dac1965127650479e1d5ccfc6bfbfcbb67996); + tempvar res = res * point + (0xa737d6916aa6a869252d8ff294a55706e95e0844e6b047755704e37d978e09); + tempvar res = res * point + (0x2833391a62030808228d14437d6f91b31c0038c14988a23742b45e16f9b84b5); + tempvar res = res * point + (0x284f7815a7eabc1dcf56da511f7d739f1a199f8ffaf3474f645d2fc93327dc); + tempvar res = res * point + (0x1e141c5429a369996563573bf61d7f713cb7d25baadff636ba2756c65a910ee); + tempvar res = res * point + (0x60bdb98c079bd5cef216803b056afce03f6ea41934275c965d6e196240fb953); + tempvar res = res * point + (0x7f2abefac9e7f8109b0a2d25d0bd297059e45dd66798ac8b299f0a3e442dd2c); + tempvar res = res * point + (0x41776c662b44a36c7075097c14b6010cb321591a4eca2866d58252eaf9471ac); + tempvar res = res * point + (0x573b13b32161c11c9b16eff7cf93fa770a3ef667547a27503e39092aeabf73e); + tempvar res = res * point + (0x327319fcc0d34a0d64f5acab00244b43674a60bef754844fb2920c87c90cff0); + tempvar res = res * point + (0x755f0e4c374e2fa4aa7eda10041e2139a4a7793eea44f415c73ad4fcba1758); + tempvar res = res * point + (0x7b9cd3b277f00a75a17961d2d8e46e6a1838c8500c569cdcad08bd4e0cbae84); + tempvar res = res * point + (0x21f5ea8660d290f28b9300e02ed84e110d7338a74503b369ad144a11cf79f63); + tempvar res = res * point + (0x5e4b0ecc6a6c15ed16c1c04e96538880785ff9b5bff350f37e83b6fed446f14); + tempvar res = res * point + (0x3d8506e792fa9ac86ac9739d3d5bf63cfc13c456a99c8581adf590c8d9b72eb); + tempvar res = res * point + (0x1e3b6498f0daba2fd99c2ac65461c3fa519cb738b53cd6f002e97199fa4161c); + tempvar res = res * point + (0x70930735d913d54915fba20c97f07cba8f33eb8f4f81fd869699a10e83264cd); + tempvar res = res * point + (0x16a36769ee50227c564bebce3d9cd7c4ca55702a7c7ccf403075f68f05a0c2); + tempvar res = res * point + (0x3aa748723229eb8b33354e0901f50ad052b6c1006916790c979133c4442be90); + tempvar res = res * point + (0x5db8c52b6adb520496f9edd7105c92df67e8605ff4e0cc59992c3eb651ac7a4); + tempvar res = res * point + (0x4b2222d0aee638c7e5efd8ada791638ac155a01b78f3b532283574653998bb2); + tempvar res = res * point + (0x26a4b2a61f40c1ad77737b99cb27d2f3118622be64f0120907e2589d2f25ebf); + tempvar res = res * point + (0x5820792f23a13d58ddef0607950d422598bb1f21888dace88929fbe7d4828c4); + tempvar res = res * point + (0x3678de28b6896959edf5c9dc0caec59b02dfbbf54811f87939b32d0523f58bb); + tempvar res = res * point + (0x3cd13f84bb7ae6eeccc1012837d2f3e017f069e66cf047172bc70371f5aed38); + tempvar res = res * point + (0x7af8995e2ceed8841e34d44365c7ca14f5980a6a5c67b9813fa7bfd74a9c1b1); + tempvar res = res * point + (0x6d7af6524127a117184a0c12a6ff30d28b14933a4e96bb3b738d2a36db72e84); + tempvar res = res * point + (0x73200d12e733294b5cbb8ffe7fb3977088135d0b0e335135f9076d04a653c58); + tempvar res = res * point + (0x229d7fc2a1bcfbe00d5773f8dadd70a2641d8578fa73e66263b3512d3e40491); + tempvar res = res * point + (0x29889daac66c404d6491ec3a435d810a2877d885df1a3a193697b79b4af39c4); + tempvar res = res * point + (0x171f0638dedf0b69655fa9930bcbc91b257e299a6717bd8ea23ef550c8faff5); + tempvar res = res * point + (0xded0f75cd0a6a5401a954d26880eaf12050ce6458d3254c9dd6354bf66278); + tempvar res = res * point + (0x7fc7d854c9d0b3bfbf826c384b3521af0f29f975613e8ea6dc14f37d8beb54c); + tempvar res = res * point + (0x6d1c3edcf1de16a4e0ad7d8aa099a31fa2cfbf81f6d1a5798bd1ef93ff906af); + tempvar res = res * point + (0x3444c0f008988c8f600270b365ff926f016e49a54ab35bac4f3b3a42a5879b1); + tempvar res = res * point + (0x2a48058c77edcd75dd4323d9bb9eccb854009b1184fd716a8202f8627bb5447); + tempvar res = res * point + (0x56cbe248ebbc2f57ca8b943b219ba245791592f687815293a4499ef598fa9b7); + tempvar res = res * point + (0x658160ea7b654d786dc624b258c691f594e080610c2d41d6ebea0d8e3396849); + tempvar res = res * point + (0x6fcc261ded0ba97b4defc7c9bcd32b5dac89e4c08cb55cef98c6b50f5a3a289); + tempvar res = res * point + (0x7b74edd15d97b289da4040272cfc573f69a8c9a8b36d05e3e50b598508b7f9d); + tempvar res = res * point + (0x19637a12aa8b822c4a3f3551ef6c538043371a12a962de1dc25d67e0a5ee561); + tempvar res = res * point + (0x4c05a7abaaf08f21d93b2257d4f4a3ab2b44f4ac44ce0444418c864ca18470b); + tempvar res = res * point + (0x657060a10db73c4a9b6aa6288dd6164e0b50a4e6efbc2ee599a0cf4fda33b81); + tempvar res = res * point + (0x688c61ee887c1497ffcef82163f1a81bf7778f2c314ffbd325627bf0b25dc5a); + tempvar res = res * point + (0x54ab13ae1984dcc7d38c867a47f4a8cf786079ee07cc94ab5ec1962c21f638b); + tempvar res = res * point + (0xccee381472bb7dcae008316038c87a44fd9295f730e389eff14e86442c41b8); + tempvar res = res * point + (0x610bf9b7ea4557d72411ec90fb677f9a2ccb84c76f003954da4e7f439c9a84c); + tempvar res = res * point + (0x51d6322f7d582892421e977464b49c4e6e64af2438da9a7f21a061c77712dc); + tempvar res = res * point + (0x7d92a463e2aec09eb86f4647dc9ec241904135b5eb53ea272e809e58c0a271e); + tempvar res = res * point + (0x17ab90241b58bd3bd90b8a5c7f30aa9e5afeedbe1c31f21ca86c46c497b573c); + tempvar res = res * point + (0x199d80ad30b4b330fc8a063d1e87307993e1d98822a1729488ba8a586045691); + tempvar res = res * point + (0x601a139ed75acbecf557cd6513171385a119087585111c30bbc1b65cd6d30d); + tempvar res = res * point + (0x77b10e23b08892ab18cc6b14dfda6f4be5c2fec94a12e3622622376edd0d6a8); + tempvar res = res * point + (0x2a17a5c34f9f598deb5bec334fde606eaa5601df908eb5825ecf70f9cecec3f); + tempvar res = res * point + (0x7e176a66dcfd58e240c4546cd760b7e5ad02e4f0265c6a2f38d710bbdf99d55); + tempvar res = res * point + (0x27e76848780aba5b12061bffefff1710995586618a2f32792d62771d31ed519); + tempvar res = res * point + (0x43f51dfe0f1cf290c9a522e2a5e734f79d220be80348438c676295c3d429e); + tempvar res = res * point + (0xf1f93c3d919653f02fba06fcba1ab89497fff53eceff6a7d129887d5a9e3b); + tempvar res = res * point + (0x79fd6f5f9b042ece36af6b10eae2eef9de9c9dd18752eb66868a0c301015dd9); + tempvar res = res * point + (0x1958435eb08883bd69b6a56a8f3103c22f8ae206a3d4deaf4a04118b4dd6a6c); + tempvar res = res * point + (0x329230075f64ffbf631eb0c40b97d71b4dc38a08bd18b638f57e5644680068c); + tempvar res = res * point + (0x219557f1604be8622e697e986c03d2a49e40cce558a264bf4f1ebe06493eceb); + tempvar res = res * point + (0x7238f034b8c57c8b59b0f744ababf9da8229152a051d4f3b3c4995233ac1111); + tempvar res = res * point + (0x201019c76d9aa29a00e6b18a4eeac7b1322b44285c57cf4c0b68a87120b1d31); + tempvar res = res * point + (0x69d95f3c7892a1cf65b45c324be2294c4c5459e05e0feaa0b8bb98cd8bc958f); + tempvar res = res * point + (0x78aafbe80fa5ee9a846e991bf35b81567a6dcbb1b190e7ee47e53fc66422e84); + tempvar res = res * point + (0x15ba3c5a882d4dfe3e23db18368ade6b2d10ef52e34f12ce0d62e7183c10f7e); + tempvar res = res * point + (0x1a4bdaf2bff969eff8cef73e762b6346492b8d0f17b2e42956c526f625241ea); + tempvar res = res * point + (0x4adaabee9ab3c6ee7fc67a2ddc09c5185755dcc76cc3b814a6b71aa7ae542ea); + tempvar res = res * point + (0x2f47cde744314dc0502faffb0387a2e765e4354b0516ee9ab0b97a1b6c33ec2); + tempvar res = res * point + (0x90b2b18b3fc2919a55b71ad6d6fa67dda752bd02c985b59e6554f557fe4a2e); + tempvar res = res * point + (0x6eba866251e1dca38a21c8b3fad0aa3c22a45dd89884c4c68bd7ef67de64f52); + tempvar res = res * point + (0xb8dd33ef8726747fb368aedf80c2f4a720bc1b5220f4a3f0e56e2fafb7e243); + tempvar res = res * point + (0x1fac2f441d05a3b483675200cb1ebc6f4ca6ecc5ae60118fe8745f95217bf8b); + tempvar res = res * point + (0x6d28879c6f75c4ede18e1b94ffff964d08c79038fd9ba2e7873cbefb5f323db); + tempvar res = res * point + (0x28b38e0334fc06af4c94ec4f9434923d4149cc51817526597423fd4692c59ad); + tempvar res = res * point + (0x84add7269e2e41ea57aaed996f4c012ba7003ea2b994670cc0d554b7a8bd2a); + tempvar res = res * point + (0x64d672ca00300ddd5e9c9d2db433d7623bb54c8eb2db51b235a07616f1517e5); + tempvar res = res * point + (0x7f71cb5526600d15d3413ec971ee3b133718224b3cbdc68171a53d7c8684382); + tempvar res = res * point + (0x38e5702bb10256e1856a5bfb03a06b231b89a36e2f84af80bcd2d027153d847); + tempvar res = res * point + (0x1a8d4b2044b8e03b325c353f3f92283013920b92f479064b6e93159d2ed3ba0); + tempvar res = res * point + (0x68384718bd3bb23f32999f1edcb2dbddd8136259e676c4492d0cafe80ffd856); + tempvar res = res * point + (0x31a77aa370bb597dbdd0422612a7dd947aae09a5b0b17d1996f13a85103d150); + tempvar res = res * point + (0x40a9cea0394d15ef057c2923d4185f290fe2347e00529d92f927ef506e3b5e7); + tempvar res = res * point + (0x2a427d70a34b6b5237894f065ef5d60a9872ba444d47d98648b080b8ddb2a68); + tempvar res = res * point + (0xe505592d606917f898c54a7afc45b328be3cd48121aee2e8f05185a3e23e5f); + tempvar res = res * point + (0x45b4e74f19b293bc3d3d172a101e344558fcf4ccfe5eecefe31f45a45614df7); + tempvar res = res * point + (0x68486394265c9dc8fae42c8fd39605d3179c981cb44cbe33740a3deb907bc59); + tempvar res = res * point + (0x2868a08eae382c069047152ee964ac5ebd242b44267e97e578802440ef764f5); + tempvar res = res * point + (0x3159144c85f2c515eb806e5aedd908553057b69c556d226adc6e4511a35423c); + tempvar res = res * point + (0x4387edee6899d4a85883d2f8524978a4634ff82779f150b7b0c861bb315ed3f); + tempvar res = res * point + (0x68c5830832f6270a189b074d7675fcbc1d1c5cc06ce9c478bf8f4d5ac1bf40); + tempvar res = res * point + (0x399c00b8ebb398248bb1f52528d5241e7366b73c2d89f57a11dc82c530cc57c); + tempvar res = res * point + (0x3238aeb8f6bea8bcaaa1bdd5b4f917ccfad8eab031785ccdc648b47d7ea4be8); + tempvar res = res * point + (0x357bf5d87c973292381fa4320114551a837a1d6cb6e2bb0eeba534fb2e01742); + tempvar res = res * point + (0x360274f27df6eeec0b7b65fbb227a8214ac3e55cb37b1970e18489ef5b574e1); + tempvar res = res * point + (0x1cb6e2fba23730f5bf9d8e726569b6e8bf6b5ffe8520339503c5469cc3713a2); + tempvar res = res * point + (0x3924324af1994280f87f289fdae0b9a2d8cb9914ec37d319c18daf029211815); + tempvar res = res * point + (0x3c4ad04a5a057e4411487858dbe16af8e3fc065ef7400749ffdc248bdb25bc5); + tempvar res = res * point + (0x50c92b3e6848a21001be2a268615e1e26cb4918ecb09640efaaf1d8b71568fb); + tempvar res = res * point + (0x47d21828025d0cbab84084965a49dd14c7833aac562b55de808a94777df2ea3); + tempvar res = res * point + (0x6207c6a2fd70c19a10430566c9efaad95eab8cbddf308f0057c81f3155a25a0); + tempvar res = res * point + (0x2d4acebd804035257147ad8d8419a5f5762b4b543c4846ef9acf41856e672ee); + tempvar res = res * point + (0x78f49c214872b5cce18ead0207a165fb741ea818a69cfe9647737323f70f4f5); + tempvar res = res * point + (0x22aa8c5c5ff26f9a0edc768ae32ff4f71a71205b4e83cfa0cc687a1e02566ba); + tempvar res = res * point + (0x5dd2e0680c7eff25211f31d3c30a9f454500d6eb09d46d87a75a42b190203cb); + tempvar res = res * point + (0x5ac4bcdb9c14634ab83c13a30822ddbabc54248cf1177b11cc2aed24d2d32f5); + tempvar res = res * point + (0x77dee5f03389585fad0d1f2a8accfa4cb985344891b8befaee42f3462cb48a); + tempvar res = res * point + (0x737dba18eb055a12d842bfae32fd146dcd2d7bb932a2591aa864458d6d652); + tempvar res = res * point + (0x23bf372b0b59abf250463697ef4b2096eb1c9674613918b4d0c79aa10d9fd59); + tempvar res = res * point + (0x73724274fdd351c378e597da1615dc51058e14994464cb7b318766199ac2a35); + tempvar res = res * point + (0x2e14e83be58cde3ed5f3fec8ba6462493a4a2f0f7d6c846006220eccd49ef25); + tempvar res = res * point + (0x4846d310812d81ffda3731e8289005e2f0e05411e76b1c84332c3ee9e831afb); + tempvar res = res * point + (0x160abeb38bc4f22af5fe618c19c77c39903007900722bdbdeaee059f31544c8); + tempvar res = res * point + (0x264a535ae10091157ed59b04955dff66897af74cae20456bb830336b803ae47); + tempvar res = res * point + (0x316ce6b23e720b8302e2d4bd968c0f140f69930e46a54784a7cee7e0b8a0c8); + tempvar res = res * point + (0x775d95a0beb287c98663a3f9a9c577ffc67c1fe6fbe2db5b08829a2c3eac922); + tempvar res = res * point + (0x2353c4a418bdc1e461be162140cc69c26eb9d99f08924991f85058f87f6df41); + tempvar res = res * point + (0x181ef9cde124459dc0e2aaf93512abd49a10328fb93dfc4d49ab671db64bbc4); + tempvar res = res * point + (0x7ff76956e0cd2b490b47a0a0497df5f874cf47f54c45f08101256429b48460); + tempvar res = res * point + (0x318e5a52d685eaa06e0f39159a344b3d97b52688b671d133954aeff0bc17707); + tempvar res = res * point + (0x7616cfc6834643d4b95ed1cfec036f816a7c3d3b9800f301f98ddf341712ebf); + tempvar res = res * point + (0x59869515fb57ea7733567e5d849bcaa00c00e0f86f4ebbd2c7a6f4c0c77692b); + tempvar res = res * point + (0xb806f4e19770279fab5427b8eaf5bc68bf984d6ccea1e878a7aaf32c9975d9); + tempvar res = res * point + (0x4fb0c93fe30da048576fe5e839483636218dfdda3d05f1d68847a4c0167597f); + tempvar res = res * point + (0x685af2d7bbf30cd0c5c3d41c430a8657eeafeeb4596165faaa73d802087ad80); + tempvar res = res * point + (0x6f617dce150ea148cb8c7488fe4caa920b2000bc8122cce1891e4b76cddc9d4); + tempvar res = res * point + (0x47f02fc512b153462379f4f793c7cab9e659bfdb07d3439d29039f566b7236d); + tempvar res = res * point + (0x4ce0a14a5a9c30a38062eb8870eeb4ff3562db743c0f3eede2e3d3862a2eb7c); + tempvar res = res * point + (0x7b077d27c7007656025224fa4e528b4c4261f43c3da1e42bd1349403af55cbb); + tempvar res = res * point + (0x50f5f6adbf0b9abc6e231b855018f4ec806a4f199cc511bed5c423ebef298e4); + tempvar res = res * point + (0x5fcfeb78685abb1ce610e516ab7e2aa210fd90844c8d1c89cd798f3d71bbcb3); + tempvar res = res * point + (0x4255a568f4597862e1dfe0c391b97059d179d7eb4d868f61364835e5028f9dd); + tempvar res = res * point + (0x206d7f23d0fe1b1c0967486ebb792d7fdf5b1691d2c2f9306e211d3b849526b); + tempvar res = res * point + (0xc61c74cc988663ee09f4c725d5b1f04549bd342d3550ce17427ac75592b637); + tempvar res = res * point + (0x175a904681c7a91856bf7fcf8410d2c19eb8705267914489664a1ea2af5b8fe); + tempvar res = res * point + (0x1bd842a4ec97e1489ceb542bd3161e5a00ce431547bfadfbced954d993b0a11); + tempvar res = res * point + (0x14899e0f97aac917d46ce5e9ddf11194fb846d2c52726af4085f27c570a98a9); + tempvar res = res * point + (0x842955243a56778a332ba9be0b22b2af62efaa50068d3078675fb76c225e76); + tempvar res = res * point + (0x6dff267c3bbce68474294da908df4f5cf2a4160c638f7cb45c098057e968f44); + tempvar res = res * point + (0x72c0dd24a576b47a84cdd1a20227773b5621f85b781c288625e3368e1cf738a); + tempvar res = res * point + (0x728771890334d0c9b0f400543bdc13ea6890497bc87c509a04f8014916c13a5); + tempvar res = res * point + (0x30632b3865a272a1a00270430744ee90b40ff16e1fc44515876ce8e36215ca0); + tempvar res = res * point + (0x76d656560dac569683063278ea2dee47d935501c2195ff53b741efe81509892); + tempvar res = res * point + (0x1dbdc2ea2e555309578eeb2352fbc47c8fd5ed77cc09903b577700f9a4d1be1); + tempvar res = res * point + (0x119bcf6402ad9953851bac8e318d50af699b0cc75e2597aff0a2cc521975aa4); + tempvar res = res * point + (0x7c3234094dff9a45064a5b9abd0667c04dd76c62722984f7f8475e7cc344c06); + tempvar res = res * point + (0x1495d40cf3f13c5fc90653c2b2f02e0b833790c07576286d3127f745ea920ae); + tempvar res = res * point + (0x40f019a18b8097235264cb8efee7d149321a199ccd32ffac43b5a778dfadda1); + tempvar res = res * point + (0x4e23809ce49747990e43b2d976083dc84d67e75cf22e5a76ad5b7a2dca50b3d); + tempvar res = res * point + (0x7f0a3bec1d34f2fd632993a3d9c6432401cec25ad9d6196b909f3672980bd05); + tempvar res = res * point + (0x9460aa25f77fc10cfcc4579e2011e39ce477a32a768aa553201e556ed2bbe1); + tempvar res = res * point + (0x611384709c407d85c93256b6aff04c4ac515450c70cf507994165abfe2347b); + tempvar res = res * point + (0x2065bc7a4aa38d5fe86f9b593ccd060f8d4a5a19a9ca8b182c32199a4bd27be); + tempvar res = res * point + (0x9969a08d753e885857a5696d1cafd39f62bb193acc99089df76c240acd2fc0); + tempvar res = res * point + (0x6df73a948c95439f3230282814ba7e26203cfdc725901e4971ad9cff4db4396); + tempvar res = res * point + (0x1cdf0446663046f35c26d51e45a5233a93c51f4f7f1985dfe130dd67addefa3); + tempvar res = res * point + (0x59cbe680183d1dc3161ee7f945f38ab9461a5293748b2b7be84899e62c9860b); + tempvar res = res * point + (0x5030fda0c29a929e6cd634b9f3d1bf975c363012cfb439cae13495f8ce10225); + tempvar res = res * point + (0x49aadcf98ef59c0e5d2097845949988862b96194abc8c5453f056f232482892); + tempvar res = res * point + (0x319c68159cdf104c2543486ff784860f302187d77effb9a5fefe4e16f0ddc2c); + tempvar res = res * point + (0x575531b404cdba72a63dbbd17aef7d9ae00f73eca7c6dcdaf5e0778c921be41); + tempvar res = res * point + (0x35ca7fa56aa38486833a976804899ba3c97fdaa0a23056cd2dc9bfdbcdd2e31); + tempvar res = res * point + (0x47dc0e209ee8d0b67f63d9e63837ff2ab462c4839bc14a1a3e802327ff0e31f); + tempvar res = res * point + (0x744bdf0c2894072564f6eca2d26efc03ef001bc6e78b34bf6be3a1a91fd90fc); + tempvar res = res * point + (0x73c57ecea0c64a9bc087e50a97a28df974b294c52a0ef5854f53f69ef6773af); + tempvar res = res * point + (0x7dd14b0299ff6064a96fe97e086df3f64a4c7e8b4a58a5bd5fe1b9cf7c61e7c); + tempvar res = res * point + (0x562f636b49796e469dfe9e6748c4468f340e8f69e3f79cfe6925a261198dbb3); + return (res=res); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/dex/public_verify.cairo b/src/starkware/cairo/stark_verifier/air/layouts/dex/public_verify.cairo new file mode 100644 index 00000000..ba1d60d3 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/dex/public_verify.cairo @@ -0,0 +1,106 @@ +from starkware.cairo.common.math import assert_le, assert_nn, assert_nn_le +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.air.layouts.dex.autogenerated import ( + CPU_COMPONENT_HEIGHT, + ECDSA_BUILTIN_RATIO, + LAYOUT_CODE, + PEDERSEN_BUILTIN_RATIO, + RC_BUILTIN_RATIO, +) +from starkware.cairo.stark_verifier.air.public_input import PublicInput, SegmentInfo +from starkware.cairo.stark_verifier.air.public_memory import AddrValue +from starkware.cairo.stark_verifier.core.domains import StarkDomains + +const MAX_LOG_N_STEPS = 50; +const MAX_RANGE_CHECK = 2 ** 16 - 1; + +namespace segments { + const PROGRAM = 0; + const EXECUTION = 1; + const OUTPUT = 2; + const PEDERSEN = 3; + const RANGE_CHECK = 4; + const ECDSA = 5; + const N_SEGMENTS = 6; +} + +const INITIAL_PC = 1; +const FINAL_PC = INITIAL_PC + 4; + +// Returns a zero-terminated list of builtins supported by this layout. +func get_layout_builtins() -> (n_builtins: felt, builtins: felt*) { + let (builtins_address) = get_label_location(data); + let n_builtins = 4; + assert builtins_address[n_builtins] = 0; + return (n_builtins=n_builtins, builtins=builtins_address); + + data: + dw 'output'; + dw 'pedersen'; + dw 'range_check'; + dw 'ecdsa'; + dw 0; +} + +// Verifies that the public input represents a valid Cairo statement: there exists a memory +// assignment and a valid corresponding program trace satisfying the public memory requirements. +// +// This function verifies that: +// * The 16-bit range-checks are properly configured (0 <= rc_min <= rc_max < 2^16). +// * The layout is valid. +// * The segments for the builtins do not exceed their maximum length (thus, +// when these builtins are properly used in the program, they will function correctly). +// +// This function DOES NOT verify anything regarding the public memory. This should be verified +// by the user. In particular, it is not validated that: +// * [initial_fp - 2] = initial_fp, which is required to guarantee the "safe call" +// feature (that is, all "call" instructions will return, even if the called function is +// malicious). It guarantees that it's not possible to create a cycle in the call stack. +// * the arguments and return values for main() are properly set (e.g., the segment +// pointers). +// * the requested program is loaded, starting from initial_pc. +// * final_pc points to the end of the program. +// * program output is valid in any sense. +// * The continuous pages are consistent. See public_memory.cairo. +func public_input_validate{range_check_ptr}( + air: AirWithLayout*, public_input: PublicInput*, stark_domains: StarkDomains* +) { + assert_nn_le(public_input.log_n_steps, MAX_LOG_N_STEPS); + let (n_steps) = pow(2, public_input.log_n_steps); + assert n_steps * CPU_COMPONENT_HEIGHT = stark_domains.trace_domain_size; + + assert_le(0, public_input.rc_min); + assert_le(public_input.rc_min, public_input.rc_max); + assert_le(public_input.rc_max, MAX_RANGE_CHECK); + + assert public_input.layout = LAYOUT_CODE; + + // Segments. + tempvar n_output_uses = ( + public_input.segments[segments.OUTPUT].stop_ptr - + public_input.segments[segments.OUTPUT].begin_addr); + assert_nn(n_output_uses); + + assert public_input.n_segments = segments.N_SEGMENTS; + tempvar n_pedersen_copies = n_steps / PEDERSEN_BUILTIN_RATIO; + tempvar n_pedersen_uses = ( + public_input.segments[segments.PEDERSEN].stop_ptr - + public_input.segments[segments.PEDERSEN].begin_addr) / 3; + // Note that the following call implies that n_steps is divisible by PEDERSEN_BUILTIN_RATIO. + assert_nn_le(n_pedersen_uses, n_pedersen_copies); + + tempvar n_range_check_copies = n_steps / RC_BUILTIN_RATIO; + tempvar n_range_check_uses = ( + public_input.segments[segments.RANGE_CHECK].stop_ptr - + public_input.segments[segments.RANGE_CHECK].begin_addr); + assert_nn_le(n_range_check_uses, n_range_check_copies); + + tempvar n_ecdsa_copies = n_steps / ECDSA_BUILTIN_RATIO; + tempvar n_ecdsa_uses = ( + public_input.segments[segments.ECDSA].stop_ptr - + public_input.segments[segments.ECDSA].begin_addr) / 2; + assert_nn_le(n_ecdsa_uses, n_ecdsa_copies); + return (); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/dex/verify.cairo b/src/starkware/cairo/stark_verifier/air/layouts/dex/verify.cairo new file mode 100644 index 00000000..5261532f --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/dex/verify.cairo @@ -0,0 +1,73 @@ +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.hash import HashBuiltin +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layout import AirWithLayout, Layout +from starkware.cairo.stark_verifier.air.layouts.dex.autogenerated import ( + CONSTRAINT_DEGREE, + MASK_SIZE, + N_CONSTRAINTS, + N_INTERACTION_COLUMNS, + N_ORIGINAL_COLUMNS, + eval_oods_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.dex.composition import ( + traces_eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.dex.global_values import InteractionElements +from starkware.cairo.stark_verifier.air.layouts.dex.public_verify import public_input_validate +from starkware.cairo.stark_verifier.air.oods import eval_oods_boundary_poly_at_points +from starkware.cairo.stark_verifier.air.public_input import public_input_hash +from starkware.cairo.stark_verifier.air.traces import ( + traces_commit, + traces_config_validate, + traces_decommit, +) +from starkware.cairo.stark_verifier.core.air_interface import AirInstance +from starkware.cairo.stark_verifier.core.stark import StarkProof, verify_stark_proof + +// Builds an AirInstance object to use for STARK verification. See AirInstance at +// air_interface.cairo. +func build_air() -> (air: AirWithLayout*) { + let (arg_public_input_hash) = get_label_location(public_input_hash); + let (arg_public_input_validate) = get_label_location(public_input_validate); + let (arg_traces_config_validate) = get_label_location(traces_config_validate); + let (arg_traces_commit) = get_label_location(traces_commit); + let (arg_traces_decommit) = get_label_location(traces_decommit); + let (arg_traces_eval_composition_polynomial) = get_label_location( + traces_eval_composition_polynomial + ); + let (arg_eval_oods_boundary_poly_at_points) = get_label_location( + eval_oods_boundary_poly_at_points + ); + let (arg_eval_oods_polynomial) = get_label_location(eval_oods_polynomial); + + tempvar air = new AirWithLayout(air=AirInstance( + public_input_hash=arg_public_input_hash, + public_input_validate=arg_public_input_validate, + traces_config_validate=arg_traces_config_validate, + traces_commit=arg_traces_commit, + traces_decommit=arg_traces_decommit, + traces_eval_composition_polynomial=arg_traces_eval_composition_polynomial, + eval_oods_boundary_poly_at_points=arg_eval_oods_boundary_poly_at_points, + n_constraints=N_CONSTRAINTS, + constraint_degree=CONSTRAINT_DEGREE, + mask_size=MASK_SIZE, + ), + layout=Layout( + eval_oods_polynomial=arg_eval_oods_polynomial, + n_original_columns=N_ORIGINAL_COLUMNS, + n_interaction_columns=N_INTERACTION_COLUMNS, + n_interaction_elements=InteractionElements.SIZE, + ), + ); + return (air=air); +} + +func verify_proof{range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*}( + proof: StarkProof*, security_bits: felt +) -> () { + let (air) = build_air(); + return verify_stark_proof( + air=cast(air, AirInstance*), proof=proof, security_bits=security_bits + ); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/autogenerated.cairo b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/autogenerated.cairo new file mode 100644 index 00000000..8aa22db3 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/autogenerated.cairo @@ -0,0 +1,1902 @@ +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.global_values import ( + GlobalValues, +) +from starkware.cairo.stark_verifier.air.oods import OodsGlobalValues +from starkware.cairo.common.pow import pow + +const N_CONSTRAINTS = 167; +const MASK_SIZE = 212; +const N_ORIGINAL_COLUMNS = 9; +const N_INTERACTION_COLUMNS = 1; +const PUBLIC_MEMORY_STEP = 8; +const HAS_DILUTED_POOL = 1; +const DILUTED_SPACING = 4; +const DILUTED_N_BITS = 16; +const PEDERSEN_BUILTIN_RATIO = 32; +const PEDERSEN_BUILTIN_REPETITIONS = 1; +const RC_BUILTIN_RATIO = 16; +const RC_N_PARTS = 8; +const ECDSA_BUILTIN_RATIO = 2048; +const ECDSA_BUILTIN_REPETITIONS = 1; +const ECDSA_ELEMENT_BITS = 251; +const ECDSA_ELEMENT_HEIGHT = 256; +const BITWISE__RATIO = 64; +const BITWISE__TOTAL_N_BITS = 251; +const EC_OP_BUILTIN_RATIO = 1024; +const EC_OP_SCALAR_HEIGHT = 256; +const EC_OP_N_BITS = 252; +const HAS_OUTPUT_BUILTIN = 1; +const HAS_PEDERSEN_BUILTIN = 1; +const HAS_RANGE_CHECK_BUILTIN = 1; +const HAS_ECDSA_BUILTIN = 1; +const HAS_BITWISE_BUILTIN = 1; +const HAS_KECCAK_BUILTIN = 0; +const HAS_EC_OP_BUILTIN = 1; +const LAYOUT_CODE = 0x70657270657475616c5f776974685f62697477697365; +const CONSTRAINT_DEGREE = 2; +const CPU_COMPONENT_HEIGHT = 16; +const LOG_CPU_COMPONENT_HEIGHT = 4; +const MEMORY_STEP = 2; +const IS_DYNAMIC_AIR = 0; + +func eval_composition_polynomial{range_check_ptr}( + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_generator: felt, + global_values: GlobalValues*, +) -> (res: felt) { + alloc_locals; + + // Compute powers. + let (local pow0) = pow(point, global_values.trace_length / 32768); + local pow1 = pow0 * pow0; + let (local pow2) = pow(point, global_values.trace_length / 1024); + local pow3 = pow2 * pow2; + local pow4 = pow3 * pow3; + local pow5 = pow4 * pow4; + local pow6 = pow5 * pow5; + let (local pow7) = pow(point, global_values.trace_length / 16); + local pow8 = pow7 * pow7; + local pow9 = pow8 * pow8; + local pow10 = pow9 * pow9; + local pow11 = pow10 * pow10; + let (local pow12) = pow(trace_generator, global_values.trace_length / 64); + local pow13 = pow12 * pow12; + local pow14 = pow12 * pow13; + local pow15 = pow12 * pow14; + local pow16 = pow12 * pow15; + local pow17 = pow12 * pow16; + local pow18 = pow12 * pow17; + local pow19 = pow12 * pow18; + local pow20 = pow12 * pow19; + local pow21 = pow12 * pow20; + local pow22 = pow12 * pow21; + local pow23 = pow12 * pow22; + local pow24 = pow12 * pow23; + local pow25 = pow12 * pow24; + local pow26 = pow12 * pow25; + let (local pow27) = pow(trace_generator, global_values.trace_length / 2); + let (local pow28) = pow(trace_generator, 3 * global_values.trace_length / 4); + local pow29 = pow23 * pow28; + let (local pow30) = pow(trace_generator, 251 * global_values.trace_length / 256); + local pow31 = pow14 * pow29; + local pow32 = pow12 * pow30; + let (local pow33) = pow(trace_generator, 16 * (global_values.trace_length / 16 - 1)); + let (local pow34) = pow(trace_generator, 2 * (global_values.trace_length / 2 - 1)); + let (local pow35) = pow(trace_generator, 4 * (global_values.trace_length / 4 - 1)); + let (local pow36) = pow(trace_generator, 8 * (global_values.trace_length / 8 - 1)); + let (local pow37) = pow(trace_generator, 512 * (global_values.trace_length / 512 - 1)); + let (local pow38) = pow(trace_generator, 256 * (global_values.trace_length / 256 - 1)); + let (local pow39) = pow(trace_generator, 32768 * (global_values.trace_length / 32768 - 1)); + let (local pow40) = pow(trace_generator, 1024 * (global_values.trace_length / 1024 - 1)); + let (local pow41) = pow(trace_generator, 16384 * (global_values.trace_length / 16384 - 1)); + + // Compute domains. + tempvar domain0 = pow11 - 1; + tempvar domain1 = pow10 - 1; + tempvar domain2 = pow9 - 1; + tempvar domain3 = pow8 - 1; + tempvar domain4 = pow7 - pow29; + tempvar domain5 = pow7 - 1; + tempvar domain6 = pow6 - 1; + tempvar domain7 = pow5 - 1; + tempvar domain8 = pow4 - 1; + tempvar domain9 = pow4 - pow32; + tempvar domain10 = pow4 - pow31; + tempvar domain11 = pow3 - pow27; + tempvar domain12 = pow3 - 1; + tempvar domain13 = pow2 - pow28; + tempvar domain14 = pow2 - 1; + tempvar domain15 = pow2 - pow12; + tempvar domain15 = domain15 * (pow2 - pow13); + tempvar domain15 = domain15 * (pow2 - pow14); + tempvar domain15 = domain15 * (pow2 - pow15); + tempvar domain15 = domain15 * (pow2 - pow16); + tempvar domain15 = domain15 * (pow2 - pow17); + tempvar domain15 = domain15 * (pow2 - pow18); + tempvar domain15 = domain15 * (pow2 - pow19); + tempvar domain15 = domain15 * (pow2 - pow20); + tempvar domain15 = domain15 * (pow2 - pow21); + tempvar domain15 = domain15 * (pow2 - pow22); + tempvar domain15 = domain15 * (pow2 - pow23); + tempvar domain15 = domain15 * (pow2 - pow24); + tempvar domain15 = domain15 * (pow2 - pow25); + tempvar domain15 = domain15 * (pow2 - pow26); + tempvar domain15 = domain15 * (domain14); + tempvar domain16 = pow1 - pow32; + tempvar domain17 = pow1 - pow30; + tempvar domain18 = pow1 - 1; + tempvar domain19 = pow1 - pow31; + tempvar domain20 = pow0 - pow32; + tempvar domain21 = pow0 - pow30; + tempvar domain22 = pow0 - 1; + tempvar domain23 = point - pow33; + tempvar domain24 = point - 1; + tempvar domain25 = point - pow34; + tempvar domain26 = point - pow35; + tempvar domain27 = point - pow36; + tempvar domain28 = point - pow37; + tempvar domain29 = point - pow38; + tempvar domain30 = point - pow39; + tempvar domain31 = point - pow40; + tempvar domain32 = point - pow41; + + // Fetch mask variables. + tempvar column0_row0 = mask_values[0]; + tempvar column0_row1 = mask_values[1]; + tempvar column0_row2 = mask_values[2]; + tempvar column0_row3 = mask_values[3]; + tempvar column0_row4 = mask_values[4]; + tempvar column0_row5 = mask_values[5]; + tempvar column0_row6 = mask_values[6]; + tempvar column0_row7 = mask_values[7]; + tempvar column0_row8 = mask_values[8]; + tempvar column0_row9 = mask_values[9]; + tempvar column0_row10 = mask_values[10]; + tempvar column0_row11 = mask_values[11]; + tempvar column0_row12 = mask_values[12]; + tempvar column0_row13 = mask_values[13]; + tempvar column0_row14 = mask_values[14]; + tempvar column0_row15 = mask_values[15]; + tempvar column1_row0 = mask_values[16]; + tempvar column1_row1 = mask_values[17]; + tempvar column1_row255 = mask_values[18]; + tempvar column1_row256 = mask_values[19]; + tempvar column1_row511 = mask_values[20]; + tempvar column2_row0 = mask_values[21]; + tempvar column2_row1 = mask_values[22]; + tempvar column2_row255 = mask_values[23]; + tempvar column2_row256 = mask_values[24]; + tempvar column3_row0 = mask_values[25]; + tempvar column3_row1 = mask_values[26]; + tempvar column3_row192 = mask_values[27]; + tempvar column3_row193 = mask_values[28]; + tempvar column3_row196 = mask_values[29]; + tempvar column3_row197 = mask_values[30]; + tempvar column3_row251 = mask_values[31]; + tempvar column3_row252 = mask_values[32]; + tempvar column3_row256 = mask_values[33]; + tempvar column4_row0 = mask_values[34]; + tempvar column4_row255 = mask_values[35]; + tempvar column5_row0 = mask_values[36]; + tempvar column5_row1 = mask_values[37]; + tempvar column5_row2 = mask_values[38]; + tempvar column5_row3 = mask_values[39]; + tempvar column5_row4 = mask_values[40]; + tempvar column5_row5 = mask_values[41]; + tempvar column5_row6 = mask_values[42]; + tempvar column5_row7 = mask_values[43]; + tempvar column5_row8 = mask_values[44]; + tempvar column5_row9 = mask_values[45]; + tempvar column5_row12 = mask_values[46]; + tempvar column5_row13 = mask_values[47]; + tempvar column5_row16 = mask_values[48]; + tempvar column5_row70 = mask_values[49]; + tempvar column5_row71 = mask_values[50]; + tempvar column5_row134 = mask_values[51]; + tempvar column5_row135 = mask_values[52]; + tempvar column5_row198 = mask_values[53]; + tempvar column5_row199 = mask_values[54]; + tempvar column5_row262 = mask_values[55]; + tempvar column5_row263 = mask_values[56]; + tempvar column5_row326 = mask_values[57]; + tempvar column5_row390 = mask_values[58]; + tempvar column5_row391 = mask_values[59]; + tempvar column5_row454 = mask_values[60]; + tempvar column5_row518 = mask_values[61]; + tempvar column5_row711 = mask_values[62]; + tempvar column5_row902 = mask_values[63]; + tempvar column5_row903 = mask_values[64]; + tempvar column5_row966 = mask_values[65]; + tempvar column5_row967 = mask_values[66]; + tempvar column5_row1222 = mask_values[67]; + tempvar column5_row2438 = mask_values[68]; + tempvar column5_row2439 = mask_values[69]; + tempvar column5_row4486 = mask_values[70]; + tempvar column5_row4487 = mask_values[71]; + tempvar column5_row6534 = mask_values[72]; + tempvar column5_row6535 = mask_values[73]; + tempvar column5_row8582 = mask_values[74]; + tempvar column5_row8583 = mask_values[75]; + tempvar column5_row10630 = mask_values[76]; + tempvar column5_row10631 = mask_values[77]; + tempvar column5_row12678 = mask_values[78]; + tempvar column5_row12679 = mask_values[79]; + tempvar column5_row14726 = mask_values[80]; + tempvar column5_row14727 = mask_values[81]; + tempvar column5_row16774 = mask_values[82]; + tempvar column5_row16775 = mask_values[83]; + tempvar column5_row24966 = mask_values[84]; + tempvar column5_row33158 = mask_values[85]; + tempvar column6_row0 = mask_values[86]; + tempvar column6_row1 = mask_values[87]; + tempvar column6_row2 = mask_values[88]; + tempvar column6_row3 = mask_values[89]; + tempvar column7_row0 = mask_values[90]; + tempvar column7_row1 = mask_values[91]; + tempvar column7_row2 = mask_values[92]; + tempvar column7_row3 = mask_values[93]; + tempvar column7_row4 = mask_values[94]; + tempvar column7_row5 = mask_values[95]; + tempvar column7_row6 = mask_values[96]; + tempvar column7_row7 = mask_values[97]; + tempvar column7_row8 = mask_values[98]; + tempvar column7_row9 = mask_values[99]; + tempvar column7_row11 = mask_values[100]; + tempvar column7_row12 = mask_values[101]; + tempvar column7_row13 = mask_values[102]; + tempvar column7_row15 = mask_values[103]; + tempvar column7_row17 = mask_values[104]; + tempvar column7_row19 = mask_values[105]; + tempvar column7_row27 = mask_values[106]; + tempvar column7_row33 = mask_values[107]; + tempvar column7_row44 = mask_values[108]; + tempvar column7_row49 = mask_values[109]; + tempvar column7_row65 = mask_values[110]; + tempvar column7_row76 = mask_values[111]; + tempvar column7_row81 = mask_values[112]; + tempvar column7_row97 = mask_values[113]; + tempvar column7_row108 = mask_values[114]; + tempvar column7_row113 = mask_values[115]; + tempvar column7_row129 = mask_values[116]; + tempvar column7_row140 = mask_values[117]; + tempvar column7_row145 = mask_values[118]; + tempvar column7_row161 = mask_values[119]; + tempvar column7_row172 = mask_values[120]; + tempvar column7_row177 = mask_values[121]; + tempvar column7_row193 = mask_values[122]; + tempvar column7_row204 = mask_values[123]; + tempvar column7_row209 = mask_values[124]; + tempvar column7_row225 = mask_values[125]; + tempvar column7_row236 = mask_values[126]; + tempvar column7_row241 = mask_values[127]; + tempvar column7_row257 = mask_values[128]; + tempvar column7_row265 = mask_values[129]; + tempvar column7_row513 = mask_values[130]; + tempvar column7_row521 = mask_values[131]; + tempvar column7_row705 = mask_values[132]; + tempvar column7_row721 = mask_values[133]; + tempvar column7_row737 = mask_values[134]; + tempvar column7_row753 = mask_values[135]; + tempvar column7_row769 = mask_values[136]; + tempvar column7_row777 = mask_values[137]; + tempvar column7_row961 = mask_values[138]; + tempvar column7_row977 = mask_values[139]; + tempvar column7_row993 = mask_values[140]; + tempvar column7_row1009 = mask_values[141]; + tempvar column8_row0 = mask_values[142]; + tempvar column8_row2 = mask_values[143]; + tempvar column8_row4 = mask_values[144]; + tempvar column8_row6 = mask_values[145]; + tempvar column8_row8 = mask_values[146]; + tempvar column8_row10 = mask_values[147]; + tempvar column8_row12 = mask_values[148]; + tempvar column8_row18 = mask_values[149]; + tempvar column8_row20 = mask_values[150]; + tempvar column8_row22 = mask_values[151]; + tempvar column8_row26 = mask_values[152]; + tempvar column8_row28 = mask_values[153]; + tempvar column8_row34 = mask_values[154]; + tempvar column8_row36 = mask_values[155]; + tempvar column8_row38 = mask_values[156]; + tempvar column8_row42 = mask_values[157]; + tempvar column8_row44 = mask_values[158]; + tempvar column8_row50 = mask_values[159]; + tempvar column8_row52 = mask_values[160]; + tempvar column8_row58 = mask_values[161]; + tempvar column8_row60 = mask_values[162]; + tempvar column8_row66 = mask_values[163]; + tempvar column8_row68 = mask_values[164]; + tempvar column8_row70 = mask_values[165]; + tempvar column8_row76 = mask_values[166]; + tempvar column8_row82 = mask_values[167]; + tempvar column8_row84 = mask_values[168]; + tempvar column8_row86 = mask_values[169]; + tempvar column8_row92 = mask_values[170]; + tempvar column8_row98 = mask_values[171]; + tempvar column8_row100 = mask_values[172]; + tempvar column8_row102 = mask_values[173]; + tempvar column8_row108 = mask_values[174]; + tempvar column8_row116 = mask_values[175]; + tempvar column8_row134 = mask_values[176]; + tempvar column8_row166 = mask_values[177]; + tempvar column8_row198 = mask_values[178]; + tempvar column8_row12306 = mask_values[179]; + tempvar column8_row12370 = mask_values[180]; + tempvar column8_row12562 = mask_values[181]; + tempvar column8_row12626 = mask_values[182]; + tempvar column8_row16082 = mask_values[183]; + tempvar column8_row16146 = mask_values[184]; + tempvar column8_row16322 = mask_values[185]; + tempvar column8_row16330 = mask_values[186]; + tempvar column8_row16340 = mask_values[187]; + tempvar column8_row16346 = mask_values[188]; + tempvar column8_row16354 = mask_values[189]; + tempvar column8_row16362 = mask_values[190]; + tempvar column8_row16370 = mask_values[191]; + tempvar column8_row16372 = mask_values[192]; + tempvar column8_row16378 = mask_values[193]; + tempvar column8_row16388 = mask_values[194]; + tempvar column8_row16420 = mask_values[195]; + tempvar column8_row32646 = mask_values[196]; + tempvar column8_row32662 = mask_values[197]; + tempvar column8_row32710 = mask_values[198]; + tempvar column8_row32724 = mask_values[199]; + tempvar column8_row32730 = mask_values[200]; + tempvar column8_row32742 = mask_values[201]; + tempvar column8_row32756 = mask_values[202]; + tempvar column8_row32762 = mask_values[203]; + tempvar column9_inter1_row0 = mask_values[204]; + tempvar column9_inter1_row1 = mask_values[205]; + tempvar column9_inter1_row2 = mask_values[206]; + tempvar column9_inter1_row3 = mask_values[207]; + tempvar column9_inter1_row5 = mask_values[208]; + tempvar column9_inter1_row7 = mask_values[209]; + tempvar column9_inter1_row11 = mask_values[210]; + tempvar column9_inter1_row15 = mask_values[211]; + + // Compute intermediate values. + tempvar cpu__decode__opcode_rc__bit_0 = column0_row0 - (column0_row1 + column0_row1); + tempvar cpu__decode__opcode_rc__bit_2 = column0_row2 - (column0_row3 + column0_row3); + tempvar cpu__decode__opcode_rc__bit_4 = column0_row4 - (column0_row5 + column0_row5); + tempvar cpu__decode__opcode_rc__bit_3 = column0_row3 - (column0_row4 + column0_row4); + tempvar cpu__decode__flag_op1_base_op0_0 = 1 - (cpu__decode__opcode_rc__bit_2 + cpu__decode__opcode_rc__bit_4 + cpu__decode__opcode_rc__bit_3); + tempvar cpu__decode__opcode_rc__bit_5 = column0_row5 - (column0_row6 + column0_row6); + tempvar cpu__decode__opcode_rc__bit_6 = column0_row6 - (column0_row7 + column0_row7); + tempvar cpu__decode__opcode_rc__bit_9 = column0_row9 - (column0_row10 + column0_row10); + tempvar cpu__decode__flag_res_op1_0 = 1 - (cpu__decode__opcode_rc__bit_5 + cpu__decode__opcode_rc__bit_6 + cpu__decode__opcode_rc__bit_9); + tempvar cpu__decode__opcode_rc__bit_7 = column0_row7 - (column0_row8 + column0_row8); + tempvar cpu__decode__opcode_rc__bit_8 = column0_row8 - (column0_row9 + column0_row9); + tempvar cpu__decode__flag_pc_update_regular_0 = 1 - (cpu__decode__opcode_rc__bit_7 + cpu__decode__opcode_rc__bit_8 + cpu__decode__opcode_rc__bit_9); + tempvar cpu__decode__opcode_rc__bit_12 = column0_row12 - (column0_row13 + column0_row13); + tempvar cpu__decode__opcode_rc__bit_13 = column0_row13 - (column0_row14 + column0_row14); + tempvar cpu__decode__fp_update_regular_0 = 1 - (cpu__decode__opcode_rc__bit_12 + cpu__decode__opcode_rc__bit_13); + tempvar cpu__decode__opcode_rc__bit_1 = column0_row1 - (column0_row2 + column0_row2); + tempvar npc_reg_0 = column5_row0 + cpu__decode__opcode_rc__bit_2 + 1; + tempvar cpu__decode__opcode_rc__bit_10 = column0_row10 - (column0_row11 + column0_row11); + tempvar cpu__decode__opcode_rc__bit_11 = column0_row11 - (column0_row12 + column0_row12); + tempvar cpu__decode__opcode_rc__bit_14 = column0_row14 - (column0_row15 + column0_row15); + tempvar memory__address_diff_0 = column6_row2 - column6_row0; + tempvar rc16__diff_0 = column7_row6 - column7_row2; + tempvar pedersen__hash0__ec_subset_sum__bit_0 = column3_row0 - (column3_row1 + column3_row1); + tempvar pedersen__hash0__ec_subset_sum__bit_neg_0 = 1 - pedersen__hash0__ec_subset_sum__bit_0; + tempvar rc_builtin__value0_0 = column7_row12; + tempvar rc_builtin__value1_0 = rc_builtin__value0_0 * global_values.offset_size + column7_row44; + tempvar rc_builtin__value2_0 = rc_builtin__value1_0 * global_values.offset_size + column7_row76; + tempvar rc_builtin__value3_0 = rc_builtin__value2_0 * global_values.offset_size + column7_row108; + tempvar rc_builtin__value4_0 = rc_builtin__value3_0 * global_values.offset_size + column7_row140; + tempvar rc_builtin__value5_0 = rc_builtin__value4_0 * global_values.offset_size + column7_row172; + tempvar rc_builtin__value6_0 = rc_builtin__value5_0 * global_values.offset_size + column7_row204; + tempvar rc_builtin__value7_0 = rc_builtin__value6_0 * global_values.offset_size + column7_row236; + tempvar ecdsa__signature0__doubling_key__x_squared = column8_row4 * column8_row4; + tempvar ecdsa__signature0__exponentiate_generator__bit_0 = column8_row38 - (column8_row166 + column8_row166); + tempvar ecdsa__signature0__exponentiate_generator__bit_neg_0 = 1 - ecdsa__signature0__exponentiate_generator__bit_0; + tempvar ecdsa__signature0__exponentiate_key__bit_0 = column8_row12 - (column8_row76 + column8_row76); + tempvar ecdsa__signature0__exponentiate_key__bit_neg_0 = 1 - ecdsa__signature0__exponentiate_key__bit_0; + tempvar bitwise__sum_var_0_0 = column7_row1 + column7_row17 * 2 + column7_row33 * 4 + column7_row49 * 8 + column7_row65 * 18446744073709551616 + column7_row81 * 36893488147419103232 + column7_row97 * 73786976294838206464 + column7_row113 * 147573952589676412928; + tempvar bitwise__sum_var_8_0 = column7_row129 * 340282366920938463463374607431768211456 + column7_row145 * 680564733841876926926749214863536422912 + column7_row161 * 1361129467683753853853498429727072845824 + column7_row177 * 2722258935367507707706996859454145691648 + column7_row193 * 6277101735386680763835789423207666416102355444464034512896 + column7_row209 * 12554203470773361527671578846415332832204710888928069025792 + column7_row225 * 25108406941546723055343157692830665664409421777856138051584 + column7_row241 * 50216813883093446110686315385661331328818843555712276103168; + tempvar ec_op__doubling_q__x_squared_0 = column8_row44 * column8_row44; + tempvar ec_op__ec_subset_sum__bit_0 = column8_row18 - (column8_row82 + column8_row82); + tempvar ec_op__ec_subset_sum__bit_neg_0 = 1 - ec_op__ec_subset_sum__bit_0; + + // Sum constraints. + tempvar total_sum = 0; + + // Constraint: cpu/decode/opcode_rc/bit. + tempvar value = (cpu__decode__opcode_rc__bit_0 * cpu__decode__opcode_rc__bit_0 - cpu__decode__opcode_rc__bit_0) * domain4 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[0] * value; + + // Constraint: cpu/decode/opcode_rc/zero. + tempvar value = (column0_row0) / domain4; + tempvar total_sum = total_sum + constraint_coefficients[1] * value; + + // Constraint: cpu/decode/opcode_rc_input. + tempvar value = (column5_row1 - (((column0_row0 * global_values.offset_size + column7_row4) * global_values.offset_size + column7_row8) * global_values.offset_size + column7_row0)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[2] * value; + + // Constraint: cpu/decode/flag_op1_base_op0_bit. + tempvar value = (cpu__decode__flag_op1_base_op0_0 * cpu__decode__flag_op1_base_op0_0 - cpu__decode__flag_op1_base_op0_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[3] * value; + + // Constraint: cpu/decode/flag_res_op1_bit. + tempvar value = (cpu__decode__flag_res_op1_0 * cpu__decode__flag_res_op1_0 - cpu__decode__flag_res_op1_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[4] * value; + + // Constraint: cpu/decode/flag_pc_update_regular_bit. + tempvar value = (cpu__decode__flag_pc_update_regular_0 * cpu__decode__flag_pc_update_regular_0 - cpu__decode__flag_pc_update_regular_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[5] * value; + + // Constraint: cpu/decode/fp_update_regular_bit. + tempvar value = (cpu__decode__fp_update_regular_0 * cpu__decode__fp_update_regular_0 - cpu__decode__fp_update_regular_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[6] * value; + + // Constraint: cpu/operands/mem_dst_addr. + tempvar value = (column5_row8 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_0 * column7_row11 + (1 - cpu__decode__opcode_rc__bit_0) * column7_row3 + column7_row0)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[7] * value; + + // Constraint: cpu/operands/mem0_addr. + tempvar value = (column5_row4 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_1 * column7_row11 + (1 - cpu__decode__opcode_rc__bit_1) * column7_row3 + column7_row8)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[8] * value; + + // Constraint: cpu/operands/mem1_addr. + tempvar value = (column5_row12 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_2 * column5_row0 + cpu__decode__opcode_rc__bit_4 * column7_row3 + cpu__decode__opcode_rc__bit_3 * column7_row11 + cpu__decode__flag_op1_base_op0_0 * column5_row5 + column7_row4)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[9] * value; + + // Constraint: cpu/operands/ops_mul. + tempvar value = (column7_row7 - column5_row5 * column5_row13) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[10] * value; + + // Constraint: cpu/operands/res. + tempvar value = ((1 - cpu__decode__opcode_rc__bit_9) * column7_row15 - (cpu__decode__opcode_rc__bit_5 * (column5_row5 + column5_row13) + cpu__decode__opcode_rc__bit_6 * column7_row7 + cpu__decode__flag_res_op1_0 * column5_row13)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[11] * value; + + // Constraint: cpu/update_registers/update_pc/tmp0. + tempvar value = (column8_row0 - cpu__decode__opcode_rc__bit_9 * column5_row9) * domain23 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[12] * value; + + // Constraint: cpu/update_registers/update_pc/tmp1. + tempvar value = (column8_row8 - column8_row0 * column7_row15) * domain23 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[13] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_negative. + tempvar value = ((1 - cpu__decode__opcode_rc__bit_9) * column5_row16 + column8_row0 * (column5_row16 - (column5_row0 + column5_row13)) - (cpu__decode__flag_pc_update_regular_0 * npc_reg_0 + cpu__decode__opcode_rc__bit_7 * column7_row15 + cpu__decode__opcode_rc__bit_8 * (column5_row0 + column7_row15))) * domain23 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[14] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_positive. + tempvar value = ((column8_row8 - cpu__decode__opcode_rc__bit_9) * (column5_row16 - npc_reg_0)) * domain23 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[15] * value; + + // Constraint: cpu/update_registers/update_ap/ap_update. + tempvar value = (column7_row19 - (column7_row3 + cpu__decode__opcode_rc__bit_10 * column7_row15 + cpu__decode__opcode_rc__bit_11 + cpu__decode__opcode_rc__bit_12 * 2)) * domain23 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[16] * value; + + // Constraint: cpu/update_registers/update_fp/fp_update. + tempvar value = (column7_row27 - (cpu__decode__fp_update_regular_0 * column7_row11 + cpu__decode__opcode_rc__bit_13 * column5_row9 + cpu__decode__opcode_rc__bit_12 * (column7_row3 + 2))) * domain23 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[17] * value; + + // Constraint: cpu/opcodes/call/push_fp. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column5_row9 - column7_row11)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[18] * value; + + // Constraint: cpu/opcodes/call/push_pc. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column5_row5 - (column5_row0 + cpu__decode__opcode_rc__bit_2 + 1))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[19] * value; + + // Constraint: cpu/opcodes/call/off0. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column7_row0 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[20] * value; + + // Constraint: cpu/opcodes/call/off1. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column7_row8 - (global_values.half_offset_size + 1))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[21] * value; + + // Constraint: cpu/opcodes/call/flags. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (cpu__decode__opcode_rc__bit_12 + cpu__decode__opcode_rc__bit_12 + 1 + 1 - (cpu__decode__opcode_rc__bit_0 + cpu__decode__opcode_rc__bit_1 + 4))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[22] * value; + + // Constraint: cpu/opcodes/ret/off0. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (column7_row0 + 2 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[23] * value; + + // Constraint: cpu/opcodes/ret/off2. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (column7_row4 + 1 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[24] * value; + + // Constraint: cpu/opcodes/ret/flags. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (cpu__decode__opcode_rc__bit_7 + cpu__decode__opcode_rc__bit_0 + cpu__decode__opcode_rc__bit_3 + cpu__decode__flag_res_op1_0 - 4)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[25] * value; + + // Constraint: cpu/opcodes/assert_eq/assert_eq. + tempvar value = (cpu__decode__opcode_rc__bit_14 * (column5_row9 - column7_row15)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[26] * value; + + // Constraint: initial_ap. + tempvar value = (column7_row3 - global_values.initial_ap) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[27] * value; + + // Constraint: initial_fp. + tempvar value = (column7_row11 - global_values.initial_ap) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[28] * value; + + // Constraint: initial_pc. + tempvar value = (column5_row0 - global_values.initial_pc) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[29] * value; + + // Constraint: final_ap. + tempvar value = (column7_row3 - global_values.final_ap) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[30] * value; + + // Constraint: final_fp. + tempvar value = (column7_row11 - global_values.initial_ap) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[31] * value; + + // Constraint: final_pc. + tempvar value = (column5_row0 - global_values.final_pc) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[32] * value; + + // Constraint: memory/multi_column_perm/perm/init0. + tempvar value = ((global_values.memory__multi_column_perm__perm__interaction_elm - (column6_row0 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column6_row1)) * column9_inter1_row0 + column5_row0 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column5_row1 - global_values.memory__multi_column_perm__perm__interaction_elm) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[33] * value; + + // Constraint: memory/multi_column_perm/perm/step0. + tempvar value = ((global_values.memory__multi_column_perm__perm__interaction_elm - (column6_row2 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column6_row3)) * column9_inter1_row2 - (global_values.memory__multi_column_perm__perm__interaction_elm - (column5_row2 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column5_row3)) * column9_inter1_row0) * domain25 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[34] * value; + + // Constraint: memory/multi_column_perm/perm/last. + tempvar value = (column9_inter1_row0 - global_values.memory__multi_column_perm__perm__public_memory_prod) / domain25; + tempvar total_sum = total_sum + constraint_coefficients[35] * value; + + // Constraint: memory/diff_is_bit. + tempvar value = (memory__address_diff_0 * memory__address_diff_0 - memory__address_diff_0) * domain25 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[36] * value; + + // Constraint: memory/is_func. + tempvar value = ((memory__address_diff_0 - 1) * (column6_row1 - column6_row3)) * domain25 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[37] * value; + + // Constraint: memory/initial_addr. + tempvar value = (column6_row0 - 1) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[38] * value; + + // Constraint: public_memory_addr_zero. + tempvar value = (column5_row2) / domain3; + tempvar total_sum = total_sum + constraint_coefficients[39] * value; + + // Constraint: public_memory_value_zero. + tempvar value = (column5_row3) / domain3; + tempvar total_sum = total_sum + constraint_coefficients[40] * value; + + // Constraint: rc16/perm/init0. + tempvar value = ((global_values.rc16__perm__interaction_elm - column7_row2) * column9_inter1_row1 + column7_row0 - global_values.rc16__perm__interaction_elm) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[41] * value; + + // Constraint: rc16/perm/step0. + tempvar value = ((global_values.rc16__perm__interaction_elm - column7_row6) * column9_inter1_row5 - (global_values.rc16__perm__interaction_elm - column7_row4) * column9_inter1_row1) * domain26 / domain2; + tempvar total_sum = total_sum + constraint_coefficients[42] * value; + + // Constraint: rc16/perm/last. + tempvar value = (column9_inter1_row1 - global_values.rc16__perm__public_memory_prod) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[43] * value; + + // Constraint: rc16/diff_is_bit. + tempvar value = (rc16__diff_0 * rc16__diff_0 - rc16__diff_0) * domain26 / domain2; + tempvar total_sum = total_sum + constraint_coefficients[44] * value; + + // Constraint: rc16/minimum. + tempvar value = (column7_row2 - global_values.rc_min) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[45] * value; + + // Constraint: rc16/maximum. + tempvar value = (column7_row2 - global_values.rc_max) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[46] * value; + + // Constraint: diluted_check/permutation/init0. + tempvar value = ((global_values.diluted_check__permutation__interaction_elm - column7_row5) * column9_inter1_row7 + column7_row1 - global_values.diluted_check__permutation__interaction_elm) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[47] * value; + + // Constraint: diluted_check/permutation/step0. + tempvar value = ((global_values.diluted_check__permutation__interaction_elm - column7_row13) * column9_inter1_row15 - (global_values.diluted_check__permutation__interaction_elm - column7_row9) * column9_inter1_row7) * domain27 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[48] * value; + + // Constraint: diluted_check/permutation/last. + tempvar value = (column9_inter1_row7 - global_values.diluted_check__permutation__public_memory_prod) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[49] * value; + + // Constraint: diluted_check/init. + tempvar value = (column9_inter1_row3 - 1) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[50] * value; + + // Constraint: diluted_check/first_element. + tempvar value = (column7_row5 - global_values.diluted_check__first_elm) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[51] * value; + + // Constraint: diluted_check/step. + tempvar value = (column9_inter1_row11 - (column9_inter1_row3 * (1 + global_values.diluted_check__interaction_z * (column7_row13 - column7_row5)) + global_values.diluted_check__interaction_alpha * (column7_row13 - column7_row5) * (column7_row13 - column7_row5))) * domain27 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[52] * value; + + // Constraint: diluted_check/last. + tempvar value = (column9_inter1_row3 - global_values.diluted_check__final_cum_val) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[53] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/last_one_is_zero. + tempvar value = (column8_row86 * (column3_row0 - (column3_row1 + column3_row1))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[54] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + tempvar value = (column8_row86 * (column3_row1 - 3138550867693340381917894711603833208051177722232017256448 * column3_row192)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[55] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit192. + tempvar value = (column8_row86 - column4_row255 * (column3_row192 - (column3_row193 + column3_row193))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[56] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + tempvar value = (column4_row255 * (column3_row193 - 8 * column3_row196)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[57] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit196. + tempvar value = (column4_row255 - (column3_row251 - (column3_row252 + column3_row252)) * (column3_row196 - (column3_row197 + column3_row197))) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[58] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + tempvar value = ((column3_row251 - (column3_row252 + column3_row252)) * (column3_row197 - 18014398509481984 * column3_row251)) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[59] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/booleanity_test. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (pedersen__hash0__ec_subset_sum__bit_0 - 1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[60] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_extraction_end. + tempvar value = (column3_row0) / domain10; + tempvar total_sum = total_sum + constraint_coefficients[61] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/zeros_tail. + tempvar value = (column3_row0) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[62] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/slope. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (column2_row0 - global_values.pedersen__points__y) - column4_row0 * (column1_row0 - global_values.pedersen__points__x)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[63] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/x. + tempvar value = (column4_row0 * column4_row0 - pedersen__hash0__ec_subset_sum__bit_0 * (column1_row0 + global_values.pedersen__points__x + column1_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[64] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/y. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (column2_row0 + column2_row1) - column4_row0 * (column1_row0 - column1_row1)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[65] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/x. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_neg_0 * (column1_row1 - column1_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[66] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/y. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_neg_0 * (column2_row1 - column2_row0)) * domain9 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[67] * value; + + // Constraint: pedersen/hash0/copy_point/x. + tempvar value = (column1_row256 - column1_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[68] * value; + + // Constraint: pedersen/hash0/copy_point/y. + tempvar value = (column2_row256 - column2_row255) * domain11 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[69] * value; + + // Constraint: pedersen/hash0/init/x. + tempvar value = (column1_row0 - global_values.pedersen__shift_point.x) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[70] * value; + + // Constraint: pedersen/hash0/init/y. + tempvar value = (column2_row0 - global_values.pedersen__shift_point.y) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[71] * value; + + // Constraint: pedersen/input0_value0. + tempvar value = (column5_row7 - column3_row0) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[72] * value; + + // Constraint: pedersen/input0_addr. + tempvar value = (column5_row518 - (column5_row134 + 1)) * domain28 / domain12; + tempvar total_sum = total_sum + constraint_coefficients[73] * value; + + // Constraint: pedersen/init_addr. + tempvar value = (column5_row6 - global_values.initial_pedersen_addr) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[74] * value; + + // Constraint: pedersen/input1_value0. + tempvar value = (column5_row263 - column3_row256) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[75] * value; + + // Constraint: pedersen/input1_addr. + tempvar value = (column5_row262 - (column5_row6 + 1)) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[76] * value; + + // Constraint: pedersen/output_value0. + tempvar value = (column5_row135 - column1_row511) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[77] * value; + + // Constraint: pedersen/output_addr. + tempvar value = (column5_row134 - (column5_row262 + 1)) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[78] * value; + + // Constraint: rc_builtin/value. + tempvar value = (rc_builtin__value7_0 - column5_row71) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[79] * value; + + // Constraint: rc_builtin/addr_step. + tempvar value = (column5_row326 - (column5_row70 + 1)) * domain29 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[80] * value; + + // Constraint: rc_builtin/init_addr. + tempvar value = (column5_row70 - global_values.initial_rc_addr) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[81] * value; + + // Constraint: ecdsa/signature0/doubling_key/slope. + tempvar value = (ecdsa__signature0__doubling_key__x_squared + ecdsa__signature0__doubling_key__x_squared + ecdsa__signature0__doubling_key__x_squared + global_values.ecdsa__sig_config.alpha - (column8_row36 + column8_row36) * column8_row50) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[82] * value; + + // Constraint: ecdsa/signature0/doubling_key/x. + tempvar value = (column8_row50 * column8_row50 - (column8_row4 + column8_row4 + column8_row68)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[83] * value; + + // Constraint: ecdsa/signature0/doubling_key/y. + tempvar value = (column8_row36 + column8_row100 - column8_row50 * (column8_row4 - column8_row68)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[84] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/booleanity_test. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (ecdsa__signature0__exponentiate_generator__bit_0 - 1)) * domain20 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[85] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/bit_extraction_end. + tempvar value = (column8_row38) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[86] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/zeros_tail. + tempvar value = (column8_row38) / domain20; + tempvar total_sum = total_sum + constraint_coefficients[87] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/slope. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (column8_row70 - global_values.ecdsa__generator_points__y) - column8_row102 * (column8_row6 - global_values.ecdsa__generator_points__x)) * domain20 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[88] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/x. + tempvar value = (column8_row102 * column8_row102 - ecdsa__signature0__exponentiate_generator__bit_0 * (column8_row6 + global_values.ecdsa__generator_points__x + column8_row134)) * domain20 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[89] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/y. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_0 * (column8_row70 + column8_row198) - column8_row102 * (column8_row6 - column8_row134)) * domain20 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[90] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/add_points/x_diff_inv. + tempvar value = (column8_row22 * (column8_row6 - global_values.ecdsa__generator_points__x) - 1) * domain20 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[91] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/copy_point/x. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_neg_0 * (column8_row134 - column8_row6)) * domain20 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[92] * value; + + // Constraint: ecdsa/signature0/exponentiate_generator/copy_point/y. + tempvar value = (ecdsa__signature0__exponentiate_generator__bit_neg_0 * (column8_row198 - column8_row70)) * domain20 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[93] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/booleanity_test. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (ecdsa__signature0__exponentiate_key__bit_0 - 1)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[94] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/bit_extraction_end. + tempvar value = (column8_row12) / domain17; + tempvar total_sum = total_sum + constraint_coefficients[95] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/zeros_tail. + tempvar value = (column8_row12) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[96] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/slope. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (column8_row52 - column8_row36) - column8_row10 * (column8_row20 - column8_row4)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[97] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/x. + tempvar value = (column8_row10 * column8_row10 - ecdsa__signature0__exponentiate_key__bit_0 * (column8_row20 + column8_row4 + column8_row84)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[98] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/y. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_0 * (column8_row52 + column8_row116) - column8_row10 * (column8_row20 - column8_row84)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[99] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/add_points/x_diff_inv. + tempvar value = (column8_row42 * (column8_row20 - column8_row4) - 1) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[100] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/copy_point/x. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_neg_0 * (column8_row84 - column8_row20)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[101] * value; + + // Constraint: ecdsa/signature0/exponentiate_key/copy_point/y. + tempvar value = (ecdsa__signature0__exponentiate_key__bit_neg_0 * (column8_row116 - column8_row52)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[102] * value; + + // Constraint: ecdsa/signature0/init_gen/x. + tempvar value = (column8_row6 - global_values.ecdsa__sig_config.shift_point.x) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[103] * value; + + // Constraint: ecdsa/signature0/init_gen/y. + tempvar value = (column8_row70 + global_values.ecdsa__sig_config.shift_point.y) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[104] * value; + + // Constraint: ecdsa/signature0/init_key/x. + tempvar value = (column8_row20 - global_values.ecdsa__sig_config.shift_point.x) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[105] * value; + + // Constraint: ecdsa/signature0/init_key/y. + tempvar value = (column8_row52 - global_values.ecdsa__sig_config.shift_point.y) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[106] * value; + + // Constraint: ecdsa/signature0/add_results/slope. + tempvar value = (column8_row32710 - (column8_row16372 + column8_row32742 * (column8_row32646 - column8_row16340))) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[107] * value; + + // Constraint: ecdsa/signature0/add_results/x. + tempvar value = (column8_row32742 * column8_row32742 - (column8_row32646 + column8_row16340 + column8_row16388)) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[108] * value; + + // Constraint: ecdsa/signature0/add_results/y. + tempvar value = (column8_row32710 + column8_row16420 - column8_row32742 * (column8_row32646 - column8_row16388)) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[109] * value; + + // Constraint: ecdsa/signature0/add_results/x_diff_inv. + tempvar value = (column8_row32662 * (column8_row32646 - column8_row16340) - 1) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[110] * value; + + // Constraint: ecdsa/signature0/extract_r/slope. + tempvar value = (column8_row32756 + global_values.ecdsa__sig_config.shift_point.y - column8_row16346 * (column8_row32724 - global_values.ecdsa__sig_config.shift_point.x)) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[111] * value; + + // Constraint: ecdsa/signature0/extract_r/x. + tempvar value = (column8_row16346 * column8_row16346 - (column8_row32724 + global_values.ecdsa__sig_config.shift_point.x + column8_row12)) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[112] * value; + + // Constraint: ecdsa/signature0/extract_r/x_diff_inv. + tempvar value = (column8_row32730 * (column8_row32724 - global_values.ecdsa__sig_config.shift_point.x) - 1) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[113] * value; + + // Constraint: ecdsa/signature0/z_nonzero. + tempvar value = (column8_row38 * column8_row16378 - 1) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[114] * value; + + // Constraint: ecdsa/signature0/r_and_w_nonzero. + tempvar value = (column8_row12 * column8_row16370 - 1) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[115] * value; + + // Constraint: ecdsa/signature0/q_on_curve/x_squared. + tempvar value = (column8_row32762 - column8_row4 * column8_row4) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[116] * value; + + // Constraint: ecdsa/signature0/q_on_curve/on_curve. + tempvar value = (column8_row36 * column8_row36 - (column8_row4 * column8_row32762 + global_values.ecdsa__sig_config.alpha * column8_row4 + global_values.ecdsa__sig_config.beta)) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[117] * value; + + // Constraint: ecdsa/init_addr. + tempvar value = (column5_row390 - global_values.initial_ecdsa_addr) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[118] * value; + + // Constraint: ecdsa/message_addr. + tempvar value = (column5_row16774 - (column5_row390 + 1)) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[119] * value; + + // Constraint: ecdsa/pubkey_addr. + tempvar value = (column5_row33158 - (column5_row16774 + 1)) * domain30 / domain22; + tempvar total_sum = total_sum + constraint_coefficients[120] * value; + + // Constraint: ecdsa/message_value0. + tempvar value = (column5_row16775 - column8_row38) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[121] * value; + + // Constraint: ecdsa/pubkey_value0. + tempvar value = (column5_row391 - column8_row4) / domain22; + tempvar total_sum = total_sum + constraint_coefficients[122] * value; + + // Constraint: bitwise/init_var_pool_addr. + tempvar value = (column5_row198 - global_values.initial_bitwise_addr) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[123] * value; + + // Constraint: bitwise/step_var_pool_addr. + tempvar value = (column5_row454 - (column5_row198 + 1)) * domain13 / domain8; + tempvar total_sum = total_sum + constraint_coefficients[124] * value; + + // Constraint: bitwise/x_or_y_addr. + tempvar value = (column5_row902 - (column5_row966 + 1)) / domain14; + tempvar total_sum = total_sum + constraint_coefficients[125] * value; + + // Constraint: bitwise/next_var_pool_addr. + tempvar value = (column5_row1222 - (column5_row902 + 1)) * domain31 / domain14; + tempvar total_sum = total_sum + constraint_coefficients[126] * value; + + // Constraint: bitwise/partition. + tempvar value = (bitwise__sum_var_0_0 + bitwise__sum_var_8_0 - column5_row199) / domain8; + tempvar total_sum = total_sum + constraint_coefficients[127] * value; + + // Constraint: bitwise/or_is_and_plus_xor. + tempvar value = (column5_row903 - (column5_row711 + column5_row967)) / domain14; + tempvar total_sum = total_sum + constraint_coefficients[128] * value; + + // Constraint: bitwise/addition_is_xor_with_and. + tempvar value = (column7_row1 + column7_row257 - (column7_row769 + column7_row513 + column7_row513)) / domain15; + tempvar total_sum = total_sum + constraint_coefficients[129] * value; + + // Constraint: bitwise/unique_unpacking192. + tempvar value = ((column7_row705 + column7_row961) * 16 - column7_row9) / domain14; + tempvar total_sum = total_sum + constraint_coefficients[130] * value; + + // Constraint: bitwise/unique_unpacking193. + tempvar value = ((column7_row721 + column7_row977) * 16 - column7_row521) / domain14; + tempvar total_sum = total_sum + constraint_coefficients[131] * value; + + // Constraint: bitwise/unique_unpacking194. + tempvar value = ((column7_row737 + column7_row993) * 16 - column7_row265) / domain14; + tempvar total_sum = total_sum + constraint_coefficients[132] * value; + + // Constraint: bitwise/unique_unpacking195. + tempvar value = ((column7_row753 + column7_row1009) * 256 - column7_row777) / domain14; + tempvar total_sum = total_sum + constraint_coefficients[133] * value; + + // Constraint: ec_op/init_addr. + tempvar value = (column5_row8582 - global_values.initial_ec_op_addr) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[134] * value; + + // Constraint: ec_op/p_x_addr. + tempvar value = (column5_row24966 - (column5_row8582 + 7)) * domain32 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[135] * value; + + // Constraint: ec_op/p_y_addr. + tempvar value = (column5_row4486 - (column5_row8582 + 1)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[136] * value; + + // Constraint: ec_op/q_x_addr. + tempvar value = (column5_row12678 - (column5_row4486 + 1)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[137] * value; + + // Constraint: ec_op/q_y_addr. + tempvar value = (column5_row2438 - (column5_row12678 + 1)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[138] * value; + + // Constraint: ec_op/m_addr. + tempvar value = (column5_row10630 - (column5_row2438 + 1)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[139] * value; + + // Constraint: ec_op/r_x_addr. + tempvar value = (column5_row6534 - (column5_row10630 + 1)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[140] * value; + + // Constraint: ec_op/r_y_addr. + tempvar value = (column5_row14726 - (column5_row6534 + 1)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[141] * value; + + // Constraint: ec_op/doubling_q/slope. + tempvar value = (ec_op__doubling_q__x_squared_0 + ec_op__doubling_q__x_squared_0 + ec_op__doubling_q__x_squared_0 + global_values.ec_op__curve_config.alpha - (column8_row28 + column8_row28) * column8_row60) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[142] * value; + + // Constraint: ec_op/doubling_q/x. + tempvar value = (column8_row60 * column8_row60 - (column8_row44 + column8_row44 + column8_row108)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[143] * value; + + // Constraint: ec_op/doubling_q/y. + tempvar value = (column8_row28 + column8_row92 - column8_row60 * (column8_row44 - column8_row108)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[144] * value; + + // Constraint: ec_op/get_q_x. + tempvar value = (column5_row12679 - column8_row44) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[145] * value; + + // Constraint: ec_op/get_q_y. + tempvar value = (column5_row2439 - column8_row28) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[146] * value; + + // Constraint: ec_op/ec_subset_sum/bit_unpacking/last_one_is_zero. + tempvar value = (column8_row16362 * (column8_row18 - (column8_row82 + column8_row82))) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[147] * value; + + // Constraint: ec_op/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + tempvar value = (column8_row16362 * (column8_row82 - 3138550867693340381917894711603833208051177722232017256448 * column8_row12306)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[148] * value; + + // Constraint: ec_op/ec_subset_sum/bit_unpacking/cumulative_bit192. + tempvar value = (column8_row16362 - column8_row16330 * (column8_row12306 - (column8_row12370 + column8_row12370))) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[149] * value; + + // Constraint: ec_op/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + tempvar value = (column8_row16330 * (column8_row12370 - 8 * column8_row12562)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[150] * value; + + // Constraint: ec_op/ec_subset_sum/bit_unpacking/cumulative_bit196. + tempvar value = (column8_row16330 - (column8_row16082 - (column8_row16146 + column8_row16146)) * (column8_row12562 - (column8_row12626 + column8_row12626))) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[151] * value; + + // Constraint: ec_op/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + tempvar value = ((column8_row16082 - (column8_row16146 + column8_row16146)) * (column8_row12626 - 18014398509481984 * column8_row16082)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[152] * value; + + // Constraint: ec_op/ec_subset_sum/booleanity_test. + tempvar value = (ec_op__ec_subset_sum__bit_0 * (ec_op__ec_subset_sum__bit_0 - 1)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[153] * value; + + // Constraint: ec_op/ec_subset_sum/bit_extraction_end. + tempvar value = (column8_row18) / domain19; + tempvar total_sum = total_sum + constraint_coefficients[154] * value; + + // Constraint: ec_op/ec_subset_sum/zeros_tail. + tempvar value = (column8_row18) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[155] * value; + + // Constraint: ec_op/ec_subset_sum/add_points/slope. + tempvar value = (ec_op__ec_subset_sum__bit_0 * (column8_row34 - column8_row28) - column8_row26 * (column8_row2 - column8_row44)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[156] * value; + + // Constraint: ec_op/ec_subset_sum/add_points/x. + tempvar value = (column8_row26 * column8_row26 - ec_op__ec_subset_sum__bit_0 * (column8_row2 + column8_row44 + column8_row66)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[157] * value; + + // Constraint: ec_op/ec_subset_sum/add_points/y. + tempvar value = (ec_op__ec_subset_sum__bit_0 * (column8_row34 + column8_row98) - column8_row26 * (column8_row2 - column8_row66)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[158] * value; + + // Constraint: ec_op/ec_subset_sum/add_points/x_diff_inv. + tempvar value = (column8_row58 * (column8_row2 - column8_row44) - 1) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[159] * value; + + // Constraint: ec_op/ec_subset_sum/copy_point/x. + tempvar value = (ec_op__ec_subset_sum__bit_neg_0 * (column8_row66 - column8_row2)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[160] * value; + + // Constraint: ec_op/ec_subset_sum/copy_point/y. + tempvar value = (ec_op__ec_subset_sum__bit_neg_0 * (column8_row98 - column8_row34)) * domain16 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[161] * value; + + // Constraint: ec_op/get_m. + tempvar value = (column8_row18 - column5_row10631) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[162] * value; + + // Constraint: ec_op/get_p_x. + tempvar value = (column5_row8583 - column8_row2) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[163] * value; + + // Constraint: ec_op/get_p_y. + tempvar value = (column5_row4487 - column8_row34) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[164] * value; + + // Constraint: ec_op/set_r_x. + tempvar value = (column5_row6535 - column8_row16322) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[165] * value; + + // Constraint: ec_op/set_r_y. + tempvar value = (column5_row14727 - column8_row16354) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[166] * value; + + return (res=total_sum); +} + +func eval_oods_polynomial{range_check_ptr}( + self: felt*, + column_values: felt*, + oods_values: felt*, + constraint_coefficients: felt*, + point: felt, + oods_point: felt, + trace_generator: felt, + global_values: OodsGlobalValues*, +) -> (res: felt) { + alloc_locals; + + // Compute powers. + let (local pow0) = pow(trace_generator, 0); + let (local pow1) = pow(trace_generator, 1); + local pow2 = pow1 * pow1; + local pow3 = pow1 * pow2; + local pow4 = pow1 * pow3; + local pow5 = pow1 * pow4; + local pow6 = pow1 * pow5; + local pow7 = pow1 * pow6; + local pow8 = pow1 * pow7; + local pow9 = pow1 * pow8; + local pow10 = pow1 * pow9; + local pow11 = pow1 * pow10; + local pow12 = pow1 * pow11; + local pow13 = pow1 * pow12; + local pow14 = pow1 * pow13; + local pow15 = pow1 * pow14; + local pow16 = pow1 * pow15; + local pow17 = pow1 * pow16; + local pow18 = pow1 * pow17; + local pow19 = pow1 * pow18; + local pow20 = pow1 * pow19; + local pow21 = pow2 * pow20; + local pow22 = pow4 * pow21; + local pow23 = pow1 * pow22; + local pow24 = pow1 * pow23; + local pow25 = pow5 * pow24; + local pow26 = pow1 * pow25; + local pow27 = pow2 * pow26; + local pow28 = pow2 * pow27; + local pow29 = pow4 * pow28; + local pow30 = pow2 * pow29; + local pow31 = pow5 * pow30; + local pow32 = pow1 * pow31; + local pow33 = pow2 * pow32; + local pow34 = pow6 * pow33; + local pow35 = pow2 * pow34; + local pow36 = pow5 * pow35; + local pow37 = pow1 * pow36; + local pow38 = pow2 * pow37; + local pow39 = pow2 * pow38; + local pow40 = pow1 * pow39; + local pow41 = pow5 * pow40; + local pow42 = pow5 * pow41; + local pow43 = pow1 * pow42; + local pow44 = pow2 * pow43; + local pow45 = pow2 * pow44; + local pow46 = pow6 * pow45; + local pow47 = pow5 * pow46; + local pow48 = pow1 * pow47; + local pow49 = pow2 * pow48; + local pow50 = pow2 * pow49; + local pow51 = pow6 * pow50; + local pow52 = pow5 * pow51; + local pow53 = pow3 * pow52; + local pow54 = pow13 * pow53; + local pow55 = pow5 * pow54; + local pow56 = pow1 * pow55; + local pow57 = pow5 * pow56; + local pow58 = pow5 * pow57; + local pow59 = pow16 * pow58; + local pow60 = pow5 * pow59; + local pow61 = pow6 * pow60; + local pow62 = pow5 * pow61; + local pow63 = pow15 * pow62; + local pow64 = pow1 * pow63; + local pow65 = pow3 * pow64; + local pow66 = pow1 * pow65; + local pow67 = pow1 * pow66; + local pow68 = pow1 * pow67; + local pow69 = pow5 * pow68; + local pow70 = pow5 * pow69; + local pow71 = pow16 * pow70; + local pow72 = pow11 * pow71; + local pow73 = pow5 * pow72; + local pow74 = pow10 * pow73; + local pow75 = pow1 * pow74; + local pow76 = pow3 * pow75; + local pow77 = pow1 * pow76; + local pow78 = pow1 * pow77; + local pow79 = pow5 * pow78; + local pow80 = pow1 * pow79; + local pow81 = pow2 * pow80; + local pow82 = pow39 * pow77; + local pow83 = pow55 * pow77; + local pow84 = pow1 * pow83; + local pow85 = pow63 * pow79; + local pow86 = pow76 * pow77; + local pow87 = pow2 * pow86; + local pow88 = pow5 * pow87; + local pow89 = pow3 * pow88; + local pow90 = pow63 * pow87; + local pow91 = pow6 * pow90; + local pow92 = pow10 * pow91; + local pow93 = pow16 * pow92; + local pow94 = pow16 * pow93; + local pow95 = pow16 * pow94; + local pow96 = pow8 * pow95; + local pow97 = pow66 * pow90; + local pow98 = pow1 * pow97; + local pow99 = pow34 * pow98; + local pow100 = pow5 * pow99; + local pow101 = pow1 * pow100; + local pow102 = pow10 * pow101; + local pow103 = pow16 * pow102; + local pow104 = pow16 * pow103; + local pow105 = pow76 * pow101; + let (local pow106) = pow(trace_generator, 2438); + local pow107 = pow1 * pow106; + let (local pow108) = pow(trace_generator, 4486); + local pow109 = pow1 * pow108; + let (local pow110) = pow(trace_generator, 6534); + local pow111 = pow1 * pow110; + let (local pow112) = pow(trace_generator, 8582); + local pow113 = pow1 * pow112; + let (local pow114) = pow(trace_generator, 10630); + local pow115 = pow1 * pow114; + let (local pow116) = pow(trace_generator, 12306); + let (local pow117) = pow(trace_generator, 12370); + local pow118 = pow63 * pow117; + local pow119 = pow77 * pow117; + local pow120 = pow33 * pow119; + local pow121 = pow1 * pow120; + let (local pow122) = pow(trace_generator, 14726); + local pow123 = pow1 * pow122; + let (local pow124) = pow(trace_generator, 16082); + let (local pow125) = pow(trace_generator, 16146); + let (local pow126) = pow(trace_generator, 16322); + local pow127 = pow8 * pow126; + local pow128 = pow10 * pow127; + local pow129 = pow6 * pow128; + local pow130 = pow8 * pow129; + local pow131 = pow8 * pow130; + local pow132 = pow8 * pow131; + local pow133 = pow2 * pow132; + local pow134 = pow6 * pow133; + local pow135 = pow10 * pow134; + local pow136 = pow29 * pow134; + let (local pow137) = pow(trace_generator, 16774); + local pow138 = pow1 * pow137; + let (local pow139) = pow(trace_generator, 24966); + let (local pow140) = pow(trace_generator, 32646); + local pow141 = pow16 * pow140; + local pow142 = pow126 * pow135; + local pow143 = pow14 * pow142; + local pow144 = pow6 * pow143; + local pow145 = pow12 * pow144; + local pow146 = pow14 * pow145; + local pow147 = pow6 * pow146; + let (local pow148) = pow(trace_generator, 33158); + + // Fetch columns. + tempvar column0 = column_values[0]; + tempvar column1 = column_values[1]; + tempvar column2 = column_values[2]; + tempvar column3 = column_values[3]; + tempvar column4 = column_values[4]; + tempvar column5 = column_values[5]; + tempvar column6 = column_values[6]; + tempvar column7 = column_values[7]; + tempvar column8 = column_values[8]; + tempvar column9 = column_values[9]; + + // Sum the OODS constraints on the trace polynomials. + tempvar total_sum = 0; + + tempvar value = (column0 - oods_values[0]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[0] * value; + + tempvar value = (column0 - oods_values[1]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[1] * value; + + tempvar value = (column0 - oods_values[2]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[2] * value; + + tempvar value = (column0 - oods_values[3]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[3] * value; + + tempvar value = (column0 - oods_values[4]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[4] * value; + + tempvar value = (column0 - oods_values[5]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[5] * value; + + tempvar value = (column0 - oods_values[6]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[6] * value; + + tempvar value = (column0 - oods_values[7]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[7] * value; + + tempvar value = (column0 - oods_values[8]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[8] * value; + + tempvar value = (column0 - oods_values[9]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[9] * value; + + tempvar value = (column0 - oods_values[10]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[10] * value; + + tempvar value = (column0 - oods_values[11]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[11] * value; + + tempvar value = (column0 - oods_values[12]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[12] * value; + + tempvar value = (column0 - oods_values[13]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[13] * value; + + tempvar value = (column0 - oods_values[14]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[14] * value; + + tempvar value = (column0 - oods_values[15]) / (point - pow15 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[15] * value; + + tempvar value = (column1 - oods_values[16]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[16] * value; + + tempvar value = (column1 - oods_values[17]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[17] * value; + + tempvar value = (column1 - oods_values[18]) / (point - pow76 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[18] * value; + + tempvar value = (column1 - oods_values[19]) / (point - pow77 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[19] * value; + + tempvar value = (column1 - oods_values[20]) / (point - pow86 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[20] * value; + + tempvar value = (column2 - oods_values[21]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[21] * value; + + tempvar value = (column2 - oods_values[22]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[22] * value; + + tempvar value = (column2 - oods_values[23]) / (point - pow76 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[23] * value; + + tempvar value = (column2 - oods_values[24]) / (point - pow77 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[24] * value; + + tempvar value = (column3 - oods_values[25]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[25] * value; + + tempvar value = (column3 - oods_values[26]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[26] * value; + + tempvar value = (column3 - oods_values[27]) / (point - pow63 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[27] * value; + + tempvar value = (column3 - oods_values[28]) / (point - pow64 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[28] * value; + + tempvar value = (column3 - oods_values[29]) / (point - pow65 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[29] * value; + + tempvar value = (column3 - oods_values[30]) / (point - pow66 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[30] * value; + + tempvar value = (column3 - oods_values[31]) / (point - pow74 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[31] * value; + + tempvar value = (column3 - oods_values[32]) / (point - pow75 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[32] * value; + + tempvar value = (column3 - oods_values[33]) / (point - pow77 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[33] * value; + + tempvar value = (column4 - oods_values[34]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[34] * value; + + tempvar value = (column4 - oods_values[35]) / (point - pow76 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[35] * value; + + tempvar value = (column5 - oods_values[36]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[36] * value; + + tempvar value = (column5 - oods_values[37]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[37] * value; + + tempvar value = (column5 - oods_values[38]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[38] * value; + + tempvar value = (column5 - oods_values[39]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[39] * value; + + tempvar value = (column5 - oods_values[40]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[40] * value; + + tempvar value = (column5 - oods_values[41]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[41] * value; + + tempvar value = (column5 - oods_values[42]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[42] * value; + + tempvar value = (column5 - oods_values[43]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[43] * value; + + tempvar value = (column5 - oods_values[44]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[44] * value; + + tempvar value = (column5 - oods_values[45]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[45] * value; + + tempvar value = (column5 - oods_values[46]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[46] * value; + + tempvar value = (column5 - oods_values[47]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[47] * value; + + tempvar value = (column5 - oods_values[48]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[48] * value; + + tempvar value = (column5 - oods_values[49]) / (point - pow39 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[49] * value; + + tempvar value = (column5 - oods_values[50]) / (point - pow40 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[50] * value; + + tempvar value = (column5 - oods_values[51]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[51] * value; + + tempvar value = (column5 - oods_values[52]) / (point - pow56 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[52] * value; + + tempvar value = (column5 - oods_values[53]) / (point - pow67 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[53] * value; + + tempvar value = (column5 - oods_values[54]) / (point - pow68 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[54] * value; + + tempvar value = (column5 - oods_values[55]) / (point - pow79 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[55] * value; + + tempvar value = (column5 - oods_values[56]) / (point - pow80 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[56] * value; + + tempvar value = (column5 - oods_values[57]) / (point - pow82 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[57] * value; + + tempvar value = (column5 - oods_values[58]) / (point - pow83 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[58] * value; + + tempvar value = (column5 - oods_values[59]) / (point - pow84 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[59] * value; + + tempvar value = (column5 - oods_values[60]) / (point - pow85 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[60] * value; + + tempvar value = (column5 - oods_values[61]) / (point - pow88 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[61] * value; + + tempvar value = (column5 - oods_values[62]) / (point - pow91 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[62] * value; + + tempvar value = (column5 - oods_values[63]) / (point - pow97 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[63] * value; + + tempvar value = (column5 - oods_values[64]) / (point - pow98 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[64] * value; + + tempvar value = (column5 - oods_values[65]) / (point - pow100 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[65] * value; + + tempvar value = (column5 - oods_values[66]) / (point - pow101 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[66] * value; + + tempvar value = (column5 - oods_values[67]) / (point - pow105 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[67] * value; + + tempvar value = (column5 - oods_values[68]) / (point - pow106 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[68] * value; + + tempvar value = (column5 - oods_values[69]) / (point - pow107 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[69] * value; + + tempvar value = (column5 - oods_values[70]) / (point - pow108 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[70] * value; + + tempvar value = (column5 - oods_values[71]) / (point - pow109 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[71] * value; + + tempvar value = (column5 - oods_values[72]) / (point - pow110 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[72] * value; + + tempvar value = (column5 - oods_values[73]) / (point - pow111 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[73] * value; + + tempvar value = (column5 - oods_values[74]) / (point - pow112 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[74] * value; + + tempvar value = (column5 - oods_values[75]) / (point - pow113 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[75] * value; + + tempvar value = (column5 - oods_values[76]) / (point - pow114 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[76] * value; + + tempvar value = (column5 - oods_values[77]) / (point - pow115 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[77] * value; + + tempvar value = (column5 - oods_values[78]) / (point - pow120 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[78] * value; + + tempvar value = (column5 - oods_values[79]) / (point - pow121 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[79] * value; + + tempvar value = (column5 - oods_values[80]) / (point - pow122 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[80] * value; + + tempvar value = (column5 - oods_values[81]) / (point - pow123 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[81] * value; + + tempvar value = (column5 - oods_values[82]) / (point - pow137 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[82] * value; + + tempvar value = (column5 - oods_values[83]) / (point - pow138 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[83] * value; + + tempvar value = (column5 - oods_values[84]) / (point - pow139 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[84] * value; + + tempvar value = (column5 - oods_values[85]) / (point - pow148 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[85] * value; + + tempvar value = (column6 - oods_values[86]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[86] * value; + + tempvar value = (column6 - oods_values[87]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[87] * value; + + tempvar value = (column6 - oods_values[88]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[88] * value; + + tempvar value = (column6 - oods_values[89]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[89] * value; + + tempvar value = (column7 - oods_values[90]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[90] * value; + + tempvar value = (column7 - oods_values[91]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[91] * value; + + tempvar value = (column7 - oods_values[92]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[92] * value; + + tempvar value = (column7 - oods_values[93]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[93] * value; + + tempvar value = (column7 - oods_values[94]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[94] * value; + + tempvar value = (column7 - oods_values[95]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[95] * value; + + tempvar value = (column7 - oods_values[96]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[96] * value; + + tempvar value = (column7 - oods_values[97]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[97] * value; + + tempvar value = (column7 - oods_values[98]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[98] * value; + + tempvar value = (column7 - oods_values[99]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[99] * value; + + tempvar value = (column7 - oods_values[100]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[100] * value; + + tempvar value = (column7 - oods_values[101]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[101] * value; + + tempvar value = (column7 - oods_values[102]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[102] * value; + + tempvar value = (column7 - oods_values[103]) / (point - pow15 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[103] * value; + + tempvar value = (column7 - oods_values[104]) / (point - pow17 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[104] * value; + + tempvar value = (column7 - oods_values[105]) / (point - pow19 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[105] * value; + + tempvar value = (column7 - oods_values[106]) / (point - pow23 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[106] * value; + + tempvar value = (column7 - oods_values[107]) / (point - pow25 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[107] * value; + + tempvar value = (column7 - oods_values[108]) / (point - pow30 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[108] * value; + + tempvar value = (column7 - oods_values[109]) / (point - pow31 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[109] * value; + + tempvar value = (column7 - oods_values[110]) / (point - pow36 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[110] * value; + + tempvar value = (column7 - oods_values[111]) / (point - pow41 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[111] * value; + + tempvar value = (column7 - oods_values[112]) / (point - pow42 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[112] * value; + + tempvar value = (column7 - oods_values[113]) / (point - pow47 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[113] * value; + + tempvar value = (column7 - oods_values[114]) / (point - pow51 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[114] * value; + + tempvar value = (column7 - oods_values[115]) / (point - pow52 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[115] * value; + + tempvar value = (column7 - oods_values[116]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[116] * value; + + tempvar value = (column7 - oods_values[117]) / (point - pow57 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[117] * value; + + tempvar value = (column7 - oods_values[118]) / (point - pow58 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[118] * value; + + tempvar value = (column7 - oods_values[119]) / (point - pow59 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[119] * value; + + tempvar value = (column7 - oods_values[120]) / (point - pow61 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[120] * value; + + tempvar value = (column7 - oods_values[121]) / (point - pow62 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[121] * value; + + tempvar value = (column7 - oods_values[122]) / (point - pow64 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[122] * value; + + tempvar value = (column7 - oods_values[123]) / (point - pow69 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[123] * value; + + tempvar value = (column7 - oods_values[124]) / (point - pow70 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[124] * value; + + tempvar value = (column7 - oods_values[125]) / (point - pow71 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[125] * value; + + tempvar value = (column7 - oods_values[126]) / (point - pow72 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[126] * value; + + tempvar value = (column7 - oods_values[127]) / (point - pow73 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[127] * value; + + tempvar value = (column7 - oods_values[128]) / (point - pow78 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[128] * value; + + tempvar value = (column7 - oods_values[129]) / (point - pow81 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[129] * value; + + tempvar value = (column7 - oods_values[130]) / (point - pow87 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[130] * value; + + tempvar value = (column7 - oods_values[131]) / (point - pow89 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[131] * value; + + tempvar value = (column7 - oods_values[132]) / (point - pow90 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[132] * value; + + tempvar value = (column7 - oods_values[133]) / (point - pow92 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[133] * value; + + tempvar value = (column7 - oods_values[134]) / (point - pow93 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[134] * value; + + tempvar value = (column7 - oods_values[135]) / (point - pow94 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[135] * value; + + tempvar value = (column7 - oods_values[136]) / (point - pow95 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[136] * value; + + tempvar value = (column7 - oods_values[137]) / (point - pow96 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[137] * value; + + tempvar value = (column7 - oods_values[138]) / (point - pow99 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[138] * value; + + tempvar value = (column7 - oods_values[139]) / (point - pow102 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[139] * value; + + tempvar value = (column7 - oods_values[140]) / (point - pow103 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[140] * value; + + tempvar value = (column7 - oods_values[141]) / (point - pow104 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[141] * value; + + tempvar value = (column8 - oods_values[142]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[142] * value; + + tempvar value = (column8 - oods_values[143]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[143] * value; + + tempvar value = (column8 - oods_values[144]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[144] * value; + + tempvar value = (column8 - oods_values[145]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[145] * value; + + tempvar value = (column8 - oods_values[146]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[146] * value; + + tempvar value = (column8 - oods_values[147]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[147] * value; + + tempvar value = (column8 - oods_values[148]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[148] * value; + + tempvar value = (column8 - oods_values[149]) / (point - pow18 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[149] * value; + + tempvar value = (column8 - oods_values[150]) / (point - pow20 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[150] * value; + + tempvar value = (column8 - oods_values[151]) / (point - pow21 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[151] * value; + + tempvar value = (column8 - oods_values[152]) / (point - pow22 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[152] * value; + + tempvar value = (column8 - oods_values[153]) / (point - pow24 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[153] * value; + + tempvar value = (column8 - oods_values[154]) / (point - pow26 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[154] * value; + + tempvar value = (column8 - oods_values[155]) / (point - pow27 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[155] * value; + + tempvar value = (column8 - oods_values[156]) / (point - pow28 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[156] * value; + + tempvar value = (column8 - oods_values[157]) / (point - pow29 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[157] * value; + + tempvar value = (column8 - oods_values[158]) / (point - pow30 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[158] * value; + + tempvar value = (column8 - oods_values[159]) / (point - pow32 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[159] * value; + + tempvar value = (column8 - oods_values[160]) / (point - pow33 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[160] * value; + + tempvar value = (column8 - oods_values[161]) / (point - pow34 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[161] * value; + + tempvar value = (column8 - oods_values[162]) / (point - pow35 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[162] * value; + + tempvar value = (column8 - oods_values[163]) / (point - pow37 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[163] * value; + + tempvar value = (column8 - oods_values[164]) / (point - pow38 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[164] * value; + + tempvar value = (column8 - oods_values[165]) / (point - pow39 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[165] * value; + + tempvar value = (column8 - oods_values[166]) / (point - pow41 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[166] * value; + + tempvar value = (column8 - oods_values[167]) / (point - pow43 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[167] * value; + + tempvar value = (column8 - oods_values[168]) / (point - pow44 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[168] * value; + + tempvar value = (column8 - oods_values[169]) / (point - pow45 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[169] * value; + + tempvar value = (column8 - oods_values[170]) / (point - pow46 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[170] * value; + + tempvar value = (column8 - oods_values[171]) / (point - pow48 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[171] * value; + + tempvar value = (column8 - oods_values[172]) / (point - pow49 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[172] * value; + + tempvar value = (column8 - oods_values[173]) / (point - pow50 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[173] * value; + + tempvar value = (column8 - oods_values[174]) / (point - pow51 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[174] * value; + + tempvar value = (column8 - oods_values[175]) / (point - pow53 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[175] * value; + + tempvar value = (column8 - oods_values[176]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[176] * value; + + tempvar value = (column8 - oods_values[177]) / (point - pow60 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[177] * value; + + tempvar value = (column8 - oods_values[178]) / (point - pow67 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[178] * value; + + tempvar value = (column8 - oods_values[179]) / (point - pow116 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[179] * value; + + tempvar value = (column8 - oods_values[180]) / (point - pow117 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[180] * value; + + tempvar value = (column8 - oods_values[181]) / (point - pow118 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[181] * value; + + tempvar value = (column8 - oods_values[182]) / (point - pow119 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[182] * value; + + tempvar value = (column8 - oods_values[183]) / (point - pow124 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[183] * value; + + tempvar value = (column8 - oods_values[184]) / (point - pow125 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[184] * value; + + tempvar value = (column8 - oods_values[185]) / (point - pow126 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[185] * value; + + tempvar value = (column8 - oods_values[186]) / (point - pow127 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[186] * value; + + tempvar value = (column8 - oods_values[187]) / (point - pow128 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[187] * value; + + tempvar value = (column8 - oods_values[188]) / (point - pow129 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[188] * value; + + tempvar value = (column8 - oods_values[189]) / (point - pow130 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[189] * value; + + tempvar value = (column8 - oods_values[190]) / (point - pow131 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[190] * value; + + tempvar value = (column8 - oods_values[191]) / (point - pow132 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[191] * value; + + tempvar value = (column8 - oods_values[192]) / (point - pow133 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[192] * value; + + tempvar value = (column8 - oods_values[193]) / (point - pow134 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[193] * value; + + tempvar value = (column8 - oods_values[194]) / (point - pow135 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[194] * value; + + tempvar value = (column8 - oods_values[195]) / (point - pow136 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[195] * value; + + tempvar value = (column8 - oods_values[196]) / (point - pow140 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[196] * value; + + tempvar value = (column8 - oods_values[197]) / (point - pow141 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[197] * value; + + tempvar value = (column8 - oods_values[198]) / (point - pow142 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[198] * value; + + tempvar value = (column8 - oods_values[199]) / (point - pow143 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[199] * value; + + tempvar value = (column8 - oods_values[200]) / (point - pow144 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[200] * value; + + tempvar value = (column8 - oods_values[201]) / (point - pow145 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[201] * value; + + tempvar value = (column8 - oods_values[202]) / (point - pow146 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[202] * value; + + tempvar value = (column8 - oods_values[203]) / (point - pow147 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[203] * value; + + tempvar value = (column9 - oods_values[204]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[204] * value; + + tempvar value = (column9 - oods_values[205]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[205] * value; + + tempvar value = (column9 - oods_values[206]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[206] * value; + + tempvar value = (column9 - oods_values[207]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[207] * value; + + tempvar value = (column9 - oods_values[208]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[208] * value; + + tempvar value = (column9 - oods_values[209]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[209] * value; + + tempvar value = (column9 - oods_values[210]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[210] * value; + + tempvar value = (column9 - oods_values[211]) / (point - pow15 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[211] * value; + + // Sum the OODS boundary constraints on the composition polynomials. + let (oods_point_to_deg) = pow(oods_point, CONSTRAINT_DEGREE); + + tempvar value = (column_values[10] - oods_values[212]) / (point - oods_point_to_deg); + tempvar total_sum = total_sum + constraint_coefficients[212] * value; + + tempvar value = (column_values[11] - oods_values[213]) / (point - oods_point_to_deg); + tempvar total_sum = total_sum + constraint_coefficients[213] * value; + + static_assert 214 == MASK_SIZE + CONSTRAINT_DEGREE; + return (res=total_sum); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/composition.cairo b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/composition.cairo new file mode 100644 index 00000000..164b6b05 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/composition.cairo @@ -0,0 +1,141 @@ +from starkware.cairo.common.ec import StarkCurve +from starkware.cairo.common.math import assert_nn +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_fp_and_pc +from starkware.cairo.stark_verifier.air.diluted import get_diluted_prod +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.autogenerated import ( + CONSTRAINT_DEGREE, + DILUTED_N_BITS, + DILUTED_SPACING, + ECDSA_BUILTIN_RATIO, + ECDSA_BUILTIN_REPETITIONS, + MASK_SIZE, + N_CONSTRAINTS, + PEDERSEN_BUILTIN_RATIO, + PEDERSEN_BUILTIN_REPETITIONS, + PUBLIC_MEMORY_STEP, + eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.global_values import ( + CurveConfig, + EcdsaSigConfig, + EcPoint, + GlobalValues, + InteractionElements, +) +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.periodic_columns import ( + eval_ecdsa_x, + eval_ecdsa_y, + eval_pedersen_x, + eval_pedersen_y, +) +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.public_verify import segments +from starkware.cairo.stark_verifier.air.public_input import get_public_memory_product_ratio +from starkware.cairo.stark_verifier.air.traces import TracesCommitment + +// Constants. +const SHIFT_POINT_X = 0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804; +const SHIFT_POINT_Y = 0x3ca0cfe4b3bc6ddf346d49d06ea0ed34e621062c0e056c1d0405d266e10268a; + +// Evaluates the composition polynomial at a point, given the mask_values and the constraint +// coefficients. +func traces_eval_composition_polynomial{range_check_ptr}( + air: AirWithLayout*, + commitment: TracesCommitment*, + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_domain_size: felt, + trace_generator: felt, +) -> (res: felt) { + alloc_locals; + + tempvar interaction_elements = cast(commitment.interaction_elements, InteractionElements*); + tempvar public_input = commitment.public_input; + let (__fp__, _) = get_fp_and_pc(); + + // Public memory. + let memory_z = interaction_elements.memory__multi_column_perm__perm__interaction_elm; + let memory_alpha = interaction_elements.memory__multi_column_perm__hash_interaction_elm0; + tempvar public_memory_column_size = trace_domain_size / PUBLIC_MEMORY_STEP; + assert_nn(public_memory_column_size); + let (public_memory_prod_ratio) = get_public_memory_product_ratio( + public_input=public_input, + z=memory_z, + alpha=memory_alpha, + public_memory_column_size=public_memory_column_size, + ); + + // Diluted. + let diluted_z = interaction_elements.diluted_check__interaction_z; + let diluted_alpha = interaction_elements.diluted_check__interaction_alpha; + let (diluted_prod) = get_diluted_prod( + n_bits=DILUTED_N_BITS, spacing=DILUTED_SPACING, z=diluted_z, alpha=diluted_alpha + ); + + // Periodic columns. + let (n_steps) = pow(2, public_input.log_n_steps); + tempvar n_pedersen_hash_copies = n_steps / ( + PEDERSEN_BUILTIN_RATIO * PEDERSEN_BUILTIN_REPETITIONS); + assert_nn(n_pedersen_hash_copies); + let (pedersen_point) = pow(point, n_pedersen_hash_copies); + let (pedersen__points__x) = eval_pedersen_x(pedersen_point); + let (pedersen__points__y) = eval_pedersen_y(pedersen_point); + + tempvar n_ecdsa_signature_copies = n_steps / ( + ECDSA_BUILTIN_RATIO * ECDSA_BUILTIN_REPETITIONS); + assert_nn(n_ecdsa_signature_copies); + let (ecdsa_point) = pow(point, n_ecdsa_signature_copies); + let (ecdsa__generator_points__x) = eval_ecdsa_x(ecdsa_point); + let (ecdsa__generator_points__y) = eval_ecdsa_y(ecdsa_point); + + // Global values. + local global_values: GlobalValues = GlobalValues( + trace_length=trace_domain_size, + initial_pc=public_input.segments[segments.PROGRAM].begin_addr, + final_pc=public_input.segments[segments.PROGRAM].stop_ptr, + initial_ap=public_input.segments[segments.EXECUTION].begin_addr, + final_ap=public_input.segments[segments.EXECUTION].stop_ptr, + initial_pedersen_addr=public_input.segments[segments.PEDERSEN].begin_addr, + initial_rc_addr=public_input.segments[segments.RANGE_CHECK].begin_addr, + initial_ecdsa_addr=public_input.segments[segments.ECDSA].begin_addr, + initial_bitwise_addr=public_input.segments[segments.BITWISE].begin_addr, + initial_ec_op_addr=public_input.segments[segments.EC_OP].begin_addr, + rc_min=public_input.rc_min, + rc_max=public_input.rc_max, + offset_size=2 ** 16, + half_offset_size=2 ** 15, + pedersen__shift_point=EcPoint(x=SHIFT_POINT_X, y=SHIFT_POINT_Y), + ecdsa__sig_config=EcdsaSigConfig( + alpha=StarkCurve.ALPHA, + beta=StarkCurve.BETA, + shift_point=EcPoint(x=SHIFT_POINT_X, y=SHIFT_POINT_Y)), + ec_op__curve_config=CurveConfig( + alpha=StarkCurve.ALPHA, + beta=StarkCurve.BETA), + pedersen__points__x=pedersen__points__x, + pedersen__points__y=pedersen__points__y, + ecdsa__generator_points__x=ecdsa__generator_points__x, + ecdsa__generator_points__y=ecdsa__generator_points__y, + memory__multi_column_perm__perm__interaction_elm=memory_z, + memory__multi_column_perm__hash_interaction_elm0=memory_alpha, + rc16__perm__interaction_elm=interaction_elements.rc16__perm__interaction_elm, + diluted_check__permutation__interaction_elm=( + interaction_elements.diluted_check__permutation__interaction_elm), + diluted_check__interaction_z=diluted_z, + diluted_check__interaction_alpha=diluted_alpha, + memory__multi_column_perm__perm__public_memory_prod=public_memory_prod_ratio, + rc16__perm__public_memory_prod=1, + diluted_check__first_elm=0, + diluted_check__permutation__public_memory_prod=1, + diluted_check__final_cum_val=diluted_prod); + + return eval_composition_polynomial( + mask_values=mask_values, + constraint_coefficients=constraint_coefficients, + point=point, + trace_generator=trace_generator, + global_values=&global_values, + ); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/global_values.cairo b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/global_values.cairo new file mode 100644 index 00000000..e7324608 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/global_values.cairo @@ -0,0 +1,71 @@ +struct EcPoint { + x: felt, + y: felt, +} + +struct CurveConfig { + alpha: felt, + beta: felt, +} + +struct EcdsaSigConfig { + alpha: felt, + beta: felt, + shift_point: EcPoint, +} + +// Accumulation of member expressions for auto generated composition polynomial code. +struct GlobalValues { + // Public input. + trace_length: felt, + initial_pc: felt, + final_pc: felt, + initial_ap: felt, + final_ap: felt, + initial_pedersen_addr: felt, + initial_rc_addr: felt, + initial_ecdsa_addr: felt, + initial_bitwise_addr: felt, + initial_ec_op_addr: felt, + rc_min: felt, + rc_max: felt, + + // Constants. + offset_size: felt, + half_offset_size: felt, + pedersen__shift_point: EcPoint, + ecdsa__sig_config: EcdsaSigConfig, + ec_op__curve_config: CurveConfig, + + // Periodic columns. + pedersen__points__x: felt, + pedersen__points__y: felt, + ecdsa__generator_points__x: felt, + ecdsa__generator_points__y: felt, + + // Interaction elements. + memory__multi_column_perm__perm__interaction_elm: felt, + memory__multi_column_perm__hash_interaction_elm0: felt, + rc16__perm__interaction_elm: felt, + diluted_check__permutation__interaction_elm: felt, + diluted_check__interaction_z: felt, + diluted_check__interaction_alpha: felt, + + // Permutation products. + memory__multi_column_perm__perm__public_memory_prod: felt, + rc16__perm__public_memory_prod: felt, + diluted_check__first_elm: felt, + diluted_check__permutation__public_memory_prod: felt, + diluted_check__final_cum_val: felt, +} + +// Elements that are sent from the prover after the commitment on the original trace. +// Used for components after the first interaction, e.g., memory and range check. +struct InteractionElements { + memory__multi_column_perm__perm__interaction_elm: felt, + memory__multi_column_perm__hash_interaction_elm0: felt, + rc16__perm__interaction_elm: felt, + diluted_check__permutation__interaction_elm: felt, + diluted_check__interaction_z: felt, + diluted_check__interaction_alpha: felt, +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/periodic_columns.cairo b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/periodic_columns.cairo new file mode 100644 index 00000000..46218847 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/periodic_columns.cairo @@ -0,0 +1,1571 @@ +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_pedersen_x(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x43869b387c2d0eab20661ebdfaca58b4b23feac014e1e1d9413164312e77da); + tempvar res = res * point + (0x4cec4cd52fab6da76b4ab7a41ffd844aad8981917d2295273ff6ab2cce622d8); + tempvar res = res * point + (0x295046a010dd6757176414b0fd144c1d2517fc463df01a12c0ab58bbbac26ea); + tempvar res = res * point + (0x60105b3cb5aab151ce615173eaecbe94014ff5d72e884addcd4b9d973fed9fd); + tempvar res = res * point + (0x233eff8cfcc744de79d412f724898d13c0e53b1132046ee45db7a101242a73f); + tempvar res = res * point + (0x6f753527f0dec9b713d52f08e4556a3963a2f7e5e282b2e97ffde3e12569b76); + tempvar res = res * point + (0x549a83d43c90aaf1a28c445c81abc883cb61e4353a84ea0fcb15ccee6d6482f); + tempvar res = res * point + (0x4259be645aaf0a661e7877276fa5559ed7d04349f577595702efed3050402c5); + tempvar res = res * point + (0x71e67bd6a0b1b8518cb06837a78b92ab3dec98c4989f946285042655ffe516e); + tempvar res = res * point + (0x19b7924c29a944ecb61165a663d76d84e5ce44b4617fdbca8ff02fbdea6deba); + tempvar res = res * point + (0x70454f9541d96fc1552f984330389ff616cf80eaf699ba2e82b77f43fd163a); + tempvar res = res * point + (0x479c09d33c38f1c8f73247aace507da354ae87ca5cd4aa096bd3a6229e3006d); + tempvar res = res * point + (0x6fcf0e32e3e99f51d8cdac9c19cc25179eb97f2757844fa0c72e7c3bf453e4); + tempvar res = res * point + (0x4ccee6b6ecd4ea8733198e95935d13474d34cf54d7631fde59720e40378e1eb); + tempvar res = res * point + (0x627cb37206e5ee9da20c04a92cc765e3bd3f3d4e42ad4de0d709f366d446d8e); + tempvar res = res * point + (0x4183c04ef7d778f11e57b44c1a7f354c4497f1e3d420d3fa9f9c27c4bb58759); + tempvar res = res * point + (0x1e2c5c3fb2b47ea8cf33099c610f6132a5dd7099d29b02f4a041fe5947ff53b); + tempvar res = res * point + (0x4d44944716e0e13728fa8b84fde421f0f66a120ed2b7cfcf59f5ff6718b8b6c); + tempvar res = res * point + (0x394d0eed011068acc2f55f541c4d113a9c0afe7269cd7d9711aa7e8be661a60); + tempvar res = res * point + (0x52b5bdbcf28603ba60abcbf52bd4f7b4988ce0b4e2346e4875a3f117d4143b4); + tempvar res = res * point + (0x5975b93cee7a147a93cc98aabbb713f151924c4ede3306bb5e14e5e4d5d5c05); + tempvar res = res * point + (0x787053fc3649b17965b9e6ef5e05e024cdc188e90aef1cbf13ba78542a0407d); + tempvar res = res * point + (0x7cbef72611c8e1e08e52ca202382a8545bc7fe124ec080058988e45771e3b40); + tempvar res = res * point + (0x32bd55700baf7283995407f470139326a670d60a5d5428904596584629a053d); + tempvar res = res * point + (0x3485ad12aa365fac51a6296931abdcb54fa848c587cfbfe5bdbad2d6f6d3bd3); + tempvar res = res * point + (0x7f9850620a3435695ec7a6d9378cfe218ab0e5fa674cdc572fb9c197b0dbd25); + tempvar res = res * point + (0x1c7c40b6e4cd3d473e8f84b8fa63610ac6c7e3f4f0017f3ed84eae8f042bf15); + tempvar res = res * point + (0x1e3e1d970342085c482175cf60d93e1cc2cf96dec12f1d839b9b829cc957b7d); + tempvar res = res * point + (0x2d1547488e174e0a8662decd2cf020dd40718f070c84cf36bfa261aa90f814); + tempvar res = res * point + (0x31b8dd40040d22aae383c1e628e427f7aa4a7b0c3a83f815fd7ae2b36864af0); + tempvar res = res * point + (0x5efc7dfab3ad0b3f01e313c50ced95363d8dbaa9f91f801d6f1f00869467a16); + tempvar res = res * point + (0x724a3072c9f315cba63e5d99034b3218ff29a9bbf04155060ebdd6c848a652); + tempvar res = res * point + (0x2a0c1eade4037c10729bdc8a8f38bb5bf359078eedba633047377a09b6cde4d); + tempvar res = res * point + (0x6aacb14e31ebb5066e78eb597842812d7ad137880a6dd0d065c4acee231b7c3); + tempvar res = res * point + (0x468b88ba32ca1eac6c8d3196eea0561e25770818221ed0da3ae749e2a302e); + tempvar res = res * point + (0x5b52f487f8c3d78fb6ea4be227325a7386c7e95cd5f9b72710cfcc870cbba59); + tempvar res = res * point + (0x2bec10dd6a541c12555ff040b5949407713b4227867f53a435e80847b7932f0); + tempvar res = res * point + (0x41e1c8870eea4b7f4308e8173f97482d80afd055f07b1a058f182a775aef593); + tempvar res = res * point + (0x126a03f3c5cbe523484111d915d6d7eab5edad02a327a383171be09597336b4); + tempvar res = res * point + (0xa8db86341624832893780e36fe1f60490da5768f9aeb2a5803240f29ec5a2); + tempvar res = res * point + (0x751a8c7382e8fc0141b4ec5bf37fa457ab8301640b58cfc3b6a0b8d1a12bec2); + tempvar res = res * point + (0x5e56f3654b68256095b54a7868763aa3ff60a98ea3508039def82d2098d8a6d); + tempvar res = res * point + (0x60a9a4ccb72bde44d8a6c5f1d7b9303cc32013ef621bce1b8af413f00e77ef2); + tempvar res = res * point + (0x4efe82f8cacf9761cac9fefb6c13c1afdaed68ee650c37684bfce323070e480); + tempvar res = res * point + (0x40c43992a86359c71f5b8051d84d1fd6971eb36ab486f321a1fc50a52a02a44); + tempvar res = res * point + (0x538392c6ca2c04b5096aa69392b76ff109aabe165df488f3d1a8e5c4022db64); + tempvar res = res * point + (0x2b783063fa1948abfa91d79d225d52ed2ddd11bf20fc388b1ec00fdb5867921); + tempvar res = res * point + (0x1ec66f3f326120e659b78867bdfd7dac4dd3f1a92ffeaf46d39725de341afd4); + tempvar res = res * point + (0x5f4ed6b86202d76686a0b4c1efdfc93c46dce1b843c7181d1db1f8cd4d6dfb); + tempvar res = res * point + (0x34b9f6e8d5debbb4aea334310dc8d8075f896e7eb9f1c09788c7ec62ccb6116); + tempvar res = res * point + (0x4e57c6677d3bd56b425a3b3a92517344d4875e1710667e3dee1954395269af); + tempvar res = res * point + (0x1c5110241881e087e201d211da338d8377dd228afbd84850b76f3e5dfeb9361); + tempvar res = res * point + (0xa64b536ff29309d613af1c27c7229c3f6c583471c6b589b25026db08d3767a); + tempvar res = res * point + (0x3f6f9a9c3f6e175b59fd8e4268a6ae5734034fb1d7c43f97ef474b75ba80cc8); + tempvar res = res * point + (0x775ad15685181f15e34a6b0036c16fc8d1a9860ced1cc5ece39d19a6add939b); + tempvar res = res * point + (0x7775ec7b0ee9812c8df83957c5b46c316fdac82a2d736d4a6eea6124abc5849); + tempvar res = res * point + (0x41f320f863037e381ff83f2c9f1a8ae2802fc22cfea674d9cfd10171da6dea8); + tempvar res = res * point + (0x67649ac75ea692acb3aa4432d48de15aacfa347a37afdf489cc7e954e4ab100); + tempvar res = res * point + (0x7fd8c6108133b8109f4058192bd614b5de2c50afe7ac08a7bb0e0b12ef04e4f); + tempvar res = res * point + (0x57f8ef270683ea78b167dcbe5bb122a79ba760c95f8103dc4c6e7788fb1ac9c); + tempvar res = res * point + (0x6dc0d996fc95036c8cfa408fb12793bf8a4773d698f55085c2ccbc906c6d2d0); + tempvar res = res * point + (0x6713ddde3f2da61b676f5e4c52177bfc8c1576bc97ab3c48f08ff02d26cc03e); + tempvar res = res * point + (0x16b450dd2bb4712f6412b35603aaa02e7345124e5fd13e919c269f3874970f9); + tempvar res = res * point + (0x5f81b087ad750a0ebddd5239bb3682c84d88326b4679a24890f5fec98df45a); + tempvar res = res * point + (0x33f4151b710663772765df7f95b3710c3e8e81bacdbe3729b0a43b6d19e428c); + tempvar res = res * point + (0x5d122cd95f43fb6fc2373ef7e66072140f0f20d552f186faff2622b55a3e063); + tempvar res = res * point + (0x9b478a0767cca2c6f9b4268bffc9e907eb69b32f8ff7b43fc24edd38a88ec2); + tempvar res = res * point + (0x597cee65bc7c6f0faa3e0aa1958897acf7fd4e4e69569f5d18254b0b8c09aab); + tempvar res = res * point + (0x218bc11c668ef7ae5f04a16dc9933c5bc41c194a439d0af802568e598c54630); + tempvar res = res * point + (0x3394eac0b3787b323686cddaef3af972d7fbbd75940bf7f682b8fe3676cd46b); + tempvar res = res * point + (0x4aeb3836ccb2a9ebf9f1c5b6ee3c42f66c8059cc55188335a47a3583d986018); + tempvar res = res * point + (0x5db68a5c4527fff0ebf61fe064888b0fb6e277cfecca6d206986293256f31f); + tempvar res = res * point + (0x63372394d373e7a2f2fa6405509da05fe9cb546ea2742ac0716bccf50ad9227); + tempvar res = res * point + (0x22d4ed1a29943bc16343e01eab25e45adf74b6a7072e4e26aa8d141f2cac5ca); + tempvar res = res * point + (0xf8ea3b2c0b72747301b2778cc071cb9d2e09bbdd7a386b7931582ab412dbd1); + tempvar res = res * point + (0xf78d4b72e0f5f55913884d0714674dd6f534b211ec5dcdba419347828c7c35); + tempvar res = res * point + (0x5142430fc3f872dd6fefb7e9804e3e63714f71a2f43b155cebc53671f964af); + tempvar res = res * point + (0x72fe5010e70102306b21cc388b7f2ab8b0324b84654cf98032b83a81099e72e); + tempvar res = res * point + (0xfd959b09bb704fe63c73e2331f8e76dc1fbf85c2dc9dcaa0e8108664f7f988); + tempvar res = res * point + (0x4180556f79a47df725eca2c2f65389e27281443847a7d9e84640e6d589182f7); + tempvar res = res * point + (0x2dc12726f7f06ef1adfb10747e5d4ef8052e4e57bad9bb10529d7994ef91035); + tempvar res = res * point + (0x3c62720cac42a262b58765d7c0588231c5c2c9ce9d48f0fd547575289ede8c8); + tempvar res = res * point + (0x5744178090cdd56ae12fdd51b74bc097f23f735b7ca16e415a1854597b1caf8); + tempvar res = res * point + (0x597cbefb648f47e763b9b1be8c3f815a0e8b65d0101e11b5bedc380c10e9f4); + tempvar res = res * point + (0x78e66ae8b3ef57289d92561dbe4ef72f4ee551d5cad363720a78d104a89163); + tempvar res = res * point + (0x3cb89319d8172da012c036c40116fd325d65af69f80a1df8f56ec890e920592); + tempvar res = res * point + (0x29d152196b7ea7446182efe778a2db796f5fab17286405953476ac97f94a96a); + tempvar res = res * point + (0x6348748d43d48acafb8ce688f25a1245df86dd20c3a96c5c85cfc0960ca2fa7); + tempvar res = res * point + (0x3609fff81e15da2a88036d1c2d28814035ce829430fabcc3986c08acdc2d44); + tempvar res = res * point + (0x3241fcabfd99b666b151970558fb59fdfca47ded4caf2af4b15839767edb190); + tempvar res = res * point + (0x3f61241934753ca9c4f4210885b87863abdc8637d4dafe5da4bfa5e0206988e); + tempvar res = res * point + (0x6a16c0b648c72c8d718d53099cb11725ee09fe1b49487d8f55f307a6a265920); + tempvar res = res * point + (0x43ef0fbc56a0a46c7099f5e6d6550a77e1ac023e2201f01bde0a3f5fb0f16a5); + tempvar res = res * point + (0x1f6bf768424619cc2d34c01cbf4e137b6cc33a4a5a3db0bc704f790f86ad67c); + tempvar res = res * point + (0x49eac48d453d5de07fe3f4bdb5aac21e7fe69858afedfbeb0daf175459dd9d7); + tempvar res = res * point + (0x2a390a6737563e9edc22b0b0cce94a67adc10db18d6f978c826f24b8848c6df); + tempvar res = res * point + (0x23e127bf290465acfb7500962d426be5241f0e8c6f844d25aa8e262df6e70cb); + tempvar res = res * point + (0x5e51a00b7437caee2acdb81781212bc3d1c397b477ec784d1a7b304c9f8c687); + tempvar res = res * point + (0x6e52308f62433fe92ca9064e06aa17d793d3ad7bedb9590c8bb9edd3272fbae); + tempvar res = res * point + (0x7aa1d2348e13a031dc4fa20d453fcd59eead9adbccc3ea64997d09a0f58216b); + tempvar res = res * point + (0x1c02d3ffc30c7172a132ac604ad28e89466845c139dba509b896c997ee4ce8a); + tempvar res = res * point + (0x3ea018d81f9118cb5cf251d6c795b4ca4aeeb28d6ea5464fb4807d219453728); + tempvar res = res * point + (0x62c2fa993dee607ef195fb6620051b4df127d933de3a417d21de3b0c6dfdc95); + tempvar res = res * point + (0x2fd6fab5c4d0e6bd5bf5b950632e2dfc3be19c9a80e3bf8934e878003b0816a); + tempvar res = res * point + (0x12f2b0b280b64cb9f6bd77cd5103b7668ae42e5d40ae156607c69043b4da5a9); + tempvar res = res * point + (0x51a3ba83e3f68b2df85f3b9e770b5294312fd634fa48ace215a029fdb5593); + tempvar res = res * point + (0x56f19df91009289c7f5304026cf6d2c26541cd4caf867b2d2ea8a954560ed7b); + tempvar res = res * point + (0x362dd19b8207511079a352fad991df9582315ca2539ed4da5cbb5b82e414fc5); + tempvar res = res * point + (0x2dd7ddf328b439b3047a93c6fff6ef901946438cbb55a4c1fa1848f80baf2ce); + tempvar res = res * point + (0x2120274511adcc680703d33146477a31c42684b5163a628eb3f84258ae78786); + tempvar res = res * point + (0x11076126b67298371103d89e76ec2fbe30b28c5de422e61d3fade2e190450a4); + tempvar res = res * point + (0x1868ebbc59cb1c69b32ea2b3a7ce3f87b680731b96a42403878df0a0e4bb3e2); + tempvar res = res * point + (0x5b7abf66fda1917e0e1d44924cb73d713b5fc16b3a64bd4857d089adfd6a814); + tempvar res = res * point + (0x13df9c113e40f246d806089e437629de52f8a247ece912785004efcafd4ea94); + tempvar res = res * point + (0xbdcc31feec5ca8cfbf7227269d1e120132c51307ec03cc2d59c471e2510a24); + tempvar res = res * point + (0x3b2efe16624d8d0a1beeb037b02f0a4f7e11eb3859852cea1f83ab1752a4099); + tempvar res = res * point + (0x596104fc8bded038e39f0de5e80a2f2b65fd39fa4ab7b3453bbe8a40e06a317); + tempvar res = res * point + (0x5fec9e8e9ad35ec1091706f4f39c0e8a610f58be6c987c2327ce0794af7cb7c); + tempvar res = res * point + (0x5fb45888a7861e18a320bff7b0baee50ef9cbe1b06c78a5a16a6fbda3c6b77f); + tempvar res = res * point + (0x2c15afc87ef81cb58ec29c7dd81b4cfe291e5d33a7b36126289a8ebc1af4eb4); + tempvar res = res * point + (0x1f90c3eb7ed36bec79f803ab1884e5455581110ab713139cdb5207561a89a34); + tempvar res = res * point + (0x7c537f749e37ed15d7e5d5d0f88686c5d02242b6c487ae2c5606d2c7de986b6); + tempvar res = res * point + (0x4db0795b76ed3b5cf3cbc23bc47d20abe9b9f76a2731f2774e6dd5ecd6eea05); + tempvar res = res * point + (0x3a7ada56cb16708c6eee7af3688765728c706a16baf61d0582186a3717ef552); + tempvar res = res * point + (0x4c9b9f2c154c6a8cb1fbf50793787d215f2857d042b21c6f5e2740732cca567); + tempvar res = res * point + (0xdf2e87cea7f46ab09a5011d8afca4e7cb962e008fc991ea16d85c472dcf3ef); + tempvar res = res * point + (0x4df83db997cffc8598b838a9c8373bfff5e109d71ee3bf2a18dc0e621e93d2d); + tempvar res = res * point + (0x17eb7ae4a950bce2abe1e7165594eaa60be7b75cefd8007425a735264a1371a); + tempvar res = res * point + (0x6c8258350c092e7b5cf658a6bed95d620afe0563482911a1435a93bcb0d5beb); + tempvar res = res * point + (0x554563c23e6ec8a4497d670e81940a92ddad53c27e7bbc18de74d2b3734d824); + tempvar res = res * point + (0x6c9568c4a9f64874e71c88cc80576e4083f6d0649f66929612a9bb99bd958e1); + tempvar res = res * point + (0x14e46f8471beb6479fadac1286dc86683c659bf1c77dc96bcb303d48c115d7e); + tempvar res = res * point + (0x5eb4774b76a39af609243ea0ca61eaf03255a02d90be9a83901debf64875f0b); + tempvar res = res * point + (0x3317e8a32e8f82246423237d2a4039eba358a76adb8065751b6d7939fadb85c); + tempvar res = res * point + (0x6cfe464b2a4d4e77c09e0beceb4e368bd93aae5efaddbb92e003afc508fcb33); + tempvar res = res * point + (0x3b69a8579df2cea96435a07c81ae1d9f8a5e0e52433335c3e7ad81b76789788); + tempvar res = res * point + (0x3f26981ddcd3549baf47e3f1242b0bb90d6b7f426ba71d2ce628ceb801f3734); + tempvar res = res * point + (0x40d8fb43bbc7e5c35e4b57fef4e8351ffb118c9d92346f97ff7cb48b0170eff); + tempvar res = res * point + (0x19eec9d276c006f19cfa904a4e2ead857e99000d16e897dc8dc955c57615d54); + tempvar res = res * point + (0xcfff274a78e56ec27e29d01f2e900bd226cdb493a83358f9b807235c9aa407); + tempvar res = res * point + (0x13d4454abb9515f00c3daa6034ed3759ea722a953679c4f857511141b87da93); + tempvar res = res * point + (0x2ea5039159478e68762063624b0f396cb7f1bbfe8c1a159f65f0f663f219136); + tempvar res = res * point + (0x40508ab9b5b8d885f85750bb659071d6cc04639f43070b94a802d41723bd0f3); + tempvar res = res * point + (0x40a9f47d93280a641e7f903b1e608cb443ed5d59f24cde6b92c6631cab1e009); + tempvar res = res * point + (0x5a5085cb551c472af264b5de50ebb7b4bb04539c9afac1339f903b943578eea); + tempvar res = res * point + (0xa89bb9df4a46c56f2f40748d826d50285082118f8995f5e7638a05ec117c47); + tempvar res = res * point + (0x5950e4370508dbfa764621025e9341994a3ac21848f3e39d02370b193ba6937); + tempvar res = res * point + (0x6f20da2f1a25f1fab33e7856067226784ad992f8bb53249ee7bb17e86c82070); + tempvar res = res * point + (0x42271e06f205c1bfc9f9d9411bf835f43941c88aa3dc75f044a0143faa4d5cc); + tempvar res = res * point + (0x411f9def562556de87d47af60354512d9a1261152e7f4636038699d468fc2bb); + tempvar res = res * point + (0x66490371a5dfa3fb85bf3f088b89614b5e56cafc263eec39dc4a1bb39e03433); + tempvar res = res * point + (0x6d49bd35b4e4aa46b7098d306632014b4fbfd84892d6997b58d9463a0ea2c05); + tempvar res = res * point + (0xa9c2bf87d58d3f72d985b4b1129f0a1664caac1ee26a15675d1a5086de3a79); + tempvar res = res * point + (0x46df5faa750270394a4253e63ba3e437550ee216ebf8ddbbd7304940c85ad02); + tempvar res = res * point + (0x6e5bf767f3b0646dc16377f3bb7c17db6069555e100dd2215eb20c4d29fb1c3); + tempvar res = res * point + (0x5d9acf8582d4ccc017af36a8a9863e4383b63893d3fb5d81f7fabf4ba3d1023); + tempvar res = res * point + (0x6933ce3f88628188f7a1b1be5b0506dedadd9559c4766be0e7db1ace3adb592); + tempvar res = res * point + (0x40ba0e2f504aa0e9972018d91be21f56bde16361282915563796c750f8936b7); + tempvar res = res * point + (0x6fd73eabd21a86dd8094dd0ebb5924b1aab0753a0d251571ea93f83ab4bd519); + tempvar res = res * point + (0x2761e32194ddef695d1837c8a3f48a3773ae392b5633bfa0c1451e51e33b69b); + tempvar res = res * point + (0x5519091c464bab5646294ae41d087ddcef8bd0508a94a07890fa07220bdaad3); + tempvar res = res * point + (0x3b160cef807b72e95938852093a3a633e72b61e0afad5099201885b54be4098); + tempvar res = res * point + (0x7692b996dcfecd35db6aa22de10144724c478f85a328ab893c6fbadf43d7a9e); + tempvar res = res * point + (0x3512eb8a3bbded6fad1c19190d857629efc56f93fb4aa527e2958dfcce12153); + tempvar res = res * point + (0x591ad3fb7ab83f8d9fcf184ab793baf3db128cda0de1618932851108771cf0d); + tempvar res = res * point + (0x5f7da39edb0781ca1f96af191cf4c70fe0c121b7b2c92f09b49503bb070dc99); + tempvar res = res * point + (0x4a94669a4901cb5527124a2dc7ff6c278d540da41a95e819d0ca10269f7b380); + tempvar res = res * point + (0x20a06257ccfa90a74adf9bb1130a8385b8c91bc61e18acc30843463e5abaa2); + tempvar res = res * point + (0x7e3c052c620ef7fcf180898d28e39348e96e92ed0634dcae3f5fc64be5094a6); + tempvar res = res * point + (0x578dfc700a95a564b41ba8f33b885ad04209bf5169a4046f603a3d84f792d6d); + tempvar res = res * point + (0x796c9b073e2c56f55601eb1f6147d028553275e9fb792f0b76007c9710459c7); + tempvar res = res * point + (0x8c2c75a2fe00432f77ef57e906f264ea76c439e0c4cb19e87867a6ebb34d0a); + tempvar res = res * point + (0x525fee2e2cdb7a293f50f630a840d5cf5f29a158eadd6fa9d0159951712d19a); + tempvar res = res * point + (0x7991462c103abfc3bc31427227b1fb82f7fdf2be1b39316f46e3baef2fcf588); + tempvar res = res * point + (0x46d1e806178137e82ea97c54d8c15dd45c2a9a0082b18aeb9f849158ffc0ee5); + tempvar res = res * point + (0x25a127bbf961fe2b5bd9facbda706223206c40acff003152cbb3b28e9668030); + tempvar res = res * point + (0x1e3d7c65a8f40b6f8aab1635e3b78d0f798746532f08771267a9b6149632a5a); + tempvar res = res * point + (0x25fc8ba8ab421b6dacf2ce03263e037374e4d61c6ce26422fbcb2e755c0d9c4); + tempvar res = res * point + (0x48294f41052135cca94fcf88cf236437b8a55370c3de81fb0d781aa7b0f8eca); + tempvar res = res * point + (0x8c5762a12210a7fdc96a7d3aa966476d3b28650e7c49fc90f95e49a80d4324); + tempvar res = res * point + (0x4ffe8275d3344b4ae2f7d9992d68598e50f365c0b8a721d723841485fc25c0d); + tempvar res = res * point + (0x2959a6947bc4eee0135bbd0a6f2053b62317a1718bcceecbd507417d31e8806); + tempvar res = res * point + (0x77efd8893058f8e00863205582a5e274c344b9af63b9c40ddd92c97c33b52ea); + tempvar res = res * point + (0x73796a0ce0fe851bc22b99faded48a24a21745bb62603e750f78b854d7c32c7); + tempvar res = res * point + (0x2d2e43c0ad60d4265774479258211274ae32b5e151aacf6f8ac1b7708076f09); + tempvar res = res * point + (0x22b5eab11c9e1e6b8d64d5db4b12502fdf0899497f72ee1a27c8797b617f76d); + tempvar res = res * point + (0x703c768145191a10344e5ca400be8fd249e653d564015d46fcd7096cb723a0); + tempvar res = res * point + (0x4159f8056bde7fd4f72615f7bdd0bb6408256b8b216ca52fee253113d9d007c); + tempvar res = res * point + (0x5fde2cdf0d23d5649e3aead1b2b90ca0309715a029654e8984e43de7bde7b06); + tempvar res = res * point + (0x50372d2aff2ebc566505a564d971c6491095e009d9887899aee0b5017fcb877); + tempvar res = res * point + (0x3333c3d925d8c58b9e4e533531e93046039577cf0e57d011c7ce87c6ef1a835); + tempvar res = res * point + (0x575fb11a4d7e3876ae4c86b80b4b9530e0d3e9db218f4d5644f612348f8f002); + tempvar res = res * point + (0x3481879ec47fc8cfabf38ffaa75311c787b7006e7f9def35e96454263bba4aa); + tempvar res = res * point + (0x5c1e733995aad208f0697e4d2a6e28bec9fddc3e30bd033f2f50a83927baef1); + tempvar res = res * point + (0x2edf44b1f59efb0f36c0fce5edbb7576c89cb9f191300fc5e0240def1b88b9d); + tempvar res = res * point + (0x1d46036b736e06016c817d2b51a0918189881a4f1b7c71d556db583df762d37); + tempvar res = res * point + (0x258ef77b90879282ccc2ffcea5052cad266d77b75db36b7996e5fe7638e9b00); + tempvar res = res * point + (0x4219a0a13e09662f3ec712da51b36967947f6d5a09d8044e3005a7f0ab45915); + tempvar res = res * point + (0x18d0f552fd62f81b6076265c7a3a0b81f6bd37152a2f16c71210021ecf68468); + tempvar res = res * point + (0x31abb6310a44d65ac8c308011d4afab938fdacfbaec14c62b808452310b799b); + tempvar res = res * point + (0x1765a9eca4f4551f177b35089f8befc808613bbcd971a47d485b1c220d0bbb4); + tempvar res = res * point + (0x7fd44af0ef24f061aa7dd5bbde15098dfc3721790ee9bac2caa71cca714ebf0); + tempvar res = res * point + (0x566edfbe3c59cbd43838ee245edfebe292c7163f79b1454b03ef3cf8af23c10); + tempvar res = res * point + (0x14d01a0c81aa61c5a238243e78afe80e5d0d7bf528c3d05a343d0f4470d2b0a); + tempvar res = res * point + (0x38445d5f2de7993c48c9da8e77a87dbe289dc0428b1e4ca87e30b2376535543); + tempvar res = res * point + (0x324db878e3842c25a78e94453c98434c54b41955db62234b0ec5ddde6641556); + tempvar res = res * point + (0x184f23c10c726d4a7036c39466db02c4fe7c3d40bade571fe07acaa282f4c07); + tempvar res = res * point + (0x7fb1cbd7a48f2d44a148bd4d17ccd47c438f4f1b45a02945cf4312afa0d6f95); + tempvar res = res * point + (0x20d2002cba899acc7d333031e0977d8df94557ca0749bef6c38b72dbcd462f); + tempvar res = res * point + (0x75bd5b63008c2e005df64ca189ecce11c060f0df6903011a3d95cf9f7b48878); + tempvar res = res * point + (0x548724b5683cd6427513b4c4f84a6d888b9a03843bc0dbdc501b8752d99ada1); + tempvar res = res * point + (0x38441dfe93fd3133faf52208f3263d4ecaca0643bf9c9d4bc952c86cf280f7a); + tempvar res = res * point + (0x182e50e36b753ff5f95f2bc47a6aac8c6f2e5c3975476252a7c29250eefb056); + tempvar res = res * point + (0x2593b010eb6fe0f64833e4f22f6854c063085e0dd393226e6b5fb20ea7f432d); + tempvar res = res * point + (0xcc060a8b007b2dd0efa786afa5edcb512d83ddcba8ed69c27ccef5769deb23); + tempvar res = res * point + (0x672717b74bc3dca9e53494681a5ffa02edbb0290de1c5209843a16964df7a3); + tempvar res = res * point + (0x53774852c8f84d21eec107e1da7a2ab3f4b5ceba6479d1f902ad404e7dde329); + tempvar res = res * point + (0x96de7b9a7eac739df4d13902971804aaf40f5559d18593be0daac0ff86c636); + tempvar res = res * point + (0x725601ed4fcfdaa392b91e8ea982fc57f1874378ab8d6b55301b3d4b6efd802); + tempvar res = res * point + (0x7bc4fea0ea687295d72735a62a19c1a160a1b9a19342717b527f94770aca77); + tempvar res = res * point + (0x3dfab578cfc7a1581212074e0969db9accb619a043dd7194a253af67ef3698); + tempvar res = res * point + (0x44090861421dbb6b4a325a6832e02986be80f7ea475313ae01a3215c3510346); + tempvar res = res * point + (0x7384363b4495aacafd81d0a139a66afd3243309395e3444fb3f1496832240a9); + tempvar res = res * point + (0x4f6ea70b9090971f8de7071f27b0d036b112211403e0547fb7b7903704f295b); + tempvar res = res * point + (0xd55dad93e837d31e8f120398e09b83ca68f160c16043e1c65d033a19adbc30); + tempvar res = res * point + (0x6cc09dc2faf0903dbf5121b97ef058300b18efcc30c25f55de752d395b568a9); + tempvar res = res * point + (0x2b2091e41b10140bea196a1cc28d7f6db6ae1b55d1f115d882c321221a32eb4); + tempvar res = res * point + (0x11b19b3abd2b297728768027b1370566bd845bfb6f49197a76255c1d8c661f); + tempvar res = res * point + (0x3236ab2e0e0b1b013c2100283e36fe75521bd50091f1c73deb165e86616d80a); + tempvar res = res * point + (0x7351448e92ce6914278e73ceeb080e280c146dbcc21cb35af8d2c7e5560aa7d); + tempvar res = res * point + (0x100a89bccb889f183c2a6ced12bab8ef86403230ae6b23def0b784f73ff296f); + tempvar res = res * point + (0x31e49312e1d59acae36bf3562443259500039a7a77d9a57a44cbbb4a80932e3); + tempvar res = res * point + (0x273647256f95d2e5f98bd7830191abd89dc4ab241fc7fa12b27e16a6bd423c3); + tempvar res = res * point + (0x424396bedfddf4192963ef0f87b3989a99f277fe2c60756a4a60fae4d6dfa31); + tempvar res = res * point + (0x6e3a0355459b8b7c35837f3f19f0d8954907326cb08d7d084f2ed0f4b2af8f5); + tempvar res = res * point + (0x2d88caa65f47db103fb1ca354bf50c93f24bca5001598f716b6c9e5c51d1d2); + tempvar res = res * point + (0x2dca037a615e8cf99f8614f437e953c5625b9b57d95f16c174f63346e31c5da); + tempvar res = res * point + (0x5800bf15808a39f1acfbb193af1ab0c22f18d9738753bd3cd2aeea81982409e); + tempvar res = res * point + (0x4ad97a9b0ab95abc1b8fcff31a48e18fb2391ac95baaacc62125bd87fd75e13); + tempvar res = res * point + (0x5ba49d41f62b6d6903fc455bf02bca54becb6ee7f39650fcd0b717ac396159c); + tempvar res = res * point + (0x959c7bf3885d75ab3ca9480101ff64d62c9f138d35f63c137009c1b3eb39f3); + tempvar res = res * point + (0x6da06ce868c140c8ff9ec1eb0323fe2c8b35b46c8d4f5a27727450e87ebd906); + tempvar res = res * point + (0x1bf01c19527dd1d9094c44e3acee4d1ec8c4192026b6f996776294cc9dbc4a8); + tempvar res = res * point + (0x40d1ae7e7bcddc520ed8c0fd736e9b5147d278ed1b720abf76439377023abea); + tempvar res = res * point + (0x2f26fb29017b5ab80328de8488db547e47c44c0d56f30e330354d5b980e50ad); + tempvar res = res * point + (0x72bcdfbdd09f13eeb0c01565dc6a79999a9642dbcb0c570e3e7621ca94df215); + tempvar res = res * point + (0x140ed138dfc5b5417b25a4512bb991f3fd04cf750e082fd4fb82cc15b645835); + tempvar res = res * point + (0x40ffb20c2a3dba0a0d8b6aa51ccaa1b690aa08670ceee556d76053cd671d522); + tempvar res = res * point + (0x283c74c8066141911634401af10106c29dd77458d059ff3b2dd7aa796b2a559); + tempvar res = res * point + (0x593df80dd238cbdc6398146502310a5cb459b0e7d79fa9bee5cc389385c95b3); + tempvar res = res * point + (0x669bfada09faa64c005321d60752662598d69c517e9ffa462dc1b1af42228d1); + tempvar res = res * point + (0x70cc78b821b198e72f8feeb8f31d81e5a4854de3575a62909e0bb51cee921d0); + tempvar res = res * point + (0x68539d0ccd1737a8b2e540f9165638f86f6c4e44943455d311999b0b3684b7d); + tempvar res = res * point + (0xbb867c323532bde3d5b0e08b1b7531a95a2a1706132dcd8ebb7063cd1b1bbb); + tempvar res = res * point + (0x751a2c218f4feffc61e90939c4d2672a263d3b33528c7c6eb40042640f45146); + tempvar res = res * point + (0x6473d78fc37e48379ef8a9d57e3e92cf4fdad3a1bcc170dd177dbc51c4dc62c); + tempvar res = res * point + (0x7218f86344ea46cdcc372a22a14663105eef03bb0de9da9bfcd10818d36ba28); + tempvar res = res * point + (0xaa17b17cdb757833dd4b1670371ef55345debfb2c1b6bdfae64d8759e04349); + tempvar res = res * point + (0x38cb4173a2b057da41d5d30b55f6d11f25effdc69c14843cc43a9ab269630f0); + tempvar res = res * point + (0x4350a29d7b4b242b20b68f6eabd75b758d8631c192b7da5032181b71740b96b); + tempvar res = res * point + (0x42518069a18922e90fa2fa8fe9bf5e2371a40ea88c25d247e6a73a007105dd9); + tempvar res = res * point + (0x7f43f7128a1b46f8ab168a06df9d0cade82a3193eec2d51e2b83f4f0c7fabd9); + tempvar res = res * point + (0x6e694d9385207d7cc8a7cdbf90eb4ed3be49cabc0e6b8d0e69172d73f4a5c11); + tempvar res = res * point + (0x2782ab60e8e9c6cccd40f438a2d2814ef39f50f02bbeb790bc6df78d75af42b); + tempvar res = res * point + (0x259f8eeaf6cbdabd37b9de029661bdcb219245a7599207d3df08c7cc452a13d); + tempvar res = res * point + (0x9345d2e4fc86ae78c4879ecc3adf9e6c482044052bc3738618247b60f069ad); + tempvar res = res * point + (0x4419f27879dacd62144bde4f904890c6d5b312282335a57cf1b04b403bddbea); + tempvar res = res * point + (0x581755fd25823d2f3b07ac5d8dd1bd5b26eab362cec3f9e03573a2b03f62ab9); + tempvar res = res * point + (0x37622de79f6252ff6bb76900db06504434856faf33c59a1b2e39a4fa60ed143); + tempvar res = res * point + (0x2c4ffe18ae93ab53ff6d7d01a7b5bdc5b08dc8d144e0b917f47e60e3cf723f3); + tempvar res = res * point + (0x42ca1f8224d317275c78ca7762a78e6c51978afe1abcbf535da6d299c799c1); + tempvar res = res * point + (0x6403910df189d75aca61c604de3b0802a4ec2ffadb0ff60f1a01f363d66ea67); + tempvar res = res * point + (0x44094080f29bf84d3d5849f264713647289e9af1534ec38d1a7c3d2d2f1ab64); + tempvar res = res * point + (0x3dd2900899d2219ea16fc41413af028057f0c2a674e1cc65032fe4dcb062d4d); + tempvar res = res * point + (0x5a612887264b1ff8e5239b3e04143dc30d0a80cef1c880fe52ee2d5009092b1); + tempvar res = res * point + (0x5ca2e5676dde96127ca85ff6ac82a8fb35b45651b88bcdbfab7ae5298d427c8); + tempvar res = res * point + (0x4b135ec421e9138d09c709a5d92ba70e6944cd44a7eb7f705ab3612de315ac); + tempvar res = res * point + (0x152b3265b01fa9ce0cdf58c17cd14c2cf3e3fafba140db9e27da4fdde7d3c0d); + tempvar res = res * point + (0x55554f904554d2f262d1db49d7c515414870717c829b73d6c439260a8bba3da); + tempvar res = res * point + (0x3e2b9e4151827bb0d04858df547978536215dc06143674d0d2e788dcdc9c36); + tempvar res = res * point + (0x2c30d5e07853079c9f11624e2431795e2bd8b4bebd8cac92f158306b45b0549); + tempvar res = res * point + (0x4e922a3c7df1c668f86b866cf0c07ee4658e7754f6fc0fb62cb297bb6960320); + tempvar res = res * point + (0x35b787fb9889163a9fb5ab831838f19092aa4ef8d8dabb299045740959573d4); + tempvar res = res * point + (0x2d847968e995dcfcecc6ef98ab27f9f1db36b14ce3ba81b80cc92cf19750f88); + tempvar res = res * point + (0x6785d833096c9d9d06034ba4d7f8d71481d4b680b63693d9fa24ea10d3511cf); + tempvar res = res * point + (0x5617f72f8d0da5d7cafeef9269395ee34f921f5cc8d1a4f4c0292a83cb0b9bb); + tempvar res = res * point + (0x6a1373cca7777e3cfacc6502ca9bc645678445d98acf3d6f5ca6c82cab53174); + tempvar res = res * point + (0x5b07a69abcc274ea09eb67f2f6036b492db1f9b7e0a3497d8f3920de22b3b4); + tempvar res = res * point + (0x74399a1effe3a13a8effe952dd57142c254ebe807a56f13521da38984a0b55d); + tempvar res = res * point + (0x6a399f5bede4f507c7251a7ccd110e21173729f5f9a57eb16a27203d3c5e731); + tempvar res = res * point + (0x13102ce3fef387b552a6b8967f788cc8f8502ef0f2ec293d2b872328f78b6c9); + tempvar res = res * point + (0x2233376db0eee71ed0bc6ec0de23782ca9e244a06b8e515b2855b522259eda4); + tempvar res = res * point + (0x6319176edd9fe726efbcc70108b516e26152cb56329b842a1e14adc2a3e47b2); + tempvar res = res * point + (0x12e828f63839dc0dd62bc23385c0bdd5b11e7b6de2cddeccc47f85027c9862f); + tempvar res = res * point + (0x1b5bfb21e549706eaf5c771448f91d1ce03498029ff4159d8cd11f4b6d523a8); + tempvar res = res * point + (0x223b2c9fcd5a1d4b0f7decaab98bdf87e5083865ef9b6562a261fc75009e725); + tempvar res = res * point + (0x6856abcc37696eadf09ac823f589a05b034ef8f86e41d2c6222f039707017fb); + tempvar res = res * point + (0xabbe74553aa10ee20ec6f0f49f73281124ca34d0b71c2e80160f37d3ae0345); + tempvar res = res * point + (0xf7043785f78a94a68b669cb366c00538eafb8e87b5380c68518d4e23922d6f); + tempvar res = res * point + (0x43a4dbc140986d44a7099720e13ec46817f0131dd109a48fbbcf190671f35d6); + tempvar res = res * point + (0x7fb8438581e1ae31877119b91ef1ea28181ba8c0a89eb356313c8a910295d7c); + tempvar res = res * point + (0x125399adcf39aaf7962e3be41c6f9c7691e45c2c31b937e26257d94b5454985); + tempvar res = res * point + (0x3a3c97667e93fa5cc0531c8a2f6d9f84c4f683133b8941fe1382ca8f6f2fe0d); + tempvar res = res * point + (0x253548b05c44cb4d8f2d97641773cf812f709663fe8f492f5a77bfbc8477d79); + tempvar res = res * point + (0x3e828a46091dc07cbbbb0dcbf390e4b5cc44d086b0ba74051fff237f7d6a74a); + tempvar res = res * point + (0x74a80f191573d77481059c14f56764dd2c11571b2736d355efa299c400f0377); + tempvar res = res * point + (0x76169700b631b19086b8b1737e23f1c59cf1428075904c80db724383d3c6b5e); + tempvar res = res * point + (0x7febfa3ce41434e03eccb6be0099dc31d90e36558dfb6f9d21b3e0be41472b4); + tempvar res = res * point + (0xaee16ac845b8bdb7d9c1c85ca7b0e749a7c47229ba24ba097b4b6b8151cc4d); + tempvar res = res * point + (0x31cac8c51732d8aad5bc41c9a6440d482c2c4967e75a571c31b2d9aaaa64068); + tempvar res = res * point + (0x203db741e5e80c19c2bea387e3091420b918fe1142bcf2bc13ae7e098282fda); + tempvar res = res * point + (0x2449d2be3af1fcd8984a9f857309ab5e0e5c010680e33b03a194c6e902a553c); + tempvar res = res * point + (0x40246dcd91afc0098ab9568a5c97d54e09065c551bc9d26ba0ab6a00089bec); + tempvar res = res * point + (0x50cdaac85b8d8bbf55a920bf8d213e333eba5f2bd92e92c61f3946617222ade); + tempvar res = res * point + (0x65dbe95ea2b7d1894854b235f2cc66e910fd2791ff09b92366c7685c652a8c7); + tempvar res = res * point + (0x18f3259c8451dc5007e94efcc6e90c6951543474925fd28ff35e56890bfb66); + tempvar res = res * point + (0x69021f5cefc75ce473977c2ceae2e7c66a84bb3d734eebf4bf497e56eb69959); + tempvar res = res * point + (0x4ded7eedcfca4ee336fa075aef6a017beab322cf7ddf83bccfba05f1c93cad); + tempvar res = res * point + (0xdcc0df28639fd96570d93a6d1df1cb1dcf6db8a259ab092b34cdb411895aa2); + tempvar res = res * point + (0x2333165fa7f9414f082253b8451638fe1e9da3ba8c1246723dbf9995e49d017); + tempvar res = res * point + (0xc8b65a737b5605606028a064d168ccf32d8d87fcb55c6c853fd95ae0961410); + tempvar res = res * point + (0x71d72b0c23e31d703f0210ecb2b28994ad828417531a15a17a1fd401daca2cf); + tempvar res = res * point + (0x211c3e223a3c9c4a024b490a819254ee133ef9740a4026eb3a036bb9e5c6581); + tempvar res = res * point + (0x621692ad7ad27517f4de4e528e1271719cf5b344d463c86b9cd8424a4fc274f); + tempvar res = res * point + (0x5ab65084f4ee8261bfd290e2d5608fde744be92da2eadd5f2fb909ac3d14818); + tempvar res = res * point + (0x5896811c73c991f479c7af6238b51252178dcf4371c297326bcceeb8ee454e2); + tempvar res = res * point + (0x453705ada0d5db6b0afb289b29db6c9acedb01e742cb0d68705d07f8dfcfaae); + tempvar res = res * point + (0x168f97539fdebde7280f4d33f7d5b469cca77495efd4660f31b7d8018f7f89e); + tempvar res = res * point + (0x7829c898e33552459e8fff13c01f1e0d9f5b098f0de7161cbf97da52914bc38); + tempvar res = res * point + (0x5b23dd8ead53bea28246af5a3a63daabf41e7987fe61255d97f2a57bb6d14eb); + tempvar res = res * point + (0x7b631dfaa76643b5f46a069b8c40038f77f088374320add0ac3c9924a12f153); + tempvar res = res * point + (0x2408fff139dae5eb756ea03ef15a2484f582f7ab27ccaa09fa8154f3bf0024b); + tempvar res = res * point + (0x28aa32bfd8c8d7ffcb0b5dadfcfd1b6bbd69b02de9ac1bee786da98ce76c8e1); + tempvar res = res * point + (0x33eb39eae1db6ea48126be6b300b31f6bbe275845822f9eb293e9f7ac38a777); + tempvar res = res * point + (0x3e549a3d3849a09d8f1c50f84f7caa4aa0a5b8ef6f957dafcd13c7c90e4ea11); + tempvar res = res * point + (0x2f5e865731de5068f289b616b39c2294284c111540abfdbb33a39780eb0bceb); + tempvar res = res * point + (0x4e51def182a5bd5672ced3106f19ecd94b760dcfc68e66a3656d0b5db19165f); + tempvar res = res * point + (0x42f46c19b87a82522476372ae65817f8d53f263674a040531bb37935b289893); + tempvar res = res * point + (0xf0bd4817ef6ef818a35ca3678f88abb078678a1364539bd7886dad527cb28d); + tempvar res = res * point + (0x501f0235f18b49889497cf7c91fe0a1f81d74da8cb1e88bcfca9127392aabfd); + tempvar res = res * point + (0xc11cd155f0a514a5a419d10ffa72405817256ffc8d580b9d3ab002f596b2ff); + tempvar res = res * point + (0x9f712ae0384a87901ad44f53eee9e7c39544893d10b891a92e87e4d78e8374); + tempvar res = res * point + (0x2d511bed457c57d7354252189efd19e4f5c3496c1dbe1f1408ff79c8cb97025); + tempvar res = res * point + (0x6c8d7abe5c83db80647ff904bdbf25bd0e979607d2310ffbefaa1edb7ae1bb9); + tempvar res = res * point + (0x46e747695d9d234e15781125d05b85ce3cb01d676ef8fc45a939d5e6d4e2e56); + tempvar res = res * point + (0x21c86da8be11246b29f17d5f7f3566c20712711e03eba57f0ecace8c4355418); + tempvar res = res * point + (0x7b851f4004fd9f20561e3755d7c89528ddefddbbbcbaa9293e416c0dfbb95d1); + tempvar res = res * point + (0x31587ae13086228663118a1fbfad6d65bb9741d5682abfb43c7524cc6c240e6); + tempvar res = res * point + (0x2ef1cb499e790f2de6129225457520b560c1c3120457e742957d1148bb934ca); + tempvar res = res * point + (0x781fe3d95c096c6df1c9ced110914917e26d0860da4bd769e4682a17540768b); + tempvar res = res * point + (0x7cf92bf7e933187b6ea01019ed1c2d9936e53a9ea89724e00e36672dca1e36); + tempvar res = res * point + (0x290b573a86b30d59fd1301b7985a68fd9bf9dfca5451179bcd13d10eee988aa); + tempvar res = res * point + (0x4d3987a0850d8159f9290a8ae8cf99a0ece9961d22135b584d8fc742d42c15f); + tempvar res = res * point + (0x6247162754e5af6a0efa837daba678811cd749e92d91acf35d732aaf4bfb4f3); + tempvar res = res * point + (0x1e3df9ca8b80529441770e007a27cda52e54307e4f3370a83705e0f3ffc86fc); + tempvar res = res * point + (0x25579cd0082839ce295d9bdb24140a8f2fe19f7d582a4993a88639a0347a522); + tempvar res = res * point + (0x70181ba88ba8d19c0220225ca0112845e23ed7609ffa4f2aea3cd40a40eef30); + tempvar res = res * point + (0x481c8091e40139c67f7e69737f83a6c868e582526afd50b548bcfa5ec2e83f9); + tempvar res = res * point + (0x1a758f2faad6702cac573f8ee11d83977ca75744f52d650a6dff79bd6c5caf3); + tempvar res = res * point + (0x5a87e6f4731da56e8b078bdea4cc3f1fa2059943de95ba404ab38addce3d6db); + tempvar res = res * point + (0x62a78aa9e73bc6da0a8536da8dd43311ccfb52829e89e9e94f3b413efb8ff93); + tempvar res = res * point + (0x4cb8044c471e8cdc896ac725744d1a6942bcb26d50b3641e2a95f57b0e7dddf); + tempvar res = res * point + (0x57d63baf011722f5c5a9c4c60899bd918c3287302c97e91fc6f9f8ba089cb97); + tempvar res = res * point + (0x60de66fa4cc5d53fcd9d027cc06945a96de2f9b4f7d0c81c53a7567fde886dc); + tempvar res = res * point + (0x794e6f83556e5ffee6d83daf40a067363b22e157cdd970366757d5d6a02dbc9); + tempvar res = res * point + (0x1dcd10514fdded828639c9c21d0c8064647947e9ced01014ba8943b1d81bd12); + tempvar res = res * point + (0x7cf749a9a9177ecfa46b901ce91a8ebe103f8920d83713df80efb7fc8868346); + tempvar res = res * point + (0x1ecd644cdd8b92b3c042932407033c073c7da5f3a8726210a443f10af466ff5); + tempvar res = res * point + (0x55b74b3af769611aa4c4fc71b1abed4396b218a9d5884844c937bc38b30bf8e); + tempvar res = res * point + (0x4fc4e265c8471510fe6f0dc99d7be1108eab6200b0845dab07c5a126c79919b); + tempvar res = res * point + (0x37edf969a82e9364a741858bfca74b30e86b1b69b4f33bb4a31666f4b2e7c10); + tempvar res = res * point + (0x2a3ca69d295e5e750b4db8367227f9cb347b3693251ba9761a22d411de1c41c); + tempvar res = res * point + (0x7e9f729b710f0fb173b36a6ee9611a9d309a9dc69a776c08dfe63c64c528a45); + tempvar res = res * point + (0x1e2c3057002cdd12b80fb157887fc066b41436bbb71e328bf79ed2799947c49); + tempvar res = res * point + (0x32124f76e477a3c6f5f4346f8abc19cd481b6f43088ccd1c3e8c634bd90cf); + tempvar res = res * point + (0x5007d334256950aba31d4bedb5decc0ba6ab62a09c41baa8ab8d0eb4cdc170d); + tempvar res = res * point + (0x3a06f0e39b3afd46934c41a79a317f220c6321664cbe236ffe1c191ee0b2c85); + tempvar res = res * point + (0x18db208640b40e1acf69b256f0cf86c76f381ee79fa0bbea47fed2c95b5467c); + tempvar res = res * point + (0xa0c5ba0b916bdf79b70c0d23013443f65bd087aaca62088b0d1f7009dd2d70); + tempvar res = res * point + (0x5dd2afd2e8b09f86360d183e2700f71a4fb5e458c61823ece1a4e60200b82f3); + tempvar res = res * point + (0x5b3102b46125dd26f3ae75c22cb8be10a3c98f269a2e91ce7d595d25c77e6aa); + tempvar res = res * point + (0x2c489389378216a8f4a24999efae5d41af3bf123b10601d2efb419999f329e9); + tempvar res = res * point + (0x28bb7956a08b64ed0ed089f0219b05b282eb25c107731d88867f7a78c3e387e); + tempvar res = res * point + (0x450e38572d5b45eba95a4368d52056640cc18213b3065bb7b373a05561cd44f); + tempvar res = res * point + (0x6931414c4f1e51dd287a8273a71ff946d1502d29539815c6652e6b71c95d013); + tempvar res = res * point + (0x48fdfbe3980d1df8db00fd59b4b529abb0569c82a25c6b23186de11aee23a40); + tempvar res = res * point + (0x680f30c7e737040028b548f49d2110d8889aa8dec6afe1de989e3f1f0c1c84b); + tempvar res = res * point + (0x8955f2b26c2c91645402ea61e0b3bd091758afa740b4478e3fd2d97b7d5729); + tempvar res = res * point + (0x62796f07255aabe16df1ca5ebe7f7be4eb1e9b688defe3044b1fb8eb56765a3); + tempvar res = res * point + (0x29f85ec8df7c753f09bd36309e6d7d65f5d5c327d4c80ca33eca932da5eea0c); + tempvar res = res * point + (0x40f21a24062575a80e5a6b6fa209f04178fce24323888c3fc9a083c6cfffe71); + tempvar res = res * point + (0x29eeec3cf3ff9267792e170045fcbc1358ad5b9c28b97db6f4cb5a131dd1e57); + tempvar res = res * point + (0x6d82291b429009057a7d89082c7c3ffeade1cbb4598b6bd1322c2e2d3c6819f); + tempvar res = res * point + (0x78ffe33137f03476882656c458a984b78bfe509d0ed005657860541fdd16506); + tempvar res = res * point + (0x13f6d5bd19a25ef48bb5a89c64894e9351380c31e98fcb8404c490081665acf); + tempvar res = res * point + (0x36d9f7e5746b465ccd284ac21d5cec14258587d22189b4f85ea87f9b4d7c2ef); + tempvar res = res * point + (0x54730884e1c5c7ff5bff889e8e5846f7e552f07beedb27035c0eaebfe676023); + tempvar res = res * point + (0x7344cd22ecc8029fc605bc46e5f2f60c2910130290257210f9db71f26dfbdcf); + tempvar res = res * point + (0x6a60ae65aaae41d02d6ad44360c269051a870c66a87e430eabd1c2c5dd8261f); + tempvar res = res * point + (0x639a281c19217bb79dde39d86549ffeaa0694283fa876ab39fa6b663869ac9); + tempvar res = res * point + (0x48a07a1f3adb4348f65ca07f7e1ad0b70a6024c4934df5724c35f1930befc90); + tempvar res = res * point + (0x527d59fcf4e21663d7e921cf93b705e95fca41d9d2f88720800586e03bdc283); + tempvar res = res * point + (0x1b07576ead1fa791e38995e423ee788587adb512c1bda749fc0869ac6b40c6b); + tempvar res = res * point + (0x7b59c1f0252efd3b471c3047a2060ccb98cb86148c1b1893af4f86384821b04); + tempvar res = res * point + (0x56e48833c5707aaa1e38a0d644765251c038ac3f89ed4d58fc3b24d03a83e77); + tempvar res = res * point + (0x14d1da51db79b82ff5fc48e18ad84a98b1390d8e61e1580ef5c6100d49da80a); + tempvar res = res * point + (0x6ade2f8ff114a1c0a0f108286f0f0e820073e7fee989a85fe11a97b972f077e); + tempvar res = res * point + (0x20268b11ea1f54c737a14073b8bd83a6151aa30b0d51182446adc72aa2bef83); + tempvar res = res * point + (0x937368e9df8289ef2d93e806914cc9ac730750d1ecc6ccf6c4aa6e6788d35c); + tempvar res = res * point + (0x297d16ecee6310efbcf8a2946e1f03e23ce1eaf88fa6279dced371db9dbc299); + tempvar res = res * point + (0x74d40da7c08b8fbd488137dcb60906f2004a26faf06e6ee4dbe1feceb94d98a); + tempvar res = res * point + (0x5669aa7f25c6cefb4a3e1f5491dc50af7c44ca9f8405864906b353c4c3529b6); + tempvar res = res * point + (0x4a5077d73c41429dcb66a5557cd392c5e8b64f4f93507e5e7b8f1cbe29a309a); + tempvar res = res * point + (0x5974550418ba46ba346cb87069b6c17f9a6d57ce7554827c8191072b4ff8357); + tempvar res = res * point + (0x6fb7a7f6c760b606b4f7cefa186540604099bd229b954096179a12ccd50e323); + tempvar res = res * point + (0x4fe2139f7019584c7f395a18bfca2f5ea89a9300bf208b9dc73686c76e724d6); + tempvar res = res * point + (0x4b45d3cd223171c9e2e8030a3983c2e4b6ed61a560db3a8da8a2bf1da05ae2a); + tempvar res = res * point + (0x223dbf6f82e6f2b2dce8397a7a6d00c8fe38fdd8463fe7612c1a90bb76a16c9); + tempvar res = res * point + (0x13e7cbf6809b1c282b1716db08a549825b9e1f24479288cf615c6557249f675); + tempvar res = res * point + (0x13b2e8b26fec1c97c5fac659532830270b08cc6861df86b3f3b4894175551d9); + tempvar res = res * point + (0x34a45f657061a57b808e337faed21f722e6298262a2df69d6bd34ecf2e29243); + tempvar res = res * point + (0x372a448e249504e459982c7d114b3c79270419467208096cfa6a96f3e5de755); + tempvar res = res * point + (0x5d62087a11238dba183191a31e686ffea34bd393310e7a2b11c75d63ec340); + tempvar res = res * point + (0x5f25fb2b70ae9e334bd288d6768a7b3b6b2f4672cb671f6b0ebd781134609d3); + tempvar res = res * point + (0x1025bf3b6ef4dc8e3637f4dd1cda0ea30ebba8c30ce5638b5f9b5291faa0036); + tempvar res = res * point + (0x7d2b1bf76ecca560b7409dee16ead5b2b3691ff75ef8fe5a844306a7e29b252); + tempvar res = res * point + (0x7cb9fc14dc4bbad427efdb3f5821fc9dd10fe8595577e39645ab9f62e6fa50); + tempvar res = res * point + (0x6f61949d4cbc8298879b470d1fa9aec82261a8099c448dfa4379a597ab01d03); + tempvar res = res * point + (0x336d1ccaccbef10084bc4a18f8c86f699642878a2b5d5af3a3fbe7a773e6904); + tempvar res = res * point + (0x354e8d015485a06adadbf43a6bad63e9330c4070fbf2a704c166e1d278c8d4c); + tempvar res = res * point + (0x45526e767c14a531fbc10f287b2a4203e18daad8a4883a1900a63dccc1a18f6); + tempvar res = res * point + (0x688bfd9b23436077dd139ccf0a7286444429f3a2457ce7e2cc939be2172921e); + tempvar res = res * point + (0x5dd26663ad2931b249bcf054211723be60b5b46de16a61928c0a9326874f3e0); + tempvar res = res * point + (0xaeb2689fd195377c86c55bb52ba2ee27c7c5395d8163355a3c04135b43333a); + tempvar res = res * point + (0x73ce15dc2409ac614aba33d14c4ad294a3a8136eec69e8b34b0b14b92eb240f); + tempvar res = res * point + (0x73a3905fdf4a2f53d66ca4cb99ca729e776ce66d9a474fd71da35b3fa949d34); + tempvar res = res * point + (0x1d60249bd6492637249efa94de232264fa23d62153d7a36e99aaede0be5d842); + tempvar res = res * point + (0x728595451b9c3918b04e7ce1637804c1df21495ad8f188eb46a5f1796e2e3c1); + tempvar res = res * point + (0x5dc73d8837d2fd0c754ecd371e94f0af344396efdb4337a8c7c2a0755838f46); + tempvar res = res * point + (0x7dd917167308b602914680880c9c8c8519f34be930ccafbaca3d126a30c4a45); + tempvar res = res * point + (0x1950cc259cc77027d5c86ea77f51a34cd30ad768676d77a0503f36f797eb4af); + tempvar res = res * point + (0x4d5df514fa9a8bd7515039e59bea7a1a1381a76f475a7dea23549106a7df8e2); + tempvar res = res * point + (0x1d74577e412af12fd886706cdce3c238f2761d096043a084c20d2bd087ad4e6); + tempvar res = res * point + (0x7871f7217ff1c7b739678e28908c4222f492ebf866cbcc410148ad1d143de0f); + tempvar res = res * point + (0x59a88072f92b384925c9091497269ba9f8226c24f740e928e410ae0bfb9350e); + tempvar res = res * point + (0x19c90daa3645b62f461545c7c38ce5bf8b5cdad399f417e0abbaf2b2df0ca64); + tempvar res = res * point + (0x53b86dc3cb8ef3d5920ea35c40e2d05496e45245eca4e0d058e2a0e2d583dfb); + tempvar res = res * point + (0xe00c78bcfc271dcc6556cb1cf6501e16d20b188c7412681c0b2ae0f2cbae05); + tempvar res = res * point + (0x36ac6cfd4f2ef6be5b1e83cf9e36e894b2575a8f4690c14484a17c222ec3c00); + tempvar res = res * point + (0x32cad92232ea7886b829887e6ca4ae084800803277076107b1078feb66e95bf); + tempvar res = res * point + (0x38269de0c80a2d8f4bef1d5e76805d1e412fef7b18886279e98c57a0fe64627); + tempvar res = res * point + (0x217df85b26b6b3bfc67bec919866b6e146621c30685a31e8c93eaa27d5dbaf5); + tempvar res = res * point + (0x4ee32b2ff29b0918618f173c4e5dc3b606a1ca2e0eb989257e0bf78dd2e9589); + tempvar res = res * point + (0x2d51937feb119772693523625e23756d172e996d1cfb82a258580bd51c15e33); + tempvar res = res * point + (0x7c2468c14a7ea994c89e2e4ddd6d2d624b67a96e7ccec4f27a5e0122531291c); + tempvar res = res * point + (0x602aca232b11ad63241b5f401c368acb1e9cfd4e5fc8ae699491d9c51b4db18); + tempvar res = res * point + (0x39c92f0c55d99aa6b082d21129a9402e6b0fe38a639a8140d76ebee9dc45877); + tempvar res = res * point + (0x4fff8b45f7ede0580424c4e2c75213c4c42ec6c68266c8d5d750a2863bd474a); + tempvar res = res * point + (0x3ba2c93d59d6a361b9ac28d93e54d775b040bd7fca9ac72339ea4388c533dda); + tempvar res = res * point + (0x6d567c1dbb663fb2fd92140cf66ea33a19cda580d18c10fe56a62e5bd3f47b1); + tempvar res = res * point + (0x2781266a2070c9d3f045010a32c98ce3e0765446e3ee20eacd73a0dc0c7c2c2); + tempvar res = res * point + (0x7dcfd5001e21e030b006d54c7fe0f7ca97a2c18d4e00ba92c005705a4f0563d); + tempvar res = res * point + (0x2fe4c112d7bfd4ad5f81ecdc4b30cf73aa51df4e4ba6d255a0e3eee283aff46); + tempvar res = res * point + (0x2433d40f2b8f9461b5368cb396f7604999a735414d3537ed6f1451f1fe93cb3); + tempvar res = res * point + (0x72f959288185bd36ca4e23472ed7a2577f8e5f0ef0c0d5df6f63e60f40ba307); + tempvar res = res * point + (0x4c5592288cc342232d76c80e858c08ecbfde64b747637ccc9a2734e90f85264); + tempvar res = res * point + (0x48ed57151b6dc68b039dc327f79bc2c26db62ff957809c5538360facc04d9c3); + tempvar res = res * point + (0x5ebd9b268cc66bb85a5e67a6b9d5fdbeba8b3672491068ef43b688a3a043a33); + tempvar res = res * point + (0xdf6c1013f3076e6044f0a7032e0bf80833f3c7d9eb0c3eb1f3c2a37314d19a); + tempvar res = res * point + (0x5f0cb66613216a1339c1cd15239b7f03c1d4b9098a931f65ae50b877f861880); + tempvar res = res * point + (0x5d5fbd560f7bf1e97190f888fa43b32db1e8070f046d6016b536b94d1473a57); + tempvar res = res * point + (0x33381003a653f0327cbdd8a11252ffe714e1061ee214329cb99e667c835af97); + tempvar res = res * point + (0x7b86849a979796096f7d7b46eebaf00913a082c638c5b2bfdedbcd78c480272); + tempvar res = res * point + (0x5f27bcacc10845ad41cb26244112faa8b91d46d97024445f50ced796ac5a93e); + tempvar res = res * point + (0x31cdca47c96b32e99077a96aa5cd73ec9c4da04212667805c82dff3e498f4ed); + tempvar res = res * point + (0x66a032c182ae70dd4487897d0c79dd860a25d21c61e3aeef8b9fa45349dee89); + tempvar res = res * point + (0x148523eabde5554538a1114351f3d8730d4a4d003311c7b57ce9e709afeeca5); + tempvar res = res * point + (0x62ea67803c421a4bbdc672d556bca219fd24e7145cb3e9113a625eeb4459254); + tempvar res = res * point + (0x2c2c70075ac99cfe68a7354ed29842c5207bbdbd09dbbd225ea93d0c07fd9f6); + tempvar res = res * point + (0x48b0cc6241c99407bb346db57db9cf82b2e66d1fcc1d756889a4f4b4bb8b396); + tempvar res = res * point + (0x506f990d7037060dea08ed53c5b17483ca8a7c58f94ba5e64fae258be4c78ed); + tempvar res = res * point + (0x777be5852ea7798899d4750e9decd1430bdad6a8b0d1827a7a89ce6f1afd89a); + tempvar res = res * point + (0x689fb22cd95d6f1868a4e3cd6ef1bba9f974931f76153e73038ff5ae7d09018); + tempvar res = res * point + (0x560fef0ed77bc94e16b9d9a21bec0ceadf81b26fe683b9c74b31e2d72a4c92e); + tempvar res = res * point + (0x28c74f03f409c942d16a773fde01b3f0bec544b42c1d46944db6253561e1ac2); + tempvar res = res * point + (0x4d62e1ef04cb039a58dd8cb8c37dceb78b10fd84bbec6302c964b899a957d02); + tempvar res = res * point + (0x44094c265809e3d5765071826547999dce8ba7058a7c1b1301294d8291949c); + tempvar res = res * point + (0x4e0f90743d3df3d3c4aeb80e7f6db457620430ff28475c6194c757f81927dc5); + tempvar res = res * point + (0x2cde734d2a82619ba69ca4f5ca5035f699a1e34b47560d761780546c9b04d44); + tempvar res = res * point + (0xf09069dc6a2745587b447ae03ebd6524aa9757f1090a92dc5e7ce8db848195); + tempvar res = res * point + (0x5522f48902001bf41de34be900783ac957fd867cca0f35666ca491ea89d8fb3); + tempvar res = res * point + (0x5b4be8af83915fd955ba32de729f6f2aef6c76501d82ee325d72d620bce8b7b); + tempvar res = res * point + (0x78e74ffaf944c363f3fc42cedaea8a9a450ebaac98bf1327590a11e064bd76a); + tempvar res = res * point + (0x6ade7c482d201c23145e3890086b22ab0d43495f5c83b1672316c10ca52af0b); + tempvar res = res * point + (0x79c066efe4c22c6e9e097e84401e183d3c45c645d986ed640a8faf8fd4dd096); + tempvar res = res * point + (0x21d59ca7451d83d78ab4d9d17a662367ac84b555866ae92d036d71de22872bf); + tempvar res = res * point + (0x6d100d3db14939bb442e5f5ce6a05939f201837007331536440a57c2bf2b609); + tempvar res = res * point + (0x7e5bc177982061f124cbe521c713c24438aa021fe6928d82452e44f6cdcd631); + tempvar res = res * point + (0x179e4b1e4817460085d47376a1971fdcb0287408cc7d11fb62cc3785772249c); + tempvar res = res * point + (0x2a7cd1fb12f896bff4d3db49ee74a51e970e3e386c2c8e7622412a6156a300d); + tempvar res = res * point + (0x3c5581c15733dcc4d548aa0a6e648e075e9be412680a76a556f91ae5f01e44e); + tempvar res = res * point + (0x4a4eb8f57c99e931a666de76c20173adcde82ff59fd8ecaf8b8c05e29b63fc9); + tempvar res = res * point + (0x58fa31f9a4a7e8b238898eb1296ec55e3e2000a48a2edc8e65d260d31bfd7bf); + tempvar res = res * point + (0x2c37f85ac7b1aab52ce3d28bfc65c65b7d4ffd000757c07fc493d183b7bb582); + tempvar res = res * point + (0x461b788a24347588e4f8d4f2d66640f31d6b580223a21919ccef9480987db1f); + tempvar res = res * point + (0x47c3222376f8f18dc6e82eebaab03fcf4c425acd901a7bf9841a3aba54b82a6); + tempvar res = res * point + (0xbece573771924d045b75bb992a87b26ab067a0f2dba4d1a9efbe5029963533); + tempvar res = res * point + (0x67c2a0e19b59921666716fe2b3f9c7f59c4da17d993956eb87eece7ef542269); + tempvar res = res * point + (0x8940bc9dc45fd06ce4046337963c849324bbe5f82632b94972c0ccb205480d); + tempvar res = res * point + (0x38bff358ccfd92418537a9b9858df499d2c44404c1886b109edb14c897e74fa); + tempvar res = res * point + (0x533a5a2ebd098297604e96118f2007ddd12af50edd525e9e5a0b154e620b2e5); + tempvar res = res * point + (0x312411292b7fe7eee015fcfaab65b611bc2b9f9498489fc3c1452862902bbf); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_pedersen_y(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x62b07622f501888a668440d9b856be4b0c3bf12a401fc2bebaeab4a7e1684ad); + tempvar res = res * point + (0x75a127d817aee244517479bab5c4bfc2a0035d43d673badaf64d8adf94353bd); + tempvar res = res * point + (0x14f3359ce0d2891d1bc2b6f4d2d6dd71fe22925b8a09f66147db095a9d4983); + tempvar res = res * point + (0x2d6129632b4fc43e4142abf55fe2d1f3e79dfa01c73d8fb56a465dbd07a9682); + tempvar res = res * point + (0x5115ade709c058be5dc6f406794062642086e431bab03c9a86d53c79aa83db4); + tempvar res = res * point + (0x29f6aa5fc92eab8b8b9871c8449c1f617b808ea9860717f3e5e1678672ec565); + tempvar res = res * point + (0x7e08f9d222cc0764fb5ca69e51ad4cdb7f1b612058568a142bc7a4cdd0e39c4); + tempvar res = res * point + (0x54c5dff0aed23c07edcd958ee3690e617011b87a5fec541725237d4ebf34382); + tempvar res = res * point + (0x2b7d501bedc4e7c604b0e55dd2d8166fa39a541efc24d81d8464fabfef3fa37); + tempvar res = res * point + (0x68e1d50b4d0570e357eac7bc742ec26dac1edc5b179989c7ae8d31791639103); + tempvar res = res * point + (0x707c572424682b685a1ba90dfd7e56f86254862d86e20b5a2d3ca85fe0017ad); + tempvar res = res * point + (0x2cd9a093ece61e554b2bdde3ec474900e4412775ad25456e5be6e11df7b9fff); + tempvar res = res * point + (0x7492aa940f34a027f8fb3700f29cf628c1d05d1675cb7865509f20617a90b2f); + tempvar res = res * point + (0x55e928ba557ed7fe0ecde6d1fbb83d112e6b06a087b4013b9c425fa36eb0415); + tempvar res = res * point + (0x3cdb28a913a41d597915de055aecc59f2b13079d3d8b33ab0a075eeddb1bf8e); + tempvar res = res * point + (0xfd48fb35400aaaf57d130b6143b241db8af174cada72ede8f2fac4ec6688d2); + tempvar res = res * point + (0x133b6505a6afd2e5fada0e53ea51c012e4935ea6d2d02caaa15ffc50a45079b); + tempvar res = res * point + (0x2d2d27711772cafff2cad828dd78d8b213e317e8939cf79164ae64dea577d61); + tempvar res = res * point + (0x60ac57e328ff6938a17d43e6137a55399b95459be60fe980ed8960edaeee10d); + tempvar res = res * point + (0x7b056cb6f172b25e3555d6b1422ff769fd4c07258fa16b03609f0e374012ed4); + tempvar res = res * point + (0xd21afb1901f1b3ad66587a7fb97ee06662edc3bc8c8d32b48625a135ba23a9); + tempvar res = res * point + (0x7784c2e140072fd26e95911df38f9a337107750a72b9ce05a21a0f781b92dba); + tempvar res = res * point + (0x7c1667b8d44d288c4f5150d01c5206d4d5868497630745b6916466c8a5b1228); + tempvar res = res * point + (0x491c2243a95c44528b86167a4418ff9d93a04bde8dd7a5d2b19ea579d295312); + tempvar res = res * point + (0x6aebd7a9279eba43cb1c0b14bb723dde464a86cac92518ca16ae27a8684d9cf); + tempvar res = res * point + (0x709be747b0a69a9523680ff69e6bfea4637bd570ce5c45256b39ff695557da6); + tempvar res = res * point + (0x47275cd67ff3b7637ed55ced299a6142a821ab466a897f1eecfc8bca557269); + tempvar res = res * point + (0x58ccfd44df4e339c65e1423eaad47210f2e16aa6530d3d51f38b70e5eb3a623); + tempvar res = res * point + (0x28218a1bc7586b71ec1989082b8f7ab0efba14569c6f6e5d7aeee1964ab6d70); + tempvar res = res * point + (0x660bd8049bd301d093aab9ae530bedc37467d4ff0a12c89d689d61ef9b9546a); + tempvar res = res * point + (0x4dd38543d129d0a71b1836c6e2eae47fde5d572e32ee9a5791f7ee823eab4db); + tempvar res = res * point + (0x8509234000e130c8828328ae4997d5116117716cca9490e6e63f30b7df699); + tempvar res = res * point + (0x62ad4d764ed0072a7649425270e2b210421c77d3ce98e2587ea5440a591ecc0); + tempvar res = res * point + (0x66c5222dc133e37dfa0566c49d107852d978eb7454489d3b2ada8de022125d8); + tempvar res = res * point + (0xe4d1f1f1f9b379bea473f76bc8f3c4d530335e2d6bd782b42324872767b628); + tempvar res = res * point + (0x6ac2f92bc4c04fd50ebd3e336b53b866e790ace39838aa96a4b791011455b29); + tempvar res = res * point + (0x59d753a23735a336c50466f5ccaab3671230fbdaf55101530e5f562a5efcaf5); + tempvar res = res * point + (0x166b26359c51d067955874f5612eb70806d7b8d5de4d8e0a75e0d57b39b1846); + tempvar res = res * point + (0x2dd27ce7910e44ee00ec3335bd79429846a70d92d482adf81b36a9ff1aaa30a); + tempvar res = res * point + (0x45970c86c25bc9a68f2e2a34969faa2134c95b19230fcfe7436c98f537539eb); + tempvar res = res * point + (0x539cd2c1a28df263709cf0eadef73a600f563ab3d82c27692b1424814cc3e15); + tempvar res = res * point + (0x31eb3b57e6844e3efc1e3975ea393476d8aace5f43ca62b09314c90b8ae9688); + tempvar res = res * point + (0x47359c8dd2b86e4f634a9a50950abde25942877bc5db93d62bf43d2886692e4); + tempvar res = res * point + (0x2d8ae7b28c8c3acc8bef3d4c2a9f5ef1323748de693a9a1ad3ff8601116b165); + tempvar res = res * point + (0x4538fc863186b4babe3b424b4111251bb1e20ba5516be54160cd560ec0d5a3); + tempvar res = res * point + (0x559548517b1025ad61020be3e252b6ddbf1d5d53043231f8850c0da52b8268a); + tempvar res = res * point + (0x3132d42e4a928c08a972e17b2c3b500dbcadbe6190b2e7f5b58300a0c8a38c6); + tempvar res = res * point + (0x5b02adb78afd4e219642a1fc38b2ef9f63926841ccfda072ac17326d3d50f3c); + tempvar res = res * point + (0x75971517855ffbc9657dab30657ed1e3797307bbec1ffe136cb0d8a64ed6eea); + tempvar res = res * point + (0x174a4710688db61da7559255caebf641a268b4df53d45de5e8156d36b4b2ab0); + tempvar res = res * point + (0x295fb60eec46a40a33b1a9532427b42e224c0ac6c50e3c1c5d17c2c16651a25); + tempvar res = res * point + (0x2037a7d08a1c4fa4d5d4f53436a252302840007c09163026637e9cdddc958f0); + tempvar res = res * point + (0x7e9e1c3d4bd3231686c235a495f737a9ec3d633331a95d85e17e90f99a08af5); + tempvar res = res * point + (0x218da336adf8608530fdf8320c4edc00631d36c8726430732038a369548cf56); + tempvar res = res * point + (0x78c7b0512cae47833eb6bf01c1075aafca19eef9b32e37f4f9a9eff315637c7); + tempvar res = res * point + (0x628226c46fe0bfa8aa36074ed0785cb16461ee2945ecee9deaa6399bba2742c); + tempvar res = res * point + (0x2eb6bd70a00ec26418d347df1a444f7ba0972416103f00c771e0f3d50bd8e5); + tempvar res = res * point + (0xdf82eebd6cde9b50958606c6ff83c855c43ce9613fec366c7792cb456ea913); + tempvar res = res * point + (0x4221572cf29651f508bab9eb82545b17cf6f9efd0416b65262e5491ad408e39); + tempvar res = res * point + (0x1d5fc46deed0eb9b56cba1d2bf8075227504aaf6ab1330b346cc3cb84a07cc8); + tempvar res = res * point + (0x55ee57d4096ccf0260baa2a1a2639978d965a786e4fc917cb2426f8a99591d2); + tempvar res = res * point + (0x21706619a453a544bee0ccaceda9fe69f860c894b36bc9cb7ea4455dd88a9ca); + tempvar res = res * point + (0x76ea16625d0cf0c04f096ac7d6eacafd00809ef1d1a3cf5e37dc2a13a02d303); + tempvar res = res * point + (0x6d0d885e8d2530c7a324f7b2ef47db35aa8162289a4420a54f13a82b871d850); + tempvar res = res * point + (0x471bb97187c83c0e7b51ab70022147e8d8ebe25d4081907e7d1bee8d6c6581f); + tempvar res = res * point + (0x12b9157240a237f319beefb6019bf0de1897b9e2d8e5536e3a21d8f9fd689e7); + tempvar res = res * point + (0x2ef7f1dfebad70ef549da1a143c838cea27749807efcb1a0a29cfab16420928); + tempvar res = res * point + (0x519de0df91b17442a8f60b512297d69a1b516f70f67d76eb9c287f06e37c55c); + tempvar res = res * point + (0x2a45de0b79a4e9c53d47f6126d35b1d050775d5fb17f3c3dc22c7b6476608c0); + tempvar res = res * point + (0x27e3cfc87448bc0392a0d6c1b1aa06626636fc703bbcf3717fbe6f0759c4855); + tempvar res = res * point + (0x77a45066995089dbd4072d6817397ce0c7e92b53d19338e9bd7549e954bd961); + tempvar res = res * point + (0x3139ae970d95891aa70cbbf6f172223e07eb521a5149b7e0c9202793f6dbdb); + tempvar res = res * point + (0x25dd21ff92e6f1075df6b5ddb2b774ff963b1b84a985261b1e94ca9eedaa49d); + tempvar res = res * point + (0x13eb9f5362c087af5ee758bf0b589c0e34af337b3c06c788573534e96de30b7); + tempvar res = res * point + (0x6a39a27be962632e0bfb245f65a4d70912d1572e39003d63def5f45bbcc8f7); + tempvar res = res * point + (0x2c11fa8c0ba68518942f1c686dafd32aa26545886d28cdedae00071360df674); + tempvar res = res * point + (0x7ce49a9b8d374e1174ae6ccea7cae8d743404552253f7ec854317722a5efffe); + tempvar res = res * point + (0x6bf518769635f9fa39c1258844d4f62e5fc00b70792944da0a939990492313b); + tempvar res = res * point + (0x6123efb57144c151864b4f717a44cecc667fb2ebc47bf24bda4f7d0ef8f550f); + tempvar res = res * point + (0x2c29d0056cfe7325567a9f2d09d917b37a45aa3cefe20b78c4bda2942af59bd); + tempvar res = res * point + (0x76914b565dab13e76053b7a74c24c005b0930011e48ab26db44b6b49a1e7ae5); + tempvar res = res * point + (0x648c35904fdb8bbf9c0bc9288319c248e17974fbb6616a70acdac004878bb9); + tempvar res = res * point + (0x1cc7ec07c4e1e6626b5263044071687d0ad34ad4d08996a213380e9b728585b); + tempvar res = res * point + (0x154a5ad294d41caedd8d927eac226dea1e2b78f6ed0a6901a00e45ae0ad78f6); + tempvar res = res * point + (0xbd5fd7dcc1ce2bcd7f7415a22115f0c846d16ac7458e6c531e7e44dc664962); + tempvar res = res * point + (0x2b2b08bfc4c3d5941538b2eda43b3cd009656cf83b6b23be56b3041df3dbb0b); + tempvar res = res * point + (0x5e48cfc304417473eb4e587942a76921fb007d8b11ce648d36828e8cbb5d595); + tempvar res = res * point + (0x79c11c262fc2efc9aceafe4a5886713151352e60c4db45826e0e343cc5919a9); + tempvar res = res * point + (0xe2acacfba8f832e4e3cffb6ecf4675df678403610fe91363172229444ac0c0); + tempvar res = res * point + (0x6dbd918c7623bb07b05ca515146ddd7193373250e0836062fd1c430e2b7894a); + tempvar res = res * point + (0x61b210c04a0899fe2a3dc53348507d6f53d4cd3831644e4630eb40564ee5b47); + tempvar res = res * point + (0x1e3816f2a6a4900b65d140d144225a8a81cb3ea22f56de3cbcfe3944fc0e898); + tempvar res = res * point + (0x3c99839cb11fecd878ab9efd1d2ed2a718f6e0df4caac1a070de06ddf1a6091); + tempvar res = res * point + (0x567205f3e5ec69ce7962918c41ed0309c3ddfd85fc92702ce1c207b282f17c2); + tempvar res = res * point + (0x10382fdec78a18047041629179e18ec7dd067bed125bf5fe83f13d637a8ff67); + tempvar res = res * point + (0x43aeb91e6f453d372353d9814a85c21617e6c934c694a0b06100e1e9aec4087); + tempvar res = res * point + (0x2b6a2e9d453e19e3d766f24cb7c6753f84adca0f75f7a871092688bb5ba0d37); + tempvar res = res * point + (0x1f3e3e61713ab64544b28dfcaf4da25b64e625048ca55cc783dff614f5796d0); + tempvar res = res * point + (0x364cf25e248a3f2fc2106025945389328c0ef37848a59ff2afdc685c0854822); + tempvar res = res * point + (0xf9762bf5620ec90d711f12cbe600f29906fcdcdea4f17cf51ffad2e07887e2); + tempvar res = res * point + (0x78e4cf312ec50466bfea965b655e9514d9d69bf0bae566fc88187fe730f70); + tempvar res = res * point + (0x8981cc99962f20f8814162568d9d7edb7fcc637fc6907a98b1d1eece9811c6); + tempvar res = res * point + (0x4e28bfd662fc5e09399fc49a49a622a7e845631244b9472df8c91c4a703321a); + tempvar res = res * point + (0x3085800be446839854dfb7bd9ea67ff139267fb5268faaf153db26b00368630); + tempvar res = res * point + (0x787a6c80d5a23f91cb91d2508633cce6125da76e797ed460256933a4e6a24b7); + tempvar res = res * point + (0x5ad768a2e70b4018e505bb5f6f44d249d9f5ba5f126106cde9be7726cf5c0a3); + tempvar res = res * point + (0x58afefb8e3180356e33794e20db869aba4bd4e5dfc795f8089d6f123025179b); + tempvar res = res * point + (0x4f62f4d968964e4908d16fb9412f8d10eb82e14e83f3e094a02470f27eae006); + tempvar res = res * point + (0x5ffa0d51bff335ad53cfe99165aa64f5ac1b01c360bd0101856537fb03da5ed); + tempvar res = res * point + (0x43fa3aa05db6331941265719fc1ee057d9f3dc81704f81c2ce7faece0fe86c6); + tempvar res = res * point + (0x1e836012f5509ea2f3dfdd474e9e4a96f6924e6619924ee4c6870a5294e26a9); + tempvar res = res * point + (0x41052d90f803f015bee5bd1a5f6e2f78f30439ecbe39861cdaebaa8f7c56371); + tempvar res = res * point + (0x16f6ec82023f48ea80196121afab584b9bce7f01e9515d0a3b489d68df3e2a9); + tempvar res = res * point + (0x4b7236fb7f8b72b2d369effbee5b4bebe7d2205ed72f9831b41c711680cbbf2); + tempvar res = res * point + (0x6620ec871e8a2c03933d0621b13e7f357b7349ea16bb549e7e15e2652692252); + tempvar res = res * point + (0x5b553a6606a3f01d862af22a3309a6df0aadec753fd1e0321b0eb08504c1f12); + tempvar res = res * point + (0x17a1bf17777a3b56a76df412810d05c9e222027aca604791694d3b020ea40cc); + tempvar res = res * point + (0x64fecb621f4dc18fa1b66152f28bdd15b7b12d495c496e77016bf3b979e4b1b); + tempvar res = res * point + (0x7e31ce22d2a3d776ad90e008ce82c594dab9ff2c42708f4f0676000cd86891a); + tempvar res = res * point + (0x43530eaa364a9df353dcfc154bae168e0fa9b51a3362c6cb351d47bb7f6b829); + tempvar res = res * point + (0x35fea15e2101714f172da73da6ddc2077ebd42ada067e7879bba8c2ee1d9db1); + tempvar res = res * point + (0x4509575b94136d744c8679c3028b0db514688db5338c4bcc9f50ccd7d15c95f); + tempvar res = res * point + (0xf8bd8807280892ca46c092b74f845d90f3a6b61b197a0594fa30686ca41a5f); + tempvar res = res * point + (0x51443fc9bbe11d787df4afc59f4366629cfb3a14c80cda1caa1ce6107fd063f); + tempvar res = res * point + (0x22cf3cd9fc0103158f7de369046ac0cff77c44c3f9c6ca942616fe7d59d6231); + tempvar res = res * point + (0x14714592154025f15704e279d2db4c70f545137269ccbd82c11fba275bacc85); + tempvar res = res * point + (0x1d44a3f67a1142e7922f4329f775fec5f8bd2d32ef8ab41a00821e76fbaa89f); + tempvar res = res * point + (0x2d9f309e84716b322c26aa86a3fe3cb6ff230e0968dfc58b869268c751e510d); + tempvar res = res * point + (0x64ff5a81d9e22197bb59e8cb340a0f44e22e226fed168f8b125d850bd727b7b); + tempvar res = res * point + (0x2cf1eefdbf254a549ddf4069288ea075d9aae074aac7853005b57c37c2039e5); + tempvar res = res * point + (0x20d846afc1a11dae8646d542770f294b9c9f21f1196fba567f2f74d058ebc25); + tempvar res = res * point + (0x4ce9244cd3966ce1a6fd7f8b85fb1c8751e35aa53032f8063535665ac3a69f6); + tempvar res = res * point + (0x203ddf8cbfae2898d2d2f183cd0efd1c3f7db1b84b8e96e38f2b87b4bdad1bb); + tempvar res = res * point + (0x37b40695420e59161b338e413a72daa6909f0e4f6f85426f8eeb6bd0dc3a1b5); + tempvar res = res * point + (0x8554877281326c1c7e1f3a2f5e81341554ecea862c2677fa67ab2f88b3b03f); + tempvar res = res * point + (0x619cb05e71db22ca1ef274bd0a7cdaf4fb79b3015b96f44814b490f048d2af0); + tempvar res = res * point + (0x66af1f51f840c438b502c2a5ab689f9b38c2c96df36988710951bf185cb8501); + tempvar res = res * point + (0x5486125e0ed23fdc42a4f8c96cb08d934b6f3b429c4af5f8396618e978e9811); + tempvar res = res * point + (0x41d785e118be2d27a159ed5216de66a84873e1f62088726d9607c6443a14090); + tempvar res = res * point + (0xa6117e45c1c561307d63895569d34fd7e3f2b2ea088dec37dc3a5527deffd4); + tempvar res = res * point + (0x3bfe2f1e8df44829fa27a78c46c223c7e64bda85be60d8a3a5d0e7d36c20e29); + tempvar res = res * point + (0x3daea06a4a96480c4f7fff1082d95836964b63c14281ef942fa9a9890d8754c); + tempvar res = res * point + (0x3678ebeaffc3e64d76141f41be973ff36e8398a6aa0385eddaa0c4183e3646); + tempvar res = res * point + (0x5cc1da57cf1059231e195a26b1323599c95f98e4b302d6e6f4bd41180b56d35); + tempvar res = res * point + (0x4f4cd7f9fd5b694cc5ea6154d0738cdbac3978ce74a7314bcafea3dbc1da61d); + tempvar res = res * point + (0x77bdb42e999e93273fa3cbb7ae7160522231680eccc4d38c1b8a83d2a0420a7); + tempvar res = res * point + (0x4e1cdd107e3116b4ff22720938a201eed2ea0b499bfde301562f5e39a42b066); + tempvar res = res * point + (0x513bd3eda9403f4167249972ce4947f3ac9e9da03a7b9ef557a65645b9616be); + tempvar res = res * point + (0x23d7ed01587af3b9aefeae8a627c6401d36245cafa9367631036d2bd7c47e26); + tempvar res = res * point + (0x1ec8c3c39ec4705944ffa8b3b9b61f73c9ad759cb79a107dd93a125685f5119); + tempvar res = res * point + (0x4d0db05514a8c0f152a8664579c004fb738cd3790214984bc3f21f31d494361); + tempvar res = res * point + (0x2bc791bd7e68342116218ed9bb657b8b54e550022e39af11ce55b29ae49218b); + tempvar res = res * point + (0x7ea13011e0dce5c917be4cd36c8931f5969852109a16d7c5142e8fb3c8b7650); + tempvar res = res * point + (0x11a9029a5c07557ec347592ba7181acafbaf0f0c5c9e81d7e995a4de57fe566); + tempvar res = res * point + (0x359506efbff0e2b81d91cd6a5f808a6c65255e1bf06cc03dbaba94758b3acfd); + tempvar res = res * point + (0x491899cb7600abb42ac8cd91f2c775ec410469573f57c1030ed1582327eedb8); + tempvar res = res * point + (0x7a42c4e98f014e50dba6b25fc32401b7695fadb7bf271fe0a763712ee545c2); + tempvar res = res * point + (0x2f7d26f183c54146bd83514f5459bfd95ac635649d74225c2168a8e7baec082); + tempvar res = res * point + (0x3ab952be650de0c679ddc0a35bac2907a6e58303059d4edb914e74c67d05226); + tempvar res = res * point + (0x2b7f9df93ba787a9a5a7a0a3b5daba02e2ce65df16ada37575735697eda6c1d); + tempvar res = res * point + (0xb04ac19a9f1483b8ee3b763be73814c9621fb3d23e6d874d9093d999d3d4eb); + tempvar res = res * point + (0x4f4df07e55d3ebf0ed955bd9f7c34de001f09a92c1ead17b0c1a485d48a4329); + tempvar res = res * point + (0x1522043741ba933948d7298114b71322258a3d4e7cf2496590c35683dbe2a7c); + tempvar res = res * point + (0xb489643a1aa2c181b4739d45582e2576a6f9bd51c81d300ebdc3a58b79bb2); + tempvar res = res * point + (0x4db70c63a1dac4e5ddde15e3626d009683aa8ea14face2c3fdb6ec97c8a86a); + tempvar res = res * point + (0x309bca858a0f9fc5a468a57981c9c6b7c79636b1f31284938d1c6a21f006a33); + tempvar res = res * point + (0x625a1fce22a9fb7717107b137a0f5ea4ca059008f5cc6fdfb5cb5bb1734bd17); + tempvar res = res * point + (0x6ae2e00f7827692b0d20f483d3c71594f61d50846b52abfee39f6697513c0d0); + tempvar res = res * point + (0x4b5acbaa0f7e360885677439654649256829cdd6d4a6c7ffa904a0683fb5fe7); + tempvar res = res * point + (0x66a63b8ed2255586855fb30333ce0e2ff4eb2b4cd5d2125d8d20cd3fcfc1d04); + tempvar res = res * point + (0x55351e9d60f58241736330de978242e4e40c4209a7879d7ae3823c148abd82a); + tempvar res = res * point + (0x588747248358bf8bdbd990996cb43468c89909cad0f8230cc939538b9b331df); + tempvar res = res * point + (0x67801dffe217a1a64e0b12f405157af52025266fcc391fddaebf3b6c7ab79a9); + tempvar res = res * point + (0x411556b9c89186a2f9f79e55d045295790b28af97fab64e77777e3828532be5); + tempvar res = res * point + (0x5c01501e6a113ccca7cc9c723b1fad6ba60ec5b0a85b7d09c72120d3f733bd5); + tempvar res = res * point + (0x5b0d578cb7aa59ba02b0bb894848b745440c0cf562c2e635312c9bfc305e169); + tempvar res = res * point + (0x3013a9c6094ab0086b1397621f93ac07bf45574ea26b09d3e4587afffe995ca); + tempvar res = res * point + (0x7d9c679179dfab605ca04e1993b37ddff490c440665005698a47c442a1cc10c); + tempvar res = res * point + (0x4f6e24500755d20ec5f28480a41a0cf23baa1aa24202382e9f4ec8ec6d7596); + tempvar res = res * point + (0x4e0a6e0c26f85c74373782bd2924f3bc0f6b4a2914c4f7f8850a79eab580566); + tempvar res = res * point + (0x6caac68bec6ce4eff4f74c1f33dbc027165cc02cec8f69e9470ff99c0b132c3); + tempvar res = res * point + (0x1c867fa9ae031469be012c4f201ed3ad56573a22891351012ad1f7d300361f0); + tempvar res = res * point + (0x1761abb092f6c4e3eda770480fb4ab095e786bc3f1b1f960bc4c95232308b3a); + tempvar res = res * point + (0x4a35c4582c91999a39b553248bf2a39ae5825204085a9e98bd6ddab3bfcc0a4); + tempvar res = res * point + (0x6a4efc048a81614dede6c4f6181253e84f20d4a4f95f973147ee3fcd72077fa); + tempvar res = res * point + (0x65c14f7de75359a40c5f244f78b2920b61087fdbbf59aa507644d94f5bd210); + tempvar res = res * point + (0x9be8b219ca1684dfbef720a3e9f034b319e2d233aed85063924fc60aedf20e); + tempvar res = res * point + (0x7352e8793ed3f6283e492544b2944d6fea715980d8884f6821574d36868b0c7); + tempvar res = res * point + (0x65c04013accf25a2cd1d9eb98689d71694ffb20dced009df5b9af167602b4c2); + tempvar res = res * point + (0x679bf3101f8b2112eefab47d7372f0297507511c7cceb4478f2baf0541740f5); + tempvar res = res * point + (0x162e6e8431b7280f8401ca08922c5452c7237132efe3a481a71b5c97183e9d0); + tempvar res = res * point + (0xd9da926adbb5ffa493c54223f97fa1b0d141129d8736bc4f5768426c7e82a2); + tempvar res = res * point + (0x711628cee8d673863e18f058cf82551ca8351486b9b210873b4e18447e11408); + tempvar res = res * point + (0x6f6131c193cd7b3fdb4d0848df70474ba9e80529097311cd7c13e322205a1c0); + tempvar res = res * point + (0x2512f776d1b3d212be7c2adce1cfa083d1b2b9af1c6f3cc424b266bfa19aa06); + tempvar res = res * point + (0x400330fb079fb4cc8671ea9a996de8f5442f20b9b9a3bc9df8b81e01506c5ad); + tempvar res = res * point + (0x40cfb729788e16fa80b7d937f0088157d18ff2cf7c79b748d0e150c896d348f); + tempvar res = res * point + (0x59786091e2d824242c7aa5dde34ffbac99f6a9a1aa5ecc8a395aa13e8aa55af); + tempvar res = res * point + (0x4adf53e64235d5327822ee3e584674af053e496c5d92a6c8c43e1e8e7d327fb); + tempvar res = res * point + (0xfe9d827d7e6387c7228d92f78574add4ceddddac1fbe71dec1258220c08402); + tempvar res = res * point + (0x37f1342e071f8a087c1405692443305d28d4c11b84d92bd7dedc563fc3ad329); + tempvar res = res * point + (0x74a39339d1d708a9ea407f03d8b0e5ab103c3251596258b78be1bd97ad06915); + tempvar res = res * point + (0x152c16cce8c1c782287b8908a790014fe3c51c57cefaef63e2c8dae5a7a5daa); + tempvar res = res * point + (0x5b32dadeb15d554f39f227de4ad20600eea4b763fa4c90ffa1a41812ae43479); + tempvar res = res * point + (0x3b4b0f9b88e16446a2de79c1d8c34865d5d6e581f08bbbc652ce67d8ac1d952); + tempvar res = res * point + (0x44041800e20fa7a15dd9274ea8283b09c30a0d900d9c165217004e669b39d99); + tempvar res = res * point + (0x5609324fa7ef5213591c8d36c59dd42df8f5f26f84468bb84f843707a5c9c48); + tempvar res = res * point + (0x6235547369b594514d2fa1ca9b06fd25f9d2764fe8b099c7d9671f542a01d46); + tempvar res = res * point + (0x614509129cebd380f416c4c9c7127ee7b53d878860905f047ad722a82147236); + tempvar res = res * point + (0x4f847058896f8e2727ef3b4577e62d5f6a729696b8705fe217b97c73fd1afee); + tempvar res = res * point + (0xfee20b19c4437f06eeffccb05b88c4e236d18f8e3518ba124ab4eec844c496); + tempvar res = res * point + (0x5897638208b8e9509d1128c29af87cf30c57942d47016819435b373c0a309d7); + tempvar res = res * point + (0x1fb19890707fa2e617de7dcea9ad35ce9960009f1e38aa2629c66fa5b8d5d19); + tempvar res = res * point + (0x45fb29b3ac673e9f525332c8bad73d76521985406fc09398078b30339c857b5); + tempvar res = res * point + (0x528d041bf152aa3a0205430412a196619b68c81d7a706fea0fc090e0cc6a105); + tempvar res = res * point + (0x1e149d42cd477212ab7f01fe40f76858f09ce2bdfc397df635ed8a453714e7e); + tempvar res = res * point + (0x75f781602ada44803c0ca4bc8c1bd5064700762d18c309a2b9059dcd8c3dcca); + tempvar res = res * point + (0x1571843ced13a8d342b63c63abc4b83d357eb286af04380edd1eaefcef3f1f8); + tempvar res = res * point + (0x304103a8d35f43cf87d50682e86e473fffd71d13e0c783e596a59a62b06402d); + tempvar res = res * point + (0x2849ac77a2f5398eef51aeb8312dcef8b347b690728d4eb835bf4670301e6e7); + tempvar res = res * point + (0x52a36a173c7ebc96cfc55bda4bbc73bc349657d39ebe096725e9cc4bff01def); + tempvar res = res * point + (0x43e371660fff35e52cd5dc08c9c347d8f7c64a116375d0e6e3ad3512d85a99a); + tempvar res = res * point + (0x76594f29261e2aa9cf4a90b58b0f79c2aaa99d63c4ff64b4806cb8cfb0df316); + tempvar res = res * point + (0x4cbae4979c7a1313c2d0f68b21f5734ec83f9e1a88c78b3976a6ef84a1b6dbd); + tempvar res = res * point + (0x76702a08064b5768ae2979aca07322782191172276f1bcfbc14cbaa3e758dc); + tempvar res = res * point + (0x64f8c462b308a1337bca235add2482fdc3607507b2c9c0f91b9187f5676303); + tempvar res = res * point + (0x2ef5951aae064a7357b1e4ed49f05f17f778f2e8735f8d17b5cfb82faf3b848); + tempvar res = res * point + (0x66e2651e6f5758c334d1c1451d563b2df07b424b5d0125c739ada959479890e); + tempvar res = res * point + (0xb3dd17f46d6b12bf4e5db184d6962c156bef94f9f73861e34d88503fbc517a); + tempvar res = res * point + (0x19412ccd078bf5665579cbd16035a251e08f40722eca4452eedb31732488468); + tempvar res = res * point + (0x719df2a50d9c3f2eb3f0336665f2980e432191e21fc49f488854b8352fd94fe); + tempvar res = res * point + (0x459f095ba3b70f76e493c6afe2d4b6eebd21343f74bfe3390868612fc250fdc); + tempvar res = res * point + (0xdef6a0b2b71d97a59c674c052fe23f7d000a334e180b0793b6974fe29a64c3); + tempvar res = res * point + (0x74e503d57e49daf6939077c0b4a4d68e66bc2425ce53b01b48f146295476401); + tempvar res = res * point + (0xd49f196e60ebea0eb13d85f05cffedff32477e83129bad30bd9dd555755429); + tempvar res = res * point + (0x298215f335fb63a11d31958d950d95c909bb94e144c113cc4ecc08488469097); + tempvar res = res * point + (0x6232d26f420f9b4f119e64762927b5e8a21192575b200081b0545ad4e9a2c25); + tempvar res = res * point + (0x2b51d7f94ec71f3a8e3e20d766a4a7f13d08d758a686ff86dbda48026c7ec3d); + tempvar res = res * point + (0x45fb08bc21969d5ca9b1ec473cc92a4ad911de8b0607ddc12b9ee98c286d37f); + tempvar res = res * point + (0x70c0f7da90cd889d8df06f9774de8a9a20c88e86753506c7afd0e1f6ef15e76); + tempvar res = res * point + (0x1b16d94e84ffd3ad61286f5a79d5a6f7b5b5dd6442aea9013ad21467bf1281d); + tempvar res = res * point + (0x6a81925732161d4e5dc61ed6a10726027fa66d892aabbf46a477f4455072c02); + tempvar res = res * point + (0x13ed29a84c4875ac188521bc40e9258e03d83c9ceb8716c6fbeed065a5df73b); + tempvar res = res * point + (0x184ee38f80fa532983fa248c14c0220c2a5691836e899a5c9b83c975b03608f); + tempvar res = res * point + (0x65f4a97d2b1c90582859966540e839ac2d62ad2ea960aa2af36776b2d07ce34); + tempvar res = res * point + (0xe00ac968fe5a147fef45fbd626c540a194ec3dfb2c1cca7938e037349d4f34); + tempvar res = res * point + (0x96935be4e41797417259166181bb646a619ef95cc8978ffeca81d141d062f7); + tempvar res = res * point + (0x61c61341c83517cb7d112a76864271492473e04130ce4ce23331f7300bd8c89); + tempvar res = res * point + (0x73eba0e9e52c3a93ab6dce26d5858b2d699d8401b2c43253616b5701aa803c5); + tempvar res = res * point + (0x77434256511acfd027b41e03a571a9f56b0442dc675c139a2e1476fe716102c); + tempvar res = res * point + (0x325f10662fc8bd38e591b0e8caa47b3fff46703656b2c5863d39c150d298fc8); + tempvar res = res * point + (0x3c835256339330b1c94cad78cfefda36a949b9c8553d918f3d8547cd1805ac5); + tempvar res = res * point + (0x7340540d0c9f9dd2c1142f03f408ab977afc7371934c62259fdd29f0652f8d0); + tempvar res = res * point + (0x17d8ab17e403b1925b40206c11f8a6a29ed08217e1ef303906ecb354fdda1f3); + tempvar res = res * point + (0x78562cbfb984ebea085472a1b004dbf86e7d99f4809a5020969246a84a9d165); + tempvar res = res * point + (0x60c93d3dac2628ad796e1dc80bc0796d054c991ea23094d699bffb43a630add); + tempvar res = res * point + (0x72bafd4641e6928ca65cb48e8001ee077944201f70d5bed524c69b709410d3e); + tempvar res = res * point + (0x6321e76192ba31cc63bf7c526c8ebbf4df5b705f01e4151068ee3dd658aa674); + tempvar res = res * point + (0x7caaf4f7b073af26c036d8bab5c74fc3f752f9ecc01041787e9ddf773596189); + tempvar res = res * point + (0x66ada08fe725f364ca32c1055e1ab1216967856d6cd8762dd4ea915c2ed40e9); + tempvar res = res * point + (0x5b6477413bac2f0d370c0cdcdec4cea10fd322fbcd7b202d4ccbeb0581fd34f); + tempvar res = res * point + (0x35c99bed31baaf7833ca759a9bea792965a87b42171259ac51b00d872d581fb); + tempvar res = res * point + (0x7ce96f5a3261a977f04ff70ef416a3d5c165100d19f551a6ac514e4d00fb18e); + tempvar res = res * point + (0x1c933d3449f6241d0f9d547db9e708fc2ee3e0598be5f87b675fb6736a15c39); + tempvar res = res * point + (0x687aac173963fe1e01f9e0d50eba0e95e1e8783eb21c0f6c1f45cd42408198d); + tempvar res = res * point + (0x2f2f5447e274a20d9d60615f83a18b2a4db300d5e199d7c8c6c6cfb754e8cbf); + tempvar res = res * point + (0x91cd6c3b8ddd8954a44e8a9cf6f7f183af8e6226849f05e6e6ebda2409e042); + tempvar res = res * point + (0x282ad11848887c771898b5a32ac6ca14cc2510830454aa8e194975e308fe042); + tempvar res = res * point + (0x5455d2de2d7570fbeeb431a9a21187ecc049874b64a227bb543aab4af16e27b); + tempvar res = res * point + (0x2fcabf82bfd2529eac169a520cbdb2a0f8c205c5a9b1f1ac69bd3a44b25faa9); + tempvar res = res * point + (0x33d4fbf9dae7a87cc13db3c95ed3976b50113f072e56a13e675e4af241bb864); + tempvar res = res * point + (0x3cbf28927ecbda443555c9d51f40c294fb6688a17812cb0c85fb6501cdc0709); + tempvar res = res * point + (0x4fefb86cfccbbea031f15d85033f10f92f2b6b689153e305bfa8821935979c3); + tempvar res = res * point + (0x63f4ad31c4d59ee741b1b0ac99e022959df079b5b033ec7a1ecd3b4797f94d9); + tempvar res = res * point + (0x6c74e3b74559e12949b8c3b55369b2d275b2920b4442c536d63f91debd61499); + tempvar res = res * point + (0x45a5b88744e83d901f33da0d0de869381e7a125a6d8bd104cf72ded013ea4c6); + tempvar res = res * point + (0x11243de8b4214dc3220693acfaa6b626cfc3b8c812140779af9b72dfb1b92f1); + tempvar res = res * point + (0x123f50f65a68168d6b43c464270479801376ff6979b94f60252a47d9d7d34d2); + tempvar res = res * point + (0x25446fd382a1b0f5350b91290b2dc35a6dabaf215d53cbb32d1732fc6ebfffb); + tempvar res = res * point + (0x160d7d587f3a17673bf04189e0062c7bab764fb54ebd0f042fec72f953a91da); + tempvar res = res * point + (0x1e0fcefcc1d1c5a69e81c4fdfe7de04d95b53c162a3b64b5956df8e59e1b93b); + tempvar res = res * point + (0x1925470cee5111eb991ccc8b0412be603c0b8df342d7b186a3aaeddae103bf3); + tempvar res = res * point + (0x2848af5bb20ab624881dc9244ea18b1d6939e14270714253a896e57cb0f63ea); + tempvar res = res * point + (0x6c2a98464d6eb4038d55b57632bb283ab091eac255fd6797df41612cfe3ea1b); + tempvar res = res * point + (0x31563499de399383464854a8679e0b073513c5bc46cdcc2a2107f00677e6356); + tempvar res = res * point + (0x6da4d6fb1e6b2f1b42910a9dcc4702912002d7d36ac7100e19c7f298c7948a8); + tempvar res = res * point + (0x3d368784067d457e43cb63b3f526e721fab153949b090a99a128c5744fab4a2); + tempvar res = res * point + (0x266b63657dbde655f034c014a8fb73b77138b52eb0e17eacbf402bb90305f10); + tempvar res = res * point + (0x179f2a40de3db251b95a60431e7cfe2dfa48dc8654bbf81add938e9f2f6725c); + tempvar res = res * point + (0x1118c09adef545b07e209d88b0a645673a103c9e71e8f671e74c84abf1a2a2d); + tempvar res = res * point + (0x6ebb7c4ee2d4212e6d7cea8c16f97c935f3bbbc2f400c9a738f1ebd37eec6ee); + tempvar res = res * point + (0x41d1ca4f756c80f197ba1635314a3dc756f9d8d9406af16538643d3e1021bd7); + tempvar res = res * point + (0x3129daa367a01a45fe3f0ccde215371f59c5643bfad33f4269a6478c8c8b7f8); + tempvar res = res * point + (0x1fefe6ebd886640df863e5f5c25e9b42fbc10adfa7ef07d1fda0eabafa60a6e); + tempvar res = res * point + (0x37e79bd72d714d3de7ed2b1ba79e345f75646bf67efd8ea3050ddb357802a3c); + tempvar res = res * point + (0x24eb6fb4dbac687e35d4168b970db6e7dc76c4c886dce0d4bad2e6544b8e6c6); + tempvar res = res * point + (0x6508b5fcc13191197f91407d5b1b21d321b7f311e55ede9ab8a6975308dcee); + tempvar res = res * point + (0x43e46c5f1cf3b5cac9722eeee991cbcf53af25a4a355a91ea9b8a4d4754d908); + tempvar res = res * point + (0x7393709fd08807a84ca44526a2b8ec97bce5aad1adf00560d04110de6d9eda8); + tempvar res = res * point + (0x690c8328ca161c48f3f8f37570e42095d1a0d9e101b3ec0ddc91426fc22facb); + tempvar res = res * point + (0x41354bad5cbef57b0e7eacebef8f0176f3b70992ea5a418f502242acbc4a1ff); + tempvar res = res * point + (0x3475f32b5bea9dbd19ec199ef34e531b696cac0461e644ffb41a5e99d0735fb); + tempvar res = res * point + (0x33cfe02e240929353f193c6d3387f1117d04f116889f38d9a196abdf986e48a); + tempvar res = res * point + (0x33e7ba5f7e56065e3f8b091578e8e7a7b118116de47237fa5a97e44e97b7f69); + tempvar res = res * point + (0x5526001b8a8c2c6209e40b5d380836bcf63db4ef85c25fd5b72d749b0bd36de); + tempvar res = res * point + (0x64028a3945aa2866db68b304dd0d83d75ed0ba5c2f9d0b47e80d11d8da6526d); + tempvar res = res * point + (0x378113f110b2404e7d185e920249519ded728cb1027fa8cc2843a588886a7ed); + tempvar res = res * point + (0x5f4fd7854cf7b89a3983da1a39839d85c7331c3353b0a8cd218f7f4e1f780c); + tempvar res = res * point + (0x6467afeee167ea95feb4a85c48fabb2c7067de57acd5098692855189e21c57e); + tempvar res = res * point + (0x1e4bf5029043367487394808d7ee7df5ad1ad1da2c4710a1b2444ffde106f2a); + tempvar res = res * point + (0x684a30c1084e8edf34a77bf8848fd2098459f5461bdf3352faf9c8801435b6); + tempvar res = res * point + (0xe3f2bdc2de2b623c56390eb0044adb980766ae1a58d775e003c39724d1d6f7); + tempvar res = res * point + (0x62dae59d425684ef78c1829e0454cd5e76f5d322ea8cb5ae5e911f545beeee1); + tempvar res = res * point + (0x5761ff2e0a250691a66dc36d372afbd6a8016726efe0c418d7899d60d26bde6); + tempvar res = res * point + (0x4dc27c76881bb820eb74814d1b69825e9048b1a3b064e603cca4bd4814b2243); + tempvar res = res * point + (0x5a15d718a45959d16dd6e0b98badbb086e2a9741ac04086f078bc6951506e05); + tempvar res = res * point + (0x23cf69cfd7730dd096fd485b2d8bdfcd89ca6004689bcbcacbeff288f18ff9b); + tempvar res = res * point + (0x4d6c233f7bf3ade219a8e3a89e12d05beb7faccbfa811ebd930c391523f7b4); + tempvar res = res * point + (0x5a347e7937c7a178952905f499babbeda500a820ccfdf7f3a99589687a623e7); + tempvar res = res * point + (0x43394095e27ddb7825c0671833a6ac9784f31626914c902c225f05ce42bbd9f); + tempvar res = res * point + (0x66d91bcc591c880303ee4695475e8a8e402926f0c01ade8880c7b03c76998ee); + tempvar res = res * point + (0x3348152349370ec1c4d753735ef255b50e54aa9a432f48a121c39b8887827e0); + tempvar res = res * point + (0xfa17235a82497674de45bfa59e61a329b2d0e63eb18ab9b74aa46783e04c81); + tempvar res = res * point + (0x45ffc1ad229bf52b2531afadd1c5ba120c57b34def87149880d1e5cb6c5391c); + tempvar res = res * point + (0x37f5f6b25ee428e91e886127b961856d9ebc52740ceb763baa7e71371b84364); + tempvar res = res * point + (0x58281d625ddb432caef06e485bc2b74cc077aea9ba5072198e76542f0c69dd0); + tempvar res = res * point + (0x3e35aebb590266ea1fdd8198cf3c23c77731dddd95d488a9d9f9837e3bd0f6f); + tempvar res = res * point + (0x2850977abc89355540e8abb804da7805ef88b12f40cbd9158ef330b767901eb); + tempvar res = res * point + (0x72fb3298da88c470a2f93a391063810be01078c8375183b57a024c223f2f428); + tempvar res = res * point + (0x53f792c81d26c122898d70ed7fcfd8f02a8f5a9ec8b9868fc4490d3a46b4e8e); + tempvar res = res * point + (0xa7da81afc9f3c93366b6e161b1fc7a497d6c770fb140bf4b64e5fc707cd3d3); + tempvar res = res * point + (0x26601a459facdd83458b56099975d2b7dbbc431d41b53f5dd6ca2901dfaacfe); + tempvar res = res * point + (0x4a048ce90e3a1eeedd4932ff37760fd8b1dc995aff7107bd66318652efd1032); + tempvar res = res * point + (0x287fed27ab81e5f721d2bd5aab0e69f53e94ce5dccc35c2dcc88e12465fadc2); + tempvar res = res * point + (0x414215fbcef7f5af60f320e67a845e4a17b0a0eca39b4e18ba89fbe8a189491); + tempvar res = res * point + (0x208f0c2f5a114b2342f51e919e4fe44c2a42cd06382d9edc4ef58939b249bab); + tempvar res = res * point + (0x5726e3dee7bbc5e5b4f3ad65f0fb17699efb5936d50ad380785f2b10fe8953b); + tempvar res = res * point + (0x6fa8562db8de26797e9c9905aa769e4881304b4f20cb64d718d271c182f44fc); + tempvar res = res * point + (0x2a60396cf912573be2837653283a23702037f614e33e1c6fe2834eee9a1c7a6); + tempvar res = res * point + (0x5b6b3213744858ad659c4c07c9220380d63c01f680986191c8776eb703661c3); + tempvar res = res * point + (0x709a47e72cda4fdf428bb9784f02f77c700086755d4bdb5b229d1b80a2ea4e5); + tempvar res = res * point + (0x75e9c821cdd2e754759306283aa4af8bdbb0ed31f4e978dc550141fd10da6be); + tempvar res = res * point + (0x2adfa41f72ba3b61b9dfa6f017b19682b0b0f8cd86be3d37374aba3ce990a55); + tempvar res = res * point + (0x6e313bf82c34d3af1e7fc14d811dde163ca6e57accbe476875e4a967da00b8); + tempvar res = res * point + (0x78516acc9d32f4e54f8925865c91f70b210f4ebc7533fc624685b3d5daa7b18); + tempvar res = res * point + (0x3b8cca1c3fb2b26b7e206802d52d2ed1c725b8f95407e3ef295a7dd9ee0d45e); + tempvar res = res * point + (0x287ef69d6f69ab853e4f0d24b22e4c15169d12c41706dbeede9fb49c61179c4); + tempvar res = res * point + (0x7c84837e6872bea4f0448183cecd6bb24a8574456ab91173b04b9423be8a64b); + tempvar res = res * point + (0x78f890541865c12169233143f47a056a91dbd18222c5d31bfb2db19162c204c); + tempvar res = res * point + (0x46cbc37eff4616daaa86160d5690f5473e24171441e29705ae564223a351c23); + tempvar res = res * point + (0x309f9698e38823c05e56d073d83ea551bfa80ace08e749aa4c83031a22360c2); + tempvar res = res * point + (0x1a2cd41155bbb7ceee94dbd01bd876140b1698f03b2ff8f8de3ba45b4ea14e); + tempvar res = res * point + (0x10699899068f86fa3843b06693288630b9ac4b87be7b3726fdba32b41caac2b); + tempvar res = res * point + (0x2762878a5f6665bee609c26e750cd886e239c31caf1508d5a2a185b58576b77); + tempvar res = res * point + (0x57f7a737e643bd859d8a53e1b621c09be89fcca7b96f8e42333e46426f26a20); + tempvar res = res * point + (0x7239c3b89513196e3cae91f8df8bd79f08033061ba63c089bd764644907479e); + tempvar res = res * point + (0x38cb4f77410e9a33306f8a4b92b6f76bf239ba44e0ef45dab0bfcb75dfe4141); + tempvar res = res * point + (0x382114ce9d712af864a253d29471a436b83ee4f7b8ae3fe19ec3ab315e18d8a); + tempvar res = res * point + (0x51ceb130c1908fdcfa6896756241fca8f74ab172d98c76facb7b8b931fa8812); + tempvar res = res * point + (0x4f6b918e40f8022d2bda8d53214e8fd84743bc2280231d3ae772844bbcd1aac); + tempvar res = res * point + (0x2d9af4ef0d50851ae1b0cdab3587a71728eaaa4e56e67803c5ff9126e722696); + tempvar res = res * point + (0x4640cb2cbc73d7c9fd2a1783122cb5ee8c68e7c04b0b647d43a35cd4961e4ca); + tempvar res = res * point + (0x1b3104591a23f262051182209c0f73caa30e8631fc4413a5bf97c9d51a70abb); + tempvar res = res * point + (0x2103ea7ff918748c4325a992c561b551b70fa9d97e48a52b3c157799d213693); + tempvar res = res * point + (0x69fb58adef701279dddeff71e1832aea01ae10a5128a9f744a5a945b5fff200); + tempvar res = res * point + (0x375e99f4993200342e6f6ad713711052d518e5dac24681b3999878bbad627d); + tempvar res = res * point + (0xe051fab79733dd773d13f5bec04b1c20252df512d937f6b7352e4c4fa49cb); + tempvar res = res * point + (0x5d72a87fe662c05530c3ec822f925a10c121a44c4adecf24850fa2442cb4abb); + tempvar res = res * point + (0x6f2a9f716b1fa27c35675a57273feb79ffce02286bcb1e253a8e126c2cea357); + tempvar res = res * point + (0x9b419422a2083bf174263351640e009b56d6e2278552f9e7ee6a6004d45524); + tempvar res = res * point + (0x3dee84f905f6a06940783bc3f322a0fc22a984dd244d00a85ea3a4295558377); + tempvar res = res * point + (0x3dbd68c7c5945f48515d975002a1caf1c491c6743f151df31f95c5870c90fb3); + tempvar res = res * point + (0x7d52bb08c1d72a66c3e5c60f6742675ac788ec8b4f2178ff9990a04d22c076e); + tempvar res = res * point + (0x107c8fc81a96a3c13d1ddf04b8bcce0450610c2ee6c127e0f47ce2ed2fa0613); + tempvar res = res * point + (0x6d8f39b47e79d44503aa87a3fdf101b055f89c663bd7ec377d175280f3f8db9); + tempvar res = res * point + (0x6d5a755e91ed732dcf8afd32eac3b4875843bb116430a966ef88f17aad54c16); + tempvar res = res * point + (0x64035ce25716c9c7675ecce40d3cfb65ce3121439e10367fe29f2742cc02d85); + tempvar res = res * point + (0x3e44a162d501fc521774c75994f4b55eb85878f5e867cacb75c7ff0b7efe941); + tempvar res = res * point + (0x1b2441db55dbd9b87c45b1afba238ed28d1f2dfe9725d9a4cae3a45e3d59b63); + tempvar res = res * point + (0x8b54ed775cf8f3dd5b54fcdea07e2bcefae323f6212b8f54877a60e1f8026f); + tempvar res = res * point + (0x338c001d0c722d793cc14219415d61c52de28d33ab8bfe5dd31674784f2b568); + tempvar res = res * point + (0x4ea62ac09b98dcc34b5437f6bdb4fb9a681dac12d1ca7090011c73259dcef4b); + tempvar res = res * point + (0x6a226b1dabca8ff2fbb52f0adcf4267a47e0eed089774157f318b507361a0b8); + tempvar res = res * point + (0x6ba0329f670df105c31eb665f3b6f243ab5de7ed8aa59ce9b0683e6bdfd9019); + tempvar res = res * point + (0x77f62cb2f9db71ba7a9913be0a434ca045a26704681af5353b7c7860be6e774); + tempvar res = res * point + (0x770018fe3435297b82b391a3bd2d09151dd3949545d0ef111cdf9fece9f389c); + tempvar res = res * point + (0x4279b49402fada9fcb602f909bc138c3547baf384dfef9594e2fa488cfdf8b8); + tempvar res = res * point + (0x4dabf5afe371cde17b9fa6c54c1b38d603f345c58d4f66e06fedd8948b402b0); + tempvar res = res * point + (0x15296a7d071a85f1358bb157d5e62b18a11e189415c16f594a18be7276ed2c7); + tempvar res = res * point + (0x79708fbce6bbe1c862e988648dd25347d60c9e0981540dd81ccaf78054a12f8); + tempvar res = res * point + (0x209866f9b8d946508db2df8eb9d30f65ede2c99ec8deb2e5a1b7093e9a62416); + tempvar res = res * point + (0x4ab0da9c66ca2588350bdb85cc745b4c5e7226cf7c4fb69708cddf6e8145f29); + tempvar res = res * point + (0x54578b117a58f5beb0d511ba42110c4696f4fec165acfbbde208a4705045fc0); + tempvar res = res * point + (0x55c9e37b0208bfbbb61e5e0e05c72111421b24b45ea53d3ddfad1cdfd243ff0); + tempvar res = res * point + (0x5889b4a99416f2f954450c60492129c5f7a36f875a56dde5188318e88d6032a); + tempvar res = res * point + (0x5919f2392a53f9b230145d1b5e6da28165dd1d8cc7d28d3310a805ebee721fd); + tempvar res = res * point + (0x43e49d0d9bfd165776eeab9118ea672c24a055a700e35a04426abe1b236506b); + tempvar res = res * point + (0x40e394412097f7c06183ae2997707604273b0a4ec1add0030bd7e115c20ca70); + tempvar res = res * point + (0x6337d741eb226911e37cc48087126cdd89f00941523cda2fa5e965dc4fa25e4); + tempvar res = res * point + (0x64592b7d9a6a922f5cf5f74c56e167ec000436a6b3caec299bcefea25e5fdd1); + tempvar res = res * point + (0x1d608ffab983d8aa17db9385433abb0025c77e27357285448c4ff6a8438570a); + tempvar res = res * point + (0x333793406d06dad0406a859ea2c203aff33e3cd906d6f04aabb0dffbabbc9c); + tempvar res = res * point + (0x3b5f2338d066753b2507a39884bddc2d0c5bef88e4bc3e79288331afe9a6234); + tempvar res = res * point + (0x3fa0ff20cc486bd0b43f96826c66b070a6f6e3df3359ebd2970661f9c679e2e); + tempvar res = res * point + (0x62cea6c83442875da8b98083d8bb18bce5d3d431a3301afc635600578b33506); + tempvar res = res * point + (0x4835c753d4b5059c1b4186516851f562e63e348f8810714cc393be9810a1de8); + tempvar res = res * point + (0xc230c4af49117fa614b1d4d74ef462211a5d55537ac71564ace080dd4b325); + tempvar res = res * point + (0x1917c10cc63bc9f43116c3688542cd867e1a84ce0d3e58dfb0c11c4b0828748); + tempvar res = res * point + (0x13c6580dce66b35fd24183e1635fb6008a6deb6cb507bf48d531273d5b4c2e9); + tempvar res = res * point + (0x6c6dbd58b8657f8588bae8a4d990e6f9b0525af4eabe87512c5f6a655c92028); + tempvar res = res * point + (0x59daeadc724e9c227258a56b000c6a613db617da41bbeb694521c86323c93b); + tempvar res = res * point + (0xead9e7eac2f6c388de28561955e6009f9f1ed098f70516f2bda28597c9ee03); + tempvar res = res * point + (0x54600ac31d014f7241c14e5aedefdc72b839cb0e98b84aa13f031316af48648); + tempvar res = res * point + (0x5370b38ea84ca67c75ab50a4cb8f23f4017175a98b23df9e1c92f92c279e169); + tempvar res = res * point + (0x23ae2f35a2da5ff92426d59ce066e29a525ee1207de1c370023975b4403ac6d); + tempvar res = res * point + (0x5952b292edb661874ff2d3482fb968149f09982bd7a194d2b502ee3dd32927b); + tempvar res = res * point + (0x30c7ab8fe6b61574f49c3d76b3173f76816f31beb33097d425a94beab6caaa2); + tempvar res = res * point + (0x4dbc9ceabbf1c8d5c679cf80d9bfc26ab696135792e83061e98b9c36ae6a4a0); + tempvar res = res * point + (0x3f1908469233dcf5c433790cb3574261ed6debca41fb55b912be7cf34adc187); + tempvar res = res * point + (0x51778c6b175ce13e994dc1604dac3b901990cbae0246b2cec2aecbe96dd2006); + tempvar res = res * point + (0x6a91b3677713dc15cd110c71cb8e174c8ebd8d7df1a1b4120bb4b6b1683ad5c); + tempvar res = res * point + (0x3cfdc71122fdfc7807b2efe35fb6c7691985d2727401eb8a8132d0e0df3cdd6); + tempvar res = res * point + (0x5099f832fdec91fd27af0d221e009ed6770227d63bcee6e1802cdd122751260); + tempvar res = res * point + (0x1793fa490096ddd67530e29cb3e8e9632d1885815be3f9d96375aa5946f511); + tempvar res = res * point + (0x6d4bd8c4aa4a530d965180c18062d6bc440e6e70cbf0836d6af11235c7fde2d); + tempvar res = res * point + (0x3d7587a79c4ae9c24934a10a9c1398c04f3915fb6889b72b361505a85db2b69); + tempvar res = res * point + (0x39007630deec4a6eaf806518c109f4aff9cbfb8826d86f301e562ec560ff89); + tempvar res = res * point + (0x51e4a728ecd68dc30e4a1b5867a1022af5808edafc3cb12d26d43b495528f18); + tempvar res = res * point + (0x7f921548c686f600b302290f692a66e9ececa142f691f9129c7d8bd2a06803f); + tempvar res = res * point + (0x42cdd4f6ecbfd891fedb9ecb6d320f6adafdb274ee15cc11ef4c0436a4e9afb); + tempvar res = res * point + (0x755d64434e4e4233388c34a90438764c568353cfde4311021b45e0f369b0db3); + tempvar res = res * point + (0x4b5e107dbcd02c0dbef4d3a77d66386a864d31109d0d0392847c8919d926fbe); + tempvar res = res * point + (0x373a1f2fbe36dae9a5f2c2b35febe59b53869e1678c8da23bd9e92c3c2ac0a7); + tempvar res = res * point + (0x53bad76d22e1525dcec248b73438d6f444caf75794c26144e26803fe2bc7736); + tempvar res = res * point + (0xaeb135e456ad66bb5bb2b91a4aa429915f6f9951aa15bba78576744a698016); + tempvar res = res * point + (0x111d440a13cab69043e1072b61c1736cf3901941b4c57d7602b8effa7e74b3c); + tempvar res = res * point + (0x5fb8d87e82c3547e32ce316e4439d1aaf3723e4a906c91533ba8dd9631f1661); + tempvar res = res * point + (0x1426a2050d240104b5c07a9cdaf7fce03c2accadb0ce98344ecb4942c434db); + tempvar res = res * point + (0x929eaf221c110efdaa57970581428d66d5866fb9547aab76e89e8971efc91b); + tempvar res = res * point + (0xcb3220da969b95193a25d1d4d76d1cd1ec596040a7b31da7f64164809bdc4); + tempvar res = res * point + (0x3c3ea2cbc8ce544c6c98ad9053cb2c35326f4e502214e5f72c7951474b5a84c); + tempvar res = res * point + (0x68892b41018bc73b541800d91f0bb2a8cd9fcfee8be13bacbaf7dff7aecdcd4); + tempvar res = res * point + (0x2a652d2592f5cc1197a206db79d06e3b74a55b1d4ec03c516a6957e87345cbf); + tempvar res = res * point + (0x1e0c96f0b836d1e2df4e4063d56b78f38f2ad16040d61855b0f664c066d130c); + tempvar res = res * point + (0x65d167bcce20a40b78583e4dcf7e3f44663e0c595e18f48f83ea4230b207047); + tempvar res = res * point + (0x1668b919fcdf512b5683880ed048853e00f456adde728427fcde63ac9f59611); + tempvar res = res * point + (0x1489d6012d4c9701b63f3610034fb5bfca185c7b01222907781eb104e031097); + tempvar res = res * point + (0x57ad5370b26ea1478f3fa0346d2e390e90feda8022c9820813d9ddd0f36e7ba); + tempvar res = res * point + (0x522f83a59f717f37b235c05338a02630ad83c3ed307838f6e795f9705cbc849); + tempvar res = res * point + (0xb6bca44a12ba7914e575f83cf8b9b8bcd4780622806901dcb9530ff9a454f8); + tempvar res = res * point + (0x6fb8324456f1dc4b423220d18d40de524a27dc4f35e4c780a042f6edc95f97d); + tempvar res = res * point + (0x2039c72c1c7c134fb300e82b104394f54a5b7ffe6f7f00e7c3e4ca6640841a9); + tempvar res = res * point + (0x614a280377b9dc732773d969da5ddd8cc125262313eb7b2bd38b7668cdf00b4); + tempvar res = res * point + (0x243a084aa8c82348102320b0ad19ede41b6bd7ffb3a7041339a13f34f6b5671); + tempvar res = res * point + (0x73e8c35fa646fce6bf10c33168dcf3d2e40af17ced70b1929826d0ca4ba2e99); + tempvar res = res * point + (0x64f6f50e51b19d5a90e6d2c9cfc3486dbf2b37c7f949cc4f8ac4dd988e5bdff); + tempvar res = res * point + (0x1365aaaf8c72d7e9b250bd91ee2c2264362e87679abcf2df2b7a4e1eda1575f); + tempvar res = res * point + (0x24a083b7cf164138ea0c468f33317d89c97b69378c906d918123f3ed5a02cf7); + tempvar res = res * point + (0x25ea89f2d7ad620296fda2be181b5a6be626eade8974facd81e53df842c125b); + tempvar res = res * point + (0x2d32dd179cf74693057ede607e0054fbc3e4194efd6415156f3ec909c37ead2); + tempvar res = res * point + (0x3b74f537f03a28e72bae3bf1810f1a2fde1711eacd6bc64bf55f37b3bd9940b); + tempvar res = res * point + (0x575b929bc0caa43939bfae95a6d5cd8d4082be7fe0934be4c08f7fd3cbe89c5); + tempvar res = res * point + (0x7ab2a5ce120c251b658bfe532880535e93cbf88aa60a1b384017195e6715706); + tempvar res = res * point + (0x7a7d5ce80c8498175cdd4408e08cea457517e37dcba08d0a6cd2a4defcce34d); + tempvar res = res * point + (0x6475aad2a1631a6103b238548fe8a03934779ecadeaead2bc20a677c0c71c); + tempvar res = res * point + (0x547ddf1021a2cbacc8081cbe3a5c89b8ae808942513cd6f6ad166b0306cee66); + tempvar res = res * point + (0x653405343098520984b06f707cee84ea765ecc932783cca87058b88d0f2bbe9); + tempvar res = res * point + (0x3f22422d66d77bda123b47b7f5bffe5527f95d331346f6a545c66887ad75ab9); + tempvar res = res * point + (0x1b18b73effab8a483156d16e87be4dfce1250333eafc784d76c6ee145978c48); + tempvar res = res * point + (0x2843bf3d789d84faebdd6ceb0eed3ec0acd959732178b00b4242eb5cff0ef3a); + tempvar res = res * point + (0x592d2fbca1f86935e587f6cfdacd0a221237bd378e2d1cbadc3d168c7a1756c); + tempvar res = res * point + (0x4c35c95cf7170d2ab6b9b6e3c1be66dba2de170638f27975fb5ec12c36a45d); + tempvar res = res * point + (0x405f9011670f0f202814795cdf0251b665e8f39991dfe2282a1dd2acdbaccb1); + tempvar res = res * point + (0x43b4be816239e45b4d22123c840717fe3e8f6ce53238fad4ad56e27c85f3e9); + tempvar res = res * point + (0x3a2c1769a49e0632c149dc9d3f30306f9d9cc00cdb426d58b2741c804c51af4); + tempvar res = res * point + (0x422c03b47f25f698d3dfbb02556367c97b7d8e2657af2e45ebc61845aa2c52b); + tempvar res = res * point + (0x5a47f80b2d6e8c8e89f08c23e4eee09ae23882290a4dbdc5d0b09e713297124); + tempvar res = res * point + (0x2059b2385d435959cedebbb68ab5c484441832a20d67889ff9974057cdbf874); + tempvar res = res * point + (0x6b735de6be3ab4aa1425c328c838ba09dec586718729f1e172554cac036483b); + tempvar res = res * point + (0x3c05c93a63aad66725d8d25e62f76199a1e9f5743577777caa05832f4e79acc); + tempvar res = res * point + (0x4245e03d0378593b2d4230b945a2a147b36ebfdf368f0dd5fc22e3b31ac1186); + tempvar res = res * point + (0x4de104ea20937d5d6cb02c4ab4d7c4d03ab2eb16d1b837ccf0c2a05ea2873b1); + tempvar res = res * point + (0x48876d457eaebe03383add02eb4c0c49a09923757428595a4f3ad6299d69cba); + tempvar res = res * point + (0x6d6ed610ff1347a9252bf835af9666acc415b28796d968ab76353cdc1181733); + tempvar res = res * point + (0x1da9b14257c5c5cbc1a97aff87690dfa51e82af9a11eaf5cb2538f595ea2105); + tempvar res = res * point + (0x416057baac3a1780d7d25b192188b9b3981bdcab0e2dffb2fd95456a5313201); + tempvar res = res * point + (0x1706af2f962881d86f167571fcbb909b6f1e4fa386fca8d87b674335196f44b); + tempvar res = res * point + (0x6d9c76938c974418e62166285ade6564712e6a263357e11d70f3e1f2ae531e8); + tempvar res = res * point + (0x771fefe011becb392f5c379dc9e902c41be8f1069ae3c5e0bf6016b7b1b3f55); + tempvar res = res * point + (0x40cbcae9364d8af8b767a72b260793922cf1ba2a03fedfc60d4eab1d5f00042); + tempvar res = res * point + (0x274b54e6342ced28b28c62edbc8a6cdb44d1530e0fba56e4940e55d806f437f); + tempvar res = res * point + (0x77273f7030b86a46aee79ed44f0968feb0ffccfa0964ffff141e693fd0fb6d1); + tempvar res = res * point + (0x4dbe5188f23eedad88bab99323be5ac9bf747525c23d4c0665334dafd1f0c6); + tempvar res = res * point + (0x3410d8b91297b00cf8d438bea18b9ebd55ae441a2f6bac6623a15e43ad64d4d); + tempvar res = res * point + (0x4195cb2f46ca4e1ef5d93ab3a5decbdc9e74d0bb81d56abcf59304ecf79863c); + tempvar res = res * point + (0x6581a70ec64b4268a4741b4f7de866050d31b69005c782630f4bdc51a1650b2); + tempvar res = res * point + (0x754535ea8702292678b57fbde36c97454994bed59e0d0e13cf8a6c3ef7a0324); + tempvar res = res * point + (0x71034c062fdc1b61e812617b037c5dd1e80d158a92bdae7ccaec162fff4edd3); + tempvar res = res * point + (0x297d52739d69b228b057588496920930df6ada28e5e2a431b65502750a5bad7); + tempvar res = res * point + (0x446d7e2595a1940ab7f6dec4c9f78953de9c0f4c67a130b55f1894779e73ac3); + tempvar res = res * point + (0x5b0a8465067d8f43cac5dbc1145110e1e79e0f32ba1d59d2514405a0a806860); + tempvar res = res * point + (0x5bdc50def36283e003e9ccf2f1bed188326bec8bed554815f9e49062ed6da4a); + tempvar res = res * point + (0x3b591c6de6700576abbe4b4544de71cd3266a5dbb70740762d0c16a863bead8); + tempvar res = res * point + (0x7fe75f49544ac3cf237a17e58179851f5b3e7420330e5861ec505291d9a0380); + tempvar res = res * point + (0xe09e3870dab755cabbeac23076891b510207da569b75bf32d3f63c8ce08460); + tempvar res = res * point + (0x66bb11e034bb55410211b7cd410cf076db77f008bd93f0dc938f089e853f0ee); + tempvar res = res * point + (0x630cb6b8bcbe79e58025a699d489116a875f287fef6f1677b497b8702c3777d); + tempvar res = res * point + (0x46ebc0bdf94c2f85023a0c1b29d229ef7a23e173d310b814f72c73904f6a5f9); + tempvar res = res * point + (0x3fdf21da099da6c005b076001c5a95f2fe26aeff47e2cb9e8e52166a22b643e); + tempvar res = res * point + (0x6c647f1e5e8e93fda4bc0ae5d513cb60558e2b44bf885484161bbfb5e093969); + tempvar res = res * point + (0x688dbf5c443560c219afd8c54a0b26bdc9284925f2cc0adc889c1de024d6ecd); + tempvar res = res * point + (0x3c782f4a1a6d94adf1448fd7feef975f47af9c79bbf7e2d74940673704b828a); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_ecdsa_x(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x22aac295d2c9dd7e94269a4a72b2fb3c3af04a0cb42ed1f66cfd446fc505ee2); + tempvar res = res * point + (0x2bc4092c868bab2802fe0ba3cffdb1eed98b88a2a35d8c9b94a75f695bd3323); + tempvar res = res * point + (0xf685b119593168b5dc2b7887e7f1720165a1bd180b86185590ba3393987935); + tempvar res = res * point + (0x5febf85978de1a675512012a9a5d5c89590284d93ae486a94b7bd8df0032421); + tempvar res = res * point + (0x4e1b2bc38487c21db3fcea13aaf850884b9aafee1e3a9e045f204f24f4ed900); + tempvar res = res * point + (0x324182d53af0aa949e3b5ef1cda6d56bed021853be8bcef83bf87df8b308b5a); + tempvar res = res * point + (0x5d4c38bd21ee4c36da189b6114280570d274811852ed6788ba0570f2414a914); + tempvar res = res * point + (0x529414d56e9f6bf4ce8be38c8f79ffab78b185da61d606c411098f981f139a); + tempvar res = res * point + (0x66d15398bbd83688bda1d5372e048536a27d011f0f54a6311971822f55f9c07); + tempvar res = res * point + (0x52e5e75be2c96802a958af156a9e171dc7d5cfa7f586d90ed45027e57c5fe92); + tempvar res = res * point + (0xb0e39f10e5433b2341ecef312e79ed95d5c8fe5a2e571490dd789dad41a2b9); + tempvar res = res * point + (0x703dcca99c0a4f2b2b7f1b653dbbf907dd1958c248de5dcb35be82031f7d170); + tempvar res = res * point + (0x749e86688f11d3d0ef67e4f55535c715a475ceec08547c81d11de8884436d8d); + tempvar res = res * point + (0x44a14e5af0c3454a97df201eb3e4c91b5925d06da6741c055504c10ea8a534d); + tempvar res = res * point + (0x6cd537aebc479350e63acbcf7b9da84f4b06c6c26a571d3a7dd416a94a956ca); + tempvar res = res * point + (0x5e2909b1136e1d6608663e5cbabb616b28d2fd6f5dfb7cd03c4a7e719b7c53f); + tempvar res = res * point + (0x51170abac6896de6a5b478741dd56f52b1d2a1feea59b1f26d060e09ed98b32); + tempvar res = res * point + (0x1d0f94ce5d9d3beaa42ebed05a2f172aa2227e9a9fee0bf43a3fb068c1ac345); + tempvar res = res * point + (0x785dc572a88712cb4eddcc8a167bb1b62f9a79282f21ee92a0374af76169344); + tempvar res = res * point + (0x39d9d83e0ac884a5ee0f2d227f9eda71724a55002a41938458e45251e121308); + tempvar res = res * point + (0x7fdc637318ea00385719f9ce50848d13cc955eef9f36a90b87e646dac85e3aa); + tempvar res = res * point + (0x72d82458ba49cd6c638f89d2e3a68e49944f486cdfb7d2848e51aa9f99292a4); + tempvar res = res * point + (0x4c484b2cc04747d8d812180ec716f779302231983fa17971b575274c0a9c378); + tempvar res = res * point + (0x62773dee1773834dbb324c4c0d48dcdf9bbf0511547feb1b2ab0f7af7fa2dc2); + tempvar res = res * point + (0x5b0343972ee9e17afaf76adc54e6797d54e6e47a7ea1167654ce076e3c6c360); + tempvar res = res * point + (0x3ca8d84242dd2bd2a5d6e644fa1dc9f5082ee6131b6f0db8fd7d4f87109098b); + tempvar res = res * point + (0x6f4ab1f3bccea47669a4c93da36db05bd6f5197945b5ab29191a703312ed3a8); + tempvar res = res * point + (0x2d626ebcfae2d3618e350c190fc636495fbb04dd4a4e563680fb961a3d30d8); + tempvar res = res * point + (0x42f0a74ce045e8194b7a5cac4e882b1f1a9face49c38fb3383cfd3d960806c); + tempvar res = res * point + (0x34b7ebee71c5876183407c57610a0a8a33d3138ccd6ae416651cd505e5761d9); + tempvar res = res * point + (0x150c633a21f3cfa157978e9561161f3953e180b9588347a0c819e4173afcfa8); + tempvar res = res * point + (0x4f8cecab5f743c7227a63fa7f320930ffa7cc52b0fff6c351d3e9d4c22f9f9a); + tempvar res = res * point + (0x98ad9c2080ba0663fb302025e6224cff41d1d30c5c9101ad77a48a71d8ac); + tempvar res = res * point + (0x58a6d8229d82c192f190e55d28489f621cbcc64e4ef10c1ec5663c5384e60f); + tempvar res = res * point + (0x7850ac1ef437d1b99c026a910b2437c1b877242e605c8f31a456f10e2f78743); + tempvar res = res * point + (0x337092590652e19c23b48de3629ae0bd4157a5a72ecd3fcd17bb93f05814716); + tempvar res = res * point + (0x95fd265a2a87c42af5a20a199e6730ee3f0e3352a38a5e7e84ef46c621903d); + tempvar res = res * point + (0x38ada3df52cd03154d66b7da4a8a01835a461e61a76ac9576649d8c00013610); + tempvar res = res * point + (0xc1bbae3cf2d414dc12119a0c746e3c10e148f8b522d574eff757d44d8b3a14); + tempvar res = res * point + (0x7122e4b28d4ee35902b7f7b8ad5f525b6c70a2f2bb6b4ee4b9f0008845ffacf); + tempvar res = res * point + (0x75275c33b919425b271966642fabd9ea7c917e70e96eda669040935b1d49db6); + tempvar res = res * point + (0x70af32c484244d3435bb65b0ed076f48d06abb45b7765de9c6f26c1c8e9156d); + tempvar res = res * point + (0x47c78a993a13204796a2fca3b20c0f02c0601e7cc59f84570fa026c65796dc9); + tempvar res = res * point + (0x55713c4cc9f91e9f158f70683238853d0bb7cbd8358ff72b01fb60808b5c1de); + tempvar res = res * point + (0x412fcd2551c0516392f685a62b54fb82b9a73bcffd42abecea4482b65aeea47); + tempvar res = res * point + (0x6925415cd4dbae0ea5e9f41edcb503ff6f668da1cb13ec73eab6a99cd96752a); + tempvar res = res * point + (0x3a2a902a0e43ab33c19459984fe116fb215796cb40c48e254de6126b55e9c3); + tempvar res = res * point + (0x552e18bfefab6c3362cec587f0a7433a914f1359e5767b4fe883f1ad902dd13); + tempvar res = res * point + (0x5643c5a69044bb8e86d10d3248ea3f50f8598732b0c517b256fe108294e09f3); + tempvar res = res * point + (0x542f931640d9010e906b7e1e375cd0481740157eb51500ea1e10afe77f26265); + tempvar res = res * point + (0x2a2811098d68a747bebe9ca2eae06b604bb307e5f51a9bdac1636f380feabb5); + tempvar res = res * point + (0x57d53073d66a528c88f24e40011321f74ce5bdbecd6ca319e5e770ae29b21da); + tempvar res = res * point + (0x1a4393bce3924d765902469c715fedeea69adca566859b4c8c412b7d7cb566d); + tempvar res = res * point + (0x6dfc1fb08b981f73911dc43811caa0ed99749c2f0903f87f389c9a0e2a88126); + tempvar res = res * point + (0x224fe4f546c8f999947a5864ed0dbcd64fcac6f774ebce11667c2bbb7d8603); + tempvar res = res * point + (0x1f7d548c5a6f2bc70ff6f8ee47f38221ae25dcb4f9b068054ee66227494f87); + tempvar res = res * point + (0x735f4476c2b51acb4f0dd9dbc4306108e37543538b2cd3cd2327ae5377a2e5d); + tempvar res = res * point + (0x66ec70c796374a71b6aec5520467ebed547f645d1670b990dfa680a1b415cd); + tempvar res = res * point + (0x14ac38a4b82b4c65e4993726b58f32c74988997b8e8f7729fe9032cf187896d); + tempvar res = res * point + (0x27092905558602aec9af09947b70bb974caa3dd7cb1cb991810e15d75194aa6); + tempvar res = res * point + (0x44e3645cc1b135410b2a52a5b92bcb454985033615453a51ac46377885c4309); + tempvar res = res * point + (0x352b933e5d853527d2a4317db613d07117fad8115948957515bc07d72e161f5); + tempvar res = res * point + (0x268c1e10f6f9969291b1d2f54289371a2f40a14cc67b3736e04eb891c1824ed); + tempvar res = res * point + (0xaa81707e389769aeb31cc8b45276af0370dd702ac79461bae0a4078cefb5df); + tempvar res = res * point + (0x67dec5ad6ddb1761ec61d2820533f7a2bb56d66f2fb8ecff9cbe28218990061); + tempvar res = res * point + (0x106911de08ef437acabf58d178db7c81ff4d7de25f3ef5cd2582f44176d449e); + tempvar res = res * point + (0x356591a80d5c2e14c3d8a180c030a9529a8580a4f3be00a5a9eea83d0d585f0); + tempvar res = res * point + (0x40a3ea8c4059a1b9138884234381d6d383e66dd48eac1bf05f5fcddd593c881); + tempvar res = res * point + (0x699e679a8f38a1ecb14c6695a2848c6abbab8a05003e43aa5cf4a9c6e6058f2); + tempvar res = res * point + (0x6b86f825e41b2c9934f71cc2cb08787d1bd4f2eefd2be9c44e37bf387b35940); + tempvar res = res * point + (0x4eb2786b11bc602bbf773564eb9b057d7dc02daaf4359c015295d97b74e72bb); + tempvar res = res * point + (0x7b0ed28b968689517aaa216c0203e57f1cf56b22ff1213561499ae140d37fa2); + tempvar res = res * point + (0x367ea925556a875faedf4d61bd2a95a31067bde6e682c50035bb3310cc54b03); + tempvar res = res * point + (0x781cf0ea1c0ba9cf908656aa2c5a9403d54c26c8ece401a2c13be8d3090f9c1); + tempvar res = res * point + (0x20ffc2b4c6c318bee0cdfdca40b2c10f2c629d3b52472b17c1bfd909cb7b85a); + tempvar res = res * point + (0xe5e89fde76daa211fadf1178785f0c25a94d47a468cda257a895b871a928c2); + tempvar res = res * point + (0x164344bae5b9dca8f384612e7351fecde28adee3d245c98dc2f65509b181d8e); + tempvar res = res * point + (0x4063a6202df9488fe5384aaf7be7610b3e88a9c01486c1b88767ca36355340); + tempvar res = res * point + (0x546f65cf3367a004f10e9a4e47d71f6ec80086cb2be19d7b225825e01eb323); + tempvar res = res * point + (0x72c11bd84cd54152607e4c6e558a28e480a6487e374b865682c167484f8c29b); + tempvar res = res * point + (0x7a5d11f284ee7db72bed2338784d6467e05cae85f333e05c5610c018a57c2a7); + tempvar res = res * point + (0x64c71feb673d2655bb1865f9c4bdfb16b1bcd0f278a911363056674dacb812f); + tempvar res = res * point + (0x62334e7d6094be4431aeebefc420f7e656459d6fc2cb10455123ede054f4cdf); + tempvar res = res * point + (0x5dd4b3dd252fa7eda7b46674369a2f8c5b00a891cf01ada0ea5aada8bfbf6d4); + tempvar res = res * point + (0x3373dcd7d0f0f8bb31ec396e1ec67e1f121121356dba549bce9fd4d3bbfbaad); + tempvar res = res * point + (0x42a6c571001e263b1ec8168805bf4d6cb65935cd0687c696ae3a6968fd28378); + tempvar res = res * point + (0x16f35b8d34d425a85fe48e66632d3e4af27d5d65cb180cb99047fdc2b908ea6); + tempvar res = res * point + (0x24327b5849aaae0d313870c10e8010a115b70a99cf6b92925f51d2f05686287); + tempvar res = res * point + (0x45ba7e524d75c65ab27b57a6e0b90458c9b0eb651935f84898a5d3cd0db9b8e); + tempvar res = res * point + (0x767d8839373a2e97b7e3de1be6f4c18df648806920e92fcc4da9ab6bd8525ce); + tempvar res = res * point + (0x741b0f4e1bf8ed4d6318f5dc5ebba8529089f5ef4a84cd727564c60cc11a96f); + tempvar res = res * point + (0x68682814e1b4dd639cf396a9f60efe5ca035c6ccd75054b8911e8a15230efa7); + tempvar res = res * point + (0x68edfc809bfa6534b583624db421a2cb885d2ce888e6f95eae85ad9cb38249d); + tempvar res = res * point + (0x5d6575134d1b37e610f25e65bc8b0b1ad7fd0cdcaa56fe573142a09707640b5); + tempvar res = res * point + (0x327bd35b3ec38fb121c039f777669426d3d60df3922e688a408a06d4e7ee3a1); + tempvar res = res * point + (0x29a66c93ef1fa5ac4b6f96ed329810085b294a7ab8e16c61b1e225fd7406236); + tempvar res = res * point + (0xac01d3129d24fe9b9209df8bfeb2526bc27e9c27d78f69eac16ce151b13540); + tempvar res = res * point + (0x3a967c407600baaac716275b8fa16a08c22e928d895c762b2843d00496b3390); + tempvar res = res * point + (0x4d111629c799fb16f602183ae372aee382e0b401312951eefe77a1674575242); + tempvar res = res * point + (0xa8a00bb9874fbb44ee3411814dfb9d4d6048f5e3af6f7f09fff4e9f0263901); + tempvar res = res * point + (0x3abd943152451107f59aa81194e7bbbe37c4a86a6b41e20a02f8145dd32fa87); + tempvar res = res * point + (0x580bd7107af3afc93d0cfd1f0bd39f78f06ebe3a900f5d79943c25e980e5653); + tempvar res = res * point + (0x7a615360e826e937db0c91cc1c9196086a3fd608cb01d20186ba1ce856904ed); + tempvar res = res * point + (0x21df6648e6f783b7361a20191b8d399a4373dcbcc83f6b4a9a40bf11956219c); + tempvar res = res * point + (0x2c82b2a99d198138ca2c4229a1929d044b113c1b0f693659712318ca7e7f804); + tempvar res = res * point + (0x6dd74321080cc46d816a963c8a6f5dac42cb11e66c79831efba77433cce0d23); + tempvar res = res * point + (0x1e54c3a5a3beca7932090ff58784aa43261075950feaab0e2a840f3801b81b9); + tempvar res = res * point + (0x3360af40b57c0a951da3219025643a76516f85119dfbb05f61874eb3b56b130); + tempvar res = res * point + (0x164d44fb88efb41e301934bf2c61a20e41c9bcb3f8e784ac5857063b4fc3d5a); + tempvar res = res * point + (0x46efbcd0bd7f06d59a430ddeb9f239d66a24ce1fa72f5dbcc2bab48b707b2dd); + tempvar res = res * point + (0x5ae517bdefe7b6785680842685de0b5cd972a22dae9ceb50a6ea3665feb06f0); + tempvar res = res * point + (0x51f4698c121db3db4a5244334c5180cfba256dc80a59689e2c0f1f8d946e6c); + tempvar res = res * point + (0x67d2681fae96c0b4bf22d10a73a1882c5bf4a5440f8d0458394d514ff7bd18b); + tempvar res = res * point + (0x3dab30754623b91aec7a165cc167e9003269ebab3e551781e4c8cfb73402de7); + tempvar res = res * point + (0x44be18892438118a0b3fc099da7489a89cffd4206678abfd37b1e649ad19178); + tempvar res = res * point + (0xdb0ad3bd8a33b8daf1d53ff8604bbe5259b6620e3b547d5c6f392dbc10ccd5); + tempvar res = res * point + (0x1a36f20817da4dc0c2e8b62fa08ce15cd3cb50419acf5211d6948bd6b28c8ce); + tempvar res = res * point + (0x5fa6f7f2a7a527880a5b58911dd7f3a491fc702f481cee30e67c4980092f851); + tempvar res = res * point + (0x6f682eebabbcbfa3e7084b47b2a01acb693865749df222b4b8dee0ec41903cb); + tempvar res = res * point + (0x1fd7088411b30cb5762147b1d6749942485b36c68ea32f60ab83fdcbe987d83); + tempvar res = res * point + (0x7172b43d0c88348e5453b0b26d54d4a7ad7e99e6b0c4b787341c8d89936197e); + tempvar res = res * point + (0x34369f479f013d44dd5bb0d79d8a9effdb2ca36ce8b3d7e759bf707233c5bbe); + tempvar res = res * point + (0x3054d35b59baf5b0a2078c23322de031b383033837cd6b978b6c060120b7fb3); + tempvar res = res * point + (0x23f0124cd1c3f3605fa1ec36dc4d6cb6e229f8ba8998b138a44595f96f3bf21); + tempvar res = res * point + (0x2300892e3f3c180333d091901ba99ab9e23c7947309b9e88ad47025847ec3a0); + tempvar res = res * point + (0x4182bea2ea16dcacb0194876cd5fe8c79e1a55836aff8aa6074d235af5f7b29); + tempvar res = res * point + (0x50f3e383aaf3533fc91b9633386542798abd69b79af893f47f6603d3cc35ea4); + tempvar res = res * point + (0xc37f91c81a7006d6681cb511dab2e4d83928ccb78d1dc72c4c556e4cd72db8); + tempvar res = res * point + (0x2693f31fd4bb5a1ef9cacdc4f2b33c3d6d965b76e7bf289020ab1b6c6660d70); + tempvar res = res * point + (0x2bebc90c59dc0e37e28c7c7d8254520ce08894637bf1a089aed26012690d119); + tempvar res = res * point + (0x17626d3869adf0fdd3fedd48e9fe1266bb33419bfe9046df43c6409b440980e); + tempvar res = res * point + (0x734438bc30566591da45df9366f936415d29eaeaeab392488bcccb9acf0edcf); + tempvar res = res * point + (0x22a7b1c897f54da39a1db61b345b234969e36ef6ba0ea02f8d8b3e83b5c6242); + tempvar res = res * point + (0x22eef827b9d0b57649233c5d527b4641decab31df78347a20da21c705df093b); + tempvar res = res * point + (0x193185be6e02dc0a07c0dced4ed031bf0a406219cce325e76408123406c318b); + tempvar res = res * point + (0xb10494024548b14df121b738abc7babe56c12acc0490699443426a52f3a4f9); + tempvar res = res * point + (0x375ce3766894524209e2043a150f10ad0bf4f726e3dc5453c3c757e56943a51); + tempvar res = res * point + (0x1b1c82e5c561dc42f8c9c2a9f7db6bacd729b2646892a8ecfae9ead9a338aa6); + tempvar res = res * point + (0x4b540d0085be455b24f014bf51dc7d0eceb8c93bb644a5208fa02dc58c718ae); + tempvar res = res * point + (0x17f2709d2719458a9bf72a2b04463f0a6529fd9368a47715c628ba4e006cea); + tempvar res = res * point + (0x20e468bb2828fb774d5ab538ff7f93ada201c2e392936e05cec29cd5a7a462d); + tempvar res = res * point + (0x29cc816e6be353f6ad5e2c390f37ed3940b0dd67610a7eeb0bcded94bdcf920); + tempvar res = res * point + (0x4d3b0654fd74862a92aa716af33b5ad5ac20dc0460c724d95ca94fe6d8a9d7e); + tempvar res = res * point + (0x7ba5194da963f8224987db2720f16baa604ff62351e66a63c0c9dba00fbc7c4); + tempvar res = res * point + (0x31d335bd885c9cdf2adc68ab45b8eecd2d3588cf85b93206896b2626eb1e369); + tempvar res = res * point + (0x4efcba706a8b7868e32f363efac2696ad0625d046a3ef97917c710515016386); + tempvar res = res * point + (0x56017977a273ad0e91c7c26a702ae4508343e97968295b08447b3cc7f20522f); + tempvar res = res * point + (0x16416cc193a5ced6ff213fc18c86bd6f08d17c576f26b9ebd00d2653bbd6444); + tempvar res = res * point + (0x4237c41364975eb79919303fc0a381b934befe871fdbd72c18f97627292923e); + tempvar res = res * point + (0x1b389d976c22a3bfb42424896c9b135a3794048724c729968f81e04ce414194); + tempvar res = res * point + (0x62fc206aa283139f7451e54cdac873fe86b6e7e89214a3c0318fbcaf6016fa4); + tempvar res = res * point + (0x88f6e5a835dfda9fa2e2ff248d9378352f4a89b6bf5935700da390baebadb7); + tempvar res = res * point + (0x4f9e975176d3aacd79c322d013c854c4b8829d1e469c9b242461f35e8dc6fed); + tempvar res = res * point + (0x6e1143b147dd1bcc56dd43e6a3616c9a4016d6887cf0009ebf9f9796efc944a); + tempvar res = res * point + (0x284c547c04ca83fdb01020cfc797eb362838317f09e5d25e1e4eef353ab7a7f); + tempvar res = res * point + (0x60c327ef73c8468805ecace45a33ccc375fc91ffbf01b4b10a01ffd4b7aaefe); + tempvar res = res * point + (0x59cd87f8751437900e984a009c63fdf7461b177067760f30d4f648ab271660a); + tempvar res = res * point + (0xdaf5a68420fa7ad811f6dc75c5b4e92173a5d89255dc75accb8cec80a9cd91); + tempvar res = res * point + (0x1f573af6e3ad146eeaa582f540de6a8db237ff2f28423660de998a4275bf4d0); + tempvar res = res * point + (0x2830a6edb344b7fa86506557a0b2b0bd900429218fb35e7990951fe4fe869c6); + tempvar res = res * point + (0x58f2e18613b3b25529935a623e7d5c8318ca9ff3fb180f16f7454ca9e348e35); + tempvar res = res * point + (0x42c8f0b5507417eb48ffeb1a7df8808633f193c27df8e2f44ee7bd62cb2c3bf); + tempvar res = res * point + (0x50d603bf9c2a456b828ae476092affde072ecd878877ec3f99ba8f574d263a2); + tempvar res = res * point + (0x413fda31150aa8462deae8a6043fc5624599fb7f638c4d5c5f89472e1223c28); + tempvar res = res * point + (0x13fe84c8ecc2e3fd289560c0ada7a251fdd5fba24c076be4be465feec4262e6); + tempvar res = res * point + (0x2b2a0768e9a5f59e7f33ea449690794c8b409bacd1c808f7ee8065ed9d8648c); + tempvar res = res * point + (0x3030332e9cf430f72159914e59ab9af532bdfdafedc1be39691256c8084954e); + tempvar res = res * point + (0x16617a52bfe5d2fd0eedb0d6411f5fafeb14a4ac17da0cc828c914acb500ce9); + tempvar res = res * point + (0x553f8ab49053432bab53835480b6f4c416eeffb3470fb6bcf122741cac3d71d); + tempvar res = res * point + (0x3939ef0e572dcc3b67f0cb819fffc521df26e50814281621fa6982b1465f786); + tempvar res = res * point + (0x520b18e79de342aa7095ffe56be6222b0d2e44fc3c676a5c994f24e427b45e2); + tempvar res = res * point + (0x3f3ae3871460ac578f5030d925e91c138f3290f8f3cb6d4b560b4b16fbacd64); + tempvar res = res * point + (0xbffb0e4f7ccfff0cee519edd1004eefbc47024f92c4409bbdf688c133ad285); + tempvar res = res * point + (0x62d6874b6dcb1c4dc8ed797b9158da4359c6c49f27af4851a12908ecad2092e); + tempvar res = res * point + (0x511c0ad7c0bfdcfcfaf925895a8ef5e8c5e0d147e29c9cdae45fbc998fce346); + tempvar res = res * point + (0x25199c11f7193e07191cd9b9108aa8b440ce1972dd1cbe5f0cc33b7783203a8); + tempvar res = res * point + (0x3cf3b95ba351a72019ed1bcadab32116adcf079e72800a9d88f15244e7743e0); + tempvar res = res * point + (0x19cf240d04f4859941f9b6af4a7088729aa10307cd08aa75f01cb22e872543d); + tempvar res = res * point + (0x1cd528d070930aef19e0f928fc744e79ff57e227b6aa1bbfce15a79166aefd8); + tempvar res = res * point + (0x475f8af086f7aa4ec3739f754f7dd291dc50decc7c7fb03de8aee3cf06824f); + tempvar res = res * point + (0x28f86fe2d71f9410e14c17195ae19c2c5e623c525c979f4f74dec3ef8848eb5); + tempvar res = res * point + (0x508243aa19e23cdb8ca0154055c05130462908c6a2691ae522e37ab9d6168f2); + tempvar res = res * point + (0x37cf9640e321e7bccf1926d5fea92918d6888c5805e27193722995233a4adc5); + tempvar res = res * point + (0x66336e2e2eeb939818f861fa4aa9b2576936470f511786f8fa3417850a6c2d); + tempvar res = res * point + (0x19a0ff21908842e412addb744b0ca384a54bdde819f6337c4c672f682fea9cb); + tempvar res = res * point + (0x44147236daf669f8a94b7ea353c3dd7e64312ece01ccc1d4dad67916591d50b); + tempvar res = res * point + (0x1d6cb5a655919a581078aa2f8a21d300425026ccd7d047302443d78dbc67abd); + tempvar res = res * point + (0x4d8d9b92b38a45147bc9c87c071672edd93cbf5bdc8d85e608f26f1d82d172b); + tempvar res = res * point + (0x4acd125e74056ca611a1b07369166eb5c02af7a4cbf387b2bd584a362fa9e60); + tempvar res = res * point + (0x3b4fdc8d965de1761e445ee88cb406f707f9d0b1ea3c069d12084c0ccba9b44); + tempvar res = res * point + (0x1f27c20f47daaf01d4627d5e9bee0e9bd2aa5b75807064cd60ed87e307f677a); + tempvar res = res * point + (0x4758304a75f149e24563c2b22459151389b86d36108f5dfe11ea1fc7a64fd7); + tempvar res = res * point + (0x1c1216fe648d287c2645dfc5152e171f25483df5ef112b745c2e59b5d9ee07c); + tempvar res = res * point + (0x24adf288d61c113e28d9a298d2642eb67586019adcb952abf274ebe1d30e24a); + tempvar res = res * point + (0x3e09706cb43c83143c9dc46f97e0e1ab4327de19ced69badaa8b2c80f68fb9b); + tempvar res = res * point + (0x589a2e11637d0c90fe91bb9f4d55a80cd1a2df7f3431e8b8bdce8fe7d35126c); + tempvar res = res * point + (0x5f506aaae7ce6d94712c9e0ab02bd2a4ae09600608d54a8ca381b8e96222cf7); + tempvar res = res * point + (0x3f64b3a307276c6a7169c54297bb12aaeebadec98df6ba1184492a82effe353); + tempvar res = res * point + (0xc3e0400cbde1da659381240d9c84b977eef3cd70e3e4a1a8763a05e682eb3b); + tempvar res = res * point + (0x1fdb038204ac50e87e3e7239d8c1c0572893ba98e031c982e545e6de64cb8e0); + tempvar res = res * point + (0xe0b21e37008355c35f7aee295a8b2b72465866b2bd68e72d36f032c34b38a0); + tempvar res = res * point + (0x2cc90219912af16cf9a39f57f8b8c514f797dd5d49dfed5eabdc278e31106a2); + tempvar res = res * point + (0xab2147a23a826d5f7c6fea5bf889eaafb5531721f31ee0a9f02fd58f09f65c); + tempvar res = res * point + (0xa5d4606609371577b0d17fadcd85ce659885b00245a67b038f902176d99a7c); + tempvar res = res * point + (0xfc76b77f717a5b3ecafafadf29e7f886c8ae67a3a2bb30467c440472349953); + tempvar res = res * point + (0x40fb948f8a4a10d2b2e928a5d77b481f8d3068b47fa388a3ee65609aade1a41); + tempvar res = res * point + (0x13d322a0ecbe1e785921a7aa6f4d1135e0798e72f4c055226205314b8348144); + tempvar res = res * point + (0x20096a7aa30c6c42f1d5f1ed88de275d1d1610f2548711a75fbbd72d373a50e); + tempvar res = res * point + (0x18f9cfeaf2c33e21d7c6fd9e15a3601a2fb3905588868167566e8c1f1dd30fa); + tempvar res = res * point + (0x3e3aa48bb5db9e2b0dc6d294009ecd5d4ff6255dfcdde3f5b4e545032ea9b68); + tempvar res = res * point + (0x425b03b0356b92e66ca816869a76110d68862a0d8ad76f950fdb1d5c03279d1); + tempvar res = res * point + (0x7cdb723061223f33289237c7476e737ef0bbc5e2c1ed9a70566511fc2036ba5); + tempvar res = res * point + (0x18b8b8d0f393950c9a2e674052150a328d214618049c7e2f58cbad76adbfbd5); + tempvar res = res * point + (0xf19faf3accc43b56369dccdec35dc7b49c5b8f8976764886bd16dd2e155f92); + tempvar res = res * point + (0xe08853aabc9eb934b4470bb4ae1dbbe90c61d2093516df998ca7adc98afe10); + tempvar res = res * point + (0x7736291268c775a82caea06004d53edb829be2566fc7c4053b1d850a8116cac); + tempvar res = res * point + (0x1bc1186238f0d39e1c56185a8d2bf00c90c9c89647917d60a5b762932856524); + tempvar res = res * point + (0x6cf772fa8050ad8eb87bc8f0c8fc511622b416fdb084cbc93b79501c96b0bda); + tempvar res = res * point + (0x7417da24519b4c55ec0d698ecaceeb49711aa1e7f7d907102351e73388a0fa5); + tempvar res = res * point + (0x66e1e25d1bcea87acd136f2c33498e3223fbf78bc6cc816ad6aaf68e961da0d); + tempvar res = res * point + (0x60db5bf6f060d82c169a1c4ed6c548d5e8cdb6cfd2e3257c155bf11f48ca609); + tempvar res = res * point + (0x2d5447623584d3a19e9993814622d6369248bc61813f067c4825c9b0a81551f); + tempvar res = res * point + (0xac068a1aae938e26e125b35c88a87130044bf3637bf1acd797103e7388b33a); + tempvar res = res * point + (0x3ab2d353537697d4de9c5c4c0bc31e5e776cb93181029144f6c6d4b5ea4317b); + tempvar res = res * point + (0x6ca2dd473297a2852e68ea2b83faf8f71e5cb471adcc74a858132c6a823f0c0); + tempvar res = res * point + (0x1ec5264a5287f1c6de79b3df3adbfa157e8430e594078c3fba7002a077db447); + tempvar res = res * point + (0x50ee695deb5a4e63c5dd6de35621d1c0c5a496bf41fecbaa929b2b3e23f174a); + tempvar res = res * point + (0x36f446f7e5a51114cbdd3b460431bacb5a42cd61f4690cf5e9d9f13e488318d); + tempvar res = res * point + (0x195f98a85cfe403a7d229a6eb4533a1fea641c331db75a5807711fdf1e27dac); + tempvar res = res * point + (0x63d4964faab567e795024a17032ec564ff221a421bd2e42632d3770c73dbba1); + tempvar res = res * point + (0x68d729620eca6b4d904198a0e6d241953b9b8c874a10b5ede5596146d560979); + tempvar res = res * point + (0x1137975bab819ce0cbc73714305030fcd4a185f71d46c169908460390d56d18); + tempvar res = res * point + (0xf639bcd7777c1ffd41a693ac9f5a051bd124b7edce3d568f14304c9fd90a67); + tempvar res = res * point + (0x2322f8d96071356feee538e0c53d857b1924134b94377af20ed5d0e8b3925b); + tempvar res = res * point + (0x22cf65c6bbbf76765555748cc1ae91c83ea93ca2c8b34a59332567b5b3b0cd2); + tempvar res = res * point + (0xd62eb553de83e5d51f78ddd9480d65870dc426f61153e732eb6cd62cee09cd); + tempvar res = res * point + (0x6afb39d46d5a846e9d58a6ae27e6cdd83bee29c72754cd4cd3d3cae423f5c9d); + tempvar res = res * point + (0x364889e46da58b66c827835a0c2807338eeb4431f2099f490d13bbad0777a01); + tempvar res = res * point + (0xaea6f7f915e4aec612029a9d02316baa3f6297ea4cfd38897f4c9859ec485e); + tempvar res = res * point + (0x5c180e2fbb2b51e053941d0e1611424fe60ced6d439115dd98530c8d79cca4a); + tempvar res = res * point + (0x1ab93f16e576b6a54598582eff5e2cfc33baeeb607826579680636b05046d16); + tempvar res = res * point + (0x4de47e973af27fde9ad29f812de8a04855110118eb73fcdb46865390486a287); + tempvar res = res * point + (0x50be25e516e30f96d8b420a7c494506d2cd21d64f4d5ecb67d58c2ae99bf5e0); + tempvar res = res * point + (0x2aa45ec320ea12beb804e35af3684dc981324dc9bd044592d1c408c052a4322); + tempvar res = res * point + (0x26701dfe3cc76754a4ab893fef59886a43013ea6ba648efd82fd03941fa2910); + tempvar res = res * point + (0x1773ba95dbeaab6e5e9fc79ac153d46be1e57828e92287d698a3f4f87ef4984); + tempvar res = res * point + (0x4e92d5f575fcaac9adedb4e0c3549dc18f61bc40e3752e3506f3761c32c6e3); + tempvar res = res * point + (0x580f9d95c2bd746c9210a87b0f9ed275afee1dde7a41d9ad5e69861ec0e43f6); + tempvar res = res * point + (0x3e2dbef5f162784e13b5ff4c33bcbc444ad1546922b293d6783b5de5c5aba78); + tempvar res = res * point + (0x596f89b6ca79194eb6a87c17692aa491f5b014da3cc7e5f05caf4fc1779c2dc); + tempvar res = res * point + (0x7e84842d5fff1666e01505f62661bcc822dd3fa530ebd1e4089230a4045a04f); + tempvar res = res * point + (0x5626d2ae9581d1d335bfc3863a4eaf3568ec8e70fcdae93f50a15b0cf601b6b); + tempvar res = res * point + (0x68371fc7cb3e0670a73eb3a7e773ddb63f231c26bf25bb1fc1fe6e93a7e3bd0); + tempvar res = res * point + (0x4d215dd42f87632a9cce2cb95081dc731e36796c3d2847dc96a3554231c6aef); + tempvar res = res * point + (0x421fac0e48da8e6355c07f6a64bcea96384848e8ea9a7113ab45f15b1dd15aa); + tempvar res = res * point + (0x679061e5f453c8bb1855dce8f7d61f2cb64b15d2c4e70b969ec4ead3fc6a226); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_ecdsa_y(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x23a2994e807cd40717d68f37e1d765f4354a81b12374c82f481f09f9faff31a); + tempvar res = res * point + (0x49d16d6e3720b63f7d1e74ed7fd8ea759132735c094c112c0e9dd8cc4653820); + tempvar res = res * point + (0x6c930134c99ac7200d41939eb29fb4f4e380b3f2a11437dd01d12fd9ebe8909); + tempvar res = res * point + (0x347dfb13aea22cacbef33972ad3017a5a9bab04c296295d5d372bad5e076a80); + tempvar res = res * point + (0x62e62fafc55013ee6450e33e81f6ba8524e37558ea7df7c06785f3784a3d9a8); + tempvar res = res * point + (0x23b940cd5c4f2e13c6df782f88cce6294315a1b406fda6137ed4a330bd80e37); + tempvar res = res * point + (0xf524ffcb160c3dfcc72d40b12754e2dc26433a37b8207934f489a203628137); + tempvar res = res * point + (0x603e3a8698c5c3a0b0b40a79ba0fdff25e5971f0ef0d3242ead1d1a413e443b); + tempvar res = res * point + (0xa401d8071183f0c7b4801d57de9ba6cda7bd67d7941b4507eab5a851a51b09); + tempvar res = res * point + (0x37d720cf4c846de254d76df8b6f92e93b839ee34bf528d059c3112d87080a38); + tempvar res = res * point + (0x5057b804cff6566354ca744df3686abec58eda846cafdc361a7757f58bd336e); + tempvar res = res * point + (0x76b4883fd523dff46e4e330a3dd140c3eded71524a67a56a75bd51d01d6b6ca); + tempvar res = res * point + (0x1058ff85f121d7902521abfa5f3f5c953fee83e0f58e069545f2fc0f4eda1ba); + tempvar res = res * point + (0x4eac8ffa98cdea2259f5c8ad87a797b29c9dccc28996aed0b545c075c17ebe1); + tempvar res = res * point + (0x6e7240c4a94fa3e10de72070fd2bf611af5429b7e83d53cfe1a758dee7d2a79); + tempvar res = res * point + (0x59fef071cf1eeff5303f28f4fe10b16471a2230766915d70b525d62871f6bc6); + tempvar res = res * point + (0x480d06bb4222e222e39ab600b8aadf591db4c70bae30fe756b61564eec6c7e); + tempvar res = res * point + (0x7d2292c8660492e8a1ce3db5c80b743d60cdaac7f438b6feab02f8e2aade260); + tempvar res = res * point + (0x5a593d928542a100c16f3dc5344734c9ef474609bd7099257675cef0392fab8); + tempvar res = res * point + (0x761717d47600662a250116e2403b5115f4071de6e26e8dc231840eeb4484ec3); + tempvar res = res * point + (0x4b74b468c4ef808ddcc6e582393940111941abece8a285da201171dc50525c7); + tempvar res = res * point + (0x14ef999212f88ca277747cc57dca607a1e7049232becedf47e98aca47c1d3fe); + tempvar res = res * point + (0x47b2a5ef58d331c30cfcd098ee011aaeae87781fd8ce2d7427c6b859229c523); + tempvar res = res * point + (0x59bd7fe1c9553495b493f875799d79fc86d0c26e794cce09c659c397c5c4778); + tempvar res = res * point + (0x3ede75d46d49ceb580d53f8f0553a2e370138eb76ac5e734b39a55b958c847d); + tempvar res = res * point + (0x6e0bed1b41ee1cf8667c2924ebd460772a0cd97d68eaea63c6fa77bf73f9a9e); + tempvar res = res * point + (0x739edb8cdd16692deaba7fb1bb03f55dd417891bacb39c7927969551f29cb37); + tempvar res = res * point + (0x247573f2f3fbd5386eac2d26851f9512cd57ad19773b8ca119d20852b9b6538); + tempvar res = res * point + (0x2f6efb89f27d2c0a86ec1e6f231b225caf2af9be01aca173a15fa02b11fdf24); + tempvar res = res * point + (0x75a0f99a4dec1988f19db3f8b29eeef87836eb0c3d8493913b7502cfedcef28); + tempvar res = res * point + (0x278a7c68986adbe634d44c882a1242147e276fee7962d4c69ca4c8747b3e497); + tempvar res = res * point + (0x675532b80f5aaa605219de7fe8650e24fee1c3b0d36cdf4fb605f6215afacee); + tempvar res = res * point + (0x5599e790bd325b322395d63d96cd0bd1494d4648e3d1991d54c23d24a714342); + tempvar res = res * point + (0x43545892bb5a364c0b9acd28e36371bede7fd05e59a9dcd875c44ff68275b2b); + tempvar res = res * point + (0x38db61aa2a2b03053f5c51b155bc757b0634ce89baace113391369682fc1f74); + tempvar res = res * point + (0x71b2b6b03e8cc0365ac26c4dbf71e8d426167d79f8bd1af44738890c563062a); + tempvar res = res * point + (0x3a663fc27ec3ad56da89d407089bcec0971cebcb3edf0c393112501919643d7); + tempvar res = res * point + (0x1030d58878296e14b1c5bcafe7e817ebe4aa1039aa96b9d0dd7fc915b23f42a); + tempvar res = res * point + (0xcb3335374cc2a2350fe53d2389f04952c4d634f489031742dfccca17be2e09); + tempvar res = res * point + (0x6ae3ee97ea5dcfbb7c36cffd89665baf114fae391c0367be688db09861a8ca1); + tempvar res = res * point + (0x7b16c33c4a8ffcecbd83f382469e1d00a340ceab5e7d9c0bd4fd010b83f4310); + tempvar res = res * point + (0x10f236430f20aafda49d1c3e3759c510fdf0c0c19f89df6d5d71deac88b547b); + tempvar res = res * point + (0x104b04e96151f5103118c4eb556cd79899148fd6656e73cb62f41b41d65e4d8); + tempvar res = res * point + (0x253bf2869135f4bda4029cae2819b2f468ae88530f3ea771090b2727814c494); + tempvar res = res * point + (0x65d50aa3c1d84a3deee14057eec98656a1296cdcbe32250bfdaa50ffac4c5dc); + tempvar res = res * point + (0x76323f8567119897f10d58e1552c98f5a62f03a16d3737e20fc2b0a31a3a843); + tempvar res = res * point + (0xdaee1c7b34ecb34717b7313dc4a299dd1a161447e2e0249426a6fc33a72289); + tempvar res = res * point + (0x2bfd1294f111a5a90842d19cffb97481aefbc09ab6c47d7dcf91ba228019c07); + tempvar res = res * point + (0x4f63db02e10fbe428a5dda8d9093feef46cc19568a3c8ad2fce7e7519004095); + tempvar res = res * point + (0x761a240cd8aa2f135daf0760bfc2c9d5e896e93a45426571cdad9118722e2b0); + tempvar res = res * point + (0x30a2e8ac9e6605fd722dffb4caca8c06dd4a8968a7bf41a5371cb1a07d11c00); + tempvar res = res * point + (0x5ba89e0eb3830039d0f8a9ca00acef15db22374c965b01abc49dee46270a7d); + tempvar res = res * point + (0x7e8659c39d7a102a198f0e7c3814060926ec0410330dd1a13dfadeab4e74593); + tempvar res = res * point + (0x5a00feeb391114d7b976654ab16ddf8360f05671b34d4a97da278c0aef34d76); + tempvar res = res * point + (0x33ff2d848bf237f536524da818598ae0f2516ebee526b77957448973eefacd3); + tempvar res = res * point + (0x4e0a5dd802deed7cb8d06527beb15dad32547bae77141c32473f4c8148912e3); + tempvar res = res * point + (0x776459dfedbbdfcef7a31e0f60c6480fc0676b280fdb6290859fe586d6e6106); + tempvar res = res * point + (0x59d0d8ca9ecda81081dfcae7580ab3c08a72195438c1556000c0c1dbdc08174); + tempvar res = res * point + (0x6eb66d366da57e4ae717307dfc3351579fe857c51aa82b95044473c9ed14377); + tempvar res = res * point + (0xa758a70ba6a0cbcbc65abfeca51359904f790752c3df55d42707253d8dea70); + tempvar res = res * point + (0x2046e1b4fd4c108e8f832f5bcc4dd46abf0d19ef0237beaec29d6c12fb9832e); + tempvar res = res * point + (0x472d99d1a6e1a6aef339eab1af3d53af7a8326e4d0a6bac73c3a159031c3686); + tempvar res = res * point + (0x1b0fa36439192f135c239918bf47ad14b55ced699f4582d929a60dd227b34ff); + tempvar res = res * point + (0x728dd423dbf134972cbc7c934407424743843dd438e0f229afbcca6ce34d07d); + tempvar res = res * point + (0x4e42531395d8b35bf28ccc6fab19ea1f63c635e5a3683ac9147306c1640e887); + tempvar res = res * point + (0x1ea9bd78c80641dbf20eddd35786028691180ddcf8df7c87552dee1525368ba); + tempvar res = res * point + (0x68a8c6f86a8c1ebaeb6aa72acef7fb5357b40700af043ce66d3dccee116510a); + tempvar res = res * point + (0x25c5f348c260177cd57b483694290574a936a4d585ea7cf55d114a8005b17d0); + tempvar res = res * point + (0x339b405bffb6dbb25bc0432e9c726b7f94e18cf1332ec7adfeb613345e935ab); + tempvar res = res * point + (0x23590dabe53e4ef12cba4a89b4741fcfaa232b7713d89df162031c8a627011e); + tempvar res = res * point + (0x534a4f3cf71c93023e473f12e407558b6c24b712204fd59ddc18c7bcddd571e); + tempvar res = res * point + (0x2e1b2a3c32aebc0be30addd8929c01714783aaf01be8a1d35e830646e8a54f0); + tempvar res = res * point + (0x605a244f646a825602891bf9ddffef80525010517b32625759b0bf5a7f2c386); + tempvar res = res * point + (0x4f81a946bb92416d212e4d54f2be5fa8043be6fa482b417d772bfa90be4e273); + tempvar res = res * point + (0x655038ca08eba87484bc562e7fd50ce0584363278f9d716e31c650ee6989a2b); + tempvar res = res * point + (0x44938959c2e944eb6e5c52fc4ee40b34df37905fa348fa109f6875c1aa18000); + tempvar res = res * point + (0x30b11c32e8aab0c5908651a8d445395de52d5ce6a1efe75f2ad5e2c8c854a30); + tempvar res = res * point + (0x4a92733a733f225226a3d7f69297e7ff378b62c8a369e1bbf0accfd7fb0977e); + tempvar res = res * point + (0x1345876a6ab567477c15bf37cc95b4ec39ac287887b4407593203d76f853334); + tempvar res = res * point + (0x580550e76557c8ff3368e6578a0e3bed0bac53b88fefdde88f00d7089bc175d); + tempvar res = res * point + (0x7d7faca17be1da74cf132dda889a05fce6e710af72897a941625ea07caa8b01); + tempvar res = res * point + (0x62be425458d26cfedf8ec23961cdfd9f4abeb21f1debbe87bd51469013358fe); + tempvar res = res * point + (0xd77a8e8eed7ce4931a6d2a4774c21864e2c9f468d080af9aba6756433a1a8d); + tempvar res = res * point + (0x3e850e31c0345726c1ace38537dd88a50c85d6819ae98add1bbd62b618f7a1c); + tempvar res = res * point + (0x375a5d9b11c83d06a04dc9f1908b8183adc6f04e5b2ceeaa23d3b68c973ee77); + tempvar res = res * point + (0x76640613af9ed1a125624e0c38252bee457ce87badb24fc4f961e55883d9077); + tempvar res = res * point + (0x5428ff423f2bbabcb5f54aafa03d99a320b4b255115351f50b229eae5522178); + tempvar res = res * point + (0x6dcfc3a99563a5ba4368ac4f11f43e830c5b620a7273330e841bedec0bfb5a); + tempvar res = res * point + (0x2652523cbbec2f84fae1a17397dac1965127650479e1d5ccfc6bfbfcbb67996); + tempvar res = res * point + (0xa737d6916aa6a869252d8ff294a55706e95e0844e6b047755704e37d978e09); + tempvar res = res * point + (0x2833391a62030808228d14437d6f91b31c0038c14988a23742b45e16f9b84b5); + tempvar res = res * point + (0x284f7815a7eabc1dcf56da511f7d739f1a199f8ffaf3474f645d2fc93327dc); + tempvar res = res * point + (0x1e141c5429a369996563573bf61d7f713cb7d25baadff636ba2756c65a910ee); + tempvar res = res * point + (0x60bdb98c079bd5cef216803b056afce03f6ea41934275c965d6e196240fb953); + tempvar res = res * point + (0x7f2abefac9e7f8109b0a2d25d0bd297059e45dd66798ac8b299f0a3e442dd2c); + tempvar res = res * point + (0x41776c662b44a36c7075097c14b6010cb321591a4eca2866d58252eaf9471ac); + tempvar res = res * point + (0x573b13b32161c11c9b16eff7cf93fa770a3ef667547a27503e39092aeabf73e); + tempvar res = res * point + (0x327319fcc0d34a0d64f5acab00244b43674a60bef754844fb2920c87c90cff0); + tempvar res = res * point + (0x755f0e4c374e2fa4aa7eda10041e2139a4a7793eea44f415c73ad4fcba1758); + tempvar res = res * point + (0x7b9cd3b277f00a75a17961d2d8e46e6a1838c8500c569cdcad08bd4e0cbae84); + tempvar res = res * point + (0x21f5ea8660d290f28b9300e02ed84e110d7338a74503b369ad144a11cf79f63); + tempvar res = res * point + (0x5e4b0ecc6a6c15ed16c1c04e96538880785ff9b5bff350f37e83b6fed446f14); + tempvar res = res * point + (0x3d8506e792fa9ac86ac9739d3d5bf63cfc13c456a99c8581adf590c8d9b72eb); + tempvar res = res * point + (0x1e3b6498f0daba2fd99c2ac65461c3fa519cb738b53cd6f002e97199fa4161c); + tempvar res = res * point + (0x70930735d913d54915fba20c97f07cba8f33eb8f4f81fd869699a10e83264cd); + tempvar res = res * point + (0x16a36769ee50227c564bebce3d9cd7c4ca55702a7c7ccf403075f68f05a0c2); + tempvar res = res * point + (0x3aa748723229eb8b33354e0901f50ad052b6c1006916790c979133c4442be90); + tempvar res = res * point + (0x5db8c52b6adb520496f9edd7105c92df67e8605ff4e0cc59992c3eb651ac7a4); + tempvar res = res * point + (0x4b2222d0aee638c7e5efd8ada791638ac155a01b78f3b532283574653998bb2); + tempvar res = res * point + (0x26a4b2a61f40c1ad77737b99cb27d2f3118622be64f0120907e2589d2f25ebf); + tempvar res = res * point + (0x5820792f23a13d58ddef0607950d422598bb1f21888dace88929fbe7d4828c4); + tempvar res = res * point + (0x3678de28b6896959edf5c9dc0caec59b02dfbbf54811f87939b32d0523f58bb); + tempvar res = res * point + (0x3cd13f84bb7ae6eeccc1012837d2f3e017f069e66cf047172bc70371f5aed38); + tempvar res = res * point + (0x7af8995e2ceed8841e34d44365c7ca14f5980a6a5c67b9813fa7bfd74a9c1b1); + tempvar res = res * point + (0x6d7af6524127a117184a0c12a6ff30d28b14933a4e96bb3b738d2a36db72e84); + tempvar res = res * point + (0x73200d12e733294b5cbb8ffe7fb3977088135d0b0e335135f9076d04a653c58); + tempvar res = res * point + (0x229d7fc2a1bcfbe00d5773f8dadd70a2641d8578fa73e66263b3512d3e40491); + tempvar res = res * point + (0x29889daac66c404d6491ec3a435d810a2877d885df1a3a193697b79b4af39c4); + tempvar res = res * point + (0x171f0638dedf0b69655fa9930bcbc91b257e299a6717bd8ea23ef550c8faff5); + tempvar res = res * point + (0xded0f75cd0a6a5401a954d26880eaf12050ce6458d3254c9dd6354bf66278); + tempvar res = res * point + (0x7fc7d854c9d0b3bfbf826c384b3521af0f29f975613e8ea6dc14f37d8beb54c); + tempvar res = res * point + (0x6d1c3edcf1de16a4e0ad7d8aa099a31fa2cfbf81f6d1a5798bd1ef93ff906af); + tempvar res = res * point + (0x3444c0f008988c8f600270b365ff926f016e49a54ab35bac4f3b3a42a5879b1); + tempvar res = res * point + (0x2a48058c77edcd75dd4323d9bb9eccb854009b1184fd716a8202f8627bb5447); + tempvar res = res * point + (0x56cbe248ebbc2f57ca8b943b219ba245791592f687815293a4499ef598fa9b7); + tempvar res = res * point + (0x658160ea7b654d786dc624b258c691f594e080610c2d41d6ebea0d8e3396849); + tempvar res = res * point + (0x6fcc261ded0ba97b4defc7c9bcd32b5dac89e4c08cb55cef98c6b50f5a3a289); + tempvar res = res * point + (0x7b74edd15d97b289da4040272cfc573f69a8c9a8b36d05e3e50b598508b7f9d); + tempvar res = res * point + (0x19637a12aa8b822c4a3f3551ef6c538043371a12a962de1dc25d67e0a5ee561); + tempvar res = res * point + (0x4c05a7abaaf08f21d93b2257d4f4a3ab2b44f4ac44ce0444418c864ca18470b); + tempvar res = res * point + (0x657060a10db73c4a9b6aa6288dd6164e0b50a4e6efbc2ee599a0cf4fda33b81); + tempvar res = res * point + (0x688c61ee887c1497ffcef82163f1a81bf7778f2c314ffbd325627bf0b25dc5a); + tempvar res = res * point + (0x54ab13ae1984dcc7d38c867a47f4a8cf786079ee07cc94ab5ec1962c21f638b); + tempvar res = res * point + (0xccee381472bb7dcae008316038c87a44fd9295f730e389eff14e86442c41b8); + tempvar res = res * point + (0x610bf9b7ea4557d72411ec90fb677f9a2ccb84c76f003954da4e7f439c9a84c); + tempvar res = res * point + (0x51d6322f7d582892421e977464b49c4e6e64af2438da9a7f21a061c77712dc); + tempvar res = res * point + (0x7d92a463e2aec09eb86f4647dc9ec241904135b5eb53ea272e809e58c0a271e); + tempvar res = res * point + (0x17ab90241b58bd3bd90b8a5c7f30aa9e5afeedbe1c31f21ca86c46c497b573c); + tempvar res = res * point + (0x199d80ad30b4b330fc8a063d1e87307993e1d98822a1729488ba8a586045691); + tempvar res = res * point + (0x601a139ed75acbecf557cd6513171385a119087585111c30bbc1b65cd6d30d); + tempvar res = res * point + (0x77b10e23b08892ab18cc6b14dfda6f4be5c2fec94a12e3622622376edd0d6a8); + tempvar res = res * point + (0x2a17a5c34f9f598deb5bec334fde606eaa5601df908eb5825ecf70f9cecec3f); + tempvar res = res * point + (0x7e176a66dcfd58e240c4546cd760b7e5ad02e4f0265c6a2f38d710bbdf99d55); + tempvar res = res * point + (0x27e76848780aba5b12061bffefff1710995586618a2f32792d62771d31ed519); + tempvar res = res * point + (0x43f51dfe0f1cf290c9a522e2a5e734f79d220be80348438c676295c3d429e); + tempvar res = res * point + (0xf1f93c3d919653f02fba06fcba1ab89497fff53eceff6a7d129887d5a9e3b); + tempvar res = res * point + (0x79fd6f5f9b042ece36af6b10eae2eef9de9c9dd18752eb66868a0c301015dd9); + tempvar res = res * point + (0x1958435eb08883bd69b6a56a8f3103c22f8ae206a3d4deaf4a04118b4dd6a6c); + tempvar res = res * point + (0x329230075f64ffbf631eb0c40b97d71b4dc38a08bd18b638f57e5644680068c); + tempvar res = res * point + (0x219557f1604be8622e697e986c03d2a49e40cce558a264bf4f1ebe06493eceb); + tempvar res = res * point + (0x7238f034b8c57c8b59b0f744ababf9da8229152a051d4f3b3c4995233ac1111); + tempvar res = res * point + (0x201019c76d9aa29a00e6b18a4eeac7b1322b44285c57cf4c0b68a87120b1d31); + tempvar res = res * point + (0x69d95f3c7892a1cf65b45c324be2294c4c5459e05e0feaa0b8bb98cd8bc958f); + tempvar res = res * point + (0x78aafbe80fa5ee9a846e991bf35b81567a6dcbb1b190e7ee47e53fc66422e84); + tempvar res = res * point + (0x15ba3c5a882d4dfe3e23db18368ade6b2d10ef52e34f12ce0d62e7183c10f7e); + tempvar res = res * point + (0x1a4bdaf2bff969eff8cef73e762b6346492b8d0f17b2e42956c526f625241ea); + tempvar res = res * point + (0x4adaabee9ab3c6ee7fc67a2ddc09c5185755dcc76cc3b814a6b71aa7ae542ea); + tempvar res = res * point + (0x2f47cde744314dc0502faffb0387a2e765e4354b0516ee9ab0b97a1b6c33ec2); + tempvar res = res * point + (0x90b2b18b3fc2919a55b71ad6d6fa67dda752bd02c985b59e6554f557fe4a2e); + tempvar res = res * point + (0x6eba866251e1dca38a21c8b3fad0aa3c22a45dd89884c4c68bd7ef67de64f52); + tempvar res = res * point + (0xb8dd33ef8726747fb368aedf80c2f4a720bc1b5220f4a3f0e56e2fafb7e243); + tempvar res = res * point + (0x1fac2f441d05a3b483675200cb1ebc6f4ca6ecc5ae60118fe8745f95217bf8b); + tempvar res = res * point + (0x6d28879c6f75c4ede18e1b94ffff964d08c79038fd9ba2e7873cbefb5f323db); + tempvar res = res * point + (0x28b38e0334fc06af4c94ec4f9434923d4149cc51817526597423fd4692c59ad); + tempvar res = res * point + (0x84add7269e2e41ea57aaed996f4c012ba7003ea2b994670cc0d554b7a8bd2a); + tempvar res = res * point + (0x64d672ca00300ddd5e9c9d2db433d7623bb54c8eb2db51b235a07616f1517e5); + tempvar res = res * point + (0x7f71cb5526600d15d3413ec971ee3b133718224b3cbdc68171a53d7c8684382); + tempvar res = res * point + (0x38e5702bb10256e1856a5bfb03a06b231b89a36e2f84af80bcd2d027153d847); + tempvar res = res * point + (0x1a8d4b2044b8e03b325c353f3f92283013920b92f479064b6e93159d2ed3ba0); + tempvar res = res * point + (0x68384718bd3bb23f32999f1edcb2dbddd8136259e676c4492d0cafe80ffd856); + tempvar res = res * point + (0x31a77aa370bb597dbdd0422612a7dd947aae09a5b0b17d1996f13a85103d150); + tempvar res = res * point + (0x40a9cea0394d15ef057c2923d4185f290fe2347e00529d92f927ef506e3b5e7); + tempvar res = res * point + (0x2a427d70a34b6b5237894f065ef5d60a9872ba444d47d98648b080b8ddb2a68); + tempvar res = res * point + (0xe505592d606917f898c54a7afc45b328be3cd48121aee2e8f05185a3e23e5f); + tempvar res = res * point + (0x45b4e74f19b293bc3d3d172a101e344558fcf4ccfe5eecefe31f45a45614df7); + tempvar res = res * point + (0x68486394265c9dc8fae42c8fd39605d3179c981cb44cbe33740a3deb907bc59); + tempvar res = res * point + (0x2868a08eae382c069047152ee964ac5ebd242b44267e97e578802440ef764f5); + tempvar res = res * point + (0x3159144c85f2c515eb806e5aedd908553057b69c556d226adc6e4511a35423c); + tempvar res = res * point + (0x4387edee6899d4a85883d2f8524978a4634ff82779f150b7b0c861bb315ed3f); + tempvar res = res * point + (0x68c5830832f6270a189b074d7675fcbc1d1c5cc06ce9c478bf8f4d5ac1bf40); + tempvar res = res * point + (0x399c00b8ebb398248bb1f52528d5241e7366b73c2d89f57a11dc82c530cc57c); + tempvar res = res * point + (0x3238aeb8f6bea8bcaaa1bdd5b4f917ccfad8eab031785ccdc648b47d7ea4be8); + tempvar res = res * point + (0x357bf5d87c973292381fa4320114551a837a1d6cb6e2bb0eeba534fb2e01742); + tempvar res = res * point + (0x360274f27df6eeec0b7b65fbb227a8214ac3e55cb37b1970e18489ef5b574e1); + tempvar res = res * point + (0x1cb6e2fba23730f5bf9d8e726569b6e8bf6b5ffe8520339503c5469cc3713a2); + tempvar res = res * point + (0x3924324af1994280f87f289fdae0b9a2d8cb9914ec37d319c18daf029211815); + tempvar res = res * point + (0x3c4ad04a5a057e4411487858dbe16af8e3fc065ef7400749ffdc248bdb25bc5); + tempvar res = res * point + (0x50c92b3e6848a21001be2a268615e1e26cb4918ecb09640efaaf1d8b71568fb); + tempvar res = res * point + (0x47d21828025d0cbab84084965a49dd14c7833aac562b55de808a94777df2ea3); + tempvar res = res * point + (0x6207c6a2fd70c19a10430566c9efaad95eab8cbddf308f0057c81f3155a25a0); + tempvar res = res * point + (0x2d4acebd804035257147ad8d8419a5f5762b4b543c4846ef9acf41856e672ee); + tempvar res = res * point + (0x78f49c214872b5cce18ead0207a165fb741ea818a69cfe9647737323f70f4f5); + tempvar res = res * point + (0x22aa8c5c5ff26f9a0edc768ae32ff4f71a71205b4e83cfa0cc687a1e02566ba); + tempvar res = res * point + (0x5dd2e0680c7eff25211f31d3c30a9f454500d6eb09d46d87a75a42b190203cb); + tempvar res = res * point + (0x5ac4bcdb9c14634ab83c13a30822ddbabc54248cf1177b11cc2aed24d2d32f5); + tempvar res = res * point + (0x77dee5f03389585fad0d1f2a8accfa4cb985344891b8befaee42f3462cb48a); + tempvar res = res * point + (0x737dba18eb055a12d842bfae32fd146dcd2d7bb932a2591aa864458d6d652); + tempvar res = res * point + (0x23bf372b0b59abf250463697ef4b2096eb1c9674613918b4d0c79aa10d9fd59); + tempvar res = res * point + (0x73724274fdd351c378e597da1615dc51058e14994464cb7b318766199ac2a35); + tempvar res = res * point + (0x2e14e83be58cde3ed5f3fec8ba6462493a4a2f0f7d6c846006220eccd49ef25); + tempvar res = res * point + (0x4846d310812d81ffda3731e8289005e2f0e05411e76b1c84332c3ee9e831afb); + tempvar res = res * point + (0x160abeb38bc4f22af5fe618c19c77c39903007900722bdbdeaee059f31544c8); + tempvar res = res * point + (0x264a535ae10091157ed59b04955dff66897af74cae20456bb830336b803ae47); + tempvar res = res * point + (0x316ce6b23e720b8302e2d4bd968c0f140f69930e46a54784a7cee7e0b8a0c8); + tempvar res = res * point + (0x775d95a0beb287c98663a3f9a9c577ffc67c1fe6fbe2db5b08829a2c3eac922); + tempvar res = res * point + (0x2353c4a418bdc1e461be162140cc69c26eb9d99f08924991f85058f87f6df41); + tempvar res = res * point + (0x181ef9cde124459dc0e2aaf93512abd49a10328fb93dfc4d49ab671db64bbc4); + tempvar res = res * point + (0x7ff76956e0cd2b490b47a0a0497df5f874cf47f54c45f08101256429b48460); + tempvar res = res * point + (0x318e5a52d685eaa06e0f39159a344b3d97b52688b671d133954aeff0bc17707); + tempvar res = res * point + (0x7616cfc6834643d4b95ed1cfec036f816a7c3d3b9800f301f98ddf341712ebf); + tempvar res = res * point + (0x59869515fb57ea7733567e5d849bcaa00c00e0f86f4ebbd2c7a6f4c0c77692b); + tempvar res = res * point + (0xb806f4e19770279fab5427b8eaf5bc68bf984d6ccea1e878a7aaf32c9975d9); + tempvar res = res * point + (0x4fb0c93fe30da048576fe5e839483636218dfdda3d05f1d68847a4c0167597f); + tempvar res = res * point + (0x685af2d7bbf30cd0c5c3d41c430a8657eeafeeb4596165faaa73d802087ad80); + tempvar res = res * point + (0x6f617dce150ea148cb8c7488fe4caa920b2000bc8122cce1891e4b76cddc9d4); + tempvar res = res * point + (0x47f02fc512b153462379f4f793c7cab9e659bfdb07d3439d29039f566b7236d); + tempvar res = res * point + (0x4ce0a14a5a9c30a38062eb8870eeb4ff3562db743c0f3eede2e3d3862a2eb7c); + tempvar res = res * point + (0x7b077d27c7007656025224fa4e528b4c4261f43c3da1e42bd1349403af55cbb); + tempvar res = res * point + (0x50f5f6adbf0b9abc6e231b855018f4ec806a4f199cc511bed5c423ebef298e4); + tempvar res = res * point + (0x5fcfeb78685abb1ce610e516ab7e2aa210fd90844c8d1c89cd798f3d71bbcb3); + tempvar res = res * point + (0x4255a568f4597862e1dfe0c391b97059d179d7eb4d868f61364835e5028f9dd); + tempvar res = res * point + (0x206d7f23d0fe1b1c0967486ebb792d7fdf5b1691d2c2f9306e211d3b849526b); + tempvar res = res * point + (0xc61c74cc988663ee09f4c725d5b1f04549bd342d3550ce17427ac75592b637); + tempvar res = res * point + (0x175a904681c7a91856bf7fcf8410d2c19eb8705267914489664a1ea2af5b8fe); + tempvar res = res * point + (0x1bd842a4ec97e1489ceb542bd3161e5a00ce431547bfadfbced954d993b0a11); + tempvar res = res * point + (0x14899e0f97aac917d46ce5e9ddf11194fb846d2c52726af4085f27c570a98a9); + tempvar res = res * point + (0x842955243a56778a332ba9be0b22b2af62efaa50068d3078675fb76c225e76); + tempvar res = res * point + (0x6dff267c3bbce68474294da908df4f5cf2a4160c638f7cb45c098057e968f44); + tempvar res = res * point + (0x72c0dd24a576b47a84cdd1a20227773b5621f85b781c288625e3368e1cf738a); + tempvar res = res * point + (0x728771890334d0c9b0f400543bdc13ea6890497bc87c509a04f8014916c13a5); + tempvar res = res * point + (0x30632b3865a272a1a00270430744ee90b40ff16e1fc44515876ce8e36215ca0); + tempvar res = res * point + (0x76d656560dac569683063278ea2dee47d935501c2195ff53b741efe81509892); + tempvar res = res * point + (0x1dbdc2ea2e555309578eeb2352fbc47c8fd5ed77cc09903b577700f9a4d1be1); + tempvar res = res * point + (0x119bcf6402ad9953851bac8e318d50af699b0cc75e2597aff0a2cc521975aa4); + tempvar res = res * point + (0x7c3234094dff9a45064a5b9abd0667c04dd76c62722984f7f8475e7cc344c06); + tempvar res = res * point + (0x1495d40cf3f13c5fc90653c2b2f02e0b833790c07576286d3127f745ea920ae); + tempvar res = res * point + (0x40f019a18b8097235264cb8efee7d149321a199ccd32ffac43b5a778dfadda1); + tempvar res = res * point + (0x4e23809ce49747990e43b2d976083dc84d67e75cf22e5a76ad5b7a2dca50b3d); + tempvar res = res * point + (0x7f0a3bec1d34f2fd632993a3d9c6432401cec25ad9d6196b909f3672980bd05); + tempvar res = res * point + (0x9460aa25f77fc10cfcc4579e2011e39ce477a32a768aa553201e556ed2bbe1); + tempvar res = res * point + (0x611384709c407d85c93256b6aff04c4ac515450c70cf507994165abfe2347b); + tempvar res = res * point + (0x2065bc7a4aa38d5fe86f9b593ccd060f8d4a5a19a9ca8b182c32199a4bd27be); + tempvar res = res * point + (0x9969a08d753e885857a5696d1cafd39f62bb193acc99089df76c240acd2fc0); + tempvar res = res * point + (0x6df73a948c95439f3230282814ba7e26203cfdc725901e4971ad9cff4db4396); + tempvar res = res * point + (0x1cdf0446663046f35c26d51e45a5233a93c51f4f7f1985dfe130dd67addefa3); + tempvar res = res * point + (0x59cbe680183d1dc3161ee7f945f38ab9461a5293748b2b7be84899e62c9860b); + tempvar res = res * point + (0x5030fda0c29a929e6cd634b9f3d1bf975c363012cfb439cae13495f8ce10225); + tempvar res = res * point + (0x49aadcf98ef59c0e5d2097845949988862b96194abc8c5453f056f232482892); + tempvar res = res * point + (0x319c68159cdf104c2543486ff784860f302187d77effb9a5fefe4e16f0ddc2c); + tempvar res = res * point + (0x575531b404cdba72a63dbbd17aef7d9ae00f73eca7c6dcdaf5e0778c921be41); + tempvar res = res * point + (0x35ca7fa56aa38486833a976804899ba3c97fdaa0a23056cd2dc9bfdbcdd2e31); + tempvar res = res * point + (0x47dc0e209ee8d0b67f63d9e63837ff2ab462c4839bc14a1a3e802327ff0e31f); + tempvar res = res * point + (0x744bdf0c2894072564f6eca2d26efc03ef001bc6e78b34bf6be3a1a91fd90fc); + tempvar res = res * point + (0x73c57ecea0c64a9bc087e50a97a28df974b294c52a0ef5854f53f69ef6773af); + tempvar res = res * point + (0x7dd14b0299ff6064a96fe97e086df3f64a4c7e8b4a58a5bd5fe1b9cf7c61e7c); + tempvar res = res * point + (0x562f636b49796e469dfe9e6748c4468f340e8f69e3f79cfe6925a261198dbb3); + return (res=res); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/public_verify.cairo b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/public_verify.cairo new file mode 100644 index 00000000..399b2289 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/public_verify.cairo @@ -0,0 +1,124 @@ +from starkware.cairo.common.math import assert_le, assert_nn, assert_nn_le +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.autogenerated import ( + BITWISE__RATIO, + CPU_COMPONENT_HEIGHT, + EC_OP_BUILTIN_RATIO, + ECDSA_BUILTIN_RATIO, + LAYOUT_CODE, + PEDERSEN_BUILTIN_RATIO, + RC_BUILTIN_RATIO, +) +from starkware.cairo.stark_verifier.air.public_input import PublicInput, SegmentInfo +from starkware.cairo.stark_verifier.air.public_memory import AddrValue +from starkware.cairo.stark_verifier.core.domains import StarkDomains + +const MAX_LOG_N_STEPS = 50; +const MAX_RANGE_CHECK = 2 ** 16 - 1; + +namespace segments { + const PROGRAM = 0; + const EXECUTION = 1; + const OUTPUT = 2; + const PEDERSEN = 3; + const RANGE_CHECK = 4; + const ECDSA = 5; + const BITWISE = 6; + const EC_OP = 7; + const N_SEGMENTS = 8; +} + +const INITIAL_PC = 1; +const FINAL_PC = INITIAL_PC + 4; + +// Returns a zero-terminated list of builtins supported by this layout. +func get_layout_builtins() -> (n_builtins: felt, builtins: felt*) { + let (builtins_address) = get_label_location(data); + let n_builtins = 6; + assert builtins_address[n_builtins] = 0; + return (n_builtins=n_builtins, builtins=builtins_address); + + data: + dw 'output'; + dw 'pedersen'; + dw 'range_check'; + dw 'ecdsa'; + dw 'bitwise'; + dw 'ec_op'; + dw 0; +} + +// Verifies that the public input represents a valid Cairo statement: there exists a memory +// assignment and a valid corresponding program trace satisfying the public memory requirements. +// +// This function verifies that: +// * The 16-bit range-checks are properly configured (0 <= rc_min <= rc_max < 2^16). +// * The layout is valid. +// * The segments for the builtins do not exceed their maximum length (thus, +// when these builtins are properly used in the program, they will function correctly). +// +// This function DOES NOT verify anything regarding the public memory. This should be verified +// by the user. In particular, it is not validated that: +// * [initial_fp - 2] = initial_fp, which is required to guarantee the "safe call" +// feature (that is, all "call" instructions will return, even if the called function is +// malicious). It guarantees that it's not possible to create a cycle in the call stack. +// * the arguments and return values for main() are properly set (e.g., the segment +// pointers). +// * the requested program is loaded, starting from initial_pc. +// * final_pc points to the end of the program. +// * program output is valid in any sense. +// * The continuous pages are consistent. See public_memory.cairo. +func public_input_validate{range_check_ptr}( + air: AirWithLayout*, public_input: PublicInput*, stark_domains: StarkDomains* +) { + assert_nn_le(public_input.log_n_steps, MAX_LOG_N_STEPS); + let (n_steps) = pow(2, public_input.log_n_steps); + assert n_steps * CPU_COMPONENT_HEIGHT = stark_domains.trace_domain_size; + + assert_le(0, public_input.rc_min); + assert_le(public_input.rc_min, public_input.rc_max); + assert_le(public_input.rc_max, MAX_RANGE_CHECK); + + assert public_input.layout = LAYOUT_CODE; + + // Segments. + tempvar n_output_uses = ( + public_input.segments[segments.OUTPUT].stop_ptr - + public_input.segments[segments.OUTPUT].begin_addr); + assert_nn(n_output_uses); + + assert public_input.n_segments = segments.N_SEGMENTS; + tempvar n_pedersen_copies = n_steps / PEDERSEN_BUILTIN_RATIO; + tempvar n_pedersen_uses = ( + public_input.segments[segments.PEDERSEN].stop_ptr - + public_input.segments[segments.PEDERSEN].begin_addr) / 3; + // Note that the following call implies that n_steps is divisible by PEDERSEN_BUILTIN_RATIO. + assert_nn_le(n_pedersen_uses, n_pedersen_copies); + + tempvar n_range_check_copies = n_steps / RC_BUILTIN_RATIO; + tempvar n_range_check_uses = ( + public_input.segments[segments.RANGE_CHECK].stop_ptr - + public_input.segments[segments.RANGE_CHECK].begin_addr); + assert_nn_le(n_range_check_uses, n_range_check_copies); + + tempvar n_ecdsa_copies = n_steps / ECDSA_BUILTIN_RATIO; + tempvar n_ecdsa_uses = ( + public_input.segments[segments.ECDSA].stop_ptr - + public_input.segments[segments.ECDSA].begin_addr) / 2; + assert_nn_le(n_ecdsa_uses, n_ecdsa_copies); + + tempvar n_bitwise_copies = n_steps / BITWISE__RATIO; + tempvar n_bitwise_uses = ( + public_input.segments[segments.BITWISE].stop_ptr - + public_input.segments[segments.BITWISE].begin_addr) / 5; + assert_nn_le(n_bitwise_uses, n_bitwise_copies); + + tempvar n_ec_op_copies = n_steps / EC_OP_BUILTIN_RATIO; + tempvar n_ec_op_uses = ( + public_input.segments[segments.EC_OP].stop_ptr - + public_input.segments[segments.EC_OP].begin_addr) / 7; + assert_nn_le(n_ec_op_uses, n_ec_op_copies); + return (); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/verify.cairo b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/verify.cairo new file mode 100644 index 00000000..7b1ce2cc --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/perpetual_with_bitwise/verify.cairo @@ -0,0 +1,75 @@ +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.hash import HashBuiltin +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layout import AirWithLayout, Layout +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.autogenerated import ( + CONSTRAINT_DEGREE, + MASK_SIZE, + N_CONSTRAINTS, + N_INTERACTION_COLUMNS, + N_ORIGINAL_COLUMNS, + eval_oods_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.composition import ( + traces_eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.global_values import ( + InteractionElements, +) +from starkware.cairo.stark_verifier.air.layouts.perpetual_with_bitwise.public_verify import ( + public_input_validate, +) +from starkware.cairo.stark_verifier.air.oods import eval_oods_boundary_poly_at_points +from starkware.cairo.stark_verifier.air.public_input import public_input_hash +from starkware.cairo.stark_verifier.air.traces import ( + traces_commit, + traces_config_validate, + traces_decommit, +) +from starkware.cairo.stark_verifier.core.air_interface import AirInstance +from starkware.cairo.stark_verifier.core.stark import StarkProof, verify_stark_proof + +// Builds an AirInstance object to use for STARK verification. See AirInstance at +// air_interface.cairo. +func build_air() -> (air: AirWithLayout*) { + let (arg_public_input_hash) = get_label_location(public_input_hash); + let (arg_public_input_validate) = get_label_location(public_input_validate); + let (arg_traces_config_validate) = get_label_location(traces_config_validate); + let (arg_traces_commit) = get_label_location(traces_commit); + let (arg_traces_decommit) = get_label_location(traces_decommit); + let (arg_traces_eval_composition_polynomial) = get_label_location( + traces_eval_composition_polynomial + ); + let (arg_eval_oods_boundary_poly_at_points) = get_label_location( + eval_oods_boundary_poly_at_points + ); + let (arg_eval_oods_polynomial) = get_label_location(eval_oods_polynomial); + + tempvar air = new AirWithLayout(air=AirInstance( + public_input_hash=arg_public_input_hash, + public_input_validate=arg_public_input_validate, + traces_config_validate=arg_traces_config_validate, + traces_commit=arg_traces_commit, + traces_decommit=arg_traces_decommit, + traces_eval_composition_polynomial=arg_traces_eval_composition_polynomial, + eval_oods_boundary_poly_at_points=arg_eval_oods_boundary_poly_at_points, + n_constraints=N_CONSTRAINTS, + constraint_degree=CONSTRAINT_DEGREE, + mask_size=MASK_SIZE, + ), + layout=Layout( + eval_oods_polynomial=arg_eval_oods_polynomial, + n_original_columns=N_ORIGINAL_COLUMNS, + n_interaction_columns=N_INTERACTION_COLUMNS, + n_interaction_elements=InteractionElements.SIZE, + ), + ); + return (air=air); +} + +func verify_proof{range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*}( + proof: StarkProof*, security_bits: felt +) -> () { + let (air) = build_air(); + return verify_stark_proof(air=&air.air, proof=proof, security_bits=security_bits); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/recursive/autogenerated.cairo b/src/starkware/cairo/stark_verifier/air/layouts/recursive/autogenerated.cairo new file mode 100644 index 00000000..366e623d --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/recursive/autogenerated.cairo @@ -0,0 +1,11044 @@ +from starkware.cairo.stark_verifier.air.layouts.recursive.global_values import GlobalValues +from starkware.cairo.stark_verifier.air.oods import OodsGlobalValues +from starkware.cairo.common.pow import pow + +const N_CONSTRAINTS = 242; +const MASK_SIZE = 596; +const N_ORIGINAL_COLUMNS = 8; +const N_INTERACTION_COLUMNS = 3; +const PUBLIC_MEMORY_STEP = 16; +const HAS_DILUTED_POOL = 1; +const DILUTED_SPACING = 4; +const DILUTED_N_BITS = 16; +const PEDERSEN_BUILTIN_RATIO = 256; +const PEDERSEN_BUILTIN_REPETITIONS = 1; +const RC_BUILTIN_RATIO = 8; +const RC_N_PARTS = 8; +const BITWISE__RATIO = 16; +const BITWISE__TOTAL_N_BITS = 251; +const KECCAK__RATIO = 2048; +const HAS_OUTPUT_BUILTIN = 1; +const HAS_PEDERSEN_BUILTIN = 1; +const HAS_RANGE_CHECK_BUILTIN = 1; +const HAS_ECDSA_BUILTIN = 0; +const HAS_BITWISE_BUILTIN = 1; +const HAS_KECCAK_BUILTIN = 1; +const HAS_EC_OP_BUILTIN = 0; +const LAYOUT_CODE = 0x726563757273697665; +const CONSTRAINT_DEGREE = 2; +const CPU_COMPONENT_HEIGHT = 16; +const LOG_CPU_COMPONENT_HEIGHT = 4; +const MEMORY_STEP = 2; +const IS_DYNAMIC_AIR = 0; + +func eval_composition_polynomial{range_check_ptr}( + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_generator: felt, + global_values: GlobalValues*, +) -> (res: felt) { + alloc_locals; + + // Compute powers. + let (local pow0) = pow(point, global_values.trace_length / 524288); + let (local pow1) = pow(point, global_values.trace_length / 32768); + let (local pow2) = pow(point, global_values.trace_length / 8192); + local pow3 = pow2 * pow2; + local pow4 = pow3 * pow3; + let (local pow5) = pow(point, global_values.trace_length / 256); + local pow6 = pow5 * pow5; + local pow7 = pow6 * pow6; + let (local pow8) = pow(point, global_values.trace_length / 16); + local pow9 = pow8 * pow8; + local pow10 = pow9 * pow9; + local pow11 = pow10 * pow10; + local pow12 = pow11 * pow11; + let (local pow13) = pow(trace_generator, global_values.trace_length / 524288); + local pow14 = pow13 * pow13; + local pow15 = pow13 * pow14; + local pow16 = pow13 * pow15; + local pow17 = pow13 * pow16; + local pow18 = pow13 * pow17; + local pow19 = pow13 * pow18; + local pow20 = pow13 * pow19; + local pow21 = pow13 * pow20; + local pow22 = pow13 * pow21; + local pow23 = pow13 * pow22; + local pow24 = pow13 * pow23; + local pow25 = pow13 * pow24; + local pow26 = pow13 * pow25; + local pow27 = pow13 * pow26; + local pow28 = pow13 * pow27; + local pow29 = pow20 * pow28; + local pow30 = pow20 * pow29; + local pow31 = pow20 * pow30; + local pow32 = pow20 * pow31; + local pow33 = pow20 * pow32; + local pow34 = pow20 * pow33; + local pow35 = pow20 * pow34; + local pow36 = pow20 * pow35; + local pow37 = pow20 * pow36; + local pow38 = pow20 * pow37; + local pow39 = pow20 * pow38; + local pow40 = pow20 * pow39; + local pow41 = pow20 * pow40; + local pow42 = pow20 * pow41; + local pow43 = pow20 * pow42; + local pow44 = pow20 * pow43; + local pow45 = pow20 * pow44; + local pow46 = pow20 * pow45; + local pow47 = pow20 * pow46; + local pow48 = pow20 * pow47; + local pow49 = pow20 * pow48; + local pow50 = pow20 * pow49; + local pow51 = pow20 * pow50; + local pow52 = pow20 * pow51; + local pow53 = pow20 * pow52; + local pow54 = pow20 * pow53; + local pow55 = pow20 * pow54; + local pow56 = pow20 * pow55; + local pow57 = pow20 * pow56; + local pow58 = pow20 * pow57; + local pow59 = pow20 * pow58; + local pow60 = pow20 * pow59; + local pow61 = pow20 * pow60; + local pow62 = pow20 * pow61; + local pow63 = pow20 * pow62; + local pow64 = pow20 * pow63; + local pow65 = pow20 * pow64; + local pow66 = pow20 * pow65; + local pow67 = pow20 * pow66; + local pow68 = pow20 * pow67; + local pow69 = pow20 * pow68; + local pow70 = pow20 * pow69; + local pow71 = pow20 * pow70; + local pow72 = pow20 * pow71; + local pow73 = pow20 * pow72; + local pow74 = pow20 * pow73; + local pow75 = pow20 * pow74; + local pow76 = pow20 * pow75; + local pow77 = pow20 * pow76; + local pow78 = pow20 * pow77; + local pow79 = pow20 * pow78; + local pow80 = pow20 * pow79; + local pow81 = pow20 * pow80; + local pow82 = pow20 * pow81; + local pow83 = pow20 * pow82; + local pow84 = pow20 * pow83; + local pow85 = pow20 * pow84; + local pow86 = pow20 * pow85; + local pow87 = pow20 * pow86; + local pow88 = pow29 * pow87; + local pow89 = pow20 * pow88; + local pow90 = pow20 * pow89; + local pow91 = pow20 * pow90; + local pow92 = pow20 * pow91; + local pow93 = pow20 * pow92; + local pow94 = pow20 * pow93; + local pow95 = pow20 * pow94; + local pow96 = pow20 * pow95; + local pow97 = pow20 * pow96; + local pow98 = pow20 * pow97; + local pow99 = pow20 * pow98; + local pow100 = pow20 * pow99; + local pow101 = pow20 * pow100; + local pow102 = pow20 * pow101; + local pow103 = pow20 * pow102; + local pow104 = pow20 * pow103; + local pow105 = pow20 * pow104; + local pow106 = pow20 * pow105; + local pow107 = pow20 * pow106; + local pow108 = pow20 * pow107; + local pow109 = pow20 * pow108; + local pow110 = pow20 * pow109; + local pow111 = pow20 * pow110; + local pow112 = pow20 * pow111; + local pow113 = pow20 * pow112; + local pow114 = pow20 * pow113; + local pow115 = pow20 * pow114; + local pow116 = pow20 * pow115; + local pow117 = pow20 * pow116; + local pow118 = pow29 * pow117; + local pow119 = pow20 * pow118; + local pow120 = pow20 * pow119; + local pow121 = pow20 * pow120; + local pow122 = pow20 * pow121; + local pow123 = pow20 * pow122; + local pow124 = pow20 * pow123; + local pow125 = pow20 * pow124; + local pow126 = pow20 * pow125; + local pow127 = pow20 * pow126; + local pow128 = pow20 * pow127; + local pow129 = pow20 * pow128; + local pow130 = pow20 * pow129; + local pow131 = pow20 * pow130; + local pow132 = pow20 * pow131; + local pow133 = pow20 * pow132; + local pow134 = pow20 * pow133; + local pow135 = pow20 * pow134; + local pow136 = pow20 * pow135; + local pow137 = pow20 * pow136; + local pow138 = pow20 * pow137; + local pow139 = pow20 * pow138; + local pow140 = pow20 * pow139; + local pow141 = pow20 * pow140; + local pow142 = pow20 * pow141; + local pow143 = pow20 * pow142; + local pow144 = pow20 * pow143; + local pow145 = pow20 * pow144; + local pow146 = pow20 * pow145; + local pow147 = pow20 * pow146; + local pow148 = pow29 * pow147; + local pow149 = pow20 * pow148; + local pow150 = pow20 * pow149; + local pow151 = pow20 * pow150; + local pow152 = pow20 * pow151; + local pow153 = pow20 * pow152; + local pow154 = pow20 * pow153; + local pow155 = pow20 * pow154; + local pow156 = pow20 * pow155; + local pow157 = pow20 * pow156; + local pow158 = pow20 * pow157; + local pow159 = pow20 * pow158; + local pow160 = pow20 * pow159; + local pow161 = pow20 * pow160; + local pow162 = pow20 * pow161; + local pow163 = pow20 * pow162; + local pow164 = pow20 * pow163; + local pow165 = pow20 * pow164; + local pow166 = pow20 * pow165; + local pow167 = pow20 * pow166; + local pow168 = pow20 * pow167; + local pow169 = pow20 * pow168; + local pow170 = pow20 * pow169; + local pow171 = pow20 * pow170; + local pow172 = pow20 * pow171; + local pow173 = pow20 * pow172; + local pow174 = pow20 * pow173; + local pow175 = pow20 * pow174; + local pow176 = pow20 * pow175; + local pow177 = pow20 * pow176; + local pow178 = pow29 * pow177; + local pow179 = pow20 * pow178; + local pow180 = pow20 * pow179; + local pow181 = pow20 * pow180; + local pow182 = pow20 * pow181; + local pow183 = pow20 * pow182; + local pow184 = pow20 * pow183; + local pow185 = pow20 * pow184; + local pow186 = pow20 * pow185; + local pow187 = pow20 * pow186; + local pow188 = pow20 * pow187; + local pow189 = pow20 * pow188; + local pow190 = pow20 * pow189; + local pow191 = pow20 * pow190; + local pow192 = pow20 * pow191; + local pow193 = pow20 * pow192; + local pow194 = pow20 * pow193; + local pow195 = pow20 * pow194; + local pow196 = pow20 * pow195; + local pow197 = pow20 * pow196; + local pow198 = pow20 * pow197; + local pow199 = pow20 * pow198; + local pow200 = pow20 * pow199; + local pow201 = pow20 * pow200; + local pow202 = pow20 * pow201; + local pow203 = pow20 * pow202; + local pow204 = pow20 * pow203; + local pow205 = pow20 * pow204; + local pow206 = pow20 * pow205; + local pow207 = pow20 * pow206; + local pow208 = pow29 * pow207; + local pow209 = pow20 * pow208; + local pow210 = pow20 * pow209; + local pow211 = pow20 * pow210; + local pow212 = pow20 * pow211; + local pow213 = pow20 * pow212; + local pow214 = pow20 * pow213; + local pow215 = pow20 * pow214; + local pow216 = pow20 * pow215; + local pow217 = pow20 * pow216; + local pow218 = pow20 * pow217; + local pow219 = pow20 * pow218; + local pow220 = pow20 * pow219; + local pow221 = pow20 * pow220; + local pow222 = pow20 * pow221; + local pow223 = pow20 * pow222; + local pow224 = pow20 * pow223; + local pow225 = pow20 * pow224; + local pow226 = pow20 * pow225; + local pow227 = pow20 * pow226; + local pow228 = pow20 * pow227; + local pow229 = pow20 * pow228; + local pow230 = pow20 * pow229; + local pow231 = pow20 * pow230; + local pow232 = pow20 * pow231; + local pow233 = pow20 * pow232; + local pow234 = pow20 * pow233; + local pow235 = pow20 * pow234; + local pow236 = pow20 * pow235; + local pow237 = pow20 * pow236; + local pow238 = pow29 * pow237; + local pow239 = pow20 * pow238; + local pow240 = pow20 * pow239; + local pow241 = pow20 * pow240; + local pow242 = pow20 * pow241; + local pow243 = pow20 * pow242; + local pow244 = pow20 * pow243; + local pow245 = pow20 * pow244; + local pow246 = pow20 * pow245; + local pow247 = pow20 * pow246; + local pow248 = pow20 * pow247; + local pow249 = pow20 * pow248; + local pow250 = pow20 * pow249; + local pow251 = pow20 * pow250; + local pow252 = pow20 * pow251; + local pow253 = pow20 * pow252; + local pow254 = pow20 * pow253; + local pow255 = pow20 * pow254; + local pow256 = pow20 * pow255; + local pow257 = pow20 * pow256; + local pow258 = pow20 * pow257; + local pow259 = pow20 * pow258; + local pow260 = pow20 * pow259; + local pow261 = pow20 * pow260; + local pow262 = pow20 * pow261; + local pow263 = pow20 * pow262; + local pow264 = pow20 * pow263; + local pow265 = pow20 * pow264; + local pow266 = pow20 * pow265; + local pow267 = pow20 * pow266; + local pow268 = pow29 * pow267; + local pow269 = pow20 * pow268; + local pow270 = pow20 * pow269; + local pow271 = pow20 * pow270; + local pow272 = pow20 * pow271; + local pow273 = pow20 * pow272; + local pow274 = pow20 * pow273; + local pow275 = pow20 * pow274; + local pow276 = pow20 * pow275; + local pow277 = pow20 * pow276; + local pow278 = pow20 * pow277; + local pow279 = pow20 * pow278; + local pow280 = pow20 * pow279; + local pow281 = pow20 * pow280; + local pow282 = pow20 * pow281; + local pow283 = pow20 * pow282; + local pow284 = pow20 * pow283; + local pow285 = pow20 * pow284; + local pow286 = pow20 * pow285; + local pow287 = pow20 * pow286; + local pow288 = pow20 * pow287; + local pow289 = pow20 * pow288; + local pow290 = pow20 * pow289; + local pow291 = pow20 * pow290; + local pow292 = pow20 * pow291; + local pow293 = pow20 * pow292; + local pow294 = pow20 * pow293; + local pow295 = pow20 * pow294; + local pow296 = pow20 * pow295; + local pow297 = pow20 * pow296; + local pow298 = pow29 * pow297; + local pow299 = pow20 * pow298; + local pow300 = pow20 * pow299; + local pow301 = pow20 * pow300; + local pow302 = pow20 * pow301; + local pow303 = pow20 * pow302; + local pow304 = pow20 * pow303; + local pow305 = pow20 * pow304; + local pow306 = pow20 * pow305; + local pow307 = pow20 * pow306; + local pow308 = pow20 * pow307; + local pow309 = pow20 * pow308; + local pow310 = pow20 * pow309; + local pow311 = pow20 * pow310; + local pow312 = pow20 * pow311; + local pow313 = pow20 * pow312; + local pow314 = pow20 * pow313; + local pow315 = pow20 * pow314; + local pow316 = pow20 * pow315; + local pow317 = pow20 * pow316; + local pow318 = pow20 * pow317; + local pow319 = pow20 * pow318; + local pow320 = pow20 * pow319; + local pow321 = pow20 * pow320; + local pow322 = pow20 * pow321; + local pow323 = pow20 * pow322; + local pow324 = pow20 * pow323; + local pow325 = pow20 * pow324; + local pow326 = pow20 * pow325; + local pow327 = pow20 * pow326; + local pow328 = pow29 * pow327; + local pow329 = pow20 * pow328; + local pow330 = pow20 * pow329; + local pow331 = pow20 * pow330; + local pow332 = pow20 * pow331; + local pow333 = pow20 * pow332; + local pow334 = pow20 * pow333; + local pow335 = pow20 * pow334; + local pow336 = pow20 * pow335; + local pow337 = pow20 * pow336; + local pow338 = pow20 * pow337; + local pow339 = pow20 * pow338; + local pow340 = pow20 * pow339; + local pow341 = pow20 * pow340; + local pow342 = pow20 * pow341; + local pow343 = pow20 * pow342; + local pow344 = pow20 * pow343; + local pow345 = pow20 * pow344; + local pow346 = pow20 * pow345; + local pow347 = pow20 * pow346; + local pow348 = pow20 * pow347; + local pow349 = pow20 * pow348; + local pow350 = pow20 * pow349; + local pow351 = pow20 * pow350; + local pow352 = pow20 * pow351; + local pow353 = pow20 * pow352; + local pow354 = pow20 * pow353; + local pow355 = pow20 * pow354; + local pow356 = pow20 * pow355; + local pow357 = pow20 * pow356; + local pow358 = pow29 * pow357; + local pow359 = pow20 * pow358; + local pow360 = pow20 * pow359; + local pow361 = pow20 * pow360; + local pow362 = pow20 * pow361; + local pow363 = pow20 * pow362; + local pow364 = pow20 * pow363; + local pow365 = pow20 * pow364; + local pow366 = pow20 * pow365; + local pow367 = pow20 * pow366; + local pow368 = pow20 * pow367; + local pow369 = pow20 * pow368; + local pow370 = pow20 * pow369; + local pow371 = pow20 * pow370; + local pow372 = pow20 * pow371; + local pow373 = pow20 * pow372; + local pow374 = pow20 * pow373; + local pow375 = pow20 * pow374; + local pow376 = pow20 * pow375; + local pow377 = pow20 * pow376; + local pow378 = pow20 * pow377; + local pow379 = pow20 * pow378; + local pow380 = pow20 * pow379; + local pow381 = pow20 * pow380; + local pow382 = pow20 * pow381; + local pow383 = pow20 * pow382; + local pow384 = pow20 * pow383; + local pow385 = pow20 * pow384; + local pow386 = pow20 * pow385; + local pow387 = pow20 * pow386; + local pow388 = pow29 * pow387; + local pow389 = pow20 * pow388; + local pow390 = pow20 * pow389; + local pow391 = pow20 * pow390; + local pow392 = pow20 * pow391; + local pow393 = pow20 * pow392; + local pow394 = pow20 * pow393; + local pow395 = pow20 * pow394; + local pow396 = pow20 * pow395; + local pow397 = pow20 * pow396; + local pow398 = pow20 * pow397; + local pow399 = pow20 * pow398; + local pow400 = pow20 * pow399; + local pow401 = pow20 * pow400; + local pow402 = pow20 * pow401; + local pow403 = pow20 * pow402; + local pow404 = pow20 * pow403; + local pow405 = pow20 * pow404; + local pow406 = pow20 * pow405; + local pow407 = pow20 * pow406; + local pow408 = pow20 * pow407; + local pow409 = pow20 * pow408; + local pow410 = pow20 * pow409; + local pow411 = pow20 * pow410; + local pow412 = pow20 * pow411; + local pow413 = pow20 * pow412; + local pow414 = pow20 * pow413; + local pow415 = pow20 * pow414; + local pow416 = pow20 * pow415; + local pow417 = pow20 * pow416; + local pow418 = pow29 * pow417; + local pow419 = pow20 * pow418; + local pow420 = pow20 * pow419; + local pow421 = pow20 * pow420; + local pow422 = pow20 * pow421; + local pow423 = pow20 * pow422; + local pow424 = pow20 * pow423; + local pow425 = pow20 * pow424; + local pow426 = pow20 * pow425; + local pow427 = pow20 * pow426; + local pow428 = pow20 * pow427; + local pow429 = pow20 * pow428; + local pow430 = pow20 * pow429; + local pow431 = pow20 * pow430; + local pow432 = pow20 * pow431; + local pow433 = pow20 * pow432; + local pow434 = pow20 * pow433; + local pow435 = pow20 * pow434; + local pow436 = pow20 * pow435; + local pow437 = pow20 * pow436; + local pow438 = pow20 * pow437; + local pow439 = pow20 * pow438; + local pow440 = pow20 * pow439; + local pow441 = pow20 * pow440; + local pow442 = pow20 * pow441; + local pow443 = pow20 * pow442; + local pow444 = pow20 * pow443; + local pow445 = pow20 * pow444; + local pow446 = pow20 * pow445; + local pow447 = pow20 * pow446; + local pow448 = pow29 * pow447; + local pow449 = pow20 * pow448; + local pow450 = pow20 * pow449; + local pow451 = pow20 * pow450; + local pow452 = pow20 * pow451; + local pow453 = pow20 * pow452; + local pow454 = pow20 * pow453; + local pow455 = pow20 * pow454; + local pow456 = pow20 * pow455; + local pow457 = pow20 * pow456; + local pow458 = pow20 * pow457; + local pow459 = pow20 * pow458; + local pow460 = pow20 * pow459; + local pow461 = pow20 * pow460; + local pow462 = pow20 * pow461; + local pow463 = pow20 * pow462; + local pow464 = pow20 * pow463; + local pow465 = pow20 * pow464; + local pow466 = pow20 * pow465; + local pow467 = pow20 * pow466; + local pow468 = pow20 * pow467; + local pow469 = pow20 * pow468; + local pow470 = pow20 * pow469; + local pow471 = pow20 * pow470; + local pow472 = pow20 * pow471; + local pow473 = pow20 * pow472; + local pow474 = pow20 * pow473; + local pow475 = pow20 * pow474; + local pow476 = pow20 * pow475; + local pow477 = pow20 * pow476; + local pow478 = pow29 * pow477; + local pow479 = pow20 * pow478; + local pow480 = pow20 * pow479; + local pow481 = pow20 * pow480; + local pow482 = pow20 * pow481; + local pow483 = pow20 * pow482; + local pow484 = pow20 * pow483; + local pow485 = pow20 * pow484; + local pow486 = pow20 * pow485; + local pow487 = pow20 * pow486; + local pow488 = pow20 * pow487; + local pow489 = pow20 * pow488; + local pow490 = pow20 * pow489; + local pow491 = pow20 * pow490; + local pow492 = pow20 * pow491; + local pow493 = pow20 * pow492; + local pow494 = pow20 * pow493; + local pow495 = pow20 * pow494; + local pow496 = pow20 * pow495; + local pow497 = pow20 * pow496; + local pow498 = pow20 * pow497; + local pow499 = pow20 * pow498; + local pow500 = pow20 * pow499; + local pow501 = pow20 * pow500; + local pow502 = pow20 * pow501; + local pow503 = pow20 * pow502; + local pow504 = pow20 * pow503; + local pow505 = pow20 * pow504; + local pow506 = pow20 * pow505; + local pow507 = pow20 * pow506; + local pow508 = pow29 * pow507; + local pow509 = pow20 * pow508; + local pow510 = pow20 * pow509; + local pow511 = pow20 * pow510; + local pow512 = pow20 * pow511; + local pow513 = pow20 * pow512; + local pow514 = pow20 * pow513; + local pow515 = pow20 * pow514; + local pow516 = pow20 * pow515; + local pow517 = pow20 * pow516; + local pow518 = pow20 * pow517; + local pow519 = pow20 * pow518; + local pow520 = pow20 * pow519; + local pow521 = pow20 * pow520; + local pow522 = pow20 * pow521; + local pow523 = pow20 * pow522; + local pow524 = pow20 * pow523; + local pow525 = pow20 * pow524; + local pow526 = pow20 * pow525; + local pow527 = pow20 * pow526; + local pow528 = pow20 * pow527; + local pow529 = pow20 * pow528; + local pow530 = pow20 * pow529; + local pow531 = pow20 * pow530; + local pow532 = pow20 * pow531; + local pow533 = pow20 * pow532; + local pow534 = pow20 * pow533; + local pow535 = pow20 * pow534; + local pow536 = pow20 * pow535; + local pow537 = pow20 * pow536; + local pow538 = pow29 * pow537; + local pow539 = pow20 * pow538; + local pow540 = pow20 * pow539; + local pow541 = pow20 * pow540; + local pow542 = pow20 * pow541; + local pow543 = pow20 * pow542; + local pow544 = pow20 * pow543; + local pow545 = pow20 * pow544; + local pow546 = pow20 * pow545; + local pow547 = pow20 * pow546; + local pow548 = pow20 * pow547; + local pow549 = pow20 * pow548; + local pow550 = pow20 * pow549; + local pow551 = pow20 * pow550; + local pow552 = pow20 * pow551; + local pow553 = pow20 * pow552; + local pow554 = pow20 * pow553; + local pow555 = pow20 * pow554; + local pow556 = pow20 * pow555; + local pow557 = pow20 * pow556; + local pow558 = pow20 * pow557; + local pow559 = pow20 * pow558; + local pow560 = pow20 * pow559; + local pow561 = pow20 * pow560; + local pow562 = pow20 * pow561; + local pow563 = pow20 * pow562; + local pow564 = pow20 * pow563; + local pow565 = pow20 * pow564; + local pow566 = pow20 * pow565; + local pow567 = pow20 * pow566; + local pow568 = pow29 * pow567; + local pow569 = pow20 * pow568; + local pow570 = pow20 * pow569; + local pow571 = pow20 * pow570; + local pow572 = pow20 * pow571; + local pow573 = pow20 * pow572; + local pow574 = pow20 * pow573; + local pow575 = pow20 * pow574; + local pow576 = pow20 * pow575; + local pow577 = pow20 * pow576; + local pow578 = pow20 * pow577; + local pow579 = pow20 * pow578; + local pow580 = pow20 * pow579; + local pow581 = pow20 * pow580; + local pow582 = pow20 * pow581; + local pow583 = pow20 * pow582; + local pow584 = pow20 * pow583; + local pow585 = pow20 * pow584; + local pow586 = pow20 * pow585; + local pow587 = pow20 * pow586; + local pow588 = pow20 * pow587; + local pow589 = pow20 * pow588; + local pow590 = pow20 * pow589; + local pow591 = pow20 * pow590; + local pow592 = pow20 * pow591; + local pow593 = pow20 * pow592; + local pow594 = pow20 * pow593; + local pow595 = pow20 * pow594; + local pow596 = pow20 * pow595; + local pow597 = pow20 * pow596; + local pow598 = pow29 * pow597; + local pow599 = pow20 * pow598; + local pow600 = pow20 * pow599; + local pow601 = pow20 * pow600; + local pow602 = pow20 * pow601; + local pow603 = pow20 * pow602; + local pow604 = pow20 * pow603; + local pow605 = pow20 * pow604; + local pow606 = pow20 * pow605; + local pow607 = pow20 * pow606; + local pow608 = pow20 * pow607; + local pow609 = pow20 * pow608; + local pow610 = pow20 * pow609; + local pow611 = pow20 * pow610; + local pow612 = pow20 * pow611; + local pow613 = pow20 * pow612; + local pow614 = pow20 * pow613; + local pow615 = pow20 * pow614; + local pow616 = pow20 * pow615; + local pow617 = pow20 * pow616; + local pow618 = pow20 * pow617; + local pow619 = pow20 * pow618; + local pow620 = pow20 * pow619; + local pow621 = pow20 * pow620; + local pow622 = pow20 * pow621; + local pow623 = pow20 * pow622; + local pow624 = pow20 * pow623; + local pow625 = pow20 * pow624; + local pow626 = pow20 * pow625; + local pow627 = pow20 * pow626; + local pow628 = pow29 * pow627; + local pow629 = pow20 * pow628; + local pow630 = pow20 * pow629; + local pow631 = pow20 * pow630; + local pow632 = pow20 * pow631; + local pow633 = pow20 * pow632; + local pow634 = pow20 * pow633; + local pow635 = pow20 * pow634; + local pow636 = pow20 * pow635; + local pow637 = pow20 * pow636; + local pow638 = pow20 * pow637; + local pow639 = pow20 * pow638; + local pow640 = pow20 * pow639; + local pow641 = pow20 * pow640; + local pow642 = pow20 * pow641; + local pow643 = pow20 * pow642; + local pow644 = pow20 * pow643; + local pow645 = pow20 * pow644; + local pow646 = pow20 * pow645; + local pow647 = pow20 * pow646; + local pow648 = pow20 * pow647; + local pow649 = pow20 * pow648; + local pow650 = pow20 * pow649; + local pow651 = pow20 * pow650; + local pow652 = pow20 * pow651; + local pow653 = pow20 * pow652; + local pow654 = pow20 * pow653; + local pow655 = pow20 * pow654; + local pow656 = pow20 * pow655; + local pow657 = pow20 * pow656; + local pow658 = pow29 * pow657; + local pow659 = pow20 * pow658; + local pow660 = pow20 * pow659; + local pow661 = pow20 * pow660; + local pow662 = pow20 * pow661; + local pow663 = pow20 * pow662; + local pow664 = pow20 * pow663; + local pow665 = pow20 * pow664; + local pow666 = pow20 * pow665; + local pow667 = pow20 * pow666; + local pow668 = pow20 * pow667; + local pow669 = pow20 * pow668; + local pow670 = pow20 * pow669; + local pow671 = pow20 * pow670; + local pow672 = pow20 * pow671; + local pow673 = pow20 * pow672; + local pow674 = pow20 * pow673; + local pow675 = pow20 * pow674; + local pow676 = pow20 * pow675; + local pow677 = pow20 * pow676; + local pow678 = pow20 * pow677; + local pow679 = pow20 * pow678; + local pow680 = pow20 * pow679; + local pow681 = pow20 * pow680; + local pow682 = pow20 * pow681; + local pow683 = pow20 * pow682; + local pow684 = pow20 * pow683; + local pow685 = pow20 * pow684; + local pow686 = pow20 * pow685; + local pow687 = pow20 * pow686; + local pow688 = pow29 * pow687; + local pow689 = pow20 * pow688; + local pow690 = pow20 * pow689; + local pow691 = pow20 * pow690; + local pow692 = pow20 * pow691; + local pow693 = pow20 * pow692; + local pow694 = pow20 * pow693; + local pow695 = pow20 * pow694; + local pow696 = pow20 * pow695; + local pow697 = pow20 * pow696; + local pow698 = pow20 * pow697; + local pow699 = pow20 * pow698; + local pow700 = pow20 * pow699; + local pow701 = pow20 * pow700; + local pow702 = pow20 * pow701; + local pow703 = pow20 * pow702; + local pow704 = pow20 * pow703; + local pow705 = pow20 * pow704; + local pow706 = pow20 * pow705; + local pow707 = pow20 * pow706; + local pow708 = pow20 * pow707; + local pow709 = pow20 * pow708; + local pow710 = pow20 * pow709; + local pow711 = pow20 * pow710; + local pow712 = pow20 * pow711; + local pow713 = pow20 * pow712; + local pow714 = pow20 * pow713; + local pow715 = pow20 * pow714; + local pow716 = pow20 * pow715; + local pow717 = pow20 * pow716; + local pow718 = pow29 * pow717; + local pow719 = pow20 * pow718; + local pow720 = pow20 * pow719; + local pow721 = pow20 * pow720; + local pow722 = pow20 * pow721; + local pow723 = pow20 * pow722; + local pow724 = pow20 * pow723; + local pow725 = pow20 * pow724; + local pow726 = pow20 * pow725; + local pow727 = pow20 * pow726; + local pow728 = pow20 * pow727; + local pow729 = pow20 * pow728; + local pow730 = pow20 * pow729; + local pow731 = pow20 * pow730; + local pow732 = pow20 * pow731; + local pow733 = pow20 * pow732; + local pow734 = pow20 * pow733; + local pow735 = pow20 * pow734; + local pow736 = pow20 * pow735; + local pow737 = pow20 * pow736; + local pow738 = pow20 * pow737; + local pow739 = pow20 * pow738; + local pow740 = pow20 * pow739; + local pow741 = pow20 * pow740; + local pow742 = pow20 * pow741; + local pow743 = pow20 * pow742; + local pow744 = pow20 * pow743; + local pow745 = pow20 * pow744; + local pow746 = pow20 * pow745; + local pow747 = pow20 * pow746; + local pow748 = pow29 * pow747; + local pow749 = pow20 * pow748; + local pow750 = pow20 * pow749; + local pow751 = pow20 * pow750; + local pow752 = pow20 * pow751; + local pow753 = pow20 * pow752; + local pow754 = pow20 * pow753; + local pow755 = pow20 * pow754; + local pow756 = pow20 * pow755; + local pow757 = pow20 * pow756; + local pow758 = pow20 * pow757; + local pow759 = pow20 * pow758; + local pow760 = pow20 * pow759; + local pow761 = pow20 * pow760; + local pow762 = pow20 * pow761; + local pow763 = pow20 * pow762; + local pow764 = pow20 * pow763; + local pow765 = pow20 * pow764; + local pow766 = pow20 * pow765; + local pow767 = pow20 * pow766; + local pow768 = pow20 * pow767; + local pow769 = pow20 * pow768; + local pow770 = pow20 * pow769; + local pow771 = pow20 * pow770; + local pow772 = pow20 * pow771; + local pow773 = pow20 * pow772; + local pow774 = pow20 * pow773; + local pow775 = pow20 * pow774; + local pow776 = pow20 * pow775; + local pow777 = pow20 * pow776; + local pow778 = pow61 * pow777; + local pow779 = pow88 * pow778; + local pow780 = pow88 * pow779; + local pow781 = pow88 * pow780; + local pow782 = pow20 * pow781; + local pow783 = pow20 * pow782; + local pow784 = pow20 * pow783; + local pow785 = pow20 * pow784; + local pow786 = pow20 * pow785; + local pow787 = pow20 * pow786; + local pow788 = pow20 * pow787; + local pow789 = pow20 * pow788; + local pow790 = pow20 * pow789; + local pow791 = pow20 * pow790; + local pow792 = pow20 * pow791; + local pow793 = pow20 * pow792; + local pow794 = pow20 * pow793; + local pow795 = pow20 * pow794; + local pow796 = pow20 * pow795; + local pow797 = pow20 * pow796; + local pow798 = pow20 * pow797; + local pow799 = pow20 * pow798; + local pow800 = pow20 * pow799; + local pow801 = pow20 * pow800; + local pow802 = pow20 * pow801; + local pow803 = pow20 * pow802; + local pow804 = pow20 * pow803; + local pow805 = pow67 * pow804; + local pow806 = pow88 * pow805; + local pow807 = pow88 * pow806; + local pow808 = pow88 * pow807; + local pow809 = pow88 * pow808; + local pow810 = pow88 * pow809; + local pow811 = pow88 * pow810; + local pow812 = pow568 * pow811; + local pow813 = pow20 * pow812; + local pow814 = pow20 * pow813; + local pow815 = pow20 * pow814; + local pow816 = pow20 * pow815; + local pow817 = pow20 * pow816; + local pow818 = pow20 * pow817; + local pow819 = pow20 * pow818; + local pow820 = pow20 * pow819; + local pow821 = pow20 * pow820; + local pow822 = pow20 * pow821; + local pow823 = pow20 * pow822; + local pow824 = pow20 * pow823; + local pow825 = pow20 * pow824; + local pow826 = pow20 * pow825; + local pow827 = pow20 * pow826; + local pow828 = pow20 * pow827; + local pow829 = pow20 * pow828; + local pow830 = pow20 * pow829; + local pow831 = pow20 * pow830; + local pow832 = pow20 * pow831; + local pow833 = pow20 * pow832; + local pow834 = pow20 * pow833; + local pow835 = pow20 * pow834; + local pow836 = pow67 * pow835; + local pow837 = pow88 * pow836; + local pow838 = pow88 * pow837; + local pow839 = pow88 * pow838; + local pow840 = pow88 * pow839; + local pow841 = pow88 * pow840; + local pow842 = pow88 * pow841; + local pow843 = pow88 * pow842; + local pow844 = pow88 * pow843; + local pow845 = pow88 * pow844; + local pow846 = pow88 * pow845; + local pow847 = pow88 * pow846; + local pow848 = pow88 * pow847; + local pow849 = pow88 * pow848; + local pow850 = pow88 * pow849; + local pow851 = pow88 * pow850; + local pow852 = pow20 * pow851; + local pow853 = pow20 * pow852; + local pow854 = pow20 * pow853; + local pow855 = pow20 * pow854; + local pow856 = pow20 * pow855; + local pow857 = pow20 * pow856; + local pow858 = pow20 * pow857; + local pow859 = pow20 * pow858; + local pow860 = pow20 * pow859; + local pow861 = pow20 * pow860; + local pow862 = pow20 * pow861; + local pow863 = pow20 * pow862; + local pow864 = pow20 * pow863; + local pow865 = pow20 * pow864; + local pow866 = pow20 * pow865; + local pow867 = pow20 * pow866; + local pow868 = pow20 * pow867; + local pow869 = pow20 * pow868; + local pow870 = pow20 * pow869; + local pow871 = pow20 * pow870; + local pow872 = pow20 * pow871; + local pow873 = pow20 * pow872; + local pow874 = pow20 * pow873; + local pow875 = pow67 * pow874; + local pow876 = pow88 * pow875; + local pow877 = pow88 * pow876; + local pow878 = pow88 * pow877; + local pow879 = pow88 * pow878; + local pow880 = pow88 * pow879; + local pow881 = pow88 * pow880; + local pow882 = pow568 * pow881; + local pow883 = pow20 * pow882; + local pow884 = pow20 * pow883; + local pow885 = pow20 * pow884; + local pow886 = pow20 * pow885; + local pow887 = pow20 * pow886; + local pow888 = pow20 * pow887; + local pow889 = pow20 * pow888; + local pow890 = pow20 * pow889; + local pow891 = pow20 * pow890; + local pow892 = pow20 * pow891; + local pow893 = pow20 * pow892; + local pow894 = pow20 * pow893; + local pow895 = pow20 * pow894; + local pow896 = pow20 * pow895; + local pow897 = pow20 * pow896; + local pow898 = pow20 * pow897; + local pow899 = pow20 * pow898; + local pow900 = pow20 * pow899; + local pow901 = pow20 * pow900; + local pow902 = pow20 * pow901; + local pow903 = pow20 * pow902; + local pow904 = pow20 * pow903; + local pow905 = pow20 * pow904; + local pow906 = pow67 * pow905; + local pow907 = pow88 * pow906; + local pow908 = pow88 * pow907; + local pow909 = pow88 * pow908; + local pow910 = pow88 * pow909; + local pow911 = pow88 * pow910; + local pow912 = pow88 * pow911; + local pow913 = pow88 * pow912; + local pow914 = pow88 * pow913; + local pow915 = pow88 * pow914; + local pow916 = pow88 * pow915; + local pow917 = pow88 * pow916; + local pow918 = pow88 * pow917; + local pow919 = pow88 * pow918; + local pow920 = pow88 * pow919; + local pow921 = pow88 * pow920; + local pow922 = pow20 * pow921; + local pow923 = pow20 * pow922; + local pow924 = pow20 * pow923; + local pow925 = pow20 * pow924; + local pow926 = pow20 * pow925; + local pow927 = pow20 * pow926; + local pow928 = pow20 * pow927; + local pow929 = pow20 * pow928; + local pow930 = pow20 * pow929; + local pow931 = pow20 * pow930; + local pow932 = pow20 * pow931; + local pow933 = pow20 * pow932; + local pow934 = pow20 * pow933; + local pow935 = pow20 * pow934; + local pow936 = pow20 * pow935; + local pow937 = pow20 * pow936; + local pow938 = pow20 * pow937; + local pow939 = pow20 * pow938; + local pow940 = pow20 * pow939; + local pow941 = pow20 * pow940; + local pow942 = pow20 * pow941; + local pow943 = pow20 * pow942; + local pow944 = pow20 * pow943; + local pow945 = pow67 * pow944; + local pow946 = pow88 * pow945; + local pow947 = pow88 * pow946; + local pow948 = pow88 * pow947; + local pow949 = pow88 * pow948; + local pow950 = pow88 * pow949; + local pow951 = pow88 * pow950; + local pow952 = pow568 * pow951; + local pow953 = pow20 * pow952; + local pow954 = pow20 * pow953; + local pow955 = pow20 * pow954; + local pow956 = pow20 * pow955; + local pow957 = pow20 * pow956; + local pow958 = pow20 * pow957; + local pow959 = pow20 * pow958; + local pow960 = pow20 * pow959; + local pow961 = pow20 * pow960; + local pow962 = pow20 * pow961; + local pow963 = pow20 * pow962; + local pow964 = pow20 * pow963; + local pow965 = pow20 * pow964; + local pow966 = pow20 * pow965; + local pow967 = pow20 * pow966; + local pow968 = pow20 * pow967; + local pow969 = pow20 * pow968; + local pow970 = pow20 * pow969; + local pow971 = pow20 * pow970; + local pow972 = pow20 * pow971; + local pow973 = pow20 * pow972; + local pow974 = pow20 * pow973; + local pow975 = pow20 * pow974; + local pow976 = pow781 * pow952; + local pow977 = pow20 * pow976; + local pow978 = pow20 * pow977; + local pow979 = pow20 * pow978; + local pow980 = pow20 * pow979; + local pow981 = pow20 * pow980; + local pow982 = pow20 * pow981; + local pow983 = pow20 * pow982; + local pow984 = pow20 * pow983; + local pow985 = pow20 * pow984; + local pow986 = pow20 * pow985; + local pow987 = pow20 * pow986; + local pow988 = pow20 * pow987; + local pow989 = pow20 * pow988; + local pow990 = pow20 * pow989; + local pow991 = pow20 * pow990; + local pow992 = pow20 * pow991; + local pow993 = pow20 * pow992; + local pow994 = pow20 * pow993; + local pow995 = pow20 * pow994; + local pow996 = pow20 * pow995; + local pow997 = pow20 * pow996; + local pow998 = pow20 * pow997; + local pow999 = pow20 * pow998; + local pow1000 = pow781 * pow976; + local pow1001 = pow20 * pow1000; + local pow1002 = pow20 * pow1001; + local pow1003 = pow20 * pow1002; + local pow1004 = pow20 * pow1003; + local pow1005 = pow20 * pow1004; + local pow1006 = pow20 * pow1005; + local pow1007 = pow20 * pow1006; + local pow1008 = pow20 * pow1007; + local pow1009 = pow20 * pow1008; + local pow1010 = pow20 * pow1009; + local pow1011 = pow20 * pow1010; + local pow1012 = pow20 * pow1011; + local pow1013 = pow20 * pow1012; + local pow1014 = pow20 * pow1013; + local pow1015 = pow20 * pow1014; + local pow1016 = pow20 * pow1015; + local pow1017 = pow20 * pow1016; + local pow1018 = pow20 * pow1017; + local pow1019 = pow20 * pow1018; + local pow1020 = pow20 * pow1019; + local pow1021 = pow20 * pow1020; + local pow1022 = pow20 * pow1021; + local pow1023 = pow20 * pow1022; + local pow1024 = pow781 * pow1000; + local pow1025 = pow20 * pow1024; + local pow1026 = pow20 * pow1025; + local pow1027 = pow20 * pow1026; + local pow1028 = pow20 * pow1027; + local pow1029 = pow20 * pow1028; + local pow1030 = pow20 * pow1029; + local pow1031 = pow20 * pow1030; + local pow1032 = pow20 * pow1031; + local pow1033 = pow20 * pow1032; + local pow1034 = pow20 * pow1033; + local pow1035 = pow20 * pow1034; + local pow1036 = pow20 * pow1035; + local pow1037 = pow20 * pow1036; + local pow1038 = pow20 * pow1037; + local pow1039 = pow20 * pow1038; + local pow1040 = pow20 * pow1039; + local pow1041 = pow20 * pow1040; + local pow1042 = pow20 * pow1041; + local pow1043 = pow20 * pow1042; + local pow1044 = pow20 * pow1043; + local pow1045 = pow20 * pow1044; + local pow1046 = pow20 * pow1045; + local pow1047 = pow20 * pow1046; + local pow1048 = pow781 * pow1024; + local pow1049 = pow20 * pow1048; + local pow1050 = pow20 * pow1049; + local pow1051 = pow20 * pow1050; + local pow1052 = pow20 * pow1051; + local pow1053 = pow20 * pow1052; + local pow1054 = pow20 * pow1053; + local pow1055 = pow20 * pow1054; + local pow1056 = pow20 * pow1055; + local pow1057 = pow20 * pow1056; + local pow1058 = pow20 * pow1057; + local pow1059 = pow20 * pow1058; + local pow1060 = pow20 * pow1059; + local pow1061 = pow20 * pow1060; + local pow1062 = pow20 * pow1061; + local pow1063 = pow20 * pow1062; + local pow1064 = pow20 * pow1063; + local pow1065 = pow20 * pow1064; + local pow1066 = pow20 * pow1065; + local pow1067 = pow20 * pow1066; + local pow1068 = pow20 * pow1067; + local pow1069 = pow20 * pow1068; + local pow1070 = pow20 * pow1069; + local pow1071 = pow20 * pow1070; + local pow1072 = pow67 * pow1071; + local pow1073 = pow88 * pow1072; + local pow1074 = pow88 * pow1073; + local pow1075 = pow88 * pow1074; + local pow1076 = pow88 * pow1075; + local pow1077 = pow88 * pow1076; + local pow1078 = pow88 * pow1077; + local pow1079 = pow88 * pow1078; + local pow1080 = pow88 * pow1079; + local pow1081 = pow88 * pow1080; + local pow1082 = pow88 * pow1081; + local pow1083 = pow88 * pow1082; + local pow1084 = pow88 * pow1083; + local pow1085 = pow88 * pow1084; + local pow1086 = pow88 * pow1085; + local pow1087 = pow88 * pow1086; + local pow1088 = pow20 * pow1087; + local pow1089 = pow20 * pow1088; + local pow1090 = pow20 * pow1089; + local pow1091 = pow20 * pow1090; + local pow1092 = pow20 * pow1091; + local pow1093 = pow20 * pow1092; + local pow1094 = pow20 * pow1093; + local pow1095 = pow20 * pow1094; + local pow1096 = pow20 * pow1095; + local pow1097 = pow20 * pow1096; + local pow1098 = pow20 * pow1097; + local pow1099 = pow20 * pow1098; + local pow1100 = pow20 * pow1099; + local pow1101 = pow20 * pow1100; + local pow1102 = pow20 * pow1101; + local pow1103 = pow20 * pow1102; + local pow1104 = pow20 * pow1103; + local pow1105 = pow20 * pow1104; + local pow1106 = pow20 * pow1105; + local pow1107 = pow20 * pow1106; + local pow1108 = pow20 * pow1107; + local pow1109 = pow20 * pow1108; + local pow1110 = pow20 * pow1109; + local pow1111 = pow67 * pow1110; + local pow1112 = pow88 * pow1111; + local pow1113 = pow88 * pow1112; + local pow1114 = pow88 * pow1113; + local pow1115 = pow88 * pow1114; + local pow1116 = pow88 * pow1115; + local pow1117 = pow88 * pow1116; + local pow1118 = pow568 * pow1117; + local pow1119 = pow20 * pow1118; + local pow1120 = pow20 * pow1119; + local pow1121 = pow20 * pow1120; + local pow1122 = pow20 * pow1121; + local pow1123 = pow20 * pow1122; + local pow1124 = pow20 * pow1123; + local pow1125 = pow20 * pow1124; + local pow1126 = pow20 * pow1125; + local pow1127 = pow20 * pow1126; + local pow1128 = pow20 * pow1127; + local pow1129 = pow20 * pow1128; + local pow1130 = pow20 * pow1129; + local pow1131 = pow20 * pow1130; + local pow1132 = pow20 * pow1131; + local pow1133 = pow20 * pow1132; + local pow1134 = pow20 * pow1133; + local pow1135 = pow20 * pow1134; + local pow1136 = pow20 * pow1135; + local pow1137 = pow20 * pow1136; + local pow1138 = pow20 * pow1137; + local pow1139 = pow20 * pow1138; + local pow1140 = pow20 * pow1139; + local pow1141 = pow20 * pow1140; + local pow1142 = pow67 * pow1141; + local pow1143 = pow88 * pow1142; + local pow1144 = pow88 * pow1143; + local pow1145 = pow88 * pow1144; + local pow1146 = pow88 * pow1145; + local pow1147 = pow88 * pow1146; + local pow1148 = pow88 * pow1147; + local pow1149 = pow88 * pow1148; + local pow1150 = pow88 * pow1149; + local pow1151 = pow88 * pow1150; + local pow1152 = pow88 * pow1151; + local pow1153 = pow88 * pow1152; + local pow1154 = pow88 * pow1153; + local pow1155 = pow88 * pow1154; + local pow1156 = pow88 * pow1155; + local pow1157 = pow88 * pow1156; + local pow1158 = pow20 * pow1157; + local pow1159 = pow20 * pow1158; + local pow1160 = pow20 * pow1159; + local pow1161 = pow20 * pow1160; + local pow1162 = pow20 * pow1161; + local pow1163 = pow20 * pow1162; + local pow1164 = pow20 * pow1163; + local pow1165 = pow20 * pow1164; + local pow1166 = pow20 * pow1165; + local pow1167 = pow20 * pow1166; + local pow1168 = pow20 * pow1167; + local pow1169 = pow20 * pow1168; + local pow1170 = pow20 * pow1169; + local pow1171 = pow20 * pow1170; + local pow1172 = pow20 * pow1171; + local pow1173 = pow20 * pow1172; + local pow1174 = pow20 * pow1173; + local pow1175 = pow20 * pow1174; + local pow1176 = pow20 * pow1175; + local pow1177 = pow20 * pow1176; + local pow1178 = pow20 * pow1177; + local pow1179 = pow20 * pow1178; + local pow1180 = pow20 * pow1179; + local pow1181 = pow67 * pow1180; + local pow1182 = pow88 * pow1181; + local pow1183 = pow88 * pow1182; + local pow1184 = pow88 * pow1183; + local pow1185 = pow88 * pow1184; + local pow1186 = pow88 * pow1185; + local pow1187 = pow88 * pow1186; + local pow1188 = pow568 * pow1187; + local pow1189 = pow20 * pow1188; + local pow1190 = pow20 * pow1189; + local pow1191 = pow20 * pow1190; + local pow1192 = pow20 * pow1191; + local pow1193 = pow20 * pow1192; + local pow1194 = pow20 * pow1193; + local pow1195 = pow20 * pow1194; + local pow1196 = pow20 * pow1195; + local pow1197 = pow20 * pow1196; + local pow1198 = pow20 * pow1197; + local pow1199 = pow20 * pow1198; + local pow1200 = pow20 * pow1199; + local pow1201 = pow20 * pow1200; + local pow1202 = pow20 * pow1201; + local pow1203 = pow20 * pow1202; + local pow1204 = pow20 * pow1203; + local pow1205 = pow20 * pow1204; + local pow1206 = pow20 * pow1205; + local pow1207 = pow20 * pow1206; + local pow1208 = pow20 * pow1207; + local pow1209 = pow20 * pow1208; + local pow1210 = pow20 * pow1209; + local pow1211 = pow20 * pow1210; + local pow1212 = pow67 * pow1211; + local pow1213 = pow88 * pow1212; + local pow1214 = pow88 * pow1213; + local pow1215 = pow88 * pow1214; + local pow1216 = pow88 * pow1215; + local pow1217 = pow88 * pow1216; + local pow1218 = pow88 * pow1217; + local pow1219 = pow88 * pow1218; + local pow1220 = pow88 * pow1219; + local pow1221 = pow88 * pow1220; + local pow1222 = pow88 * pow1221; + local pow1223 = pow88 * pow1222; + local pow1224 = pow88 * pow1223; + local pow1225 = pow88 * pow1224; + local pow1226 = pow88 * pow1225; + local pow1227 = pow88 * pow1226; + local pow1228 = pow20 * pow1227; + local pow1229 = pow20 * pow1228; + local pow1230 = pow20 * pow1229; + local pow1231 = pow20 * pow1230; + local pow1232 = pow20 * pow1231; + local pow1233 = pow20 * pow1232; + local pow1234 = pow20 * pow1233; + local pow1235 = pow20 * pow1234; + local pow1236 = pow20 * pow1235; + local pow1237 = pow20 * pow1236; + local pow1238 = pow20 * pow1237; + local pow1239 = pow20 * pow1238; + local pow1240 = pow20 * pow1239; + local pow1241 = pow20 * pow1240; + local pow1242 = pow20 * pow1241; + local pow1243 = pow20 * pow1242; + local pow1244 = pow20 * pow1243; + local pow1245 = pow20 * pow1244; + local pow1246 = pow20 * pow1245; + local pow1247 = pow20 * pow1246; + local pow1248 = pow20 * pow1247; + local pow1249 = pow20 * pow1248; + local pow1250 = pow20 * pow1249; + local pow1251 = pow67 * pow1250; + local pow1252 = pow88 * pow1251; + local pow1253 = pow88 * pow1252; + local pow1254 = pow88 * pow1253; + local pow1255 = pow88 * pow1254; + local pow1256 = pow88 * pow1255; + local pow1257 = pow88 * pow1256; + local pow1258 = pow568 * pow1257; + local pow1259 = pow20 * pow1258; + local pow1260 = pow20 * pow1259; + local pow1261 = pow20 * pow1260; + local pow1262 = pow20 * pow1261; + local pow1263 = pow20 * pow1262; + local pow1264 = pow20 * pow1263; + local pow1265 = pow20 * pow1264; + local pow1266 = pow20 * pow1265; + local pow1267 = pow20 * pow1266; + local pow1268 = pow20 * pow1267; + local pow1269 = pow20 * pow1268; + local pow1270 = pow20 * pow1269; + local pow1271 = pow20 * pow1270; + local pow1272 = pow20 * pow1271; + local pow1273 = pow20 * pow1272; + local pow1274 = pow20 * pow1273; + local pow1275 = pow20 * pow1274; + local pow1276 = pow20 * pow1275; + local pow1277 = pow20 * pow1276; + local pow1278 = pow20 * pow1277; + local pow1279 = pow20 * pow1278; + local pow1280 = pow20 * pow1279; + local pow1281 = pow20 * pow1280; + local pow1282 = pow781 * pow1258; + local pow1283 = pow20 * pow1282; + local pow1284 = pow20 * pow1283; + local pow1285 = pow20 * pow1284; + local pow1286 = pow20 * pow1285; + local pow1287 = pow20 * pow1286; + local pow1288 = pow20 * pow1287; + local pow1289 = pow20 * pow1288; + local pow1290 = pow20 * pow1289; + local pow1291 = pow20 * pow1290; + local pow1292 = pow20 * pow1291; + local pow1293 = pow20 * pow1292; + local pow1294 = pow20 * pow1293; + local pow1295 = pow20 * pow1294; + local pow1296 = pow20 * pow1295; + local pow1297 = pow20 * pow1296; + local pow1298 = pow20 * pow1297; + local pow1299 = pow20 * pow1298; + local pow1300 = pow20 * pow1299; + local pow1301 = pow20 * pow1300; + local pow1302 = pow20 * pow1301; + local pow1303 = pow20 * pow1302; + local pow1304 = pow20 * pow1303; + local pow1305 = pow20 * pow1304; + local pow1306 = pow781 * pow1282; + local pow1307 = pow20 * pow1306; + local pow1308 = pow20 * pow1307; + local pow1309 = pow20 * pow1308; + local pow1310 = pow20 * pow1309; + local pow1311 = pow20 * pow1310; + local pow1312 = pow20 * pow1311; + local pow1313 = pow20 * pow1312; + local pow1314 = pow20 * pow1313; + local pow1315 = pow20 * pow1314; + local pow1316 = pow20 * pow1315; + local pow1317 = pow20 * pow1316; + local pow1318 = pow20 * pow1317; + local pow1319 = pow20 * pow1318; + local pow1320 = pow20 * pow1319; + local pow1321 = pow20 * pow1320; + local pow1322 = pow20 * pow1321; + local pow1323 = pow20 * pow1322; + local pow1324 = pow20 * pow1323; + local pow1325 = pow20 * pow1324; + local pow1326 = pow20 * pow1325; + local pow1327 = pow20 * pow1326; + local pow1328 = pow20 * pow1327; + local pow1329 = pow20 * pow1328; + local pow1330 = pow781 * pow1306; + local pow1331 = pow20 * pow1330; + local pow1332 = pow20 * pow1331; + local pow1333 = pow20 * pow1332; + local pow1334 = pow20 * pow1333; + local pow1335 = pow20 * pow1334; + local pow1336 = pow20 * pow1335; + local pow1337 = pow20 * pow1336; + local pow1338 = pow20 * pow1337; + local pow1339 = pow20 * pow1338; + local pow1340 = pow20 * pow1339; + local pow1341 = pow20 * pow1340; + local pow1342 = pow20 * pow1341; + local pow1343 = pow20 * pow1342; + local pow1344 = pow20 * pow1343; + local pow1345 = pow20 * pow1344; + local pow1346 = pow20 * pow1345; + local pow1347 = pow20 * pow1346; + local pow1348 = pow20 * pow1347; + local pow1349 = pow20 * pow1348; + local pow1350 = pow20 * pow1349; + local pow1351 = pow20 * pow1350; + local pow1352 = pow20 * pow1351; + local pow1353 = pow20 * pow1352; + local pow1354 = pow781 * pow1330; + local pow1355 = pow20 * pow1354; + local pow1356 = pow20 * pow1355; + local pow1357 = pow20 * pow1356; + local pow1358 = pow20 * pow1357; + local pow1359 = pow20 * pow1358; + local pow1360 = pow20 * pow1359; + local pow1361 = pow20 * pow1360; + local pow1362 = pow20 * pow1361; + local pow1363 = pow20 * pow1362; + local pow1364 = pow20 * pow1363; + local pow1365 = pow20 * pow1364; + local pow1366 = pow20 * pow1365; + local pow1367 = pow20 * pow1366; + local pow1368 = pow20 * pow1367; + local pow1369 = pow20 * pow1368; + local pow1370 = pow20 * pow1369; + local pow1371 = pow20 * pow1370; + local pow1372 = pow20 * pow1371; + local pow1373 = pow20 * pow1372; + local pow1374 = pow20 * pow1373; + local pow1375 = pow20 * pow1374; + local pow1376 = pow20 * pow1375; + local pow1377 = pow20 * pow1376; + local pow1378 = pow67 * pow1377; + local pow1379 = pow88 * pow1378; + local pow1380 = pow88 * pow1379; + local pow1381 = pow88 * pow1380; + local pow1382 = pow88 * pow1381; + local pow1383 = pow88 * pow1382; + local pow1384 = pow88 * pow1383; + local pow1385 = pow88 * pow1384; + local pow1386 = pow88 * pow1385; + local pow1387 = pow88 * pow1386; + local pow1388 = pow88 * pow1387; + local pow1389 = pow88 * pow1388; + local pow1390 = pow88 * pow1389; + local pow1391 = pow88 * pow1390; + local pow1392 = pow88 * pow1391; + local pow1393 = pow88 * pow1392; + local pow1394 = pow20 * pow1393; + local pow1395 = pow20 * pow1394; + local pow1396 = pow20 * pow1395; + local pow1397 = pow20 * pow1396; + local pow1398 = pow20 * pow1397; + local pow1399 = pow20 * pow1398; + local pow1400 = pow20 * pow1399; + local pow1401 = pow20 * pow1400; + local pow1402 = pow20 * pow1401; + local pow1403 = pow20 * pow1402; + local pow1404 = pow20 * pow1403; + local pow1405 = pow20 * pow1404; + local pow1406 = pow20 * pow1405; + local pow1407 = pow20 * pow1406; + local pow1408 = pow20 * pow1407; + local pow1409 = pow20 * pow1408; + local pow1410 = pow20 * pow1409; + local pow1411 = pow20 * pow1410; + local pow1412 = pow20 * pow1411; + local pow1413 = pow20 * pow1412; + local pow1414 = pow20 * pow1413; + local pow1415 = pow20 * pow1414; + local pow1416 = pow20 * pow1415; + local pow1417 = pow67 * pow1416; + local pow1418 = pow88 * pow1417; + local pow1419 = pow88 * pow1418; + local pow1420 = pow88 * pow1419; + local pow1421 = pow88 * pow1420; + local pow1422 = pow88 * pow1421; + local pow1423 = pow88 * pow1422; + local pow1424 = pow568 * pow1423; + local pow1425 = pow20 * pow1424; + local pow1426 = pow20 * pow1425; + local pow1427 = pow20 * pow1426; + local pow1428 = pow20 * pow1427; + local pow1429 = pow20 * pow1428; + local pow1430 = pow20 * pow1429; + local pow1431 = pow20 * pow1430; + local pow1432 = pow20 * pow1431; + local pow1433 = pow20 * pow1432; + local pow1434 = pow20 * pow1433; + local pow1435 = pow20 * pow1434; + local pow1436 = pow20 * pow1435; + local pow1437 = pow20 * pow1436; + local pow1438 = pow20 * pow1437; + local pow1439 = pow20 * pow1438; + local pow1440 = pow20 * pow1439; + local pow1441 = pow20 * pow1440; + local pow1442 = pow20 * pow1441; + local pow1443 = pow20 * pow1442; + local pow1444 = pow20 * pow1443; + local pow1445 = pow20 * pow1444; + local pow1446 = pow20 * pow1445; + local pow1447 = pow20 * pow1446; + local pow1448 = pow67 * pow1447; + local pow1449 = pow88 * pow1448; + local pow1450 = pow88 * pow1449; + local pow1451 = pow88 * pow1450; + local pow1452 = pow88 * pow1451; + local pow1453 = pow88 * pow1452; + local pow1454 = pow88 * pow1453; + local pow1455 = pow88 * pow1454; + local pow1456 = pow88 * pow1455; + local pow1457 = pow88 * pow1456; + local pow1458 = pow88 * pow1457; + local pow1459 = pow88 * pow1458; + local pow1460 = pow88 * pow1459; + local pow1461 = pow88 * pow1460; + local pow1462 = pow88 * pow1461; + local pow1463 = pow88 * pow1462; + local pow1464 = pow20 * pow1463; + local pow1465 = pow20 * pow1464; + local pow1466 = pow20 * pow1465; + local pow1467 = pow20 * pow1466; + local pow1468 = pow20 * pow1467; + local pow1469 = pow20 * pow1468; + local pow1470 = pow20 * pow1469; + local pow1471 = pow20 * pow1470; + local pow1472 = pow20 * pow1471; + local pow1473 = pow20 * pow1472; + local pow1474 = pow20 * pow1473; + local pow1475 = pow20 * pow1474; + local pow1476 = pow20 * pow1475; + local pow1477 = pow20 * pow1476; + local pow1478 = pow20 * pow1477; + local pow1479 = pow20 * pow1478; + local pow1480 = pow20 * pow1479; + local pow1481 = pow20 * pow1480; + local pow1482 = pow20 * pow1481; + local pow1483 = pow20 * pow1482; + local pow1484 = pow20 * pow1483; + local pow1485 = pow20 * pow1484; + local pow1486 = pow20 * pow1485; + local pow1487 = pow67 * pow1486; + local pow1488 = pow88 * pow1487; + local pow1489 = pow88 * pow1488; + local pow1490 = pow88 * pow1489; + local pow1491 = pow88 * pow1490; + local pow1492 = pow88 * pow1491; + local pow1493 = pow88 * pow1492; + local pow1494 = pow568 * pow1493; + local pow1495 = pow20 * pow1494; + local pow1496 = pow20 * pow1495; + local pow1497 = pow20 * pow1496; + local pow1498 = pow20 * pow1497; + local pow1499 = pow20 * pow1498; + local pow1500 = pow20 * pow1499; + local pow1501 = pow20 * pow1500; + local pow1502 = pow20 * pow1501; + local pow1503 = pow20 * pow1502; + local pow1504 = pow20 * pow1503; + local pow1505 = pow20 * pow1504; + local pow1506 = pow20 * pow1505; + local pow1507 = pow20 * pow1506; + local pow1508 = pow20 * pow1507; + local pow1509 = pow20 * pow1508; + local pow1510 = pow20 * pow1509; + local pow1511 = pow20 * pow1510; + local pow1512 = pow20 * pow1511; + local pow1513 = pow20 * pow1512; + local pow1514 = pow20 * pow1513; + local pow1515 = pow20 * pow1514; + local pow1516 = pow20 * pow1515; + local pow1517 = pow20 * pow1516; + local pow1518 = pow67 * pow1517; + local pow1519 = pow88 * pow1518; + local pow1520 = pow88 * pow1519; + local pow1521 = pow88 * pow1520; + local pow1522 = pow88 * pow1521; + local pow1523 = pow88 * pow1522; + local pow1524 = pow88 * pow1523; + local pow1525 = pow88 * pow1524; + local pow1526 = pow88 * pow1525; + local pow1527 = pow88 * pow1526; + local pow1528 = pow88 * pow1527; + local pow1529 = pow88 * pow1528; + local pow1530 = pow88 * pow1529; + local pow1531 = pow88 * pow1530; + local pow1532 = pow88 * pow1531; + local pow1533 = pow88 * pow1532; + local pow1534 = pow20 * pow1533; + local pow1535 = pow20 * pow1534; + local pow1536 = pow20 * pow1535; + local pow1537 = pow20 * pow1536; + local pow1538 = pow20 * pow1537; + local pow1539 = pow20 * pow1538; + local pow1540 = pow20 * pow1539; + local pow1541 = pow20 * pow1540; + local pow1542 = pow20 * pow1541; + local pow1543 = pow20 * pow1542; + local pow1544 = pow20 * pow1543; + local pow1545 = pow20 * pow1544; + local pow1546 = pow20 * pow1545; + local pow1547 = pow20 * pow1546; + local pow1548 = pow20 * pow1547; + local pow1549 = pow20 * pow1548; + local pow1550 = pow20 * pow1549; + local pow1551 = pow20 * pow1550; + local pow1552 = pow20 * pow1551; + local pow1553 = pow20 * pow1552; + local pow1554 = pow20 * pow1553; + local pow1555 = pow20 * pow1554; + local pow1556 = pow20 * pow1555; + local pow1557 = pow67 * pow1556; + local pow1558 = pow88 * pow1557; + local pow1559 = pow88 * pow1558; + local pow1560 = pow88 * pow1559; + local pow1561 = pow88 * pow1560; + local pow1562 = pow88 * pow1561; + local pow1563 = pow88 * pow1562; + local pow1564 = pow568 * pow1563; + local pow1565 = pow20 * pow1564; + local pow1566 = pow20 * pow1565; + local pow1567 = pow20 * pow1566; + local pow1568 = pow20 * pow1567; + local pow1569 = pow20 * pow1568; + local pow1570 = pow20 * pow1569; + local pow1571 = pow20 * pow1570; + local pow1572 = pow20 * pow1571; + local pow1573 = pow20 * pow1572; + local pow1574 = pow20 * pow1573; + local pow1575 = pow20 * pow1574; + local pow1576 = pow20 * pow1575; + local pow1577 = pow20 * pow1576; + local pow1578 = pow20 * pow1577; + local pow1579 = pow20 * pow1578; + local pow1580 = pow20 * pow1579; + local pow1581 = pow20 * pow1580; + local pow1582 = pow20 * pow1581; + local pow1583 = pow20 * pow1582; + local pow1584 = pow20 * pow1583; + local pow1585 = pow20 * pow1584; + local pow1586 = pow20 * pow1585; + local pow1587 = pow20 * pow1586; + local pow1588 = pow781 * pow1564; + local pow1589 = pow20 * pow1588; + local pow1590 = pow20 * pow1589; + local pow1591 = pow20 * pow1590; + local pow1592 = pow20 * pow1591; + local pow1593 = pow20 * pow1592; + local pow1594 = pow20 * pow1593; + local pow1595 = pow20 * pow1594; + local pow1596 = pow20 * pow1595; + local pow1597 = pow20 * pow1596; + local pow1598 = pow20 * pow1597; + local pow1599 = pow20 * pow1598; + local pow1600 = pow20 * pow1599; + local pow1601 = pow20 * pow1600; + local pow1602 = pow20 * pow1601; + local pow1603 = pow20 * pow1602; + local pow1604 = pow20 * pow1603; + local pow1605 = pow20 * pow1604; + local pow1606 = pow20 * pow1605; + local pow1607 = pow20 * pow1606; + local pow1608 = pow20 * pow1607; + local pow1609 = pow20 * pow1608; + local pow1610 = pow20 * pow1609; + local pow1611 = pow20 * pow1610; + local pow1612 = pow851 * pow1588; + local pow1613 = pow88 * pow1612; + local pow1614 = pow88 * pow1613; + local pow1615 = pow88 * pow1614; + local pow1616 = pow88 * pow1615; + local pow1617 = pow88 * pow1616; + local pow1618 = pow88 * pow1617; + local pow1619 = pow88 * pow1618; + local pow1620 = pow88 * pow1619; + local pow1621 = pow88 * pow1620; + local pow1622 = pow88 * pow1621; + local pow1623 = pow88 * pow1622; + local pow1624 = pow88 * pow1623; + local pow1625 = pow88 * pow1624; + local pow1626 = pow88 * pow1625; + local pow1627 = pow88 * pow1626; + local pow1628 = pow88 * pow1627; + local pow1629 = pow20 * pow1628; + local pow1630 = pow20 * pow1629; + local pow1631 = pow20 * pow1630; + local pow1632 = pow20 * pow1631; + local pow1633 = pow20 * pow1632; + local pow1634 = pow20 * pow1633; + local pow1635 = pow20 * pow1634; + local pow1636 = pow20 * pow1635; + local pow1637 = pow20 * pow1636; + local pow1638 = pow20 * pow1637; + local pow1639 = pow20 * pow1638; + local pow1640 = pow20 * pow1639; + local pow1641 = pow20 * pow1640; + local pow1642 = pow20 * pow1641; + local pow1643 = pow20 * pow1642; + local pow1644 = pow20 * pow1643; + local pow1645 = pow20 * pow1644; + local pow1646 = pow20 * pow1645; + local pow1647 = pow20 * pow1646; + local pow1648 = pow20 * pow1647; + local pow1649 = pow20 * pow1648; + local pow1650 = pow20 * pow1649; + local pow1651 = pow20 * pow1650; + local pow1652 = pow67 * pow1651; + local pow1653 = pow88 * pow1652; + local pow1654 = pow88 * pow1653; + local pow1655 = pow88 * pow1654; + local pow1656 = pow88 * pow1655; + local pow1657 = pow88 * pow1656; + local pow1658 = pow88 * pow1657; + local pow1659 = pow568 * pow1658; + local pow1660 = pow88 * pow1659; + local pow1661 = pow88 * pow1660; + local pow1662 = pow88 * pow1661; + local pow1663 = pow88 * pow1662; + local pow1664 = pow88 * pow1663; + local pow1665 = pow88 * pow1664; + local pow1666 = pow88 * pow1665; + local pow1667 = pow88 * pow1666; + local pow1668 = pow88 * pow1667; + local pow1669 = pow88 * pow1668; + local pow1670 = pow88 * pow1669; + local pow1671 = pow88 * pow1670; + local pow1672 = pow88 * pow1671; + local pow1673 = pow88 * pow1672; + local pow1674 = pow88 * pow1673; + local pow1675 = pow88 * pow1674; + local pow1676 = pow88 * pow1675; + local pow1677 = pow88 * pow1676; + local pow1678 = pow88 * pow1677; + local pow1679 = pow88 * pow1678; + local pow1680 = pow88 * pow1679; + local pow1681 = pow88 * pow1680; + local pow1682 = pow88 * pow1681; + local pow1683 = pow568 * pow1682; + local pow1684 = pow88 * pow1683; + local pow1685 = pow88 * pow1684; + local pow1686 = pow88 * pow1685; + local pow1687 = pow88 * pow1686; + local pow1688 = pow88 * pow1687; + local pow1689 = pow88 * pow1688; + local pow1690 = pow88 * pow1689; + local pow1691 = pow88 * pow1690; + local pow1692 = pow88 * pow1691; + local pow1693 = pow88 * pow1692; + local pow1694 = pow88 * pow1693; + local pow1695 = pow88 * pow1694; + local pow1696 = pow88 * pow1695; + local pow1697 = pow88 * pow1696; + local pow1698 = pow88 * pow1697; + local pow1699 = pow88 * pow1698; + local pow1700 = pow88 * pow1699; + local pow1701 = pow88 * pow1700; + local pow1702 = pow88 * pow1701; + local pow1703 = pow88 * pow1702; + local pow1704 = pow88 * pow1703; + local pow1705 = pow88 * pow1704; + local pow1706 = pow88 * pow1705; + local pow1707 = pow568 * pow1706; + local pow1708 = pow20 * pow1707; + local pow1709 = pow20 * pow1708; + local pow1710 = pow20 * pow1709; + local pow1711 = pow20 * pow1710; + local pow1712 = pow20 * pow1711; + local pow1713 = pow20 * pow1712; + local pow1714 = pow20 * pow1713; + local pow1715 = pow20 * pow1714; + local pow1716 = pow20 * pow1715; + local pow1717 = pow20 * pow1716; + local pow1718 = pow20 * pow1717; + local pow1719 = pow20 * pow1718; + local pow1720 = pow20 * pow1719; + local pow1721 = pow20 * pow1720; + local pow1722 = pow20 * pow1721; + local pow1723 = pow20 * pow1722; + local pow1724 = pow20 * pow1723; + local pow1725 = pow20 * pow1724; + local pow1726 = pow20 * pow1725; + local pow1727 = pow20 * pow1726; + local pow1728 = pow20 * pow1727; + local pow1729 = pow20 * pow1728; + local pow1730 = pow20 * pow1729; + local pow1731 = pow781 * pow1707; + local pow1732 = pow20 * pow1731; + local pow1733 = pow20 * pow1732; + local pow1734 = pow20 * pow1733; + local pow1735 = pow20 * pow1734; + local pow1736 = pow20 * pow1735; + local pow1737 = pow20 * pow1736; + local pow1738 = pow20 * pow1737; + local pow1739 = pow20 * pow1738; + local pow1740 = pow20 * pow1739; + local pow1741 = pow20 * pow1740; + local pow1742 = pow20 * pow1741; + local pow1743 = pow20 * pow1742; + local pow1744 = pow20 * pow1743; + local pow1745 = pow20 * pow1744; + local pow1746 = pow20 * pow1745; + local pow1747 = pow20 * pow1746; + local pow1748 = pow20 * pow1747; + local pow1749 = pow20 * pow1748; + local pow1750 = pow20 * pow1749; + local pow1751 = pow20 * pow1750; + local pow1752 = pow20 * pow1751; + local pow1753 = pow20 * pow1752; + local pow1754 = pow20 * pow1753; + local pow1755 = pow781 * pow1731; + local pow1756 = pow20 * pow1755; + local pow1757 = pow20 * pow1756; + local pow1758 = pow20 * pow1757; + local pow1759 = pow20 * pow1758; + local pow1760 = pow20 * pow1759; + local pow1761 = pow20 * pow1760; + local pow1762 = pow20 * pow1761; + local pow1763 = pow20 * pow1762; + local pow1764 = pow20 * pow1763; + local pow1765 = pow20 * pow1764; + local pow1766 = pow20 * pow1765; + local pow1767 = pow20 * pow1766; + local pow1768 = pow20 * pow1767; + local pow1769 = pow20 * pow1768; + local pow1770 = pow20 * pow1769; + local pow1771 = pow20 * pow1770; + local pow1772 = pow20 * pow1771; + local pow1773 = pow20 * pow1772; + local pow1774 = pow20 * pow1773; + local pow1775 = pow20 * pow1774; + local pow1776 = pow20 * pow1775; + local pow1777 = pow20 * pow1776; + local pow1778 = pow20 * pow1777; + local pow1779 = pow781 * pow1755; + local pow1780 = pow20 * pow1779; + local pow1781 = pow20 * pow1780; + local pow1782 = pow20 * pow1781; + local pow1783 = pow20 * pow1782; + local pow1784 = pow20 * pow1783; + local pow1785 = pow20 * pow1784; + local pow1786 = pow20 * pow1785; + local pow1787 = pow20 * pow1786; + local pow1788 = pow20 * pow1787; + local pow1789 = pow20 * pow1788; + local pow1790 = pow20 * pow1789; + local pow1791 = pow20 * pow1790; + local pow1792 = pow20 * pow1791; + local pow1793 = pow20 * pow1792; + local pow1794 = pow20 * pow1793; + local pow1795 = pow20 * pow1794; + local pow1796 = pow20 * pow1795; + local pow1797 = pow20 * pow1796; + local pow1798 = pow20 * pow1797; + local pow1799 = pow20 * pow1798; + local pow1800 = pow20 * pow1799; + local pow1801 = pow20 * pow1800; + local pow1802 = pow20 * pow1801; + local pow1803 = pow781 * pow1779; + local pow1804 = pow20 * pow1803; + local pow1805 = pow20 * pow1804; + local pow1806 = pow20 * pow1805; + local pow1807 = pow20 * pow1806; + local pow1808 = pow20 * pow1807; + local pow1809 = pow20 * pow1808; + local pow1810 = pow20 * pow1809; + local pow1811 = pow20 * pow1810; + local pow1812 = pow20 * pow1811; + local pow1813 = pow20 * pow1812; + local pow1814 = pow20 * pow1813; + local pow1815 = pow20 * pow1814; + local pow1816 = pow20 * pow1815; + local pow1817 = pow20 * pow1816; + local pow1818 = pow20 * pow1817; + local pow1819 = pow20 * pow1818; + local pow1820 = pow20 * pow1819; + local pow1821 = pow20 * pow1820; + local pow1822 = pow20 * pow1821; + local pow1823 = pow20 * pow1822; + local pow1824 = pow20 * pow1823; + local pow1825 = pow20 * pow1824; + local pow1826 = pow20 * pow1825; + local pow1827 = pow67 * pow1826; + local pow1828 = pow88 * pow1827; + local pow1829 = pow88 * pow1828; + local pow1830 = pow88 * pow1829; + local pow1831 = pow88 * pow1830; + local pow1832 = pow88 * pow1831; + local pow1833 = pow88 * pow1832; + local pow1834 = pow88 * pow1833; + local pow1835 = pow88 * pow1834; + local pow1836 = pow88 * pow1835; + local pow1837 = pow88 * pow1836; + local pow1838 = pow88 * pow1837; + local pow1839 = pow88 * pow1838; + local pow1840 = pow88 * pow1839; + local pow1841 = pow88 * pow1840; + local pow1842 = pow88 * pow1841; + local pow1843 = pow20 * pow1842; + local pow1844 = pow20 * pow1843; + local pow1845 = pow20 * pow1844; + local pow1846 = pow20 * pow1845; + local pow1847 = pow20 * pow1846; + local pow1848 = pow20 * pow1847; + local pow1849 = pow20 * pow1848; + local pow1850 = pow20 * pow1849; + local pow1851 = pow20 * pow1850; + local pow1852 = pow20 * pow1851; + local pow1853 = pow20 * pow1852; + local pow1854 = pow20 * pow1853; + local pow1855 = pow20 * pow1854; + local pow1856 = pow20 * pow1855; + local pow1857 = pow20 * pow1856; + local pow1858 = pow20 * pow1857; + local pow1859 = pow20 * pow1858; + local pow1860 = pow20 * pow1859; + local pow1861 = pow20 * pow1860; + local pow1862 = pow20 * pow1861; + local pow1863 = pow20 * pow1862; + local pow1864 = pow20 * pow1863; + local pow1865 = pow20 * pow1864; + local pow1866 = pow67 * pow1865; + local pow1867 = pow88 * pow1866; + local pow1868 = pow88 * pow1867; + local pow1869 = pow88 * pow1868; + local pow1870 = pow88 * pow1869; + local pow1871 = pow88 * pow1870; + local pow1872 = pow88 * pow1871; + local pow1873 = pow568 * pow1872; + local pow1874 = pow20 * pow1873; + local pow1875 = pow20 * pow1874; + local pow1876 = pow20 * pow1875; + local pow1877 = pow20 * pow1876; + local pow1878 = pow20 * pow1877; + local pow1879 = pow20 * pow1878; + local pow1880 = pow20 * pow1879; + local pow1881 = pow20 * pow1880; + local pow1882 = pow20 * pow1881; + local pow1883 = pow20 * pow1882; + local pow1884 = pow20 * pow1883; + local pow1885 = pow20 * pow1884; + local pow1886 = pow20 * pow1885; + local pow1887 = pow20 * pow1886; + local pow1888 = pow20 * pow1887; + local pow1889 = pow20 * pow1888; + local pow1890 = pow20 * pow1889; + local pow1891 = pow20 * pow1890; + local pow1892 = pow20 * pow1891; + local pow1893 = pow20 * pow1892; + local pow1894 = pow20 * pow1893; + local pow1895 = pow20 * pow1894; + local pow1896 = pow20 * pow1895; + local pow1897 = pow67 * pow1896; + local pow1898 = pow88 * pow1897; + local pow1899 = pow88 * pow1898; + local pow1900 = pow88 * pow1899; + local pow1901 = pow88 * pow1900; + local pow1902 = pow88 * pow1901; + local pow1903 = pow88 * pow1902; + local pow1904 = pow88 * pow1903; + local pow1905 = pow88 * pow1904; + local pow1906 = pow88 * pow1905; + local pow1907 = pow88 * pow1906; + local pow1908 = pow88 * pow1907; + local pow1909 = pow88 * pow1908; + local pow1910 = pow88 * pow1909; + local pow1911 = pow88 * pow1910; + local pow1912 = pow88 * pow1911; + local pow1913 = pow20 * pow1912; + local pow1914 = pow20 * pow1913; + local pow1915 = pow20 * pow1914; + local pow1916 = pow20 * pow1915; + local pow1917 = pow20 * pow1916; + local pow1918 = pow20 * pow1917; + local pow1919 = pow20 * pow1918; + local pow1920 = pow20 * pow1919; + local pow1921 = pow20 * pow1920; + local pow1922 = pow20 * pow1921; + local pow1923 = pow20 * pow1922; + local pow1924 = pow20 * pow1923; + local pow1925 = pow20 * pow1924; + local pow1926 = pow20 * pow1925; + local pow1927 = pow20 * pow1926; + local pow1928 = pow20 * pow1927; + local pow1929 = pow20 * pow1928; + local pow1930 = pow20 * pow1929; + local pow1931 = pow20 * pow1930; + local pow1932 = pow20 * pow1931; + local pow1933 = pow20 * pow1932; + local pow1934 = pow20 * pow1933; + local pow1935 = pow20 * pow1934; + local pow1936 = pow67 * pow1935; + local pow1937 = pow88 * pow1936; + local pow1938 = pow88 * pow1937; + local pow1939 = pow88 * pow1938; + local pow1940 = pow88 * pow1939; + local pow1941 = pow88 * pow1940; + local pow1942 = pow88 * pow1941; + local pow1943 = pow568 * pow1942; + local pow1944 = pow20 * pow1943; + local pow1945 = pow20 * pow1944; + local pow1946 = pow20 * pow1945; + local pow1947 = pow20 * pow1946; + local pow1948 = pow20 * pow1947; + local pow1949 = pow20 * pow1948; + local pow1950 = pow20 * pow1949; + local pow1951 = pow20 * pow1950; + local pow1952 = pow20 * pow1951; + local pow1953 = pow20 * pow1952; + local pow1954 = pow20 * pow1953; + local pow1955 = pow20 * pow1954; + local pow1956 = pow20 * pow1955; + local pow1957 = pow20 * pow1956; + local pow1958 = pow20 * pow1957; + local pow1959 = pow20 * pow1958; + local pow1960 = pow20 * pow1959; + local pow1961 = pow20 * pow1960; + local pow1962 = pow20 * pow1961; + local pow1963 = pow20 * pow1962; + local pow1964 = pow20 * pow1963; + local pow1965 = pow20 * pow1964; + local pow1966 = pow20 * pow1965; + local pow1967 = pow67 * pow1966; + local pow1968 = pow88 * pow1967; + local pow1969 = pow88 * pow1968; + local pow1970 = pow88 * pow1969; + local pow1971 = pow88 * pow1970; + local pow1972 = pow88 * pow1971; + local pow1973 = pow88 * pow1972; + local pow1974 = pow88 * pow1973; + local pow1975 = pow88 * pow1974; + local pow1976 = pow88 * pow1975; + local pow1977 = pow88 * pow1976; + local pow1978 = pow88 * pow1977; + local pow1979 = pow88 * pow1978; + local pow1980 = pow88 * pow1979; + local pow1981 = pow88 * pow1980; + local pow1982 = pow88 * pow1981; + local pow1983 = pow20 * pow1982; + local pow1984 = pow20 * pow1983; + local pow1985 = pow20 * pow1984; + local pow1986 = pow20 * pow1985; + local pow1987 = pow20 * pow1986; + local pow1988 = pow20 * pow1987; + local pow1989 = pow20 * pow1988; + local pow1990 = pow20 * pow1989; + local pow1991 = pow20 * pow1990; + local pow1992 = pow20 * pow1991; + local pow1993 = pow20 * pow1992; + local pow1994 = pow20 * pow1993; + local pow1995 = pow20 * pow1994; + local pow1996 = pow20 * pow1995; + local pow1997 = pow20 * pow1996; + local pow1998 = pow20 * pow1997; + local pow1999 = pow20 * pow1998; + local pow2000 = pow20 * pow1999; + local pow2001 = pow20 * pow2000; + local pow2002 = pow20 * pow2001; + local pow2003 = pow20 * pow2002; + local pow2004 = pow20 * pow2003; + local pow2005 = pow20 * pow2004; + local pow2006 = pow67 * pow2005; + local pow2007 = pow88 * pow2006; + local pow2008 = pow88 * pow2007; + local pow2009 = pow88 * pow2008; + local pow2010 = pow88 * pow2009; + local pow2011 = pow88 * pow2010; + local pow2012 = pow88 * pow2011; + local pow2013 = pow568 * pow2012; + local pow2014 = pow20 * pow2013; + local pow2015 = pow20 * pow2014; + local pow2016 = pow20 * pow2015; + local pow2017 = pow20 * pow2016; + local pow2018 = pow20 * pow2017; + local pow2019 = pow20 * pow2018; + local pow2020 = pow20 * pow2019; + local pow2021 = pow20 * pow2020; + local pow2022 = pow20 * pow2021; + local pow2023 = pow20 * pow2022; + local pow2024 = pow20 * pow2023; + local pow2025 = pow20 * pow2024; + local pow2026 = pow20 * pow2025; + local pow2027 = pow20 * pow2026; + local pow2028 = pow20 * pow2027; + local pow2029 = pow20 * pow2028; + local pow2030 = pow20 * pow2029; + local pow2031 = pow20 * pow2030; + local pow2032 = pow20 * pow2031; + local pow2033 = pow20 * pow2032; + local pow2034 = pow20 * pow2033; + local pow2035 = pow20 * pow2034; + local pow2036 = pow20 * pow2035; + local pow2037 = pow781 * pow2013; + local pow2038 = pow20 * pow2037; + local pow2039 = pow20 * pow2038; + local pow2040 = pow20 * pow2039; + local pow2041 = pow20 * pow2040; + local pow2042 = pow20 * pow2041; + local pow2043 = pow20 * pow2042; + local pow2044 = pow20 * pow2043; + local pow2045 = pow20 * pow2044; + local pow2046 = pow20 * pow2045; + local pow2047 = pow20 * pow2046; + local pow2048 = pow20 * pow2047; + local pow2049 = pow20 * pow2048; + local pow2050 = pow20 * pow2049; + local pow2051 = pow20 * pow2050; + local pow2052 = pow20 * pow2051; + local pow2053 = pow20 * pow2052; + local pow2054 = pow20 * pow2053; + local pow2055 = pow20 * pow2054; + local pow2056 = pow20 * pow2055; + local pow2057 = pow20 * pow2056; + local pow2058 = pow20 * pow2057; + local pow2059 = pow20 * pow2058; + local pow2060 = pow20 * pow2059; + local pow2061 = pow781 * pow2037; + local pow2062 = pow20 * pow2061; + local pow2063 = pow20 * pow2062; + local pow2064 = pow20 * pow2063; + local pow2065 = pow20 * pow2064; + local pow2066 = pow20 * pow2065; + local pow2067 = pow20 * pow2066; + local pow2068 = pow20 * pow2067; + local pow2069 = pow20 * pow2068; + local pow2070 = pow20 * pow2069; + local pow2071 = pow20 * pow2070; + local pow2072 = pow20 * pow2071; + local pow2073 = pow20 * pow2072; + local pow2074 = pow20 * pow2073; + local pow2075 = pow20 * pow2074; + local pow2076 = pow20 * pow2075; + local pow2077 = pow20 * pow2076; + local pow2078 = pow20 * pow2077; + local pow2079 = pow20 * pow2078; + local pow2080 = pow20 * pow2079; + local pow2081 = pow20 * pow2080; + local pow2082 = pow20 * pow2081; + local pow2083 = pow20 * pow2082; + local pow2084 = pow20 * pow2083; + local pow2085 = pow781 * pow2061; + local pow2086 = pow20 * pow2085; + local pow2087 = pow20 * pow2086; + local pow2088 = pow20 * pow2087; + local pow2089 = pow20 * pow2088; + local pow2090 = pow20 * pow2089; + local pow2091 = pow20 * pow2090; + local pow2092 = pow20 * pow2091; + local pow2093 = pow20 * pow2092; + local pow2094 = pow20 * pow2093; + local pow2095 = pow20 * pow2094; + local pow2096 = pow20 * pow2095; + local pow2097 = pow20 * pow2096; + local pow2098 = pow20 * pow2097; + local pow2099 = pow20 * pow2098; + local pow2100 = pow20 * pow2099; + local pow2101 = pow20 * pow2100; + local pow2102 = pow20 * pow2101; + local pow2103 = pow20 * pow2102; + local pow2104 = pow20 * pow2103; + local pow2105 = pow20 * pow2104; + local pow2106 = pow20 * pow2105; + local pow2107 = pow20 * pow2106; + local pow2108 = pow20 * pow2107; + local pow2109 = pow781 * pow2085; + local pow2110 = pow20 * pow2109; + local pow2111 = pow20 * pow2110; + local pow2112 = pow20 * pow2111; + local pow2113 = pow20 * pow2112; + local pow2114 = pow20 * pow2113; + local pow2115 = pow20 * pow2114; + local pow2116 = pow20 * pow2115; + local pow2117 = pow20 * pow2116; + local pow2118 = pow20 * pow2117; + local pow2119 = pow20 * pow2118; + local pow2120 = pow20 * pow2119; + local pow2121 = pow20 * pow2120; + local pow2122 = pow20 * pow2121; + local pow2123 = pow20 * pow2122; + local pow2124 = pow20 * pow2123; + local pow2125 = pow20 * pow2124; + local pow2126 = pow20 * pow2125; + local pow2127 = pow20 * pow2126; + local pow2128 = pow20 * pow2127; + local pow2129 = pow20 * pow2128; + local pow2130 = pow20 * pow2129; + local pow2131 = pow20 * pow2130; + local pow2132 = pow20 * pow2131; + local pow2133 = pow781 * pow2109; + local pow2134 = pow20 * pow2133; + local pow2135 = pow20 * pow2134; + local pow2136 = pow20 * pow2135; + local pow2137 = pow20 * pow2136; + local pow2138 = pow20 * pow2137; + local pow2139 = pow20 * pow2138; + local pow2140 = pow20 * pow2139; + local pow2141 = pow20 * pow2140; + local pow2142 = pow20 * pow2141; + local pow2143 = pow20 * pow2142; + local pow2144 = pow20 * pow2143; + local pow2145 = pow20 * pow2144; + local pow2146 = pow20 * pow2145; + local pow2147 = pow20 * pow2146; + local pow2148 = pow20 * pow2147; + local pow2149 = pow20 * pow2148; + local pow2150 = pow20 * pow2149; + local pow2151 = pow20 * pow2150; + local pow2152 = pow20 * pow2151; + local pow2153 = pow20 * pow2152; + local pow2154 = pow20 * pow2153; + local pow2155 = pow20 * pow2154; + local pow2156 = pow20 * pow2155; + local pow2157 = pow781 * pow2133; + local pow2158 = pow20 * pow2157; + local pow2159 = pow20 * pow2158; + local pow2160 = pow20 * pow2159; + local pow2161 = pow20 * pow2160; + local pow2162 = pow20 * pow2161; + local pow2163 = pow20 * pow2162; + local pow2164 = pow20 * pow2163; + local pow2165 = pow20 * pow2164; + local pow2166 = pow20 * pow2165; + local pow2167 = pow20 * pow2166; + local pow2168 = pow20 * pow2167; + local pow2169 = pow20 * pow2168; + local pow2170 = pow20 * pow2169; + local pow2171 = pow20 * pow2170; + local pow2172 = pow20 * pow2171; + local pow2173 = pow20 * pow2172; + local pow2174 = pow20 * pow2173; + local pow2175 = pow20 * pow2174; + local pow2176 = pow20 * pow2175; + local pow2177 = pow20 * pow2176; + local pow2178 = pow20 * pow2177; + local pow2179 = pow20 * pow2178; + local pow2180 = pow20 * pow2179; + local pow2181 = pow67 * pow2180; + local pow2182 = pow88 * pow2181; + local pow2183 = pow88 * pow2182; + local pow2184 = pow88 * pow2183; + local pow2185 = pow88 * pow2184; + local pow2186 = pow88 * pow2185; + local pow2187 = pow88 * pow2186; + local pow2188 = pow88 * pow2187; + local pow2189 = pow88 * pow2188; + local pow2190 = pow88 * pow2189; + local pow2191 = pow88 * pow2190; + local pow2192 = pow88 * pow2191; + local pow2193 = pow88 * pow2192; + local pow2194 = pow88 * pow2193; + local pow2195 = pow88 * pow2194; + local pow2196 = pow88 * pow2195; + local pow2197 = pow20 * pow2196; + local pow2198 = pow20 * pow2197; + local pow2199 = pow20 * pow2198; + local pow2200 = pow20 * pow2199; + local pow2201 = pow20 * pow2200; + local pow2202 = pow20 * pow2201; + local pow2203 = pow20 * pow2202; + local pow2204 = pow20 * pow2203; + local pow2205 = pow20 * pow2204; + local pow2206 = pow20 * pow2205; + local pow2207 = pow20 * pow2206; + local pow2208 = pow20 * pow2207; + local pow2209 = pow20 * pow2208; + local pow2210 = pow20 * pow2209; + local pow2211 = pow20 * pow2210; + local pow2212 = pow20 * pow2211; + local pow2213 = pow20 * pow2212; + local pow2214 = pow20 * pow2213; + local pow2215 = pow20 * pow2214; + local pow2216 = pow20 * pow2215; + local pow2217 = pow20 * pow2216; + local pow2218 = pow20 * pow2217; + local pow2219 = pow20 * pow2218; + local pow2220 = pow67 * pow2219; + local pow2221 = pow88 * pow2220; + local pow2222 = pow88 * pow2221; + local pow2223 = pow88 * pow2222; + local pow2224 = pow88 * pow2223; + local pow2225 = pow88 * pow2224; + local pow2226 = pow88 * pow2225; + local pow2227 = pow88 * pow2226; + local pow2228 = pow88 * pow2227; + local pow2229 = pow88 * pow2228; + local pow2230 = pow88 * pow2229; + local pow2231 = pow88 * pow2230; + local pow2232 = pow88 * pow2231; + local pow2233 = pow208 * pow2232; + local pow2234 = pow20 * pow2233; + local pow2235 = pow20 * pow2234; + local pow2236 = pow20 * pow2235; + local pow2237 = pow20 * pow2236; + local pow2238 = pow20 * pow2237; + local pow2239 = pow20 * pow2238; + local pow2240 = pow20 * pow2239; + local pow2241 = pow20 * pow2240; + local pow2242 = pow20 * pow2241; + local pow2243 = pow20 * pow2242; + local pow2244 = pow20 * pow2243; + local pow2245 = pow20 * pow2244; + local pow2246 = pow20 * pow2245; + local pow2247 = pow20 * pow2246; + local pow2248 = pow20 * pow2247; + local pow2249 = pow20 * pow2248; + local pow2250 = pow20 * pow2249; + local pow2251 = pow20 * pow2250; + local pow2252 = pow20 * pow2251; + local pow2253 = pow20 * pow2252; + local pow2254 = pow20 * pow2253; + local pow2255 = pow20 * pow2254; + local pow2256 = pow20 * pow2255; + local pow2257 = pow67 * pow2256; + local pow2258 = pow88 * pow2257; + local pow2259 = pow88 * pow2258; + local pow2260 = pow88 * pow2259; + local pow2261 = pow88 * pow2260; + local pow2262 = pow88 * pow2261; + local pow2263 = pow88 * pow2262; + local pow2264 = pow88 * pow2263; + local pow2265 = pow88 * pow2264; + local pow2266 = pow88 * pow2265; + local pow2267 = pow88 * pow2266; + local pow2268 = pow88 * pow2267; + local pow2269 = pow88 * pow2268; + local pow2270 = pow88 * pow2269; + local pow2271 = pow88 * pow2270; + local pow2272 = pow88 * pow2271; + local pow2273 = pow20 * pow2272; + local pow2274 = pow20 * pow2273; + local pow2275 = pow20 * pow2274; + local pow2276 = pow20 * pow2275; + local pow2277 = pow20 * pow2276; + local pow2278 = pow20 * pow2277; + local pow2279 = pow20 * pow2278; + local pow2280 = pow20 * pow2279; + local pow2281 = pow20 * pow2280; + local pow2282 = pow20 * pow2281; + local pow2283 = pow20 * pow2282; + local pow2284 = pow20 * pow2283; + local pow2285 = pow20 * pow2284; + local pow2286 = pow20 * pow2285; + local pow2287 = pow20 * pow2286; + local pow2288 = pow20 * pow2287; + local pow2289 = pow20 * pow2288; + local pow2290 = pow20 * pow2289; + local pow2291 = pow20 * pow2290; + local pow2292 = pow20 * pow2291; + local pow2293 = pow20 * pow2292; + local pow2294 = pow20 * pow2293; + local pow2295 = pow20 * pow2294; + local pow2296 = pow67 * pow2295; + local pow2297 = pow88 * pow2296; + local pow2298 = pow88 * pow2297; + local pow2299 = pow88 * pow2298; + local pow2300 = pow88 * pow2299; + local pow2301 = pow88 * pow2300; + local pow2302 = pow88 * pow2301; + local pow2303 = pow88 * pow2302; + local pow2304 = pow88 * pow2303; + local pow2305 = pow88 * pow2304; + local pow2306 = pow88 * pow2305; + local pow2307 = pow88 * pow2306; + local pow2308 = pow88 * pow2307; + local pow2309 = pow208 * pow2308; + local pow2310 = pow20 * pow2309; + local pow2311 = pow20 * pow2310; + local pow2312 = pow20 * pow2311; + local pow2313 = pow20 * pow2312; + local pow2314 = pow20 * pow2313; + local pow2315 = pow20 * pow2314; + local pow2316 = pow20 * pow2315; + local pow2317 = pow20 * pow2316; + local pow2318 = pow20 * pow2317; + local pow2319 = pow20 * pow2318; + local pow2320 = pow20 * pow2319; + local pow2321 = pow20 * pow2320; + local pow2322 = pow20 * pow2321; + local pow2323 = pow20 * pow2322; + local pow2324 = pow20 * pow2323; + local pow2325 = pow20 * pow2324; + local pow2326 = pow20 * pow2325; + local pow2327 = pow20 * pow2326; + local pow2328 = pow20 * pow2327; + local pow2329 = pow20 * pow2328; + local pow2330 = pow20 * pow2329; + local pow2331 = pow20 * pow2330; + local pow2332 = pow20 * pow2331; + local pow2333 = pow67 * pow2332; + local pow2334 = pow88 * pow2333; + local pow2335 = pow88 * pow2334; + local pow2336 = pow88 * pow2335; + local pow2337 = pow88 * pow2336; + local pow2338 = pow88 * pow2337; + local pow2339 = pow88 * pow2338; + local pow2340 = pow88 * pow2339; + local pow2341 = pow88 * pow2340; + local pow2342 = pow88 * pow2341; + local pow2343 = pow88 * pow2342; + local pow2344 = pow88 * pow2343; + local pow2345 = pow88 * pow2344; + local pow2346 = pow88 * pow2345; + local pow2347 = pow88 * pow2346; + local pow2348 = pow88 * pow2347; + local pow2349 = pow20 * pow2348; + local pow2350 = pow20 * pow2349; + local pow2351 = pow20 * pow2350; + local pow2352 = pow20 * pow2351; + local pow2353 = pow20 * pow2352; + local pow2354 = pow20 * pow2353; + local pow2355 = pow20 * pow2354; + local pow2356 = pow20 * pow2355; + local pow2357 = pow20 * pow2356; + local pow2358 = pow20 * pow2357; + local pow2359 = pow20 * pow2358; + local pow2360 = pow20 * pow2359; + local pow2361 = pow20 * pow2360; + local pow2362 = pow20 * pow2361; + local pow2363 = pow20 * pow2362; + local pow2364 = pow20 * pow2363; + local pow2365 = pow20 * pow2364; + local pow2366 = pow20 * pow2365; + local pow2367 = pow20 * pow2366; + local pow2368 = pow20 * pow2367; + local pow2369 = pow20 * pow2368; + local pow2370 = pow20 * pow2369; + local pow2371 = pow20 * pow2370; + local pow2372 = pow67 * pow2371; + local pow2373 = pow88 * pow2372; + local pow2374 = pow88 * pow2373; + local pow2375 = pow88 * pow2374; + local pow2376 = pow88 * pow2375; + local pow2377 = pow88 * pow2376; + local pow2378 = pow88 * pow2377; + local pow2379 = pow88 * pow2378; + local pow2380 = pow88 * pow2379; + local pow2381 = pow88 * pow2380; + local pow2382 = pow88 * pow2381; + local pow2383 = pow88 * pow2382; + local pow2384 = pow88 * pow2383; + local pow2385 = pow208 * pow2384; + local pow2386 = pow20 * pow2385; + local pow2387 = pow20 * pow2386; + local pow2388 = pow20 * pow2387; + local pow2389 = pow20 * pow2388; + local pow2390 = pow20 * pow2389; + local pow2391 = pow20 * pow2390; + local pow2392 = pow20 * pow2391; + local pow2393 = pow20 * pow2392; + local pow2394 = pow20 * pow2393; + local pow2395 = pow20 * pow2394; + local pow2396 = pow20 * pow2395; + local pow2397 = pow20 * pow2396; + local pow2398 = pow20 * pow2397; + local pow2399 = pow20 * pow2398; + local pow2400 = pow20 * pow2399; + local pow2401 = pow20 * pow2400; + local pow2402 = pow20 * pow2401; + local pow2403 = pow20 * pow2402; + local pow2404 = pow20 * pow2403; + local pow2405 = pow20 * pow2404; + local pow2406 = pow20 * pow2405; + local pow2407 = pow20 * pow2406; + local pow2408 = pow20 * pow2407; + local pow2409 = pow67 * pow2408; + local pow2410 = pow88 * pow2409; + local pow2411 = pow88 * pow2410; + local pow2412 = pow88 * pow2411; + local pow2413 = pow88 * pow2412; + local pow2414 = pow88 * pow2413; + local pow2415 = pow88 * pow2414; + local pow2416 = pow88 * pow2415; + local pow2417 = pow88 * pow2416; + local pow2418 = pow88 * pow2417; + local pow2419 = pow88 * pow2418; + local pow2420 = pow88 * pow2419; + local pow2421 = pow88 * pow2420; + local pow2422 = pow88 * pow2421; + local pow2423 = pow88 * pow2422; + local pow2424 = pow88 * pow2423; + local pow2425 = pow20 * pow2424; + local pow2426 = pow20 * pow2425; + local pow2427 = pow20 * pow2426; + local pow2428 = pow20 * pow2427; + local pow2429 = pow20 * pow2428; + local pow2430 = pow20 * pow2429; + local pow2431 = pow20 * pow2430; + local pow2432 = pow20 * pow2431; + local pow2433 = pow20 * pow2432; + local pow2434 = pow20 * pow2433; + local pow2435 = pow20 * pow2434; + local pow2436 = pow20 * pow2435; + local pow2437 = pow20 * pow2436; + local pow2438 = pow20 * pow2437; + local pow2439 = pow20 * pow2438; + local pow2440 = pow20 * pow2439; + local pow2441 = pow20 * pow2440; + local pow2442 = pow20 * pow2441; + local pow2443 = pow20 * pow2442; + local pow2444 = pow20 * pow2443; + local pow2445 = pow20 * pow2444; + local pow2446 = pow20 * pow2445; + local pow2447 = pow20 * pow2446; + local pow2448 = pow67 * pow2447; + local pow2449 = pow88 * pow2448; + local pow2450 = pow88 * pow2449; + local pow2451 = pow88 * pow2450; + local pow2452 = pow88 * pow2451; + local pow2453 = pow88 * pow2452; + local pow2454 = pow88 * pow2453; + local pow2455 = pow88 * pow2454; + local pow2456 = pow88 * pow2455; + local pow2457 = pow88 * pow2456; + local pow2458 = pow88 * pow2457; + local pow2459 = pow88 * pow2458; + local pow2460 = pow88 * pow2459; + local pow2461 = pow208 * pow2460; + local pow2462 = pow20 * pow2461; + local pow2463 = pow20 * pow2462; + local pow2464 = pow20 * pow2463; + local pow2465 = pow20 * pow2464; + local pow2466 = pow20 * pow2465; + local pow2467 = pow20 * pow2466; + local pow2468 = pow20 * pow2467; + local pow2469 = pow20 * pow2468; + local pow2470 = pow20 * pow2469; + local pow2471 = pow20 * pow2470; + local pow2472 = pow20 * pow2471; + local pow2473 = pow20 * pow2472; + local pow2474 = pow20 * pow2473; + local pow2475 = pow20 * pow2474; + local pow2476 = pow20 * pow2475; + local pow2477 = pow20 * pow2476; + local pow2478 = pow20 * pow2477; + local pow2479 = pow20 * pow2478; + local pow2480 = pow20 * pow2479; + local pow2481 = pow20 * pow2480; + local pow2482 = pow20 * pow2481; + local pow2483 = pow20 * pow2482; + local pow2484 = pow20 * pow2483; + local pow2485 = pow67 * pow2484; + local pow2486 = pow88 * pow2485; + local pow2487 = pow88 * pow2486; + local pow2488 = pow88 * pow2487; + local pow2489 = pow88 * pow2488; + local pow2490 = pow88 * pow2489; + local pow2491 = pow88 * pow2490; + local pow2492 = pow88 * pow2491; + local pow2493 = pow88 * pow2492; + local pow2494 = pow88 * pow2493; + local pow2495 = pow88 * pow2494; + local pow2496 = pow88 * pow2495; + local pow2497 = pow88 * pow2496; + local pow2498 = pow88 * pow2497; + local pow2499 = pow88 * pow2498; + local pow2500 = pow88 * pow2499; + local pow2501 = pow20 * pow2500; + local pow2502 = pow20 * pow2501; + local pow2503 = pow20 * pow2502; + local pow2504 = pow20 * pow2503; + local pow2505 = pow20 * pow2504; + local pow2506 = pow20 * pow2505; + local pow2507 = pow20 * pow2506; + local pow2508 = pow20 * pow2507; + local pow2509 = pow20 * pow2508; + local pow2510 = pow20 * pow2509; + local pow2511 = pow20 * pow2510; + local pow2512 = pow20 * pow2511; + local pow2513 = pow20 * pow2512; + local pow2514 = pow20 * pow2513; + local pow2515 = pow20 * pow2514; + local pow2516 = pow20 * pow2515; + local pow2517 = pow20 * pow2516; + local pow2518 = pow20 * pow2517; + local pow2519 = pow20 * pow2518; + local pow2520 = pow20 * pow2519; + local pow2521 = pow20 * pow2520; + local pow2522 = pow20 * pow2521; + local pow2523 = pow20 * pow2522; + local pow2524 = pow67 * pow2523; + local pow2525 = pow88 * pow2524; + local pow2526 = pow88 * pow2525; + local pow2527 = pow88 * pow2526; + local pow2528 = pow88 * pow2527; + local pow2529 = pow88 * pow2528; + local pow2530 = pow88 * pow2529; + local pow2531 = pow88 * pow2530; + local pow2532 = pow88 * pow2531; + local pow2533 = pow88 * pow2532; + local pow2534 = pow88 * pow2533; + local pow2535 = pow88 * pow2534; + local pow2536 = pow88 * pow2535; + local pow2537 = pow208 * pow2536; + local pow2538 = pow20 * pow2537; + local pow2539 = pow20 * pow2538; + local pow2540 = pow20 * pow2539; + local pow2541 = pow20 * pow2540; + local pow2542 = pow20 * pow2541; + local pow2543 = pow20 * pow2542; + local pow2544 = pow20 * pow2543; + local pow2545 = pow20 * pow2544; + local pow2546 = pow20 * pow2545; + local pow2547 = pow20 * pow2546; + local pow2548 = pow20 * pow2547; + local pow2549 = pow20 * pow2548; + local pow2550 = pow20 * pow2549; + local pow2551 = pow20 * pow2550; + local pow2552 = pow20 * pow2551; + local pow2553 = pow20 * pow2552; + local pow2554 = pow20 * pow2553; + local pow2555 = pow20 * pow2554; + local pow2556 = pow20 * pow2555; + local pow2557 = pow20 * pow2556; + local pow2558 = pow20 * pow2557; + local pow2559 = pow20 * pow2558; + local pow2560 = pow20 * pow2559; + local pow2561 = pow67 * pow2560; + local pow2562 = pow88 * pow2561; + local pow2563 = pow88 * pow2562; + local pow2564 = pow88 * pow2563; + local pow2565 = pow88 * pow2564; + local pow2566 = pow88 * pow2565; + local pow2567 = pow88 * pow2566; + local pow2568 = pow88 * pow2567; + local pow2569 = pow88 * pow2568; + local pow2570 = pow88 * pow2569; + local pow2571 = pow88 * pow2570; + local pow2572 = pow88 * pow2571; + local pow2573 = pow88 * pow2572; + local pow2574 = pow88 * pow2573; + local pow2575 = pow88 * pow2574; + local pow2576 = pow88 * pow2575; + local pow2577 = pow20 * pow2576; + local pow2578 = pow20 * pow2577; + local pow2579 = pow20 * pow2578; + local pow2580 = pow20 * pow2579; + local pow2581 = pow20 * pow2580; + local pow2582 = pow20 * pow2581; + local pow2583 = pow20 * pow2582; + local pow2584 = pow20 * pow2583; + local pow2585 = pow20 * pow2584; + local pow2586 = pow20 * pow2585; + local pow2587 = pow20 * pow2586; + local pow2588 = pow20 * pow2587; + local pow2589 = pow20 * pow2588; + local pow2590 = pow20 * pow2589; + local pow2591 = pow20 * pow2590; + local pow2592 = pow20 * pow2591; + local pow2593 = pow20 * pow2592; + local pow2594 = pow20 * pow2593; + local pow2595 = pow20 * pow2594; + local pow2596 = pow20 * pow2595; + local pow2597 = pow20 * pow2596; + local pow2598 = pow20 * pow2597; + local pow2599 = pow20 * pow2598; + local pow2600 = pow20 * pow2599; + local pow2601 = pow20 * pow2600; + local pow2602 = pow20 * pow2601; + local pow2603 = pow20 * pow2602; + local pow2604 = pow20 * pow2603; + local pow2605 = pow20 * pow2604; + local pow2606 = pow29 * pow2605; + local pow2607 = pow20 * pow2606; + local pow2608 = pow20 * pow2607; + local pow2609 = pow20 * pow2608; + local pow2610 = pow20 * pow2609; + local pow2611 = pow20 * pow2610; + local pow2612 = pow20 * pow2611; + local pow2613 = pow20 * pow2612; + local pow2614 = pow20 * pow2613; + local pow2615 = pow20 * pow2614; + local pow2616 = pow20 * pow2615; + local pow2617 = pow20 * pow2616; + local pow2618 = pow20 * pow2617; + local pow2619 = pow20 * pow2618; + local pow2620 = pow20 * pow2619; + local pow2621 = pow20 * pow2620; + local pow2622 = pow20 * pow2621; + local pow2623 = pow20 * pow2622; + local pow2624 = pow20 * pow2623; + local pow2625 = pow20 * pow2624; + local pow2626 = pow20 * pow2625; + local pow2627 = pow20 * pow2626; + local pow2628 = pow20 * pow2627; + local pow2629 = pow20 * pow2628; + local pow2630 = pow20 * pow2629; + local pow2631 = pow20 * pow2630; + local pow2632 = pow20 * pow2631; + local pow2633 = pow20 * pow2632; + local pow2634 = pow20 * pow2633; + local pow2635 = pow20 * pow2634; + local pow2636 = pow29 * pow2635; + local pow2637 = pow20 * pow2636; + local pow2638 = pow20 * pow2637; + local pow2639 = pow20 * pow2638; + local pow2640 = pow20 * pow2639; + local pow2641 = pow20 * pow2640; + local pow2642 = pow20 * pow2641; + local pow2643 = pow20 * pow2642; + local pow2644 = pow20 * pow2643; + local pow2645 = pow20 * pow2644; + local pow2646 = pow20 * pow2645; + local pow2647 = pow20 * pow2646; + local pow2648 = pow20 * pow2647; + local pow2649 = pow20 * pow2648; + local pow2650 = pow20 * pow2649; + local pow2651 = pow20 * pow2650; + local pow2652 = pow20 * pow2651; + local pow2653 = pow20 * pow2652; + local pow2654 = pow20 * pow2653; + local pow2655 = pow20 * pow2654; + local pow2656 = pow20 * pow2655; + local pow2657 = pow20 * pow2656; + local pow2658 = pow20 * pow2657; + local pow2659 = pow20 * pow2658; + local pow2660 = pow20 * pow2659; + local pow2661 = pow20 * pow2660; + local pow2662 = pow20 * pow2661; + local pow2663 = pow20 * pow2662; + local pow2664 = pow20 * pow2663; + local pow2665 = pow20 * pow2664; + local pow2666 = pow29 * pow2665; + local pow2667 = pow20 * pow2666; + local pow2668 = pow20 * pow2667; + local pow2669 = pow20 * pow2668; + local pow2670 = pow20 * pow2669; + local pow2671 = pow20 * pow2670; + local pow2672 = pow20 * pow2671; + local pow2673 = pow20 * pow2672; + local pow2674 = pow20 * pow2673; + local pow2675 = pow20 * pow2674; + local pow2676 = pow20 * pow2675; + local pow2677 = pow20 * pow2676; + local pow2678 = pow20 * pow2677; + local pow2679 = pow20 * pow2678; + local pow2680 = pow20 * pow2679; + local pow2681 = pow20 * pow2680; + local pow2682 = pow20 * pow2681; + local pow2683 = pow20 * pow2682; + local pow2684 = pow20 * pow2683; + local pow2685 = pow20 * pow2684; + local pow2686 = pow20 * pow2685; + local pow2687 = pow20 * pow2686; + local pow2688 = pow20 * pow2687; + local pow2689 = pow20 * pow2688; + local pow2690 = pow20 * pow2689; + local pow2691 = pow20 * pow2690; + local pow2692 = pow20 * pow2691; + local pow2693 = pow20 * pow2692; + local pow2694 = pow20 * pow2693; + local pow2695 = pow20 * pow2694; + local pow2696 = pow29 * pow2695; + local pow2697 = pow20 * pow2696; + local pow2698 = pow20 * pow2697; + local pow2699 = pow20 * pow2698; + local pow2700 = pow20 * pow2699; + local pow2701 = pow20 * pow2700; + local pow2702 = pow20 * pow2701; + local pow2703 = pow20 * pow2702; + local pow2704 = pow20 * pow2703; + local pow2705 = pow20 * pow2704; + local pow2706 = pow20 * pow2705; + local pow2707 = pow20 * pow2706; + local pow2708 = pow20 * pow2707; + local pow2709 = pow20 * pow2708; + local pow2710 = pow20 * pow2709; + local pow2711 = pow20 * pow2710; + local pow2712 = pow20 * pow2711; + local pow2713 = pow20 * pow2712; + local pow2714 = pow20 * pow2713; + local pow2715 = pow20 * pow2714; + local pow2716 = pow20 * pow2715; + local pow2717 = pow20 * pow2716; + local pow2718 = pow20 * pow2717; + local pow2719 = pow20 * pow2718; + local pow2720 = pow20 * pow2719; + local pow2721 = pow20 * pow2720; + local pow2722 = pow20 * pow2721; + local pow2723 = pow20 * pow2722; + local pow2724 = pow20 * pow2723; + local pow2725 = pow20 * pow2724; + local pow2726 = pow29 * pow2725; + local pow2727 = pow20 * pow2726; + local pow2728 = pow20 * pow2727; + local pow2729 = pow20 * pow2728; + local pow2730 = pow20 * pow2729; + local pow2731 = pow20 * pow2730; + local pow2732 = pow20 * pow2731; + local pow2733 = pow20 * pow2732; + local pow2734 = pow20 * pow2733; + local pow2735 = pow20 * pow2734; + local pow2736 = pow20 * pow2735; + local pow2737 = pow20 * pow2736; + local pow2738 = pow20 * pow2737; + local pow2739 = pow20 * pow2738; + local pow2740 = pow20 * pow2739; + local pow2741 = pow20 * pow2740; + local pow2742 = pow20 * pow2741; + local pow2743 = pow20 * pow2742; + local pow2744 = pow20 * pow2743; + local pow2745 = pow20 * pow2744; + local pow2746 = pow20 * pow2745; + local pow2747 = pow20 * pow2746; + local pow2748 = pow20 * pow2747; + local pow2749 = pow20 * pow2748; + local pow2750 = pow20 * pow2749; + local pow2751 = pow20 * pow2750; + local pow2752 = pow20 * pow2751; + local pow2753 = pow20 * pow2752; + local pow2754 = pow20 * pow2753; + local pow2755 = pow20 * pow2754; + local pow2756 = pow29 * pow2755; + local pow2757 = pow20 * pow2756; + local pow2758 = pow20 * pow2757; + local pow2759 = pow20 * pow2758; + local pow2760 = pow20 * pow2759; + local pow2761 = pow20 * pow2760; + local pow2762 = pow20 * pow2761; + local pow2763 = pow20 * pow2762; + local pow2764 = pow20 * pow2763; + local pow2765 = pow20 * pow2764; + local pow2766 = pow20 * pow2765; + local pow2767 = pow20 * pow2766; + local pow2768 = pow20 * pow2767; + local pow2769 = pow20 * pow2768; + local pow2770 = pow20 * pow2769; + local pow2771 = pow20 * pow2770; + local pow2772 = pow20 * pow2771; + local pow2773 = pow20 * pow2772; + local pow2774 = pow20 * pow2773; + local pow2775 = pow20 * pow2774; + local pow2776 = pow20 * pow2775; + local pow2777 = pow20 * pow2776; + local pow2778 = pow20 * pow2777; + local pow2779 = pow20 * pow2778; + local pow2780 = pow20 * pow2779; + local pow2781 = pow20 * pow2780; + local pow2782 = pow20 * pow2781; + local pow2783 = pow20 * pow2782; + local pow2784 = pow20 * pow2783; + local pow2785 = pow20 * pow2784; + local pow2786 = pow29 * pow2785; + local pow2787 = pow20 * pow2786; + local pow2788 = pow20 * pow2787; + local pow2789 = pow20 * pow2788; + local pow2790 = pow20 * pow2789; + local pow2791 = pow20 * pow2790; + local pow2792 = pow20 * pow2791; + local pow2793 = pow20 * pow2792; + local pow2794 = pow20 * pow2793; + local pow2795 = pow20 * pow2794; + local pow2796 = pow20 * pow2795; + local pow2797 = pow20 * pow2796; + local pow2798 = pow20 * pow2797; + local pow2799 = pow20 * pow2798; + local pow2800 = pow20 * pow2799; + local pow2801 = pow20 * pow2800; + local pow2802 = pow20 * pow2801; + local pow2803 = pow20 * pow2802; + local pow2804 = pow20 * pow2803; + local pow2805 = pow20 * pow2804; + local pow2806 = pow20 * pow2805; + local pow2807 = pow20 * pow2806; + local pow2808 = pow20 * pow2807; + local pow2809 = pow20 * pow2808; + local pow2810 = pow20 * pow2809; + local pow2811 = pow20 * pow2810; + local pow2812 = pow20 * pow2811; + local pow2813 = pow20 * pow2812; + local pow2814 = pow20 * pow2813; + local pow2815 = pow20 * pow2814; + local pow2816 = pow29 * pow2815; + local pow2817 = pow20 * pow2816; + local pow2818 = pow20 * pow2817; + local pow2819 = pow20 * pow2818; + local pow2820 = pow20 * pow2819; + local pow2821 = pow20 * pow2820; + local pow2822 = pow20 * pow2821; + local pow2823 = pow20 * pow2822; + local pow2824 = pow20 * pow2823; + local pow2825 = pow20 * pow2824; + local pow2826 = pow20 * pow2825; + local pow2827 = pow20 * pow2826; + local pow2828 = pow20 * pow2827; + local pow2829 = pow20 * pow2828; + local pow2830 = pow20 * pow2829; + local pow2831 = pow20 * pow2830; + local pow2832 = pow20 * pow2831; + local pow2833 = pow20 * pow2832; + local pow2834 = pow20 * pow2833; + local pow2835 = pow20 * pow2834; + local pow2836 = pow20 * pow2835; + local pow2837 = pow20 * pow2836; + local pow2838 = pow20 * pow2837; + local pow2839 = pow20 * pow2838; + local pow2840 = pow20 * pow2839; + local pow2841 = pow20 * pow2840; + local pow2842 = pow20 * pow2841; + local pow2843 = pow20 * pow2842; + local pow2844 = pow20 * pow2843; + local pow2845 = pow20 * pow2844; + local pow2846 = pow29 * pow2845; + local pow2847 = pow20 * pow2846; + local pow2848 = pow20 * pow2847; + local pow2849 = pow20 * pow2848; + local pow2850 = pow20 * pow2849; + local pow2851 = pow20 * pow2850; + local pow2852 = pow20 * pow2851; + local pow2853 = pow20 * pow2852; + local pow2854 = pow20 * pow2853; + local pow2855 = pow20 * pow2854; + local pow2856 = pow20 * pow2855; + local pow2857 = pow20 * pow2856; + local pow2858 = pow20 * pow2857; + local pow2859 = pow20 * pow2858; + local pow2860 = pow20 * pow2859; + local pow2861 = pow20 * pow2860; + local pow2862 = pow20 * pow2861; + local pow2863 = pow20 * pow2862; + local pow2864 = pow20 * pow2863; + local pow2865 = pow20 * pow2864; + local pow2866 = pow20 * pow2865; + local pow2867 = pow20 * pow2866; + local pow2868 = pow20 * pow2867; + local pow2869 = pow20 * pow2868; + local pow2870 = pow20 * pow2869; + local pow2871 = pow20 * pow2870; + local pow2872 = pow20 * pow2871; + local pow2873 = pow20 * pow2872; + local pow2874 = pow20 * pow2873; + local pow2875 = pow20 * pow2874; + local pow2876 = pow29 * pow2875; + local pow2877 = pow20 * pow2876; + local pow2878 = pow20 * pow2877; + local pow2879 = pow20 * pow2878; + local pow2880 = pow20 * pow2879; + local pow2881 = pow20 * pow2880; + local pow2882 = pow20 * pow2881; + local pow2883 = pow20 * pow2882; + local pow2884 = pow20 * pow2883; + local pow2885 = pow20 * pow2884; + local pow2886 = pow20 * pow2885; + local pow2887 = pow20 * pow2886; + local pow2888 = pow20 * pow2887; + local pow2889 = pow20 * pow2888; + local pow2890 = pow20 * pow2889; + local pow2891 = pow20 * pow2890; + local pow2892 = pow20 * pow2891; + local pow2893 = pow20 * pow2892; + local pow2894 = pow20 * pow2893; + local pow2895 = pow20 * pow2894; + local pow2896 = pow20 * pow2895; + local pow2897 = pow20 * pow2896; + local pow2898 = pow20 * pow2897; + local pow2899 = pow20 * pow2898; + local pow2900 = pow20 * pow2899; + local pow2901 = pow20 * pow2900; + local pow2902 = pow20 * pow2901; + local pow2903 = pow20 * pow2902; + local pow2904 = pow20 * pow2903; + local pow2905 = pow20 * pow2904; + local pow2906 = pow29 * pow2905; + local pow2907 = pow20 * pow2906; + local pow2908 = pow20 * pow2907; + local pow2909 = pow20 * pow2908; + local pow2910 = pow20 * pow2909; + local pow2911 = pow20 * pow2910; + local pow2912 = pow20 * pow2911; + local pow2913 = pow20 * pow2912; + local pow2914 = pow20 * pow2913; + local pow2915 = pow20 * pow2914; + local pow2916 = pow20 * pow2915; + local pow2917 = pow20 * pow2916; + local pow2918 = pow20 * pow2917; + local pow2919 = pow20 * pow2918; + local pow2920 = pow20 * pow2919; + local pow2921 = pow20 * pow2920; + local pow2922 = pow20 * pow2921; + local pow2923 = pow20 * pow2922; + local pow2924 = pow20 * pow2923; + local pow2925 = pow20 * pow2924; + local pow2926 = pow20 * pow2925; + local pow2927 = pow20 * pow2926; + local pow2928 = pow20 * pow2927; + local pow2929 = pow20 * pow2928; + local pow2930 = pow20 * pow2929; + local pow2931 = pow20 * pow2930; + local pow2932 = pow20 * pow2931; + local pow2933 = pow20 * pow2932; + local pow2934 = pow20 * pow2933; + local pow2935 = pow20 * pow2934; + local pow2936 = pow29 * pow2935; + local pow2937 = pow20 * pow2936; + local pow2938 = pow20 * pow2937; + local pow2939 = pow20 * pow2938; + local pow2940 = pow20 * pow2939; + local pow2941 = pow20 * pow2940; + local pow2942 = pow20 * pow2941; + local pow2943 = pow20 * pow2942; + local pow2944 = pow20 * pow2943; + local pow2945 = pow20 * pow2944; + local pow2946 = pow20 * pow2945; + local pow2947 = pow20 * pow2946; + local pow2948 = pow20 * pow2947; + local pow2949 = pow20 * pow2948; + local pow2950 = pow20 * pow2949; + local pow2951 = pow20 * pow2950; + local pow2952 = pow20 * pow2951; + local pow2953 = pow20 * pow2952; + local pow2954 = pow20 * pow2953; + local pow2955 = pow20 * pow2954; + local pow2956 = pow20 * pow2955; + local pow2957 = pow20 * pow2956; + local pow2958 = pow20 * pow2957; + local pow2959 = pow20 * pow2958; + local pow2960 = pow20 * pow2959; + local pow2961 = pow20 * pow2960; + local pow2962 = pow20 * pow2961; + local pow2963 = pow20 * pow2962; + local pow2964 = pow20 * pow2963; + local pow2965 = pow20 * pow2964; + local pow2966 = pow29 * pow2965; + local pow2967 = pow20 * pow2966; + local pow2968 = pow20 * pow2967; + local pow2969 = pow20 * pow2968; + local pow2970 = pow20 * pow2969; + local pow2971 = pow20 * pow2970; + local pow2972 = pow20 * pow2971; + local pow2973 = pow20 * pow2972; + local pow2974 = pow20 * pow2973; + local pow2975 = pow20 * pow2974; + local pow2976 = pow20 * pow2975; + local pow2977 = pow20 * pow2976; + local pow2978 = pow20 * pow2977; + local pow2979 = pow20 * pow2978; + local pow2980 = pow20 * pow2979; + local pow2981 = pow20 * pow2980; + local pow2982 = pow20 * pow2981; + local pow2983 = pow20 * pow2982; + local pow2984 = pow20 * pow2983; + local pow2985 = pow20 * pow2984; + local pow2986 = pow20 * pow2985; + local pow2987 = pow20 * pow2986; + local pow2988 = pow20 * pow2987; + local pow2989 = pow20 * pow2988; + local pow2990 = pow20 * pow2989; + local pow2991 = pow20 * pow2990; + local pow2992 = pow20 * pow2991; + local pow2993 = pow20 * pow2992; + local pow2994 = pow20 * pow2993; + local pow2995 = pow20 * pow2994; + local pow2996 = pow29 * pow2995; + local pow2997 = pow20 * pow2996; + local pow2998 = pow20 * pow2997; + local pow2999 = pow20 * pow2998; + local pow3000 = pow20 * pow2999; + local pow3001 = pow20 * pow3000; + local pow3002 = pow20 * pow3001; + local pow3003 = pow20 * pow3002; + local pow3004 = pow20 * pow3003; + local pow3005 = pow20 * pow3004; + local pow3006 = pow20 * pow3005; + local pow3007 = pow20 * pow3006; + local pow3008 = pow20 * pow3007; + local pow3009 = pow20 * pow3008; + local pow3010 = pow20 * pow3009; + local pow3011 = pow20 * pow3010; + local pow3012 = pow20 * pow3011; + local pow3013 = pow20 * pow3012; + local pow3014 = pow20 * pow3013; + local pow3015 = pow20 * pow3014; + local pow3016 = pow20 * pow3015; + local pow3017 = pow20 * pow3016; + local pow3018 = pow20 * pow3017; + local pow3019 = pow20 * pow3018; + local pow3020 = pow20 * pow3019; + local pow3021 = pow20 * pow3020; + local pow3022 = pow20 * pow3021; + local pow3023 = pow20 * pow3022; + local pow3024 = pow20 * pow3023; + local pow3025 = pow20 * pow3024; + local pow3026 = pow29 * pow3025; + local pow3027 = pow20 * pow3026; + local pow3028 = pow20 * pow3027; + local pow3029 = pow20 * pow3028; + local pow3030 = pow20 * pow3029; + local pow3031 = pow20 * pow3030; + local pow3032 = pow20 * pow3031; + local pow3033 = pow20 * pow3032; + local pow3034 = pow20 * pow3033; + local pow3035 = pow20 * pow3034; + local pow3036 = pow20 * pow3035; + local pow3037 = pow20 * pow3036; + local pow3038 = pow20 * pow3037; + local pow3039 = pow20 * pow3038; + local pow3040 = pow20 * pow3039; + local pow3041 = pow20 * pow3040; + local pow3042 = pow20 * pow3041; + local pow3043 = pow20 * pow3042; + local pow3044 = pow20 * pow3043; + local pow3045 = pow20 * pow3044; + local pow3046 = pow20 * pow3045; + local pow3047 = pow20 * pow3046; + local pow3048 = pow20 * pow3047; + local pow3049 = pow20 * pow3048; + local pow3050 = pow20 * pow3049; + local pow3051 = pow20 * pow3050; + local pow3052 = pow20 * pow3051; + local pow3053 = pow20 * pow3052; + local pow3054 = pow20 * pow3053; + local pow3055 = pow20 * pow3054; + local pow3056 = pow29 * pow3055; + local pow3057 = pow20 * pow3056; + local pow3058 = pow20 * pow3057; + local pow3059 = pow20 * pow3058; + local pow3060 = pow20 * pow3059; + local pow3061 = pow20 * pow3060; + local pow3062 = pow20 * pow3061; + local pow3063 = pow20 * pow3062; + local pow3064 = pow20 * pow3063; + local pow3065 = pow20 * pow3064; + local pow3066 = pow20 * pow3065; + local pow3067 = pow20 * pow3066; + local pow3068 = pow20 * pow3067; + local pow3069 = pow20 * pow3068; + local pow3070 = pow20 * pow3069; + local pow3071 = pow20 * pow3070; + local pow3072 = pow20 * pow3071; + local pow3073 = pow20 * pow3072; + local pow3074 = pow20 * pow3073; + local pow3075 = pow20 * pow3074; + local pow3076 = pow20 * pow3075; + local pow3077 = pow20 * pow3076; + local pow3078 = pow20 * pow3077; + local pow3079 = pow20 * pow3078; + local pow3080 = pow20 * pow3079; + local pow3081 = pow20 * pow3080; + local pow3082 = pow20 * pow3081; + local pow3083 = pow20 * pow3082; + local pow3084 = pow20 * pow3083; + local pow3085 = pow20 * pow3084; + local pow3086 = pow29 * pow3085; + local pow3087 = pow20 * pow3086; + local pow3088 = pow20 * pow3087; + local pow3089 = pow20 * pow3088; + local pow3090 = pow20 * pow3089; + local pow3091 = pow20 * pow3090; + local pow3092 = pow20 * pow3091; + local pow3093 = pow20 * pow3092; + local pow3094 = pow20 * pow3093; + local pow3095 = pow20 * pow3094; + local pow3096 = pow20 * pow3095; + local pow3097 = pow20 * pow3096; + local pow3098 = pow20 * pow3097; + local pow3099 = pow20 * pow3098; + local pow3100 = pow20 * pow3099; + local pow3101 = pow20 * pow3100; + local pow3102 = pow20 * pow3101; + local pow3103 = pow20 * pow3102; + local pow3104 = pow20 * pow3103; + local pow3105 = pow20 * pow3104; + local pow3106 = pow20 * pow3105; + local pow3107 = pow20 * pow3106; + local pow3108 = pow20 * pow3107; + local pow3109 = pow20 * pow3108; + local pow3110 = pow20 * pow3109; + local pow3111 = pow20 * pow3110; + local pow3112 = pow20 * pow3111; + local pow3113 = pow20 * pow3112; + local pow3114 = pow20 * pow3113; + local pow3115 = pow20 * pow3114; + local pow3116 = pow29 * pow3115; + local pow3117 = pow20 * pow3116; + local pow3118 = pow20 * pow3117; + local pow3119 = pow20 * pow3118; + local pow3120 = pow20 * pow3119; + local pow3121 = pow20 * pow3120; + local pow3122 = pow20 * pow3121; + local pow3123 = pow20 * pow3122; + local pow3124 = pow20 * pow3123; + local pow3125 = pow20 * pow3124; + local pow3126 = pow20 * pow3125; + local pow3127 = pow20 * pow3126; + local pow3128 = pow20 * pow3127; + local pow3129 = pow20 * pow3128; + local pow3130 = pow20 * pow3129; + local pow3131 = pow20 * pow3130; + local pow3132 = pow20 * pow3131; + local pow3133 = pow20 * pow3132; + local pow3134 = pow20 * pow3133; + local pow3135 = pow20 * pow3134; + local pow3136 = pow20 * pow3135; + local pow3137 = pow20 * pow3136; + local pow3138 = pow20 * pow3137; + local pow3139 = pow20 * pow3138; + local pow3140 = pow20 * pow3139; + local pow3141 = pow20 * pow3140; + local pow3142 = pow20 * pow3141; + local pow3143 = pow20 * pow3142; + local pow3144 = pow20 * pow3143; + local pow3145 = pow20 * pow3144; + local pow3146 = pow29 * pow3145; + local pow3147 = pow20 * pow3146; + local pow3148 = pow20 * pow3147; + local pow3149 = pow20 * pow3148; + local pow3150 = pow20 * pow3149; + local pow3151 = pow20 * pow3150; + local pow3152 = pow20 * pow3151; + local pow3153 = pow20 * pow3152; + local pow3154 = pow20 * pow3153; + local pow3155 = pow20 * pow3154; + local pow3156 = pow20 * pow3155; + local pow3157 = pow20 * pow3156; + local pow3158 = pow20 * pow3157; + local pow3159 = pow20 * pow3158; + local pow3160 = pow20 * pow3159; + local pow3161 = pow20 * pow3160; + local pow3162 = pow20 * pow3161; + local pow3163 = pow20 * pow3162; + local pow3164 = pow20 * pow3163; + local pow3165 = pow20 * pow3164; + local pow3166 = pow20 * pow3165; + local pow3167 = pow20 * pow3166; + local pow3168 = pow20 * pow3167; + local pow3169 = pow20 * pow3168; + local pow3170 = pow20 * pow3169; + local pow3171 = pow20 * pow3170; + local pow3172 = pow20 * pow3171; + local pow3173 = pow20 * pow3172; + local pow3174 = pow20 * pow3173; + local pow3175 = pow20 * pow3174; + local pow3176 = pow29 * pow3175; + local pow3177 = pow20 * pow3176; + local pow3178 = pow20 * pow3177; + local pow3179 = pow20 * pow3178; + local pow3180 = pow20 * pow3179; + local pow3181 = pow20 * pow3180; + local pow3182 = pow20 * pow3181; + local pow3183 = pow20 * pow3182; + local pow3184 = pow20 * pow3183; + local pow3185 = pow20 * pow3184; + local pow3186 = pow20 * pow3185; + local pow3187 = pow20 * pow3186; + local pow3188 = pow20 * pow3187; + local pow3189 = pow20 * pow3188; + local pow3190 = pow20 * pow3189; + local pow3191 = pow20 * pow3190; + local pow3192 = pow20 * pow3191; + local pow3193 = pow20 * pow3192; + local pow3194 = pow20 * pow3193; + local pow3195 = pow20 * pow3194; + local pow3196 = pow20 * pow3195; + local pow3197 = pow20 * pow3196; + local pow3198 = pow20 * pow3197; + local pow3199 = pow20 * pow3198; + local pow3200 = pow20 * pow3199; + local pow3201 = pow20 * pow3200; + local pow3202 = pow20 * pow3201; + local pow3203 = pow20 * pow3202; + local pow3204 = pow20 * pow3203; + local pow3205 = pow20 * pow3204; + local pow3206 = pow29 * pow3205; + local pow3207 = pow20 * pow3206; + local pow3208 = pow20 * pow3207; + local pow3209 = pow20 * pow3208; + local pow3210 = pow20 * pow3209; + local pow3211 = pow20 * pow3210; + local pow3212 = pow20 * pow3211; + local pow3213 = pow20 * pow3212; + local pow3214 = pow20 * pow3213; + local pow3215 = pow20 * pow3214; + local pow3216 = pow20 * pow3215; + local pow3217 = pow20 * pow3216; + local pow3218 = pow20 * pow3217; + local pow3219 = pow20 * pow3218; + local pow3220 = pow20 * pow3219; + local pow3221 = pow20 * pow3220; + local pow3222 = pow20 * pow3221; + local pow3223 = pow20 * pow3222; + local pow3224 = pow20 * pow3223; + local pow3225 = pow20 * pow3224; + local pow3226 = pow20 * pow3225; + local pow3227 = pow20 * pow3226; + local pow3228 = pow20 * pow3227; + local pow3229 = pow20 * pow3228; + local pow3230 = pow20 * pow3229; + local pow3231 = pow20 * pow3230; + local pow3232 = pow20 * pow3231; + local pow3233 = pow20 * pow3232; + local pow3234 = pow20 * pow3233; + local pow3235 = pow20 * pow3234; + local pow3236 = pow29 * pow3235; + local pow3237 = pow20 * pow3236; + local pow3238 = pow20 * pow3237; + local pow3239 = pow20 * pow3238; + local pow3240 = pow20 * pow3239; + local pow3241 = pow20 * pow3240; + local pow3242 = pow20 * pow3241; + local pow3243 = pow20 * pow3242; + local pow3244 = pow20 * pow3243; + local pow3245 = pow20 * pow3244; + local pow3246 = pow20 * pow3245; + local pow3247 = pow20 * pow3246; + local pow3248 = pow20 * pow3247; + local pow3249 = pow20 * pow3248; + local pow3250 = pow20 * pow3249; + local pow3251 = pow20 * pow3250; + local pow3252 = pow20 * pow3251; + local pow3253 = pow20 * pow3252; + local pow3254 = pow20 * pow3253; + local pow3255 = pow20 * pow3254; + local pow3256 = pow20 * pow3255; + local pow3257 = pow20 * pow3256; + local pow3258 = pow20 * pow3257; + local pow3259 = pow20 * pow3258; + local pow3260 = pow20 * pow3259; + local pow3261 = pow20 * pow3260; + local pow3262 = pow20 * pow3261; + local pow3263 = pow20 * pow3262; + local pow3264 = pow20 * pow3263; + local pow3265 = pow20 * pow3264; + local pow3266 = pow29 * pow3265; + local pow3267 = pow20 * pow3266; + local pow3268 = pow20 * pow3267; + local pow3269 = pow20 * pow3268; + local pow3270 = pow20 * pow3269; + local pow3271 = pow20 * pow3270; + local pow3272 = pow20 * pow3271; + local pow3273 = pow20 * pow3272; + local pow3274 = pow20 * pow3273; + local pow3275 = pow20 * pow3274; + local pow3276 = pow20 * pow3275; + local pow3277 = pow20 * pow3276; + local pow3278 = pow20 * pow3277; + local pow3279 = pow20 * pow3278; + local pow3280 = pow20 * pow3279; + local pow3281 = pow20 * pow3280; + local pow3282 = pow20 * pow3281; + local pow3283 = pow20 * pow3282; + local pow3284 = pow20 * pow3283; + local pow3285 = pow20 * pow3284; + local pow3286 = pow20 * pow3285; + local pow3287 = pow20 * pow3286; + local pow3288 = pow20 * pow3287; + local pow3289 = pow20 * pow3288; + local pow3290 = pow20 * pow3289; + local pow3291 = pow20 * pow3290; + local pow3292 = pow20 * pow3291; + local pow3293 = pow20 * pow3292; + local pow3294 = pow20 * pow3293; + local pow3295 = pow20 * pow3294; + local pow3296 = pow29 * pow3295; + local pow3297 = pow20 * pow3296; + local pow3298 = pow20 * pow3297; + local pow3299 = pow20 * pow3298; + local pow3300 = pow20 * pow3299; + local pow3301 = pow20 * pow3300; + local pow3302 = pow20 * pow3301; + local pow3303 = pow20 * pow3302; + local pow3304 = pow20 * pow3303; + local pow3305 = pow20 * pow3304; + local pow3306 = pow20 * pow3305; + local pow3307 = pow20 * pow3306; + local pow3308 = pow20 * pow3307; + local pow3309 = pow20 * pow3308; + local pow3310 = pow20 * pow3309; + local pow3311 = pow20 * pow3310; + local pow3312 = pow20 * pow3311; + local pow3313 = pow20 * pow3312; + local pow3314 = pow20 * pow3313; + local pow3315 = pow20 * pow3314; + local pow3316 = pow20 * pow3315; + local pow3317 = pow20 * pow3316; + local pow3318 = pow20 * pow3317; + local pow3319 = pow20 * pow3318; + local pow3320 = pow20 * pow3319; + local pow3321 = pow20 * pow3320; + local pow3322 = pow20 * pow3321; + local pow3323 = pow20 * pow3322; + local pow3324 = pow20 * pow3323; + local pow3325 = pow20 * pow3324; + local pow3326 = pow29 * pow3325; + local pow3327 = pow20 * pow3326; + local pow3328 = pow20 * pow3327; + local pow3329 = pow20 * pow3328; + local pow3330 = pow20 * pow3329; + local pow3331 = pow20 * pow3330; + local pow3332 = pow20 * pow3331; + local pow3333 = pow20 * pow3332; + local pow3334 = pow20 * pow3333; + local pow3335 = pow20 * pow3334; + local pow3336 = pow20 * pow3335; + local pow3337 = pow20 * pow3336; + local pow3338 = pow20 * pow3337; + local pow3339 = pow20 * pow3338; + local pow3340 = pow20 * pow3339; + local pow3341 = pow20 * pow3340; + local pow3342 = pow20 * pow3341; + local pow3343 = pow20 * pow3342; + local pow3344 = pow20 * pow3343; + local pow3345 = pow20 * pow3344; + local pow3346 = pow20 * pow3345; + local pow3347 = pow20 * pow3346; + local pow3348 = pow20 * pow3347; + local pow3349 = pow20 * pow3348; + local pow3350 = pow20 * pow3349; + local pow3351 = pow20 * pow3350; + local pow3352 = pow20 * pow3351; + local pow3353 = pow20 * pow3352; + local pow3354 = pow20 * pow3353; + local pow3355 = pow20 * pow3354; + local pow3356 = pow29 * pow3355; + let (local pow3357) = pow(trace_generator, 16 * (global_values.trace_length / 16 - 1)); + let (local pow3358) = pow(trace_generator, 2 * (global_values.trace_length / 2 - 1)); + let (local pow3359) = pow(trace_generator, 4 * (global_values.trace_length / 4 - 1)); + let (local pow3360) = pow(trace_generator, global_values.trace_length - 1); + let (local pow3361) = pow(trace_generator, 4096 * (global_values.trace_length / 4096 - 1)); + let (local pow3362) = pow(trace_generator, 128 * (global_values.trace_length / 128 - 1)); + let (local pow3363) = pow(trace_generator, 256 * (global_values.trace_length / 256 - 1)); + let (local pow3364) = pow(trace_generator, 2048 * (global_values.trace_length / 2048 - 1)); + + // Compute domains. + tempvar domain0 = pow12 - 1; + tempvar domain1 = pow11 - 1; + tempvar domain2 = pow10 - 1; + tempvar domain3 = pow9 - 1; + tempvar domain4 = pow8 - pow2461; + tempvar domain5 = pow8 - 1; + tempvar domain6 = pow7 - 1; + tempvar domain7 = pow6 - 1; + tempvar domain8 = pow5 - pow2061; + tempvar domain9 = pow5 - 1; + tempvar domain10 = pow5 - pow812; + tempvar domain10 = domain10 * (domain9); + tempvar domain11 = pow5 - pow781; + tempvar domain11 = domain11 * (pow5 - pow851); + tempvar domain11 = domain11 * (pow5 - pow882); + tempvar domain11 = domain11 * (pow5 - pow921); + tempvar domain11 = domain11 * (pow5 - pow952); + tempvar domain11 = domain11 * (pow5 - pow976); + tempvar domain11 = domain11 * (pow5 - pow1000); + tempvar domain11 = domain11 * (pow5 - pow1024); + tempvar domain11 = domain11 * (pow5 - pow1048); + tempvar domain11 = domain11 * (pow5 - pow1087); + tempvar domain11 = domain11 * (pow5 - pow1118); + tempvar domain11 = domain11 * (pow5 - pow1157); + tempvar domain11 = domain11 * (pow5 - pow1188); + tempvar domain11 = domain11 * (pow5 - pow1227); + tempvar domain11 = domain11 * (domain10); + tempvar domain12 = pow4 - 1; + tempvar domain13 = pow4 - pow3296; + tempvar domain14 = pow4 - pow2576; + tempvar domain15 = pow3 - pow1659; + tempvar domain16 = pow3 - 1; + tempvar domain17 = pow2 - 1; + tempvar domain17 = domain17 * (pow2 - pow88); + tempvar domain17 = domain17 * (pow2 - pow148); + tempvar domain17 = domain17 * (pow2 - pow208); + tempvar domain17 = domain17 * (pow2 - pow268); + tempvar domain17 = domain17 * (pow2 - pow328); + tempvar domain17 = domain17 * (pow2 - pow388); + tempvar domain17 = domain17 * (pow2 - pow448); + tempvar domain18 = pow2 - pow508; + tempvar domain18 = domain18 * (pow2 - pow568); + tempvar domain18 = domain18 * (pow2 - pow628); + tempvar domain18 = domain18 * (pow2 - pow688); + tempvar domain18 = domain18 * (pow2 - pow748); + tempvar domain18 = domain18 * (pow2 - pow778); + tempvar domain18 = domain18 * (pow2 - pow779); + tempvar domain18 = domain18 * (pow2 - pow780); + tempvar domain18 = domain18 * (pow2 - pow781); + tempvar domain18 = domain18 * (pow2 - pow805); + tempvar domain18 = domain18 * (pow2 - pow806); + tempvar domain18 = domain18 * (pow2 - pow807); + tempvar domain18 = domain18 * (pow2 - pow808); + tempvar domain18 = domain18 * (pow2 - pow809); + tempvar domain18 = domain18 * (pow2 - pow810); + tempvar domain18 = domain18 * (pow2 - pow811); + tempvar domain18 = domain18 * (domain17); + tempvar domain19 = pow2 - pow1048; + tempvar domain19 = domain19 * (pow2 - pow1072); + tempvar domain19 = domain19 * (pow2 - pow1073); + tempvar domain19 = domain19 * (pow2 - pow1074); + tempvar domain19 = domain19 * (pow2 - pow1075); + tempvar domain19 = domain19 * (pow2 - pow1076); + tempvar domain19 = domain19 * (pow2 - pow1077); + tempvar domain19 = domain19 * (pow2 - pow1078); + tempvar domain19 = domain19 * (pow2 - pow1079); + tempvar domain19 = domain19 * (pow2 - pow1080); + tempvar domain19 = domain19 * (pow2 - pow1081); + tempvar domain19 = domain19 * (pow2 - pow1082); + tempvar domain19 = domain19 * (pow2 - pow1083); + tempvar domain19 = domain19 * (pow2 - pow1084); + tempvar domain19 = domain19 * (pow2 - pow1085); + tempvar domain19 = domain19 * (pow2 - pow1086); + tempvar domain19 = domain19 * (pow2 - pow1087); + tempvar domain19 = domain19 * (pow2 - pow1111); + tempvar domain19 = domain19 * (pow2 - pow1112); + tempvar domain19 = domain19 * (pow2 - pow1113); + tempvar domain19 = domain19 * (pow2 - pow1114); + tempvar domain19 = domain19 * (pow2 - pow1115); + tempvar domain19 = domain19 * (pow2 - pow1116); + tempvar domain19 = domain19 * (pow2 - pow1117); + tempvar domain19 = domain19 * (pow2 - pow1354); + tempvar domain19 = domain19 * (pow2 - pow1378); + tempvar domain19 = domain19 * (pow2 - pow1379); + tempvar domain19 = domain19 * (pow2 - pow1380); + tempvar domain19 = domain19 * (pow2 - pow1381); + tempvar domain19 = domain19 * (pow2 - pow1382); + tempvar domain19 = domain19 * (pow2 - pow1383); + tempvar domain19 = domain19 * (pow2 - pow1384); + tempvar domain19 = domain19 * (pow2 - pow1385); + tempvar domain19 = domain19 * (pow2 - pow1386); + tempvar domain19 = domain19 * (pow2 - pow1387); + tempvar domain19 = domain19 * (pow2 - pow1388); + tempvar domain19 = domain19 * (pow2 - pow1389); + tempvar domain19 = domain19 * (pow2 - pow1390); + tempvar domain19 = domain19 * (pow2 - pow1391); + tempvar domain19 = domain19 * (pow2 - pow1392); + tempvar domain19 = domain19 * (pow2 - pow1393); + tempvar domain19 = domain19 * (pow2 - pow1417); + tempvar domain19 = domain19 * (pow2 - pow1418); + tempvar domain19 = domain19 * (pow2 - pow1419); + tempvar domain19 = domain19 * (pow2 - pow1420); + tempvar domain19 = domain19 * (pow2 - pow1421); + tempvar domain19 = domain19 * (pow2 - pow1422); + tempvar domain19 = domain19 * (pow2 - pow1423); + tempvar domain19 = domain19 * (pow2 - pow1612); + tempvar domain19 = domain19 * (pow2 - pow1613); + tempvar domain19 = domain19 * (pow2 - pow1614); + tempvar domain19 = domain19 * (pow2 - pow1615); + tempvar domain19 = domain19 * (pow2 - pow1616); + tempvar domain19 = domain19 * (pow2 - pow1617); + tempvar domain19 = domain19 * (pow2 - pow1618); + tempvar domain19 = domain19 * (pow2 - pow1619); + tempvar domain19 = domain19 * (pow2 - pow1620); + tempvar domain19 = domain19 * (pow2 - pow1621); + tempvar domain19 = domain19 * (pow2 - pow1622); + tempvar domain19 = domain19 * (pow2 - pow1623); + tempvar domain19 = domain19 * (pow2 - pow1624); + tempvar domain19 = domain19 * (pow2 - pow1625); + tempvar domain19 = domain19 * (pow2 - pow1626); + tempvar domain19 = domain19 * (pow2 - pow1627); + tempvar domain19 = domain19 * (pow2 - pow1628); + tempvar domain19 = domain19 * (pow2 - pow1652); + tempvar domain19 = domain19 * (pow2 - pow1653); + tempvar domain19 = domain19 * (pow2 - pow1654); + tempvar domain19 = domain19 * (pow2 - pow1655); + tempvar domain19 = domain19 * (pow2 - pow1656); + tempvar domain19 = domain19 * (pow2 - pow1657); + tempvar domain19 = domain19 * (pow2 - pow1658); + tempvar domain19 = domain19 * (pow2 - pow1803); + tempvar domain19 = domain19 * (pow2 - pow1827); + tempvar domain19 = domain19 * (pow2 - pow1828); + tempvar domain19 = domain19 * (pow2 - pow1829); + tempvar domain19 = domain19 * (pow2 - pow1830); + tempvar domain19 = domain19 * (pow2 - pow1831); + tempvar domain19 = domain19 * (pow2 - pow1832); + tempvar domain19 = domain19 * (pow2 - pow1833); + tempvar domain19 = domain19 * (pow2 - pow1834); + tempvar domain19 = domain19 * (pow2 - pow1835); + tempvar domain19 = domain19 * (pow2 - pow1836); + tempvar domain19 = domain19 * (pow2 - pow1837); + tempvar domain19 = domain19 * (pow2 - pow1838); + tempvar domain19 = domain19 * (pow2 - pow1839); + tempvar domain19 = domain19 * (pow2 - pow1840); + tempvar domain19 = domain19 * (pow2 - pow1841); + tempvar domain19 = domain19 * (pow2 - pow1842); + tempvar domain19 = domain19 * (pow2 - pow1866); + tempvar domain19 = domain19 * (pow2 - pow1867); + tempvar domain19 = domain19 * (pow2 - pow1868); + tempvar domain19 = domain19 * (pow2 - pow1869); + tempvar domain19 = domain19 * (pow2 - pow1870); + tempvar domain19 = domain19 * (pow2 - pow1871); + tempvar domain19 = domain19 * (pow2 - pow1872); + tempvar domain19 = domain19 * (domain18); + tempvar domain20 = pow2 - pow812; + tempvar domain20 = domain20 * (pow2 - pow836); + tempvar domain20 = domain20 * (pow2 - pow837); + tempvar domain20 = domain20 * (pow2 - pow838); + tempvar domain20 = domain20 * (pow2 - pow839); + tempvar domain20 = domain20 * (pow2 - pow840); + tempvar domain20 = domain20 * (pow2 - pow841); + tempvar domain20 = domain20 * (pow2 - pow842); + tempvar domain20 = domain20 * (pow2 - pow843); + tempvar domain20 = domain20 * (pow2 - pow844); + tempvar domain20 = domain20 * (pow2 - pow845); + tempvar domain20 = domain20 * (pow2 - pow846); + tempvar domain20 = domain20 * (pow2 - pow847); + tempvar domain20 = domain20 * (pow2 - pow848); + tempvar domain20 = domain20 * (pow2 - pow849); + tempvar domain20 = domain20 * (pow2 - pow850); + tempvar domain20 = domain20 * (pow2 - pow851); + tempvar domain20 = domain20 * (pow2 - pow875); + tempvar domain20 = domain20 * (pow2 - pow876); + tempvar domain20 = domain20 * (pow2 - pow877); + tempvar domain20 = domain20 * (pow2 - pow878); + tempvar domain20 = domain20 * (pow2 - pow879); + tempvar domain20 = domain20 * (pow2 - pow880); + tempvar domain20 = domain20 * (pow2 - pow881); + tempvar domain20 = domain20 * (pow2 - pow882); + tempvar domain20 = domain20 * (pow2 - pow906); + tempvar domain20 = domain20 * (pow2 - pow907); + tempvar domain20 = domain20 * (pow2 - pow908); + tempvar domain20 = domain20 * (pow2 - pow909); + tempvar domain20 = domain20 * (pow2 - pow910); + tempvar domain20 = domain20 * (pow2 - pow911); + tempvar domain20 = domain20 * (pow2 - pow912); + tempvar domain20 = domain20 * (pow2 - pow913); + tempvar domain20 = domain20 * (pow2 - pow914); + tempvar domain20 = domain20 * (pow2 - pow915); + tempvar domain20 = domain20 * (pow2 - pow916); + tempvar domain20 = domain20 * (pow2 - pow917); + tempvar domain20 = domain20 * (pow2 - pow918); + tempvar domain20 = domain20 * (pow2 - pow919); + tempvar domain20 = domain20 * (pow2 - pow920); + tempvar domain20 = domain20 * (pow2 - pow921); + tempvar domain20 = domain20 * (pow2 - pow945); + tempvar domain20 = domain20 * (pow2 - pow946); + tempvar domain20 = domain20 * (pow2 - pow947); + tempvar domain20 = domain20 * (pow2 - pow948); + tempvar domain20 = domain20 * (pow2 - pow949); + tempvar domain20 = domain20 * (pow2 - pow950); + tempvar domain20 = domain20 * (pow2 - pow951); + tempvar domain20 = domain20 * (pow2 - pow1118); + tempvar domain20 = domain20 * (pow2 - pow1142); + tempvar domain20 = domain20 * (pow2 - pow1143); + tempvar domain20 = domain20 * (pow2 - pow1144); + tempvar domain20 = domain20 * (pow2 - pow1145); + tempvar domain20 = domain20 * (pow2 - pow1146); + tempvar domain20 = domain20 * (pow2 - pow1147); + tempvar domain20 = domain20 * (pow2 - pow1148); + tempvar domain20 = domain20 * (pow2 - pow1149); + tempvar domain20 = domain20 * (pow2 - pow1150); + tempvar domain20 = domain20 * (pow2 - pow1151); + tempvar domain20 = domain20 * (pow2 - pow1152); + tempvar domain20 = domain20 * (pow2 - pow1153); + tempvar domain20 = domain20 * (pow2 - pow1154); + tempvar domain20 = domain20 * (pow2 - pow1155); + tempvar domain20 = domain20 * (pow2 - pow1156); + tempvar domain20 = domain20 * (pow2 - pow1157); + tempvar domain20 = domain20 * (pow2 - pow1181); + tempvar domain20 = domain20 * (pow2 - pow1182); + tempvar domain20 = domain20 * (pow2 - pow1183); + tempvar domain20 = domain20 * (pow2 - pow1184); + tempvar domain20 = domain20 * (pow2 - pow1185); + tempvar domain20 = domain20 * (pow2 - pow1186); + tempvar domain20 = domain20 * (pow2 - pow1187); + tempvar domain20 = domain20 * (pow2 - pow1188); + tempvar domain20 = domain20 * (pow2 - pow1212); + tempvar domain20 = domain20 * (pow2 - pow1213); + tempvar domain20 = domain20 * (pow2 - pow1214); + tempvar domain20 = domain20 * (pow2 - pow1215); + tempvar domain20 = domain20 * (pow2 - pow1216); + tempvar domain20 = domain20 * (pow2 - pow1217); + tempvar domain20 = domain20 * (pow2 - pow1218); + tempvar domain20 = domain20 * (pow2 - pow1219); + tempvar domain20 = domain20 * (pow2 - pow1220); + tempvar domain20 = domain20 * (pow2 - pow1221); + tempvar domain20 = domain20 * (pow2 - pow1222); + tempvar domain20 = domain20 * (pow2 - pow1223); + tempvar domain20 = domain20 * (pow2 - pow1224); + tempvar domain20 = domain20 * (pow2 - pow1225); + tempvar domain20 = domain20 * (pow2 - pow1226); + tempvar domain20 = domain20 * (pow2 - pow1227); + tempvar domain20 = domain20 * (pow2 - pow1251); + tempvar domain20 = domain20 * (pow2 - pow1252); + tempvar domain20 = domain20 * (pow2 - pow1253); + tempvar domain20 = domain20 * (pow2 - pow1254); + tempvar domain20 = domain20 * (pow2 - pow1255); + tempvar domain20 = domain20 * (pow2 - pow1256); + tempvar domain20 = domain20 * (pow2 - pow1257); + tempvar domain20 = domain20 * (pow2 - pow1424); + tempvar domain20 = domain20 * (pow2 - pow1448); + tempvar domain20 = domain20 * (pow2 - pow1449); + tempvar domain20 = domain20 * (pow2 - pow1450); + tempvar domain20 = domain20 * (pow2 - pow1451); + tempvar domain20 = domain20 * (pow2 - pow1452); + tempvar domain20 = domain20 * (pow2 - pow1453); + tempvar domain20 = domain20 * (pow2 - pow1454); + tempvar domain20 = domain20 * (pow2 - pow1455); + tempvar domain20 = domain20 * (pow2 - pow1456); + tempvar domain20 = domain20 * (pow2 - pow1457); + tempvar domain20 = domain20 * (pow2 - pow1458); + tempvar domain20 = domain20 * (pow2 - pow1459); + tempvar domain20 = domain20 * (pow2 - pow1460); + tempvar domain20 = domain20 * (pow2 - pow1461); + tempvar domain20 = domain20 * (pow2 - pow1462); + tempvar domain20 = domain20 * (pow2 - pow1463); + tempvar domain20 = domain20 * (pow2 - pow1487); + tempvar domain20 = domain20 * (pow2 - pow1488); + tempvar domain20 = domain20 * (pow2 - pow1489); + tempvar domain20 = domain20 * (pow2 - pow1490); + tempvar domain20 = domain20 * (pow2 - pow1491); + tempvar domain20 = domain20 * (pow2 - pow1492); + tempvar domain20 = domain20 * (pow2 - pow1493); + tempvar domain20 = domain20 * (pow2 - pow1494); + tempvar domain20 = domain20 * (pow2 - pow1518); + tempvar domain20 = domain20 * (pow2 - pow1519); + tempvar domain20 = domain20 * (pow2 - pow1520); + tempvar domain20 = domain20 * (pow2 - pow1521); + tempvar domain20 = domain20 * (pow2 - pow1522); + tempvar domain20 = domain20 * (pow2 - pow1523); + tempvar domain20 = domain20 * (pow2 - pow1524); + tempvar domain20 = domain20 * (pow2 - pow1525); + tempvar domain20 = domain20 * (pow2 - pow1526); + tempvar domain20 = domain20 * (pow2 - pow1527); + tempvar domain20 = domain20 * (pow2 - pow1528); + tempvar domain20 = domain20 * (pow2 - pow1529); + tempvar domain20 = domain20 * (pow2 - pow1530); + tempvar domain20 = domain20 * (pow2 - pow1531); + tempvar domain20 = domain20 * (pow2 - pow1532); + tempvar domain20 = domain20 * (pow2 - pow1533); + tempvar domain20 = domain20 * (pow2 - pow1557); + tempvar domain20 = domain20 * (pow2 - pow1558); + tempvar domain20 = domain20 * (pow2 - pow1559); + tempvar domain20 = domain20 * (pow2 - pow1560); + tempvar domain20 = domain20 * (pow2 - pow1561); + tempvar domain20 = domain20 * (pow2 - pow1562); + tempvar domain20 = domain20 * (pow2 - pow1563); + tempvar domain20 = domain20 * (pow2 - pow1659); + tempvar domain20 = domain20 * (pow2 - pow1660); + tempvar domain20 = domain20 * (pow2 - pow1661); + tempvar domain20 = domain20 * (pow2 - pow1662); + tempvar domain20 = domain20 * (pow2 - pow1663); + tempvar domain20 = domain20 * (pow2 - pow1664); + tempvar domain20 = domain20 * (pow2 - pow1665); + tempvar domain20 = domain20 * (pow2 - pow1666); + tempvar domain20 = domain20 * (pow2 - pow1667); + tempvar domain20 = domain20 * (pow2 - pow1668); + tempvar domain20 = domain20 * (pow2 - pow1669); + tempvar domain20 = domain20 * (pow2 - pow1670); + tempvar domain20 = domain20 * (pow2 - pow1671); + tempvar domain20 = domain20 * (pow2 - pow1672); + tempvar domain20 = domain20 * (pow2 - pow1673); + tempvar domain20 = domain20 * (pow2 - pow1674); + tempvar domain20 = domain20 * (pow2 - pow1675); + tempvar domain20 = domain20 * (pow2 - pow1676); + tempvar domain20 = domain20 * (pow2 - pow1677); + tempvar domain20 = domain20 * (pow2 - pow1678); + tempvar domain20 = domain20 * (pow2 - pow1679); + tempvar domain20 = domain20 * (pow2 - pow1680); + tempvar domain20 = domain20 * (pow2 - pow1681); + tempvar domain20 = domain20 * (pow2 - pow1682); + tempvar domain20 = domain20 * (pow2 - pow1683); + tempvar domain20 = domain20 * (pow2 - pow1684); + tempvar domain20 = domain20 * (pow2 - pow1685); + tempvar domain20 = domain20 * (pow2 - pow1686); + tempvar domain20 = domain20 * (pow2 - pow1687); + tempvar domain20 = domain20 * (pow2 - pow1688); + tempvar domain20 = domain20 * (pow2 - pow1689); + tempvar domain20 = domain20 * (pow2 - pow1690); + tempvar domain20 = domain20 * (pow2 - pow1691); + tempvar domain20 = domain20 * (pow2 - pow1692); + tempvar domain20 = domain20 * (pow2 - pow1693); + tempvar domain20 = domain20 * (pow2 - pow1694); + tempvar domain20 = domain20 * (pow2 - pow1695); + tempvar domain20 = domain20 * (pow2 - pow1696); + tempvar domain20 = domain20 * (pow2 - pow1697); + tempvar domain20 = domain20 * (pow2 - pow1698); + tempvar domain20 = domain20 * (pow2 - pow1699); + tempvar domain20 = domain20 * (pow2 - pow1700); + tempvar domain20 = domain20 * (pow2 - pow1701); + tempvar domain20 = domain20 * (pow2 - pow1702); + tempvar domain20 = domain20 * (pow2 - pow1703); + tempvar domain20 = domain20 * (pow2 - pow1704); + tempvar domain20 = domain20 * (pow2 - pow1705); + tempvar domain20 = domain20 * (pow2 - pow1706); + tempvar domain20 = domain20 * (pow2 - pow1873); + tempvar domain20 = domain20 * (pow2 - pow1897); + tempvar domain20 = domain20 * (pow2 - pow1898); + tempvar domain20 = domain20 * (pow2 - pow1899); + tempvar domain20 = domain20 * (pow2 - pow1900); + tempvar domain20 = domain20 * (pow2 - pow1901); + tempvar domain20 = domain20 * (pow2 - pow1902); + tempvar domain20 = domain20 * (pow2 - pow1903); + tempvar domain20 = domain20 * (pow2 - pow1904); + tempvar domain20 = domain20 * (pow2 - pow1905); + tempvar domain20 = domain20 * (pow2 - pow1906); + tempvar domain20 = domain20 * (pow2 - pow1907); + tempvar domain20 = domain20 * (pow2 - pow1908); + tempvar domain20 = domain20 * (pow2 - pow1909); + tempvar domain20 = domain20 * (pow2 - pow1910); + tempvar domain20 = domain20 * (pow2 - pow1911); + tempvar domain20 = domain20 * (pow2 - pow1912); + tempvar domain20 = domain20 * (pow2 - pow1936); + tempvar domain20 = domain20 * (pow2 - pow1937); + tempvar domain20 = domain20 * (pow2 - pow1938); + tempvar domain20 = domain20 * (pow2 - pow1939); + tempvar domain20 = domain20 * (pow2 - pow1940); + tempvar domain20 = domain20 * (pow2 - pow1941); + tempvar domain20 = domain20 * (pow2 - pow1942); + tempvar domain20 = domain20 * (pow2 - pow1943); + tempvar domain20 = domain20 * (pow2 - pow1967); + tempvar domain20 = domain20 * (pow2 - pow1968); + tempvar domain20 = domain20 * (pow2 - pow1969); + tempvar domain20 = domain20 * (pow2 - pow1970); + tempvar domain20 = domain20 * (pow2 - pow1971); + tempvar domain20 = domain20 * (pow2 - pow1972); + tempvar domain20 = domain20 * (pow2 - pow1973); + tempvar domain20 = domain20 * (pow2 - pow1974); + tempvar domain20 = domain20 * (pow2 - pow1975); + tempvar domain20 = domain20 * (pow2 - pow1976); + tempvar domain20 = domain20 * (pow2 - pow1977); + tempvar domain20 = domain20 * (pow2 - pow1978); + tempvar domain20 = domain20 * (pow2 - pow1979); + tempvar domain20 = domain20 * (pow2 - pow1980); + tempvar domain20 = domain20 * (pow2 - pow1981); + tempvar domain20 = domain20 * (pow2 - pow1982); + tempvar domain20 = domain20 * (pow2 - pow2006); + tempvar domain20 = domain20 * (pow2 - pow2007); + tempvar domain20 = domain20 * (pow2 - pow2008); + tempvar domain20 = domain20 * (pow2 - pow2009); + tempvar domain20 = domain20 * (pow2 - pow2010); + tempvar domain20 = domain20 * (pow2 - pow2011); + tempvar domain20 = domain20 * (pow2 - pow2012); + tempvar domain20 = domain20 * (domain19); + tempvar domain21 = pow1 - 1; + tempvar domain22 = pow0 - 1; + tempvar domain23 = pow0 - pow20; + tempvar domain23 = domain23 * (domain22); + tempvar domain24 = pow0 - pow13; + tempvar domain24 = domain24 * (pow0 - pow14); + tempvar domain24 = domain24 * (pow0 - pow15); + tempvar domain24 = domain24 * (pow0 - pow16); + tempvar domain24 = domain24 * (pow0 - pow17); + tempvar domain24 = domain24 * (pow0 - pow18); + tempvar domain24 = domain24 * (pow0 - pow19); + tempvar domain24 = domain24 * (pow0 - pow21); + tempvar domain24 = domain24 * (pow0 - pow22); + tempvar domain24 = domain24 * (pow0 - pow23); + tempvar domain24 = domain24 * (pow0 - pow24); + tempvar domain24 = domain24 * (pow0 - pow25); + tempvar domain24 = domain24 * (pow0 - pow26); + tempvar domain24 = domain24 * (pow0 - pow27); + tempvar domain24 = domain24 * (domain23); + tempvar domain25 = pow0 - pow28; + tempvar domain25 = domain25 * (pow0 - pow29); + tempvar domain25 = domain25 * (pow0 - pow30); + tempvar domain25 = domain25 * (pow0 - pow31); + tempvar domain25 = domain25 * (pow0 - pow32); + tempvar domain25 = domain25 * (pow0 - pow33); + tempvar domain25 = domain25 * (domain23); + tempvar domain26 = pow0 - pow34; + tempvar domain26 = domain26 * (pow0 - pow35); + tempvar domain26 = domain26 * (pow0 - pow36); + tempvar domain26 = domain26 * (pow0 - pow37); + tempvar domain26 = domain26 * (pow0 - pow38); + tempvar domain26 = domain26 * (pow0 - pow39); + tempvar domain26 = domain26 * (pow0 - pow40); + tempvar domain26 = domain26 * (pow0 - pow41); + tempvar domain26 = domain26 * (pow0 - pow42); + tempvar domain26 = domain26 * (pow0 - pow43); + tempvar domain26 = domain26 * (pow0 - pow44); + tempvar domain26 = domain26 * (pow0 - pow45); + tempvar domain26 = domain26 * (pow0 - pow46); + tempvar domain26 = domain26 * (pow0 - pow47); + tempvar domain26 = domain26 * (pow0 - pow48); + tempvar domain26 = domain26 * (pow0 - pow49); + tempvar domain26 = domain26 * (domain25); + tempvar domain27 = pow0 - pow50; + tempvar domain27 = domain27 * (pow0 - pow51); + tempvar domain27 = domain27 * (pow0 - pow52); + tempvar domain27 = domain27 * (pow0 - pow53); + tempvar domain27 = domain27 * (pow0 - pow54); + tempvar domain27 = domain27 * (pow0 - pow55); + tempvar domain27 = domain27 * (domain26); + tempvar domain28 = pow0 - pow56; + tempvar domain28 = domain28 * (pow0 - pow57); + tempvar domain28 = domain28 * (domain27); + tempvar domain29 = pow0 - pow58; + tempvar domain29 = domain29 * (pow0 - pow88); + tempvar domain29 = domain29 * (pow0 - pow118); + tempvar domain29 = domain29 * (pow0 - pow148); + tempvar domain29 = domain29 * (pow0 - pow178); + tempvar domain29 = domain29 * (pow0 - pow208); + tempvar domain29 = domain29 * (pow0 - pow238); + tempvar domain29 = domain29 * (pow0 - pow268); + tempvar domain29 = domain29 * (pow0 - pow298); + tempvar domain29 = domain29 * (pow0 - pow328); + tempvar domain29 = domain29 * (pow0 - pow358); + tempvar domain29 = domain29 * (pow0 - pow388); + tempvar domain29 = domain29 * (pow0 - pow418); + tempvar domain29 = domain29 * (pow0 - pow448); + tempvar domain29 = domain29 * (pow0 - pow478); + tempvar domain29 = domain29 * (pow0 - pow508); + tempvar domain29 = domain29 * (pow0 - pow538); + tempvar domain29 = domain29 * (pow0 - pow568); + tempvar domain29 = domain29 * (pow0 - pow598); + tempvar domain29 = domain29 * (pow0 - pow628); + tempvar domain29 = domain29 * (pow0 - pow658); + tempvar domain29 = domain29 * (pow0 - pow688); + tempvar domain29 = domain29 * (pow0 - pow718); + tempvar domain29 = domain29 * (pow0 - pow748); + tempvar domain30 = pow0 - pow59; + tempvar domain30 = domain30 * (pow0 - pow89); + tempvar domain30 = domain30 * (pow0 - pow119); + tempvar domain30 = domain30 * (pow0 - pow149); + tempvar domain30 = domain30 * (pow0 - pow179); + tempvar domain30 = domain30 * (pow0 - pow209); + tempvar domain30 = domain30 * (pow0 - pow239); + tempvar domain30 = domain30 * (pow0 - pow269); + tempvar domain30 = domain30 * (pow0 - pow299); + tempvar domain30 = domain30 * (pow0 - pow329); + tempvar domain30 = domain30 * (pow0 - pow359); + tempvar domain30 = domain30 * (pow0 - pow389); + tempvar domain30 = domain30 * (pow0 - pow419); + tempvar domain30 = domain30 * (pow0 - pow449); + tempvar domain30 = domain30 * (pow0 - pow479); + tempvar domain30 = domain30 * (pow0 - pow509); + tempvar domain30 = domain30 * (pow0 - pow539); + tempvar domain30 = domain30 * (pow0 - pow569); + tempvar domain30 = domain30 * (pow0 - pow599); + tempvar domain30 = domain30 * (pow0 - pow629); + tempvar domain30 = domain30 * (pow0 - pow659); + tempvar domain30 = domain30 * (pow0 - pow689); + tempvar domain30 = domain30 * (pow0 - pow719); + tempvar domain30 = domain30 * (pow0 - pow749); + tempvar domain30 = domain30 * (domain29); + tempvar domain31 = domain23; + tempvar domain31 = domain31 * (domain30); + tempvar domain32 = pow0 - pow60; + tempvar domain32 = domain32 * (pow0 - pow61); + tempvar domain32 = domain32 * (pow0 - pow62); + tempvar domain32 = domain32 * (pow0 - pow63); + tempvar domain32 = domain32 * (pow0 - pow64); + tempvar domain32 = domain32 * (pow0 - pow65); + tempvar domain32 = domain32 * (pow0 - pow66); + tempvar domain32 = domain32 * (pow0 - pow67); + tempvar domain32 = domain32 * (pow0 - pow68); + tempvar domain32 = domain32 * (pow0 - pow69); + tempvar domain32 = domain32 * (pow0 - pow70); + tempvar domain32 = domain32 * (pow0 - pow71); + tempvar domain32 = domain32 * (pow0 - pow72); + tempvar domain32 = domain32 * (pow0 - pow73); + tempvar domain32 = domain32 * (pow0 - pow74); + tempvar domain32 = domain32 * (pow0 - pow75); + tempvar domain32 = domain32 * (pow0 - pow76); + tempvar domain32 = domain32 * (pow0 - pow77); + tempvar domain32 = domain32 * (pow0 - pow78); + tempvar domain32 = domain32 * (pow0 - pow79); + tempvar domain32 = domain32 * (pow0 - pow80); + tempvar domain32 = domain32 * (pow0 - pow81); + tempvar domain32 = domain32 * (pow0 - pow82); + tempvar domain32 = domain32 * (pow0 - pow83); + tempvar domain32 = domain32 * (pow0 - pow84); + tempvar domain32 = domain32 * (pow0 - pow85); + tempvar domain32 = domain32 * (pow0 - pow86); + tempvar domain32 = domain32 * (pow0 - pow87); + tempvar domain32 = domain32 * (pow0 - pow90); + tempvar domain32 = domain32 * (pow0 - pow91); + tempvar domain32 = domain32 * (pow0 - pow92); + tempvar domain32 = domain32 * (pow0 - pow93); + tempvar domain32 = domain32 * (pow0 - pow94); + tempvar domain32 = domain32 * (pow0 - pow95); + tempvar domain32 = domain32 * (pow0 - pow96); + tempvar domain32 = domain32 * (pow0 - pow97); + tempvar domain32 = domain32 * (pow0 - pow98); + tempvar domain32 = domain32 * (pow0 - pow99); + tempvar domain32 = domain32 * (pow0 - pow100); + tempvar domain32 = domain32 * (pow0 - pow101); + tempvar domain32 = domain32 * (pow0 - pow102); + tempvar domain32 = domain32 * (pow0 - pow103); + tempvar domain32 = domain32 * (pow0 - pow104); + tempvar domain32 = domain32 * (pow0 - pow105); + tempvar domain32 = domain32 * (pow0 - pow106); + tempvar domain32 = domain32 * (pow0 - pow107); + tempvar domain32 = domain32 * (pow0 - pow108); + tempvar domain32 = domain32 * (pow0 - pow109); + tempvar domain32 = domain32 * (pow0 - pow110); + tempvar domain32 = domain32 * (pow0 - pow111); + tempvar domain32 = domain32 * (pow0 - pow112); + tempvar domain32 = domain32 * (pow0 - pow113); + tempvar domain32 = domain32 * (pow0 - pow114); + tempvar domain32 = domain32 * (pow0 - pow115); + tempvar domain32 = domain32 * (pow0 - pow116); + tempvar domain32 = domain32 * (pow0 - pow117); + tempvar domain32 = domain32 * (pow0 - pow120); + tempvar domain32 = domain32 * (pow0 - pow121); + tempvar domain32 = domain32 * (pow0 - pow122); + tempvar domain32 = domain32 * (pow0 - pow123); + tempvar domain32 = domain32 * (pow0 - pow124); + tempvar domain32 = domain32 * (pow0 - pow125); + tempvar domain32 = domain32 * (pow0 - pow126); + tempvar domain32 = domain32 * (pow0 - pow127); + tempvar domain32 = domain32 * (pow0 - pow128); + tempvar domain32 = domain32 * (pow0 - pow129); + tempvar domain32 = domain32 * (pow0 - pow130); + tempvar domain32 = domain32 * (pow0 - pow131); + tempvar domain32 = domain32 * (pow0 - pow132); + tempvar domain32 = domain32 * (pow0 - pow133); + tempvar domain32 = domain32 * (pow0 - pow134); + tempvar domain32 = domain32 * (pow0 - pow135); + tempvar domain32 = domain32 * (pow0 - pow136); + tempvar domain32 = domain32 * (pow0 - pow137); + tempvar domain32 = domain32 * (pow0 - pow138); + tempvar domain32 = domain32 * (pow0 - pow139); + tempvar domain32 = domain32 * (pow0 - pow140); + tempvar domain32 = domain32 * (pow0 - pow141); + tempvar domain32 = domain32 * (pow0 - pow142); + tempvar domain32 = domain32 * (pow0 - pow143); + tempvar domain32 = domain32 * (pow0 - pow144); + tempvar domain32 = domain32 * (pow0 - pow145); + tempvar domain32 = domain32 * (pow0 - pow146); + tempvar domain32 = domain32 * (pow0 - pow147); + tempvar domain32 = domain32 * (pow0 - pow150); + tempvar domain32 = domain32 * (pow0 - pow151); + tempvar domain32 = domain32 * (pow0 - pow152); + tempvar domain32 = domain32 * (pow0 - pow153); + tempvar domain32 = domain32 * (pow0 - pow154); + tempvar domain32 = domain32 * (pow0 - pow155); + tempvar domain32 = domain32 * (pow0 - pow156); + tempvar domain32 = domain32 * (pow0 - pow157); + tempvar domain32 = domain32 * (pow0 - pow158); + tempvar domain32 = domain32 * (pow0 - pow159); + tempvar domain32 = domain32 * (pow0 - pow160); + tempvar domain32 = domain32 * (pow0 - pow161); + tempvar domain32 = domain32 * (pow0 - pow162); + tempvar domain32 = domain32 * (pow0 - pow163); + tempvar domain32 = domain32 * (pow0 - pow164); + tempvar domain32 = domain32 * (pow0 - pow165); + tempvar domain32 = domain32 * (pow0 - pow166); + tempvar domain32 = domain32 * (pow0 - pow167); + tempvar domain32 = domain32 * (pow0 - pow168); + tempvar domain32 = domain32 * (pow0 - pow169); + tempvar domain32 = domain32 * (pow0 - pow170); + tempvar domain32 = domain32 * (pow0 - pow171); + tempvar domain32 = domain32 * (pow0 - pow172); + tempvar domain32 = domain32 * (pow0 - pow173); + tempvar domain32 = domain32 * (pow0 - pow174); + tempvar domain32 = domain32 * (pow0 - pow175); + tempvar domain32 = domain32 * (pow0 - pow176); + tempvar domain32 = domain32 * (pow0 - pow177); + tempvar domain32 = domain32 * (pow0 - pow180); + tempvar domain32 = domain32 * (pow0 - pow181); + tempvar domain32 = domain32 * (pow0 - pow182); + tempvar domain32 = domain32 * (pow0 - pow183); + tempvar domain32 = domain32 * (pow0 - pow184); + tempvar domain32 = domain32 * (pow0 - pow185); + tempvar domain32 = domain32 * (pow0 - pow186); + tempvar domain32 = domain32 * (pow0 - pow187); + tempvar domain32 = domain32 * (pow0 - pow188); + tempvar domain32 = domain32 * (pow0 - pow189); + tempvar domain32 = domain32 * (pow0 - pow190); + tempvar domain32 = domain32 * (pow0 - pow191); + tempvar domain32 = domain32 * (pow0 - pow192); + tempvar domain32 = domain32 * (pow0 - pow193); + tempvar domain32 = domain32 * (pow0 - pow194); + tempvar domain32 = domain32 * (pow0 - pow195); + tempvar domain32 = domain32 * (pow0 - pow196); + tempvar domain32 = domain32 * (pow0 - pow197); + tempvar domain32 = domain32 * (pow0 - pow198); + tempvar domain32 = domain32 * (pow0 - pow199); + tempvar domain32 = domain32 * (pow0 - pow200); + tempvar domain32 = domain32 * (pow0 - pow201); + tempvar domain32 = domain32 * (pow0 - pow202); + tempvar domain32 = domain32 * (pow0 - pow203); + tempvar domain32 = domain32 * (pow0 - pow204); + tempvar domain32 = domain32 * (pow0 - pow205); + tempvar domain32 = domain32 * (pow0 - pow206); + tempvar domain32 = domain32 * (pow0 - pow207); + tempvar domain32 = domain32 * (pow0 - pow210); + tempvar domain32 = domain32 * (pow0 - pow211); + tempvar domain32 = domain32 * (pow0 - pow212); + tempvar domain32 = domain32 * (pow0 - pow213); + tempvar domain32 = domain32 * (pow0 - pow214); + tempvar domain32 = domain32 * (pow0 - pow215); + tempvar domain32 = domain32 * (pow0 - pow216); + tempvar domain32 = domain32 * (pow0 - pow217); + tempvar domain32 = domain32 * (pow0 - pow218); + tempvar domain32 = domain32 * (pow0 - pow219); + tempvar domain32 = domain32 * (pow0 - pow220); + tempvar domain32 = domain32 * (pow0 - pow221); + tempvar domain32 = domain32 * (pow0 - pow222); + tempvar domain32 = domain32 * (pow0 - pow223); + tempvar domain32 = domain32 * (pow0 - pow224); + tempvar domain32 = domain32 * (pow0 - pow225); + tempvar domain32 = domain32 * (pow0 - pow226); + tempvar domain32 = domain32 * (pow0 - pow227); + tempvar domain32 = domain32 * (pow0 - pow228); + tempvar domain32 = domain32 * (pow0 - pow229); + tempvar domain32 = domain32 * (pow0 - pow230); + tempvar domain32 = domain32 * (pow0 - pow231); + tempvar domain32 = domain32 * (pow0 - pow232); + tempvar domain32 = domain32 * (pow0 - pow233); + tempvar domain32 = domain32 * (pow0 - pow234); + tempvar domain32 = domain32 * (pow0 - pow235); + tempvar domain32 = domain32 * (pow0 - pow236); + tempvar domain32 = domain32 * (pow0 - pow237); + tempvar domain32 = domain32 * (pow0 - pow240); + tempvar domain32 = domain32 * (pow0 - pow241); + tempvar domain32 = domain32 * (pow0 - pow242); + tempvar domain32 = domain32 * (pow0 - pow243); + tempvar domain32 = domain32 * (pow0 - pow244); + tempvar domain32 = domain32 * (pow0 - pow245); + tempvar domain32 = domain32 * (pow0 - pow246); + tempvar domain32 = domain32 * (pow0 - pow247); + tempvar domain32 = domain32 * (pow0 - pow248); + tempvar domain32 = domain32 * (pow0 - pow249); + tempvar domain32 = domain32 * (pow0 - pow250); + tempvar domain32 = domain32 * (pow0 - pow251); + tempvar domain32 = domain32 * (pow0 - pow252); + tempvar domain32 = domain32 * (pow0 - pow253); + tempvar domain32 = domain32 * (pow0 - pow254); + tempvar domain32 = domain32 * (pow0 - pow255); + tempvar domain32 = domain32 * (pow0 - pow256); + tempvar domain32 = domain32 * (pow0 - pow257); + tempvar domain32 = domain32 * (pow0 - pow258); + tempvar domain32 = domain32 * (pow0 - pow259); + tempvar domain32 = domain32 * (pow0 - pow260); + tempvar domain32 = domain32 * (pow0 - pow261); + tempvar domain32 = domain32 * (pow0 - pow262); + tempvar domain32 = domain32 * (pow0 - pow263); + tempvar domain32 = domain32 * (pow0 - pow264); + tempvar domain32 = domain32 * (pow0 - pow265); + tempvar domain32 = domain32 * (pow0 - pow266); + tempvar domain32 = domain32 * (pow0 - pow267); + tempvar domain32 = domain32 * (pow0 - pow270); + tempvar domain32 = domain32 * (pow0 - pow271); + tempvar domain32 = domain32 * (pow0 - pow272); + tempvar domain32 = domain32 * (pow0 - pow273); + tempvar domain32 = domain32 * (pow0 - pow274); + tempvar domain32 = domain32 * (pow0 - pow275); + tempvar domain32 = domain32 * (pow0 - pow276); + tempvar domain32 = domain32 * (pow0 - pow277); + tempvar domain32 = domain32 * (pow0 - pow278); + tempvar domain32 = domain32 * (pow0 - pow279); + tempvar domain32 = domain32 * (pow0 - pow280); + tempvar domain32 = domain32 * (pow0 - pow281); + tempvar domain32 = domain32 * (pow0 - pow282); + tempvar domain32 = domain32 * (pow0 - pow283); + tempvar domain32 = domain32 * (pow0 - pow284); + tempvar domain32 = domain32 * (pow0 - pow285); + tempvar domain32 = domain32 * (pow0 - pow286); + tempvar domain32 = domain32 * (pow0 - pow287); + tempvar domain32 = domain32 * (pow0 - pow288); + tempvar domain32 = domain32 * (pow0 - pow289); + tempvar domain32 = domain32 * (pow0 - pow290); + tempvar domain32 = domain32 * (pow0 - pow291); + tempvar domain32 = domain32 * (pow0 - pow292); + tempvar domain32 = domain32 * (pow0 - pow293); + tempvar domain32 = domain32 * (pow0 - pow294); + tempvar domain32 = domain32 * (pow0 - pow295); + tempvar domain32 = domain32 * (pow0 - pow296); + tempvar domain32 = domain32 * (pow0 - pow297); + tempvar domain32 = domain32 * (pow0 - pow300); + tempvar domain32 = domain32 * (pow0 - pow301); + tempvar domain32 = domain32 * (pow0 - pow302); + tempvar domain32 = domain32 * (pow0 - pow303); + tempvar domain32 = domain32 * (pow0 - pow304); + tempvar domain32 = domain32 * (pow0 - pow305); + tempvar domain32 = domain32 * (pow0 - pow306); + tempvar domain32 = domain32 * (pow0 - pow307); + tempvar domain32 = domain32 * (pow0 - pow308); + tempvar domain32 = domain32 * (pow0 - pow309); + tempvar domain32 = domain32 * (pow0 - pow310); + tempvar domain32 = domain32 * (pow0 - pow311); + tempvar domain32 = domain32 * (pow0 - pow312); + tempvar domain32 = domain32 * (pow0 - pow313); + tempvar domain32 = domain32 * (pow0 - pow314); + tempvar domain32 = domain32 * (pow0 - pow315); + tempvar domain32 = domain32 * (pow0 - pow316); + tempvar domain32 = domain32 * (pow0 - pow317); + tempvar domain32 = domain32 * (pow0 - pow318); + tempvar domain32 = domain32 * (pow0 - pow319); + tempvar domain32 = domain32 * (pow0 - pow320); + tempvar domain32 = domain32 * (pow0 - pow321); + tempvar domain32 = domain32 * (pow0 - pow322); + tempvar domain32 = domain32 * (pow0 - pow323); + tempvar domain32 = domain32 * (pow0 - pow324); + tempvar domain32 = domain32 * (pow0 - pow325); + tempvar domain32 = domain32 * (pow0 - pow326); + tempvar domain32 = domain32 * (pow0 - pow327); + tempvar domain32 = domain32 * (pow0 - pow330); + tempvar domain32 = domain32 * (pow0 - pow331); + tempvar domain32 = domain32 * (pow0 - pow332); + tempvar domain32 = domain32 * (pow0 - pow333); + tempvar domain32 = domain32 * (pow0 - pow334); + tempvar domain32 = domain32 * (pow0 - pow335); + tempvar domain32 = domain32 * (pow0 - pow336); + tempvar domain32 = domain32 * (pow0 - pow337); + tempvar domain32 = domain32 * (pow0 - pow338); + tempvar domain32 = domain32 * (pow0 - pow339); + tempvar domain32 = domain32 * (pow0 - pow340); + tempvar domain32 = domain32 * (pow0 - pow341); + tempvar domain32 = domain32 * (pow0 - pow342); + tempvar domain32 = domain32 * (pow0 - pow343); + tempvar domain32 = domain32 * (pow0 - pow344); + tempvar domain32 = domain32 * (pow0 - pow345); + tempvar domain32 = domain32 * (pow0 - pow346); + tempvar domain32 = domain32 * (pow0 - pow347); + tempvar domain32 = domain32 * (pow0 - pow348); + tempvar domain32 = domain32 * (pow0 - pow349); + tempvar domain32 = domain32 * (pow0 - pow350); + tempvar domain32 = domain32 * (pow0 - pow351); + tempvar domain32 = domain32 * (pow0 - pow352); + tempvar domain32 = domain32 * (pow0 - pow353); + tempvar domain32 = domain32 * (pow0 - pow354); + tempvar domain32 = domain32 * (pow0 - pow355); + tempvar domain32 = domain32 * (pow0 - pow356); + tempvar domain32 = domain32 * (pow0 - pow357); + tempvar domain32 = domain32 * (pow0 - pow360); + tempvar domain32 = domain32 * (pow0 - pow361); + tempvar domain32 = domain32 * (pow0 - pow362); + tempvar domain32 = domain32 * (pow0 - pow363); + tempvar domain32 = domain32 * (pow0 - pow364); + tempvar domain32 = domain32 * (pow0 - pow365); + tempvar domain32 = domain32 * (pow0 - pow366); + tempvar domain32 = domain32 * (pow0 - pow367); + tempvar domain32 = domain32 * (pow0 - pow368); + tempvar domain32 = domain32 * (pow0 - pow369); + tempvar domain32 = domain32 * (pow0 - pow370); + tempvar domain32 = domain32 * (pow0 - pow371); + tempvar domain32 = domain32 * (pow0 - pow372); + tempvar domain32 = domain32 * (pow0 - pow373); + tempvar domain32 = domain32 * (pow0 - pow374); + tempvar domain32 = domain32 * (pow0 - pow375); + tempvar domain32 = domain32 * (pow0 - pow376); + tempvar domain32 = domain32 * (pow0 - pow377); + tempvar domain32 = domain32 * (pow0 - pow378); + tempvar domain32 = domain32 * (pow0 - pow379); + tempvar domain32 = domain32 * (pow0 - pow380); + tempvar domain32 = domain32 * (pow0 - pow381); + tempvar domain32 = domain32 * (pow0 - pow382); + tempvar domain32 = domain32 * (pow0 - pow383); + tempvar domain32 = domain32 * (pow0 - pow384); + tempvar domain32 = domain32 * (pow0 - pow385); + tempvar domain32 = domain32 * (pow0 - pow386); + tempvar domain32 = domain32 * (pow0 - pow387); + tempvar domain32 = domain32 * (pow0 - pow390); + tempvar domain32 = domain32 * (pow0 - pow391); + tempvar domain32 = domain32 * (pow0 - pow392); + tempvar domain32 = domain32 * (pow0 - pow393); + tempvar domain32 = domain32 * (pow0 - pow394); + tempvar domain32 = domain32 * (pow0 - pow395); + tempvar domain32 = domain32 * (pow0 - pow396); + tempvar domain32 = domain32 * (pow0 - pow397); + tempvar domain32 = domain32 * (pow0 - pow398); + tempvar domain32 = domain32 * (pow0 - pow399); + tempvar domain32 = domain32 * (pow0 - pow400); + tempvar domain32 = domain32 * (pow0 - pow401); + tempvar domain32 = domain32 * (pow0 - pow402); + tempvar domain32 = domain32 * (pow0 - pow403); + tempvar domain32 = domain32 * (pow0 - pow404); + tempvar domain32 = domain32 * (pow0 - pow405); + tempvar domain32 = domain32 * (pow0 - pow406); + tempvar domain32 = domain32 * (pow0 - pow407); + tempvar domain32 = domain32 * (pow0 - pow408); + tempvar domain32 = domain32 * (pow0 - pow409); + tempvar domain32 = domain32 * (pow0 - pow410); + tempvar domain32 = domain32 * (pow0 - pow411); + tempvar domain32 = domain32 * (pow0 - pow412); + tempvar domain32 = domain32 * (pow0 - pow413); + tempvar domain32 = domain32 * (pow0 - pow414); + tempvar domain32 = domain32 * (pow0 - pow415); + tempvar domain32 = domain32 * (pow0 - pow416); + tempvar domain32 = domain32 * (pow0 - pow417); + tempvar domain32 = domain32 * (pow0 - pow420); + tempvar domain32 = domain32 * (pow0 - pow421); + tempvar domain32 = domain32 * (pow0 - pow422); + tempvar domain32 = domain32 * (pow0 - pow423); + tempvar domain32 = domain32 * (pow0 - pow424); + tempvar domain32 = domain32 * (pow0 - pow425); + tempvar domain32 = domain32 * (pow0 - pow426); + tempvar domain32 = domain32 * (pow0 - pow427); + tempvar domain32 = domain32 * (pow0 - pow428); + tempvar domain32 = domain32 * (pow0 - pow429); + tempvar domain32 = domain32 * (pow0 - pow430); + tempvar domain32 = domain32 * (pow0 - pow431); + tempvar domain32 = domain32 * (pow0 - pow432); + tempvar domain32 = domain32 * (pow0 - pow433); + tempvar domain32 = domain32 * (pow0 - pow434); + tempvar domain32 = domain32 * (pow0 - pow435); + tempvar domain32 = domain32 * (pow0 - pow436); + tempvar domain32 = domain32 * (pow0 - pow437); + tempvar domain32 = domain32 * (pow0 - pow438); + tempvar domain32 = domain32 * (pow0 - pow439); + tempvar domain32 = domain32 * (pow0 - pow440); + tempvar domain32 = domain32 * (pow0 - pow441); + tempvar domain32 = domain32 * (pow0 - pow442); + tempvar domain32 = domain32 * (pow0 - pow443); + tempvar domain32 = domain32 * (pow0 - pow444); + tempvar domain32 = domain32 * (pow0 - pow445); + tempvar domain32 = domain32 * (pow0 - pow446); + tempvar domain32 = domain32 * (pow0 - pow447); + tempvar domain32 = domain32 * (pow0 - pow450); + tempvar domain32 = domain32 * (pow0 - pow451); + tempvar domain32 = domain32 * (pow0 - pow452); + tempvar domain32 = domain32 * (pow0 - pow453); + tempvar domain32 = domain32 * (pow0 - pow454); + tempvar domain32 = domain32 * (pow0 - pow455); + tempvar domain32 = domain32 * (pow0 - pow456); + tempvar domain32 = domain32 * (pow0 - pow457); + tempvar domain32 = domain32 * (pow0 - pow458); + tempvar domain32 = domain32 * (pow0 - pow459); + tempvar domain32 = domain32 * (pow0 - pow460); + tempvar domain32 = domain32 * (pow0 - pow461); + tempvar domain32 = domain32 * (pow0 - pow462); + tempvar domain32 = domain32 * (pow0 - pow463); + tempvar domain32 = domain32 * (pow0 - pow464); + tempvar domain32 = domain32 * (pow0 - pow465); + tempvar domain32 = domain32 * (pow0 - pow466); + tempvar domain32 = domain32 * (pow0 - pow467); + tempvar domain32 = domain32 * (pow0 - pow468); + tempvar domain32 = domain32 * (pow0 - pow469); + tempvar domain32 = domain32 * (pow0 - pow470); + tempvar domain32 = domain32 * (pow0 - pow471); + tempvar domain32 = domain32 * (pow0 - pow472); + tempvar domain32 = domain32 * (pow0 - pow473); + tempvar domain32 = domain32 * (pow0 - pow474); + tempvar domain32 = domain32 * (pow0 - pow475); + tempvar domain32 = domain32 * (pow0 - pow476); + tempvar domain32 = domain32 * (pow0 - pow477); + tempvar domain32 = domain32 * (pow0 - pow480); + tempvar domain32 = domain32 * (pow0 - pow481); + tempvar domain32 = domain32 * (pow0 - pow482); + tempvar domain32 = domain32 * (pow0 - pow483); + tempvar domain32 = domain32 * (pow0 - pow484); + tempvar domain32 = domain32 * (pow0 - pow485); + tempvar domain32 = domain32 * (pow0 - pow486); + tempvar domain32 = domain32 * (pow0 - pow487); + tempvar domain32 = domain32 * (pow0 - pow488); + tempvar domain32 = domain32 * (pow0 - pow489); + tempvar domain32 = domain32 * (pow0 - pow490); + tempvar domain32 = domain32 * (pow0 - pow491); + tempvar domain32 = domain32 * (pow0 - pow492); + tempvar domain32 = domain32 * (pow0 - pow493); + tempvar domain32 = domain32 * (pow0 - pow494); + tempvar domain32 = domain32 * (pow0 - pow495); + tempvar domain32 = domain32 * (pow0 - pow496); + tempvar domain32 = domain32 * (pow0 - pow497); + tempvar domain32 = domain32 * (pow0 - pow498); + tempvar domain32 = domain32 * (pow0 - pow499); + tempvar domain32 = domain32 * (pow0 - pow500); + tempvar domain32 = domain32 * (pow0 - pow501); + tempvar domain32 = domain32 * (pow0 - pow502); + tempvar domain32 = domain32 * (pow0 - pow503); + tempvar domain32 = domain32 * (pow0 - pow504); + tempvar domain32 = domain32 * (pow0 - pow505); + tempvar domain32 = domain32 * (pow0 - pow506); + tempvar domain32 = domain32 * (pow0 - pow507); + tempvar domain32 = domain32 * (pow0 - pow510); + tempvar domain32 = domain32 * (pow0 - pow511); + tempvar domain32 = domain32 * (pow0 - pow512); + tempvar domain32 = domain32 * (pow0 - pow513); + tempvar domain32 = domain32 * (pow0 - pow514); + tempvar domain32 = domain32 * (pow0 - pow515); + tempvar domain32 = domain32 * (pow0 - pow516); + tempvar domain32 = domain32 * (pow0 - pow517); + tempvar domain32 = domain32 * (pow0 - pow518); + tempvar domain32 = domain32 * (pow0 - pow519); + tempvar domain32 = domain32 * (pow0 - pow520); + tempvar domain32 = domain32 * (pow0 - pow521); + tempvar domain32 = domain32 * (pow0 - pow522); + tempvar domain32 = domain32 * (pow0 - pow523); + tempvar domain32 = domain32 * (pow0 - pow524); + tempvar domain32 = domain32 * (pow0 - pow525); + tempvar domain32 = domain32 * (pow0 - pow526); + tempvar domain32 = domain32 * (pow0 - pow527); + tempvar domain32 = domain32 * (pow0 - pow528); + tempvar domain32 = domain32 * (pow0 - pow529); + tempvar domain32 = domain32 * (pow0 - pow530); + tempvar domain32 = domain32 * (pow0 - pow531); + tempvar domain32 = domain32 * (pow0 - pow532); + tempvar domain32 = domain32 * (pow0 - pow533); + tempvar domain32 = domain32 * (pow0 - pow534); + tempvar domain32 = domain32 * (pow0 - pow535); + tempvar domain32 = domain32 * (pow0 - pow536); + tempvar domain32 = domain32 * (pow0 - pow537); + tempvar domain32 = domain32 * (pow0 - pow540); + tempvar domain32 = domain32 * (pow0 - pow541); + tempvar domain32 = domain32 * (pow0 - pow542); + tempvar domain32 = domain32 * (pow0 - pow543); + tempvar domain32 = domain32 * (pow0 - pow544); + tempvar domain32 = domain32 * (pow0 - pow545); + tempvar domain32 = domain32 * (pow0 - pow546); + tempvar domain32 = domain32 * (pow0 - pow547); + tempvar domain32 = domain32 * (pow0 - pow548); + tempvar domain32 = domain32 * (pow0 - pow549); + tempvar domain32 = domain32 * (pow0 - pow550); + tempvar domain32 = domain32 * (pow0 - pow551); + tempvar domain32 = domain32 * (pow0 - pow552); + tempvar domain32 = domain32 * (pow0 - pow553); + tempvar domain32 = domain32 * (pow0 - pow554); + tempvar domain32 = domain32 * (pow0 - pow555); + tempvar domain32 = domain32 * (pow0 - pow556); + tempvar domain32 = domain32 * (pow0 - pow557); + tempvar domain32 = domain32 * (pow0 - pow558); + tempvar domain32 = domain32 * (pow0 - pow559); + tempvar domain32 = domain32 * (pow0 - pow560); + tempvar domain32 = domain32 * (pow0 - pow561); + tempvar domain32 = domain32 * (pow0 - pow562); + tempvar domain32 = domain32 * (pow0 - pow563); + tempvar domain32 = domain32 * (pow0 - pow564); + tempvar domain32 = domain32 * (pow0 - pow565); + tempvar domain32 = domain32 * (pow0 - pow566); + tempvar domain32 = domain32 * (pow0 - pow567); + tempvar domain32 = domain32 * (pow0 - pow570); + tempvar domain32 = domain32 * (pow0 - pow571); + tempvar domain32 = domain32 * (pow0 - pow572); + tempvar domain32 = domain32 * (pow0 - pow573); + tempvar domain32 = domain32 * (pow0 - pow574); + tempvar domain32 = domain32 * (pow0 - pow575); + tempvar domain32 = domain32 * (pow0 - pow576); + tempvar domain32 = domain32 * (pow0 - pow577); + tempvar domain32 = domain32 * (pow0 - pow578); + tempvar domain32 = domain32 * (pow0 - pow579); + tempvar domain32 = domain32 * (pow0 - pow580); + tempvar domain32 = domain32 * (pow0 - pow581); + tempvar domain32 = domain32 * (pow0 - pow582); + tempvar domain32 = domain32 * (pow0 - pow583); + tempvar domain32 = domain32 * (pow0 - pow584); + tempvar domain32 = domain32 * (pow0 - pow585); + tempvar domain32 = domain32 * (pow0 - pow586); + tempvar domain32 = domain32 * (pow0 - pow587); + tempvar domain32 = domain32 * (pow0 - pow588); + tempvar domain32 = domain32 * (pow0 - pow589); + tempvar domain32 = domain32 * (pow0 - pow590); + tempvar domain32 = domain32 * (pow0 - pow591); + tempvar domain32 = domain32 * (pow0 - pow592); + tempvar domain32 = domain32 * (pow0 - pow593); + tempvar domain32 = domain32 * (pow0 - pow594); + tempvar domain32 = domain32 * (pow0 - pow595); + tempvar domain32 = domain32 * (pow0 - pow596); + tempvar domain32 = domain32 * (pow0 - pow597); + tempvar domain32 = domain32 * (pow0 - pow600); + tempvar domain32 = domain32 * (pow0 - pow601); + tempvar domain32 = domain32 * (pow0 - pow602); + tempvar domain32 = domain32 * (pow0 - pow603); + tempvar domain32 = domain32 * (pow0 - pow604); + tempvar domain32 = domain32 * (pow0 - pow605); + tempvar domain32 = domain32 * (pow0 - pow606); + tempvar domain32 = domain32 * (pow0 - pow607); + tempvar domain32 = domain32 * (pow0 - pow608); + tempvar domain32 = domain32 * (pow0 - pow609); + tempvar domain32 = domain32 * (pow0 - pow610); + tempvar domain32 = domain32 * (pow0 - pow611); + tempvar domain32 = domain32 * (pow0 - pow612); + tempvar domain32 = domain32 * (pow0 - pow613); + tempvar domain32 = domain32 * (pow0 - pow614); + tempvar domain32 = domain32 * (pow0 - pow615); + tempvar domain32 = domain32 * (pow0 - pow616); + tempvar domain32 = domain32 * (pow0 - pow617); + tempvar domain32 = domain32 * (pow0 - pow618); + tempvar domain32 = domain32 * (pow0 - pow619); + tempvar domain32 = domain32 * (pow0 - pow620); + tempvar domain32 = domain32 * (pow0 - pow621); + tempvar domain32 = domain32 * (pow0 - pow622); + tempvar domain32 = domain32 * (pow0 - pow623); + tempvar domain32 = domain32 * (pow0 - pow624); + tempvar domain32 = domain32 * (pow0 - pow625); + tempvar domain32 = domain32 * (pow0 - pow626); + tempvar domain32 = domain32 * (pow0 - pow627); + tempvar domain32 = domain32 * (pow0 - pow630); + tempvar domain32 = domain32 * (pow0 - pow631); + tempvar domain32 = domain32 * (pow0 - pow632); + tempvar domain32 = domain32 * (pow0 - pow633); + tempvar domain32 = domain32 * (pow0 - pow634); + tempvar domain32 = domain32 * (pow0 - pow635); + tempvar domain32 = domain32 * (pow0 - pow636); + tempvar domain32 = domain32 * (pow0 - pow637); + tempvar domain32 = domain32 * (pow0 - pow638); + tempvar domain32 = domain32 * (pow0 - pow639); + tempvar domain32 = domain32 * (pow0 - pow640); + tempvar domain32 = domain32 * (pow0 - pow641); + tempvar domain32 = domain32 * (pow0 - pow642); + tempvar domain32 = domain32 * (pow0 - pow643); + tempvar domain32 = domain32 * (pow0 - pow644); + tempvar domain32 = domain32 * (pow0 - pow645); + tempvar domain32 = domain32 * (pow0 - pow646); + tempvar domain32 = domain32 * (pow0 - pow647); + tempvar domain32 = domain32 * (pow0 - pow648); + tempvar domain32 = domain32 * (pow0 - pow649); + tempvar domain32 = domain32 * (pow0 - pow650); + tempvar domain32 = domain32 * (pow0 - pow651); + tempvar domain32 = domain32 * (pow0 - pow652); + tempvar domain32 = domain32 * (pow0 - pow653); + tempvar domain32 = domain32 * (pow0 - pow654); + tempvar domain32 = domain32 * (pow0 - pow655); + tempvar domain32 = domain32 * (pow0 - pow656); + tempvar domain32 = domain32 * (pow0 - pow657); + tempvar domain32 = domain32 * (pow0 - pow660); + tempvar domain32 = domain32 * (pow0 - pow661); + tempvar domain32 = domain32 * (pow0 - pow662); + tempvar domain32 = domain32 * (pow0 - pow663); + tempvar domain32 = domain32 * (pow0 - pow664); + tempvar domain32 = domain32 * (pow0 - pow665); + tempvar domain32 = domain32 * (pow0 - pow666); + tempvar domain32 = domain32 * (pow0 - pow667); + tempvar domain32 = domain32 * (pow0 - pow668); + tempvar domain32 = domain32 * (pow0 - pow669); + tempvar domain32 = domain32 * (pow0 - pow670); + tempvar domain32 = domain32 * (pow0 - pow671); + tempvar domain32 = domain32 * (pow0 - pow672); + tempvar domain32 = domain32 * (pow0 - pow673); + tempvar domain32 = domain32 * (pow0 - pow674); + tempvar domain32 = domain32 * (pow0 - pow675); + tempvar domain32 = domain32 * (pow0 - pow676); + tempvar domain32 = domain32 * (pow0 - pow677); + tempvar domain32 = domain32 * (pow0 - pow678); + tempvar domain32 = domain32 * (pow0 - pow679); + tempvar domain32 = domain32 * (pow0 - pow680); + tempvar domain32 = domain32 * (pow0 - pow681); + tempvar domain32 = domain32 * (pow0 - pow682); + tempvar domain32 = domain32 * (pow0 - pow683); + tempvar domain32 = domain32 * (pow0 - pow684); + tempvar domain32 = domain32 * (pow0 - pow685); + tempvar domain32 = domain32 * (pow0 - pow686); + tempvar domain32 = domain32 * (pow0 - pow687); + tempvar domain32 = domain32 * (pow0 - pow690); + tempvar domain32 = domain32 * (pow0 - pow691); + tempvar domain32 = domain32 * (pow0 - pow692); + tempvar domain32 = domain32 * (pow0 - pow693); + tempvar domain32 = domain32 * (pow0 - pow694); + tempvar domain32 = domain32 * (pow0 - pow695); + tempvar domain32 = domain32 * (pow0 - pow696); + tempvar domain32 = domain32 * (pow0 - pow697); + tempvar domain32 = domain32 * (pow0 - pow698); + tempvar domain32 = domain32 * (pow0 - pow699); + tempvar domain32 = domain32 * (pow0 - pow700); + tempvar domain32 = domain32 * (pow0 - pow701); + tempvar domain32 = domain32 * (pow0 - pow702); + tempvar domain32 = domain32 * (pow0 - pow703); + tempvar domain32 = domain32 * (pow0 - pow704); + tempvar domain32 = domain32 * (pow0 - pow705); + tempvar domain32 = domain32 * (pow0 - pow706); + tempvar domain32 = domain32 * (pow0 - pow707); + tempvar domain32 = domain32 * (pow0 - pow708); + tempvar domain32 = domain32 * (pow0 - pow709); + tempvar domain32 = domain32 * (pow0 - pow710); + tempvar domain32 = domain32 * (pow0 - pow711); + tempvar domain32 = domain32 * (pow0 - pow712); + tempvar domain32 = domain32 * (pow0 - pow713); + tempvar domain32 = domain32 * (pow0 - pow714); + tempvar domain32 = domain32 * (pow0 - pow715); + tempvar domain32 = domain32 * (pow0 - pow716); + tempvar domain32 = domain32 * (pow0 - pow717); + tempvar domain32 = domain32 * (pow0 - pow720); + tempvar domain32 = domain32 * (pow0 - pow721); + tempvar domain32 = domain32 * (pow0 - pow722); + tempvar domain32 = domain32 * (pow0 - pow723); + tempvar domain32 = domain32 * (pow0 - pow724); + tempvar domain32 = domain32 * (pow0 - pow725); + tempvar domain32 = domain32 * (pow0 - pow726); + tempvar domain32 = domain32 * (pow0 - pow727); + tempvar domain32 = domain32 * (pow0 - pow728); + tempvar domain32 = domain32 * (pow0 - pow729); + tempvar domain32 = domain32 * (pow0 - pow730); + tempvar domain32 = domain32 * (pow0 - pow731); + tempvar domain32 = domain32 * (pow0 - pow732); + tempvar domain32 = domain32 * (pow0 - pow733); + tempvar domain32 = domain32 * (pow0 - pow734); + tempvar domain32 = domain32 * (pow0 - pow735); + tempvar domain32 = domain32 * (pow0 - pow736); + tempvar domain32 = domain32 * (pow0 - pow737); + tempvar domain32 = domain32 * (pow0 - pow738); + tempvar domain32 = domain32 * (pow0 - pow739); + tempvar domain32 = domain32 * (pow0 - pow740); + tempvar domain32 = domain32 * (pow0 - pow741); + tempvar domain32 = domain32 * (pow0 - pow742); + tempvar domain32 = domain32 * (pow0 - pow743); + tempvar domain32 = domain32 * (pow0 - pow744); + tempvar domain32 = domain32 * (pow0 - pow745); + tempvar domain32 = domain32 * (pow0 - pow746); + tempvar domain32 = domain32 * (pow0 - pow747); + tempvar domain32 = domain32 * (pow0 - pow750); + tempvar domain32 = domain32 * (pow0 - pow751); + tempvar domain32 = domain32 * (pow0 - pow752); + tempvar domain32 = domain32 * (pow0 - pow753); + tempvar domain32 = domain32 * (pow0 - pow754); + tempvar domain32 = domain32 * (pow0 - pow755); + tempvar domain32 = domain32 * (pow0 - pow756); + tempvar domain32 = domain32 * (pow0 - pow757); + tempvar domain32 = domain32 * (pow0 - pow758); + tempvar domain32 = domain32 * (pow0 - pow759); + tempvar domain32 = domain32 * (pow0 - pow760); + tempvar domain32 = domain32 * (pow0 - pow761); + tempvar domain32 = domain32 * (pow0 - pow762); + tempvar domain32 = domain32 * (pow0 - pow763); + tempvar domain32 = domain32 * (pow0 - pow764); + tempvar domain32 = domain32 * (pow0 - pow765); + tempvar domain32 = domain32 * (pow0 - pow766); + tempvar domain32 = domain32 * (pow0 - pow767); + tempvar domain32 = domain32 * (pow0 - pow768); + tempvar domain32 = domain32 * (pow0 - pow769); + tempvar domain32 = domain32 * (pow0 - pow770); + tempvar domain32 = domain32 * (pow0 - pow771); + tempvar domain32 = domain32 * (pow0 - pow772); + tempvar domain32 = domain32 * (pow0 - pow773); + tempvar domain32 = domain32 * (pow0 - pow774); + tempvar domain32 = domain32 * (pow0 - pow775); + tempvar domain32 = domain32 * (pow0 - pow776); + tempvar domain32 = domain32 * (pow0 - pow777); + tempvar domain32 = domain32 * (domain27); + tempvar domain32 = domain32 * (domain30); + tempvar domain33 = domain22; + tempvar domain33 = domain33 * (domain29); + tempvar domain34 = pow0 - pow2576; + tempvar domain35 = pow2 - pow2157; + tempvar domain35 = domain35 * (pow2 - pow2233); + tempvar domain35 = domain35 * (pow2 - pow2309); + tempvar domain35 = domain35 * (pow2 - pow2385); + tempvar domain35 = domain35 * (pow2 - pow2461); + tempvar domain35 = domain35 * (pow2 - pow2537); + tempvar domain35 = domain35 * (pow0 - pow2606); + tempvar domain35 = domain35 * (pow0 - pow2636); + tempvar domain35 = domain35 * (pow0 - pow2666); + tempvar domain35 = domain35 * (pow0 - pow2696); + tempvar domain35 = domain35 * (pow0 - pow2726); + tempvar domain35 = domain35 * (pow0 - pow2756); + tempvar domain35 = domain35 * (pow0 - pow2786); + tempvar domain35 = domain35 * (pow0 - pow2816); + tempvar domain35 = domain35 * (pow0 - pow2846); + tempvar domain35 = domain35 * (pow0 - pow2876); + tempvar domain35 = domain35 * (pow0 - pow2906); + tempvar domain35 = domain35 * (pow0 - pow2936); + tempvar domain35 = domain35 * (pow0 - pow2966); + tempvar domain35 = domain35 * (pow0 - pow2996); + tempvar domain35 = domain35 * (pow0 - pow3026); + tempvar domain35 = domain35 * (pow0 - pow3056); + tempvar domain35 = domain35 * (pow0 - pow3086); + tempvar domain35 = domain35 * (pow0 - pow3116); + tempvar domain35 = domain35 * (pow0 - pow3146); + tempvar domain35 = domain35 * (pow0 - pow3176); + tempvar domain35 = domain35 * (pow0 - pow3206); + tempvar domain35 = domain35 * (pow0 - pow3236); + tempvar domain35 = domain35 * (pow0 - pow3266); + tempvar domain35 = domain35 * (pow0 - pow3296); + tempvar domain35 = domain35 * (domain34); + tempvar domain36 = pow0 - pow2577; + tempvar domain37 = pow2 - pow2181; + tempvar domain37 = domain37 * (pow2 - pow2257); + tempvar domain37 = domain37 * (pow2 - pow2333); + tempvar domain37 = domain37 * (pow2 - pow2409); + tempvar domain37 = domain37 * (pow2 - pow2485); + tempvar domain37 = domain37 * (pow2 - pow2561); + tempvar domain37 = domain37 * (pow0 - pow2607); + tempvar domain37 = domain37 * (pow0 - pow2637); + tempvar domain37 = domain37 * (pow0 - pow2667); + tempvar domain37 = domain37 * (pow0 - pow2697); + tempvar domain37 = domain37 * (pow0 - pow2727); + tempvar domain37 = domain37 * (pow0 - pow2757); + tempvar domain37 = domain37 * (pow0 - pow2787); + tempvar domain37 = domain37 * (pow0 - pow2817); + tempvar domain37 = domain37 * (pow0 - pow2847); + tempvar domain37 = domain37 * (pow0 - pow2877); + tempvar domain37 = domain37 * (pow0 - pow2907); + tempvar domain37 = domain37 * (pow0 - pow2937); + tempvar domain37 = domain37 * (pow0 - pow2967); + tempvar domain37 = domain37 * (pow0 - pow2997); + tempvar domain37 = domain37 * (pow0 - pow3027); + tempvar domain37 = domain37 * (pow0 - pow3057); + tempvar domain37 = domain37 * (pow0 - pow3087); + tempvar domain37 = domain37 * (pow0 - pow3117); + tempvar domain37 = domain37 * (pow0 - pow3147); + tempvar domain37 = domain37 * (pow0 - pow3177); + tempvar domain37 = domain37 * (pow0 - pow3207); + tempvar domain37 = domain37 * (pow0 - pow3237); + tempvar domain37 = domain37 * (pow0 - pow3267); + tempvar domain37 = domain37 * (pow0 - pow3297); + tempvar domain37 = domain37 * (pow0 - pow3326); + tempvar domain37 = domain37 * (pow0 - pow3327); + tempvar domain37 = domain37 * (domain35); + tempvar domain37 = domain37 * (domain36); + tempvar domain38 = pow0 - pow2578; + tempvar domain38 = domain38 * (pow0 - pow2579); + tempvar domain38 = domain38 * (pow0 - pow2580); + tempvar domain38 = domain38 * (pow0 - pow2581); + tempvar domain38 = domain38 * (pow0 - pow2582); + tempvar domain38 = domain38 * (pow0 - pow2583); + tempvar domain39 = pow0 - pow2584; + tempvar domain39 = domain39 * (pow0 - pow2585); + tempvar domain39 = domain39 * (pow0 - pow2586); + tempvar domain39 = domain39 * (pow0 - pow2587); + tempvar domain39 = domain39 * (pow0 - pow2588); + tempvar domain39 = domain39 * (pow0 - pow2589); + tempvar domain39 = domain39 * (pow0 - pow2590); + tempvar domain39 = domain39 * (pow0 - pow2591); + tempvar domain39 = domain39 * (pow0 - pow2592); + tempvar domain39 = domain39 * (pow0 - pow2593); + tempvar domain39 = domain39 * (pow0 - pow2594); + tempvar domain39 = domain39 * (pow0 - pow2595); + tempvar domain39 = domain39 * (pow0 - pow2596); + tempvar domain39 = domain39 * (pow0 - pow2597); + tempvar domain39 = domain39 * (pow0 - pow2598); + tempvar domain39 = domain39 * (pow0 - pow2599); + tempvar domain39 = domain39 * (domain38); + tempvar domain40 = pow5 - pow2461; + tempvar domain40 = domain40 * (pow5 - pow2537); + tempvar domain40 = domain40 * (pow2 - pow2182); + tempvar domain40 = domain40 * (pow2 - pow2183); + tempvar domain40 = domain40 * (pow2 - pow2184); + tempvar domain40 = domain40 * (pow2 - pow2185); + tempvar domain40 = domain40 * (pow2 - pow2186); + tempvar domain40 = domain40 * (pow2 - pow2187); + tempvar domain40 = domain40 * (pow2 - pow2188); + tempvar domain40 = domain40 * (pow2 - pow2189); + tempvar domain40 = domain40 * (pow2 - pow2190); + tempvar domain40 = domain40 * (pow2 - pow2191); + tempvar domain40 = domain40 * (pow2 - pow2192); + tempvar domain40 = domain40 * (pow2 - pow2193); + tempvar domain40 = domain40 * (pow2 - pow2194); + tempvar domain40 = domain40 * (pow2 - pow2195); + tempvar domain40 = domain40 * (pow2 - pow2196); + tempvar domain40 = domain40 * (pow2 - pow2220); + tempvar domain40 = domain40 * (pow2 - pow2221); + tempvar domain40 = domain40 * (pow2 - pow2222); + tempvar domain40 = domain40 * (pow2 - pow2223); + tempvar domain40 = domain40 * (pow2 - pow2224); + tempvar domain40 = domain40 * (pow2 - pow2225); + tempvar domain40 = domain40 * (pow2 - pow2226); + tempvar domain40 = domain40 * (pow2 - pow2227); + tempvar domain40 = domain40 * (pow2 - pow2228); + tempvar domain40 = domain40 * (pow2 - pow2229); + tempvar domain40 = domain40 * (pow2 - pow2230); + tempvar domain40 = domain40 * (pow2 - pow2231); + tempvar domain40 = domain40 * (pow2 - pow2232); + tempvar domain40 = domain40 * (pow2 - pow2258); + tempvar domain40 = domain40 * (pow2 - pow2259); + tempvar domain40 = domain40 * (pow2 - pow2260); + tempvar domain40 = domain40 * (pow2 - pow2261); + tempvar domain40 = domain40 * (pow2 - pow2262); + tempvar domain40 = domain40 * (pow2 - pow2263); + tempvar domain40 = domain40 * (pow2 - pow2264); + tempvar domain40 = domain40 * (pow2 - pow2265); + tempvar domain40 = domain40 * (pow2 - pow2266); + tempvar domain40 = domain40 * (pow2 - pow2267); + tempvar domain40 = domain40 * (pow2 - pow2268); + tempvar domain40 = domain40 * (pow2 - pow2269); + tempvar domain40 = domain40 * (pow2 - pow2270); + tempvar domain40 = domain40 * (pow2 - pow2271); + tempvar domain40 = domain40 * (pow2 - pow2272); + tempvar domain40 = domain40 * (pow2 - pow2296); + tempvar domain40 = domain40 * (pow2 - pow2297); + tempvar domain40 = domain40 * (pow2 - pow2298); + tempvar domain40 = domain40 * (pow2 - pow2299); + tempvar domain40 = domain40 * (pow2 - pow2300); + tempvar domain40 = domain40 * (pow2 - pow2301); + tempvar domain40 = domain40 * (pow2 - pow2302); + tempvar domain40 = domain40 * (pow2 - pow2303); + tempvar domain40 = domain40 * (pow2 - pow2304); + tempvar domain40 = domain40 * (pow2 - pow2305); + tempvar domain40 = domain40 * (pow2 - pow2306); + tempvar domain40 = domain40 * (pow2 - pow2307); + tempvar domain40 = domain40 * (pow2 - pow2308); + tempvar domain40 = domain40 * (pow2 - pow2334); + tempvar domain40 = domain40 * (pow2 - pow2335); + tempvar domain40 = domain40 * (pow2 - pow2336); + tempvar domain40 = domain40 * (pow2 - pow2337); + tempvar domain40 = domain40 * (pow2 - pow2338); + tempvar domain40 = domain40 * (pow2 - pow2339); + tempvar domain40 = domain40 * (pow2 - pow2340); + tempvar domain40 = domain40 * (pow2 - pow2341); + tempvar domain40 = domain40 * (pow2 - pow2342); + tempvar domain40 = domain40 * (pow2 - pow2343); + tempvar domain40 = domain40 * (pow2 - pow2344); + tempvar domain40 = domain40 * (pow2 - pow2345); + tempvar domain40 = domain40 * (pow2 - pow2346); + tempvar domain40 = domain40 * (pow2 - pow2347); + tempvar domain40 = domain40 * (pow2 - pow2348); + tempvar domain40 = domain40 * (pow2 - pow2372); + tempvar domain40 = domain40 * (pow2 - pow2373); + tempvar domain40 = domain40 * (pow2 - pow2374); + tempvar domain40 = domain40 * (pow2 - pow2375); + tempvar domain40 = domain40 * (pow2 - pow2376); + tempvar domain40 = domain40 * (pow2 - pow2377); + tempvar domain40 = domain40 * (pow2 - pow2378); + tempvar domain40 = domain40 * (pow2 - pow2379); + tempvar domain40 = domain40 * (pow2 - pow2380); + tempvar domain40 = domain40 * (pow2 - pow2381); + tempvar domain40 = domain40 * (pow2 - pow2382); + tempvar domain40 = domain40 * (pow2 - pow2383); + tempvar domain40 = domain40 * (pow2 - pow2384); + tempvar domain40 = domain40 * (pow2 - pow2410); + tempvar domain40 = domain40 * (pow2 - pow2411); + tempvar domain40 = domain40 * (pow2 - pow2412); + tempvar domain40 = domain40 * (pow2 - pow2413); + tempvar domain40 = domain40 * (pow2 - pow2414); + tempvar domain40 = domain40 * (pow2 - pow2415); + tempvar domain40 = domain40 * (pow2 - pow2416); + tempvar domain40 = domain40 * (pow2 - pow2417); + tempvar domain40 = domain40 * (pow2 - pow2418); + tempvar domain40 = domain40 * (pow2 - pow2419); + tempvar domain40 = domain40 * (pow2 - pow2420); + tempvar domain40 = domain40 * (pow2 - pow2421); + tempvar domain40 = domain40 * (pow2 - pow2422); + tempvar domain40 = domain40 * (pow2 - pow2423); + tempvar domain40 = domain40 * (pow2 - pow2424); + tempvar domain40 = domain40 * (pow2 - pow2448); + tempvar domain40 = domain40 * (pow2 - pow2449); + tempvar domain40 = domain40 * (pow2 - pow2450); + tempvar domain40 = domain40 * (pow2 - pow2451); + tempvar domain40 = domain40 * (pow2 - pow2452); + tempvar domain40 = domain40 * (pow2 - pow2453); + tempvar domain40 = domain40 * (pow2 - pow2454); + tempvar domain40 = domain40 * (pow2 - pow2455); + tempvar domain40 = domain40 * (pow2 - pow2456); + tempvar domain40 = domain40 * (pow2 - pow2457); + tempvar domain40 = domain40 * (pow2 - pow2458); + tempvar domain40 = domain40 * (pow2 - pow2459); + tempvar domain40 = domain40 * (pow2 - pow2460); + tempvar domain40 = domain40 * (pow2 - pow2486); + tempvar domain40 = domain40 * (pow2 - pow2487); + tempvar domain40 = domain40 * (pow2 - pow2488); + tempvar domain40 = domain40 * (pow2 - pow2489); + tempvar domain40 = domain40 * (pow2 - pow2490); + tempvar domain40 = domain40 * (pow2 - pow2491); + tempvar domain40 = domain40 * (pow2 - pow2492); + tempvar domain40 = domain40 * (pow2 - pow2493); + tempvar domain40 = domain40 * (pow2 - pow2494); + tempvar domain40 = domain40 * (pow2 - pow2495); + tempvar domain40 = domain40 * (pow2 - pow2496); + tempvar domain40 = domain40 * (pow2 - pow2497); + tempvar domain40 = domain40 * (pow2 - pow2498); + tempvar domain40 = domain40 * (pow2 - pow2499); + tempvar domain40 = domain40 * (pow2 - pow2500); + tempvar domain40 = domain40 * (pow2 - pow2524); + tempvar domain40 = domain40 * (pow2 - pow2525); + tempvar domain40 = domain40 * (pow2 - pow2526); + tempvar domain40 = domain40 * (pow2 - pow2527); + tempvar domain40 = domain40 * (pow2 - pow2528); + tempvar domain40 = domain40 * (pow2 - pow2529); + tempvar domain40 = domain40 * (pow2 - pow2530); + tempvar domain40 = domain40 * (pow2 - pow2531); + tempvar domain40 = domain40 * (pow2 - pow2532); + tempvar domain40 = domain40 * (pow2 - pow2533); + tempvar domain40 = domain40 * (pow2 - pow2534); + tempvar domain40 = domain40 * (pow2 - pow2535); + tempvar domain40 = domain40 * (pow2 - pow2536); + tempvar domain40 = domain40 * (pow2 - pow2562); + tempvar domain40 = domain40 * (pow2 - pow2563); + tempvar domain40 = domain40 * (pow2 - pow2564); + tempvar domain40 = domain40 * (pow2 - pow2565); + tempvar domain40 = domain40 * (pow2 - pow2566); + tempvar domain40 = domain40 * (pow2 - pow2567); + tempvar domain40 = domain40 * (pow2 - pow2568); + tempvar domain40 = domain40 * (pow2 - pow2569); + tempvar domain40 = domain40 * (pow2 - pow2570); + tempvar domain40 = domain40 * (pow2 - pow2571); + tempvar domain40 = domain40 * (pow2 - pow2572); + tempvar domain40 = domain40 * (pow2 - pow2573); + tempvar domain40 = domain40 * (pow2 - pow2574); + tempvar domain40 = domain40 * (pow2 - pow2575); + tempvar domain40 = domain40 * (pow2 - pow2576); + tempvar domain40 = domain40 * (pow2 - pow2636); + tempvar domain40 = domain40 * (pow2 - pow2696); + tempvar domain40 = domain40 * (pow2 - pow2756); + tempvar domain40 = domain40 * (pow2 - pow2816); + tempvar domain40 = domain40 * (pow2 - pow2876); + tempvar domain40 = domain40 * (pow2 - pow2936); + tempvar domain40 = domain40 * (pow2 - pow2996); + tempvar domain40 = domain40 * (pow2 - pow3056); + tempvar domain40 = domain40 * (pow2 - pow3116); + tempvar domain40 = domain40 * (pow2 - pow3176); + tempvar domain40 = domain40 * (pow2 - pow3236); + tempvar domain40 = domain40 * (pow2 - pow3296); + tempvar domain40 = domain40 * (pow2 - pow3356); + tempvar domain40 = domain40 * (pow0 - pow2600); + tempvar domain40 = domain40 * (pow0 - pow2601); + tempvar domain40 = domain40 * (pow0 - pow2602); + tempvar domain40 = domain40 * (pow0 - pow2603); + tempvar domain40 = domain40 * (pow0 - pow2604); + tempvar domain40 = domain40 * (pow0 - pow2605); + tempvar domain40 = domain40 * (pow0 - pow2608); + tempvar domain40 = domain40 * (pow0 - pow2609); + tempvar domain40 = domain40 * (pow0 - pow2610); + tempvar domain40 = domain40 * (pow0 - pow2611); + tempvar domain40 = domain40 * (pow0 - pow2612); + tempvar domain40 = domain40 * (pow0 - pow2613); + tempvar domain40 = domain40 * (pow0 - pow2614); + tempvar domain40 = domain40 * (pow0 - pow2615); + tempvar domain40 = domain40 * (pow0 - pow2616); + tempvar domain40 = domain40 * (pow0 - pow2617); + tempvar domain40 = domain40 * (pow0 - pow2618); + tempvar domain40 = domain40 * (pow0 - pow2619); + tempvar domain40 = domain40 * (pow0 - pow2620); + tempvar domain40 = domain40 * (pow0 - pow2621); + tempvar domain40 = domain40 * (pow0 - pow2622); + tempvar domain40 = domain40 * (pow0 - pow2623); + tempvar domain40 = domain40 * (pow0 - pow2624); + tempvar domain40 = domain40 * (pow0 - pow2625); + tempvar domain40 = domain40 * (pow0 - pow2626); + tempvar domain40 = domain40 * (pow0 - pow2627); + tempvar domain40 = domain40 * (pow0 - pow2628); + tempvar domain40 = domain40 * (pow0 - pow2629); + tempvar domain40 = domain40 * (pow0 - pow2630); + tempvar domain40 = domain40 * (pow0 - pow2631); + tempvar domain40 = domain40 * (pow0 - pow2632); + tempvar domain40 = domain40 * (pow0 - pow2633); + tempvar domain40 = domain40 * (pow0 - pow2634); + tempvar domain40 = domain40 * (pow0 - pow2635); + tempvar domain40 = domain40 * (pow0 - pow2638); + tempvar domain40 = domain40 * (pow0 - pow2639); + tempvar domain40 = domain40 * (pow0 - pow2640); + tempvar domain40 = domain40 * (pow0 - pow2641); + tempvar domain40 = domain40 * (pow0 - pow2642); + tempvar domain40 = domain40 * (pow0 - pow2643); + tempvar domain40 = domain40 * (pow0 - pow2644); + tempvar domain40 = domain40 * (pow0 - pow2645); + tempvar domain40 = domain40 * (pow0 - pow2646); + tempvar domain40 = domain40 * (pow0 - pow2647); + tempvar domain40 = domain40 * (pow0 - pow2648); + tempvar domain40 = domain40 * (pow0 - pow2649); + tempvar domain40 = domain40 * (pow0 - pow2650); + tempvar domain40 = domain40 * (pow0 - pow2651); + tempvar domain40 = domain40 * (pow0 - pow2652); + tempvar domain40 = domain40 * (pow0 - pow2653); + tempvar domain40 = domain40 * (pow0 - pow2654); + tempvar domain40 = domain40 * (pow0 - pow2655); + tempvar domain40 = domain40 * (pow0 - pow2656); + tempvar domain40 = domain40 * (pow0 - pow2657); + tempvar domain40 = domain40 * (pow0 - pow2658); + tempvar domain40 = domain40 * (pow0 - pow2659); + tempvar domain40 = domain40 * (pow0 - pow2660); + tempvar domain40 = domain40 * (pow0 - pow2661); + tempvar domain40 = domain40 * (pow0 - pow2662); + tempvar domain40 = domain40 * (pow0 - pow2663); + tempvar domain40 = domain40 * (pow0 - pow2664); + tempvar domain40 = domain40 * (pow0 - pow2665); + tempvar domain40 = domain40 * (pow0 - pow2668); + tempvar domain40 = domain40 * (pow0 - pow2669); + tempvar domain40 = domain40 * (pow0 - pow2670); + tempvar domain40 = domain40 * (pow0 - pow2671); + tempvar domain40 = domain40 * (pow0 - pow2672); + tempvar domain40 = domain40 * (pow0 - pow2673); + tempvar domain40 = domain40 * (pow0 - pow2674); + tempvar domain40 = domain40 * (pow0 - pow2675); + tempvar domain40 = domain40 * (pow0 - pow2676); + tempvar domain40 = domain40 * (pow0 - pow2677); + tempvar domain40 = domain40 * (pow0 - pow2678); + tempvar domain40 = domain40 * (pow0 - pow2679); + tempvar domain40 = domain40 * (pow0 - pow2680); + tempvar domain40 = domain40 * (pow0 - pow2681); + tempvar domain40 = domain40 * (pow0 - pow2682); + tempvar domain40 = domain40 * (pow0 - pow2683); + tempvar domain40 = domain40 * (pow0 - pow2684); + tempvar domain40 = domain40 * (pow0 - pow2685); + tempvar domain40 = domain40 * (pow0 - pow2686); + tempvar domain40 = domain40 * (pow0 - pow2687); + tempvar domain40 = domain40 * (pow0 - pow2688); + tempvar domain40 = domain40 * (pow0 - pow2689); + tempvar domain40 = domain40 * (pow0 - pow2690); + tempvar domain40 = domain40 * (pow0 - pow2691); + tempvar domain40 = domain40 * (pow0 - pow2692); + tempvar domain40 = domain40 * (pow0 - pow2693); + tempvar domain40 = domain40 * (pow0 - pow2694); + tempvar domain40 = domain40 * (pow0 - pow2695); + tempvar domain40 = domain40 * (pow0 - pow2698); + tempvar domain40 = domain40 * (pow0 - pow2699); + tempvar domain40 = domain40 * (pow0 - pow2700); + tempvar domain40 = domain40 * (pow0 - pow2701); + tempvar domain40 = domain40 * (pow0 - pow2702); + tempvar domain40 = domain40 * (pow0 - pow2703); + tempvar domain40 = domain40 * (pow0 - pow2704); + tempvar domain40 = domain40 * (pow0 - pow2705); + tempvar domain40 = domain40 * (pow0 - pow2706); + tempvar domain40 = domain40 * (pow0 - pow2707); + tempvar domain40 = domain40 * (pow0 - pow2708); + tempvar domain40 = domain40 * (pow0 - pow2709); + tempvar domain40 = domain40 * (pow0 - pow2710); + tempvar domain40 = domain40 * (pow0 - pow2711); + tempvar domain40 = domain40 * (pow0 - pow2712); + tempvar domain40 = domain40 * (pow0 - pow2713); + tempvar domain40 = domain40 * (pow0 - pow2714); + tempvar domain40 = domain40 * (pow0 - pow2715); + tempvar domain40 = domain40 * (pow0 - pow2716); + tempvar domain40 = domain40 * (pow0 - pow2717); + tempvar domain40 = domain40 * (pow0 - pow2718); + tempvar domain40 = domain40 * (pow0 - pow2719); + tempvar domain40 = domain40 * (pow0 - pow2720); + tempvar domain40 = domain40 * (pow0 - pow2721); + tempvar domain40 = domain40 * (pow0 - pow2722); + tempvar domain40 = domain40 * (pow0 - pow2723); + tempvar domain40 = domain40 * (pow0 - pow2724); + tempvar domain40 = domain40 * (pow0 - pow2725); + tempvar domain40 = domain40 * (pow0 - pow2728); + tempvar domain40 = domain40 * (pow0 - pow2729); + tempvar domain40 = domain40 * (pow0 - pow2730); + tempvar domain40 = domain40 * (pow0 - pow2731); + tempvar domain40 = domain40 * (pow0 - pow2732); + tempvar domain40 = domain40 * (pow0 - pow2733); + tempvar domain40 = domain40 * (pow0 - pow2734); + tempvar domain40 = domain40 * (pow0 - pow2735); + tempvar domain40 = domain40 * (pow0 - pow2736); + tempvar domain40 = domain40 * (pow0 - pow2737); + tempvar domain40 = domain40 * (pow0 - pow2738); + tempvar domain40 = domain40 * (pow0 - pow2739); + tempvar domain40 = domain40 * (pow0 - pow2740); + tempvar domain40 = domain40 * (pow0 - pow2741); + tempvar domain40 = domain40 * (pow0 - pow2742); + tempvar domain40 = domain40 * (pow0 - pow2743); + tempvar domain40 = domain40 * (pow0 - pow2744); + tempvar domain40 = domain40 * (pow0 - pow2745); + tempvar domain40 = domain40 * (pow0 - pow2746); + tempvar domain40 = domain40 * (pow0 - pow2747); + tempvar domain40 = domain40 * (pow0 - pow2748); + tempvar domain40 = domain40 * (pow0 - pow2749); + tempvar domain40 = domain40 * (pow0 - pow2750); + tempvar domain40 = domain40 * (pow0 - pow2751); + tempvar domain40 = domain40 * (pow0 - pow2752); + tempvar domain40 = domain40 * (pow0 - pow2753); + tempvar domain40 = domain40 * (pow0 - pow2754); + tempvar domain40 = domain40 * (pow0 - pow2755); + tempvar domain40 = domain40 * (pow0 - pow2758); + tempvar domain40 = domain40 * (pow0 - pow2759); + tempvar domain40 = domain40 * (pow0 - pow2760); + tempvar domain40 = domain40 * (pow0 - pow2761); + tempvar domain40 = domain40 * (pow0 - pow2762); + tempvar domain40 = domain40 * (pow0 - pow2763); + tempvar domain40 = domain40 * (pow0 - pow2764); + tempvar domain40 = domain40 * (pow0 - pow2765); + tempvar domain40 = domain40 * (pow0 - pow2766); + tempvar domain40 = domain40 * (pow0 - pow2767); + tempvar domain40 = domain40 * (pow0 - pow2768); + tempvar domain40 = domain40 * (pow0 - pow2769); + tempvar domain40 = domain40 * (pow0 - pow2770); + tempvar domain40 = domain40 * (pow0 - pow2771); + tempvar domain40 = domain40 * (pow0 - pow2772); + tempvar domain40 = domain40 * (pow0 - pow2773); + tempvar domain40 = domain40 * (pow0 - pow2774); + tempvar domain40 = domain40 * (pow0 - pow2775); + tempvar domain40 = domain40 * (pow0 - pow2776); + tempvar domain40 = domain40 * (pow0 - pow2777); + tempvar domain40 = domain40 * (pow0 - pow2778); + tempvar domain40 = domain40 * (pow0 - pow2779); + tempvar domain40 = domain40 * (pow0 - pow2780); + tempvar domain40 = domain40 * (pow0 - pow2781); + tempvar domain40 = domain40 * (pow0 - pow2782); + tempvar domain40 = domain40 * (pow0 - pow2783); + tempvar domain40 = domain40 * (pow0 - pow2784); + tempvar domain40 = domain40 * (pow0 - pow2785); + tempvar domain40 = domain40 * (pow0 - pow2788); + tempvar domain40 = domain40 * (pow0 - pow2789); + tempvar domain40 = domain40 * (pow0 - pow2790); + tempvar domain40 = domain40 * (pow0 - pow2791); + tempvar domain40 = domain40 * (pow0 - pow2792); + tempvar domain40 = domain40 * (pow0 - pow2793); + tempvar domain40 = domain40 * (pow0 - pow2794); + tempvar domain40 = domain40 * (pow0 - pow2795); + tempvar domain40 = domain40 * (pow0 - pow2796); + tempvar domain40 = domain40 * (pow0 - pow2797); + tempvar domain40 = domain40 * (pow0 - pow2798); + tempvar domain40 = domain40 * (pow0 - pow2799); + tempvar domain40 = domain40 * (pow0 - pow2800); + tempvar domain40 = domain40 * (pow0 - pow2801); + tempvar domain40 = domain40 * (pow0 - pow2802); + tempvar domain40 = domain40 * (pow0 - pow2803); + tempvar domain40 = domain40 * (pow0 - pow2804); + tempvar domain40 = domain40 * (pow0 - pow2805); + tempvar domain40 = domain40 * (pow0 - pow2806); + tempvar domain40 = domain40 * (pow0 - pow2807); + tempvar domain40 = domain40 * (pow0 - pow2808); + tempvar domain40 = domain40 * (pow0 - pow2809); + tempvar domain40 = domain40 * (pow0 - pow2810); + tempvar domain40 = domain40 * (pow0 - pow2811); + tempvar domain40 = domain40 * (pow0 - pow2812); + tempvar domain40 = domain40 * (pow0 - pow2813); + tempvar domain40 = domain40 * (pow0 - pow2814); + tempvar domain40 = domain40 * (pow0 - pow2815); + tempvar domain40 = domain40 * (pow0 - pow2818); + tempvar domain40 = domain40 * (pow0 - pow2819); + tempvar domain40 = domain40 * (pow0 - pow2820); + tempvar domain40 = domain40 * (pow0 - pow2821); + tempvar domain40 = domain40 * (pow0 - pow2822); + tempvar domain40 = domain40 * (pow0 - pow2823); + tempvar domain40 = domain40 * (pow0 - pow2824); + tempvar domain40 = domain40 * (pow0 - pow2825); + tempvar domain40 = domain40 * (pow0 - pow2826); + tempvar domain40 = domain40 * (pow0 - pow2827); + tempvar domain40 = domain40 * (pow0 - pow2828); + tempvar domain40 = domain40 * (pow0 - pow2829); + tempvar domain40 = domain40 * (pow0 - pow2830); + tempvar domain40 = domain40 * (pow0 - pow2831); + tempvar domain40 = domain40 * (pow0 - pow2832); + tempvar domain40 = domain40 * (pow0 - pow2833); + tempvar domain40 = domain40 * (pow0 - pow2834); + tempvar domain40 = domain40 * (pow0 - pow2835); + tempvar domain40 = domain40 * (pow0 - pow2836); + tempvar domain40 = domain40 * (pow0 - pow2837); + tempvar domain40 = domain40 * (pow0 - pow2838); + tempvar domain40 = domain40 * (pow0 - pow2839); + tempvar domain40 = domain40 * (pow0 - pow2840); + tempvar domain40 = domain40 * (pow0 - pow2841); + tempvar domain40 = domain40 * (pow0 - pow2842); + tempvar domain40 = domain40 * (pow0 - pow2843); + tempvar domain40 = domain40 * (pow0 - pow2844); + tempvar domain40 = domain40 * (pow0 - pow2845); + tempvar domain40 = domain40 * (pow0 - pow2848); + tempvar domain40 = domain40 * (pow0 - pow2849); + tempvar domain40 = domain40 * (pow0 - pow2850); + tempvar domain40 = domain40 * (pow0 - pow2851); + tempvar domain40 = domain40 * (pow0 - pow2852); + tempvar domain40 = domain40 * (pow0 - pow2853); + tempvar domain40 = domain40 * (pow0 - pow2854); + tempvar domain40 = domain40 * (pow0 - pow2855); + tempvar domain40 = domain40 * (pow0 - pow2856); + tempvar domain40 = domain40 * (pow0 - pow2857); + tempvar domain40 = domain40 * (pow0 - pow2858); + tempvar domain40 = domain40 * (pow0 - pow2859); + tempvar domain40 = domain40 * (pow0 - pow2860); + tempvar domain40 = domain40 * (pow0 - pow2861); + tempvar domain40 = domain40 * (pow0 - pow2862); + tempvar domain40 = domain40 * (pow0 - pow2863); + tempvar domain40 = domain40 * (pow0 - pow2864); + tempvar domain40 = domain40 * (pow0 - pow2865); + tempvar domain40 = domain40 * (pow0 - pow2866); + tempvar domain40 = domain40 * (pow0 - pow2867); + tempvar domain40 = domain40 * (pow0 - pow2868); + tempvar domain40 = domain40 * (pow0 - pow2869); + tempvar domain40 = domain40 * (pow0 - pow2870); + tempvar domain40 = domain40 * (pow0 - pow2871); + tempvar domain40 = domain40 * (pow0 - pow2872); + tempvar domain40 = domain40 * (pow0 - pow2873); + tempvar domain40 = domain40 * (pow0 - pow2874); + tempvar domain40 = domain40 * (pow0 - pow2875); + tempvar domain40 = domain40 * (pow0 - pow2878); + tempvar domain40 = domain40 * (pow0 - pow2879); + tempvar domain40 = domain40 * (pow0 - pow2880); + tempvar domain40 = domain40 * (pow0 - pow2881); + tempvar domain40 = domain40 * (pow0 - pow2882); + tempvar domain40 = domain40 * (pow0 - pow2883); + tempvar domain40 = domain40 * (pow0 - pow2884); + tempvar domain40 = domain40 * (pow0 - pow2885); + tempvar domain40 = domain40 * (pow0 - pow2886); + tempvar domain40 = domain40 * (pow0 - pow2887); + tempvar domain40 = domain40 * (pow0 - pow2888); + tempvar domain40 = domain40 * (pow0 - pow2889); + tempvar domain40 = domain40 * (pow0 - pow2890); + tempvar domain40 = domain40 * (pow0 - pow2891); + tempvar domain40 = domain40 * (pow0 - pow2892); + tempvar domain40 = domain40 * (pow0 - pow2893); + tempvar domain40 = domain40 * (pow0 - pow2894); + tempvar domain40 = domain40 * (pow0 - pow2895); + tempvar domain40 = domain40 * (pow0 - pow2896); + tempvar domain40 = domain40 * (pow0 - pow2897); + tempvar domain40 = domain40 * (pow0 - pow2898); + tempvar domain40 = domain40 * (pow0 - pow2899); + tempvar domain40 = domain40 * (pow0 - pow2900); + tempvar domain40 = domain40 * (pow0 - pow2901); + tempvar domain40 = domain40 * (pow0 - pow2902); + tempvar domain40 = domain40 * (pow0 - pow2903); + tempvar domain40 = domain40 * (pow0 - pow2904); + tempvar domain40 = domain40 * (pow0 - pow2905); + tempvar domain40 = domain40 * (pow0 - pow2908); + tempvar domain40 = domain40 * (pow0 - pow2909); + tempvar domain40 = domain40 * (pow0 - pow2910); + tempvar domain40 = domain40 * (pow0 - pow2911); + tempvar domain40 = domain40 * (pow0 - pow2912); + tempvar domain40 = domain40 * (pow0 - pow2913); + tempvar domain40 = domain40 * (pow0 - pow2914); + tempvar domain40 = domain40 * (pow0 - pow2915); + tempvar domain40 = domain40 * (pow0 - pow2916); + tempvar domain40 = domain40 * (pow0 - pow2917); + tempvar domain40 = domain40 * (pow0 - pow2918); + tempvar domain40 = domain40 * (pow0 - pow2919); + tempvar domain40 = domain40 * (pow0 - pow2920); + tempvar domain40 = domain40 * (pow0 - pow2921); + tempvar domain40 = domain40 * (pow0 - pow2922); + tempvar domain40 = domain40 * (pow0 - pow2923); + tempvar domain40 = domain40 * (pow0 - pow2924); + tempvar domain40 = domain40 * (pow0 - pow2925); + tempvar domain40 = domain40 * (pow0 - pow2926); + tempvar domain40 = domain40 * (pow0 - pow2927); + tempvar domain40 = domain40 * (pow0 - pow2928); + tempvar domain40 = domain40 * (pow0 - pow2929); + tempvar domain40 = domain40 * (pow0 - pow2930); + tempvar domain40 = domain40 * (pow0 - pow2931); + tempvar domain40 = domain40 * (pow0 - pow2932); + tempvar domain40 = domain40 * (pow0 - pow2933); + tempvar domain40 = domain40 * (pow0 - pow2934); + tempvar domain40 = domain40 * (pow0 - pow2935); + tempvar domain40 = domain40 * (pow0 - pow2938); + tempvar domain40 = domain40 * (pow0 - pow2939); + tempvar domain40 = domain40 * (pow0 - pow2940); + tempvar domain40 = domain40 * (pow0 - pow2941); + tempvar domain40 = domain40 * (pow0 - pow2942); + tempvar domain40 = domain40 * (pow0 - pow2943); + tempvar domain40 = domain40 * (pow0 - pow2944); + tempvar domain40 = domain40 * (pow0 - pow2945); + tempvar domain40 = domain40 * (pow0 - pow2946); + tempvar domain40 = domain40 * (pow0 - pow2947); + tempvar domain40 = domain40 * (pow0 - pow2948); + tempvar domain40 = domain40 * (pow0 - pow2949); + tempvar domain40 = domain40 * (pow0 - pow2950); + tempvar domain40 = domain40 * (pow0 - pow2951); + tempvar domain40 = domain40 * (pow0 - pow2952); + tempvar domain40 = domain40 * (pow0 - pow2953); + tempvar domain40 = domain40 * (pow0 - pow2954); + tempvar domain40 = domain40 * (pow0 - pow2955); + tempvar domain40 = domain40 * (pow0 - pow2956); + tempvar domain40 = domain40 * (pow0 - pow2957); + tempvar domain40 = domain40 * (pow0 - pow2958); + tempvar domain40 = domain40 * (pow0 - pow2959); + tempvar domain40 = domain40 * (pow0 - pow2960); + tempvar domain40 = domain40 * (pow0 - pow2961); + tempvar domain40 = domain40 * (pow0 - pow2962); + tempvar domain40 = domain40 * (pow0 - pow2963); + tempvar domain40 = domain40 * (pow0 - pow2964); + tempvar domain40 = domain40 * (pow0 - pow2965); + tempvar domain40 = domain40 * (pow0 - pow2968); + tempvar domain40 = domain40 * (pow0 - pow2969); + tempvar domain40 = domain40 * (pow0 - pow2970); + tempvar domain40 = domain40 * (pow0 - pow2971); + tempvar domain40 = domain40 * (pow0 - pow2972); + tempvar domain40 = domain40 * (pow0 - pow2973); + tempvar domain40 = domain40 * (pow0 - pow2974); + tempvar domain40 = domain40 * (pow0 - pow2975); + tempvar domain40 = domain40 * (pow0 - pow2976); + tempvar domain40 = domain40 * (pow0 - pow2977); + tempvar domain40 = domain40 * (pow0 - pow2978); + tempvar domain40 = domain40 * (pow0 - pow2979); + tempvar domain40 = domain40 * (pow0 - pow2980); + tempvar domain40 = domain40 * (pow0 - pow2981); + tempvar domain40 = domain40 * (pow0 - pow2982); + tempvar domain40 = domain40 * (pow0 - pow2983); + tempvar domain40 = domain40 * (pow0 - pow2984); + tempvar domain40 = domain40 * (pow0 - pow2985); + tempvar domain40 = domain40 * (pow0 - pow2986); + tempvar domain40 = domain40 * (pow0 - pow2987); + tempvar domain40 = domain40 * (pow0 - pow2988); + tempvar domain40 = domain40 * (pow0 - pow2989); + tempvar domain40 = domain40 * (pow0 - pow2990); + tempvar domain40 = domain40 * (pow0 - pow2991); + tempvar domain40 = domain40 * (pow0 - pow2992); + tempvar domain40 = domain40 * (pow0 - pow2993); + tempvar domain40 = domain40 * (pow0 - pow2994); + tempvar domain40 = domain40 * (pow0 - pow2995); + tempvar domain40 = domain40 * (pow0 - pow2998); + tempvar domain40 = domain40 * (pow0 - pow2999); + tempvar domain40 = domain40 * (pow0 - pow3000); + tempvar domain40 = domain40 * (pow0 - pow3001); + tempvar domain40 = domain40 * (pow0 - pow3002); + tempvar domain40 = domain40 * (pow0 - pow3003); + tempvar domain40 = domain40 * (pow0 - pow3004); + tempvar domain40 = domain40 * (pow0 - pow3005); + tempvar domain40 = domain40 * (pow0 - pow3006); + tempvar domain40 = domain40 * (pow0 - pow3007); + tempvar domain40 = domain40 * (pow0 - pow3008); + tempvar domain40 = domain40 * (pow0 - pow3009); + tempvar domain40 = domain40 * (pow0 - pow3010); + tempvar domain40 = domain40 * (pow0 - pow3011); + tempvar domain40 = domain40 * (pow0 - pow3012); + tempvar domain40 = domain40 * (pow0 - pow3013); + tempvar domain40 = domain40 * (pow0 - pow3014); + tempvar domain40 = domain40 * (pow0 - pow3015); + tempvar domain40 = domain40 * (pow0 - pow3016); + tempvar domain40 = domain40 * (pow0 - pow3017); + tempvar domain40 = domain40 * (pow0 - pow3018); + tempvar domain40 = domain40 * (pow0 - pow3019); + tempvar domain40 = domain40 * (pow0 - pow3020); + tempvar domain40 = domain40 * (pow0 - pow3021); + tempvar domain40 = domain40 * (pow0 - pow3022); + tempvar domain40 = domain40 * (pow0 - pow3023); + tempvar domain40 = domain40 * (pow0 - pow3024); + tempvar domain40 = domain40 * (pow0 - pow3025); + tempvar domain40 = domain40 * (pow0 - pow3028); + tempvar domain40 = domain40 * (pow0 - pow3029); + tempvar domain40 = domain40 * (pow0 - pow3030); + tempvar domain40 = domain40 * (pow0 - pow3031); + tempvar domain40 = domain40 * (pow0 - pow3032); + tempvar domain40 = domain40 * (pow0 - pow3033); + tempvar domain40 = domain40 * (pow0 - pow3034); + tempvar domain40 = domain40 * (pow0 - pow3035); + tempvar domain40 = domain40 * (pow0 - pow3036); + tempvar domain40 = domain40 * (pow0 - pow3037); + tempvar domain40 = domain40 * (pow0 - pow3038); + tempvar domain40 = domain40 * (pow0 - pow3039); + tempvar domain40 = domain40 * (pow0 - pow3040); + tempvar domain40 = domain40 * (pow0 - pow3041); + tempvar domain40 = domain40 * (pow0 - pow3042); + tempvar domain40 = domain40 * (pow0 - pow3043); + tempvar domain40 = domain40 * (pow0 - pow3044); + tempvar domain40 = domain40 * (pow0 - pow3045); + tempvar domain40 = domain40 * (pow0 - pow3046); + tempvar domain40 = domain40 * (pow0 - pow3047); + tempvar domain40 = domain40 * (pow0 - pow3048); + tempvar domain40 = domain40 * (pow0 - pow3049); + tempvar domain40 = domain40 * (pow0 - pow3050); + tempvar domain40 = domain40 * (pow0 - pow3051); + tempvar domain40 = domain40 * (pow0 - pow3052); + tempvar domain40 = domain40 * (pow0 - pow3053); + tempvar domain40 = domain40 * (pow0 - pow3054); + tempvar domain40 = domain40 * (pow0 - pow3055); + tempvar domain40 = domain40 * (pow0 - pow3058); + tempvar domain40 = domain40 * (pow0 - pow3059); + tempvar domain40 = domain40 * (pow0 - pow3060); + tempvar domain40 = domain40 * (pow0 - pow3061); + tempvar domain40 = domain40 * (pow0 - pow3062); + tempvar domain40 = domain40 * (pow0 - pow3063); + tempvar domain40 = domain40 * (pow0 - pow3064); + tempvar domain40 = domain40 * (pow0 - pow3065); + tempvar domain40 = domain40 * (pow0 - pow3066); + tempvar domain40 = domain40 * (pow0 - pow3067); + tempvar domain40 = domain40 * (pow0 - pow3068); + tempvar domain40 = domain40 * (pow0 - pow3069); + tempvar domain40 = domain40 * (pow0 - pow3070); + tempvar domain40 = domain40 * (pow0 - pow3071); + tempvar domain40 = domain40 * (pow0 - pow3072); + tempvar domain40 = domain40 * (pow0 - pow3073); + tempvar domain40 = domain40 * (pow0 - pow3074); + tempvar domain40 = domain40 * (pow0 - pow3075); + tempvar domain40 = domain40 * (pow0 - pow3076); + tempvar domain40 = domain40 * (pow0 - pow3077); + tempvar domain40 = domain40 * (pow0 - pow3078); + tempvar domain40 = domain40 * (pow0 - pow3079); + tempvar domain40 = domain40 * (pow0 - pow3080); + tempvar domain40 = domain40 * (pow0 - pow3081); + tempvar domain40 = domain40 * (pow0 - pow3082); + tempvar domain40 = domain40 * (pow0 - pow3083); + tempvar domain40 = domain40 * (pow0 - pow3084); + tempvar domain40 = domain40 * (pow0 - pow3085); + tempvar domain40 = domain40 * (pow0 - pow3088); + tempvar domain40 = domain40 * (pow0 - pow3089); + tempvar domain40 = domain40 * (pow0 - pow3090); + tempvar domain40 = domain40 * (pow0 - pow3091); + tempvar domain40 = domain40 * (pow0 - pow3092); + tempvar domain40 = domain40 * (pow0 - pow3093); + tempvar domain40 = domain40 * (pow0 - pow3094); + tempvar domain40 = domain40 * (pow0 - pow3095); + tempvar domain40 = domain40 * (pow0 - pow3096); + tempvar domain40 = domain40 * (pow0 - pow3097); + tempvar domain40 = domain40 * (pow0 - pow3098); + tempvar domain40 = domain40 * (pow0 - pow3099); + tempvar domain40 = domain40 * (pow0 - pow3100); + tempvar domain40 = domain40 * (pow0 - pow3101); + tempvar domain40 = domain40 * (pow0 - pow3102); + tempvar domain40 = domain40 * (pow0 - pow3103); + tempvar domain40 = domain40 * (pow0 - pow3104); + tempvar domain40 = domain40 * (pow0 - pow3105); + tempvar domain40 = domain40 * (pow0 - pow3106); + tempvar domain40 = domain40 * (pow0 - pow3107); + tempvar domain40 = domain40 * (pow0 - pow3108); + tempvar domain40 = domain40 * (pow0 - pow3109); + tempvar domain40 = domain40 * (pow0 - pow3110); + tempvar domain40 = domain40 * (pow0 - pow3111); + tempvar domain40 = domain40 * (pow0 - pow3112); + tempvar domain40 = domain40 * (pow0 - pow3113); + tempvar domain40 = domain40 * (pow0 - pow3114); + tempvar domain40 = domain40 * (pow0 - pow3115); + tempvar domain40 = domain40 * (pow0 - pow3118); + tempvar domain40 = domain40 * (pow0 - pow3119); + tempvar domain40 = domain40 * (pow0 - pow3120); + tempvar domain40 = domain40 * (pow0 - pow3121); + tempvar domain40 = domain40 * (pow0 - pow3122); + tempvar domain40 = domain40 * (pow0 - pow3123); + tempvar domain40 = domain40 * (pow0 - pow3124); + tempvar domain40 = domain40 * (pow0 - pow3125); + tempvar domain40 = domain40 * (pow0 - pow3126); + tempvar domain40 = domain40 * (pow0 - pow3127); + tempvar domain40 = domain40 * (pow0 - pow3128); + tempvar domain40 = domain40 * (pow0 - pow3129); + tempvar domain40 = domain40 * (pow0 - pow3130); + tempvar domain40 = domain40 * (pow0 - pow3131); + tempvar domain40 = domain40 * (pow0 - pow3132); + tempvar domain40 = domain40 * (pow0 - pow3133); + tempvar domain40 = domain40 * (pow0 - pow3134); + tempvar domain40 = domain40 * (pow0 - pow3135); + tempvar domain40 = domain40 * (pow0 - pow3136); + tempvar domain40 = domain40 * (pow0 - pow3137); + tempvar domain40 = domain40 * (pow0 - pow3138); + tempvar domain40 = domain40 * (pow0 - pow3139); + tempvar domain40 = domain40 * (pow0 - pow3140); + tempvar domain40 = domain40 * (pow0 - pow3141); + tempvar domain40 = domain40 * (pow0 - pow3142); + tempvar domain40 = domain40 * (pow0 - pow3143); + tempvar domain40 = domain40 * (pow0 - pow3144); + tempvar domain40 = domain40 * (pow0 - pow3145); + tempvar domain40 = domain40 * (pow0 - pow3148); + tempvar domain40 = domain40 * (pow0 - pow3149); + tempvar domain40 = domain40 * (pow0 - pow3150); + tempvar domain40 = domain40 * (pow0 - pow3151); + tempvar domain40 = domain40 * (pow0 - pow3152); + tempvar domain40 = domain40 * (pow0 - pow3153); + tempvar domain40 = domain40 * (pow0 - pow3154); + tempvar domain40 = domain40 * (pow0 - pow3155); + tempvar domain40 = domain40 * (pow0 - pow3156); + tempvar domain40 = domain40 * (pow0 - pow3157); + tempvar domain40 = domain40 * (pow0 - pow3158); + tempvar domain40 = domain40 * (pow0 - pow3159); + tempvar domain40 = domain40 * (pow0 - pow3160); + tempvar domain40 = domain40 * (pow0 - pow3161); + tempvar domain40 = domain40 * (pow0 - pow3162); + tempvar domain40 = domain40 * (pow0 - pow3163); + tempvar domain40 = domain40 * (pow0 - pow3164); + tempvar domain40 = domain40 * (pow0 - pow3165); + tempvar domain40 = domain40 * (pow0 - pow3166); + tempvar domain40 = domain40 * (pow0 - pow3167); + tempvar domain40 = domain40 * (pow0 - pow3168); + tempvar domain40 = domain40 * (pow0 - pow3169); + tempvar domain40 = domain40 * (pow0 - pow3170); + tempvar domain40 = domain40 * (pow0 - pow3171); + tempvar domain40 = domain40 * (pow0 - pow3172); + tempvar domain40 = domain40 * (pow0 - pow3173); + tempvar domain40 = domain40 * (pow0 - pow3174); + tempvar domain40 = domain40 * (pow0 - pow3175); + tempvar domain40 = domain40 * (pow0 - pow3178); + tempvar domain40 = domain40 * (pow0 - pow3179); + tempvar domain40 = domain40 * (pow0 - pow3180); + tempvar domain40 = domain40 * (pow0 - pow3181); + tempvar domain40 = domain40 * (pow0 - pow3182); + tempvar domain40 = domain40 * (pow0 - pow3183); + tempvar domain40 = domain40 * (pow0 - pow3184); + tempvar domain40 = domain40 * (pow0 - pow3185); + tempvar domain40 = domain40 * (pow0 - pow3186); + tempvar domain40 = domain40 * (pow0 - pow3187); + tempvar domain40 = domain40 * (pow0 - pow3188); + tempvar domain40 = domain40 * (pow0 - pow3189); + tempvar domain40 = domain40 * (pow0 - pow3190); + tempvar domain40 = domain40 * (pow0 - pow3191); + tempvar domain40 = domain40 * (pow0 - pow3192); + tempvar domain40 = domain40 * (pow0 - pow3193); + tempvar domain40 = domain40 * (pow0 - pow3194); + tempvar domain40 = domain40 * (pow0 - pow3195); + tempvar domain40 = domain40 * (pow0 - pow3196); + tempvar domain40 = domain40 * (pow0 - pow3197); + tempvar domain40 = domain40 * (pow0 - pow3198); + tempvar domain40 = domain40 * (pow0 - pow3199); + tempvar domain40 = domain40 * (pow0 - pow3200); + tempvar domain40 = domain40 * (pow0 - pow3201); + tempvar domain40 = domain40 * (pow0 - pow3202); + tempvar domain40 = domain40 * (pow0 - pow3203); + tempvar domain40 = domain40 * (pow0 - pow3204); + tempvar domain40 = domain40 * (pow0 - pow3205); + tempvar domain40 = domain40 * (pow0 - pow3208); + tempvar domain40 = domain40 * (pow0 - pow3209); + tempvar domain40 = domain40 * (pow0 - pow3210); + tempvar domain40 = domain40 * (pow0 - pow3211); + tempvar domain40 = domain40 * (pow0 - pow3212); + tempvar domain40 = domain40 * (pow0 - pow3213); + tempvar domain40 = domain40 * (pow0 - pow3214); + tempvar domain40 = domain40 * (pow0 - pow3215); + tempvar domain40 = domain40 * (pow0 - pow3216); + tempvar domain40 = domain40 * (pow0 - pow3217); + tempvar domain40 = domain40 * (pow0 - pow3218); + tempvar domain40 = domain40 * (pow0 - pow3219); + tempvar domain40 = domain40 * (pow0 - pow3220); + tempvar domain40 = domain40 * (pow0 - pow3221); + tempvar domain40 = domain40 * (pow0 - pow3222); + tempvar domain40 = domain40 * (pow0 - pow3223); + tempvar domain40 = domain40 * (pow0 - pow3224); + tempvar domain40 = domain40 * (pow0 - pow3225); + tempvar domain40 = domain40 * (pow0 - pow3226); + tempvar domain40 = domain40 * (pow0 - pow3227); + tempvar domain40 = domain40 * (pow0 - pow3228); + tempvar domain40 = domain40 * (pow0 - pow3229); + tempvar domain40 = domain40 * (pow0 - pow3230); + tempvar domain40 = domain40 * (pow0 - pow3231); + tempvar domain40 = domain40 * (pow0 - pow3232); + tempvar domain40 = domain40 * (pow0 - pow3233); + tempvar domain40 = domain40 * (pow0 - pow3234); + tempvar domain40 = domain40 * (pow0 - pow3235); + tempvar domain40 = domain40 * (pow0 - pow3238); + tempvar domain40 = domain40 * (pow0 - pow3239); + tempvar domain40 = domain40 * (pow0 - pow3240); + tempvar domain40 = domain40 * (pow0 - pow3241); + tempvar domain40 = domain40 * (pow0 - pow3242); + tempvar domain40 = domain40 * (pow0 - pow3243); + tempvar domain40 = domain40 * (pow0 - pow3244); + tempvar domain40 = domain40 * (pow0 - pow3245); + tempvar domain40 = domain40 * (pow0 - pow3246); + tempvar domain40 = domain40 * (pow0 - pow3247); + tempvar domain40 = domain40 * (pow0 - pow3248); + tempvar domain40 = domain40 * (pow0 - pow3249); + tempvar domain40 = domain40 * (pow0 - pow3250); + tempvar domain40 = domain40 * (pow0 - pow3251); + tempvar domain40 = domain40 * (pow0 - pow3252); + tempvar domain40 = domain40 * (pow0 - pow3253); + tempvar domain40 = domain40 * (pow0 - pow3254); + tempvar domain40 = domain40 * (pow0 - pow3255); + tempvar domain40 = domain40 * (pow0 - pow3256); + tempvar domain40 = domain40 * (pow0 - pow3257); + tempvar domain40 = domain40 * (pow0 - pow3258); + tempvar domain40 = domain40 * (pow0 - pow3259); + tempvar domain40 = domain40 * (pow0 - pow3260); + tempvar domain40 = domain40 * (pow0 - pow3261); + tempvar domain40 = domain40 * (pow0 - pow3262); + tempvar domain40 = domain40 * (pow0 - pow3263); + tempvar domain40 = domain40 * (pow0 - pow3264); + tempvar domain40 = domain40 * (pow0 - pow3265); + tempvar domain40 = domain40 * (pow0 - pow3268); + tempvar domain40 = domain40 * (pow0 - pow3269); + tempvar domain40 = domain40 * (pow0 - pow3270); + tempvar domain40 = domain40 * (pow0 - pow3271); + tempvar domain40 = domain40 * (pow0 - pow3272); + tempvar domain40 = domain40 * (pow0 - pow3273); + tempvar domain40 = domain40 * (pow0 - pow3274); + tempvar domain40 = domain40 * (pow0 - pow3275); + tempvar domain40 = domain40 * (pow0 - pow3276); + tempvar domain40 = domain40 * (pow0 - pow3277); + tempvar domain40 = domain40 * (pow0 - pow3278); + tempvar domain40 = domain40 * (pow0 - pow3279); + tempvar domain40 = domain40 * (pow0 - pow3280); + tempvar domain40 = domain40 * (pow0 - pow3281); + tempvar domain40 = domain40 * (pow0 - pow3282); + tempvar domain40 = domain40 * (pow0 - pow3283); + tempvar domain40 = domain40 * (pow0 - pow3284); + tempvar domain40 = domain40 * (pow0 - pow3285); + tempvar domain40 = domain40 * (pow0 - pow3286); + tempvar domain40 = domain40 * (pow0 - pow3287); + tempvar domain40 = domain40 * (pow0 - pow3288); + tempvar domain40 = domain40 * (pow0 - pow3289); + tempvar domain40 = domain40 * (pow0 - pow3290); + tempvar domain40 = domain40 * (pow0 - pow3291); + tempvar domain40 = domain40 * (pow0 - pow3292); + tempvar domain40 = domain40 * (pow0 - pow3293); + tempvar domain40 = domain40 * (pow0 - pow3294); + tempvar domain40 = domain40 * (pow0 - pow3295); + tempvar domain40 = domain40 * (pow0 - pow3298); + tempvar domain40 = domain40 * (pow0 - pow3299); + tempvar domain40 = domain40 * (pow0 - pow3300); + tempvar domain40 = domain40 * (pow0 - pow3301); + tempvar domain40 = domain40 * (pow0 - pow3302); + tempvar domain40 = domain40 * (pow0 - pow3303); + tempvar domain40 = domain40 * (pow0 - pow3304); + tempvar domain40 = domain40 * (pow0 - pow3305); + tempvar domain40 = domain40 * (pow0 - pow3306); + tempvar domain40 = domain40 * (pow0 - pow3307); + tempvar domain40 = domain40 * (pow0 - pow3308); + tempvar domain40 = domain40 * (pow0 - pow3309); + tempvar domain40 = domain40 * (pow0 - pow3310); + tempvar domain40 = domain40 * (pow0 - pow3311); + tempvar domain40 = domain40 * (pow0 - pow3312); + tempvar domain40 = domain40 * (pow0 - pow3313); + tempvar domain40 = domain40 * (pow0 - pow3314); + tempvar domain40 = domain40 * (pow0 - pow3315); + tempvar domain40 = domain40 * (pow0 - pow3316); + tempvar domain40 = domain40 * (pow0 - pow3317); + tempvar domain40 = domain40 * (pow0 - pow3318); + tempvar domain40 = domain40 * (pow0 - pow3319); + tempvar domain40 = domain40 * (pow0 - pow3320); + tempvar domain40 = domain40 * (pow0 - pow3321); + tempvar domain40 = domain40 * (pow0 - pow3322); + tempvar domain40 = domain40 * (pow0 - pow3323); + tempvar domain40 = domain40 * (pow0 - pow3324); + tempvar domain40 = domain40 * (pow0 - pow3325); + tempvar domain40 = domain40 * (pow0 - pow3328); + tempvar domain40 = domain40 * (pow0 - pow3329); + tempvar domain40 = domain40 * (pow0 - pow3330); + tempvar domain40 = domain40 * (pow0 - pow3331); + tempvar domain40 = domain40 * (pow0 - pow3332); + tempvar domain40 = domain40 * (pow0 - pow3333); + tempvar domain40 = domain40 * (pow0 - pow3334); + tempvar domain40 = domain40 * (pow0 - pow3335); + tempvar domain40 = domain40 * (pow0 - pow3336); + tempvar domain40 = domain40 * (pow0 - pow3337); + tempvar domain40 = domain40 * (pow0 - pow3338); + tempvar domain40 = domain40 * (pow0 - pow3339); + tempvar domain40 = domain40 * (pow0 - pow3340); + tempvar domain40 = domain40 * (pow0 - pow3341); + tempvar domain40 = domain40 * (pow0 - pow3342); + tempvar domain40 = domain40 * (pow0 - pow3343); + tempvar domain40 = domain40 * (pow0 - pow3344); + tempvar domain40 = domain40 * (pow0 - pow3345); + tempvar domain40 = domain40 * (pow0 - pow3346); + tempvar domain40 = domain40 * (pow0 - pow3347); + tempvar domain40 = domain40 * (pow0 - pow3348); + tempvar domain40 = domain40 * (pow0 - pow3349); + tempvar domain40 = domain40 * (pow0 - pow3350); + tempvar domain40 = domain40 * (pow0 - pow3351); + tempvar domain40 = domain40 * (pow0 - pow3352); + tempvar domain40 = domain40 * (pow0 - pow3353); + tempvar domain40 = domain40 * (pow0 - pow3354); + tempvar domain40 = domain40 * (pow0 - pow3355); + tempvar domain40 = domain40 * (domain37); + tempvar domain40 = domain40 * (domain39); + tempvar domain41 = pow2 - pow2109; + tempvar domain41 = domain41 * (domain35); + tempvar domain42 = domain34; + tempvar domain42 = domain42 * (domain36); + tempvar domain43 = domain39; + tempvar domain43 = domain43 * (domain42); + tempvar domain44 = pow0 - pow781; + tempvar domain44 = domain44 * (pow0 - pow782); + tempvar domain44 = domain44 * (pow0 - pow783); + tempvar domain44 = domain44 * (pow0 - pow784); + tempvar domain44 = domain44 * (pow0 - pow785); + tempvar domain44 = domain44 * (pow0 - pow786); + tempvar domain44 = domain44 * (pow0 - pow787); + tempvar domain44 = domain44 * (pow0 - pow788); + tempvar domain45 = pow0 - pow789; + tempvar domain45 = domain45 * (pow0 - pow790); + tempvar domain45 = domain45 * (pow0 - pow791); + tempvar domain45 = domain45 * (pow0 - pow792); + tempvar domain45 = domain45 * (pow0 - pow793); + tempvar domain45 = domain45 * (pow0 - pow794); + tempvar domain45 = domain45 * (pow0 - pow795); + tempvar domain45 = domain45 * (pow0 - pow796); + tempvar domain45 = domain45 * (pow0 - pow797); + tempvar domain45 = domain45 * (pow0 - pow798); + tempvar domain45 = domain45 * (pow0 - pow799); + tempvar domain45 = domain45 * (pow0 - pow800); + tempvar domain45 = domain45 * (pow0 - pow801); + tempvar domain45 = domain45 * (pow0 - pow802); + tempvar domain45 = domain45 * (pow0 - pow803); + tempvar domain45 = domain45 * (pow0 - pow804); + tempvar domain45 = domain45 * (domain26); + tempvar domain45 = domain45 * (domain44); + tempvar domain46 = pow0 - pow2537; + tempvar domain46 = domain46 * (pow0 - pow2538); + tempvar domain46 = domain46 * (pow0 - pow2539); + tempvar domain46 = domain46 * (pow0 - pow2540); + tempvar domain46 = domain46 * (pow0 - pow2541); + tempvar domain46 = domain46 * (pow0 - pow2542); + tempvar domain46 = domain46 * (pow0 - pow2543); + tempvar domain46 = domain46 * (pow0 - pow2544); + tempvar domain47 = pow0 - pow2545; + tempvar domain47 = domain47 * (pow0 - pow2546); + tempvar domain47 = domain47 * (pow0 - pow2547); + tempvar domain47 = domain47 * (pow0 - pow2548); + tempvar domain47 = domain47 * (pow0 - pow2549); + tempvar domain47 = domain47 * (pow0 - pow2550); + tempvar domain47 = domain47 * (pow0 - pow2551); + tempvar domain47 = domain47 * (pow0 - pow2552); + tempvar domain47 = domain47 * (pow0 - pow2553); + tempvar domain47 = domain47 * (pow0 - pow2554); + tempvar domain47 = domain47 * (pow0 - pow2555); + tempvar domain47 = domain47 * (pow0 - pow2556); + tempvar domain47 = domain47 * (pow0 - pow2557); + tempvar domain47 = domain47 * (pow0 - pow2558); + tempvar domain47 = domain47 * (pow0 - pow2559); + tempvar domain47 = domain47 * (pow0 - pow2560); + tempvar domain47 = domain47 * (domain43); + tempvar domain47 = domain47 * (domain46); + tempvar domain48 = pow0 - pow2500; + tempvar domain48 = domain48 * (pow0 - pow2501); + tempvar domain48 = domain48 * (pow0 - pow2502); + tempvar domain48 = domain48 * (pow0 - pow2503); + tempvar domain48 = domain48 * (pow0 - pow2504); + tempvar domain48 = domain48 * (pow0 - pow2505); + tempvar domain48 = domain48 * (pow0 - pow2506); + tempvar domain48 = domain48 * (pow0 - pow2507); + tempvar domain49 = pow0 - pow2385; + tempvar domain49 = domain49 * (pow0 - pow2386); + tempvar domain49 = domain49 * (pow0 - pow2387); + tempvar domain49 = domain49 * (pow0 - pow2388); + tempvar domain49 = domain49 * (pow0 - pow2389); + tempvar domain49 = domain49 * (pow0 - pow2390); + tempvar domain49 = domain49 * (pow0 - pow2391); + tempvar domain49 = domain49 * (pow0 - pow2392); + tempvar domain49 = domain49 * (pow0 - pow2424); + tempvar domain49 = domain49 * (pow0 - pow2425); + tempvar domain49 = domain49 * (pow0 - pow2426); + tempvar domain49 = domain49 * (pow0 - pow2427); + tempvar domain49 = domain49 * (pow0 - pow2428); + tempvar domain49 = domain49 * (pow0 - pow2429); + tempvar domain49 = domain49 * (pow0 - pow2430); + tempvar domain49 = domain49 * (pow0 - pow2431); + tempvar domain49 = domain49 * (pow0 - pow2461); + tempvar domain49 = domain49 * (pow0 - pow2462); + tempvar domain49 = domain49 * (pow0 - pow2463); + tempvar domain49 = domain49 * (pow0 - pow2464); + tempvar domain49 = domain49 * (pow0 - pow2465); + tempvar domain49 = domain49 * (pow0 - pow2466); + tempvar domain49 = domain49 * (pow0 - pow2467); + tempvar domain49 = domain49 * (pow0 - pow2468); + tempvar domain49 = domain49 * (domain48); + tempvar domain50 = pow0 - pow2508; + tempvar domain50 = domain50 * (pow0 - pow2509); + tempvar domain50 = domain50 * (pow0 - pow2510); + tempvar domain50 = domain50 * (pow0 - pow2511); + tempvar domain50 = domain50 * (pow0 - pow2512); + tempvar domain50 = domain50 * (pow0 - pow2513); + tempvar domain50 = domain50 * (pow0 - pow2514); + tempvar domain50 = domain50 * (pow0 - pow2515); + tempvar domain50 = domain50 * (pow0 - pow2516); + tempvar domain50 = domain50 * (pow0 - pow2517); + tempvar domain50 = domain50 * (pow0 - pow2518); + tempvar domain50 = domain50 * (pow0 - pow2519); + tempvar domain50 = domain50 * (pow0 - pow2520); + tempvar domain50 = domain50 * (pow0 - pow2521); + tempvar domain50 = domain50 * (pow0 - pow2522); + tempvar domain50 = domain50 * (pow0 - pow2523); + tempvar domain50 = domain50 * (domain47); + tempvar domain51 = pow0 - pow2393; + tempvar domain51 = domain51 * (pow0 - pow2394); + tempvar domain51 = domain51 * (pow0 - pow2395); + tempvar domain51 = domain51 * (pow0 - pow2396); + tempvar domain51 = domain51 * (pow0 - pow2397); + tempvar domain51 = domain51 * (pow0 - pow2398); + tempvar domain51 = domain51 * (pow0 - pow2399); + tempvar domain51 = domain51 * (pow0 - pow2400); + tempvar domain51 = domain51 * (pow0 - pow2401); + tempvar domain51 = domain51 * (pow0 - pow2402); + tempvar domain51 = domain51 * (pow0 - pow2403); + tempvar domain51 = domain51 * (pow0 - pow2404); + tempvar domain51 = domain51 * (pow0 - pow2405); + tempvar domain51 = domain51 * (pow0 - pow2406); + tempvar domain51 = domain51 * (pow0 - pow2407); + tempvar domain51 = domain51 * (pow0 - pow2408); + tempvar domain51 = domain51 * (pow0 - pow2432); + tempvar domain51 = domain51 * (pow0 - pow2433); + tempvar domain51 = domain51 * (pow0 - pow2434); + tempvar domain51 = domain51 * (pow0 - pow2435); + tempvar domain51 = domain51 * (pow0 - pow2436); + tempvar domain51 = domain51 * (pow0 - pow2437); + tempvar domain51 = domain51 * (pow0 - pow2438); + tempvar domain51 = domain51 * (pow0 - pow2439); + tempvar domain51 = domain51 * (pow0 - pow2440); + tempvar domain51 = domain51 * (pow0 - pow2441); + tempvar domain51 = domain51 * (pow0 - pow2442); + tempvar domain51 = domain51 * (pow0 - pow2443); + tempvar domain51 = domain51 * (pow0 - pow2444); + tempvar domain51 = domain51 * (pow0 - pow2445); + tempvar domain51 = domain51 * (pow0 - pow2446); + tempvar domain51 = domain51 * (pow0 - pow2447); + tempvar domain51 = domain51 * (pow0 - pow2469); + tempvar domain51 = domain51 * (pow0 - pow2470); + tempvar domain51 = domain51 * (pow0 - pow2471); + tempvar domain51 = domain51 * (pow0 - pow2472); + tempvar domain51 = domain51 * (pow0 - pow2473); + tempvar domain51 = domain51 * (pow0 - pow2474); + tempvar domain51 = domain51 * (pow0 - pow2475); + tempvar domain51 = domain51 * (pow0 - pow2476); + tempvar domain51 = domain51 * (pow0 - pow2477); + tempvar domain51 = domain51 * (pow0 - pow2478); + tempvar domain51 = domain51 * (pow0 - pow2479); + tempvar domain51 = domain51 * (pow0 - pow2480); + tempvar domain51 = domain51 * (pow0 - pow2481); + tempvar domain51 = domain51 * (pow0 - pow2482); + tempvar domain51 = domain51 * (pow0 - pow2483); + tempvar domain51 = domain51 * (pow0 - pow2484); + tempvar domain51 = domain51 * (domain49); + tempvar domain51 = domain51 * (domain50); + tempvar domain52 = pow0 - pow2309; + tempvar domain52 = domain52 * (pow0 - pow2310); + tempvar domain52 = domain52 * (pow0 - pow2311); + tempvar domain52 = domain52 * (pow0 - pow2312); + tempvar domain52 = domain52 * (pow0 - pow2313); + tempvar domain52 = domain52 * (pow0 - pow2314); + tempvar domain52 = domain52 * (pow0 - pow2315); + tempvar domain52 = domain52 * (pow0 - pow2316); + tempvar domain52 = domain52 * (pow0 - pow2348); + tempvar domain52 = domain52 * (pow0 - pow2349); + tempvar domain52 = domain52 * (pow0 - pow2350); + tempvar domain52 = domain52 * (pow0 - pow2351); + tempvar domain52 = domain52 * (pow0 - pow2352); + tempvar domain52 = domain52 * (pow0 - pow2353); + tempvar domain52 = domain52 * (pow0 - pow2354); + tempvar domain52 = domain52 * (pow0 - pow2355); + tempvar domain53 = pow0 - pow2272; + tempvar domain53 = domain53 * (pow0 - pow2273); + tempvar domain53 = domain53 * (pow0 - pow2274); + tempvar domain53 = domain53 * (pow0 - pow2275); + tempvar domain53 = domain53 * (pow0 - pow2276); + tempvar domain53 = domain53 * (pow0 - pow2277); + tempvar domain53 = domain53 * (pow0 - pow2278); + tempvar domain53 = domain53 * (pow0 - pow2279); + tempvar domain53 = domain53 * (domain52); + tempvar domain54 = pow0 - pow2233; + tempvar domain54 = domain54 * (pow0 - pow2234); + tempvar domain54 = domain54 * (pow0 - pow2235); + tempvar domain54 = domain54 * (pow0 - pow2236); + tempvar domain54 = domain54 * (pow0 - pow2237); + tempvar domain54 = domain54 * (pow0 - pow2238); + tempvar domain54 = domain54 * (pow0 - pow2239); + tempvar domain54 = domain54 * (pow0 - pow2240); + tempvar domain54 = domain54 * (domain53); + tempvar domain55 = pow0 - pow2317; + tempvar domain55 = domain55 * (pow0 - pow2318); + tempvar domain55 = domain55 * (pow0 - pow2319); + tempvar domain55 = domain55 * (pow0 - pow2320); + tempvar domain55 = domain55 * (pow0 - pow2321); + tempvar domain55 = domain55 * (pow0 - pow2322); + tempvar domain55 = domain55 * (pow0 - pow2323); + tempvar domain55 = domain55 * (pow0 - pow2324); + tempvar domain55 = domain55 * (pow0 - pow2325); + tempvar domain55 = domain55 * (pow0 - pow2326); + tempvar domain55 = domain55 * (pow0 - pow2327); + tempvar domain55 = domain55 * (pow0 - pow2328); + tempvar domain55 = domain55 * (pow0 - pow2329); + tempvar domain55 = domain55 * (pow0 - pow2330); + tempvar domain55 = domain55 * (pow0 - pow2331); + tempvar domain55 = domain55 * (pow0 - pow2332); + tempvar domain55 = domain55 * (pow0 - pow2356); + tempvar domain55 = domain55 * (pow0 - pow2357); + tempvar domain55 = domain55 * (pow0 - pow2358); + tempvar domain55 = domain55 * (pow0 - pow2359); + tempvar domain55 = domain55 * (pow0 - pow2360); + tempvar domain55 = domain55 * (pow0 - pow2361); + tempvar domain55 = domain55 * (pow0 - pow2362); + tempvar domain55 = domain55 * (pow0 - pow2363); + tempvar domain55 = domain55 * (pow0 - pow2364); + tempvar domain55 = domain55 * (pow0 - pow2365); + tempvar domain55 = domain55 * (pow0 - pow2366); + tempvar domain55 = domain55 * (pow0 - pow2367); + tempvar domain55 = domain55 * (pow0 - pow2368); + tempvar domain55 = domain55 * (pow0 - pow2369); + tempvar domain55 = domain55 * (pow0 - pow2370); + tempvar domain55 = domain55 * (pow0 - pow2371); + tempvar domain55 = domain55 * (domain51); + tempvar domain56 = pow0 - pow2241; + tempvar domain56 = domain56 * (pow0 - pow2242); + tempvar domain56 = domain56 * (pow0 - pow2243); + tempvar domain56 = domain56 * (pow0 - pow2244); + tempvar domain56 = domain56 * (pow0 - pow2245); + tempvar domain56 = domain56 * (pow0 - pow2246); + tempvar domain56 = domain56 * (pow0 - pow2247); + tempvar domain56 = domain56 * (pow0 - pow2248); + tempvar domain56 = domain56 * (pow0 - pow2249); + tempvar domain56 = domain56 * (pow0 - pow2250); + tempvar domain56 = domain56 * (pow0 - pow2251); + tempvar domain56 = domain56 * (pow0 - pow2252); + tempvar domain56 = domain56 * (pow0 - pow2253); + tempvar domain56 = domain56 * (pow0 - pow2254); + tempvar domain56 = domain56 * (pow0 - pow2255); + tempvar domain56 = domain56 * (pow0 - pow2256); + tempvar domain56 = domain56 * (pow0 - pow2280); + tempvar domain56 = domain56 * (pow0 - pow2281); + tempvar domain56 = domain56 * (pow0 - pow2282); + tempvar domain56 = domain56 * (pow0 - pow2283); + tempvar domain56 = domain56 * (pow0 - pow2284); + tempvar domain56 = domain56 * (pow0 - pow2285); + tempvar domain56 = domain56 * (pow0 - pow2286); + tempvar domain56 = domain56 * (pow0 - pow2287); + tempvar domain56 = domain56 * (pow0 - pow2288); + tempvar domain56 = domain56 * (pow0 - pow2289); + tempvar domain56 = domain56 * (pow0 - pow2290); + tempvar domain56 = domain56 * (pow0 - pow2291); + tempvar domain56 = domain56 * (pow0 - pow2292); + tempvar domain56 = domain56 * (pow0 - pow2293); + tempvar domain56 = domain56 * (pow0 - pow2294); + tempvar domain56 = domain56 * (pow0 - pow2295); + tempvar domain56 = domain56 * (domain54); + tempvar domain56 = domain56 * (domain55); + tempvar domain57 = pow0 - pow2109; + tempvar domain57 = domain57 * (pow0 - pow2110); + tempvar domain57 = domain57 * (pow0 - pow2111); + tempvar domain57 = domain57 * (pow0 - pow2112); + tempvar domain57 = domain57 * (pow0 - pow2113); + tempvar domain57 = domain57 * (pow0 - pow2114); + tempvar domain57 = domain57 * (pow0 - pow2115); + tempvar domain57 = domain57 * (pow0 - pow2116); + tempvar domain57 = domain57 * (pow0 - pow2133); + tempvar domain57 = domain57 * (pow0 - pow2134); + tempvar domain57 = domain57 * (pow0 - pow2135); + tempvar domain57 = domain57 * (pow0 - pow2136); + tempvar domain57 = domain57 * (pow0 - pow2137); + tempvar domain57 = domain57 * (pow0 - pow2138); + tempvar domain57 = domain57 * (pow0 - pow2139); + tempvar domain57 = domain57 * (pow0 - pow2140); + tempvar domain57 = domain57 * (pow0 - pow2157); + tempvar domain57 = domain57 * (pow0 - pow2158); + tempvar domain57 = domain57 * (pow0 - pow2159); + tempvar domain57 = domain57 * (pow0 - pow2160); + tempvar domain57 = domain57 * (pow0 - pow2161); + tempvar domain57 = domain57 * (pow0 - pow2162); + tempvar domain57 = domain57 * (pow0 - pow2163); + tempvar domain57 = domain57 * (pow0 - pow2164); + tempvar domain57 = domain57 * (pow0 - pow2196); + tempvar domain57 = domain57 * (pow0 - pow2197); + tempvar domain57 = domain57 * (pow0 - pow2198); + tempvar domain57 = domain57 * (pow0 - pow2199); + tempvar domain57 = domain57 * (pow0 - pow2200); + tempvar domain57 = domain57 * (pow0 - pow2201); + tempvar domain57 = domain57 * (pow0 - pow2202); + tempvar domain57 = domain57 * (pow0 - pow2203); + tempvar domain58 = pow0 - pow2085; + tempvar domain58 = domain58 * (pow0 - pow2086); + tempvar domain58 = domain58 * (pow0 - pow2087); + tempvar domain58 = domain58 * (pow0 - pow2088); + tempvar domain58 = domain58 * (pow0 - pow2089); + tempvar domain58 = domain58 * (pow0 - pow2090); + tempvar domain58 = domain58 * (pow0 - pow2091); + tempvar domain58 = domain58 * (pow0 - pow2092); + tempvar domain58 = domain58 * (domain57); + tempvar domain59 = pow0 - pow2013; + tempvar domain59 = domain59 * (pow0 - pow2014); + tempvar domain59 = domain59 * (pow0 - pow2015); + tempvar domain59 = domain59 * (pow0 - pow2016); + tempvar domain59 = domain59 * (pow0 - pow2017); + tempvar domain59 = domain59 * (pow0 - pow2018); + tempvar domain59 = domain59 * (pow0 - pow2019); + tempvar domain59 = domain59 * (pow0 - pow2020); + tempvar domain59 = domain59 * (pow0 - pow2037); + tempvar domain59 = domain59 * (pow0 - pow2038); + tempvar domain59 = domain59 * (pow0 - pow2039); + tempvar domain59 = domain59 * (pow0 - pow2040); + tempvar domain59 = domain59 * (pow0 - pow2041); + tempvar domain59 = domain59 * (pow0 - pow2042); + tempvar domain59 = domain59 * (pow0 - pow2043); + tempvar domain59 = domain59 * (pow0 - pow2044); + tempvar domain59 = domain59 * (pow0 - pow2061); + tempvar domain59 = domain59 * (pow0 - pow2062); + tempvar domain59 = domain59 * (pow0 - pow2063); + tempvar domain59 = domain59 * (pow0 - pow2064); + tempvar domain59 = domain59 * (pow0 - pow2065); + tempvar domain59 = domain59 * (pow0 - pow2066); + tempvar domain59 = domain59 * (pow0 - pow2067); + tempvar domain59 = domain59 * (pow0 - pow2068); + tempvar domain59 = domain59 * (domain58); + tempvar domain60 = pow0 - pow1982; + tempvar domain60 = domain60 * (pow0 - pow1983); + tempvar domain60 = domain60 * (pow0 - pow1984); + tempvar domain60 = domain60 * (pow0 - pow1985); + tempvar domain60 = domain60 * (pow0 - pow1986); + tempvar domain60 = domain60 * (pow0 - pow1987); + tempvar domain60 = domain60 * (pow0 - pow1988); + tempvar domain60 = domain60 * (pow0 - pow1989); + tempvar domain60 = domain60 * (domain59); + tempvar domain61 = pow0 - pow1943; + tempvar domain61 = domain61 * (pow0 - pow1944); + tempvar domain61 = domain61 * (pow0 - pow1945); + tempvar domain61 = domain61 * (pow0 - pow1946); + tempvar domain61 = domain61 * (pow0 - pow1947); + tempvar domain61 = domain61 * (pow0 - pow1948); + tempvar domain61 = domain61 * (pow0 - pow1949); + tempvar domain61 = domain61 * (pow0 - pow1950); + tempvar domain61 = domain61 * (domain60); + tempvar domain62 = pow0 - pow2117; + tempvar domain62 = domain62 * (pow0 - pow2118); + tempvar domain62 = domain62 * (pow0 - pow2119); + tempvar domain62 = domain62 * (pow0 - pow2120); + tempvar domain62 = domain62 * (pow0 - pow2121); + tempvar domain62 = domain62 * (pow0 - pow2122); + tempvar domain62 = domain62 * (pow0 - pow2123); + tempvar domain62 = domain62 * (pow0 - pow2124); + tempvar domain62 = domain62 * (pow0 - pow2125); + tempvar domain62 = domain62 * (pow0 - pow2126); + tempvar domain62 = domain62 * (pow0 - pow2127); + tempvar domain62 = domain62 * (pow0 - pow2128); + tempvar domain62 = domain62 * (pow0 - pow2129); + tempvar domain62 = domain62 * (pow0 - pow2130); + tempvar domain62 = domain62 * (pow0 - pow2131); + tempvar domain62 = domain62 * (pow0 - pow2132); + tempvar domain62 = domain62 * (pow0 - pow2141); + tempvar domain62 = domain62 * (pow0 - pow2142); + tempvar domain62 = domain62 * (pow0 - pow2143); + tempvar domain62 = domain62 * (pow0 - pow2144); + tempvar domain62 = domain62 * (pow0 - pow2145); + tempvar domain62 = domain62 * (pow0 - pow2146); + tempvar domain62 = domain62 * (pow0 - pow2147); + tempvar domain62 = domain62 * (pow0 - pow2148); + tempvar domain62 = domain62 * (pow0 - pow2149); + tempvar domain62 = domain62 * (pow0 - pow2150); + tempvar domain62 = domain62 * (pow0 - pow2151); + tempvar domain62 = domain62 * (pow0 - pow2152); + tempvar domain62 = domain62 * (pow0 - pow2153); + tempvar domain62 = domain62 * (pow0 - pow2154); + tempvar domain62 = domain62 * (pow0 - pow2155); + tempvar domain62 = domain62 * (pow0 - pow2156); + tempvar domain62 = domain62 * (pow0 - pow2165); + tempvar domain62 = domain62 * (pow0 - pow2166); + tempvar domain62 = domain62 * (pow0 - pow2167); + tempvar domain62 = domain62 * (pow0 - pow2168); + tempvar domain62 = domain62 * (pow0 - pow2169); + tempvar domain62 = domain62 * (pow0 - pow2170); + tempvar domain62 = domain62 * (pow0 - pow2171); + tempvar domain62 = domain62 * (pow0 - pow2172); + tempvar domain62 = domain62 * (pow0 - pow2173); + tempvar domain62 = domain62 * (pow0 - pow2174); + tempvar domain62 = domain62 * (pow0 - pow2175); + tempvar domain62 = domain62 * (pow0 - pow2176); + tempvar domain62 = domain62 * (pow0 - pow2177); + tempvar domain62 = domain62 * (pow0 - pow2178); + tempvar domain62 = domain62 * (pow0 - pow2179); + tempvar domain62 = domain62 * (pow0 - pow2180); + tempvar domain62 = domain62 * (pow0 - pow2204); + tempvar domain62 = domain62 * (pow0 - pow2205); + tempvar domain62 = domain62 * (pow0 - pow2206); + tempvar domain62 = domain62 * (pow0 - pow2207); + tempvar domain62 = domain62 * (pow0 - pow2208); + tempvar domain62 = domain62 * (pow0 - pow2209); + tempvar domain62 = domain62 * (pow0 - pow2210); + tempvar domain62 = domain62 * (pow0 - pow2211); + tempvar domain62 = domain62 * (pow0 - pow2212); + tempvar domain62 = domain62 * (pow0 - pow2213); + tempvar domain62 = domain62 * (pow0 - pow2214); + tempvar domain62 = domain62 * (pow0 - pow2215); + tempvar domain62 = domain62 * (pow0 - pow2216); + tempvar domain62 = domain62 * (pow0 - pow2217); + tempvar domain62 = domain62 * (pow0 - pow2218); + tempvar domain62 = domain62 * (pow0 - pow2219); + tempvar domain62 = domain62 * (domain56); + tempvar domain63 = pow0 - pow2093; + tempvar domain63 = domain63 * (pow0 - pow2094); + tempvar domain63 = domain63 * (pow0 - pow2095); + tempvar domain63 = domain63 * (pow0 - pow2096); + tempvar domain63 = domain63 * (pow0 - pow2097); + tempvar domain63 = domain63 * (pow0 - pow2098); + tempvar domain63 = domain63 * (pow0 - pow2099); + tempvar domain63 = domain63 * (pow0 - pow2100); + tempvar domain63 = domain63 * (pow0 - pow2101); + tempvar domain63 = domain63 * (pow0 - pow2102); + tempvar domain63 = domain63 * (pow0 - pow2103); + tempvar domain63 = domain63 * (pow0 - pow2104); + tempvar domain63 = domain63 * (pow0 - pow2105); + tempvar domain63 = domain63 * (pow0 - pow2106); + tempvar domain63 = domain63 * (pow0 - pow2107); + tempvar domain63 = domain63 * (pow0 - pow2108); + tempvar domain63 = domain63 * (domain62); + tempvar domain64 = pow0 - pow2021; + tempvar domain64 = domain64 * (pow0 - pow2022); + tempvar domain64 = domain64 * (pow0 - pow2023); + tempvar domain64 = domain64 * (pow0 - pow2024); + tempvar domain64 = domain64 * (pow0 - pow2025); + tempvar domain64 = domain64 * (pow0 - pow2026); + tempvar domain64 = domain64 * (pow0 - pow2027); + tempvar domain64 = domain64 * (pow0 - pow2028); + tempvar domain64 = domain64 * (pow0 - pow2029); + tempvar domain64 = domain64 * (pow0 - pow2030); + tempvar domain64 = domain64 * (pow0 - pow2031); + tempvar domain64 = domain64 * (pow0 - pow2032); + tempvar domain64 = domain64 * (pow0 - pow2033); + tempvar domain64 = domain64 * (pow0 - pow2034); + tempvar domain64 = domain64 * (pow0 - pow2035); + tempvar domain64 = domain64 * (pow0 - pow2036); + tempvar domain64 = domain64 * (pow0 - pow2045); + tempvar domain64 = domain64 * (pow0 - pow2046); + tempvar domain64 = domain64 * (pow0 - pow2047); + tempvar domain64 = domain64 * (pow0 - pow2048); + tempvar domain64 = domain64 * (pow0 - pow2049); + tempvar domain64 = domain64 * (pow0 - pow2050); + tempvar domain64 = domain64 * (pow0 - pow2051); + tempvar domain64 = domain64 * (pow0 - pow2052); + tempvar domain64 = domain64 * (pow0 - pow2053); + tempvar domain64 = domain64 * (pow0 - pow2054); + tempvar domain64 = domain64 * (pow0 - pow2055); + tempvar domain64 = domain64 * (pow0 - pow2056); + tempvar domain64 = domain64 * (pow0 - pow2057); + tempvar domain64 = domain64 * (pow0 - pow2058); + tempvar domain64 = domain64 * (pow0 - pow2059); + tempvar domain64 = domain64 * (pow0 - pow2060); + tempvar domain64 = domain64 * (pow0 - pow2069); + tempvar domain64 = domain64 * (pow0 - pow2070); + tempvar domain64 = domain64 * (pow0 - pow2071); + tempvar domain64 = domain64 * (pow0 - pow2072); + tempvar domain64 = domain64 * (pow0 - pow2073); + tempvar domain64 = domain64 * (pow0 - pow2074); + tempvar domain64 = domain64 * (pow0 - pow2075); + tempvar domain64 = domain64 * (pow0 - pow2076); + tempvar domain64 = domain64 * (pow0 - pow2077); + tempvar domain64 = domain64 * (pow0 - pow2078); + tempvar domain64 = domain64 * (pow0 - pow2079); + tempvar domain64 = domain64 * (pow0 - pow2080); + tempvar domain64 = domain64 * (pow0 - pow2081); + tempvar domain64 = domain64 * (pow0 - pow2082); + tempvar domain64 = domain64 * (pow0 - pow2083); + tempvar domain64 = domain64 * (pow0 - pow2084); + tempvar domain64 = domain64 * (domain63); + tempvar domain65 = pow0 - pow1990; + tempvar domain65 = domain65 * (pow0 - pow1991); + tempvar domain65 = domain65 * (pow0 - pow1992); + tempvar domain65 = domain65 * (pow0 - pow1993); + tempvar domain65 = domain65 * (pow0 - pow1994); + tempvar domain65 = domain65 * (pow0 - pow1995); + tempvar domain65 = domain65 * (pow0 - pow1996); + tempvar domain65 = domain65 * (pow0 - pow1997); + tempvar domain65 = domain65 * (pow0 - pow1998); + tempvar domain65 = domain65 * (pow0 - pow1999); + tempvar domain65 = domain65 * (pow0 - pow2000); + tempvar domain65 = domain65 * (pow0 - pow2001); + tempvar domain65 = domain65 * (pow0 - pow2002); + tempvar domain65 = domain65 * (pow0 - pow2003); + tempvar domain65 = domain65 * (pow0 - pow2004); + tempvar domain65 = domain65 * (pow0 - pow2005); + tempvar domain65 = domain65 * (domain64); + tempvar domain66 = pow0 - pow1951; + tempvar domain66 = domain66 * (pow0 - pow1952); + tempvar domain66 = domain66 * (pow0 - pow1953); + tempvar domain66 = domain66 * (pow0 - pow1954); + tempvar domain66 = domain66 * (pow0 - pow1955); + tempvar domain66 = domain66 * (pow0 - pow1956); + tempvar domain66 = domain66 * (pow0 - pow1957); + tempvar domain66 = domain66 * (pow0 - pow1958); + tempvar domain66 = domain66 * (pow0 - pow1959); + tempvar domain66 = domain66 * (pow0 - pow1960); + tempvar domain66 = domain66 * (pow0 - pow1961); + tempvar domain66 = domain66 * (pow0 - pow1962); + tempvar domain66 = domain66 * (pow0 - pow1963); + tempvar domain66 = domain66 * (pow0 - pow1964); + tempvar domain66 = domain66 * (pow0 - pow1965); + tempvar domain66 = domain66 * (pow0 - pow1966); + tempvar domain66 = domain66 * (domain61); + tempvar domain66 = domain66 * (domain65); + tempvar domain67 = pow0 - pow1912; + tempvar domain67 = domain67 * (pow0 - pow1913); + tempvar domain67 = domain67 * (pow0 - pow1914); + tempvar domain67 = domain67 * (pow0 - pow1915); + tempvar domain67 = domain67 * (pow0 - pow1916); + tempvar domain67 = domain67 * (pow0 - pow1917); + tempvar domain67 = domain67 * (pow0 - pow1918); + tempvar domain67 = domain67 * (pow0 - pow1919); + tempvar domain68 = pow0 - pow1920; + tempvar domain68 = domain68 * (pow0 - pow1921); + tempvar domain68 = domain68 * (pow0 - pow1922); + tempvar domain68 = domain68 * (pow0 - pow1923); + tempvar domain68 = domain68 * (pow0 - pow1924); + tempvar domain68 = domain68 * (pow0 - pow1925); + tempvar domain68 = domain68 * (pow0 - pow1926); + tempvar domain68 = domain68 * (pow0 - pow1927); + tempvar domain68 = domain68 * (pow0 - pow1928); + tempvar domain68 = domain68 * (pow0 - pow1929); + tempvar domain68 = domain68 * (pow0 - pow1930); + tempvar domain68 = domain68 * (pow0 - pow1931); + tempvar domain68 = domain68 * (pow0 - pow1932); + tempvar domain68 = domain68 * (pow0 - pow1933); + tempvar domain68 = domain68 * (pow0 - pow1934); + tempvar domain68 = domain68 * (pow0 - pow1935); + tempvar domain68 = domain68 * (domain66); + tempvar domain68 = domain68 * (domain67); + tempvar domain69 = pow0 - pow1842; + tempvar domain69 = domain69 * (pow0 - pow1843); + tempvar domain69 = domain69 * (pow0 - pow1844); + tempvar domain69 = domain69 * (pow0 - pow1845); + tempvar domain69 = domain69 * (pow0 - pow1846); + tempvar domain69 = domain69 * (pow0 - pow1847); + tempvar domain69 = domain69 * (pow0 - pow1848); + tempvar domain69 = domain69 * (pow0 - pow1849); + tempvar domain69 = domain69 * (pow0 - pow1873); + tempvar domain69 = domain69 * (pow0 - pow1874); + tempvar domain69 = domain69 * (pow0 - pow1875); + tempvar domain69 = domain69 * (pow0 - pow1876); + tempvar domain69 = domain69 * (pow0 - pow1877); + tempvar domain69 = domain69 * (pow0 - pow1878); + tempvar domain69 = domain69 * (pow0 - pow1879); + tempvar domain69 = domain69 * (pow0 - pow1880); + tempvar domain70 = pow0 - pow1779; + tempvar domain70 = domain70 * (pow0 - pow1780); + tempvar domain70 = domain70 * (pow0 - pow1781); + tempvar domain70 = domain70 * (pow0 - pow1782); + tempvar domain70 = domain70 * (pow0 - pow1783); + tempvar domain70 = domain70 * (pow0 - pow1784); + tempvar domain70 = domain70 * (pow0 - pow1785); + tempvar domain70 = domain70 * (pow0 - pow1786); + tempvar domain70 = domain70 * (pow0 - pow1803); + tempvar domain70 = domain70 * (pow0 - pow1804); + tempvar domain70 = domain70 * (pow0 - pow1805); + tempvar domain70 = domain70 * (pow0 - pow1806); + tempvar domain70 = domain70 * (pow0 - pow1807); + tempvar domain70 = domain70 * (pow0 - pow1808); + tempvar domain70 = domain70 * (pow0 - pow1809); + tempvar domain70 = domain70 * (pow0 - pow1810); + tempvar domain70 = domain70 * (domain69); + tempvar domain71 = pow0 - pow1787; + tempvar domain71 = domain71 * (pow0 - pow1788); + tempvar domain71 = domain71 * (pow0 - pow1789); + tempvar domain71 = domain71 * (pow0 - pow1790); + tempvar domain71 = domain71 * (pow0 - pow1791); + tempvar domain71 = domain71 * (pow0 - pow1792); + tempvar domain71 = domain71 * (pow0 - pow1793); + tempvar domain71 = domain71 * (pow0 - pow1794); + tempvar domain71 = domain71 * (pow0 - pow1795); + tempvar domain71 = domain71 * (pow0 - pow1796); + tempvar domain71 = domain71 * (pow0 - pow1797); + tempvar domain71 = domain71 * (pow0 - pow1798); + tempvar domain71 = domain71 * (pow0 - pow1799); + tempvar domain71 = domain71 * (pow0 - pow1800); + tempvar domain71 = domain71 * (pow0 - pow1801); + tempvar domain71 = domain71 * (pow0 - pow1802); + tempvar domain71 = domain71 * (pow0 - pow1811); + tempvar domain71 = domain71 * (pow0 - pow1812); + tempvar domain71 = domain71 * (pow0 - pow1813); + tempvar domain71 = domain71 * (pow0 - pow1814); + tempvar domain71 = domain71 * (pow0 - pow1815); + tempvar domain71 = domain71 * (pow0 - pow1816); + tempvar domain71 = domain71 * (pow0 - pow1817); + tempvar domain71 = domain71 * (pow0 - pow1818); + tempvar domain71 = domain71 * (pow0 - pow1819); + tempvar domain71 = domain71 * (pow0 - pow1820); + tempvar domain71 = domain71 * (pow0 - pow1821); + tempvar domain71 = domain71 * (pow0 - pow1822); + tempvar domain71 = domain71 * (pow0 - pow1823); + tempvar domain71 = domain71 * (pow0 - pow1824); + tempvar domain71 = domain71 * (pow0 - pow1825); + tempvar domain71 = domain71 * (pow0 - pow1826); + tempvar domain71 = domain71 * (pow0 - pow1850); + tempvar domain71 = domain71 * (pow0 - pow1851); + tempvar domain71 = domain71 * (pow0 - pow1852); + tempvar domain71 = domain71 * (pow0 - pow1853); + tempvar domain71 = domain71 * (pow0 - pow1854); + tempvar domain71 = domain71 * (pow0 - pow1855); + tempvar domain71 = domain71 * (pow0 - pow1856); + tempvar domain71 = domain71 * (pow0 - pow1857); + tempvar domain71 = domain71 * (pow0 - pow1858); + tempvar domain71 = domain71 * (pow0 - pow1859); + tempvar domain71 = domain71 * (pow0 - pow1860); + tempvar domain71 = domain71 * (pow0 - pow1861); + tempvar domain71 = domain71 * (pow0 - pow1862); + tempvar domain71 = domain71 * (pow0 - pow1863); + tempvar domain71 = domain71 * (pow0 - pow1864); + tempvar domain71 = domain71 * (pow0 - pow1865); + tempvar domain71 = domain71 * (pow0 - pow1881); + tempvar domain71 = domain71 * (pow0 - pow1882); + tempvar domain71 = domain71 * (pow0 - pow1883); + tempvar domain71 = domain71 * (pow0 - pow1884); + tempvar domain71 = domain71 * (pow0 - pow1885); + tempvar domain71 = domain71 * (pow0 - pow1886); + tempvar domain71 = domain71 * (pow0 - pow1887); + tempvar domain71 = domain71 * (pow0 - pow1888); + tempvar domain71 = domain71 * (pow0 - pow1889); + tempvar domain71 = domain71 * (pow0 - pow1890); + tempvar domain71 = domain71 * (pow0 - pow1891); + tempvar domain71 = domain71 * (pow0 - pow1892); + tempvar domain71 = domain71 * (pow0 - pow1893); + tempvar domain71 = domain71 * (pow0 - pow1894); + tempvar domain71 = domain71 * (pow0 - pow1895); + tempvar domain71 = domain71 * (pow0 - pow1896); + tempvar domain71 = domain71 * (domain68); + tempvar domain71 = domain71 * (domain70); + tempvar domain72 = pow0 - pow1731; + tempvar domain72 = domain72 * (pow0 - pow1732); + tempvar domain72 = domain72 * (pow0 - pow1733); + tempvar domain72 = domain72 * (pow0 - pow1734); + tempvar domain72 = domain72 * (pow0 - pow1735); + tempvar domain72 = domain72 * (pow0 - pow1736); + tempvar domain72 = domain72 * (pow0 - pow1737); + tempvar domain72 = domain72 * (pow0 - pow1738); + tempvar domain72 = domain72 * (pow0 - pow1739); + tempvar domain72 = domain72 * (pow0 - pow1740); + tempvar domain72 = domain72 * (pow0 - pow1741); + tempvar domain72 = domain72 * (pow0 - pow1742); + tempvar domain72 = domain72 * (pow0 - pow1743); + tempvar domain72 = domain72 * (pow0 - pow1744); + tempvar domain72 = domain72 * (pow0 - pow1745); + tempvar domain72 = domain72 * (pow0 - pow1746); + tempvar domain72 = domain72 * (pow0 - pow1747); + tempvar domain72 = domain72 * (pow0 - pow1748); + tempvar domain72 = domain72 * (pow0 - pow1749); + tempvar domain72 = domain72 * (pow0 - pow1750); + tempvar domain72 = domain72 * (pow0 - pow1751); + tempvar domain72 = domain72 * (pow0 - pow1752); + tempvar domain72 = domain72 * (pow0 - pow1753); + tempvar domain72 = domain72 * (pow0 - pow1754); + tempvar domain72 = domain72 * (pow0 - pow1755); + tempvar domain72 = domain72 * (pow0 - pow1756); + tempvar domain72 = domain72 * (pow0 - pow1757); + tempvar domain72 = domain72 * (pow0 - pow1758); + tempvar domain72 = domain72 * (pow0 - pow1759); + tempvar domain72 = domain72 * (pow0 - pow1760); + tempvar domain72 = domain72 * (pow0 - pow1761); + tempvar domain72 = domain72 * (pow0 - pow1762); + tempvar domain72 = domain72 * (pow0 - pow1763); + tempvar domain72 = domain72 * (pow0 - pow1764); + tempvar domain72 = domain72 * (pow0 - pow1765); + tempvar domain72 = domain72 * (pow0 - pow1766); + tempvar domain72 = domain72 * (pow0 - pow1767); + tempvar domain72 = domain72 * (pow0 - pow1768); + tempvar domain72 = domain72 * (pow0 - pow1769); + tempvar domain72 = domain72 * (pow0 - pow1770); + tempvar domain72 = domain72 * (pow0 - pow1771); + tempvar domain72 = domain72 * (pow0 - pow1772); + tempvar domain72 = domain72 * (pow0 - pow1773); + tempvar domain72 = domain72 * (pow0 - pow1774); + tempvar domain72 = domain72 * (pow0 - pow1775); + tempvar domain72 = domain72 * (pow0 - pow1776); + tempvar domain72 = domain72 * (pow0 - pow1777); + tempvar domain72 = domain72 * (pow0 - pow1778); + tempvar domain72 = domain72 * (domain71); + tempvar domain73 = pow0 - pow1707; + tempvar domain73 = domain73 * (pow0 - pow1708); + tempvar domain73 = domain73 * (pow0 - pow1709); + tempvar domain73 = domain73 * (pow0 - pow1710); + tempvar domain73 = domain73 * (pow0 - pow1711); + tempvar domain73 = domain73 * (pow0 - pow1712); + tempvar domain73 = domain73 * (pow0 - pow1713); + tempvar domain73 = domain73 * (pow0 - pow1714); + tempvar domain73 = domain73 * (pow0 - pow1715); + tempvar domain73 = domain73 * (pow0 - pow1716); + tempvar domain73 = domain73 * (pow0 - pow1717); + tempvar domain73 = domain73 * (pow0 - pow1718); + tempvar domain73 = domain73 * (pow0 - pow1719); + tempvar domain73 = domain73 * (pow0 - pow1720); + tempvar domain73 = domain73 * (pow0 - pow1721); + tempvar domain73 = domain73 * (pow0 - pow1722); + tempvar domain73 = domain73 * (pow0 - pow1723); + tempvar domain73 = domain73 * (pow0 - pow1724); + tempvar domain73 = domain73 * (pow0 - pow1725); + tempvar domain73 = domain73 * (pow0 - pow1726); + tempvar domain73 = domain73 * (pow0 - pow1727); + tempvar domain73 = domain73 * (pow0 - pow1728); + tempvar domain73 = domain73 * (pow0 - pow1729); + tempvar domain73 = domain73 * (pow0 - pow1730); + tempvar domain73 = domain73 * (domain72); + tempvar domain74 = pow0 - pow812; + tempvar domain74 = domain74 * (pow0 - pow813); + tempvar domain74 = domain74 * (pow0 - pow814); + tempvar domain74 = domain74 * (pow0 - pow815); + tempvar domain74 = domain74 * (pow0 - pow816); + tempvar domain74 = domain74 * (pow0 - pow817); + tempvar domain74 = domain74 * (pow0 - pow818); + tempvar domain74 = domain74 * (pow0 - pow819); + tempvar domain75 = pow0 - pow851; + tempvar domain75 = domain75 * (pow0 - pow852); + tempvar domain75 = domain75 * (pow0 - pow853); + tempvar domain75 = domain75 * (pow0 - pow854); + tempvar domain75 = domain75 * (pow0 - pow855); + tempvar domain75 = domain75 * (pow0 - pow856); + tempvar domain75 = domain75 * (pow0 - pow857); + tempvar domain75 = domain75 * (pow0 - pow858); + tempvar domain76 = pow0 - pow882; + tempvar domain76 = domain76 * (pow0 - pow883); + tempvar domain76 = domain76 * (pow0 - pow884); + tempvar domain76 = domain76 * (pow0 - pow885); + tempvar domain76 = domain76 * (pow0 - pow886); + tempvar domain76 = domain76 * (pow0 - pow887); + tempvar domain76 = domain76 * (pow0 - pow888); + tempvar domain76 = domain76 * (pow0 - pow889); + tempvar domain76 = domain76 * (pow0 - pow921); + tempvar domain76 = domain76 * (pow0 - pow922); + tempvar domain76 = domain76 * (pow0 - pow923); + tempvar domain76 = domain76 * (pow0 - pow924); + tempvar domain76 = domain76 * (pow0 - pow925); + tempvar domain76 = domain76 * (pow0 - pow926); + tempvar domain76 = domain76 * (pow0 - pow927); + tempvar domain76 = domain76 * (pow0 - pow928); + tempvar domain76 = domain76 * (domain74); + tempvar domain76 = domain76 * (domain75); + tempvar domain77 = pow0 - pow820; + tempvar domain77 = domain77 * (pow0 - pow821); + tempvar domain77 = domain77 * (pow0 - pow822); + tempvar domain77 = domain77 * (pow0 - pow823); + tempvar domain77 = domain77 * (pow0 - pow824); + tempvar domain77 = domain77 * (pow0 - pow825); + tempvar domain77 = domain77 * (pow0 - pow826); + tempvar domain77 = domain77 * (pow0 - pow827); + tempvar domain77 = domain77 * (pow0 - pow828); + tempvar domain77 = domain77 * (pow0 - pow829); + tempvar domain77 = domain77 * (pow0 - pow830); + tempvar domain77 = domain77 * (pow0 - pow831); + tempvar domain77 = domain77 * (pow0 - pow832); + tempvar domain77 = domain77 * (pow0 - pow833); + tempvar domain77 = domain77 * (pow0 - pow834); + tempvar domain77 = domain77 * (pow0 - pow835); + tempvar domain77 = domain77 * (domain45); + tempvar domain78 = pow0 - pow859; + tempvar domain78 = domain78 * (pow0 - pow860); + tempvar domain78 = domain78 * (pow0 - pow861); + tempvar domain78 = domain78 * (pow0 - pow862); + tempvar domain78 = domain78 * (pow0 - pow863); + tempvar domain78 = domain78 * (pow0 - pow864); + tempvar domain78 = domain78 * (pow0 - pow865); + tempvar domain78 = domain78 * (pow0 - pow866); + tempvar domain78 = domain78 * (pow0 - pow867); + tempvar domain78 = domain78 * (pow0 - pow868); + tempvar domain78 = domain78 * (pow0 - pow869); + tempvar domain78 = domain78 * (pow0 - pow870); + tempvar domain78 = domain78 * (pow0 - pow871); + tempvar domain78 = domain78 * (pow0 - pow872); + tempvar domain78 = domain78 * (pow0 - pow873); + tempvar domain78 = domain78 * (pow0 - pow874); + tempvar domain79 = pow0 - pow890; + tempvar domain79 = domain79 * (pow0 - pow891); + tempvar domain79 = domain79 * (pow0 - pow892); + tempvar domain79 = domain79 * (pow0 - pow893); + tempvar domain79 = domain79 * (pow0 - pow894); + tempvar domain79 = domain79 * (pow0 - pow895); + tempvar domain79 = domain79 * (pow0 - pow896); + tempvar domain79 = domain79 * (pow0 - pow897); + tempvar domain79 = domain79 * (pow0 - pow898); + tempvar domain79 = domain79 * (pow0 - pow899); + tempvar domain79 = domain79 * (pow0 - pow900); + tempvar domain79 = domain79 * (pow0 - pow901); + tempvar domain79 = domain79 * (pow0 - pow902); + tempvar domain79 = domain79 * (pow0 - pow903); + tempvar domain79 = domain79 * (pow0 - pow904); + tempvar domain79 = domain79 * (pow0 - pow905); + tempvar domain79 = domain79 * (pow0 - pow929); + tempvar domain79 = domain79 * (pow0 - pow930); + tempvar domain79 = domain79 * (pow0 - pow931); + tempvar domain79 = domain79 * (pow0 - pow932); + tempvar domain79 = domain79 * (pow0 - pow933); + tempvar domain79 = domain79 * (pow0 - pow934); + tempvar domain79 = domain79 * (pow0 - pow935); + tempvar domain79 = domain79 * (pow0 - pow936); + tempvar domain79 = domain79 * (pow0 - pow937); + tempvar domain79 = domain79 * (pow0 - pow938); + tempvar domain79 = domain79 * (pow0 - pow939); + tempvar domain79 = domain79 * (pow0 - pow940); + tempvar domain79 = domain79 * (pow0 - pow941); + tempvar domain79 = domain79 * (pow0 - pow942); + tempvar domain79 = domain79 * (pow0 - pow943); + tempvar domain79 = domain79 * (pow0 - pow944); + tempvar domain79 = domain79 * (domain76); + tempvar domain79 = domain79 * (domain77); + tempvar domain79 = domain79 * (domain78); + tempvar domain80 = pow0 - pow976; + tempvar domain80 = domain80 * (pow0 - pow977); + tempvar domain80 = domain80 * (pow0 - pow978); + tempvar domain80 = domain80 * (pow0 - pow979); + tempvar domain80 = domain80 * (pow0 - pow980); + tempvar domain80 = domain80 * (pow0 - pow981); + tempvar domain80 = domain80 * (pow0 - pow982); + tempvar domain80 = domain80 * (pow0 - pow983); + tempvar domain81 = pow0 - pow952; + tempvar domain81 = domain81 * (pow0 - pow953); + tempvar domain81 = domain81 * (pow0 - pow954); + tempvar domain81 = domain81 * (pow0 - pow955); + tempvar domain81 = domain81 * (pow0 - pow956); + tempvar domain81 = domain81 * (pow0 - pow957); + tempvar domain81 = domain81 * (pow0 - pow958); + tempvar domain81 = domain81 * (pow0 - pow959); + tempvar domain81 = domain81 * (domain80); + tempvar domain82 = pow0 - pow1000; + tempvar domain82 = domain82 * (pow0 - pow1001); + tempvar domain82 = domain82 * (pow0 - pow1002); + tempvar domain82 = domain82 * (pow0 - pow1003); + tempvar domain82 = domain82 * (pow0 - pow1004); + tempvar domain82 = domain82 * (pow0 - pow1005); + tempvar domain82 = domain82 * (pow0 - pow1006); + tempvar domain82 = domain82 * (pow0 - pow1007); + tempvar domain82 = domain82 * (domain81); + tempvar domain83 = pow0 - pow1024; + tempvar domain83 = domain83 * (pow0 - pow1025); + tempvar domain83 = domain83 * (pow0 - pow1026); + tempvar domain83 = domain83 * (pow0 - pow1027); + tempvar domain83 = domain83 * (pow0 - pow1028); + tempvar domain83 = domain83 * (pow0 - pow1029); + tempvar domain83 = domain83 * (pow0 - pow1030); + tempvar domain83 = domain83 * (pow0 - pow1031); + tempvar domain83 = domain83 * (domain82); + tempvar domain84 = pow0 - pow984; + tempvar domain84 = domain84 * (pow0 - pow985); + tempvar domain84 = domain84 * (pow0 - pow986); + tempvar domain84 = domain84 * (pow0 - pow987); + tempvar domain84 = domain84 * (pow0 - pow988); + tempvar domain84 = domain84 * (pow0 - pow989); + tempvar domain84 = domain84 * (pow0 - pow990); + tempvar domain84 = domain84 * (pow0 - pow991); + tempvar domain84 = domain84 * (pow0 - pow992); + tempvar domain84 = domain84 * (pow0 - pow993); + tempvar domain84 = domain84 * (pow0 - pow994); + tempvar domain84 = domain84 * (pow0 - pow995); + tempvar domain84 = domain84 * (pow0 - pow996); + tempvar domain84 = domain84 * (pow0 - pow997); + tempvar domain84 = domain84 * (pow0 - pow998); + tempvar domain84 = domain84 * (pow0 - pow999); + tempvar domain85 = pow0 - pow960; + tempvar domain85 = domain85 * (pow0 - pow961); + tempvar domain85 = domain85 * (pow0 - pow962); + tempvar domain85 = domain85 * (pow0 - pow963); + tempvar domain85 = domain85 * (pow0 - pow964); + tempvar domain85 = domain85 * (pow0 - pow965); + tempvar domain85 = domain85 * (pow0 - pow966); + tempvar domain85 = domain85 * (pow0 - pow967); + tempvar domain85 = domain85 * (pow0 - pow968); + tempvar domain85 = domain85 * (pow0 - pow969); + tempvar domain85 = domain85 * (pow0 - pow970); + tempvar domain85 = domain85 * (pow0 - pow971); + tempvar domain85 = domain85 * (pow0 - pow972); + tempvar domain85 = domain85 * (pow0 - pow973); + tempvar domain85 = domain85 * (pow0 - pow974); + tempvar domain85 = domain85 * (pow0 - pow975); + tempvar domain85 = domain85 * (domain79); + tempvar domain85 = domain85 * (domain84); + tempvar domain86 = pow0 - pow1008; + tempvar domain86 = domain86 * (pow0 - pow1009); + tempvar domain86 = domain86 * (pow0 - pow1010); + tempvar domain86 = domain86 * (pow0 - pow1011); + tempvar domain86 = domain86 * (pow0 - pow1012); + tempvar domain86 = domain86 * (pow0 - pow1013); + tempvar domain86 = domain86 * (pow0 - pow1014); + tempvar domain86 = domain86 * (pow0 - pow1015); + tempvar domain86 = domain86 * (pow0 - pow1016); + tempvar domain86 = domain86 * (pow0 - pow1017); + tempvar domain86 = domain86 * (pow0 - pow1018); + tempvar domain86 = domain86 * (pow0 - pow1019); + tempvar domain86 = domain86 * (pow0 - pow1020); + tempvar domain86 = domain86 * (pow0 - pow1021); + tempvar domain86 = domain86 * (pow0 - pow1022); + tempvar domain86 = domain86 * (pow0 - pow1023); + tempvar domain86 = domain86 * (pow0 - pow1032); + tempvar domain86 = domain86 * (pow0 - pow1033); + tempvar domain86 = domain86 * (pow0 - pow1034); + tempvar domain86 = domain86 * (pow0 - pow1035); + tempvar domain86 = domain86 * (pow0 - pow1036); + tempvar domain86 = domain86 * (pow0 - pow1037); + tempvar domain86 = domain86 * (pow0 - pow1038); + tempvar domain86 = domain86 * (pow0 - pow1039); + tempvar domain86 = domain86 * (pow0 - pow1040); + tempvar domain86 = domain86 * (pow0 - pow1041); + tempvar domain86 = domain86 * (pow0 - pow1042); + tempvar domain86 = domain86 * (pow0 - pow1043); + tempvar domain86 = domain86 * (pow0 - pow1044); + tempvar domain86 = domain86 * (pow0 - pow1045); + tempvar domain86 = domain86 * (pow0 - pow1046); + tempvar domain86 = domain86 * (pow0 - pow1047); + tempvar domain86 = domain86 * (domain83); + tempvar domain86 = domain86 * (domain85); + tempvar domain87 = pow0 - pow1048; + tempvar domain87 = domain87 * (pow0 - pow1049); + tempvar domain87 = domain87 * (pow0 - pow1050); + tempvar domain87 = domain87 * (pow0 - pow1051); + tempvar domain87 = domain87 * (pow0 - pow1052); + tempvar domain87 = domain87 * (pow0 - pow1053); + tempvar domain87 = domain87 * (pow0 - pow1054); + tempvar domain87 = domain87 * (pow0 - pow1055); + tempvar domain87 = domain87 * (pow0 - pow1087); + tempvar domain87 = domain87 * (pow0 - pow1088); + tempvar domain87 = domain87 * (pow0 - pow1089); + tempvar domain87 = domain87 * (pow0 - pow1090); + tempvar domain87 = domain87 * (pow0 - pow1091); + tempvar domain87 = domain87 * (pow0 - pow1092); + tempvar domain87 = domain87 * (pow0 - pow1093); + tempvar domain87 = domain87 * (pow0 - pow1094); + tempvar domain87 = domain87 * (pow0 - pow1118); + tempvar domain87 = domain87 * (pow0 - pow1119); + tempvar domain87 = domain87 * (pow0 - pow1120); + tempvar domain87 = domain87 * (pow0 - pow1121); + tempvar domain87 = domain87 * (pow0 - pow1122); + tempvar domain87 = domain87 * (pow0 - pow1123); + tempvar domain87 = domain87 * (pow0 - pow1124); + tempvar domain87 = domain87 * (pow0 - pow1125); + tempvar domain87 = domain87 * (pow0 - pow1157); + tempvar domain87 = domain87 * (pow0 - pow1158); + tempvar domain87 = domain87 * (pow0 - pow1159); + tempvar domain87 = domain87 * (pow0 - pow1160); + tempvar domain87 = domain87 * (pow0 - pow1161); + tempvar domain87 = domain87 * (pow0 - pow1162); + tempvar domain87 = domain87 * (pow0 - pow1163); + tempvar domain87 = domain87 * (pow0 - pow1164); + tempvar domain88 = pow0 - pow1188; + tempvar domain88 = domain88 * (pow0 - pow1189); + tempvar domain88 = domain88 * (pow0 - pow1190); + tempvar domain88 = domain88 * (pow0 - pow1191); + tempvar domain88 = domain88 * (pow0 - pow1192); + tempvar domain88 = domain88 * (pow0 - pow1193); + tempvar domain88 = domain88 * (pow0 - pow1194); + tempvar domain88 = domain88 * (pow0 - pow1195); + tempvar domain88 = domain88 * (domain87); + tempvar domain89 = pow0 - pow1227; + tempvar domain89 = domain89 * (pow0 - pow1228); + tempvar domain89 = domain89 * (pow0 - pow1229); + tempvar domain89 = domain89 * (pow0 - pow1230); + tempvar domain89 = domain89 * (pow0 - pow1231); + tempvar domain89 = domain89 * (pow0 - pow1232); + tempvar domain89 = domain89 * (pow0 - pow1233); + tempvar domain89 = domain89 * (pow0 - pow1234); + tempvar domain90 = pow0 - pow1258; + tempvar domain90 = domain90 * (pow0 - pow1259); + tempvar domain90 = domain90 * (pow0 - pow1260); + tempvar domain90 = domain90 * (pow0 - pow1261); + tempvar domain90 = domain90 * (pow0 - pow1262); + tempvar domain90 = domain90 * (pow0 - pow1263); + tempvar domain90 = domain90 * (pow0 - pow1264); + tempvar domain90 = domain90 * (pow0 - pow1265); + tempvar domain90 = domain90 * (pow0 - pow1282); + tempvar domain90 = domain90 * (pow0 - pow1283); + tempvar domain90 = domain90 * (pow0 - pow1284); + tempvar domain90 = domain90 * (pow0 - pow1285); + tempvar domain90 = domain90 * (pow0 - pow1286); + tempvar domain90 = domain90 * (pow0 - pow1287); + tempvar domain90 = domain90 * (pow0 - pow1288); + tempvar domain90 = domain90 * (pow0 - pow1289); + tempvar domain90 = domain90 * (domain88); + tempvar domain90 = domain90 * (domain89); + tempvar domain91 = pow0 - pow1306; + tempvar domain91 = domain91 * (pow0 - pow1307); + tempvar domain91 = domain91 * (pow0 - pow1308); + tempvar domain91 = domain91 * (pow0 - pow1309); + tempvar domain91 = domain91 * (pow0 - pow1310); + tempvar domain91 = domain91 * (pow0 - pow1311); + tempvar domain91 = domain91 * (pow0 - pow1312); + tempvar domain91 = domain91 * (pow0 - pow1313); + tempvar domain91 = domain91 * (domain90); + tempvar domain92 = pow0 - pow1330; + tempvar domain92 = domain92 * (pow0 - pow1331); + tempvar domain92 = domain92 * (pow0 - pow1332); + tempvar domain92 = domain92 * (pow0 - pow1333); + tempvar domain92 = domain92 * (pow0 - pow1334); + tempvar domain92 = domain92 * (pow0 - pow1335); + tempvar domain92 = domain92 * (pow0 - pow1336); + tempvar domain92 = domain92 * (pow0 - pow1337); + tempvar domain92 = domain92 * (domain91); + tempvar domain93 = pow0 - pow1056; + tempvar domain93 = domain93 * (pow0 - pow1057); + tempvar domain93 = domain93 * (pow0 - pow1058); + tempvar domain93 = domain93 * (pow0 - pow1059); + tempvar domain93 = domain93 * (pow0 - pow1060); + tempvar domain93 = domain93 * (pow0 - pow1061); + tempvar domain93 = domain93 * (pow0 - pow1062); + tempvar domain93 = domain93 * (pow0 - pow1063); + tempvar domain93 = domain93 * (pow0 - pow1064); + tempvar domain93 = domain93 * (pow0 - pow1065); + tempvar domain93 = domain93 * (pow0 - pow1066); + tempvar domain93 = domain93 * (pow0 - pow1067); + tempvar domain93 = domain93 * (pow0 - pow1068); + tempvar domain93 = domain93 * (pow0 - pow1069); + tempvar domain93 = domain93 * (pow0 - pow1070); + tempvar domain93 = domain93 * (pow0 - pow1071); + tempvar domain93 = domain93 * (pow0 - pow1095); + tempvar domain93 = domain93 * (pow0 - pow1096); + tempvar domain93 = domain93 * (pow0 - pow1097); + tempvar domain93 = domain93 * (pow0 - pow1098); + tempvar domain93 = domain93 * (pow0 - pow1099); + tempvar domain93 = domain93 * (pow0 - pow1100); + tempvar domain93 = domain93 * (pow0 - pow1101); + tempvar domain93 = domain93 * (pow0 - pow1102); + tempvar domain93 = domain93 * (pow0 - pow1103); + tempvar domain93 = domain93 * (pow0 - pow1104); + tempvar domain93 = domain93 * (pow0 - pow1105); + tempvar domain93 = domain93 * (pow0 - pow1106); + tempvar domain93 = domain93 * (pow0 - pow1107); + tempvar domain93 = domain93 * (pow0 - pow1108); + tempvar domain93 = domain93 * (pow0 - pow1109); + tempvar domain93 = domain93 * (pow0 - pow1110); + tempvar domain93 = domain93 * (pow0 - pow1126); + tempvar domain93 = domain93 * (pow0 - pow1127); + tempvar domain93 = domain93 * (pow0 - pow1128); + tempvar domain93 = domain93 * (pow0 - pow1129); + tempvar domain93 = domain93 * (pow0 - pow1130); + tempvar domain93 = domain93 * (pow0 - pow1131); + tempvar domain93 = domain93 * (pow0 - pow1132); + tempvar domain93 = domain93 * (pow0 - pow1133); + tempvar domain93 = domain93 * (pow0 - pow1134); + tempvar domain93 = domain93 * (pow0 - pow1135); + tempvar domain93 = domain93 * (pow0 - pow1136); + tempvar domain93 = domain93 * (pow0 - pow1137); + tempvar domain93 = domain93 * (pow0 - pow1138); + tempvar domain93 = domain93 * (pow0 - pow1139); + tempvar domain93 = domain93 * (pow0 - pow1140); + tempvar domain93 = domain93 * (pow0 - pow1141); + tempvar domain93 = domain93 * (pow0 - pow1165); + tempvar domain93 = domain93 * (pow0 - pow1166); + tempvar domain93 = domain93 * (pow0 - pow1167); + tempvar domain93 = domain93 * (pow0 - pow1168); + tempvar domain93 = domain93 * (pow0 - pow1169); + tempvar domain93 = domain93 * (pow0 - pow1170); + tempvar domain93 = domain93 * (pow0 - pow1171); + tempvar domain93 = domain93 * (pow0 - pow1172); + tempvar domain93 = domain93 * (pow0 - pow1173); + tempvar domain93 = domain93 * (pow0 - pow1174); + tempvar domain93 = domain93 * (pow0 - pow1175); + tempvar domain93 = domain93 * (pow0 - pow1176); + tempvar domain93 = domain93 * (pow0 - pow1177); + tempvar domain93 = domain93 * (pow0 - pow1178); + tempvar domain93 = domain93 * (pow0 - pow1179); + tempvar domain93 = domain93 * (pow0 - pow1180); + tempvar domain93 = domain93 * (domain86); + tempvar domain94 = pow0 - pow1196; + tempvar domain94 = domain94 * (pow0 - pow1197); + tempvar domain94 = domain94 * (pow0 - pow1198); + tempvar domain94 = domain94 * (pow0 - pow1199); + tempvar domain94 = domain94 * (pow0 - pow1200); + tempvar domain94 = domain94 * (pow0 - pow1201); + tempvar domain94 = domain94 * (pow0 - pow1202); + tempvar domain94 = domain94 * (pow0 - pow1203); + tempvar domain94 = domain94 * (pow0 - pow1204); + tempvar domain94 = domain94 * (pow0 - pow1205); + tempvar domain94 = domain94 * (pow0 - pow1206); + tempvar domain94 = domain94 * (pow0 - pow1207); + tempvar domain94 = domain94 * (pow0 - pow1208); + tempvar domain94 = domain94 * (pow0 - pow1209); + tempvar domain94 = domain94 * (pow0 - pow1210); + tempvar domain94 = domain94 * (pow0 - pow1211); + tempvar domain94 = domain94 * (domain93); + tempvar domain95 = pow0 - pow1235; + tempvar domain95 = domain95 * (pow0 - pow1236); + tempvar domain95 = domain95 * (pow0 - pow1237); + tempvar domain95 = domain95 * (pow0 - pow1238); + tempvar domain95 = domain95 * (pow0 - pow1239); + tempvar domain95 = domain95 * (pow0 - pow1240); + tempvar domain95 = domain95 * (pow0 - pow1241); + tempvar domain95 = domain95 * (pow0 - pow1242); + tempvar domain95 = domain95 * (pow0 - pow1243); + tempvar domain95 = domain95 * (pow0 - pow1244); + tempvar domain95 = domain95 * (pow0 - pow1245); + tempvar domain95 = domain95 * (pow0 - pow1246); + tempvar domain95 = domain95 * (pow0 - pow1247); + tempvar domain95 = domain95 * (pow0 - pow1248); + tempvar domain95 = domain95 * (pow0 - pow1249); + tempvar domain95 = domain95 * (pow0 - pow1250); + tempvar domain96 = pow0 - pow1266; + tempvar domain96 = domain96 * (pow0 - pow1267); + tempvar domain96 = domain96 * (pow0 - pow1268); + tempvar domain96 = domain96 * (pow0 - pow1269); + tempvar domain96 = domain96 * (pow0 - pow1270); + tempvar domain96 = domain96 * (pow0 - pow1271); + tempvar domain96 = domain96 * (pow0 - pow1272); + tempvar domain96 = domain96 * (pow0 - pow1273); + tempvar domain96 = domain96 * (pow0 - pow1274); + tempvar domain96 = domain96 * (pow0 - pow1275); + tempvar domain96 = domain96 * (pow0 - pow1276); + tempvar domain96 = domain96 * (pow0 - pow1277); + tempvar domain96 = domain96 * (pow0 - pow1278); + tempvar domain96 = domain96 * (pow0 - pow1279); + tempvar domain96 = domain96 * (pow0 - pow1280); + tempvar domain96 = domain96 * (pow0 - pow1281); + tempvar domain96 = domain96 * (pow0 - pow1290); + tempvar domain96 = domain96 * (pow0 - pow1291); + tempvar domain96 = domain96 * (pow0 - pow1292); + tempvar domain96 = domain96 * (pow0 - pow1293); + tempvar domain96 = domain96 * (pow0 - pow1294); + tempvar domain96 = domain96 * (pow0 - pow1295); + tempvar domain96 = domain96 * (pow0 - pow1296); + tempvar domain96 = domain96 * (pow0 - pow1297); + tempvar domain96 = domain96 * (pow0 - pow1298); + tempvar domain96 = domain96 * (pow0 - pow1299); + tempvar domain96 = domain96 * (pow0 - pow1300); + tempvar domain96 = domain96 * (pow0 - pow1301); + tempvar domain96 = domain96 * (pow0 - pow1302); + tempvar domain96 = domain96 * (pow0 - pow1303); + tempvar domain96 = domain96 * (pow0 - pow1304); + tempvar domain96 = domain96 * (pow0 - pow1305); + tempvar domain96 = domain96 * (domain94); + tempvar domain96 = domain96 * (domain95); + tempvar domain97 = pow0 - pow1314; + tempvar domain97 = domain97 * (pow0 - pow1315); + tempvar domain97 = domain97 * (pow0 - pow1316); + tempvar domain97 = domain97 * (pow0 - pow1317); + tempvar domain97 = domain97 * (pow0 - pow1318); + tempvar domain97 = domain97 * (pow0 - pow1319); + tempvar domain97 = domain97 * (pow0 - pow1320); + tempvar domain97 = domain97 * (pow0 - pow1321); + tempvar domain97 = domain97 * (pow0 - pow1322); + tempvar domain97 = domain97 * (pow0 - pow1323); + tempvar domain97 = domain97 * (pow0 - pow1324); + tempvar domain97 = domain97 * (pow0 - pow1325); + tempvar domain97 = domain97 * (pow0 - pow1326); + tempvar domain97 = domain97 * (pow0 - pow1327); + tempvar domain97 = domain97 * (pow0 - pow1328); + tempvar domain97 = domain97 * (pow0 - pow1329); + tempvar domain97 = domain97 * (domain96); + tempvar domain98 = pow0 - pow1338; + tempvar domain98 = domain98 * (pow0 - pow1339); + tempvar domain98 = domain98 * (pow0 - pow1340); + tempvar domain98 = domain98 * (pow0 - pow1341); + tempvar domain98 = domain98 * (pow0 - pow1342); + tempvar domain98 = domain98 * (pow0 - pow1343); + tempvar domain98 = domain98 * (pow0 - pow1344); + tempvar domain98 = domain98 * (pow0 - pow1345); + tempvar domain98 = domain98 * (pow0 - pow1346); + tempvar domain98 = domain98 * (pow0 - pow1347); + tempvar domain98 = domain98 * (pow0 - pow1348); + tempvar domain98 = domain98 * (pow0 - pow1349); + tempvar domain98 = domain98 * (pow0 - pow1350); + tempvar domain98 = domain98 * (pow0 - pow1351); + tempvar domain98 = domain98 * (pow0 - pow1352); + tempvar domain98 = domain98 * (pow0 - pow1353); + tempvar domain98 = domain98 * (domain92); + tempvar domain98 = domain98 * (domain97); + tempvar domain99 = pow0 - pow1354; + tempvar domain99 = domain99 * (pow0 - pow1355); + tempvar domain99 = domain99 * (pow0 - pow1356); + tempvar domain99 = domain99 * (pow0 - pow1357); + tempvar domain99 = domain99 * (pow0 - pow1358); + tempvar domain99 = domain99 * (pow0 - pow1359); + tempvar domain99 = domain99 * (pow0 - pow1360); + tempvar domain99 = domain99 * (pow0 - pow1361); + tempvar domain100 = pow0 - pow1362; + tempvar domain100 = domain100 * (pow0 - pow1363); + tempvar domain100 = domain100 * (pow0 - pow1364); + tempvar domain100 = domain100 * (pow0 - pow1365); + tempvar domain100 = domain100 * (pow0 - pow1366); + tempvar domain100 = domain100 * (pow0 - pow1367); + tempvar domain100 = domain100 * (pow0 - pow1368); + tempvar domain100 = domain100 * (pow0 - pow1369); + tempvar domain100 = domain100 * (pow0 - pow1370); + tempvar domain100 = domain100 * (pow0 - pow1371); + tempvar domain100 = domain100 * (pow0 - pow1372); + tempvar domain100 = domain100 * (pow0 - pow1373); + tempvar domain100 = domain100 * (pow0 - pow1374); + tempvar domain100 = domain100 * (pow0 - pow1375); + tempvar domain100 = domain100 * (pow0 - pow1376); + tempvar domain100 = domain100 * (pow0 - pow1377); + tempvar domain100 = domain100 * (domain98); + tempvar domain100 = domain100 * (domain99); + tempvar domain101 = pow0 - pow1393; + tempvar domain101 = domain101 * (pow0 - pow1394); + tempvar domain101 = domain101 * (pow0 - pow1395); + tempvar domain101 = domain101 * (pow0 - pow1396); + tempvar domain101 = domain101 * (pow0 - pow1397); + tempvar domain101 = domain101 * (pow0 - pow1398); + tempvar domain101 = domain101 * (pow0 - pow1399); + tempvar domain101 = domain101 * (pow0 - pow1400); + tempvar domain101 = domain101 * (pow0 - pow1424); + tempvar domain101 = domain101 * (pow0 - pow1425); + tempvar domain101 = domain101 * (pow0 - pow1426); + tempvar domain101 = domain101 * (pow0 - pow1427); + tempvar domain101 = domain101 * (pow0 - pow1428); + tempvar domain101 = domain101 * (pow0 - pow1429); + tempvar domain101 = domain101 * (pow0 - pow1430); + tempvar domain101 = domain101 * (pow0 - pow1431); + tempvar domain102 = pow0 - pow1463; + tempvar domain102 = domain102 * (pow0 - pow1464); + tempvar domain102 = domain102 * (pow0 - pow1465); + tempvar domain102 = domain102 * (pow0 - pow1466); + tempvar domain102 = domain102 * (pow0 - pow1467); + tempvar domain102 = domain102 * (pow0 - pow1468); + tempvar domain102 = domain102 * (pow0 - pow1469); + tempvar domain102 = domain102 * (pow0 - pow1470); + tempvar domain102 = domain102 * (pow0 - pow1494); + tempvar domain102 = domain102 * (pow0 - pow1495); + tempvar domain102 = domain102 * (pow0 - pow1496); + tempvar domain102 = domain102 * (pow0 - pow1497); + tempvar domain102 = domain102 * (pow0 - pow1498); + tempvar domain102 = domain102 * (pow0 - pow1499); + tempvar domain102 = domain102 * (pow0 - pow1500); + tempvar domain102 = domain102 * (pow0 - pow1501); + tempvar domain102 = domain102 * (domain101); + tempvar domain103 = pow0 - pow1401; + tempvar domain103 = domain103 * (pow0 - pow1402); + tempvar domain103 = domain103 * (pow0 - pow1403); + tempvar domain103 = domain103 * (pow0 - pow1404); + tempvar domain103 = domain103 * (pow0 - pow1405); + tempvar domain103 = domain103 * (pow0 - pow1406); + tempvar domain103 = domain103 * (pow0 - pow1407); + tempvar domain103 = domain103 * (pow0 - pow1408); + tempvar domain103 = domain103 * (pow0 - pow1409); + tempvar domain103 = domain103 * (pow0 - pow1410); + tempvar domain103 = domain103 * (pow0 - pow1411); + tempvar domain103 = domain103 * (pow0 - pow1412); + tempvar domain103 = domain103 * (pow0 - pow1413); + tempvar domain103 = domain103 * (pow0 - pow1414); + tempvar domain103 = domain103 * (pow0 - pow1415); + tempvar domain103 = domain103 * (pow0 - pow1416); + tempvar domain103 = domain103 * (pow0 - pow1432); + tempvar domain103 = domain103 * (pow0 - pow1433); + tempvar domain103 = domain103 * (pow0 - pow1434); + tempvar domain103 = domain103 * (pow0 - pow1435); + tempvar domain103 = domain103 * (pow0 - pow1436); + tempvar domain103 = domain103 * (pow0 - pow1437); + tempvar domain103 = domain103 * (pow0 - pow1438); + tempvar domain103 = domain103 * (pow0 - pow1439); + tempvar domain103 = domain103 * (pow0 - pow1440); + tempvar domain103 = domain103 * (pow0 - pow1441); + tempvar domain103 = domain103 * (pow0 - pow1442); + tempvar domain103 = domain103 * (pow0 - pow1443); + tempvar domain103 = domain103 * (pow0 - pow1444); + tempvar domain103 = domain103 * (pow0 - pow1445); + tempvar domain103 = domain103 * (pow0 - pow1446); + tempvar domain103 = domain103 * (pow0 - pow1447); + tempvar domain103 = domain103 * (pow0 - pow1471); + tempvar domain103 = domain103 * (pow0 - pow1472); + tempvar domain103 = domain103 * (pow0 - pow1473); + tempvar domain103 = domain103 * (pow0 - pow1474); + tempvar domain103 = domain103 * (pow0 - pow1475); + tempvar domain103 = domain103 * (pow0 - pow1476); + tempvar domain103 = domain103 * (pow0 - pow1477); + tempvar domain103 = domain103 * (pow0 - pow1478); + tempvar domain103 = domain103 * (pow0 - pow1479); + tempvar domain103 = domain103 * (pow0 - pow1480); + tempvar domain103 = domain103 * (pow0 - pow1481); + tempvar domain103 = domain103 * (pow0 - pow1482); + tempvar domain103 = domain103 * (pow0 - pow1483); + tempvar domain103 = domain103 * (pow0 - pow1484); + tempvar domain103 = domain103 * (pow0 - pow1485); + tempvar domain103 = domain103 * (pow0 - pow1486); + tempvar domain103 = domain103 * (pow0 - pow1502); + tempvar domain103 = domain103 * (pow0 - pow1503); + tempvar domain103 = domain103 * (pow0 - pow1504); + tempvar domain103 = domain103 * (pow0 - pow1505); + tempvar domain103 = domain103 * (pow0 - pow1506); + tempvar domain103 = domain103 * (pow0 - pow1507); + tempvar domain103 = domain103 * (pow0 - pow1508); + tempvar domain103 = domain103 * (pow0 - pow1509); + tempvar domain103 = domain103 * (pow0 - pow1510); + tempvar domain103 = domain103 * (pow0 - pow1511); + tempvar domain103 = domain103 * (pow0 - pow1512); + tempvar domain103 = domain103 * (pow0 - pow1513); + tempvar domain103 = domain103 * (pow0 - pow1514); + tempvar domain103 = domain103 * (pow0 - pow1515); + tempvar domain103 = domain103 * (pow0 - pow1516); + tempvar domain103 = domain103 * (pow0 - pow1517); + tempvar domain103 = domain103 * (domain100); + tempvar domain103 = domain103 * (domain102); + tempvar domain104 = pow0 - pow1533; + tempvar domain104 = domain104 * (pow0 - pow1534); + tempvar domain104 = domain104 * (pow0 - pow1535); + tempvar domain104 = domain104 * (pow0 - pow1536); + tempvar domain104 = domain104 * (pow0 - pow1537); + tempvar domain104 = domain104 * (pow0 - pow1538); + tempvar domain104 = domain104 * (pow0 - pow1539); + tempvar domain104 = domain104 * (pow0 - pow1540); + tempvar domain104 = domain104 * (pow0 - pow1541); + tempvar domain104 = domain104 * (pow0 - pow1542); + tempvar domain104 = domain104 * (pow0 - pow1543); + tempvar domain104 = domain104 * (pow0 - pow1544); + tempvar domain104 = domain104 * (pow0 - pow1545); + tempvar domain104 = domain104 * (pow0 - pow1546); + tempvar domain104 = domain104 * (pow0 - pow1547); + tempvar domain104 = domain104 * (pow0 - pow1548); + tempvar domain104 = domain104 * (pow0 - pow1549); + tempvar domain104 = domain104 * (pow0 - pow1550); + tempvar domain104 = domain104 * (pow0 - pow1551); + tempvar domain104 = domain104 * (pow0 - pow1552); + tempvar domain104 = domain104 * (pow0 - pow1553); + tempvar domain104 = domain104 * (pow0 - pow1554); + tempvar domain104 = domain104 * (pow0 - pow1555); + tempvar domain104 = domain104 * (pow0 - pow1556); + tempvar domain104 = domain104 * (pow0 - pow1564); + tempvar domain104 = domain104 * (pow0 - pow1565); + tempvar domain104 = domain104 * (pow0 - pow1566); + tempvar domain104 = domain104 * (pow0 - pow1567); + tempvar domain104 = domain104 * (pow0 - pow1568); + tempvar domain104 = domain104 * (pow0 - pow1569); + tempvar domain104 = domain104 * (pow0 - pow1570); + tempvar domain104 = domain104 * (pow0 - pow1571); + tempvar domain104 = domain104 * (pow0 - pow1572); + tempvar domain104 = domain104 * (pow0 - pow1573); + tempvar domain104 = domain104 * (pow0 - pow1574); + tempvar domain104 = domain104 * (pow0 - pow1575); + tempvar domain104 = domain104 * (pow0 - pow1576); + tempvar domain104 = domain104 * (pow0 - pow1577); + tempvar domain104 = domain104 * (pow0 - pow1578); + tempvar domain104 = domain104 * (pow0 - pow1579); + tempvar domain104 = domain104 * (pow0 - pow1580); + tempvar domain104 = domain104 * (pow0 - pow1581); + tempvar domain104 = domain104 * (pow0 - pow1582); + tempvar domain104 = domain104 * (pow0 - pow1583); + tempvar domain104 = domain104 * (pow0 - pow1584); + tempvar domain104 = domain104 * (pow0 - pow1585); + tempvar domain104 = domain104 * (pow0 - pow1586); + tempvar domain104 = domain104 * (pow0 - pow1587); + tempvar domain104 = domain104 * (domain103); + tempvar domain105 = pow0 - pow1588; + tempvar domain105 = domain105 * (pow0 - pow1589); + tempvar domain105 = domain105 * (pow0 - pow1590); + tempvar domain105 = domain105 * (pow0 - pow1591); + tempvar domain105 = domain105 * (pow0 - pow1592); + tempvar domain105 = domain105 * (pow0 - pow1593); + tempvar domain105 = domain105 * (pow0 - pow1594); + tempvar domain105 = domain105 * (pow0 - pow1595); + tempvar domain105 = domain105 * (pow0 - pow1596); + tempvar domain105 = domain105 * (pow0 - pow1597); + tempvar domain105 = domain105 * (pow0 - pow1598); + tempvar domain105 = domain105 * (pow0 - pow1599); + tempvar domain105 = domain105 * (pow0 - pow1600); + tempvar domain105 = domain105 * (pow0 - pow1601); + tempvar domain105 = domain105 * (pow0 - pow1602); + tempvar domain105 = domain105 * (pow0 - pow1603); + tempvar domain105 = domain105 * (pow0 - pow1604); + tempvar domain105 = domain105 * (pow0 - pow1605); + tempvar domain105 = domain105 * (pow0 - pow1606); + tempvar domain105 = domain105 * (pow0 - pow1607); + tempvar domain105 = domain105 * (pow0 - pow1608); + tempvar domain105 = domain105 * (pow0 - pow1609); + tempvar domain105 = domain105 * (pow0 - pow1610); + tempvar domain105 = domain105 * (pow0 - pow1611); + tempvar domain105 = domain105 * (domain104); + tempvar domain106 = domain25; + tempvar domain106 = domain106 * (domain44); + tempvar domain107 = domain76; + tempvar domain107 = domain107 * (domain106); + tempvar domain108 = domain82; + tempvar domain108 = domain108 * (domain107); + tempvar domain109 = domain38; + tempvar domain109 = domain109 * (domain42); + tempvar domain109 = domain109 * (domain46); + tempvar domain110 = domain49; + tempvar domain110 = domain110 * (domain109); + tempvar domain111 = domain53; + tempvar domain111 = domain111 * (domain110); + tempvar domain112 = domain48; + tempvar domain112 = domain112 * (domain50); + tempvar domain113 = domain74; + tempvar domain113 = domain113 * (domain77); + tempvar domain114 = domain83; + tempvar domain114 = domain114 * (domain92); + tempvar domain114 = domain114 * (domain99); + tempvar domain114 = domain114 * (domain107); + tempvar domain115 = domain102; + tempvar domain115 = domain115 * (domain114); + tempvar domain116 = domain54; + tempvar domain116 = domain116 * (domain61); + tempvar domain116 = domain116 * (domain67); + tempvar domain116 = domain116 * (domain110); + tempvar domain117 = domain70; + tempvar domain117 = domain117 * (domain116); + tempvar domain118 = domain101; + tempvar domain118 = domain118 * (domain114); + tempvar domain119 = domain69; + tempvar domain119 = domain119 * (domain116); + tempvar domain120 = domain91; + tempvar domain120 = domain120 * (domain97); + tempvar domain121 = domain60; + tempvar domain121 = domain121 * (domain65); + tempvar domain122 = domain58; + tempvar domain122 = domain122 * (domain63); + tempvar domain123 = domain88; + tempvar domain123 = domain123 * (domain94); + tempvar domain124 = domain52; + tempvar domain124 = domain124 * (domain55); + tempvar domain125 = domain81; + tempvar domain125 = domain125 * (domain85); + tempvar domain126 = domain59; + tempvar domain126 = domain126 * (domain64); + tempvar domain127 = domain90; + tempvar domain127 = domain127 * (domain96); + tempvar domain128 = domain57; + tempvar domain128 = domain128 * (domain62); + tempvar domain129 = domain87; + tempvar domain129 = domain129 * (domain93); + tempvar domain130 = pow0 - pow1628; + tempvar domain130 = domain130 * (pow0 - pow1629); + tempvar domain130 = domain130 * (pow0 - pow1630); + tempvar domain130 = domain130 * (pow0 - pow1631); + tempvar domain130 = domain130 * (pow0 - pow1632); + tempvar domain130 = domain130 * (pow0 - pow1633); + tempvar domain130 = domain130 * (pow0 - pow1634); + tempvar domain130 = domain130 * (pow0 - pow1635); + tempvar domain130 = domain130 * (pow0 - pow1636); + tempvar domain130 = domain130 * (pow0 - pow1637); + tempvar domain130 = domain130 * (pow0 - pow1638); + tempvar domain130 = domain130 * (pow0 - pow1639); + tempvar domain130 = domain130 * (pow0 - pow1640); + tempvar domain130 = domain130 * (pow0 - pow1641); + tempvar domain130 = domain130 * (pow0 - pow1642); + tempvar domain130 = domain130 * (pow0 - pow1643); + tempvar domain130 = domain130 * (pow0 - pow1644); + tempvar domain130 = domain130 * (pow0 - pow1645); + tempvar domain130 = domain130 * (pow0 - pow1646); + tempvar domain130 = domain130 * (pow0 - pow1647); + tempvar domain130 = domain130 * (pow0 - pow1648); + tempvar domain130 = domain130 * (pow0 - pow1649); + tempvar domain130 = domain130 * (pow0 - pow1650); + tempvar domain130 = domain130 * (pow0 - pow1651); + tempvar domain130 = domain130 * (domain43); + tempvar domain130 = domain130 * (domain45); + tempvar domain130 = domain130 * (domain75); + tempvar domain130 = domain130 * (domain78); + tempvar domain130 = domain130 * (domain80); + tempvar domain130 = domain130 * (domain84); + tempvar domain130 = domain130 * (domain89); + tempvar domain130 = domain130 * (domain95); + tempvar domain131 = point - pow3357; + tempvar domain132 = point - 1; + tempvar domain133 = point - pow3358; + tempvar domain134 = point - pow3359; + tempvar domain135 = point - pow3360; + tempvar domain136 = point - pow3361; + tempvar domain137 = point - pow3362; + tempvar domain138 = point - pow3363; + tempvar domain139 = point - pow3364; + + // Fetch mask variables. + tempvar column0_row0 = mask_values[0]; + tempvar column0_row1 = mask_values[1]; + tempvar column0_row2 = mask_values[2]; + tempvar column0_row3 = mask_values[3]; + tempvar column0_row4 = mask_values[4]; + tempvar column0_row5 = mask_values[5]; + tempvar column0_row6 = mask_values[6]; + tempvar column0_row7 = mask_values[7]; + tempvar column0_row8 = mask_values[8]; + tempvar column0_row9 = mask_values[9]; + tempvar column0_row10 = mask_values[10]; + tempvar column0_row11 = mask_values[11]; + tempvar column0_row12 = mask_values[12]; + tempvar column0_row13 = mask_values[13]; + tempvar column0_row14 = mask_values[14]; + tempvar column0_row15 = mask_values[15]; + tempvar column1_row0 = mask_values[16]; + tempvar column1_row1 = mask_values[17]; + tempvar column1_row2 = mask_values[18]; + tempvar column1_row3 = mask_values[19]; + tempvar column1_row4 = mask_values[20]; + tempvar column1_row5 = mask_values[21]; + tempvar column1_row6 = mask_values[22]; + tempvar column1_row8 = mask_values[23]; + tempvar column1_row12 = mask_values[24]; + tempvar column1_row14 = mask_values[25]; + tempvar column1_row16 = mask_values[26]; + tempvar column1_row20 = mask_values[27]; + tempvar column1_row24 = mask_values[28]; + tempvar column1_row28 = mask_values[29]; + tempvar column1_row32 = mask_values[30]; + tempvar column1_row36 = mask_values[31]; + tempvar column1_row40 = mask_values[32]; + tempvar column1_row44 = mask_values[33]; + tempvar column1_row48 = mask_values[34]; + tempvar column1_row52 = mask_values[35]; + tempvar column1_row56 = mask_values[36]; + tempvar column1_row60 = mask_values[37]; + tempvar column1_row64 = mask_values[38]; + tempvar column1_row66 = mask_values[39]; + tempvar column1_row128 = mask_values[40]; + tempvar column1_row130 = mask_values[41]; + tempvar column1_row176 = mask_values[42]; + tempvar column1_row180 = mask_values[43]; + tempvar column1_row184 = mask_values[44]; + tempvar column1_row188 = mask_values[45]; + tempvar column1_row192 = mask_values[46]; + tempvar column1_row194 = mask_values[47]; + tempvar column1_row195 = mask_values[48]; + tempvar column1_row198 = mask_values[49]; + tempvar column1_row240 = mask_values[50]; + tempvar column1_row244 = mask_values[51]; + tempvar column1_row248 = mask_values[52]; + tempvar column1_row252 = mask_values[53]; + tempvar column1_row259 = mask_values[54]; + tempvar column1_row262 = mask_values[55]; + tempvar column1_row451 = mask_values[56]; + tempvar column1_row515 = mask_values[57]; + tempvar column1_row518 = mask_values[58]; + tempvar column1_row707 = mask_values[59]; + tempvar column1_row769 = mask_values[60]; + tempvar column1_row771 = mask_values[61]; + tempvar column1_row773 = mask_values[62]; + tempvar column1_row774 = mask_values[63]; + tempvar column1_row782 = mask_values[64]; + tempvar column1_row963 = mask_values[65]; + tempvar column1_row1025 = mask_values[66]; + tempvar column1_row1027 = mask_values[67]; + tempvar column1_row1029 = mask_values[68]; + tempvar column1_row1030 = mask_values[69]; + tempvar column1_row1038 = mask_values[70]; + tempvar column1_row1219 = mask_values[71]; + tempvar column1_row1283 = mask_values[72]; + tempvar column1_row1286 = mask_values[73]; + tempvar column1_row1475 = mask_values[74]; + tempvar column1_row1539 = mask_values[75]; + tempvar column1_row1542 = mask_values[76]; + tempvar column1_row1731 = mask_values[77]; + tempvar column1_row1795 = mask_values[78]; + tempvar column1_row1798 = mask_values[79]; + tempvar column1_row1987 = mask_values[80]; + tempvar column1_row2051 = mask_values[81]; + tempvar column1_row2054 = mask_values[82]; + tempvar column1_row2118 = mask_values[83]; + tempvar column1_row2182 = mask_values[84]; + tempvar column1_row2243 = mask_values[85]; + tempvar column1_row2307 = mask_values[86]; + tempvar column1_row2310 = mask_values[87]; + tempvar column1_row2499 = mask_values[88]; + tempvar column1_row2563 = mask_values[89]; + tempvar column1_row2566 = mask_values[90]; + tempvar column1_row2755 = mask_values[91]; + tempvar column1_row2819 = mask_values[92]; + tempvar column1_row2822 = mask_values[93]; + tempvar column1_row3011 = mask_values[94]; + tempvar column1_row3075 = mask_values[95]; + tempvar column1_row3078 = mask_values[96]; + tempvar column1_row3331 = mask_values[97]; + tempvar column1_row3334 = mask_values[98]; + tempvar column1_row3587 = mask_values[99]; + tempvar column1_row3590 = mask_values[100]; + tempvar column1_row3654 = mask_values[101]; + tempvar column1_row3718 = mask_values[102]; + tempvar column1_row3843 = mask_values[103]; + tempvar column1_row3846 = mask_values[104]; + tempvar column1_row3910 = mask_values[105]; + tempvar column1_row3974 = mask_values[106]; + tempvar column1_row4099 = mask_values[107]; + tempvar column1_row4102 = mask_values[108]; + tempvar column1_row4355 = mask_values[109]; + tempvar column1_row4358 = mask_values[110]; + tempvar column1_row4611 = mask_values[111]; + tempvar column1_row4614 = mask_values[112]; + tempvar column1_row4867 = mask_values[113]; + tempvar column1_row4870 = mask_values[114]; + tempvar column1_row5123 = mask_values[115]; + tempvar column1_row5126 = mask_values[116]; + tempvar column1_row5379 = mask_values[117]; + tempvar column1_row5382 = mask_values[118]; + tempvar column1_row5443 = mask_values[119]; + tempvar column1_row5446 = mask_values[120]; + tempvar column1_row5507 = mask_values[121]; + tempvar column1_row5510 = mask_values[122]; + tempvar column1_row5635 = mask_values[123]; + tempvar column1_row5638 = mask_values[124]; + tempvar column1_row5699 = mask_values[125]; + tempvar column1_row5763 = mask_values[126]; + tempvar column1_row5891 = mask_values[127]; + tempvar column1_row5894 = mask_values[128]; + tempvar column1_row5955 = mask_values[129]; + tempvar column1_row6019 = mask_values[130]; + tempvar column1_row6147 = mask_values[131]; + tempvar column1_row6150 = mask_values[132]; + tempvar column1_row6211 = mask_values[133]; + tempvar column1_row6275 = mask_values[134]; + tempvar column1_row6401 = mask_values[135]; + tempvar column1_row6403 = mask_values[136]; + tempvar column1_row6405 = mask_values[137]; + tempvar column1_row6406 = mask_values[138]; + tempvar column1_row6469 = mask_values[139]; + tempvar column1_row6470 = mask_values[140]; + tempvar column1_row6533 = mask_values[141]; + tempvar column1_row6534 = mask_values[142]; + tempvar column1_row6593 = mask_values[143]; + tempvar column1_row6595 = mask_values[144]; + tempvar column1_row6597 = mask_values[145]; + tempvar column1_row6598 = mask_values[146]; + tempvar column1_row6657 = mask_values[147]; + tempvar column1_row6662 = mask_values[148]; + tempvar column1_row6721 = mask_values[149]; + tempvar column1_row6726 = mask_values[150]; + tempvar column1_row6785 = mask_values[151]; + tempvar column1_row6787 = mask_values[152]; + tempvar column1_row6789 = mask_values[153]; + tempvar column1_row6790 = mask_values[154]; + tempvar column1_row6977 = mask_values[155]; + tempvar column1_row6979 = mask_values[156]; + tempvar column1_row6981 = mask_values[157]; + tempvar column1_row6982 = mask_values[158]; + tempvar column1_row7169 = mask_values[159]; + tempvar column1_row7171 = mask_values[160]; + tempvar column1_row7173 = mask_values[161]; + tempvar column1_row7174 = mask_values[162]; + tempvar column1_row7361 = mask_values[163]; + tempvar column1_row7363 = mask_values[164]; + tempvar column1_row7365 = mask_values[165]; + tempvar column1_row7366 = mask_values[166]; + tempvar column1_row7553 = mask_values[167]; + tempvar column1_row7555 = mask_values[168]; + tempvar column1_row7557 = mask_values[169]; + tempvar column1_row7558 = mask_values[170]; + tempvar column1_row7745 = mask_values[171]; + tempvar column1_row7747 = mask_values[172]; + tempvar column1_row7749 = mask_values[173]; + tempvar column1_row7750 = mask_values[174]; + tempvar column1_row7937 = mask_values[175]; + tempvar column1_row7939 = mask_values[176]; + tempvar column1_row7941 = mask_values[177]; + tempvar column1_row7942 = mask_values[178]; + tempvar column1_row8193 = mask_values[179]; + tempvar column1_row8195 = mask_values[180]; + tempvar column1_row8197 = mask_values[181]; + tempvar column1_row8206 = mask_values[182]; + tempvar column1_row8451 = mask_values[183]; + tempvar column1_row8707 = mask_values[184]; + tempvar column1_row10755 = mask_values[185]; + tempvar column1_row15941 = mask_values[186]; + tempvar column1_row16902 = mask_values[187]; + tempvar column1_row18883 = mask_values[188]; + tempvar column1_row19139 = mask_values[189]; + tempvar column1_row19395 = mask_values[190]; + tempvar column1_row22531 = mask_values[191]; + tempvar column1_row22595 = mask_values[192]; + tempvar column1_row22659 = mask_values[193]; + tempvar column1_row22785 = mask_values[194]; + tempvar column1_row24577 = mask_values[195]; + tempvar column1_row24579 = mask_values[196]; + tempvar column1_row24581 = mask_values[197]; + tempvar column1_row24590 = mask_values[198]; + tempvar column1_row24835 = mask_values[199]; + tempvar column1_row25091 = mask_values[200]; + tempvar column1_row26371 = mask_values[201]; + tempvar column1_row30214 = mask_values[202]; + tempvar column1_row30977 = mask_values[203]; + tempvar column1_row31171 = mask_values[204]; + tempvar column1_row51971 = mask_values[205]; + tempvar column1_row55939 = mask_values[206]; + tempvar column1_row57345 = mask_values[207]; + tempvar column1_row57347 = mask_values[208]; + tempvar column1_row57349 = mask_values[209]; + tempvar column1_row57358 = mask_values[210]; + tempvar column1_row57603 = mask_values[211]; + tempvar column1_row57859 = mask_values[212]; + tempvar column1_row68867 = mask_values[213]; + tempvar column1_row71430 = mask_values[214]; + tempvar column1_row71941 = mask_values[215]; + tempvar column1_row73473 = mask_values[216]; + tempvar column1_row75782 = mask_values[217]; + tempvar column1_row75846 = mask_values[218]; + tempvar column1_row75910 = mask_values[219]; + tempvar column1_row80133 = mask_values[220]; + tempvar column1_row80197 = mask_values[221]; + tempvar column1_row80261 = mask_values[222]; + tempvar column1_row86275 = mask_values[223]; + tempvar column1_row89283 = mask_values[224]; + tempvar column1_row115715 = mask_values[225]; + tempvar column1_row122246 = mask_values[226]; + tempvar column1_row122881 = mask_values[227]; + tempvar column1_row122883 = mask_values[228]; + tempvar column1_row122885 = mask_values[229]; + tempvar column1_row122894 = mask_values[230]; + tempvar column1_row123139 = mask_values[231]; + tempvar column1_row123395 = mask_values[232]; + tempvar column1_row127491 = mask_values[233]; + tempvar column1_row130435 = mask_values[234]; + tempvar column1_row151043 = mask_values[235]; + tempvar column1_row155397 = mask_values[236]; + tempvar column1_row159750 = mask_values[237]; + tempvar column1_row162054 = mask_values[238]; + tempvar column1_row165379 = mask_values[239]; + tempvar column1_row165382 = mask_values[240]; + tempvar column1_row170246 = mask_values[241]; + tempvar column1_row171397 = mask_values[242]; + tempvar column1_row172803 = mask_values[243]; + tempvar column1_row175110 = mask_values[244]; + tempvar column1_row178433 = mask_values[245]; + tempvar column1_row178435 = mask_values[246]; + tempvar column1_row192262 = mask_values[247]; + tempvar column1_row192326 = mask_values[248]; + tempvar column1_row192390 = mask_values[249]; + tempvar column1_row195009 = mask_values[250]; + tempvar column1_row195073 = mask_values[251]; + tempvar column1_row195137 = mask_values[252]; + tempvar column1_row207875 = mask_values[253]; + tempvar column1_row208390 = mask_values[254]; + tempvar column1_row208454 = mask_values[255]; + tempvar column1_row208518 = mask_values[256]; + tempvar column1_row211398 = mask_values[257]; + tempvar column1_row211462 = mask_values[258]; + tempvar column1_row211526 = mask_values[259]; + tempvar column1_row212742 = mask_values[260]; + tempvar column1_row225027 = mask_values[261]; + tempvar column1_row228163 = mask_values[262]; + tempvar column1_row230659 = mask_values[263]; + tempvar column1_row230662 = mask_values[264]; + tempvar column1_row235969 = mask_values[265]; + tempvar column1_row236929 = mask_values[266]; + tempvar column1_row253953 = mask_values[267]; + tempvar column1_row253955 = mask_values[268]; + tempvar column1_row253957 = mask_values[269]; + tempvar column1_row253966 = mask_values[270]; + tempvar column1_row254211 = mask_values[271]; + tempvar column1_row254467 = mask_values[272]; + tempvar column1_row295686 = mask_values[273]; + tempvar column1_row299011 = mask_values[274]; + tempvar column1_row301317 = mask_values[275]; + tempvar column1_row302083 = mask_values[276]; + tempvar column1_row304134 = mask_values[277]; + tempvar column1_row309702 = mask_values[278]; + tempvar column1_row320451 = mask_values[279]; + tempvar column1_row320707 = mask_values[280]; + tempvar column1_row320963 = mask_values[281]; + tempvar column1_row322822 = mask_values[282]; + tempvar column1_row325123 = mask_values[283]; + tempvar column1_row325187 = mask_values[284]; + tempvar column1_row325251 = mask_values[285]; + tempvar column1_row325893 = mask_values[286]; + tempvar column1_row337603 = mask_values[287]; + tempvar column1_row337859 = mask_values[288]; + tempvar column1_row338115 = mask_values[289]; + tempvar column1_row341763 = mask_values[290]; + tempvar column1_row341827 = mask_values[291]; + tempvar column1_row341891 = mask_values[292]; + tempvar column1_row352771 = mask_values[293]; + tempvar column1_row356870 = mask_values[294]; + tempvar column1_row358661 = mask_values[295]; + tempvar column1_row359621 = mask_values[296]; + tempvar column1_row360707 = mask_values[297]; + tempvar column1_row362758 = mask_values[298]; + tempvar column1_row367046 = mask_values[299]; + tempvar column1_row367809 = mask_values[300]; + tempvar column1_row370691 = mask_values[301]; + tempvar column1_row376390 = mask_values[302]; + tempvar column1_row381958 = mask_values[303]; + tempvar column1_row383425 = mask_values[304]; + tempvar column1_row405766 = mask_values[305]; + tempvar column1_row407809 = mask_values[306]; + tempvar column1_row415750 = mask_values[307]; + tempvar column1_row416198 = mask_values[308]; + tempvar column1_row445190 = mask_values[309]; + tempvar column1_row448774 = mask_values[310]; + tempvar column1_row450755 = mask_values[311]; + tempvar column1_row451011 = mask_values[312]; + tempvar column1_row451267 = mask_values[313]; + tempvar column1_row455939 = mask_values[314]; + tempvar column1_row456003 = mask_values[315]; + tempvar column1_row456067 = mask_values[316]; + tempvar column1_row463619 = mask_values[317]; + tempvar column1_row463622 = mask_values[318]; + tempvar column1_row465350 = mask_values[319]; + tempvar column1_row466499 = mask_values[320]; + tempvar column1_row476934 = mask_values[321]; + tempvar column1_row481537 = mask_values[322]; + tempvar column1_row502019 = mask_values[323]; + tempvar column1_row502278 = mask_values[324]; + tempvar column1_row506305 = mask_values[325]; + tempvar column1_row507457 = mask_values[326]; + tempvar column1_row513027 = mask_values[327]; + tempvar column1_row513286 = mask_values[328]; + tempvar column1_row513350 = mask_values[329]; + tempvar column1_row513414 = mask_values[330]; + tempvar column1_row514310 = mask_values[331]; + tempvar column1_row514374 = mask_values[332]; + tempvar column1_row514438 = mask_values[333]; + tempvar column1_row515843 = mask_values[334]; + tempvar column1_row516097 = mask_values[335]; + tempvar column1_row516099 = mask_values[336]; + tempvar column1_row516101 = mask_values[337]; + tempvar column1_row516102 = mask_values[338]; + tempvar column1_row516110 = mask_values[339]; + tempvar column1_row516294 = mask_values[340]; + tempvar column1_row516355 = mask_values[341]; + tempvar column1_row516358 = mask_values[342]; + tempvar column1_row516611 = mask_values[343]; + tempvar column1_row522497 = mask_values[344]; + tempvar column1_row522501 = mask_values[345]; + tempvar column1_row522502 = mask_values[346]; + tempvar column1_row522689 = mask_values[347]; + tempvar column1_row522694 = mask_values[348]; + tempvar column2_row0 = mask_values[349]; + tempvar column2_row1 = mask_values[350]; + tempvar column3_row0 = mask_values[351]; + tempvar column3_row1 = mask_values[352]; + tempvar column3_row2 = mask_values[353]; + tempvar column3_row3 = mask_values[354]; + tempvar column3_row4 = mask_values[355]; + tempvar column3_row5 = mask_values[356]; + tempvar column3_row6 = mask_values[357]; + tempvar column3_row7 = mask_values[358]; + tempvar column3_row8 = mask_values[359]; + tempvar column3_row9 = mask_values[360]; + tempvar column3_row10 = mask_values[361]; + tempvar column3_row11 = mask_values[362]; + tempvar column3_row12 = mask_values[363]; + tempvar column3_row13 = mask_values[364]; + tempvar column3_row14 = mask_values[365]; + tempvar column3_row15 = mask_values[366]; + tempvar column3_row16 = mask_values[367]; + tempvar column3_row20 = mask_values[368]; + tempvar column3_row32 = mask_values[369]; + tempvar column3_row256 = mask_values[370]; + tempvar column3_row264 = mask_values[371]; + tempvar column3_row272 = mask_values[372]; + tempvar column3_row288 = mask_values[373]; + tempvar column3_row512 = mask_values[374]; + tempvar column3_row520 = mask_values[375]; + tempvar column3_row1876 = mask_values[376]; + tempvar column3_row1940 = mask_values[377]; + tempvar column3_row2004 = mask_values[378]; + tempvar column3_row3924 = mask_values[379]; + tempvar column3_row3988 = mask_values[380]; + tempvar column3_row4052 = mask_values[381]; + tempvar column3_row5972 = mask_values[382]; + tempvar column3_row6036 = mask_values[383]; + tempvar column3_row6100 = mask_values[384]; + tempvar column3_row6416 = mask_values[385]; + tempvar column3_row6432 = mask_values[386]; + tempvar column3_row7568 = mask_values[387]; + tempvar column3_row7760 = mask_values[388]; + tempvar column3_row7824 = mask_values[389]; + tempvar column3_row7888 = mask_values[390]; + tempvar column3_row8208 = mask_values[391]; + tempvar column3_row8224 = mask_values[392]; + tempvar column3_row8448 = mask_values[393]; + tempvar column3_row8456 = mask_values[394]; + tempvar column3_row10068 = mask_values[395]; + tempvar column3_row12116 = mask_values[396]; + tempvar column3_row14164 = mask_values[397]; + tempvar column3_row15760 = mask_values[398]; + tempvar column3_row15952 = mask_values[399]; + tempvar column3_row16144 = mask_values[400]; + tempvar column3_row16145 = mask_values[401]; + tempvar column3_row16146 = mask_values[402]; + tempvar column3_row16147 = mask_values[403]; + tempvar column3_row16148 = mask_values[404]; + tempvar column3_row16149 = mask_values[405]; + tempvar column3_row16150 = mask_values[406]; + tempvar column3_row16151 = mask_values[407]; + tempvar column3_row16160 = mask_values[408]; + tempvar column3_row16161 = mask_values[409]; + tempvar column3_row16162 = mask_values[410]; + tempvar column3_row16163 = mask_values[411]; + tempvar column3_row16164 = mask_values[412]; + tempvar column3_row16165 = mask_values[413]; + tempvar column3_row16166 = mask_values[414]; + tempvar column3_row16167 = mask_values[415]; + tempvar column3_row16176 = mask_values[416]; + tempvar column3_row16192 = mask_values[417]; + tempvar column3_row16208 = mask_values[418]; + tempvar column3_row16224 = mask_values[419]; + tempvar column3_row16240 = mask_values[420]; + tempvar column3_row16256 = mask_values[421]; + tempvar column3_row16272 = mask_values[422]; + tempvar column3_row16288 = mask_values[423]; + tempvar column3_row16304 = mask_values[424]; + tempvar column3_row16320 = mask_values[425]; + tempvar column3_row16336 = mask_values[426]; + tempvar column3_row16352 = mask_values[427]; + tempvar column3_row16368 = mask_values[428]; + tempvar column3_row16384 = mask_values[429]; + tempvar column3_row23952 = mask_values[430]; + tempvar column3_row32144 = mask_values[431]; + tempvar column3_row32768 = mask_values[432]; + tempvar column3_row65536 = mask_values[433]; + tempvar column3_row66320 = mask_values[434]; + tempvar column3_row66336 = mask_values[435]; + tempvar column3_row71508 = mask_values[436]; + tempvar column3_row79700 = mask_values[437]; + tempvar column3_row79764 = mask_values[438]; + tempvar column3_row79828 = mask_values[439]; + tempvar column3_row98304 = mask_values[440]; + tempvar column3_row131072 = mask_values[441]; + tempvar column3_row132624 = mask_values[442]; + tempvar column3_row132640 = mask_values[443]; + tempvar column3_row157524 = mask_values[444]; + tempvar column3_row163840 = mask_values[445]; + tempvar column3_row165716 = mask_values[446]; + tempvar column3_row179600 = mask_values[447]; + tempvar column3_row196176 = mask_values[448]; + tempvar column3_row196240 = mask_values[449]; + tempvar column3_row196304 = mask_values[450]; + tempvar column3_row196608 = mask_values[451]; + tempvar column3_row198928 = mask_values[452]; + tempvar column3_row198944 = mask_values[453]; + tempvar column3_row208724 = mask_values[454]; + tempvar column3_row208788 = mask_values[455]; + tempvar column3_row208852 = mask_values[456]; + tempvar column3_row229376 = mask_values[457]; + tempvar column3_row237136 = mask_values[458]; + tempvar column3_row262144 = mask_values[459]; + tempvar column3_row265232 = mask_values[460]; + tempvar column3_row265248 = mask_values[461]; + tempvar column3_row294912 = mask_values[462]; + tempvar column3_row300884 = mask_values[463]; + tempvar column3_row307028 = mask_values[464]; + tempvar column3_row325460 = mask_values[465]; + tempvar column3_row327680 = mask_values[466]; + tempvar column3_row331536 = mask_values[467]; + tempvar column3_row331552 = mask_values[468]; + tempvar column3_row358228 = mask_values[469]; + tempvar column3_row360448 = mask_values[470]; + tempvar column3_row364372 = mask_values[471]; + tempvar column3_row384592 = mask_values[472]; + tempvar column3_row393216 = mask_values[473]; + tempvar column3_row397840 = mask_values[474]; + tempvar column3_row397856 = mask_values[475]; + tempvar column3_row408976 = mask_values[476]; + tempvar column3_row413524 = mask_values[477]; + tempvar column3_row425984 = mask_values[478]; + tempvar column3_row444244 = mask_values[479]; + tempvar column3_row458752 = mask_values[480]; + tempvar column3_row462676 = mask_values[481]; + tempvar column3_row464144 = mask_values[482]; + tempvar column3_row464160 = mask_values[483]; + tempvar column3_row482704 = mask_values[484]; + tempvar column3_row491520 = mask_values[485]; + tempvar column3_row507472 = mask_values[486]; + tempvar column3_row509780 = mask_values[487]; + tempvar column3_row509844 = mask_values[488]; + tempvar column3_row509908 = mask_values[489]; + tempvar column3_row516112 = mask_values[490]; + tempvar column3_row516128 = mask_values[491]; + tempvar column3_row516352 = mask_values[492]; + tempvar column3_row516360 = mask_values[493]; + tempvar column3_row517972 = mask_values[494]; + tempvar column4_row0 = mask_values[495]; + tempvar column4_row1 = mask_values[496]; + tempvar column4_row2 = mask_values[497]; + tempvar column4_row3 = mask_values[498]; + tempvar column4_row4 = mask_values[499]; + tempvar column4_row5 = mask_values[500]; + tempvar column4_row8 = mask_values[501]; + tempvar column4_row9 = mask_values[502]; + tempvar column4_row10 = mask_values[503]; + tempvar column4_row11 = mask_values[504]; + tempvar column4_row12 = mask_values[505]; + tempvar column4_row13 = mask_values[506]; + tempvar column4_row16 = mask_values[507]; + tempvar column4_row42 = mask_values[508]; + tempvar column4_row43 = mask_values[509]; + tempvar column4_row74 = mask_values[510]; + tempvar column4_row75 = mask_values[511]; + tempvar column4_row106 = mask_values[512]; + tempvar column4_row138 = mask_values[513]; + tempvar column4_row139 = mask_values[514]; + tempvar column4_row171 = mask_values[515]; + tempvar column4_row202 = mask_values[516]; + tempvar column4_row234 = mask_values[517]; + tempvar column4_row235 = mask_values[518]; + tempvar column4_row298 = mask_values[519]; + tempvar column4_row522 = mask_values[520]; + tempvar column4_row523 = mask_values[521]; + tempvar column4_row1034 = mask_values[522]; + tempvar column4_row1035 = mask_values[523]; + tempvar column4_row2058 = mask_values[524]; + tempvar column4_row2059 = mask_values[525]; + tempvar column4_row2570 = mask_values[526]; + tempvar column4_row2571 = mask_values[527]; + tempvar column4_row4106 = mask_values[528]; + tempvar column4_row4619 = mask_values[529]; + tempvar column4_row6667 = mask_values[530]; + tempvar column4_row8715 = mask_values[531]; + tempvar column4_row10763 = mask_values[532]; + tempvar column4_row12811 = mask_values[533]; + tempvar column4_row14859 = mask_values[534]; + tempvar column4_row16907 = mask_values[535]; + tempvar column4_row18955 = mask_values[536]; + tempvar column4_row21003 = mask_values[537]; + tempvar column4_row23051 = mask_values[538]; + tempvar column4_row25099 = mask_values[539]; + tempvar column4_row27147 = mask_values[540]; + tempvar column4_row29195 = mask_values[541]; + tempvar column4_row31243 = mask_values[542]; + tempvar column5_row0 = mask_values[543]; + tempvar column5_row1 = mask_values[544]; + tempvar column5_row2 = mask_values[545]; + tempvar column5_row3 = mask_values[546]; + tempvar column6_row0 = mask_values[547]; + tempvar column6_row1 = mask_values[548]; + tempvar column6_row2 = mask_values[549]; + tempvar column6_row3 = mask_values[550]; + tempvar column6_row4 = mask_values[551]; + tempvar column6_row5 = mask_values[552]; + tempvar column6_row6 = mask_values[553]; + tempvar column6_row7 = mask_values[554]; + tempvar column6_row8 = mask_values[555]; + tempvar column6_row9 = mask_values[556]; + tempvar column6_row11 = mask_values[557]; + tempvar column6_row12 = mask_values[558]; + tempvar column6_row13 = mask_values[559]; + tempvar column6_row28 = mask_values[560]; + tempvar column6_row44 = mask_values[561]; + tempvar column6_row60 = mask_values[562]; + tempvar column6_row76 = mask_values[563]; + tempvar column6_row92 = mask_values[564]; + tempvar column6_row108 = mask_values[565]; + tempvar column6_row124 = mask_values[566]; + tempvar column6_row1539 = mask_values[567]; + tempvar column6_row1547 = mask_values[568]; + tempvar column6_row1571 = mask_values[569]; + tempvar column6_row1579 = mask_values[570]; + tempvar column6_row2011 = mask_values[571]; + tempvar column6_row2019 = mask_values[572]; + tempvar column6_row2041 = mask_values[573]; + tempvar column6_row2045 = mask_values[574]; + tempvar column6_row2047 = mask_values[575]; + tempvar column6_row2049 = mask_values[576]; + tempvar column6_row2051 = mask_values[577]; + tempvar column6_row2053 = mask_values[578]; + tempvar column6_row4089 = mask_values[579]; + tempvar column7_row0 = mask_values[580]; + tempvar column7_row2 = mask_values[581]; + tempvar column7_row4 = mask_values[582]; + tempvar column7_row8 = mask_values[583]; + tempvar column7_row10 = mask_values[584]; + tempvar column7_row12 = mask_values[585]; + tempvar column7_row16 = mask_values[586]; + tempvar column7_row24 = mask_values[587]; + tempvar column8_inter1_row0 = mask_values[588]; + tempvar column8_inter1_row1 = mask_values[589]; + tempvar column9_inter1_row0 = mask_values[590]; + tempvar column9_inter1_row1 = mask_values[591]; + tempvar column10_inter1_row0 = mask_values[592]; + tempvar column10_inter1_row1 = mask_values[593]; + tempvar column10_inter1_row2 = mask_values[594]; + tempvar column10_inter1_row5 = mask_values[595]; + + // Compute intermediate values. + tempvar cpu__decode__opcode_rc__bit_0 = column0_row0 - (column0_row1 + column0_row1); + tempvar cpu__decode__opcode_rc__bit_2 = column0_row2 - (column0_row3 + column0_row3); + tempvar cpu__decode__opcode_rc__bit_4 = column0_row4 - (column0_row5 + column0_row5); + tempvar cpu__decode__opcode_rc__bit_3 = column0_row3 - (column0_row4 + column0_row4); + tempvar cpu__decode__flag_op1_base_op0_0 = 1 - (cpu__decode__opcode_rc__bit_2 + cpu__decode__opcode_rc__bit_4 + cpu__decode__opcode_rc__bit_3); + tempvar cpu__decode__opcode_rc__bit_5 = column0_row5 - (column0_row6 + column0_row6); + tempvar cpu__decode__opcode_rc__bit_6 = column0_row6 - (column0_row7 + column0_row7); + tempvar cpu__decode__opcode_rc__bit_9 = column0_row9 - (column0_row10 + column0_row10); + tempvar cpu__decode__flag_res_op1_0 = 1 - (cpu__decode__opcode_rc__bit_5 + cpu__decode__opcode_rc__bit_6 + cpu__decode__opcode_rc__bit_9); + tempvar cpu__decode__opcode_rc__bit_7 = column0_row7 - (column0_row8 + column0_row8); + tempvar cpu__decode__opcode_rc__bit_8 = column0_row8 - (column0_row9 + column0_row9); + tempvar cpu__decode__flag_pc_update_regular_0 = 1 - (cpu__decode__opcode_rc__bit_7 + cpu__decode__opcode_rc__bit_8 + cpu__decode__opcode_rc__bit_9); + tempvar cpu__decode__opcode_rc__bit_12 = column0_row12 - (column0_row13 + column0_row13); + tempvar cpu__decode__opcode_rc__bit_13 = column0_row13 - (column0_row14 + column0_row14); + tempvar cpu__decode__fp_update_regular_0 = 1 - (cpu__decode__opcode_rc__bit_12 + cpu__decode__opcode_rc__bit_13); + tempvar cpu__decode__opcode_rc__bit_1 = column0_row1 - (column0_row2 + column0_row2); + tempvar npc_reg_0 = column4_row0 + cpu__decode__opcode_rc__bit_2 + 1; + tempvar cpu__decode__opcode_rc__bit_10 = column0_row10 - (column0_row11 + column0_row11); + tempvar cpu__decode__opcode_rc__bit_11 = column0_row11 - (column0_row12 + column0_row12); + tempvar cpu__decode__opcode_rc__bit_14 = column0_row14 - (column0_row15 + column0_row15); + tempvar memory__address_diff_0 = column5_row2 - column5_row0; + tempvar rc16__diff_0 = column6_row6 - column6_row2; + tempvar pedersen__hash0__ec_subset_sum__bit_0 = column6_row3 - (column6_row11 + column6_row11); + tempvar pedersen__hash0__ec_subset_sum__bit_neg_0 = 1 - pedersen__hash0__ec_subset_sum__bit_0; + tempvar rc_builtin__value0_0 = column6_row12; + tempvar rc_builtin__value1_0 = rc_builtin__value0_0 * global_values.offset_size + column6_row28; + tempvar rc_builtin__value2_0 = rc_builtin__value1_0 * global_values.offset_size + column6_row44; + tempvar rc_builtin__value3_0 = rc_builtin__value2_0 * global_values.offset_size + column6_row60; + tempvar rc_builtin__value4_0 = rc_builtin__value3_0 * global_values.offset_size + column6_row76; + tempvar rc_builtin__value5_0 = rc_builtin__value4_0 * global_values.offset_size + column6_row92; + tempvar rc_builtin__value6_0 = rc_builtin__value5_0 * global_values.offset_size + column6_row108; + tempvar rc_builtin__value7_0 = rc_builtin__value6_0 * global_values.offset_size + column6_row124; + tempvar bitwise__sum_var_0_0 = column1_row0 + column1_row4 * 2 + column1_row8 * 4 + column1_row12 * 8 + column1_row16 * 18446744073709551616 + column1_row20 * 36893488147419103232 + column1_row24 * 73786976294838206464 + column1_row28 * 147573952589676412928; + tempvar bitwise__sum_var_8_0 = column1_row32 * 340282366920938463463374607431768211456 + column1_row36 * 680564733841876926926749214863536422912 + column1_row40 * 1361129467683753853853498429727072845824 + column1_row44 * 2722258935367507707706996859454145691648 + column1_row48 * 6277101735386680763835789423207666416102355444464034512896 + column1_row52 * 12554203470773361527671578846415332832204710888928069025792 + column1_row56 * 25108406941546723055343157692830665664409421777856138051584 + column1_row60 * 50216813883093446110686315385661331328818843555712276103168; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances0_0 = column3_row16 - column3_row66320 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances0_2 = column3_row32 - column3_row66336 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances1_0 = column3_row66320 - column3_row132624 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances1_2 = column3_row66336 - column3_row132640 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances2_0 = column3_row132624 - column3_row198928 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances2_2 = column3_row132640 - column3_row198944 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances3_0 = column3_row198928 - column3_row265232 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances3_2 = column3_row198944 - column3_row265248 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances4_0 = column3_row265232 - column3_row331536 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances4_2 = column3_row265248 - column3_row331552 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances5_0 = column3_row331536 - column3_row397840 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances5_2 = column3_row331552 - column3_row397856 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances6_0 = column3_row397840 - column3_row464144 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances6_2 = column3_row397856 - column3_row464160 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances7_0 = column3_row464144 - column3_row6416 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__sum_words_over_instances7_2 = column3_row464160 - column3_row6432 * 1606938044258990275541962092341162602522202993782792835301376; + tempvar keccak__keccak__parse_to_diluted__partial_diluted1_0 = column3_row516112 - (column3_row272 + column3_row272); + tempvar keccak__keccak__parse_to_diluted__partial_diluted1_2 = column3_row516128 - (column3_row288 + column3_row288); + tempvar keccak__keccak__parse_to_diluted__bit_other1_0 = keccak__keccak__parse_to_diluted__partial_diluted1_2 - 16 * keccak__keccak__parse_to_diluted__partial_diluted1_0; + tempvar keccak__keccak__parse_to_diluted__partial_diluted1_30 = column3_row516352 - (column3_row512 + column3_row512); + tempvar keccak__keccak__parse_to_diluted__partial_diluted1_31 = column3_row516360 - (column3_row520 + column3_row520); + tempvar keccak__keccak__parse_to_diluted__partial_diluted0_0 = column3_row16 - (column3_row8208 + column3_row8208); + tempvar keccak__keccak__parse_to_diluted__partial_diluted0_2 = column3_row32 - (column3_row8224 + column3_row8224); + tempvar keccak__keccak__parse_to_diluted__bit_other0_0 = keccak__keccak__parse_to_diluted__partial_diluted0_2 - 16 * keccak__keccak__parse_to_diluted__partial_diluted0_0; + tempvar keccak__keccak__parse_to_diluted__partial_diluted0_30 = column3_row256 - (column3_row8448 + column3_row8448); + tempvar keccak__keccak__parse_to_diluted__partial_diluted0_31 = column3_row264 - (column3_row8456 + column3_row8456); + tempvar keccak__keccak__sum_parities0_0 = column1_row6593 + column3_row7760; + tempvar keccak__keccak__sum_parities1_0 = column1_row6406 + column3_row1876; + tempvar keccak__keccak__sum_parities1_64512 = column1_row522502 + column3_row517972; + tempvar keccak__keccak__sum_parities2_0 = column1_row6401 + column3_row7568; + tempvar keccak__keccak__sum_parities2_2048 = column1_row22785 + column3_row23952; + tempvar keccak__keccak__sum_parities3_0 = column1_row6405 + column3_row5972; + tempvar keccak__keccak__sum_parities3_36864 = column1_row301317 + column3_row300884; + tempvar keccak__keccak__sum_parities4_0 = column1_row6598 + column3_row3924; + tempvar keccak__keccak__sum_parities4_37888 = column1_row309702 + column3_row307028; + tempvar keccak__keccak__sum_parities0_28672 = column1_row235969 + column3_row237136; + tempvar keccak__keccak__sum_parities1_20480 = column1_row170246 + column3_row165716; + tempvar keccak__keccak__sum_parities2_59392 = column1_row481537 + column3_row482704; + tempvar keccak__keccak__sum_parities3_8 = column1_row6469 + column3_row6036; + tempvar keccak__keccak__sum_parities3_16 = column1_row6533 + column3_row6100; + tempvar keccak__keccak__sum_parities3_9216 = column1_row80133 + column3_row79700; + tempvar keccak__keccak__sum_parities3_9224 = column1_row80197 + column3_row79764; + tempvar keccak__keccak__sum_parities3_9232 = column1_row80261 + column3_row79828; + tempvar keccak__keccak__sum_parities4_45056 = column1_row367046 + column3_row364372; + tempvar keccak__keccak__sum_parities0_62464 = column1_row506305 + column3_row507472; + tempvar keccak__keccak__sum_parities1_55296 = column1_row448774 + column3_row444244; + tempvar keccak__keccak__sum_parities2_21504 = column1_row178433 + column3_row179600; + tempvar keccak__keccak__sum_parities3_39936 = column1_row325893 + column3_row325460; + tempvar keccak__keccak__sum_parities4_8 = column1_row6662 + column3_row3988; + tempvar keccak__keccak__sum_parities4_16 = column1_row6726 + column3_row4052; + tempvar keccak__keccak__sum_parities4_25600 = column1_row211398 + column3_row208724; + tempvar keccak__keccak__sum_parities4_25608 = column1_row211462 + column3_row208788; + tempvar keccak__keccak__sum_parities4_25616 = column1_row211526 + column3_row208852; + tempvar keccak__keccak__sum_parities0_8 = column1_row6657 + column3_row7824; + tempvar keccak__keccak__sum_parities0_16 = column1_row6721 + column3_row7888; + tempvar keccak__keccak__sum_parities0_23552 = column1_row195009 + column3_row196176; + tempvar keccak__keccak__sum_parities0_23560 = column1_row195073 + column3_row196240; + tempvar keccak__keccak__sum_parities0_23568 = column1_row195137 + column3_row196304; + tempvar keccak__keccak__sum_parities1_19456 = column1_row162054 + column3_row157524; + tempvar keccak__keccak__sum_parities2_50176 = column1_row407809 + column3_row408976; + tempvar keccak__keccak__sum_parities3_44032 = column1_row358661 + column3_row358228; + tempvar keccak__keccak__sum_parities4_57344 = column1_row465350 + column3_row462676; + tempvar keccak__keccak__sum_parities0_47104 = column1_row383425 + column3_row384592; + tempvar keccak__keccak__sum_parities1_8 = column1_row6470 + column3_row1940; + tempvar keccak__keccak__sum_parities1_16 = column1_row6534 + column3_row2004; + tempvar keccak__keccak__sum_parities1_63488 = column1_row514310 + column3_row509780; + tempvar keccak__keccak__sum_parities1_63496 = column1_row514374 + column3_row509844; + tempvar keccak__keccak__sum_parities1_63504 = column1_row514438 + column3_row509908; + tempvar keccak__keccak__sum_parities2_3072 = column1_row30977 + column3_row32144; + tempvar keccak__keccak__sum_parities3_8192 = column1_row71941 + column3_row71508; + tempvar keccak__keccak__sum_parities4_51200 = column1_row416198 + column3_row413524; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_32 = 1229782938247303441 - column1_row259; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_1056 = 1229782938247303441 - column1_row8451; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_3104 = 1229782938247303441 - column1_row24835; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_7200 = 1229782938247303441 - column1_row57603; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_15392 = 1229782938247303441 - column1_row123139; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_31776 = 1229782938247303441 - column1_row254211; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_64544 = 1229782938247303441 - column1_row516355; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_0 = 1229782938247303441 - column1_row3; + tempvar keccak__keccak__after_theta_rho_pi_xor_one_128 = 1229782938247303441 - column1_row1027; + + // Sum constraints. + tempvar total_sum = 0; + + // Constraint: cpu/decode/opcode_rc/bit. + tempvar value = (cpu__decode__opcode_rc__bit_0 * cpu__decode__opcode_rc__bit_0 - cpu__decode__opcode_rc__bit_0) * domain4 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[0] * value; + + // Constraint: cpu/decode/opcode_rc/zero. + tempvar value = (column0_row0) / domain4; + tempvar total_sum = total_sum + constraint_coefficients[1] * value; + + // Constraint: cpu/decode/opcode_rc_input. + tempvar value = (column4_row1 - (((column0_row0 * global_values.offset_size + column6_row4) * global_values.offset_size + column6_row8) * global_values.offset_size + column6_row0)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[2] * value; + + // Constraint: cpu/decode/flag_op1_base_op0_bit. + tempvar value = (cpu__decode__flag_op1_base_op0_0 * cpu__decode__flag_op1_base_op0_0 - cpu__decode__flag_op1_base_op0_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[3] * value; + + // Constraint: cpu/decode/flag_res_op1_bit. + tempvar value = (cpu__decode__flag_res_op1_0 * cpu__decode__flag_res_op1_0 - cpu__decode__flag_res_op1_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[4] * value; + + // Constraint: cpu/decode/flag_pc_update_regular_bit. + tempvar value = (cpu__decode__flag_pc_update_regular_0 * cpu__decode__flag_pc_update_regular_0 - cpu__decode__flag_pc_update_regular_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[5] * value; + + // Constraint: cpu/decode/fp_update_regular_bit. + tempvar value = (cpu__decode__fp_update_regular_0 * cpu__decode__fp_update_regular_0 - cpu__decode__fp_update_regular_0) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[6] * value; + + // Constraint: cpu/operands/mem_dst_addr. + tempvar value = (column4_row8 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_0 * column7_row8 + (1 - cpu__decode__opcode_rc__bit_0) * column7_row0 + column6_row0)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[7] * value; + + // Constraint: cpu/operands/mem0_addr. + tempvar value = (column4_row4 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_1 * column7_row8 + (1 - cpu__decode__opcode_rc__bit_1) * column7_row0 + column6_row8)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[8] * value; + + // Constraint: cpu/operands/mem1_addr. + tempvar value = (column4_row12 + global_values.half_offset_size - (cpu__decode__opcode_rc__bit_2 * column4_row0 + cpu__decode__opcode_rc__bit_4 * column7_row0 + cpu__decode__opcode_rc__bit_3 * column7_row8 + cpu__decode__flag_op1_base_op0_0 * column4_row5 + column6_row4)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[9] * value; + + // Constraint: cpu/operands/ops_mul. + tempvar value = (column7_row4 - column4_row5 * column4_row13) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[10] * value; + + // Constraint: cpu/operands/res. + tempvar value = ((1 - cpu__decode__opcode_rc__bit_9) * column7_row12 - (cpu__decode__opcode_rc__bit_5 * (column4_row5 + column4_row13) + cpu__decode__opcode_rc__bit_6 * column7_row4 + cpu__decode__flag_res_op1_0 * column4_row13)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[11] * value; + + // Constraint: cpu/update_registers/update_pc/tmp0. + tempvar value = (column7_row2 - cpu__decode__opcode_rc__bit_9 * column4_row9) * domain131 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[12] * value; + + // Constraint: cpu/update_registers/update_pc/tmp1. + tempvar value = (column7_row10 - column7_row2 * column7_row12) * domain131 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[13] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_negative. + tempvar value = ((1 - cpu__decode__opcode_rc__bit_9) * column4_row16 + column7_row2 * (column4_row16 - (column4_row0 + column4_row13)) - (cpu__decode__flag_pc_update_regular_0 * npc_reg_0 + cpu__decode__opcode_rc__bit_7 * column7_row12 + cpu__decode__opcode_rc__bit_8 * (column4_row0 + column7_row12))) * domain131 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[14] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_positive. + tempvar value = ((column7_row10 - cpu__decode__opcode_rc__bit_9) * (column4_row16 - npc_reg_0)) * domain131 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[15] * value; + + // Constraint: cpu/update_registers/update_ap/ap_update. + tempvar value = (column7_row16 - (column7_row0 + cpu__decode__opcode_rc__bit_10 * column7_row12 + cpu__decode__opcode_rc__bit_11 + cpu__decode__opcode_rc__bit_12 * 2)) * domain131 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[16] * value; + + // Constraint: cpu/update_registers/update_fp/fp_update. + tempvar value = (column7_row24 - (cpu__decode__fp_update_regular_0 * column7_row8 + cpu__decode__opcode_rc__bit_13 * column4_row9 + cpu__decode__opcode_rc__bit_12 * (column7_row0 + 2))) * domain131 / domain5; + tempvar total_sum = total_sum + constraint_coefficients[17] * value; + + // Constraint: cpu/opcodes/call/push_fp. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column4_row9 - column7_row8)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[18] * value; + + // Constraint: cpu/opcodes/call/push_pc. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column4_row5 - (column4_row0 + cpu__decode__opcode_rc__bit_2 + 1))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[19] * value; + + // Constraint: cpu/opcodes/call/off0. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column6_row0 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[20] * value; + + // Constraint: cpu/opcodes/call/off1. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (column6_row8 - (global_values.half_offset_size + 1))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[21] * value; + + // Constraint: cpu/opcodes/call/flags. + tempvar value = (cpu__decode__opcode_rc__bit_12 * (cpu__decode__opcode_rc__bit_12 + cpu__decode__opcode_rc__bit_12 + 1 + 1 - (cpu__decode__opcode_rc__bit_0 + cpu__decode__opcode_rc__bit_1 + 4))) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[22] * value; + + // Constraint: cpu/opcodes/ret/off0. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (column6_row0 + 2 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[23] * value; + + // Constraint: cpu/opcodes/ret/off2. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (column6_row4 + 1 - global_values.half_offset_size)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[24] * value; + + // Constraint: cpu/opcodes/ret/flags. + tempvar value = (cpu__decode__opcode_rc__bit_13 * (cpu__decode__opcode_rc__bit_7 + cpu__decode__opcode_rc__bit_0 + cpu__decode__opcode_rc__bit_3 + cpu__decode__flag_res_op1_0 - 4)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[25] * value; + + // Constraint: cpu/opcodes/assert_eq/assert_eq. + tempvar value = (cpu__decode__opcode_rc__bit_14 * (column4_row9 - column7_row12)) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[26] * value; + + // Constraint: initial_ap. + tempvar value = (column7_row0 - global_values.initial_ap) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[27] * value; + + // Constraint: initial_fp. + tempvar value = (column7_row8 - global_values.initial_ap) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[28] * value; + + // Constraint: initial_pc. + tempvar value = (column4_row0 - global_values.initial_pc) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[29] * value; + + // Constraint: final_ap. + tempvar value = (column7_row0 - global_values.final_ap) / domain131; + tempvar total_sum = total_sum + constraint_coefficients[30] * value; + + // Constraint: final_fp. + tempvar value = (column7_row8 - global_values.initial_ap) / domain131; + tempvar total_sum = total_sum + constraint_coefficients[31] * value; + + // Constraint: final_pc. + tempvar value = (column4_row0 - global_values.final_pc) / domain131; + tempvar total_sum = total_sum + constraint_coefficients[32] * value; + + // Constraint: memory/multi_column_perm/perm/init0. + tempvar value = ((global_values.memory__multi_column_perm__perm__interaction_elm - (column5_row0 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column5_row1)) * column10_inter1_row0 + column4_row0 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column4_row1 - global_values.memory__multi_column_perm__perm__interaction_elm) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[33] * value; + + // Constraint: memory/multi_column_perm/perm/step0. + tempvar value = ((global_values.memory__multi_column_perm__perm__interaction_elm - (column5_row2 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column5_row3)) * column10_inter1_row2 - (global_values.memory__multi_column_perm__perm__interaction_elm - (column4_row2 + global_values.memory__multi_column_perm__hash_interaction_elm0 * column4_row3)) * column10_inter1_row0) * domain133 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[34] * value; + + // Constraint: memory/multi_column_perm/perm/last. + tempvar value = (column10_inter1_row0 - global_values.memory__multi_column_perm__perm__public_memory_prod) / domain133; + tempvar total_sum = total_sum + constraint_coefficients[35] * value; + + // Constraint: memory/diff_is_bit. + tempvar value = (memory__address_diff_0 * memory__address_diff_0 - memory__address_diff_0) * domain133 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[36] * value; + + // Constraint: memory/is_func. + tempvar value = ((memory__address_diff_0 - 1) * (column5_row1 - column5_row3)) * domain133 / domain1; + tempvar total_sum = total_sum + constraint_coefficients[37] * value; + + // Constraint: memory/initial_addr. + tempvar value = (column5_row0 - 1) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[38] * value; + + // Constraint: public_memory_addr_zero. + tempvar value = (column4_row2) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[39] * value; + + // Constraint: public_memory_value_zero. + tempvar value = (column4_row3) / domain5; + tempvar total_sum = total_sum + constraint_coefficients[40] * value; + + // Constraint: rc16/perm/init0. + tempvar value = ((global_values.rc16__perm__interaction_elm - column6_row2) * column10_inter1_row1 + column6_row0 - global_values.rc16__perm__interaction_elm) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[41] * value; + + // Constraint: rc16/perm/step0. + tempvar value = ((global_values.rc16__perm__interaction_elm - column6_row6) * column10_inter1_row5 - (global_values.rc16__perm__interaction_elm - column6_row4) * column10_inter1_row1) * domain134 / domain2; + tempvar total_sum = total_sum + constraint_coefficients[42] * value; + + // Constraint: rc16/perm/last. + tempvar value = (column10_inter1_row1 - global_values.rc16__perm__public_memory_prod) / domain134; + tempvar total_sum = total_sum + constraint_coefficients[43] * value; + + // Constraint: rc16/diff_is_bit. + tempvar value = (rc16__diff_0 * rc16__diff_0 - rc16__diff_0) * domain134 / domain2; + tempvar total_sum = total_sum + constraint_coefficients[44] * value; + + // Constraint: rc16/minimum. + tempvar value = (column6_row2 - global_values.rc_min) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[45] * value; + + // Constraint: rc16/maximum. + tempvar value = (column6_row2 - global_values.rc_max) / domain134; + tempvar total_sum = total_sum + constraint_coefficients[46] * value; + + // Constraint: diluted_check/permutation/init0. + tempvar value = ((global_values.diluted_check__permutation__interaction_elm - column2_row0) * column9_inter1_row0 + column1_row0 - global_values.diluted_check__permutation__interaction_elm) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[47] * value; + + // Constraint: diluted_check/permutation/step0. + tempvar value = ((global_values.diluted_check__permutation__interaction_elm - column2_row1) * column9_inter1_row1 - (global_values.diluted_check__permutation__interaction_elm - column1_row1) * column9_inter1_row0) * domain135 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[48] * value; + + // Constraint: diluted_check/permutation/last. + tempvar value = (column9_inter1_row0 - global_values.diluted_check__permutation__public_memory_prod) / domain135; + tempvar total_sum = total_sum + constraint_coefficients[49] * value; + + // Constraint: diluted_check/init. + tempvar value = (column8_inter1_row0 - 1) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[50] * value; + + // Constraint: diluted_check/first_element. + tempvar value = (column2_row0 - global_values.diluted_check__first_elm) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[51] * value; + + // Constraint: diluted_check/step. + tempvar value = (column8_inter1_row1 - (column8_inter1_row0 * (1 + global_values.diluted_check__interaction_z * (column2_row1 - column2_row0)) + global_values.diluted_check__interaction_alpha * (column2_row1 - column2_row0) * (column2_row1 - column2_row0))) * domain135 / domain0; + tempvar total_sum = total_sum + constraint_coefficients[52] * value; + + // Constraint: diluted_check/last. + tempvar value = (column8_inter1_row0 - global_values.diluted_check__final_cum_val) / domain135; + tempvar total_sum = total_sum + constraint_coefficients[53] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/last_one_is_zero. + tempvar value = (column3_row20 * (column6_row3 - (column6_row11 + column6_row11))) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[54] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + tempvar value = (column3_row20 * (column6_row11 - 3138550867693340381917894711603833208051177722232017256448 * column6_row1539)) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[55] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit192. + tempvar value = (column3_row20 - column6_row2047 * (column6_row1539 - (column6_row1547 + column6_row1547))) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[56] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + tempvar value = (column6_row2047 * (column6_row1547 - 8 * column6_row1571)) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[57] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit196. + tempvar value = (column6_row2047 - (column6_row2011 - (column6_row2019 + column6_row2019)) * (column6_row1571 - (column6_row1579 + column6_row1579))) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[58] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + tempvar value = ((column6_row2011 - (column6_row2019 + column6_row2019)) * (column6_row1579 - 18014398509481984 * column6_row2011)) / domain12; + tempvar total_sum = total_sum + constraint_coefficients[59] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/booleanity_test. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (pedersen__hash0__ec_subset_sum__bit_0 - 1)) * domain13 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[60] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_extraction_end. + tempvar value = (column6_row3) / domain14; + tempvar total_sum = total_sum + constraint_coefficients[61] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/zeros_tail. + tempvar value = (column6_row3) / domain13; + tempvar total_sum = total_sum + constraint_coefficients[62] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/slope. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (column6_row5 - global_values.pedersen__points__y) - column6_row7 * (column6_row1 - global_values.pedersen__points__x)) * domain13 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[63] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/x. + tempvar value = (column6_row7 * column6_row7 - pedersen__hash0__ec_subset_sum__bit_0 * (column6_row1 + global_values.pedersen__points__x + column6_row9)) * domain13 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[64] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/y. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_0 * (column6_row5 + column6_row13) - column6_row7 * (column6_row1 - column6_row9)) * domain13 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[65] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/x. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_neg_0 * (column6_row9 - column6_row1)) * domain13 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[66] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/y. + tempvar value = (pedersen__hash0__ec_subset_sum__bit_neg_0 * (column6_row13 - column6_row5)) * domain13 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[67] * value; + + // Constraint: pedersen/hash0/copy_point/x. + tempvar value = (column6_row2049 - column6_row2041) * domain15 / domain12; + tempvar total_sum = total_sum + constraint_coefficients[68] * value; + + // Constraint: pedersen/hash0/copy_point/y. + tempvar value = (column6_row2053 - column6_row2045) * domain15 / domain12; + tempvar total_sum = total_sum + constraint_coefficients[69] * value; + + // Constraint: pedersen/hash0/init/x. + tempvar value = (column6_row1 - global_values.pedersen__shift_point.x) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[70] * value; + + // Constraint: pedersen/hash0/init/y. + tempvar value = (column6_row5 - global_values.pedersen__shift_point.y) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[71] * value; + + // Constraint: pedersen/input0_value0. + tempvar value = (column4_row11 - column6_row3) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[72] * value; + + // Constraint: pedersen/input0_addr. + tempvar value = (column4_row4106 - (column4_row1034 + 1)) * domain136 / domain16; + tempvar total_sum = total_sum + constraint_coefficients[73] * value; + + // Constraint: pedersen/init_addr. + tempvar value = (column4_row10 - global_values.initial_pedersen_addr) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[74] * value; + + // Constraint: pedersen/input1_value0. + tempvar value = (column4_row2059 - column6_row2051) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[75] * value; + + // Constraint: pedersen/input1_addr. + tempvar value = (column4_row2058 - (column4_row10 + 1)) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[76] * value; + + // Constraint: pedersen/output_value0. + tempvar value = (column4_row1035 - column6_row4089) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[77] * value; + + // Constraint: pedersen/output_addr. + tempvar value = (column4_row1034 - (column4_row2058 + 1)) / domain16; + tempvar total_sum = total_sum + constraint_coefficients[78] * value; + + // Constraint: rc_builtin/value. + tempvar value = (rc_builtin__value7_0 - column4_row75) / domain7; + tempvar total_sum = total_sum + constraint_coefficients[79] * value; + + // Constraint: rc_builtin/addr_step. + tempvar value = (column4_row202 - (column4_row74 + 1)) * domain137 / domain7; + tempvar total_sum = total_sum + constraint_coefficients[80] * value; + + // Constraint: rc_builtin/init_addr. + tempvar value = (column4_row74 - global_values.initial_rc_addr) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[81] * value; + + // Constraint: bitwise/init_var_pool_addr. + tempvar value = (column4_row42 - global_values.initial_bitwise_addr) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[82] * value; + + // Constraint: bitwise/step_var_pool_addr. + tempvar value = (column4_row106 - (column4_row42 + 1)) * domain8 / domain6; + tempvar total_sum = total_sum + constraint_coefficients[83] * value; + + // Constraint: bitwise/x_or_y_addr. + tempvar value = (column4_row138 - (column4_row234 + 1)) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[84] * value; + + // Constraint: bitwise/next_var_pool_addr. + tempvar value = (column4_row298 - (column4_row138 + 1)) * domain138 / domain9; + tempvar total_sum = total_sum + constraint_coefficients[85] * value; + + // Constraint: bitwise/partition. + tempvar value = (bitwise__sum_var_0_0 + bitwise__sum_var_8_0 - column4_row43) / domain6; + tempvar total_sum = total_sum + constraint_coefficients[86] * value; + + // Constraint: bitwise/or_is_and_plus_xor. + tempvar value = (column4_row139 - (column4_row171 + column4_row235)) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[87] * value; + + // Constraint: bitwise/addition_is_xor_with_and. + tempvar value = (column1_row0 + column1_row64 - (column1_row192 + column1_row128 + column1_row128)) / domain11; + tempvar total_sum = total_sum + constraint_coefficients[88] * value; + + // Constraint: bitwise/unique_unpacking192. + tempvar value = ((column1_row176 + column1_row240) * 16 - column1_row2) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[89] * value; + + // Constraint: bitwise/unique_unpacking193. + tempvar value = ((column1_row180 + column1_row244) * 16 - column1_row130) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[90] * value; + + // Constraint: bitwise/unique_unpacking194. + tempvar value = ((column1_row184 + column1_row248) * 16 - column1_row66) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[91] * value; + + // Constraint: bitwise/unique_unpacking195. + tempvar value = ((column1_row188 + column1_row252) * 256 - column1_row194) / domain9; + tempvar total_sum = total_sum + constraint_coefficients[92] * value; + + // Constraint: keccak/init_input_output_addr. + tempvar value = (column4_row522 - global_values.initial_keccak_addr) / domain132; + tempvar total_sum = total_sum + constraint_coefficients[93] * value; + + // Constraint: keccak/addr_input_output_step. + tempvar value = (column4_row2570 - (column4_row522 + 1)) * domain139 / domain12; + tempvar total_sum = total_sum + constraint_coefficients[94] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate0_w0. + tempvar value = (column4_row523 - column3_row0) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[95] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate0_w1. + tempvar value = (column4_row2571 - column3_row1) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[96] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate0_w2. + tempvar value = (column4_row4619 - column3_row2) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[97] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate0_w3. + tempvar value = (column4_row6667 - column3_row3) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[98] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate0_w4. + tempvar value = (column4_row8715 - column3_row4) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[99] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate0_w5. + tempvar value = (column4_row10763 - column3_row5) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[100] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate0_w6. + tempvar value = (column4_row12811 - column3_row6) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[101] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate0_w7. + tempvar value = (column4_row14859 - column3_row7) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[102] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate1_w0. + tempvar value = (column4_row16907 - column3_row8) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[103] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate1_w1. + tempvar value = (column4_row18955 - column3_row9) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[104] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate1_w2. + tempvar value = (column4_row21003 - column3_row10) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[105] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate1_w3. + tempvar value = (column4_row23051 - column3_row11) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[106] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate1_w4. + tempvar value = (column4_row25099 - column3_row12) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[107] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate1_w5. + tempvar value = (column4_row27147 - column3_row13) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[108] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate1_w6. + tempvar value = (column4_row29195 - column3_row14) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[109] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_intermediate1_w7. + tempvar value = (column4_row31243 - column3_row15) / domain21; + tempvar total_sum = total_sum + constraint_coefficients[110] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final0. + tempvar value = (column3_row0 - column3_row16144) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[111] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final1. + tempvar value = (column3_row32768 - column3_row16160) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[112] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final2. + tempvar value = (column3_row65536 - column3_row16176) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[113] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final3. + tempvar value = (column3_row98304 - column3_row16192) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[114] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final4. + tempvar value = (column3_row131072 - column3_row16208) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[115] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final5. + tempvar value = (column3_row163840 - column3_row16224) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[116] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final6. + tempvar value = (column3_row196608 - column3_row16240) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[117] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final7. + tempvar value = (column3_row229376 - column3_row16256) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[118] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final8. + tempvar value = (column3_row262144 - column3_row16272) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[119] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final9. + tempvar value = (column3_row294912 - column3_row16288) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[120] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final10. + tempvar value = (column3_row327680 - column3_row16304) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[121] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final11. + tempvar value = (column3_row360448 - column3_row16320) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[122] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final12. + tempvar value = (column3_row393216 - column3_row16336) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[123] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final13. + tempvar value = (column3_row425984 - column3_row16352) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[124] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final14. + tempvar value = (column3_row458752 - column3_row16368) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[125] * value; + + // Constraint: keccak/keccak/parse_to_diluted/reshape_final15. + tempvar value = (column3_row491520 - column3_row16384) / domain24; + tempvar total_sum = total_sum + constraint_coefficients[126] * value; + + // Constraint: keccak/keccak/parse_to_diluted/start_accumulation. + tempvar value = (column3_row6416) / domain28; + tempvar total_sum = total_sum + constraint_coefficients[127] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_first_invocation0. + tempvar value = (column3_row16144 - keccak__keccak__parse_to_diluted__sum_words_over_instances0_0) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[128] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_other_invocations0. + tempvar value = (column3_row16160 + keccak__keccak__parse_to_diluted__sum_words_over_instances0_0 * 16 - keccak__keccak__parse_to_diluted__sum_words_over_instances0_2) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[129] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_first_invocation1. + tempvar value = (column3_row16145 - keccak__keccak__parse_to_diluted__sum_words_over_instances1_0) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[130] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_other_invocations1. + tempvar value = (column3_row16161 + keccak__keccak__parse_to_diluted__sum_words_over_instances1_0 * 16 - keccak__keccak__parse_to_diluted__sum_words_over_instances1_2) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[131] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_first_invocation2. + tempvar value = (column3_row16146 - keccak__keccak__parse_to_diluted__sum_words_over_instances2_0) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[132] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_other_invocations2. + tempvar value = (column3_row16162 + keccak__keccak__parse_to_diluted__sum_words_over_instances2_0 * 16 - keccak__keccak__parse_to_diluted__sum_words_over_instances2_2) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[133] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_first_invocation3. + tempvar value = (column3_row16147 - keccak__keccak__parse_to_diluted__sum_words_over_instances3_0) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[134] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_other_invocations3. + tempvar value = (column3_row16163 + keccak__keccak__parse_to_diluted__sum_words_over_instances3_0 * 16 - keccak__keccak__parse_to_diluted__sum_words_over_instances3_2) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[135] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_first_invocation4. + tempvar value = (column3_row16148 - keccak__keccak__parse_to_diluted__sum_words_over_instances4_0) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[136] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_other_invocations4. + tempvar value = (column3_row16164 + keccak__keccak__parse_to_diluted__sum_words_over_instances4_0 * 16 - keccak__keccak__parse_to_diluted__sum_words_over_instances4_2) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[137] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_first_invocation5. + tempvar value = (column3_row16149 - keccak__keccak__parse_to_diluted__sum_words_over_instances5_0) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[138] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_other_invocations5. + tempvar value = (column3_row16165 + keccak__keccak__parse_to_diluted__sum_words_over_instances5_0 * 16 - keccak__keccak__parse_to_diluted__sum_words_over_instances5_2) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[139] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_first_invocation6. + tempvar value = (column3_row16150 - keccak__keccak__parse_to_diluted__sum_words_over_instances6_0) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[140] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_other_invocations6. + tempvar value = (column3_row16166 + keccak__keccak__parse_to_diluted__sum_words_over_instances6_0 * 16 - keccak__keccak__parse_to_diluted__sum_words_over_instances6_2) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[141] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_first_invocation7. + tempvar value = (column3_row16151 - keccak__keccak__parse_to_diluted__sum_words_over_instances7_0) / domain23; + tempvar total_sum = total_sum + constraint_coefficients[142] * value; + + // Constraint: keccak/keccak/parse_to_diluted/init_other_invocations7. + tempvar value = (column3_row16167 + keccak__keccak__parse_to_diluted__sum_words_over_instances7_0 * 16 - keccak__keccak__parse_to_diluted__sum_words_over_instances7_2) / domain27; + tempvar total_sum = total_sum + constraint_coefficients[143] * value; + + // Constraint: keccak/keccak/parse_to_diluted/extract_bit_first_invocation1. + tempvar value = (keccak__keccak__parse_to_diluted__partial_diluted1_0 * keccak__keccak__parse_to_diluted__partial_diluted1_0 - keccak__keccak__parse_to_diluted__partial_diluted1_0) / domain31; + tempvar total_sum = total_sum + constraint_coefficients[144] * value; + + // Constraint: keccak/keccak/parse_to_diluted/extract_bit_other_invocations1. + tempvar value = (keccak__keccak__parse_to_diluted__bit_other1_0 * keccak__keccak__parse_to_diluted__bit_other1_0 - keccak__keccak__parse_to_diluted__bit_other1_0) / domain32; + tempvar total_sum = total_sum + constraint_coefficients[145] * value; + + // Constraint: keccak/keccak/parse_to_diluted/to_diluted0_p1. + tempvar value = (keccak__keccak__parse_to_diluted__partial_diluted1_30 - column1_row516102) / domain33; + tempvar total_sum = total_sum + constraint_coefficients[146] * value; + + // Constraint: keccak/keccak/parse_to_diluted/to_diluted1_p1. + tempvar value = (keccak__keccak__parse_to_diluted__partial_diluted1_31 - column1_row516294) / domain33; + tempvar total_sum = total_sum + constraint_coefficients[147] * value; + + // Constraint: keccak/keccak/parse_to_diluted/extract_bit_first_invocation0. + tempvar value = (keccak__keccak__parse_to_diluted__partial_diluted0_0 * keccak__keccak__parse_to_diluted__partial_diluted0_0 - keccak__keccak__parse_to_diluted__partial_diluted0_0) * domain37 / domain10; + tempvar total_sum = total_sum + constraint_coefficients[148] * value; + + // Constraint: keccak/keccak/parse_to_diluted/extract_bit_other_invocations0. + tempvar value = (keccak__keccak__parse_to_diluted__bit_other0_0 * keccak__keccak__parse_to_diluted__bit_other0_0 - keccak__keccak__parse_to_diluted__bit_other0_0) * domain40 / domain3; + tempvar total_sum = total_sum + constraint_coefficients[149] * value; + + // Constraint: keccak/keccak/parse_to_diluted/to_diluted0_p0. + tempvar value = (keccak__keccak__parse_to_diluted__partial_diluted0_30 - column1_row6) * domain41 / domain9; + tempvar total_sum = total_sum + constraint_coefficients[150] * value; + + // Constraint: keccak/keccak/parse_to_diluted/to_diluted1_p0. + tempvar value = (keccak__keccak__parse_to_diluted__partial_diluted0_31 - column1_row198) * domain41 / domain9; + tempvar total_sum = total_sum + constraint_coefficients[151] * value; + + // Constraint: keccak/keccak/parity0. + tempvar value = (column1_row6 + column1_row1286 + column1_row2566 + column1_row3846 + column1_row5126 - (column1_row6406 + column1_row6597 + column1_row6597 + column1_row6977 * 4)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[152] * value; + + // Constraint: keccak/keccak/parity1. + tempvar value = (column1_row262 + column1_row1542 + column1_row2822 + column1_row4102 + column1_row5382 - (column1_row6401 + column1_row6790 + column1_row6790 + column1_row6981 * 4)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[153] * value; + + // Constraint: keccak/keccak/parity2. + tempvar value = (column1_row518 + column1_row1798 + column1_row3078 + column1_row4358 + column1_row5638 - (column1_row6405 + column1_row6785 + column1_row6785 + column1_row7174 * 4)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[154] * value; + + // Constraint: keccak/keccak/parity3. + tempvar value = (column1_row774 + column1_row2054 + column1_row3334 + column1_row4614 + column1_row5894 - (column1_row6598 + column1_row6789 + column1_row6789 + column1_row7169 * 4)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[155] * value; + + // Constraint: keccak/keccak/parity4. + tempvar value = (column1_row1030 + column1_row2310 + column1_row3590 + column1_row4870 + column1_row6150 - (column1_row6593 + column1_row6982 + column1_row6982 + column1_row7173 * 4)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[156] * value; + + // Constraint: keccak/keccak/rotate_parity0/n0. + tempvar value = (column3_row3924 - column1_row522502) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[157] * value; + + // Constraint: keccak/keccak/rotate_parity0/n1. + tempvar value = (column3_row12116 - column1_row6406) * domain43 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[158] * value; + + // Constraint: keccak/keccak/rotate_parity1/n0. + tempvar value = (column3_row7760 - column1_row522497) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[159] * value; + + // Constraint: keccak/keccak/rotate_parity1/n1. + tempvar value = (column3_row15952 - column1_row6401) * domain43 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[160] * value; + + // Constraint: keccak/keccak/rotate_parity2/n0. + tempvar value = (column3_row1876 - column1_row522501) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[161] * value; + + // Constraint: keccak/keccak/rotate_parity2/n1. + tempvar value = (column3_row10068 - column1_row6405) * domain43 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[162] * value; + + // Constraint: keccak/keccak/rotate_parity3/n0. + tempvar value = (column3_row7568 - column1_row522694) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[163] * value; + + // Constraint: keccak/keccak/rotate_parity3/n1. + tempvar value = (column3_row15760 - column1_row6598) * domain43 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[164] * value; + + // Constraint: keccak/keccak/rotate_parity4/n0. + tempvar value = (column3_row5972 - column1_row522689) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[165] * value; + + // Constraint: keccak/keccak/rotate_parity4/n1. + tempvar value = (column3_row14164 - column1_row6593) * domain43 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[166] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j0. + tempvar value = (keccak__keccak__sum_parities0_0 + column1_row6 - (column1_row3 + column1_row7366 + column1_row7366)) / domain18; + tempvar total_sum = total_sum + constraint_coefficients[167] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j1/n0. + tempvar value = (keccak__keccak__sum_parities1_0 + column1_row262 - (column1_row10755 + column1_row15941 + column1_row15941)) * domain43 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[168] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j1/n1. + tempvar value = (keccak__keccak__sum_parities1_64512 + column1_row516358 - (column1_row2563 + column1_row7749 + column1_row7749)) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[169] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j2/n0. + tempvar value = (keccak__keccak__sum_parities2_0 + column1_row518 - (column1_row513027 + column1_row515843 + column1_row515843)) / domain45; + tempvar total_sum = total_sum + constraint_coefficients[170] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j2/n1. + tempvar value = (keccak__keccak__sum_parities2_2048 + column1_row16902 - (column1_row5123 + column1_row7939 + column1_row7939)) * domain47 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[171] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j3/n0. + tempvar value = (keccak__keccak__sum_parities3_0 + column1_row774 - (column1_row230659 + column1_row236929 + column1_row236929)) * domain73 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[172] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j3/n1. + tempvar value = (keccak__keccak__sum_parities3_36864 + column1_row295686 - (column1_row1283 + column1_row7553 + column1_row7553)) / domain105; + tempvar total_sum = total_sum + constraint_coefficients[173] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j4/n0. + tempvar value = (keccak__keccak__sum_parities4_0 + column1_row1030 - (column1_row225027 + column1_row228163 + column1_row228163)) * domain72 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[174] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i0_j4/n1. + tempvar value = (keccak__keccak__sum_parities4_37888 + column1_row304134 - (column1_row3843 + column1_row6979 + column1_row6979)) / domain104; + tempvar total_sum = total_sum + constraint_coefficients[175] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j0/n0. + tempvar value = (keccak__keccak__sum_parities0_0 + column1_row1286 - (column1_row299011 + column1_row302083 + column1_row302083)) / domain105; + tempvar total_sum = total_sum + constraint_coefficients[176] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j0/n1. + tempvar value = (keccak__keccak__sum_parities0_28672 + column1_row230662 - (column1_row4099 + column1_row7171 + column1_row7171)) * domain73 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[177] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j1/n0. + tempvar value = (keccak__keccak__sum_parities1_0 + column1_row1542 - (column1_row360707 + column1_row367809 + column1_row367809)) / domain98; + tempvar total_sum = total_sum + constraint_coefficients[178] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j1/n1. + tempvar value = (keccak__keccak__sum_parities1_20480 + column1_row165382 - (column1_row259 + column1_row7361 + column1_row7361)) * domain66 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[179] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j2/n0. + tempvar value = (keccak__keccak__sum_parities2_0 + column1_row1798 - (column1_row51971 + column1_row55939 + column1_row55939)) * domain51 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[180] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j2/n1. + tempvar value = (keccak__keccak__sum_parities2_59392 + column1_row476934 - (column1_row2819 + column1_row6787 + column1_row6787)) / domain79; + tempvar total_sum = total_sum + constraint_coefficients[181] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j3/n0. + tempvar value = (keccak__keccak__sum_parities3_0 + column1_row2054 - (column1_row455939 + column1_row450755 + column1_row450755)) / domain108; + tempvar total_sum = total_sum + constraint_coefficients[182] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j3/n1. + tempvar value = (keccak__keccak__sum_parities3_8 + column1_row2118 - (column1_row456003 + column1_row451011 + column1_row451011)) / domain108; + tempvar total_sum = total_sum + constraint_coefficients[183] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j3/n2. + tempvar value = (keccak__keccak__sum_parities3_16 + column1_row2182 - (column1_row456067 + column1_row451267 + column1_row451267)) / domain108; + tempvar total_sum = total_sum + constraint_coefficients[184] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j3/n3. + tempvar value = (keccak__keccak__sum_parities3_9216 + column1_row75782 - (column1_row5379 + column1_row195 + column1_row195)) * domain111 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[185] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j3/n4. + tempvar value = (keccak__keccak__sum_parities3_9224 + column1_row75846 - (column1_row5443 + column1_row451 + column1_row451)) * domain111 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[186] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j3/n5. + tempvar value = (keccak__keccak__sum_parities3_9232 + column1_row75910 - (column1_row5507 + column1_row707 + column1_row707)) * domain111 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[187] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j4/n0. + tempvar value = (keccak__keccak__sum_parities4_0 + column1_row2310 - (column1_row165379 + column1_row171397 + column1_row171397)) * domain66 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[188] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i1_j4/n1. + tempvar value = (keccak__keccak__sum_parities4_45056 + column1_row362758 - (column1_row1539 + column1_row7557 + column1_row7557)) / domain98; + tempvar total_sum = total_sum + constraint_coefficients[189] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j0/n0. + tempvar value = (keccak__keccak__sum_parities0_0 + column1_row2566 - (column1_row26371 + column1_row31171 + column1_row31171)) * domain112 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[190] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j0/n1. + tempvar value = (keccak__keccak__sum_parities0_62464 + column1_row502278 - (column1_row1795 + column1_row6595 + column1_row6595)) / domain113; + tempvar total_sum = total_sum + constraint_coefficients[191] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j1/n0. + tempvar value = (keccak__keccak__sum_parities1_0 + column1_row2822 - (column1_row86275 + column1_row89283 + column1_row89283)) * domain56 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[192] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j1/n1. + tempvar value = (keccak__keccak__sum_parities1_55296 + column1_row445190 - (column1_row4355 + column1_row7363 + column1_row7363)) / domain86; + tempvar total_sum = total_sum + constraint_coefficients[193] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j2/n0. + tempvar value = (keccak__keccak__sum_parities2_0 + column1_row3078 - (column1_row352771 + column1_row359621 + column1_row359621)) / domain100; + tempvar total_sum = total_sum + constraint_coefficients[194] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j2/n1. + tempvar value = (keccak__keccak__sum_parities2_21504 + column1_row175110 - (column1_row515 + column1_row7365 + column1_row7365)) * domain68 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[195] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j3/n0. + tempvar value = (keccak__keccak__sum_parities3_0 + column1_row3334 - (column1_row207875 + column1_row212742 + column1_row212742)) * domain71 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[196] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j3/n1. + tempvar value = (keccak__keccak__sum_parities3_39936 + column1_row322822 - (column1_row3075 + column1_row7942 + column1_row7942)) / domain103; + tempvar total_sum = total_sum + constraint_coefficients[197] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j4/n0. + tempvar value = (keccak__keccak__sum_parities4_0 + column1_row3590 - (column1_row325123 + column1_row320451 + column1_row320451)) / domain115; + tempvar total_sum = total_sum + constraint_coefficients[198] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j4/n1. + tempvar value = (keccak__keccak__sum_parities4_8 + column1_row3654 - (column1_row325187 + column1_row320707 + column1_row320707)) / domain115; + tempvar total_sum = total_sum + constraint_coefficients[199] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j4/n2. + tempvar value = (keccak__keccak__sum_parities4_16 + column1_row3718 - (column1_row325251 + column1_row320963 + column1_row320963)) / domain115; + tempvar total_sum = total_sum + constraint_coefficients[200] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j4/n3. + tempvar value = (keccak__keccak__sum_parities4_25600 + column1_row208390 - (column1_row5635 + column1_row963 + column1_row963)) * domain117 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[201] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j4/n4. + tempvar value = (keccak__keccak__sum_parities4_25608 + column1_row208454 - (column1_row5699 + column1_row1219 + column1_row1219)) * domain117 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[202] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i2_j4/n5. + tempvar value = (keccak__keccak__sum_parities4_25616 + column1_row208518 - (column1_row5763 + column1_row1475 + column1_row1475)) * domain117 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[203] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j0/n0. + tempvar value = (keccak__keccak__sum_parities0_0 + column1_row3846 - (column1_row341763 + column1_row337603 + column1_row337603)) / domain118; + tempvar total_sum = total_sum + constraint_coefficients[204] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j0/n1. + tempvar value = (keccak__keccak__sum_parities0_8 + column1_row3910 - (column1_row341827 + column1_row337859 + column1_row337859)) / domain118; + tempvar total_sum = total_sum + constraint_coefficients[205] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j0/n2. + tempvar value = (keccak__keccak__sum_parities0_16 + column1_row3974 - (column1_row341891 + column1_row338115 + column1_row338115)) / domain118; + tempvar total_sum = total_sum + constraint_coefficients[206] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j0/n3. + tempvar value = (keccak__keccak__sum_parities0_23552 + column1_row192262 - (column1_row5891 + column1_row1731 + column1_row1731)) * domain119 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[207] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j0/n4. + tempvar value = (keccak__keccak__sum_parities0_23560 + column1_row192326 - (column1_row5955 + column1_row1987 + column1_row1987)) * domain119 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[208] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j0/n5. + tempvar value = (keccak__keccak__sum_parities0_23568 + column1_row192390 - (column1_row6019 + column1_row2243 + column1_row2243)) * domain119 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[209] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j1/n0. + tempvar value = (keccak__keccak__sum_parities1_0 + column1_row4102 - (column1_row370691 + column1_row376390 + column1_row376390)) / domain120; + tempvar total_sum = total_sum + constraint_coefficients[210] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j1/n1. + tempvar value = (keccak__keccak__sum_parities1_19456 + column1_row159750 - (column1_row2051 + column1_row7750 + column1_row7750)) * domain121 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[211] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j2/n0. + tempvar value = (keccak__keccak__sum_parities2_0 + column1_row4358 - (column1_row127491 + column1_row130435 + column1_row130435)) * domain122 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[212] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j2/n1. + tempvar value = (keccak__keccak__sum_parities2_50176 + column1_row405766 - (column1_row4611 + column1_row7555 + column1_row7555)) / domain123; + tempvar total_sum = total_sum + constraint_coefficients[213] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j3/n0. + tempvar value = (keccak__keccak__sum_parities3_0 + column1_row4614 - (column1_row172803 + column1_row178435 + column1_row178435)) * domain68 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[214] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j3/n1. + tempvar value = (keccak__keccak__sum_parities3_44032 + column1_row356870 - (column1_row771 + column1_row6403 + column1_row6403)) / domain100; + tempvar total_sum = total_sum + constraint_coefficients[215] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j4/n0. + tempvar value = (keccak__keccak__sum_parities4_0 + column1_row4870 - (column1_row68867 + column1_row73473 + column1_row73473)) * domain124 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[216] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i3_j4/n1. + tempvar value = (keccak__keccak__sum_parities4_57344 + column1_row463622 - (column1_row3331 + column1_row7937 + column1_row7937)) / domain125; + tempvar total_sum = total_sum + constraint_coefficients[217] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j0/n0. + tempvar value = (keccak__keccak__sum_parities0_0 + column1_row5126 - (column1_row151043 + column1_row155397 + column1_row155397)) * domain126 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[218] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j0/n1. + tempvar value = (keccak__keccak__sum_parities0_47104 + column1_row381958 - (column1_row3587 + column1_row7941 + column1_row7941)) / domain127; + tempvar total_sum = total_sum + constraint_coefficients[219] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j1/n0. + tempvar value = (keccak__keccak__sum_parities1_0 + column1_row5382 - (column1_row22531 + column1_row18883 + column1_row18883)) * domain109 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[220] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j1/n1. + tempvar value = (keccak__keccak__sum_parities1_8 + column1_row5446 - (column1_row22595 + column1_row19139 + column1_row19139)) * domain109 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[221] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j1/n2. + tempvar value = (keccak__keccak__sum_parities1_16 + column1_row5510 - (column1_row22659 + column1_row19395 + column1_row19395)) * domain109 / domain17; + tempvar total_sum = total_sum + constraint_coefficients[222] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j1/n3. + tempvar value = (keccak__keccak__sum_parities1_63488 + column1_row513286 - (column1_row6147 + column1_row2499 + column1_row2499)) / domain106; + tempvar total_sum = total_sum + constraint_coefficients[223] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j1/n4. + tempvar value = (keccak__keccak__sum_parities1_63496 + column1_row513350 - (column1_row6211 + column1_row2755 + column1_row2755)) / domain106; + tempvar total_sum = total_sum + constraint_coefficients[224] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j1/n5. + tempvar value = (keccak__keccak__sum_parities1_63504 + column1_row513414 - (column1_row6275 + column1_row3011 + column1_row3011)) / domain106; + tempvar total_sum = total_sum + constraint_coefficients[225] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j2/n0. + tempvar value = (keccak__keccak__sum_parities2_0 + column1_row5638 - (column1_row502019 + column1_row507457 + column1_row507457)) / domain113; + tempvar total_sum = total_sum + constraint_coefficients[226] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j2/n1. + tempvar value = (keccak__keccak__sum_parities2_3072 + column1_row30214 - (column1_row2307 + column1_row7745 + column1_row7745)) * domain112 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[227] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j3/n0. + tempvar value = (keccak__keccak__sum_parities3_0 + column1_row5894 - (column1_row463619 + column1_row466499 + column1_row466499)) / domain125; + tempvar total_sum = total_sum + constraint_coefficients[228] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j3/n1. + tempvar value = (keccak__keccak__sum_parities3_8192 + column1_row71430 - (column1_row4867 + column1_row7747 + column1_row7747)) * domain124 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[229] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j4/n0. + tempvar value = (keccak__keccak__sum_parities4_0 + column1_row6150 - (column1_row115715 + column1_row122246 + column1_row122246)) * domain128 / domain18; + tempvar total_sum = total_sum + constraint_coefficients[230] * value; + + // Constraint: keccak/keccak/theta_rho_pi_i4_j4/n1. + tempvar value = (keccak__keccak__sum_parities4_51200 + column1_row415750 - (column1_row1027 + column1_row7558 + column1_row7558)) / domain129; + tempvar total_sum = total_sum + constraint_coefficients[231] * value; + + // Constraint: keccak/keccak/chi_iota0. + tempvar value = (global_values.keccak__keccak__keccak_round_key0 + column1_row3 + column1_row3 + keccak__keccak__after_theta_rho_pi_xor_one_32 + column1_row515 - (column1_row1 + column1_row14 + column1_row14 + column1_row5 * 4)) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[232] * value; + + // Constraint: keccak/keccak/chi_iota1. + tempvar value = (global_values.keccak__keccak__keccak_round_key1 + column1_row8195 + column1_row8195 + keccak__keccak__after_theta_rho_pi_xor_one_1056 + column1_row8707 - (column1_row8193 + column1_row8206 + column1_row8206 + column1_row8197 * 4)) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[233] * value; + + // Constraint: keccak/keccak/chi_iota3. + tempvar value = (global_values.keccak__keccak__keccak_round_key3 + column1_row24579 + column1_row24579 + keccak__keccak__after_theta_rho_pi_xor_one_3104 + column1_row25091 - (column1_row24577 + column1_row24590 + column1_row24590 + column1_row24581 * 4)) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[234] * value; + + // Constraint: keccak/keccak/chi_iota7. + tempvar value = (global_values.keccak__keccak__keccak_round_key7 + column1_row57347 + column1_row57347 + keccak__keccak__after_theta_rho_pi_xor_one_7200 + column1_row57859 - (column1_row57345 + column1_row57358 + column1_row57358 + column1_row57349 * 4)) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[235] * value; + + // Constraint: keccak/keccak/chi_iota15. + tempvar value = (global_values.keccak__keccak__keccak_round_key15 + column1_row122883 + column1_row122883 + keccak__keccak__after_theta_rho_pi_xor_one_15392 + column1_row123395 - (column1_row122881 + column1_row122894 + column1_row122894 + column1_row122885 * 4)) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[236] * value; + + // Constraint: keccak/keccak/chi_iota31. + tempvar value = (global_values.keccak__keccak__keccak_round_key31 + column1_row253955 + column1_row253955 + keccak__keccak__after_theta_rho_pi_xor_one_31776 + column1_row254467 - (column1_row253953 + column1_row253966 + column1_row253966 + column1_row253957 * 4)) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[237] * value; + + // Constraint: keccak/keccak/chi_iota63. + tempvar value = (global_values.keccak__keccak__keccak_round_key63 + column1_row516099 + column1_row516099 + keccak__keccak__after_theta_rho_pi_xor_one_64544 + column1_row516611 - (column1_row516097 + column1_row516110 + column1_row516110 + column1_row516101 * 4)) / domain26; + tempvar total_sum = total_sum + constraint_coefficients[238] * value; + + // Constraint: keccak/keccak/chi0. + tempvar value = (column1_row3 + column1_row3 + keccak__keccak__after_theta_rho_pi_xor_one_32 + column1_row515 - (column1_row1 + column1_row14 + column1_row14 + column1_row5 * 4)) * domain130 / domain20; + tempvar total_sum = total_sum + constraint_coefficients[239] * value; + + // Constraint: keccak/keccak/chi1. + tempvar value = (column1_row1027 + column1_row1027 + keccak__keccak__after_theta_rho_pi_xor_one_0 + column1_row259 - (column1_row1025 + column1_row1038 + column1_row1038 + column1_row1029 * 4)) / domain19; + tempvar total_sum = total_sum + constraint_coefficients[240] * value; + + // Constraint: keccak/keccak/chi2. + tempvar value = (column1_row771 + column1_row771 + keccak__keccak__after_theta_rho_pi_xor_one_128 + column1_row3 - (column1_row769 + column1_row782 + column1_row782 + column1_row773 * 4)) / domain19; + tempvar total_sum = total_sum + constraint_coefficients[241] * value; + + return (res=total_sum); +} + +func eval_oods_polynomial{range_check_ptr}( + self: felt*, + column_values: felt*, + oods_values: felt*, + constraint_coefficients: felt*, + point: felt, + oods_point: felt, + trace_generator: felt, + global_values: OodsGlobalValues*, +) -> (res: felt) { + alloc_locals; + + // Compute powers. + let (local pow0) = pow(trace_generator, 0); + let (local pow1) = pow(trace_generator, 1); + local pow2 = pow1 * pow1; + local pow3 = pow1 * pow2; + local pow4 = pow1 * pow3; + local pow5 = pow1 * pow4; + local pow6 = pow1 * pow5; + local pow7 = pow1 * pow6; + local pow8 = pow1 * pow7; + local pow9 = pow1 * pow8; + local pow10 = pow1 * pow9; + local pow11 = pow1 * pow10; + local pow12 = pow1 * pow11; + local pow13 = pow1 * pow12; + local pow14 = pow1 * pow13; + local pow15 = pow1 * pow14; + local pow16 = pow1 * pow15; + local pow17 = pow4 * pow16; + local pow18 = pow4 * pow17; + local pow19 = pow4 * pow18; + local pow20 = pow4 * pow19; + local pow21 = pow4 * pow20; + local pow22 = pow4 * pow21; + local pow23 = pow2 * pow22; + local pow24 = pow1 * pow23; + local pow25 = pow1 * pow24; + local pow26 = pow4 * pow25; + local pow27 = pow4 * pow26; + local pow28 = pow4 * pow27; + local pow29 = pow4 * pow28; + local pow30 = pow4 * pow29; + local pow31 = pow2 * pow30; + local pow32 = pow8 * pow31; + local pow33 = pow1 * pow32; + local pow34 = pow1 * pow33; + local pow35 = pow16 * pow34; + local pow36 = pow14 * pow35; + local pow37 = pow2 * pow36; + local pow38 = pow16 * pow37; + local pow39 = pow4 * pow38; + local pow40 = pow2 * pow39; + local pow41 = pow8 * pow40; + local pow42 = pow1 * pow41; + local pow43 = pow20 * pow42; + local pow44 = pow5 * pow43; + local pow45 = pow4 * pow44; + local pow46 = pow4 * pow45; + local pow47 = pow4 * pow46; + local pow48 = pow4 * pow47; + local pow49 = pow2 * pow48; + local pow50 = pow1 * pow49; + local pow51 = pow3 * pow50; + local pow52 = pow4 * pow51; + local pow53 = pow20 * pow52; + local pow54 = pow1 * pow53; + local pow55 = pow5 * pow54; + local pow56 = pow4 * pow55; + local pow57 = pow4 * pow56; + local pow58 = pow4 * pow57; + local pow59 = pow4 * pow58; + local pow60 = pow3 * pow59; + local pow61 = pow3 * pow60; + local pow62 = pow2 * pow61; + local pow63 = pow8 * pow62; + local pow64 = pow16 * pow63; + local pow65 = pow10 * pow64; + local pow66 = pow48 * pow60; + local pow67 = pow55 * pow63; + local pow68 = pow3 * pow67; + local pow69 = pow3 * pow68; + local pow70 = pow2 * pow69; + local pow71 = pow2 * pow70; + local pow72 = pow1 * pow71; + local pow73 = pow46 * pow72; + let (local pow74) = pow(trace_generator, 769); + local pow75 = pow2 * pow74; + local pow76 = pow2 * pow75; + local pow77 = pow1 * pow76; + local pow78 = pow8 * pow77; + local pow79 = pow48 * pow75; + local pow80 = pow58 * pow76; + local pow81 = pow2 * pow80; + local pow82 = pow2 * pow81; + local pow83 = pow1 * pow82; + local pow84 = pow4 * pow83; + local pow85 = pow1 * pow84; + local pow86 = pow3 * pow85; + local pow87 = pow46 * pow85; + local pow88 = pow30 * pow87; + local pow89 = pow3 * pow88; + local pow90 = pow48 * pow88; + local pow91 = pow30 * pow90; + local pow92 = pow3 * pow91; + local pow93 = pow5 * pow92; + local pow94 = pow18 * pow93; + local pow95 = pow8 * pow94; + local pow96 = pow46 * pow93; + local pow97 = pow30 * pow96; + local pow98 = pow3 * pow97; + let (local pow99) = pow(trace_generator, 1876); + local pow100 = pow30 * pow99; + local pow101 = pow48 * pow97; + local pow102 = pow30 * pow100; + local pow103 = pow7 * pow102; + local pow104 = pow8 * pow103; + let (local pow105) = pow(trace_generator, 2041); + local pow106 = pow4 * pow105; + local pow107 = pow2 * pow106; + local pow108 = pow2 * pow107; + local pow109 = pow2 * pow108; + local pow110 = pow2 * pow109; + local pow111 = pow1 * pow110; + local pow112 = pow4 * pow111; + local pow113 = pow1 * pow112; + local pow114 = pow29 * pow112; + local pow115 = pow30 * pow114; + local pow116 = pow46 * pow113; + local pow117 = pow30 * pow116; + local pow118 = pow3 * pow117; + local pow119 = pow48 * pow117; + local pow120 = pow30 * pow119; + local pow121 = pow3 * pow120; + local pow122 = pow4 * pow121; + local pow123 = pow1 * pow122; + local pow124 = pow46 * pow123; + local pow125 = pow30 * pow124; + local pow126 = pow3 * pow125; + local pow127 = pow48 * pow125; + local pow128 = pow30 * pow127; + local pow129 = pow3 * pow128; + local pow130 = pow59 * pow128; + local pow131 = pow3 * pow130; + local pow132 = pow59 * pow130; + local pow133 = pow3 * pow132; + local pow134 = pow30 * pow133; + local pow135 = pow30 * pow134; + local pow136 = pow59 * pow132; + local pow137 = pow3 * pow136; + local pow138 = pow30 * pow137; + local pow139 = pow14 * pow138; + local pow140 = pow30 * pow138; + local pow141 = pow14 * pow140; + local pow142 = pow30 * pow141; + let (local pow143) = pow(trace_generator, 4089); + local pow144 = pow10 * pow143; + local pow145 = pow3 * pow144; + local pow146 = pow4 * pow145; + local pow147 = pow59 * pow144; + local pow148 = pow3 * pow147; + local pow149 = pow59 * pow147; + local pow150 = pow3 * pow149; + local pow151 = pow5 * pow150; + local pow152 = pow57 * pow151; + local pow153 = pow3 * pow152; + local pow154 = pow59 * pow152; + local pow155 = pow3 * pow154; + local pow156 = pow59 * pow154; + local pow157 = pow3 * pow156; + local pow158 = pow30 * pow156; + local pow159 = pow3 * pow158; + local pow160 = pow30 * pow158; + local pow161 = pow3 * pow160; + local pow162 = pow39 * pow160; + local pow163 = pow3 * pow162; + local pow164 = pow30 * pow162; + local pow165 = pow30 * pow164; + local pow166 = pow39 * pow165; + local pow167 = pow3 * pow166; + local pow168 = pow30 * pow166; + let (local pow169) = pow(trace_generator, 5972); + local pow170 = pow30 * pow168; + local pow171 = pow30 * pow169; + local pow172 = pow30 * pow171; + local pow173 = pow39 * pow170; + local pow174 = pow3 * pow173; + local pow175 = pow30 * pow173; + local pow176 = pow30 * pow175; + let (local pow177) = pow(trace_generator, 6401); + local pow178 = pow2 * pow177; + local pow179 = pow2 * pow178; + local pow180 = pow1 * pow179; + local pow181 = pow10 * pow180; + local pow182 = pow16 * pow181; + local pow183 = pow30 * pow179; + local pow184 = pow1 * pow183; + local pow185 = pow30 * pow183; + local pow186 = pow1 * pow185; + local pow187 = pow29 * pow185; + local pow188 = pow2 * pow187; + local pow189 = pow2 * pow188; + local pow190 = pow1 * pow189; + local pow191 = pow29 * pow189; + local pow192 = pow5 * pow191; + local pow193 = pow5 * pow192; + local pow194 = pow30 * pow191; + local pow195 = pow5 * pow194; + local pow196 = pow30 * pow194; + local pow197 = pow2 * pow196; + local pow198 = pow2 * pow197; + local pow199 = pow1 * pow198; + local pow200 = pow47 * pow198; + local pow201 = pow2 * pow200; + local pow202 = pow2 * pow201; + local pow203 = pow1 * pow202; + local pow204 = pow47 * pow202; + local pow205 = pow2 * pow204; + local pow206 = pow2 * pow205; + local pow207 = pow1 * pow206; + local pow208 = pow47 * pow206; + local pow209 = pow2 * pow208; + local pow210 = pow2 * pow209; + local pow211 = pow1 * pow210; + local pow212 = pow47 * pow210; + local pow213 = pow2 * pow212; + local pow214 = pow2 * pow213; + local pow215 = pow1 * pow214; + local pow216 = pow10 * pow215; + local pow217 = pow47 * pow214; + local pow218 = pow2 * pow217; + local pow219 = pow2 * pow218; + local pow220 = pow1 * pow219; + local pow221 = pow10 * pow220; + local pow222 = pow30 * pow221; + local pow223 = pow30 * pow222; + local pow224 = pow47 * pow219; + local pow225 = pow2 * pow224; + local pow226 = pow2 * pow225; + local pow227 = pow1 * pow226; + local pow228 = pow58 * pow226; + local pow229 = pow2 * pow228; + local pow230 = pow2 * pow229; + local pow231 = pow9 * pow230; + local pow232 = pow2 * pow231; + local pow233 = pow16 * pow232; + local pow234 = pow55 * pow232; + local pow235 = pow3 * pow234; + local pow236 = pow5 * pow235; + local pow237 = pow59 * pow235; + local pow238 = pow8 * pow237; + let (local pow239) = pow(trace_generator, 10068); + local pow240 = pow117 * pow234; + local pow241 = pow8 * pow240; + local pow242 = pow138 * pow231; + local pow243 = pow147 * pow236; + let (local pow244) = pow(trace_generator, 14164); + local pow245 = pow178 * pow236; + let (local pow246) = pow(trace_generator, 15760); + let (local pow247) = pow(trace_generator, 15941); + local pow248 = pow11 * pow247; + local pow249 = pow48 * pow248; + local pow250 = pow1 * pow249; + local pow251 = pow1 * pow250; + local pow252 = pow1 * pow251; + local pow253 = pow1 * pow252; + local pow254 = pow1 * pow253; + local pow255 = pow1 * pow254; + local pow256 = pow1 * pow255; + local pow257 = pow9 * pow256; + local pow258 = pow1 * pow257; + local pow259 = pow1 * pow258; + local pow260 = pow1 * pow259; + local pow261 = pow1 * pow260; + local pow262 = pow1 * pow261; + local pow263 = pow1 * pow262; + local pow264 = pow1 * pow263; + local pow265 = pow9 * pow264; + local pow266 = pow16 * pow265; + local pow267 = pow16 * pow266; + local pow268 = pow16 * pow267; + local pow269 = pow16 * pow268; + local pow270 = pow16 * pow269; + local pow271 = pow16 * pow270; + local pow272 = pow16 * pow271; + local pow273 = pow16 * pow272; + local pow274 = pow16 * pow273; + local pow275 = pow16 * pow274; + local pow276 = pow16 * pow275; + local pow277 = pow16 * pow276; + local pow278 = pow16 * pow277; + local pow279 = pow69 * pow278; + local pow280 = pow5 * pow279; + local pow281 = pow119 * pow278; + local pow282 = pow110 * pow279; + local pow283 = pow46 * pow282; + local pow284 = pow59 * pow283; + local pow285 = pow151 * pow278; + local pow286 = pow173 * pow278; + local pow287 = pow30 * pow286; + local pow288 = pow30 * pow287; + local pow289 = pow177 * pow278; + local pow290 = pow70 * pow286; + local pow291 = pow216 * pow278; + local pow292 = pow228 * pow278; + local pow293 = pow2 * pow292; + local pow294 = pow2 * pow293; + local pow295 = pow9 * pow294; + local pow296 = pow59 * pow293; + local pow297 = pow59 * pow296; + local pow298 = pow8 * pow297; + let (local pow299) = pow(trace_generator, 26371); + local pow300 = pow121 * pow294; + local pow301 = pow150 * pow294; + local pow302 = pow136 * pow299; + let (local pow303) = pow(trace_generator, 30977); + local pow304 = pow49 * pow303; + local pow305 = pow82 * pow302; + local pow306 = pow246 * pow278; + local pow307 = pow278 * pow278; + let (local pow308) = pow(trace_generator, 51971); + let (local pow309) = pow(trace_generator, 55939); + local pow310 = pow292 * pow307; + local pow311 = pow2 * pow310; + local pow312 = pow2 * pow311; + local pow313 = pow9 * pow312; + local pow314 = pow59 * pow311; + local pow315 = pow59 * pow314; + local pow316 = pow307 * pow307; + let (local pow317) = pow(trace_generator, 66320); + local pow318 = pow16 * pow317; + local pow319 = pow130 * pow316; + local pow320 = pow120 * pow319; + local pow321 = pow169 * pow316; + local pow322 = pow179 * pow316; + local pow323 = pow224 * pow316; + let (local pow324) = pow(trace_generator, 75782); + local pow325 = pow30 * pow324; + local pow326 = pow30 * pow325; + local pow327 = pow244 * pow316; + local pow328 = pow30 * pow327; + local pow329 = pow30 * pow328; + let (local pow330) = pow(trace_generator, 80133); + local pow331 = pow30 * pow330; + local pow332 = pow30 * pow331; + let (local pow333) = pow(trace_generator, 86275); + let (local pow334) = pow(trace_generator, 89283); + local pow335 = pow307 * pow316; + let (local pow336) = pow(trace_generator, 115715); + let (local pow337) = pow(trace_generator, 122246); + local pow338 = pow292 * pow335; + local pow339 = pow2 * pow338; + local pow340 = pow2 * pow339; + local pow341 = pow9 * pow340; + local pow342 = pow59 * pow339; + local pow343 = pow59 * pow342; + let (local pow344) = pow(trace_generator, 127491); + let (local pow345) = pow(trace_generator, 130435); + local pow346 = pow307 * pow335; + let (local pow347) = pow(trace_generator, 132624); + local pow348 = pow16 * pow347; + let (local pow349) = pow(trace_generator, 151043); + let (local pow350) = pow(trace_generator, 155397); + let (local pow351) = pow(trace_generator, 157524); + local pow352 = pow237 * pow349; + local pow353 = pow191 * pow350; + local pow354 = pow307 * pow346; + local pow355 = pow91 * pow354; + local pow356 = pow3 * pow355; + local pow357 = pow99 * pow354; + local pow358 = pow152 * pow355; + local pow359 = pow214 * pow354; + let (local pow360) = pow(trace_generator, 172803); + local pow361 = pow117 * pow360; + let (local pow362) = pow(trace_generator, 178433); + local pow363 = pow2 * pow362; + local pow364 = pow246 * pow354; + local pow365 = pow319 * pow343; + local pow366 = pow30 * pow365; + local pow367 = pow30 * pow366; + let (local pow368) = pow(trace_generator, 195009); + local pow369 = pow30 * pow368; + local pow370 = pow30 * pow369; + let (local pow371) = pow(trace_generator, 196176); + local pow372 = pow30 * pow371; + local pow373 = pow30 * pow372; + local pow374 = pow307 * pow354; + let (local pow375) = pow(trace_generator, 198928); + local pow376 = pow16 * pow375; + let (local pow377) = pow(trace_generator, 207875); + local pow378 = pow68 * pow377; + local pow379 = pow30 * pow378; + local pow380 = pow30 * pow379; + local pow381 = pow242 * pow374; + local pow382 = pow30 * pow381; + local pow383 = pow30 * pow382; + let (local pow384) = pow(trace_generator, 211398); + local pow385 = pow30 * pow384; + local pow386 = pow30 * pow385; + local pow387 = pow152 * pow377; + let (local pow388) = pow(trace_generator, 225027); + let (local pow389) = pow(trace_generator, 228163); + local pow390 = pow307 * pow374; + local pow391 = pow88 * pow390; + local pow392 = pow3 * pow391; + local pow393 = pow187 * pow390; + local pow394 = pow212 * pow390; + local pow395 = pow221 * pow390; + local pow396 = pow292 * pow390; + local pow397 = pow2 * pow396; + local pow398 = pow2 * pow397; + local pow399 = pow9 * pow398; + local pow400 = pow59 * pow397; + local pow401 = pow59 * pow400; + local pow402 = pow307 * pow390; + let (local pow403) = pow(trace_generator, 265232); + local pow404 = pow16 * pow403; + local pow405 = pow307 * pow402; + local pow406 = pow77 * pow405; + local pow407 = pow144 * pow405; + local pow408 = pow169 * pow405; + local pow409 = pow179 * pow405; + local pow410 = pow205 * pow405; + local pow411 = pow109 * pow410; + local pow412 = pow242 * pow405; + local pow413 = pow335 * pow384; + let (local pow414) = pow(trace_generator, 320451); + local pow415 = pow59 * pow414; + local pow416 = pow59 * pow415; + local pow417 = pow319 * pow397; + let (local pow418) = pow(trace_generator, 325123); + local pow419 = pow30 * pow418; + local pow420 = pow30 * pow419; + let (local pow421) = pow(trace_generator, 325460); + let (local pow422) = pow(trace_generator, 325893); + local pow423 = pow307 * pow405; + let (local pow424) = pow(trace_generator, 331536); + local pow425 = pow16 * pow424; + let (local pow426) = pow(trace_generator, 337603); + local pow427 = pow59 * pow426; + local pow428 = pow59 * pow427; + let (local pow429) = pow(trace_generator, 341763); + local pow430 = pow30 * pow429; + local pow431 = pow30 * pow430; + local pow432 = pow297 * pow423; + local pow433 = pow144 * pow432; + local pow434 = pow307 * pow421; + local pow435 = pow307 * pow422; + let (local pow436) = pow(trace_generator, 359621); + local pow437 = pow307 * pow423; + local pow438 = pow60 * pow437; + local pow439 = pow109 * pow438; + local pow440 = pow139 * pow437; + local pow441 = pow190 * pow437; + local pow442 = pow208 * pow437; + let (local pow443) = pow(trace_generator, 370691); + local pow444 = pow164 * pow443; + local pow445 = pow344 * pow401; + let (local pow446) = pow(trace_generator, 383425); + let (local pow447) = pow(trace_generator, 384592); + local pow448 = pow307 * pow437; + let (local pow449) = pow(trace_generator, 397840); + local pow450 = pow16 * pow449; + let (local pow451) = pow(trace_generator, 405766); + local pow452 = pow362 * pow390; + local pow453 = pow246 * pow448; + let (local pow454) = pow(trace_generator, 413524); + local pow455 = pow226 * pow452; + let (local pow456) = pow(trace_generator, 416198); + local pow457 = pow307 * pow448; + let (local pow458) = pow(trace_generator, 444244); + let (local pow459) = pow(trace_generator, 445190); + local pow460 = pow338 * pow422; + let (local pow461) = pow(trace_generator, 450755); + local pow462 = pow59 * pow461; + local pow463 = pow59 * pow462; + let (local pow464) = pow(trace_generator, 455939); + local pow465 = pow30 * pow464; + local pow466 = pow30 * pow465; + local pow467 = pow307 * pow457; + local pow468 = pow139 * pow467; + local pow469 = pow152 * pow467; + local pow470 = pow3 * pow469; + local pow471 = pow71 * pow470; + local pow472 = pow16 * pow471; + local pow473 = pow96 * pow469; + local pow474 = pow218 * pow467; + let (local pow475) = pow(trace_generator, 476934); + local pow476 = pow289 * pow467; + local pow477 = pow291 * pow467; + local pow478 = pow307 * pow467; + let (local pow479) = pow(trace_generator, 502019); + local pow480 = pow60 * pow479; + let (local pow481) = pow(trace_generator, 506305); + let (local pow482) = pow(trace_generator, 507457); + local pow483 = pow15 * pow482; + local pow484 = pow316 * pow458; + local pow485 = pow30 * pow484; + local pow486 = pow30 * pow485; + let (local pow487) = pow(trace_generator, 513027); + local pow488 = pow60 * pow487; + local pow489 = pow30 * pow488; + local pow490 = pow30 * pow489; + local pow491 = pow88 * pow487; + local pow492 = pow30 * pow491; + local pow493 = pow30 * pow492; + let (local pow494) = pow(trace_generator, 515843); + local pow495 = pow292 * pow478; + local pow496 = pow2 * pow495; + local pow497 = pow2 * pow496; + local pow498 = pow1 * pow497; + local pow499 = pow8 * pow498; + local pow500 = pow2 * pow499; + local pow501 = pow16 * pow500; + local pow502 = pow46 * pow499; + local pow503 = pow55 * pow500; + local pow504 = pow3 * pow503; + local pow505 = pow3 * pow504; + local pow506 = pow2 * pow505; + local pow507 = pow59 * pow504; + local pow508 = pow351 * pow437; + local pow509 = pow266 * pow481; + local pow510 = pow4 * pow509; + local pow511 = pow1 * pow510; + local pow512 = pow47 * pow510; + local pow513 = pow5 * pow512; + + // Fetch columns. + tempvar column0 = column_values[0]; + tempvar column1 = column_values[1]; + tempvar column2 = column_values[2]; + tempvar column3 = column_values[3]; + tempvar column4 = column_values[4]; + tempvar column5 = column_values[5]; + tempvar column6 = column_values[6]; + tempvar column7 = column_values[7]; + tempvar column8 = column_values[8]; + tempvar column9 = column_values[9]; + tempvar column10 = column_values[10]; + + // Sum the OODS constraints on the trace polynomials. + tempvar total_sum = 0; + + tempvar value = (column0 - oods_values[0]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[0] * value; + + tempvar value = (column0 - oods_values[1]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[1] * value; + + tempvar value = (column0 - oods_values[2]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[2] * value; + + tempvar value = (column0 - oods_values[3]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[3] * value; + + tempvar value = (column0 - oods_values[4]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[4] * value; + + tempvar value = (column0 - oods_values[5]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[5] * value; + + tempvar value = (column0 - oods_values[6]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[6] * value; + + tempvar value = (column0 - oods_values[7]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[7] * value; + + tempvar value = (column0 - oods_values[8]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[8] * value; + + tempvar value = (column0 - oods_values[9]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[9] * value; + + tempvar value = (column0 - oods_values[10]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[10] * value; + + tempvar value = (column0 - oods_values[11]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[11] * value; + + tempvar value = (column0 - oods_values[12]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[12] * value; + + tempvar value = (column0 - oods_values[13]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[13] * value; + + tempvar value = (column0 - oods_values[14]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[14] * value; + + tempvar value = (column0 - oods_values[15]) / (point - pow15 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[15] * value; + + tempvar value = (column1 - oods_values[16]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[16] * value; + + tempvar value = (column1 - oods_values[17]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[17] * value; + + tempvar value = (column1 - oods_values[18]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[18] * value; + + tempvar value = (column1 - oods_values[19]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[19] * value; + + tempvar value = (column1 - oods_values[20]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[20] * value; + + tempvar value = (column1 - oods_values[21]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[21] * value; + + tempvar value = (column1 - oods_values[22]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[22] * value; + + tempvar value = (column1 - oods_values[23]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[23] * value; + + tempvar value = (column1 - oods_values[24]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[24] * value; + + tempvar value = (column1 - oods_values[25]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[25] * value; + + tempvar value = (column1 - oods_values[26]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[26] * value; + + tempvar value = (column1 - oods_values[27]) / (point - pow17 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[27] * value; + + tempvar value = (column1 - oods_values[28]) / (point - pow18 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[28] * value; + + tempvar value = (column1 - oods_values[29]) / (point - pow19 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[29] * value; + + tempvar value = (column1 - oods_values[30]) / (point - pow20 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[30] * value; + + tempvar value = (column1 - oods_values[31]) / (point - pow21 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[31] * value; + + tempvar value = (column1 - oods_values[32]) / (point - pow22 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[32] * value; + + tempvar value = (column1 - oods_values[33]) / (point - pow25 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[33] * value; + + tempvar value = (column1 - oods_values[34]) / (point - pow26 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[34] * value; + + tempvar value = (column1 - oods_values[35]) / (point - pow27 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[35] * value; + + tempvar value = (column1 - oods_values[36]) / (point - pow28 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[36] * value; + + tempvar value = (column1 - oods_values[37]) / (point - pow29 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[37] * value; + + tempvar value = (column1 - oods_values[38]) / (point - pow30 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[38] * value; + + tempvar value = (column1 - oods_values[39]) / (point - pow31 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[39] * value; + + tempvar value = (column1 - oods_values[40]) / (point - pow39 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[40] * value; + + tempvar value = (column1 - oods_values[41]) / (point - pow40 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[41] * value; + + tempvar value = (column1 - oods_values[42]) / (point - pow44 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[42] * value; + + tempvar value = (column1 - oods_values[43]) / (point - pow45 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[43] * value; + + tempvar value = (column1 - oods_values[44]) / (point - pow46 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[44] * value; + + tempvar value = (column1 - oods_values[45]) / (point - pow47 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[45] * value; + + tempvar value = (column1 - oods_values[46]) / (point - pow48 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[46] * value; + + tempvar value = (column1 - oods_values[47]) / (point - pow49 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[47] * value; + + tempvar value = (column1 - oods_values[48]) / (point - pow50 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[48] * value; + + tempvar value = (column1 - oods_values[49]) / (point - pow51 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[49] * value; + + tempvar value = (column1 - oods_values[50]) / (point - pow55 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[50] * value; + + tempvar value = (column1 - oods_values[51]) / (point - pow56 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[51] * value; + + tempvar value = (column1 - oods_values[52]) / (point - pow57 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[52] * value; + + tempvar value = (column1 - oods_values[53]) / (point - pow58 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[53] * value; + + tempvar value = (column1 - oods_values[54]) / (point - pow60 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[54] * value; + + tempvar value = (column1 - oods_values[55]) / (point - pow61 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[55] * value; + + tempvar value = (column1 - oods_values[56]) / (point - pow66 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[56] * value; + + tempvar value = (column1 - oods_values[57]) / (point - pow68 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[57] * value; + + tempvar value = (column1 - oods_values[58]) / (point - pow69 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[58] * value; + + tempvar value = (column1 - oods_values[59]) / (point - pow73 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[59] * value; + + tempvar value = (column1 - oods_values[60]) / (point - pow74 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[60] * value; + + tempvar value = (column1 - oods_values[61]) / (point - pow75 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[61] * value; + + tempvar value = (column1 - oods_values[62]) / (point - pow76 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[62] * value; + + tempvar value = (column1 - oods_values[63]) / (point - pow77 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[63] * value; + + tempvar value = (column1 - oods_values[64]) / (point - pow78 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[64] * value; + + tempvar value = (column1 - oods_values[65]) / (point - pow79 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[65] * value; + + tempvar value = (column1 - oods_values[66]) / (point - pow80 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[66] * value; + + tempvar value = (column1 - oods_values[67]) / (point - pow81 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[67] * value; + + tempvar value = (column1 - oods_values[68]) / (point - pow82 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[68] * value; + + tempvar value = (column1 - oods_values[69]) / (point - pow83 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[69] * value; + + tempvar value = (column1 - oods_values[70]) / (point - pow86 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[70] * value; + + tempvar value = (column1 - oods_values[71]) / (point - pow87 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[71] * value; + + tempvar value = (column1 - oods_values[72]) / (point - pow88 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[72] * value; + + tempvar value = (column1 - oods_values[73]) / (point - pow89 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[73] * value; + + tempvar value = (column1 - oods_values[74]) / (point - pow90 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[74] * value; + + tempvar value = (column1 - oods_values[75]) / (point - pow91 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[75] * value; + + tempvar value = (column1 - oods_values[76]) / (point - pow92 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[76] * value; + + tempvar value = (column1 - oods_values[77]) / (point - pow96 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[77] * value; + + tempvar value = (column1 - oods_values[78]) / (point - pow97 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[78] * value; + + tempvar value = (column1 - oods_values[79]) / (point - pow98 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[79] * value; + + tempvar value = (column1 - oods_values[80]) / (point - pow101 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[80] * value; + + tempvar value = (column1 - oods_values[81]) / (point - pow109 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[81] * value; + + tempvar value = (column1 - oods_values[82]) / (point - pow111 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[82] * value; + + tempvar value = (column1 - oods_values[83]) / (point - pow114 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[83] * value; + + tempvar value = (column1 - oods_values[84]) / (point - pow115 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[84] * value; + + tempvar value = (column1 - oods_values[85]) / (point - pow116 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[85] * value; + + tempvar value = (column1 - oods_values[86]) / (point - pow117 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[86] * value; + + tempvar value = (column1 - oods_values[87]) / (point - pow118 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[87] * value; + + tempvar value = (column1 - oods_values[88]) / (point - pow119 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[88] * value; + + tempvar value = (column1 - oods_values[89]) / (point - pow120 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[89] * value; + + tempvar value = (column1 - oods_values[90]) / (point - pow121 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[90] * value; + + tempvar value = (column1 - oods_values[91]) / (point - pow124 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[91] * value; + + tempvar value = (column1 - oods_values[92]) / (point - pow125 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[92] * value; + + tempvar value = (column1 - oods_values[93]) / (point - pow126 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[93] * value; + + tempvar value = (column1 - oods_values[94]) / (point - pow127 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[94] * value; + + tempvar value = (column1 - oods_values[95]) / (point - pow128 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[95] * value; + + tempvar value = (column1 - oods_values[96]) / (point - pow129 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[96] * value; + + tempvar value = (column1 - oods_values[97]) / (point - pow130 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[97] * value; + + tempvar value = (column1 - oods_values[98]) / (point - pow131 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[98] * value; + + tempvar value = (column1 - oods_values[99]) / (point - pow132 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[99] * value; + + tempvar value = (column1 - oods_values[100]) / (point - pow133 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[100] * value; + + tempvar value = (column1 - oods_values[101]) / (point - pow134 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[101] * value; + + tempvar value = (column1 - oods_values[102]) / (point - pow135 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[102] * value; + + tempvar value = (column1 - oods_values[103]) / (point - pow136 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[103] * value; + + tempvar value = (column1 - oods_values[104]) / (point - pow137 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[104] * value; + + tempvar value = (column1 - oods_values[105]) / (point - pow138 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[105] * value; + + tempvar value = (column1 - oods_values[106]) / (point - pow140 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[106] * value; + + tempvar value = (column1 - oods_values[107]) / (point - pow144 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[107] * value; + + tempvar value = (column1 - oods_values[108]) / (point - pow145 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[108] * value; + + tempvar value = (column1 - oods_values[109]) / (point - pow147 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[109] * value; + + tempvar value = (column1 - oods_values[110]) / (point - pow148 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[110] * value; + + tempvar value = (column1 - oods_values[111]) / (point - pow149 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[111] * value; + + tempvar value = (column1 - oods_values[112]) / (point - pow150 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[112] * value; + + tempvar value = (column1 - oods_values[113]) / (point - pow152 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[113] * value; + + tempvar value = (column1 - oods_values[114]) / (point - pow153 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[114] * value; + + tempvar value = (column1 - oods_values[115]) / (point - pow154 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[115] * value; + + tempvar value = (column1 - oods_values[116]) / (point - pow155 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[116] * value; + + tempvar value = (column1 - oods_values[117]) / (point - pow156 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[117] * value; + + tempvar value = (column1 - oods_values[118]) / (point - pow157 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[118] * value; + + tempvar value = (column1 - oods_values[119]) / (point - pow158 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[119] * value; + + tempvar value = (column1 - oods_values[120]) / (point - pow159 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[120] * value; + + tempvar value = (column1 - oods_values[121]) / (point - pow160 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[121] * value; + + tempvar value = (column1 - oods_values[122]) / (point - pow161 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[122] * value; + + tempvar value = (column1 - oods_values[123]) / (point - pow162 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[123] * value; + + tempvar value = (column1 - oods_values[124]) / (point - pow163 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[124] * value; + + tempvar value = (column1 - oods_values[125]) / (point - pow164 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[125] * value; + + tempvar value = (column1 - oods_values[126]) / (point - pow165 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[126] * value; + + tempvar value = (column1 - oods_values[127]) / (point - pow166 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[127] * value; + + tempvar value = (column1 - oods_values[128]) / (point - pow167 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[128] * value; + + tempvar value = (column1 - oods_values[129]) / (point - pow168 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[129] * value; + + tempvar value = (column1 - oods_values[130]) / (point - pow170 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[130] * value; + + tempvar value = (column1 - oods_values[131]) / (point - pow173 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[131] * value; + + tempvar value = (column1 - oods_values[132]) / (point - pow174 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[132] * value; + + tempvar value = (column1 - oods_values[133]) / (point - pow175 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[133] * value; + + tempvar value = (column1 - oods_values[134]) / (point - pow176 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[134] * value; + + tempvar value = (column1 - oods_values[135]) / (point - pow177 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[135] * value; + + tempvar value = (column1 - oods_values[136]) / (point - pow178 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[136] * value; + + tempvar value = (column1 - oods_values[137]) / (point - pow179 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[137] * value; + + tempvar value = (column1 - oods_values[138]) / (point - pow180 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[138] * value; + + tempvar value = (column1 - oods_values[139]) / (point - pow183 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[139] * value; + + tempvar value = (column1 - oods_values[140]) / (point - pow184 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[140] * value; + + tempvar value = (column1 - oods_values[141]) / (point - pow185 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[141] * value; + + tempvar value = (column1 - oods_values[142]) / (point - pow186 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[142] * value; + + tempvar value = (column1 - oods_values[143]) / (point - pow187 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[143] * value; + + tempvar value = (column1 - oods_values[144]) / (point - pow188 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[144] * value; + + tempvar value = (column1 - oods_values[145]) / (point - pow189 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[145] * value; + + tempvar value = (column1 - oods_values[146]) / (point - pow190 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[146] * value; + + tempvar value = (column1 - oods_values[147]) / (point - pow191 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[147] * value; + + tempvar value = (column1 - oods_values[148]) / (point - pow192 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[148] * value; + + tempvar value = (column1 - oods_values[149]) / (point - pow194 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[149] * value; + + tempvar value = (column1 - oods_values[150]) / (point - pow195 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[150] * value; + + tempvar value = (column1 - oods_values[151]) / (point - pow196 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[151] * value; + + tempvar value = (column1 - oods_values[152]) / (point - pow197 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[152] * value; + + tempvar value = (column1 - oods_values[153]) / (point - pow198 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[153] * value; + + tempvar value = (column1 - oods_values[154]) / (point - pow199 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[154] * value; + + tempvar value = (column1 - oods_values[155]) / (point - pow200 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[155] * value; + + tempvar value = (column1 - oods_values[156]) / (point - pow201 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[156] * value; + + tempvar value = (column1 - oods_values[157]) / (point - pow202 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[157] * value; + + tempvar value = (column1 - oods_values[158]) / (point - pow203 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[158] * value; + + tempvar value = (column1 - oods_values[159]) / (point - pow204 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[159] * value; + + tempvar value = (column1 - oods_values[160]) / (point - pow205 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[160] * value; + + tempvar value = (column1 - oods_values[161]) / (point - pow206 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[161] * value; + + tempvar value = (column1 - oods_values[162]) / (point - pow207 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[162] * value; + + tempvar value = (column1 - oods_values[163]) / (point - pow208 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[163] * value; + + tempvar value = (column1 - oods_values[164]) / (point - pow209 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[164] * value; + + tempvar value = (column1 - oods_values[165]) / (point - pow210 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[165] * value; + + tempvar value = (column1 - oods_values[166]) / (point - pow211 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[166] * value; + + tempvar value = (column1 - oods_values[167]) / (point - pow212 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[167] * value; + + tempvar value = (column1 - oods_values[168]) / (point - pow213 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[168] * value; + + tempvar value = (column1 - oods_values[169]) / (point - pow214 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[169] * value; + + tempvar value = (column1 - oods_values[170]) / (point - pow215 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[170] * value; + + tempvar value = (column1 - oods_values[171]) / (point - pow217 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[171] * value; + + tempvar value = (column1 - oods_values[172]) / (point - pow218 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[172] * value; + + tempvar value = (column1 - oods_values[173]) / (point - pow219 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[173] * value; + + tempvar value = (column1 - oods_values[174]) / (point - pow220 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[174] * value; + + tempvar value = (column1 - oods_values[175]) / (point - pow224 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[175] * value; + + tempvar value = (column1 - oods_values[176]) / (point - pow225 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[176] * value; + + tempvar value = (column1 - oods_values[177]) / (point - pow226 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[177] * value; + + tempvar value = (column1 - oods_values[178]) / (point - pow227 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[178] * value; + + tempvar value = (column1 - oods_values[179]) / (point - pow228 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[179] * value; + + tempvar value = (column1 - oods_values[180]) / (point - pow229 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[180] * value; + + tempvar value = (column1 - oods_values[181]) / (point - pow230 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[181] * value; + + tempvar value = (column1 - oods_values[182]) / (point - pow231 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[182] * value; + + tempvar value = (column1 - oods_values[183]) / (point - pow235 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[183] * value; + + tempvar value = (column1 - oods_values[184]) / (point - pow237 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[184] * value; + + tempvar value = (column1 - oods_values[185]) / (point - pow240 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[185] * value; + + tempvar value = (column1 - oods_values[186]) / (point - pow247 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[186] * value; + + tempvar value = (column1 - oods_values[187]) / (point - pow279 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[187] * value; + + tempvar value = (column1 - oods_values[188]) / (point - pow281 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[188] * value; + + tempvar value = (column1 - oods_values[189]) / (point - pow283 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[189] * value; + + tempvar value = (column1 - oods_values[190]) / (point - pow284 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[190] * value; + + tempvar value = (column1 - oods_values[191]) / (point - pow286 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[191] * value; + + tempvar value = (column1 - oods_values[192]) / (point - pow287 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[192] * value; + + tempvar value = (column1 - oods_values[193]) / (point - pow288 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[193] * value; + + tempvar value = (column1 - oods_values[194]) / (point - pow289 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[194] * value; + + tempvar value = (column1 - oods_values[195]) / (point - pow292 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[195] * value; + + tempvar value = (column1 - oods_values[196]) / (point - pow293 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[196] * value; + + tempvar value = (column1 - oods_values[197]) / (point - pow294 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[197] * value; + + tempvar value = (column1 - oods_values[198]) / (point - pow295 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[198] * value; + + tempvar value = (column1 - oods_values[199]) / (point - pow296 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[199] * value; + + tempvar value = (column1 - oods_values[200]) / (point - pow297 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[200] * value; + + tempvar value = (column1 - oods_values[201]) / (point - pow299 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[201] * value; + + tempvar value = (column1 - oods_values[202]) / (point - pow302 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[202] * value; + + tempvar value = (column1 - oods_values[203]) / (point - pow303 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[203] * value; + + tempvar value = (column1 - oods_values[204]) / (point - pow304 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[204] * value; + + tempvar value = (column1 - oods_values[205]) / (point - pow308 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[205] * value; + + tempvar value = (column1 - oods_values[206]) / (point - pow309 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[206] * value; + + tempvar value = (column1 - oods_values[207]) / (point - pow310 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[207] * value; + + tempvar value = (column1 - oods_values[208]) / (point - pow311 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[208] * value; + + tempvar value = (column1 - oods_values[209]) / (point - pow312 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[209] * value; + + tempvar value = (column1 - oods_values[210]) / (point - pow313 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[210] * value; + + tempvar value = (column1 - oods_values[211]) / (point - pow314 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[211] * value; + + tempvar value = (column1 - oods_values[212]) / (point - pow315 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[212] * value; + + tempvar value = (column1 - oods_values[213]) / (point - pow319 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[213] * value; + + tempvar value = (column1 - oods_values[214]) / (point - pow320 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[214] * value; + + tempvar value = (column1 - oods_values[215]) / (point - pow322 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[215] * value; + + tempvar value = (column1 - oods_values[216]) / (point - pow323 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[216] * value; + + tempvar value = (column1 - oods_values[217]) / (point - pow324 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[217] * value; + + tempvar value = (column1 - oods_values[218]) / (point - pow325 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[218] * value; + + tempvar value = (column1 - oods_values[219]) / (point - pow326 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[219] * value; + + tempvar value = (column1 - oods_values[220]) / (point - pow330 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[220] * value; + + tempvar value = (column1 - oods_values[221]) / (point - pow331 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[221] * value; + + tempvar value = (column1 - oods_values[222]) / (point - pow332 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[222] * value; + + tempvar value = (column1 - oods_values[223]) / (point - pow333 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[223] * value; + + tempvar value = (column1 - oods_values[224]) / (point - pow334 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[224] * value; + + tempvar value = (column1 - oods_values[225]) / (point - pow336 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[225] * value; + + tempvar value = (column1 - oods_values[226]) / (point - pow337 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[226] * value; + + tempvar value = (column1 - oods_values[227]) / (point - pow338 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[227] * value; + + tempvar value = (column1 - oods_values[228]) / (point - pow339 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[228] * value; + + tempvar value = (column1 - oods_values[229]) / (point - pow340 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[229] * value; + + tempvar value = (column1 - oods_values[230]) / (point - pow341 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[230] * value; + + tempvar value = (column1 - oods_values[231]) / (point - pow342 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[231] * value; + + tempvar value = (column1 - oods_values[232]) / (point - pow343 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[232] * value; + + tempvar value = (column1 - oods_values[233]) / (point - pow344 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[233] * value; + + tempvar value = (column1 - oods_values[234]) / (point - pow345 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[234] * value; + + tempvar value = (column1 - oods_values[235]) / (point - pow349 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[235] * value; + + tempvar value = (column1 - oods_values[236]) / (point - pow350 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[236] * value; + + tempvar value = (column1 - oods_values[237]) / (point - pow352 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[237] * value; + + tempvar value = (column1 - oods_values[238]) / (point - pow353 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[238] * value; + + tempvar value = (column1 - oods_values[239]) / (point - pow355 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[239] * value; + + tempvar value = (column1 - oods_values[240]) / (point - pow356 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[240] * value; + + tempvar value = (column1 - oods_values[241]) / (point - pow358 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[241] * value; + + tempvar value = (column1 - oods_values[242]) / (point - pow359 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[242] * value; + + tempvar value = (column1 - oods_values[243]) / (point - pow360 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[243] * value; + + tempvar value = (column1 - oods_values[244]) / (point - pow361 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[244] * value; + + tempvar value = (column1 - oods_values[245]) / (point - pow362 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[245] * value; + + tempvar value = (column1 - oods_values[246]) / (point - pow363 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[246] * value; + + tempvar value = (column1 - oods_values[247]) / (point - pow365 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[247] * value; + + tempvar value = (column1 - oods_values[248]) / (point - pow366 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[248] * value; + + tempvar value = (column1 - oods_values[249]) / (point - pow367 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[249] * value; + + tempvar value = (column1 - oods_values[250]) / (point - pow368 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[250] * value; + + tempvar value = (column1 - oods_values[251]) / (point - pow369 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[251] * value; + + tempvar value = (column1 - oods_values[252]) / (point - pow370 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[252] * value; + + tempvar value = (column1 - oods_values[253]) / (point - pow377 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[253] * value; + + tempvar value = (column1 - oods_values[254]) / (point - pow378 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[254] * value; + + tempvar value = (column1 - oods_values[255]) / (point - pow379 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[255] * value; + + tempvar value = (column1 - oods_values[256]) / (point - pow380 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[256] * value; + + tempvar value = (column1 - oods_values[257]) / (point - pow384 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[257] * value; + + tempvar value = (column1 - oods_values[258]) / (point - pow385 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[258] * value; + + tempvar value = (column1 - oods_values[259]) / (point - pow386 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[259] * value; + + tempvar value = (column1 - oods_values[260]) / (point - pow387 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[260] * value; + + tempvar value = (column1 - oods_values[261]) / (point - pow388 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[261] * value; + + tempvar value = (column1 - oods_values[262]) / (point - pow389 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[262] * value; + + tempvar value = (column1 - oods_values[263]) / (point - pow391 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[263] * value; + + tempvar value = (column1 - oods_values[264]) / (point - pow392 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[264] * value; + + tempvar value = (column1 - oods_values[265]) / (point - pow393 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[265] * value; + + tempvar value = (column1 - oods_values[266]) / (point - pow394 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[266] * value; + + tempvar value = (column1 - oods_values[267]) / (point - pow396 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[267] * value; + + tempvar value = (column1 - oods_values[268]) / (point - pow397 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[268] * value; + + tempvar value = (column1 - oods_values[269]) / (point - pow398 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[269] * value; + + tempvar value = (column1 - oods_values[270]) / (point - pow399 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[270] * value; + + tempvar value = (column1 - oods_values[271]) / (point - pow400 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[271] * value; + + tempvar value = (column1 - oods_values[272]) / (point - pow401 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[272] * value; + + tempvar value = (column1 - oods_values[273]) / (point - pow406 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[273] * value; + + tempvar value = (column1 - oods_values[274]) / (point - pow407 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[274] * value; + + tempvar value = (column1 - oods_values[275]) / (point - pow409 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[275] * value; + + tempvar value = (column1 - oods_values[276]) / (point - pow410 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[276] * value; + + tempvar value = (column1 - oods_values[277]) / (point - pow411 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[277] * value; + + tempvar value = (column1 - oods_values[278]) / (point - pow413 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[278] * value; + + tempvar value = (column1 - oods_values[279]) / (point - pow414 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[279] * value; + + tempvar value = (column1 - oods_values[280]) / (point - pow415 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[280] * value; + + tempvar value = (column1 - oods_values[281]) / (point - pow416 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[281] * value; + + tempvar value = (column1 - oods_values[282]) / (point - pow417 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[282] * value; + + tempvar value = (column1 - oods_values[283]) / (point - pow418 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[283] * value; + + tempvar value = (column1 - oods_values[284]) / (point - pow419 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[284] * value; + + tempvar value = (column1 - oods_values[285]) / (point - pow420 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[285] * value; + + tempvar value = (column1 - oods_values[286]) / (point - pow422 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[286] * value; + + tempvar value = (column1 - oods_values[287]) / (point - pow426 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[287] * value; + + tempvar value = (column1 - oods_values[288]) / (point - pow427 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[288] * value; + + tempvar value = (column1 - oods_values[289]) / (point - pow428 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[289] * value; + + tempvar value = (column1 - oods_values[290]) / (point - pow429 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[290] * value; + + tempvar value = (column1 - oods_values[291]) / (point - pow430 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[291] * value; + + tempvar value = (column1 - oods_values[292]) / (point - pow431 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[292] * value; + + tempvar value = (column1 - oods_values[293]) / (point - pow432 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[293] * value; + + tempvar value = (column1 - oods_values[294]) / (point - pow433 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[294] * value; + + tempvar value = (column1 - oods_values[295]) / (point - pow435 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[295] * value; + + tempvar value = (column1 - oods_values[296]) / (point - pow436 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[296] * value; + + tempvar value = (column1 - oods_values[297]) / (point - pow438 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[297] * value; + + tempvar value = (column1 - oods_values[298]) / (point - pow439 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[298] * value; + + tempvar value = (column1 - oods_values[299]) / (point - pow441 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[299] * value; + + tempvar value = (column1 - oods_values[300]) / (point - pow442 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[300] * value; + + tempvar value = (column1 - oods_values[301]) / (point - pow443 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[301] * value; + + tempvar value = (column1 - oods_values[302]) / (point - pow444 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[302] * value; + + tempvar value = (column1 - oods_values[303]) / (point - pow445 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[303] * value; + + tempvar value = (column1 - oods_values[304]) / (point - pow446 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[304] * value; + + tempvar value = (column1 - oods_values[305]) / (point - pow451 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[305] * value; + + tempvar value = (column1 - oods_values[306]) / (point - pow452 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[306] * value; + + tempvar value = (column1 - oods_values[307]) / (point - pow455 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[307] * value; + + tempvar value = (column1 - oods_values[308]) / (point - pow456 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[308] * value; + + tempvar value = (column1 - oods_values[309]) / (point - pow459 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[309] * value; + + tempvar value = (column1 - oods_values[310]) / (point - pow460 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[310] * value; + + tempvar value = (column1 - oods_values[311]) / (point - pow461 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[311] * value; + + tempvar value = (column1 - oods_values[312]) / (point - pow462 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[312] * value; + + tempvar value = (column1 - oods_values[313]) / (point - pow463 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[313] * value; + + tempvar value = (column1 - oods_values[314]) / (point - pow464 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[314] * value; + + tempvar value = (column1 - oods_values[315]) / (point - pow465 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[315] * value; + + tempvar value = (column1 - oods_values[316]) / (point - pow466 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[316] * value; + + tempvar value = (column1 - oods_values[317]) / (point - pow469 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[317] * value; + + tempvar value = (column1 - oods_values[318]) / (point - pow470 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[318] * value; + + tempvar value = (column1 - oods_values[319]) / (point - pow473 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[319] * value; + + tempvar value = (column1 - oods_values[320]) / (point - pow474 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[320] * value; + + tempvar value = (column1 - oods_values[321]) / (point - pow475 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[321] * value; + + tempvar value = (column1 - oods_values[322]) / (point - pow476 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[322] * value; + + tempvar value = (column1 - oods_values[323]) / (point - pow479 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[323] * value; + + tempvar value = (column1 - oods_values[324]) / (point - pow480 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[324] * value; + + tempvar value = (column1 - oods_values[325]) / (point - pow481 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[325] * value; + + tempvar value = (column1 - oods_values[326]) / (point - pow482 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[326] * value; + + tempvar value = (column1 - oods_values[327]) / (point - pow487 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[327] * value; + + tempvar value = (column1 - oods_values[328]) / (point - pow488 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[328] * value; + + tempvar value = (column1 - oods_values[329]) / (point - pow489 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[329] * value; + + tempvar value = (column1 - oods_values[330]) / (point - pow490 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[330] * value; + + tempvar value = (column1 - oods_values[331]) / (point - pow491 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[331] * value; + + tempvar value = (column1 - oods_values[332]) / (point - pow492 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[332] * value; + + tempvar value = (column1 - oods_values[333]) / (point - pow493 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[333] * value; + + tempvar value = (column1 - oods_values[334]) / (point - pow494 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[334] * value; + + tempvar value = (column1 - oods_values[335]) / (point - pow495 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[335] * value; + + tempvar value = (column1 - oods_values[336]) / (point - pow496 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[336] * value; + + tempvar value = (column1 - oods_values[337]) / (point - pow497 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[337] * value; + + tempvar value = (column1 - oods_values[338]) / (point - pow498 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[338] * value; + + tempvar value = (column1 - oods_values[339]) / (point - pow499 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[339] * value; + + tempvar value = (column1 - oods_values[340]) / (point - pow502 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[340] * value; + + tempvar value = (column1 - oods_values[341]) / (point - pow504 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[341] * value; + + tempvar value = (column1 - oods_values[342]) / (point - pow505 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[342] * value; + + tempvar value = (column1 - oods_values[343]) / (point - pow507 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[343] * value; + + tempvar value = (column1 - oods_values[344]) / (point - pow509 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[344] * value; + + tempvar value = (column1 - oods_values[345]) / (point - pow510 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[345] * value; + + tempvar value = (column1 - oods_values[346]) / (point - pow511 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[346] * value; + + tempvar value = (column1 - oods_values[347]) / (point - pow512 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[347] * value; + + tempvar value = (column1 - oods_values[348]) / (point - pow513 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[348] * value; + + tempvar value = (column2 - oods_values[349]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[349] * value; + + tempvar value = (column2 - oods_values[350]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[350] * value; + + tempvar value = (column3 - oods_values[351]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[351] * value; + + tempvar value = (column3 - oods_values[352]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[352] * value; + + tempvar value = (column3 - oods_values[353]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[353] * value; + + tempvar value = (column3 - oods_values[354]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[354] * value; + + tempvar value = (column3 - oods_values[355]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[355] * value; + + tempvar value = (column3 - oods_values[356]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[356] * value; + + tempvar value = (column3 - oods_values[357]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[357] * value; + + tempvar value = (column3 - oods_values[358]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[358] * value; + + tempvar value = (column3 - oods_values[359]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[359] * value; + + tempvar value = (column3 - oods_values[360]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[360] * value; + + tempvar value = (column3 - oods_values[361]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[361] * value; + + tempvar value = (column3 - oods_values[362]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[362] * value; + + tempvar value = (column3 - oods_values[363]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[363] * value; + + tempvar value = (column3 - oods_values[364]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[364] * value; + + tempvar value = (column3 - oods_values[365]) / (point - pow14 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[365] * value; + + tempvar value = (column3 - oods_values[366]) / (point - pow15 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[366] * value; + + tempvar value = (column3 - oods_values[367]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[367] * value; + + tempvar value = (column3 - oods_values[368]) / (point - pow17 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[368] * value; + + tempvar value = (column3 - oods_values[369]) / (point - pow20 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[369] * value; + + tempvar value = (column3 - oods_values[370]) / (point - pow59 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[370] * value; + + tempvar value = (column3 - oods_values[371]) / (point - pow62 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[371] * value; + + tempvar value = (column3 - oods_values[372]) / (point - pow63 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[372] * value; + + tempvar value = (column3 - oods_values[373]) / (point - pow64 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[373] * value; + + tempvar value = (column3 - oods_values[374]) / (point - pow67 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[374] * value; + + tempvar value = (column3 - oods_values[375]) / (point - pow70 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[375] * value; + + tempvar value = (column3 - oods_values[376]) / (point - pow99 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[376] * value; + + tempvar value = (column3 - oods_values[377]) / (point - pow100 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[377] * value; + + tempvar value = (column3 - oods_values[378]) / (point - pow102 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[378] * value; + + tempvar value = (column3 - oods_values[379]) / (point - pow139 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[379] * value; + + tempvar value = (column3 - oods_values[380]) / (point - pow141 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[380] * value; + + tempvar value = (column3 - oods_values[381]) / (point - pow142 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[381] * value; + + tempvar value = (column3 - oods_values[382]) / (point - pow169 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[382] * value; + + tempvar value = (column3 - oods_values[383]) / (point - pow171 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[383] * value; + + tempvar value = (column3 - oods_values[384]) / (point - pow172 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[384] * value; + + tempvar value = (column3 - oods_values[385]) / (point - pow181 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[385] * value; + + tempvar value = (column3 - oods_values[386]) / (point - pow182 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[386] * value; + + tempvar value = (column3 - oods_values[387]) / (point - pow216 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[387] * value; + + tempvar value = (column3 - oods_values[388]) / (point - pow221 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[388] * value; + + tempvar value = (column3 - oods_values[389]) / (point - pow222 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[389] * value; + + tempvar value = (column3 - oods_values[390]) / (point - pow223 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[390] * value; + + tempvar value = (column3 - oods_values[391]) / (point - pow232 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[391] * value; + + tempvar value = (column3 - oods_values[392]) / (point - pow233 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[392] * value; + + tempvar value = (column3 - oods_values[393]) / (point - pow234 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[393] * value; + + tempvar value = (column3 - oods_values[394]) / (point - pow236 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[394] * value; + + tempvar value = (column3 - oods_values[395]) / (point - pow239 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[395] * value; + + tempvar value = (column3 - oods_values[396]) / (point - pow242 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[396] * value; + + tempvar value = (column3 - oods_values[397]) / (point - pow244 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[397] * value; + + tempvar value = (column3 - oods_values[398]) / (point - pow246 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[398] * value; + + tempvar value = (column3 - oods_values[399]) / (point - pow248 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[399] * value; + + tempvar value = (column3 - oods_values[400]) / (point - pow249 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[400] * value; + + tempvar value = (column3 - oods_values[401]) / (point - pow250 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[401] * value; + + tempvar value = (column3 - oods_values[402]) / (point - pow251 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[402] * value; + + tempvar value = (column3 - oods_values[403]) / (point - pow252 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[403] * value; + + tempvar value = (column3 - oods_values[404]) / (point - pow253 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[404] * value; + + tempvar value = (column3 - oods_values[405]) / (point - pow254 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[405] * value; + + tempvar value = (column3 - oods_values[406]) / (point - pow255 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[406] * value; + + tempvar value = (column3 - oods_values[407]) / (point - pow256 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[407] * value; + + tempvar value = (column3 - oods_values[408]) / (point - pow257 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[408] * value; + + tempvar value = (column3 - oods_values[409]) / (point - pow258 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[409] * value; + + tempvar value = (column3 - oods_values[410]) / (point - pow259 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[410] * value; + + tempvar value = (column3 - oods_values[411]) / (point - pow260 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[411] * value; + + tempvar value = (column3 - oods_values[412]) / (point - pow261 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[412] * value; + + tempvar value = (column3 - oods_values[413]) / (point - pow262 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[413] * value; + + tempvar value = (column3 - oods_values[414]) / (point - pow263 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[414] * value; + + tempvar value = (column3 - oods_values[415]) / (point - pow264 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[415] * value; + + tempvar value = (column3 - oods_values[416]) / (point - pow265 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[416] * value; + + tempvar value = (column3 - oods_values[417]) / (point - pow266 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[417] * value; + + tempvar value = (column3 - oods_values[418]) / (point - pow267 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[418] * value; + + tempvar value = (column3 - oods_values[419]) / (point - pow268 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[419] * value; + + tempvar value = (column3 - oods_values[420]) / (point - pow269 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[420] * value; + + tempvar value = (column3 - oods_values[421]) / (point - pow270 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[421] * value; + + tempvar value = (column3 - oods_values[422]) / (point - pow271 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[422] * value; + + tempvar value = (column3 - oods_values[423]) / (point - pow272 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[423] * value; + + tempvar value = (column3 - oods_values[424]) / (point - pow273 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[424] * value; + + tempvar value = (column3 - oods_values[425]) / (point - pow274 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[425] * value; + + tempvar value = (column3 - oods_values[426]) / (point - pow275 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[426] * value; + + tempvar value = (column3 - oods_values[427]) / (point - pow276 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[427] * value; + + tempvar value = (column3 - oods_values[428]) / (point - pow277 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[428] * value; + + tempvar value = (column3 - oods_values[429]) / (point - pow278 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[429] * value; + + tempvar value = (column3 - oods_values[430]) / (point - pow291 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[430] * value; + + tempvar value = (column3 - oods_values[431]) / (point - pow306 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[431] * value; + + tempvar value = (column3 - oods_values[432]) / (point - pow307 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[432] * value; + + tempvar value = (column3 - oods_values[433]) / (point - pow316 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[433] * value; + + tempvar value = (column3 - oods_values[434]) / (point - pow317 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[434] * value; + + tempvar value = (column3 - oods_values[435]) / (point - pow318 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[435] * value; + + tempvar value = (column3 - oods_values[436]) / (point - pow321 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[436] * value; + + tempvar value = (column3 - oods_values[437]) / (point - pow327 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[437] * value; + + tempvar value = (column3 - oods_values[438]) / (point - pow328 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[438] * value; + + tempvar value = (column3 - oods_values[439]) / (point - pow329 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[439] * value; + + tempvar value = (column3 - oods_values[440]) / (point - pow335 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[440] * value; + + tempvar value = (column3 - oods_values[441]) / (point - pow346 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[441] * value; + + tempvar value = (column3 - oods_values[442]) / (point - pow347 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[442] * value; + + tempvar value = (column3 - oods_values[443]) / (point - pow348 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[443] * value; + + tempvar value = (column3 - oods_values[444]) / (point - pow351 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[444] * value; + + tempvar value = (column3 - oods_values[445]) / (point - pow354 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[445] * value; + + tempvar value = (column3 - oods_values[446]) / (point - pow357 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[446] * value; + + tempvar value = (column3 - oods_values[447]) / (point - pow364 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[447] * value; + + tempvar value = (column3 - oods_values[448]) / (point - pow371 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[448] * value; + + tempvar value = (column3 - oods_values[449]) / (point - pow372 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[449] * value; + + tempvar value = (column3 - oods_values[450]) / (point - pow373 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[450] * value; + + tempvar value = (column3 - oods_values[451]) / (point - pow374 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[451] * value; + + tempvar value = (column3 - oods_values[452]) / (point - pow375 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[452] * value; + + tempvar value = (column3 - oods_values[453]) / (point - pow376 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[453] * value; + + tempvar value = (column3 - oods_values[454]) / (point - pow381 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[454] * value; + + tempvar value = (column3 - oods_values[455]) / (point - pow382 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[455] * value; + + tempvar value = (column3 - oods_values[456]) / (point - pow383 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[456] * value; + + tempvar value = (column3 - oods_values[457]) / (point - pow390 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[457] * value; + + tempvar value = (column3 - oods_values[458]) / (point - pow395 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[458] * value; + + tempvar value = (column3 - oods_values[459]) / (point - pow402 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[459] * value; + + tempvar value = (column3 - oods_values[460]) / (point - pow403 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[460] * value; + + tempvar value = (column3 - oods_values[461]) / (point - pow404 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[461] * value; + + tempvar value = (column3 - oods_values[462]) / (point - pow405 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[462] * value; + + tempvar value = (column3 - oods_values[463]) / (point - pow408 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[463] * value; + + tempvar value = (column3 - oods_values[464]) / (point - pow412 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[464] * value; + + tempvar value = (column3 - oods_values[465]) / (point - pow421 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[465] * value; + + tempvar value = (column3 - oods_values[466]) / (point - pow423 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[466] * value; + + tempvar value = (column3 - oods_values[467]) / (point - pow424 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[467] * value; + + tempvar value = (column3 - oods_values[468]) / (point - pow425 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[468] * value; + + tempvar value = (column3 - oods_values[469]) / (point - pow434 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[469] * value; + + tempvar value = (column3 - oods_values[470]) / (point - pow437 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[470] * value; + + tempvar value = (column3 - oods_values[471]) / (point - pow440 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[471] * value; + + tempvar value = (column3 - oods_values[472]) / (point - pow447 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[472] * value; + + tempvar value = (column3 - oods_values[473]) / (point - pow448 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[473] * value; + + tempvar value = (column3 - oods_values[474]) / (point - pow449 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[474] * value; + + tempvar value = (column3 - oods_values[475]) / (point - pow450 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[475] * value; + + tempvar value = (column3 - oods_values[476]) / (point - pow453 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[476] * value; + + tempvar value = (column3 - oods_values[477]) / (point - pow454 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[477] * value; + + tempvar value = (column3 - oods_values[478]) / (point - pow457 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[478] * value; + + tempvar value = (column3 - oods_values[479]) / (point - pow458 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[479] * value; + + tempvar value = (column3 - oods_values[480]) / (point - pow467 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[480] * value; + + tempvar value = (column3 - oods_values[481]) / (point - pow468 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[481] * value; + + tempvar value = (column3 - oods_values[482]) / (point - pow471 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[482] * value; + + tempvar value = (column3 - oods_values[483]) / (point - pow472 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[483] * value; + + tempvar value = (column3 - oods_values[484]) / (point - pow477 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[484] * value; + + tempvar value = (column3 - oods_values[485]) / (point - pow478 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[485] * value; + + tempvar value = (column3 - oods_values[486]) / (point - pow483 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[486] * value; + + tempvar value = (column3 - oods_values[487]) / (point - pow484 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[487] * value; + + tempvar value = (column3 - oods_values[488]) / (point - pow485 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[488] * value; + + tempvar value = (column3 - oods_values[489]) / (point - pow486 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[489] * value; + + tempvar value = (column3 - oods_values[490]) / (point - pow500 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[490] * value; + + tempvar value = (column3 - oods_values[491]) / (point - pow501 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[491] * value; + + tempvar value = (column3 - oods_values[492]) / (point - pow503 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[492] * value; + + tempvar value = (column3 - oods_values[493]) / (point - pow506 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[493] * value; + + tempvar value = (column3 - oods_values[494]) / (point - pow508 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[494] * value; + + tempvar value = (column4 - oods_values[495]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[495] * value; + + tempvar value = (column4 - oods_values[496]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[496] * value; + + tempvar value = (column4 - oods_values[497]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[497] * value; + + tempvar value = (column4 - oods_values[498]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[498] * value; + + tempvar value = (column4 - oods_values[499]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[499] * value; + + tempvar value = (column4 - oods_values[500]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[500] * value; + + tempvar value = (column4 - oods_values[501]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[501] * value; + + tempvar value = (column4 - oods_values[502]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[502] * value; + + tempvar value = (column4 - oods_values[503]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[503] * value; + + tempvar value = (column4 - oods_values[504]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[504] * value; + + tempvar value = (column4 - oods_values[505]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[505] * value; + + tempvar value = (column4 - oods_values[506]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[506] * value; + + tempvar value = (column4 - oods_values[507]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[507] * value; + + tempvar value = (column4 - oods_values[508]) / (point - pow23 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[508] * value; + + tempvar value = (column4 - oods_values[509]) / (point - pow24 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[509] * value; + + tempvar value = (column4 - oods_values[510]) / (point - pow32 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[510] * value; + + tempvar value = (column4 - oods_values[511]) / (point - pow33 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[511] * value; + + tempvar value = (column4 - oods_values[512]) / (point - pow36 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[512] * value; + + tempvar value = (column4 - oods_values[513]) / (point - pow41 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[513] * value; + + tempvar value = (column4 - oods_values[514]) / (point - pow42 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[514] * value; + + tempvar value = (column4 - oods_values[515]) / (point - pow43 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[515] * value; + + tempvar value = (column4 - oods_values[516]) / (point - pow52 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[516] * value; + + tempvar value = (column4 - oods_values[517]) / (point - pow53 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[517] * value; + + tempvar value = (column4 - oods_values[518]) / (point - pow54 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[518] * value; + + tempvar value = (column4 - oods_values[519]) / (point - pow65 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[519] * value; + + tempvar value = (column4 - oods_values[520]) / (point - pow71 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[520] * value; + + tempvar value = (column4 - oods_values[521]) / (point - pow72 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[521] * value; + + tempvar value = (column4 - oods_values[522]) / (point - pow84 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[522] * value; + + tempvar value = (column4 - oods_values[523]) / (point - pow85 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[523] * value; + + tempvar value = (column4 - oods_values[524]) / (point - pow112 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[524] * value; + + tempvar value = (column4 - oods_values[525]) / (point - pow113 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[525] * value; + + tempvar value = (column4 - oods_values[526]) / (point - pow122 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[526] * value; + + tempvar value = (column4 - oods_values[527]) / (point - pow123 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[527] * value; + + tempvar value = (column4 - oods_values[528]) / (point - pow146 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[528] * value; + + tempvar value = (column4 - oods_values[529]) / (point - pow151 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[529] * value; + + tempvar value = (column4 - oods_values[530]) / (point - pow193 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[530] * value; + + tempvar value = (column4 - oods_values[531]) / (point - pow238 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[531] * value; + + tempvar value = (column4 - oods_values[532]) / (point - pow241 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[532] * value; + + tempvar value = (column4 - oods_values[533]) / (point - pow243 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[533] * value; + + tempvar value = (column4 - oods_values[534]) / (point - pow245 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[534] * value; + + tempvar value = (column4 - oods_values[535]) / (point - pow280 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[535] * value; + + tempvar value = (column4 - oods_values[536]) / (point - pow282 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[536] * value; + + tempvar value = (column4 - oods_values[537]) / (point - pow285 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[537] * value; + + tempvar value = (column4 - oods_values[538]) / (point - pow290 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[538] * value; + + tempvar value = (column4 - oods_values[539]) / (point - pow298 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[539] * value; + + tempvar value = (column4 - oods_values[540]) / (point - pow300 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[540] * value; + + tempvar value = (column4 - oods_values[541]) / (point - pow301 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[541] * value; + + tempvar value = (column4 - oods_values[542]) / (point - pow305 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[542] * value; + + tempvar value = (column5 - oods_values[543]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[543] * value; + + tempvar value = (column5 - oods_values[544]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[544] * value; + + tempvar value = (column5 - oods_values[545]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[545] * value; + + tempvar value = (column5 - oods_values[546]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[546] * value; + + tempvar value = (column6 - oods_values[547]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[547] * value; + + tempvar value = (column6 - oods_values[548]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[548] * value; + + tempvar value = (column6 - oods_values[549]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[549] * value; + + tempvar value = (column6 - oods_values[550]) / (point - pow3 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[550] * value; + + tempvar value = (column6 - oods_values[551]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[551] * value; + + tempvar value = (column6 - oods_values[552]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[552] * value; + + tempvar value = (column6 - oods_values[553]) / (point - pow6 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[553] * value; + + tempvar value = (column6 - oods_values[554]) / (point - pow7 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[554] * value; + + tempvar value = (column6 - oods_values[555]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[555] * value; + + tempvar value = (column6 - oods_values[556]) / (point - pow9 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[556] * value; + + tempvar value = (column6 - oods_values[557]) / (point - pow11 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[557] * value; + + tempvar value = (column6 - oods_values[558]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[558] * value; + + tempvar value = (column6 - oods_values[559]) / (point - pow13 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[559] * value; + + tempvar value = (column6 - oods_values[560]) / (point - pow19 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[560] * value; + + tempvar value = (column6 - oods_values[561]) / (point - pow25 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[561] * value; + + tempvar value = (column6 - oods_values[562]) / (point - pow29 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[562] * value; + + tempvar value = (column6 - oods_values[563]) / (point - pow34 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[563] * value; + + tempvar value = (column6 - oods_values[564]) / (point - pow35 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[564] * value; + + tempvar value = (column6 - oods_values[565]) / (point - pow37 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[565] * value; + + tempvar value = (column6 - oods_values[566]) / (point - pow38 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[566] * value; + + tempvar value = (column6 - oods_values[567]) / (point - pow91 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[567] * value; + + tempvar value = (column6 - oods_values[568]) / (point - pow93 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[568] * value; + + tempvar value = (column6 - oods_values[569]) / (point - pow94 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[569] * value; + + tempvar value = (column6 - oods_values[570]) / (point - pow95 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[570] * value; + + tempvar value = (column6 - oods_values[571]) / (point - pow103 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[571] * value; + + tempvar value = (column6 - oods_values[572]) / (point - pow104 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[572] * value; + + tempvar value = (column6 - oods_values[573]) / (point - pow105 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[573] * value; + + tempvar value = (column6 - oods_values[574]) / (point - pow106 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[574] * value; + + tempvar value = (column6 - oods_values[575]) / (point - pow107 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[575] * value; + + tempvar value = (column6 - oods_values[576]) / (point - pow108 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[576] * value; + + tempvar value = (column6 - oods_values[577]) / (point - pow109 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[577] * value; + + tempvar value = (column6 - oods_values[578]) / (point - pow110 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[578] * value; + + tempvar value = (column6 - oods_values[579]) / (point - pow143 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[579] * value; + + tempvar value = (column7 - oods_values[580]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[580] * value; + + tempvar value = (column7 - oods_values[581]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[581] * value; + + tempvar value = (column7 - oods_values[582]) / (point - pow4 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[582] * value; + + tempvar value = (column7 - oods_values[583]) / (point - pow8 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[583] * value; + + tempvar value = (column7 - oods_values[584]) / (point - pow10 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[584] * value; + + tempvar value = (column7 - oods_values[585]) / (point - pow12 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[585] * value; + + tempvar value = (column7 - oods_values[586]) / (point - pow16 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[586] * value; + + tempvar value = (column7 - oods_values[587]) / (point - pow18 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[587] * value; + + tempvar value = (column8 - oods_values[588]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[588] * value; + + tempvar value = (column8 - oods_values[589]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[589] * value; + + tempvar value = (column9 - oods_values[590]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[590] * value; + + tempvar value = (column9 - oods_values[591]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[591] * value; + + tempvar value = (column10 - oods_values[592]) / (point - pow0 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[592] * value; + + tempvar value = (column10 - oods_values[593]) / (point - pow1 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[593] * value; + + tempvar value = (column10 - oods_values[594]) / (point - pow2 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[594] * value; + + tempvar value = (column10 - oods_values[595]) / (point - pow5 * oods_point); + tempvar total_sum = total_sum + constraint_coefficients[595] * value; + + // Sum the OODS boundary constraints on the composition polynomials. + let (oods_point_to_deg) = pow(oods_point, CONSTRAINT_DEGREE); + + tempvar value = (column_values[11] - oods_values[596]) / (point - oods_point_to_deg); + tempvar total_sum = total_sum + constraint_coefficients[596] * value; + + tempvar value = (column_values[12] - oods_values[597]) / (point - oods_point_to_deg); + tempvar total_sum = total_sum + constraint_coefficients[597] * value; + + static_assert 598 == MASK_SIZE + CONSTRAINT_DEGREE; + return (res=total_sum); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/recursive/composition.cairo b/src/starkware/cairo/stark_verifier/air/layouts/recursive/composition.cairo new file mode 100644 index 00000000..379a5aaa --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/recursive/composition.cairo @@ -0,0 +1,150 @@ +from starkware.cairo.common.ec import StarkCurve +from starkware.cairo.common.math import assert_nn +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_fp_and_pc +from starkware.cairo.stark_verifier.air.diluted import get_diluted_prod +from starkware.cairo.stark_verifier.air.layouts.recursive.autogenerated import ( + CONSTRAINT_DEGREE, + DILUTED_N_BITS, + DILUTED_SPACING, + KECCAK__RATIO, + MASK_SIZE, + N_CONSTRAINTS, + PEDERSEN_BUILTIN_RATIO, + PEDERSEN_BUILTIN_REPETITIONS, + PUBLIC_MEMORY_STEP, + eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.recursive.global_values import ( + EcPoint, + GlobalValues, + InteractionElements, +) +from starkware.cairo.stark_verifier.air.layouts.recursive.periodic_columns import ( + eval_keccak__keccak__keccak_round_key0, + eval_keccak__keccak__keccak_round_key1, + eval_keccak__keccak__keccak_round_key3, + eval_keccak__keccak__keccak_round_key7, + eval_keccak__keccak__keccak_round_key15, + eval_keccak__keccak__keccak_round_key31, + eval_keccak__keccak__keccak_round_key63, + eval_pedersen_x, + eval_pedersen_y, +) +from starkware.cairo.stark_verifier.air.layouts.recursive.public_verify import segments +from starkware.cairo.stark_verifier.air.public_input import get_public_memory_product_ratio +from starkware.cairo.stark_verifier.air.traces import TracesCommitment + +// Constants. +const SHIFT_POINT_X = 0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804; +const SHIFT_POINT_Y = 0x3ca0cfe4b3bc6ddf346d49d06ea0ed34e621062c0e056c1d0405d266e10268a; + +// Evaluates the composition polynomial at a point, given the mask_values and the constraint +// coefficients. +func traces_eval_composition_polynomial{range_check_ptr}( + air: felt*, + commitment: TracesCommitment*, + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_domain_size: felt, + trace_generator: felt, +) -> (res: felt) { + alloc_locals; + + tempvar interaction_elements = cast(commitment.interaction_elements, InteractionElements*); + tempvar public_input = commitment.public_input; + let (__fp__, _) = get_fp_and_pc(); + + // Public memory. + let memory_z = interaction_elements.memory__multi_column_perm__perm__interaction_elm; + let memory_alpha = interaction_elements.memory__multi_column_perm__hash_interaction_elm0; + tempvar public_memory_column_size = trace_domain_size / PUBLIC_MEMORY_STEP; + assert_nn(public_memory_column_size); + let (public_memory_prod_ratio) = get_public_memory_product_ratio( + public_input=public_input, + z=memory_z, + alpha=memory_alpha, + public_memory_column_size=public_memory_column_size, + ); + + // Diluted. + let diluted_z = interaction_elements.diluted_check__interaction_z; + let diluted_alpha = interaction_elements.diluted_check__interaction_alpha; + let (diluted_prod) = get_diluted_prod( + n_bits=DILUTED_N_BITS, spacing=DILUTED_SPACING, z=diluted_z, alpha=diluted_alpha + ); + + // Periodic columns. + let (n_steps) = pow(2, public_input.log_n_steps); + tempvar n_pedersen_hash_copies = n_steps / ( + PEDERSEN_BUILTIN_RATIO * PEDERSEN_BUILTIN_REPETITIONS); + assert_nn(n_pedersen_hash_copies); + let (pedersen_point) = pow(point, n_pedersen_hash_copies); + let (pedersen__points__x) = eval_pedersen_x(pedersen_point); + let (pedersen__points__y) = eval_pedersen_y(pedersen_point); + + tempvar n_keccak_component_copies = n_steps / (DILUTED_N_BITS * KECCAK__RATIO); + assert_nn(n_keccak_component_copies); + tempvar n_keccak_periodic_columns_copies = 2048 * n_keccak_component_copies; + let (keccak_point) = pow(point, n_keccak_periodic_columns_copies); + let (keccak__keccak__keccak_round_key0) = eval_keccak__keccak__keccak_round_key0(keccak_point); + let (keccak__keccak__keccak_round_key1) = eval_keccak__keccak__keccak_round_key1(keccak_point); + let (keccak__keccak__keccak_round_key3) = eval_keccak__keccak__keccak_round_key3(keccak_point); + let (keccak__keccak__keccak_round_key7) = eval_keccak__keccak__keccak_round_key7(keccak_point); + let (keccak__keccak__keccak_round_key15) = eval_keccak__keccak__keccak_round_key15( + keccak_point + ); + let (keccak__keccak__keccak_round_key31) = eval_keccak__keccak__keccak_round_key31( + keccak_point + ); + let (keccak__keccak__keccak_round_key63) = eval_keccak__keccak__keccak_round_key63( + keccak_point + ); + + // Global values. + local global_values: GlobalValues = GlobalValues( + trace_length=trace_domain_size, + initial_pc=public_input.segments[segments.PROGRAM].begin_addr, + final_pc=public_input.segments[segments.PROGRAM].stop_ptr, + initial_ap=public_input.segments[segments.EXECUTION].begin_addr, + final_ap=public_input.segments[segments.EXECUTION].stop_ptr, + initial_pedersen_addr=public_input.segments[segments.PEDERSEN].begin_addr, + initial_rc_addr=public_input.segments[segments.RANGE_CHECK].begin_addr, + initial_bitwise_addr=public_input.segments[segments.BITWISE].begin_addr, + initial_keccak_addr=public_input.segments[segments.KECCAK].begin_addr, + rc_min=public_input.rc_min, + rc_max=public_input.rc_max, + offset_size=2 ** 16, + half_offset_size=2 ** 15, + pedersen__shift_point=EcPoint(x=SHIFT_POINT_X, y=SHIFT_POINT_Y), + pedersen__points__x=pedersen__points__x, + pedersen__points__y=pedersen__points__y, + keccak__keccak__keccak_round_key0=keccak__keccak__keccak_round_key0, + keccak__keccak__keccak_round_key1=keccak__keccak__keccak_round_key1, + keccak__keccak__keccak_round_key3=keccak__keccak__keccak_round_key3, + keccak__keccak__keccak_round_key7=keccak__keccak__keccak_round_key7, + keccak__keccak__keccak_round_key15=keccak__keccak__keccak_round_key15, + keccak__keccak__keccak_round_key31=keccak__keccak__keccak_round_key31, + keccak__keccak__keccak_round_key63=keccak__keccak__keccak_round_key63, + memory__multi_column_perm__perm__interaction_elm=memory_z, + memory__multi_column_perm__hash_interaction_elm0=memory_alpha, + rc16__perm__interaction_elm=interaction_elements.rc16__perm__interaction_elm, + diluted_check__permutation__interaction_elm=( + interaction_elements.diluted_check__permutation__interaction_elm), + diluted_check__interaction_z=diluted_z, + diluted_check__interaction_alpha=diluted_alpha, + memory__multi_column_perm__perm__public_memory_prod=public_memory_prod_ratio, + rc16__perm__public_memory_prod=1, + diluted_check__first_elm=0, + diluted_check__permutation__public_memory_prod=1, + diluted_check__final_cum_val=diluted_prod); + + return eval_composition_polynomial( + mask_values=mask_values, + constraint_coefficients=constraint_coefficients, + point=point, + trace_generator=trace_generator, + global_values=&global_values, + ); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/recursive/global_values.cairo b/src/starkware/cairo/stark_verifier/air/layouts/recursive/global_values.cairo new file mode 100644 index 00000000..9590b88f --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/recursive/global_values.cairo @@ -0,0 +1,62 @@ +struct EcPoint { + x: felt, + y: felt, +} + +// Accumulation of member expressions for auto generated composition polynomial code. +struct GlobalValues { + // Public input. + trace_length: felt, + initial_pc: felt, + final_pc: felt, + initial_ap: felt, + final_ap: felt, + initial_pedersen_addr: felt, + initial_rc_addr: felt, + initial_bitwise_addr: felt, + initial_keccak_addr: felt, + rc_min: felt, + rc_max: felt, + + // Constants. + offset_size: felt, + half_offset_size: felt, + pedersen__shift_point: EcPoint, + + // Periodic columns. + pedersen__points__x: felt, + pedersen__points__y: felt, + keccak__keccak__keccak_round_key0: felt, + keccak__keccak__keccak_round_key1: felt, + keccak__keccak__keccak_round_key3: felt, + keccak__keccak__keccak_round_key7: felt, + keccak__keccak__keccak_round_key15: felt, + keccak__keccak__keccak_round_key31: felt, + keccak__keccak__keccak_round_key63: felt, + + // Interaction elements. + memory__multi_column_perm__perm__interaction_elm: felt, + memory__multi_column_perm__hash_interaction_elm0: felt, + rc16__perm__interaction_elm: felt, + diluted_check__permutation__interaction_elm: felt, + diluted_check__interaction_z: felt, + diluted_check__interaction_alpha: felt, + + // Permutation products. + memory__multi_column_perm__perm__public_memory_prod: felt, + rc16__perm__public_memory_prod: felt, + diluted_check__first_elm: felt, + diluted_check__permutation__public_memory_prod: felt, + diluted_check__final_cum_val: felt, +} + +// Elements that are sent from the prover after the commitment on the original trace. +// Used for components after the first interaction, e.g., memory and range check. +struct InteractionElements { + memory__multi_column_perm__perm__interaction_elm: felt, + memory__multi_column_perm__hash_interaction_elm0: felt, + rc16__perm__interaction_elm: felt, + diluted_check__permutation__interaction_elm: felt, + diluted_check__interaction_z: felt, + diluted_check__interaction_alpha: felt, +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/recursive/periodic_columns.cairo b/src/starkware/cairo/stark_verifier/air/layouts/recursive/periodic_columns.cairo new file mode 100644 index 00000000..6bf360d8 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/recursive/periodic_columns.cairo @@ -0,0 +1,1858 @@ +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_pedersen_x(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x43869b387c2d0eab20661ebdfaca58b4b23feac014e1e1d9413164312e77da); + tempvar res = res * point + (0x4cec4cd52fab6da76b4ab7a41ffd844aad8981917d2295273ff6ab2cce622d8); + tempvar res = res * point + (0x295046a010dd6757176414b0fd144c1d2517fc463df01a12c0ab58bbbac26ea); + tempvar res = res * point + (0x60105b3cb5aab151ce615173eaecbe94014ff5d72e884addcd4b9d973fed9fd); + tempvar res = res * point + (0x233eff8cfcc744de79d412f724898d13c0e53b1132046ee45db7a101242a73f); + tempvar res = res * point + (0x6f753527f0dec9b713d52f08e4556a3963a2f7e5e282b2e97ffde3e12569b76); + tempvar res = res * point + (0x549a83d43c90aaf1a28c445c81abc883cb61e4353a84ea0fcb15ccee6d6482f); + tempvar res = res * point + (0x4259be645aaf0a661e7877276fa5559ed7d04349f577595702efed3050402c5); + tempvar res = res * point + (0x71e67bd6a0b1b8518cb06837a78b92ab3dec98c4989f946285042655ffe516e); + tempvar res = res * point + (0x19b7924c29a944ecb61165a663d76d84e5ce44b4617fdbca8ff02fbdea6deba); + tempvar res = res * point + (0x70454f9541d96fc1552f984330389ff616cf80eaf699ba2e82b77f43fd163a); + tempvar res = res * point + (0x479c09d33c38f1c8f73247aace507da354ae87ca5cd4aa096bd3a6229e3006d); + tempvar res = res * point + (0x6fcf0e32e3e99f51d8cdac9c19cc25179eb97f2757844fa0c72e7c3bf453e4); + tempvar res = res * point + (0x4ccee6b6ecd4ea8733198e95935d13474d34cf54d7631fde59720e40378e1eb); + tempvar res = res * point + (0x627cb37206e5ee9da20c04a92cc765e3bd3f3d4e42ad4de0d709f366d446d8e); + tempvar res = res * point + (0x4183c04ef7d778f11e57b44c1a7f354c4497f1e3d420d3fa9f9c27c4bb58759); + tempvar res = res * point + (0x1e2c5c3fb2b47ea8cf33099c610f6132a5dd7099d29b02f4a041fe5947ff53b); + tempvar res = res * point + (0x4d44944716e0e13728fa8b84fde421f0f66a120ed2b7cfcf59f5ff6718b8b6c); + tempvar res = res * point + (0x394d0eed011068acc2f55f541c4d113a9c0afe7269cd7d9711aa7e8be661a60); + tempvar res = res * point + (0x52b5bdbcf28603ba60abcbf52bd4f7b4988ce0b4e2346e4875a3f117d4143b4); + tempvar res = res * point + (0x5975b93cee7a147a93cc98aabbb713f151924c4ede3306bb5e14e5e4d5d5c05); + tempvar res = res * point + (0x787053fc3649b17965b9e6ef5e05e024cdc188e90aef1cbf13ba78542a0407d); + tempvar res = res * point + (0x7cbef72611c8e1e08e52ca202382a8545bc7fe124ec080058988e45771e3b40); + tempvar res = res * point + (0x32bd55700baf7283995407f470139326a670d60a5d5428904596584629a053d); + tempvar res = res * point + (0x3485ad12aa365fac51a6296931abdcb54fa848c587cfbfe5bdbad2d6f6d3bd3); + tempvar res = res * point + (0x7f9850620a3435695ec7a6d9378cfe218ab0e5fa674cdc572fb9c197b0dbd25); + tempvar res = res * point + (0x1c7c40b6e4cd3d473e8f84b8fa63610ac6c7e3f4f0017f3ed84eae8f042bf15); + tempvar res = res * point + (0x1e3e1d970342085c482175cf60d93e1cc2cf96dec12f1d839b9b829cc957b7d); + tempvar res = res * point + (0x2d1547488e174e0a8662decd2cf020dd40718f070c84cf36bfa261aa90f814); + tempvar res = res * point + (0x31b8dd40040d22aae383c1e628e427f7aa4a7b0c3a83f815fd7ae2b36864af0); + tempvar res = res * point + (0x5efc7dfab3ad0b3f01e313c50ced95363d8dbaa9f91f801d6f1f00869467a16); + tempvar res = res * point + (0x724a3072c9f315cba63e5d99034b3218ff29a9bbf04155060ebdd6c848a652); + tempvar res = res * point + (0x2a0c1eade4037c10729bdc8a8f38bb5bf359078eedba633047377a09b6cde4d); + tempvar res = res * point + (0x6aacb14e31ebb5066e78eb597842812d7ad137880a6dd0d065c4acee231b7c3); + tempvar res = res * point + (0x468b88ba32ca1eac6c8d3196eea0561e25770818221ed0da3ae749e2a302e); + tempvar res = res * point + (0x5b52f487f8c3d78fb6ea4be227325a7386c7e95cd5f9b72710cfcc870cbba59); + tempvar res = res * point + (0x2bec10dd6a541c12555ff040b5949407713b4227867f53a435e80847b7932f0); + tempvar res = res * point + (0x41e1c8870eea4b7f4308e8173f97482d80afd055f07b1a058f182a775aef593); + tempvar res = res * point + (0x126a03f3c5cbe523484111d915d6d7eab5edad02a327a383171be09597336b4); + tempvar res = res * point + (0xa8db86341624832893780e36fe1f60490da5768f9aeb2a5803240f29ec5a2); + tempvar res = res * point + (0x751a8c7382e8fc0141b4ec5bf37fa457ab8301640b58cfc3b6a0b8d1a12bec2); + tempvar res = res * point + (0x5e56f3654b68256095b54a7868763aa3ff60a98ea3508039def82d2098d8a6d); + tempvar res = res * point + (0x60a9a4ccb72bde44d8a6c5f1d7b9303cc32013ef621bce1b8af413f00e77ef2); + tempvar res = res * point + (0x4efe82f8cacf9761cac9fefb6c13c1afdaed68ee650c37684bfce323070e480); + tempvar res = res * point + (0x40c43992a86359c71f5b8051d84d1fd6971eb36ab486f321a1fc50a52a02a44); + tempvar res = res * point + (0x538392c6ca2c04b5096aa69392b76ff109aabe165df488f3d1a8e5c4022db64); + tempvar res = res * point + (0x2b783063fa1948abfa91d79d225d52ed2ddd11bf20fc388b1ec00fdb5867921); + tempvar res = res * point + (0x1ec66f3f326120e659b78867bdfd7dac4dd3f1a92ffeaf46d39725de341afd4); + tempvar res = res * point + (0x5f4ed6b86202d76686a0b4c1efdfc93c46dce1b843c7181d1db1f8cd4d6dfb); + tempvar res = res * point + (0x34b9f6e8d5debbb4aea334310dc8d8075f896e7eb9f1c09788c7ec62ccb6116); + tempvar res = res * point + (0x4e57c6677d3bd56b425a3b3a92517344d4875e1710667e3dee1954395269af); + tempvar res = res * point + (0x1c5110241881e087e201d211da338d8377dd228afbd84850b76f3e5dfeb9361); + tempvar res = res * point + (0xa64b536ff29309d613af1c27c7229c3f6c583471c6b589b25026db08d3767a); + tempvar res = res * point + (0x3f6f9a9c3f6e175b59fd8e4268a6ae5734034fb1d7c43f97ef474b75ba80cc8); + tempvar res = res * point + (0x775ad15685181f15e34a6b0036c16fc8d1a9860ced1cc5ece39d19a6add939b); + tempvar res = res * point + (0x7775ec7b0ee9812c8df83957c5b46c316fdac82a2d736d4a6eea6124abc5849); + tempvar res = res * point + (0x41f320f863037e381ff83f2c9f1a8ae2802fc22cfea674d9cfd10171da6dea8); + tempvar res = res * point + (0x67649ac75ea692acb3aa4432d48de15aacfa347a37afdf489cc7e954e4ab100); + tempvar res = res * point + (0x7fd8c6108133b8109f4058192bd614b5de2c50afe7ac08a7bb0e0b12ef04e4f); + tempvar res = res * point + (0x57f8ef270683ea78b167dcbe5bb122a79ba760c95f8103dc4c6e7788fb1ac9c); + tempvar res = res * point + (0x6dc0d996fc95036c8cfa408fb12793bf8a4773d698f55085c2ccbc906c6d2d0); + tempvar res = res * point + (0x6713ddde3f2da61b676f5e4c52177bfc8c1576bc97ab3c48f08ff02d26cc03e); + tempvar res = res * point + (0x16b450dd2bb4712f6412b35603aaa02e7345124e5fd13e919c269f3874970f9); + tempvar res = res * point + (0x5f81b087ad750a0ebddd5239bb3682c84d88326b4679a24890f5fec98df45a); + tempvar res = res * point + (0x33f4151b710663772765df7f95b3710c3e8e81bacdbe3729b0a43b6d19e428c); + tempvar res = res * point + (0x5d122cd95f43fb6fc2373ef7e66072140f0f20d552f186faff2622b55a3e063); + tempvar res = res * point + (0x9b478a0767cca2c6f9b4268bffc9e907eb69b32f8ff7b43fc24edd38a88ec2); + tempvar res = res * point + (0x597cee65bc7c6f0faa3e0aa1958897acf7fd4e4e69569f5d18254b0b8c09aab); + tempvar res = res * point + (0x218bc11c668ef7ae5f04a16dc9933c5bc41c194a439d0af802568e598c54630); + tempvar res = res * point + (0x3394eac0b3787b323686cddaef3af972d7fbbd75940bf7f682b8fe3676cd46b); + tempvar res = res * point + (0x4aeb3836ccb2a9ebf9f1c5b6ee3c42f66c8059cc55188335a47a3583d986018); + tempvar res = res * point + (0x5db68a5c4527fff0ebf61fe064888b0fb6e277cfecca6d206986293256f31f); + tempvar res = res * point + (0x63372394d373e7a2f2fa6405509da05fe9cb546ea2742ac0716bccf50ad9227); + tempvar res = res * point + (0x22d4ed1a29943bc16343e01eab25e45adf74b6a7072e4e26aa8d141f2cac5ca); + tempvar res = res * point + (0xf8ea3b2c0b72747301b2778cc071cb9d2e09bbdd7a386b7931582ab412dbd1); + tempvar res = res * point + (0xf78d4b72e0f5f55913884d0714674dd6f534b211ec5dcdba419347828c7c35); + tempvar res = res * point + (0x5142430fc3f872dd6fefb7e9804e3e63714f71a2f43b155cebc53671f964af); + tempvar res = res * point + (0x72fe5010e70102306b21cc388b7f2ab8b0324b84654cf98032b83a81099e72e); + tempvar res = res * point + (0xfd959b09bb704fe63c73e2331f8e76dc1fbf85c2dc9dcaa0e8108664f7f988); + tempvar res = res * point + (0x4180556f79a47df725eca2c2f65389e27281443847a7d9e84640e6d589182f7); + tempvar res = res * point + (0x2dc12726f7f06ef1adfb10747e5d4ef8052e4e57bad9bb10529d7994ef91035); + tempvar res = res * point + (0x3c62720cac42a262b58765d7c0588231c5c2c9ce9d48f0fd547575289ede8c8); + tempvar res = res * point + (0x5744178090cdd56ae12fdd51b74bc097f23f735b7ca16e415a1854597b1caf8); + tempvar res = res * point + (0x597cbefb648f47e763b9b1be8c3f815a0e8b65d0101e11b5bedc380c10e9f4); + tempvar res = res * point + (0x78e66ae8b3ef57289d92561dbe4ef72f4ee551d5cad363720a78d104a89163); + tempvar res = res * point + (0x3cb89319d8172da012c036c40116fd325d65af69f80a1df8f56ec890e920592); + tempvar res = res * point + (0x29d152196b7ea7446182efe778a2db796f5fab17286405953476ac97f94a96a); + tempvar res = res * point + (0x6348748d43d48acafb8ce688f25a1245df86dd20c3a96c5c85cfc0960ca2fa7); + tempvar res = res * point + (0x3609fff81e15da2a88036d1c2d28814035ce829430fabcc3986c08acdc2d44); + tempvar res = res * point + (0x3241fcabfd99b666b151970558fb59fdfca47ded4caf2af4b15839767edb190); + tempvar res = res * point + (0x3f61241934753ca9c4f4210885b87863abdc8637d4dafe5da4bfa5e0206988e); + tempvar res = res * point + (0x6a16c0b648c72c8d718d53099cb11725ee09fe1b49487d8f55f307a6a265920); + tempvar res = res * point + (0x43ef0fbc56a0a46c7099f5e6d6550a77e1ac023e2201f01bde0a3f5fb0f16a5); + tempvar res = res * point + (0x1f6bf768424619cc2d34c01cbf4e137b6cc33a4a5a3db0bc704f790f86ad67c); + tempvar res = res * point + (0x49eac48d453d5de07fe3f4bdb5aac21e7fe69858afedfbeb0daf175459dd9d7); + tempvar res = res * point + (0x2a390a6737563e9edc22b0b0cce94a67adc10db18d6f978c826f24b8848c6df); + tempvar res = res * point + (0x23e127bf290465acfb7500962d426be5241f0e8c6f844d25aa8e262df6e70cb); + tempvar res = res * point + (0x5e51a00b7437caee2acdb81781212bc3d1c397b477ec784d1a7b304c9f8c687); + tempvar res = res * point + (0x6e52308f62433fe92ca9064e06aa17d793d3ad7bedb9590c8bb9edd3272fbae); + tempvar res = res * point + (0x7aa1d2348e13a031dc4fa20d453fcd59eead9adbccc3ea64997d09a0f58216b); + tempvar res = res * point + (0x1c02d3ffc30c7172a132ac604ad28e89466845c139dba509b896c997ee4ce8a); + tempvar res = res * point + (0x3ea018d81f9118cb5cf251d6c795b4ca4aeeb28d6ea5464fb4807d219453728); + tempvar res = res * point + (0x62c2fa993dee607ef195fb6620051b4df127d933de3a417d21de3b0c6dfdc95); + tempvar res = res * point + (0x2fd6fab5c4d0e6bd5bf5b950632e2dfc3be19c9a80e3bf8934e878003b0816a); + tempvar res = res * point + (0x12f2b0b280b64cb9f6bd77cd5103b7668ae42e5d40ae156607c69043b4da5a9); + tempvar res = res * point + (0x51a3ba83e3f68b2df85f3b9e770b5294312fd634fa48ace215a029fdb5593); + tempvar res = res * point + (0x56f19df91009289c7f5304026cf6d2c26541cd4caf867b2d2ea8a954560ed7b); + tempvar res = res * point + (0x362dd19b8207511079a352fad991df9582315ca2539ed4da5cbb5b82e414fc5); + tempvar res = res * point + (0x2dd7ddf328b439b3047a93c6fff6ef901946438cbb55a4c1fa1848f80baf2ce); + tempvar res = res * point + (0x2120274511adcc680703d33146477a31c42684b5163a628eb3f84258ae78786); + tempvar res = res * point + (0x11076126b67298371103d89e76ec2fbe30b28c5de422e61d3fade2e190450a4); + tempvar res = res * point + (0x1868ebbc59cb1c69b32ea2b3a7ce3f87b680731b96a42403878df0a0e4bb3e2); + tempvar res = res * point + (0x5b7abf66fda1917e0e1d44924cb73d713b5fc16b3a64bd4857d089adfd6a814); + tempvar res = res * point + (0x13df9c113e40f246d806089e437629de52f8a247ece912785004efcafd4ea94); + tempvar res = res * point + (0xbdcc31feec5ca8cfbf7227269d1e120132c51307ec03cc2d59c471e2510a24); + tempvar res = res * point + (0x3b2efe16624d8d0a1beeb037b02f0a4f7e11eb3859852cea1f83ab1752a4099); + tempvar res = res * point + (0x596104fc8bded038e39f0de5e80a2f2b65fd39fa4ab7b3453bbe8a40e06a317); + tempvar res = res * point + (0x5fec9e8e9ad35ec1091706f4f39c0e8a610f58be6c987c2327ce0794af7cb7c); + tempvar res = res * point + (0x5fb45888a7861e18a320bff7b0baee50ef9cbe1b06c78a5a16a6fbda3c6b77f); + tempvar res = res * point + (0x2c15afc87ef81cb58ec29c7dd81b4cfe291e5d33a7b36126289a8ebc1af4eb4); + tempvar res = res * point + (0x1f90c3eb7ed36bec79f803ab1884e5455581110ab713139cdb5207561a89a34); + tempvar res = res * point + (0x7c537f749e37ed15d7e5d5d0f88686c5d02242b6c487ae2c5606d2c7de986b6); + tempvar res = res * point + (0x4db0795b76ed3b5cf3cbc23bc47d20abe9b9f76a2731f2774e6dd5ecd6eea05); + tempvar res = res * point + (0x3a7ada56cb16708c6eee7af3688765728c706a16baf61d0582186a3717ef552); + tempvar res = res * point + (0x4c9b9f2c154c6a8cb1fbf50793787d215f2857d042b21c6f5e2740732cca567); + tempvar res = res * point + (0xdf2e87cea7f46ab09a5011d8afca4e7cb962e008fc991ea16d85c472dcf3ef); + tempvar res = res * point + (0x4df83db997cffc8598b838a9c8373bfff5e109d71ee3bf2a18dc0e621e93d2d); + tempvar res = res * point + (0x17eb7ae4a950bce2abe1e7165594eaa60be7b75cefd8007425a735264a1371a); + tempvar res = res * point + (0x6c8258350c092e7b5cf658a6bed95d620afe0563482911a1435a93bcb0d5beb); + tempvar res = res * point + (0x554563c23e6ec8a4497d670e81940a92ddad53c27e7bbc18de74d2b3734d824); + tempvar res = res * point + (0x6c9568c4a9f64874e71c88cc80576e4083f6d0649f66929612a9bb99bd958e1); + tempvar res = res * point + (0x14e46f8471beb6479fadac1286dc86683c659bf1c77dc96bcb303d48c115d7e); + tempvar res = res * point + (0x5eb4774b76a39af609243ea0ca61eaf03255a02d90be9a83901debf64875f0b); + tempvar res = res * point + (0x3317e8a32e8f82246423237d2a4039eba358a76adb8065751b6d7939fadb85c); + tempvar res = res * point + (0x6cfe464b2a4d4e77c09e0beceb4e368bd93aae5efaddbb92e003afc508fcb33); + tempvar res = res * point + (0x3b69a8579df2cea96435a07c81ae1d9f8a5e0e52433335c3e7ad81b76789788); + tempvar res = res * point + (0x3f26981ddcd3549baf47e3f1242b0bb90d6b7f426ba71d2ce628ceb801f3734); + tempvar res = res * point + (0x40d8fb43bbc7e5c35e4b57fef4e8351ffb118c9d92346f97ff7cb48b0170eff); + tempvar res = res * point + (0x19eec9d276c006f19cfa904a4e2ead857e99000d16e897dc8dc955c57615d54); + tempvar res = res * point + (0xcfff274a78e56ec27e29d01f2e900bd226cdb493a83358f9b807235c9aa407); + tempvar res = res * point + (0x13d4454abb9515f00c3daa6034ed3759ea722a953679c4f857511141b87da93); + tempvar res = res * point + (0x2ea5039159478e68762063624b0f396cb7f1bbfe8c1a159f65f0f663f219136); + tempvar res = res * point + (0x40508ab9b5b8d885f85750bb659071d6cc04639f43070b94a802d41723bd0f3); + tempvar res = res * point + (0x40a9f47d93280a641e7f903b1e608cb443ed5d59f24cde6b92c6631cab1e009); + tempvar res = res * point + (0x5a5085cb551c472af264b5de50ebb7b4bb04539c9afac1339f903b943578eea); + tempvar res = res * point + (0xa89bb9df4a46c56f2f40748d826d50285082118f8995f5e7638a05ec117c47); + tempvar res = res * point + (0x5950e4370508dbfa764621025e9341994a3ac21848f3e39d02370b193ba6937); + tempvar res = res * point + (0x6f20da2f1a25f1fab33e7856067226784ad992f8bb53249ee7bb17e86c82070); + tempvar res = res * point + (0x42271e06f205c1bfc9f9d9411bf835f43941c88aa3dc75f044a0143faa4d5cc); + tempvar res = res * point + (0x411f9def562556de87d47af60354512d9a1261152e7f4636038699d468fc2bb); + tempvar res = res * point + (0x66490371a5dfa3fb85bf3f088b89614b5e56cafc263eec39dc4a1bb39e03433); + tempvar res = res * point + (0x6d49bd35b4e4aa46b7098d306632014b4fbfd84892d6997b58d9463a0ea2c05); + tempvar res = res * point + (0xa9c2bf87d58d3f72d985b4b1129f0a1664caac1ee26a15675d1a5086de3a79); + tempvar res = res * point + (0x46df5faa750270394a4253e63ba3e437550ee216ebf8ddbbd7304940c85ad02); + tempvar res = res * point + (0x6e5bf767f3b0646dc16377f3bb7c17db6069555e100dd2215eb20c4d29fb1c3); + tempvar res = res * point + (0x5d9acf8582d4ccc017af36a8a9863e4383b63893d3fb5d81f7fabf4ba3d1023); + tempvar res = res * point + (0x6933ce3f88628188f7a1b1be5b0506dedadd9559c4766be0e7db1ace3adb592); + tempvar res = res * point + (0x40ba0e2f504aa0e9972018d91be21f56bde16361282915563796c750f8936b7); + tempvar res = res * point + (0x6fd73eabd21a86dd8094dd0ebb5924b1aab0753a0d251571ea93f83ab4bd519); + tempvar res = res * point + (0x2761e32194ddef695d1837c8a3f48a3773ae392b5633bfa0c1451e51e33b69b); + tempvar res = res * point + (0x5519091c464bab5646294ae41d087ddcef8bd0508a94a07890fa07220bdaad3); + tempvar res = res * point + (0x3b160cef807b72e95938852093a3a633e72b61e0afad5099201885b54be4098); + tempvar res = res * point + (0x7692b996dcfecd35db6aa22de10144724c478f85a328ab893c6fbadf43d7a9e); + tempvar res = res * point + (0x3512eb8a3bbded6fad1c19190d857629efc56f93fb4aa527e2958dfcce12153); + tempvar res = res * point + (0x591ad3fb7ab83f8d9fcf184ab793baf3db128cda0de1618932851108771cf0d); + tempvar res = res * point + (0x5f7da39edb0781ca1f96af191cf4c70fe0c121b7b2c92f09b49503bb070dc99); + tempvar res = res * point + (0x4a94669a4901cb5527124a2dc7ff6c278d540da41a95e819d0ca10269f7b380); + tempvar res = res * point + (0x20a06257ccfa90a74adf9bb1130a8385b8c91bc61e18acc30843463e5abaa2); + tempvar res = res * point + (0x7e3c052c620ef7fcf180898d28e39348e96e92ed0634dcae3f5fc64be5094a6); + tempvar res = res * point + (0x578dfc700a95a564b41ba8f33b885ad04209bf5169a4046f603a3d84f792d6d); + tempvar res = res * point + (0x796c9b073e2c56f55601eb1f6147d028553275e9fb792f0b76007c9710459c7); + tempvar res = res * point + (0x8c2c75a2fe00432f77ef57e906f264ea76c439e0c4cb19e87867a6ebb34d0a); + tempvar res = res * point + (0x525fee2e2cdb7a293f50f630a840d5cf5f29a158eadd6fa9d0159951712d19a); + tempvar res = res * point + (0x7991462c103abfc3bc31427227b1fb82f7fdf2be1b39316f46e3baef2fcf588); + tempvar res = res * point + (0x46d1e806178137e82ea97c54d8c15dd45c2a9a0082b18aeb9f849158ffc0ee5); + tempvar res = res * point + (0x25a127bbf961fe2b5bd9facbda706223206c40acff003152cbb3b28e9668030); + tempvar res = res * point + (0x1e3d7c65a8f40b6f8aab1635e3b78d0f798746532f08771267a9b6149632a5a); + tempvar res = res * point + (0x25fc8ba8ab421b6dacf2ce03263e037374e4d61c6ce26422fbcb2e755c0d9c4); + tempvar res = res * point + (0x48294f41052135cca94fcf88cf236437b8a55370c3de81fb0d781aa7b0f8eca); + tempvar res = res * point + (0x8c5762a12210a7fdc96a7d3aa966476d3b28650e7c49fc90f95e49a80d4324); + tempvar res = res * point + (0x4ffe8275d3344b4ae2f7d9992d68598e50f365c0b8a721d723841485fc25c0d); + tempvar res = res * point + (0x2959a6947bc4eee0135bbd0a6f2053b62317a1718bcceecbd507417d31e8806); + tempvar res = res * point + (0x77efd8893058f8e00863205582a5e274c344b9af63b9c40ddd92c97c33b52ea); + tempvar res = res * point + (0x73796a0ce0fe851bc22b99faded48a24a21745bb62603e750f78b854d7c32c7); + tempvar res = res * point + (0x2d2e43c0ad60d4265774479258211274ae32b5e151aacf6f8ac1b7708076f09); + tempvar res = res * point + (0x22b5eab11c9e1e6b8d64d5db4b12502fdf0899497f72ee1a27c8797b617f76d); + tempvar res = res * point + (0x703c768145191a10344e5ca400be8fd249e653d564015d46fcd7096cb723a0); + tempvar res = res * point + (0x4159f8056bde7fd4f72615f7bdd0bb6408256b8b216ca52fee253113d9d007c); + tempvar res = res * point + (0x5fde2cdf0d23d5649e3aead1b2b90ca0309715a029654e8984e43de7bde7b06); + tempvar res = res * point + (0x50372d2aff2ebc566505a564d971c6491095e009d9887899aee0b5017fcb877); + tempvar res = res * point + (0x3333c3d925d8c58b9e4e533531e93046039577cf0e57d011c7ce87c6ef1a835); + tempvar res = res * point + (0x575fb11a4d7e3876ae4c86b80b4b9530e0d3e9db218f4d5644f612348f8f002); + tempvar res = res * point + (0x3481879ec47fc8cfabf38ffaa75311c787b7006e7f9def35e96454263bba4aa); + tempvar res = res * point + (0x5c1e733995aad208f0697e4d2a6e28bec9fddc3e30bd033f2f50a83927baef1); + tempvar res = res * point + (0x2edf44b1f59efb0f36c0fce5edbb7576c89cb9f191300fc5e0240def1b88b9d); + tempvar res = res * point + (0x1d46036b736e06016c817d2b51a0918189881a4f1b7c71d556db583df762d37); + tempvar res = res * point + (0x258ef77b90879282ccc2ffcea5052cad266d77b75db36b7996e5fe7638e9b00); + tempvar res = res * point + (0x4219a0a13e09662f3ec712da51b36967947f6d5a09d8044e3005a7f0ab45915); + tempvar res = res * point + (0x18d0f552fd62f81b6076265c7a3a0b81f6bd37152a2f16c71210021ecf68468); + tempvar res = res * point + (0x31abb6310a44d65ac8c308011d4afab938fdacfbaec14c62b808452310b799b); + tempvar res = res * point + (0x1765a9eca4f4551f177b35089f8befc808613bbcd971a47d485b1c220d0bbb4); + tempvar res = res * point + (0x7fd44af0ef24f061aa7dd5bbde15098dfc3721790ee9bac2caa71cca714ebf0); + tempvar res = res * point + (0x566edfbe3c59cbd43838ee245edfebe292c7163f79b1454b03ef3cf8af23c10); + tempvar res = res * point + (0x14d01a0c81aa61c5a238243e78afe80e5d0d7bf528c3d05a343d0f4470d2b0a); + tempvar res = res * point + (0x38445d5f2de7993c48c9da8e77a87dbe289dc0428b1e4ca87e30b2376535543); + tempvar res = res * point + (0x324db878e3842c25a78e94453c98434c54b41955db62234b0ec5ddde6641556); + tempvar res = res * point + (0x184f23c10c726d4a7036c39466db02c4fe7c3d40bade571fe07acaa282f4c07); + tempvar res = res * point + (0x7fb1cbd7a48f2d44a148bd4d17ccd47c438f4f1b45a02945cf4312afa0d6f95); + tempvar res = res * point + (0x20d2002cba899acc7d333031e0977d8df94557ca0749bef6c38b72dbcd462f); + tempvar res = res * point + (0x75bd5b63008c2e005df64ca189ecce11c060f0df6903011a3d95cf9f7b48878); + tempvar res = res * point + (0x548724b5683cd6427513b4c4f84a6d888b9a03843bc0dbdc501b8752d99ada1); + tempvar res = res * point + (0x38441dfe93fd3133faf52208f3263d4ecaca0643bf9c9d4bc952c86cf280f7a); + tempvar res = res * point + (0x182e50e36b753ff5f95f2bc47a6aac8c6f2e5c3975476252a7c29250eefb056); + tempvar res = res * point + (0x2593b010eb6fe0f64833e4f22f6854c063085e0dd393226e6b5fb20ea7f432d); + tempvar res = res * point + (0xcc060a8b007b2dd0efa786afa5edcb512d83ddcba8ed69c27ccef5769deb23); + tempvar res = res * point + (0x672717b74bc3dca9e53494681a5ffa02edbb0290de1c5209843a16964df7a3); + tempvar res = res * point + (0x53774852c8f84d21eec107e1da7a2ab3f4b5ceba6479d1f902ad404e7dde329); + tempvar res = res * point + (0x96de7b9a7eac739df4d13902971804aaf40f5559d18593be0daac0ff86c636); + tempvar res = res * point + (0x725601ed4fcfdaa392b91e8ea982fc57f1874378ab8d6b55301b3d4b6efd802); + tempvar res = res * point + (0x7bc4fea0ea687295d72735a62a19c1a160a1b9a19342717b527f94770aca77); + tempvar res = res * point + (0x3dfab578cfc7a1581212074e0969db9accb619a043dd7194a253af67ef3698); + tempvar res = res * point + (0x44090861421dbb6b4a325a6832e02986be80f7ea475313ae01a3215c3510346); + tempvar res = res * point + (0x7384363b4495aacafd81d0a139a66afd3243309395e3444fb3f1496832240a9); + tempvar res = res * point + (0x4f6ea70b9090971f8de7071f27b0d036b112211403e0547fb7b7903704f295b); + tempvar res = res * point + (0xd55dad93e837d31e8f120398e09b83ca68f160c16043e1c65d033a19adbc30); + tempvar res = res * point + (0x6cc09dc2faf0903dbf5121b97ef058300b18efcc30c25f55de752d395b568a9); + tempvar res = res * point + (0x2b2091e41b10140bea196a1cc28d7f6db6ae1b55d1f115d882c321221a32eb4); + tempvar res = res * point + (0x11b19b3abd2b297728768027b1370566bd845bfb6f49197a76255c1d8c661f); + tempvar res = res * point + (0x3236ab2e0e0b1b013c2100283e36fe75521bd50091f1c73deb165e86616d80a); + tempvar res = res * point + (0x7351448e92ce6914278e73ceeb080e280c146dbcc21cb35af8d2c7e5560aa7d); + tempvar res = res * point + (0x100a89bccb889f183c2a6ced12bab8ef86403230ae6b23def0b784f73ff296f); + tempvar res = res * point + (0x31e49312e1d59acae36bf3562443259500039a7a77d9a57a44cbbb4a80932e3); + tempvar res = res * point + (0x273647256f95d2e5f98bd7830191abd89dc4ab241fc7fa12b27e16a6bd423c3); + tempvar res = res * point + (0x424396bedfddf4192963ef0f87b3989a99f277fe2c60756a4a60fae4d6dfa31); + tempvar res = res * point + (0x6e3a0355459b8b7c35837f3f19f0d8954907326cb08d7d084f2ed0f4b2af8f5); + tempvar res = res * point + (0x2d88caa65f47db103fb1ca354bf50c93f24bca5001598f716b6c9e5c51d1d2); + tempvar res = res * point + (0x2dca037a615e8cf99f8614f437e953c5625b9b57d95f16c174f63346e31c5da); + tempvar res = res * point + (0x5800bf15808a39f1acfbb193af1ab0c22f18d9738753bd3cd2aeea81982409e); + tempvar res = res * point + (0x4ad97a9b0ab95abc1b8fcff31a48e18fb2391ac95baaacc62125bd87fd75e13); + tempvar res = res * point + (0x5ba49d41f62b6d6903fc455bf02bca54becb6ee7f39650fcd0b717ac396159c); + tempvar res = res * point + (0x959c7bf3885d75ab3ca9480101ff64d62c9f138d35f63c137009c1b3eb39f3); + tempvar res = res * point + (0x6da06ce868c140c8ff9ec1eb0323fe2c8b35b46c8d4f5a27727450e87ebd906); + tempvar res = res * point + (0x1bf01c19527dd1d9094c44e3acee4d1ec8c4192026b6f996776294cc9dbc4a8); + tempvar res = res * point + (0x40d1ae7e7bcddc520ed8c0fd736e9b5147d278ed1b720abf76439377023abea); + tempvar res = res * point + (0x2f26fb29017b5ab80328de8488db547e47c44c0d56f30e330354d5b980e50ad); + tempvar res = res * point + (0x72bcdfbdd09f13eeb0c01565dc6a79999a9642dbcb0c570e3e7621ca94df215); + tempvar res = res * point + (0x140ed138dfc5b5417b25a4512bb991f3fd04cf750e082fd4fb82cc15b645835); + tempvar res = res * point + (0x40ffb20c2a3dba0a0d8b6aa51ccaa1b690aa08670ceee556d76053cd671d522); + tempvar res = res * point + (0x283c74c8066141911634401af10106c29dd77458d059ff3b2dd7aa796b2a559); + tempvar res = res * point + (0x593df80dd238cbdc6398146502310a5cb459b0e7d79fa9bee5cc389385c95b3); + tempvar res = res * point + (0x669bfada09faa64c005321d60752662598d69c517e9ffa462dc1b1af42228d1); + tempvar res = res * point + (0x70cc78b821b198e72f8feeb8f31d81e5a4854de3575a62909e0bb51cee921d0); + tempvar res = res * point + (0x68539d0ccd1737a8b2e540f9165638f86f6c4e44943455d311999b0b3684b7d); + tempvar res = res * point + (0xbb867c323532bde3d5b0e08b1b7531a95a2a1706132dcd8ebb7063cd1b1bbb); + tempvar res = res * point + (0x751a2c218f4feffc61e90939c4d2672a263d3b33528c7c6eb40042640f45146); + tempvar res = res * point + (0x6473d78fc37e48379ef8a9d57e3e92cf4fdad3a1bcc170dd177dbc51c4dc62c); + tempvar res = res * point + (0x7218f86344ea46cdcc372a22a14663105eef03bb0de9da9bfcd10818d36ba28); + tempvar res = res * point + (0xaa17b17cdb757833dd4b1670371ef55345debfb2c1b6bdfae64d8759e04349); + tempvar res = res * point + (0x38cb4173a2b057da41d5d30b55f6d11f25effdc69c14843cc43a9ab269630f0); + tempvar res = res * point + (0x4350a29d7b4b242b20b68f6eabd75b758d8631c192b7da5032181b71740b96b); + tempvar res = res * point + (0x42518069a18922e90fa2fa8fe9bf5e2371a40ea88c25d247e6a73a007105dd9); + tempvar res = res * point + (0x7f43f7128a1b46f8ab168a06df9d0cade82a3193eec2d51e2b83f4f0c7fabd9); + tempvar res = res * point + (0x6e694d9385207d7cc8a7cdbf90eb4ed3be49cabc0e6b8d0e69172d73f4a5c11); + tempvar res = res * point + (0x2782ab60e8e9c6cccd40f438a2d2814ef39f50f02bbeb790bc6df78d75af42b); + tempvar res = res * point + (0x259f8eeaf6cbdabd37b9de029661bdcb219245a7599207d3df08c7cc452a13d); + tempvar res = res * point + (0x9345d2e4fc86ae78c4879ecc3adf9e6c482044052bc3738618247b60f069ad); + tempvar res = res * point + (0x4419f27879dacd62144bde4f904890c6d5b312282335a57cf1b04b403bddbea); + tempvar res = res * point + (0x581755fd25823d2f3b07ac5d8dd1bd5b26eab362cec3f9e03573a2b03f62ab9); + tempvar res = res * point + (0x37622de79f6252ff6bb76900db06504434856faf33c59a1b2e39a4fa60ed143); + tempvar res = res * point + (0x2c4ffe18ae93ab53ff6d7d01a7b5bdc5b08dc8d144e0b917f47e60e3cf723f3); + tempvar res = res * point + (0x42ca1f8224d317275c78ca7762a78e6c51978afe1abcbf535da6d299c799c1); + tempvar res = res * point + (0x6403910df189d75aca61c604de3b0802a4ec2ffadb0ff60f1a01f363d66ea67); + tempvar res = res * point + (0x44094080f29bf84d3d5849f264713647289e9af1534ec38d1a7c3d2d2f1ab64); + tempvar res = res * point + (0x3dd2900899d2219ea16fc41413af028057f0c2a674e1cc65032fe4dcb062d4d); + tempvar res = res * point + (0x5a612887264b1ff8e5239b3e04143dc30d0a80cef1c880fe52ee2d5009092b1); + tempvar res = res * point + (0x5ca2e5676dde96127ca85ff6ac82a8fb35b45651b88bcdbfab7ae5298d427c8); + tempvar res = res * point + (0x4b135ec421e9138d09c709a5d92ba70e6944cd44a7eb7f705ab3612de315ac); + tempvar res = res * point + (0x152b3265b01fa9ce0cdf58c17cd14c2cf3e3fafba140db9e27da4fdde7d3c0d); + tempvar res = res * point + (0x55554f904554d2f262d1db49d7c515414870717c829b73d6c439260a8bba3da); + tempvar res = res * point + (0x3e2b9e4151827bb0d04858df547978536215dc06143674d0d2e788dcdc9c36); + tempvar res = res * point + (0x2c30d5e07853079c9f11624e2431795e2bd8b4bebd8cac92f158306b45b0549); + tempvar res = res * point + (0x4e922a3c7df1c668f86b866cf0c07ee4658e7754f6fc0fb62cb297bb6960320); + tempvar res = res * point + (0x35b787fb9889163a9fb5ab831838f19092aa4ef8d8dabb299045740959573d4); + tempvar res = res * point + (0x2d847968e995dcfcecc6ef98ab27f9f1db36b14ce3ba81b80cc92cf19750f88); + tempvar res = res * point + (0x6785d833096c9d9d06034ba4d7f8d71481d4b680b63693d9fa24ea10d3511cf); + tempvar res = res * point + (0x5617f72f8d0da5d7cafeef9269395ee34f921f5cc8d1a4f4c0292a83cb0b9bb); + tempvar res = res * point + (0x6a1373cca7777e3cfacc6502ca9bc645678445d98acf3d6f5ca6c82cab53174); + tempvar res = res * point + (0x5b07a69abcc274ea09eb67f2f6036b492db1f9b7e0a3497d8f3920de22b3b4); + tempvar res = res * point + (0x74399a1effe3a13a8effe952dd57142c254ebe807a56f13521da38984a0b55d); + tempvar res = res * point + (0x6a399f5bede4f507c7251a7ccd110e21173729f5f9a57eb16a27203d3c5e731); + tempvar res = res * point + (0x13102ce3fef387b552a6b8967f788cc8f8502ef0f2ec293d2b872328f78b6c9); + tempvar res = res * point + (0x2233376db0eee71ed0bc6ec0de23782ca9e244a06b8e515b2855b522259eda4); + tempvar res = res * point + (0x6319176edd9fe726efbcc70108b516e26152cb56329b842a1e14adc2a3e47b2); + tempvar res = res * point + (0x12e828f63839dc0dd62bc23385c0bdd5b11e7b6de2cddeccc47f85027c9862f); + tempvar res = res * point + (0x1b5bfb21e549706eaf5c771448f91d1ce03498029ff4159d8cd11f4b6d523a8); + tempvar res = res * point + (0x223b2c9fcd5a1d4b0f7decaab98bdf87e5083865ef9b6562a261fc75009e725); + tempvar res = res * point + (0x6856abcc37696eadf09ac823f589a05b034ef8f86e41d2c6222f039707017fb); + tempvar res = res * point + (0xabbe74553aa10ee20ec6f0f49f73281124ca34d0b71c2e80160f37d3ae0345); + tempvar res = res * point + (0xf7043785f78a94a68b669cb366c00538eafb8e87b5380c68518d4e23922d6f); + tempvar res = res * point + (0x43a4dbc140986d44a7099720e13ec46817f0131dd109a48fbbcf190671f35d6); + tempvar res = res * point + (0x7fb8438581e1ae31877119b91ef1ea28181ba8c0a89eb356313c8a910295d7c); + tempvar res = res * point + (0x125399adcf39aaf7962e3be41c6f9c7691e45c2c31b937e26257d94b5454985); + tempvar res = res * point + (0x3a3c97667e93fa5cc0531c8a2f6d9f84c4f683133b8941fe1382ca8f6f2fe0d); + tempvar res = res * point + (0x253548b05c44cb4d8f2d97641773cf812f709663fe8f492f5a77bfbc8477d79); + tempvar res = res * point + (0x3e828a46091dc07cbbbb0dcbf390e4b5cc44d086b0ba74051fff237f7d6a74a); + tempvar res = res * point + (0x74a80f191573d77481059c14f56764dd2c11571b2736d355efa299c400f0377); + tempvar res = res * point + (0x76169700b631b19086b8b1737e23f1c59cf1428075904c80db724383d3c6b5e); + tempvar res = res * point + (0x7febfa3ce41434e03eccb6be0099dc31d90e36558dfb6f9d21b3e0be41472b4); + tempvar res = res * point + (0xaee16ac845b8bdb7d9c1c85ca7b0e749a7c47229ba24ba097b4b6b8151cc4d); + tempvar res = res * point + (0x31cac8c51732d8aad5bc41c9a6440d482c2c4967e75a571c31b2d9aaaa64068); + tempvar res = res * point + (0x203db741e5e80c19c2bea387e3091420b918fe1142bcf2bc13ae7e098282fda); + tempvar res = res * point + (0x2449d2be3af1fcd8984a9f857309ab5e0e5c010680e33b03a194c6e902a553c); + tempvar res = res * point + (0x40246dcd91afc0098ab9568a5c97d54e09065c551bc9d26ba0ab6a00089bec); + tempvar res = res * point + (0x50cdaac85b8d8bbf55a920bf8d213e333eba5f2bd92e92c61f3946617222ade); + tempvar res = res * point + (0x65dbe95ea2b7d1894854b235f2cc66e910fd2791ff09b92366c7685c652a8c7); + tempvar res = res * point + (0x18f3259c8451dc5007e94efcc6e90c6951543474925fd28ff35e56890bfb66); + tempvar res = res * point + (0x69021f5cefc75ce473977c2ceae2e7c66a84bb3d734eebf4bf497e56eb69959); + tempvar res = res * point + (0x4ded7eedcfca4ee336fa075aef6a017beab322cf7ddf83bccfba05f1c93cad); + tempvar res = res * point + (0xdcc0df28639fd96570d93a6d1df1cb1dcf6db8a259ab092b34cdb411895aa2); + tempvar res = res * point + (0x2333165fa7f9414f082253b8451638fe1e9da3ba8c1246723dbf9995e49d017); + tempvar res = res * point + (0xc8b65a737b5605606028a064d168ccf32d8d87fcb55c6c853fd95ae0961410); + tempvar res = res * point + (0x71d72b0c23e31d703f0210ecb2b28994ad828417531a15a17a1fd401daca2cf); + tempvar res = res * point + (0x211c3e223a3c9c4a024b490a819254ee133ef9740a4026eb3a036bb9e5c6581); + tempvar res = res * point + (0x621692ad7ad27517f4de4e528e1271719cf5b344d463c86b9cd8424a4fc274f); + tempvar res = res * point + (0x5ab65084f4ee8261bfd290e2d5608fde744be92da2eadd5f2fb909ac3d14818); + tempvar res = res * point + (0x5896811c73c991f479c7af6238b51252178dcf4371c297326bcceeb8ee454e2); + tempvar res = res * point + (0x453705ada0d5db6b0afb289b29db6c9acedb01e742cb0d68705d07f8dfcfaae); + tempvar res = res * point + (0x168f97539fdebde7280f4d33f7d5b469cca77495efd4660f31b7d8018f7f89e); + tempvar res = res * point + (0x7829c898e33552459e8fff13c01f1e0d9f5b098f0de7161cbf97da52914bc38); + tempvar res = res * point + (0x5b23dd8ead53bea28246af5a3a63daabf41e7987fe61255d97f2a57bb6d14eb); + tempvar res = res * point + (0x7b631dfaa76643b5f46a069b8c40038f77f088374320add0ac3c9924a12f153); + tempvar res = res * point + (0x2408fff139dae5eb756ea03ef15a2484f582f7ab27ccaa09fa8154f3bf0024b); + tempvar res = res * point + (0x28aa32bfd8c8d7ffcb0b5dadfcfd1b6bbd69b02de9ac1bee786da98ce76c8e1); + tempvar res = res * point + (0x33eb39eae1db6ea48126be6b300b31f6bbe275845822f9eb293e9f7ac38a777); + tempvar res = res * point + (0x3e549a3d3849a09d8f1c50f84f7caa4aa0a5b8ef6f957dafcd13c7c90e4ea11); + tempvar res = res * point + (0x2f5e865731de5068f289b616b39c2294284c111540abfdbb33a39780eb0bceb); + tempvar res = res * point + (0x4e51def182a5bd5672ced3106f19ecd94b760dcfc68e66a3656d0b5db19165f); + tempvar res = res * point + (0x42f46c19b87a82522476372ae65817f8d53f263674a040531bb37935b289893); + tempvar res = res * point + (0xf0bd4817ef6ef818a35ca3678f88abb078678a1364539bd7886dad527cb28d); + tempvar res = res * point + (0x501f0235f18b49889497cf7c91fe0a1f81d74da8cb1e88bcfca9127392aabfd); + tempvar res = res * point + (0xc11cd155f0a514a5a419d10ffa72405817256ffc8d580b9d3ab002f596b2ff); + tempvar res = res * point + (0x9f712ae0384a87901ad44f53eee9e7c39544893d10b891a92e87e4d78e8374); + tempvar res = res * point + (0x2d511bed457c57d7354252189efd19e4f5c3496c1dbe1f1408ff79c8cb97025); + tempvar res = res * point + (0x6c8d7abe5c83db80647ff904bdbf25bd0e979607d2310ffbefaa1edb7ae1bb9); + tempvar res = res * point + (0x46e747695d9d234e15781125d05b85ce3cb01d676ef8fc45a939d5e6d4e2e56); + tempvar res = res * point + (0x21c86da8be11246b29f17d5f7f3566c20712711e03eba57f0ecace8c4355418); + tempvar res = res * point + (0x7b851f4004fd9f20561e3755d7c89528ddefddbbbcbaa9293e416c0dfbb95d1); + tempvar res = res * point + (0x31587ae13086228663118a1fbfad6d65bb9741d5682abfb43c7524cc6c240e6); + tempvar res = res * point + (0x2ef1cb499e790f2de6129225457520b560c1c3120457e742957d1148bb934ca); + tempvar res = res * point + (0x781fe3d95c096c6df1c9ced110914917e26d0860da4bd769e4682a17540768b); + tempvar res = res * point + (0x7cf92bf7e933187b6ea01019ed1c2d9936e53a9ea89724e00e36672dca1e36); + tempvar res = res * point + (0x290b573a86b30d59fd1301b7985a68fd9bf9dfca5451179bcd13d10eee988aa); + tempvar res = res * point + (0x4d3987a0850d8159f9290a8ae8cf99a0ece9961d22135b584d8fc742d42c15f); + tempvar res = res * point + (0x6247162754e5af6a0efa837daba678811cd749e92d91acf35d732aaf4bfb4f3); + tempvar res = res * point + (0x1e3df9ca8b80529441770e007a27cda52e54307e4f3370a83705e0f3ffc86fc); + tempvar res = res * point + (0x25579cd0082839ce295d9bdb24140a8f2fe19f7d582a4993a88639a0347a522); + tempvar res = res * point + (0x70181ba88ba8d19c0220225ca0112845e23ed7609ffa4f2aea3cd40a40eef30); + tempvar res = res * point + (0x481c8091e40139c67f7e69737f83a6c868e582526afd50b548bcfa5ec2e83f9); + tempvar res = res * point + (0x1a758f2faad6702cac573f8ee11d83977ca75744f52d650a6dff79bd6c5caf3); + tempvar res = res * point + (0x5a87e6f4731da56e8b078bdea4cc3f1fa2059943de95ba404ab38addce3d6db); + tempvar res = res * point + (0x62a78aa9e73bc6da0a8536da8dd43311ccfb52829e89e9e94f3b413efb8ff93); + tempvar res = res * point + (0x4cb8044c471e8cdc896ac725744d1a6942bcb26d50b3641e2a95f57b0e7dddf); + tempvar res = res * point + (0x57d63baf011722f5c5a9c4c60899bd918c3287302c97e91fc6f9f8ba089cb97); + tempvar res = res * point + (0x60de66fa4cc5d53fcd9d027cc06945a96de2f9b4f7d0c81c53a7567fde886dc); + tempvar res = res * point + (0x794e6f83556e5ffee6d83daf40a067363b22e157cdd970366757d5d6a02dbc9); + tempvar res = res * point + (0x1dcd10514fdded828639c9c21d0c8064647947e9ced01014ba8943b1d81bd12); + tempvar res = res * point + (0x7cf749a9a9177ecfa46b901ce91a8ebe103f8920d83713df80efb7fc8868346); + tempvar res = res * point + (0x1ecd644cdd8b92b3c042932407033c073c7da5f3a8726210a443f10af466ff5); + tempvar res = res * point + (0x55b74b3af769611aa4c4fc71b1abed4396b218a9d5884844c937bc38b30bf8e); + tempvar res = res * point + (0x4fc4e265c8471510fe6f0dc99d7be1108eab6200b0845dab07c5a126c79919b); + tempvar res = res * point + (0x37edf969a82e9364a741858bfca74b30e86b1b69b4f33bb4a31666f4b2e7c10); + tempvar res = res * point + (0x2a3ca69d295e5e750b4db8367227f9cb347b3693251ba9761a22d411de1c41c); + tempvar res = res * point + (0x7e9f729b710f0fb173b36a6ee9611a9d309a9dc69a776c08dfe63c64c528a45); + tempvar res = res * point + (0x1e2c3057002cdd12b80fb157887fc066b41436bbb71e328bf79ed2799947c49); + tempvar res = res * point + (0x32124f76e477a3c6f5f4346f8abc19cd481b6f43088ccd1c3e8c634bd90cf); + tempvar res = res * point + (0x5007d334256950aba31d4bedb5decc0ba6ab62a09c41baa8ab8d0eb4cdc170d); + tempvar res = res * point + (0x3a06f0e39b3afd46934c41a79a317f220c6321664cbe236ffe1c191ee0b2c85); + tempvar res = res * point + (0x18db208640b40e1acf69b256f0cf86c76f381ee79fa0bbea47fed2c95b5467c); + tempvar res = res * point + (0xa0c5ba0b916bdf79b70c0d23013443f65bd087aaca62088b0d1f7009dd2d70); + tempvar res = res * point + (0x5dd2afd2e8b09f86360d183e2700f71a4fb5e458c61823ece1a4e60200b82f3); + tempvar res = res * point + (0x5b3102b46125dd26f3ae75c22cb8be10a3c98f269a2e91ce7d595d25c77e6aa); + tempvar res = res * point + (0x2c489389378216a8f4a24999efae5d41af3bf123b10601d2efb419999f329e9); + tempvar res = res * point + (0x28bb7956a08b64ed0ed089f0219b05b282eb25c107731d88867f7a78c3e387e); + tempvar res = res * point + (0x450e38572d5b45eba95a4368d52056640cc18213b3065bb7b373a05561cd44f); + tempvar res = res * point + (0x6931414c4f1e51dd287a8273a71ff946d1502d29539815c6652e6b71c95d013); + tempvar res = res * point + (0x48fdfbe3980d1df8db00fd59b4b529abb0569c82a25c6b23186de11aee23a40); + tempvar res = res * point + (0x680f30c7e737040028b548f49d2110d8889aa8dec6afe1de989e3f1f0c1c84b); + tempvar res = res * point + (0x8955f2b26c2c91645402ea61e0b3bd091758afa740b4478e3fd2d97b7d5729); + tempvar res = res * point + (0x62796f07255aabe16df1ca5ebe7f7be4eb1e9b688defe3044b1fb8eb56765a3); + tempvar res = res * point + (0x29f85ec8df7c753f09bd36309e6d7d65f5d5c327d4c80ca33eca932da5eea0c); + tempvar res = res * point + (0x40f21a24062575a80e5a6b6fa209f04178fce24323888c3fc9a083c6cfffe71); + tempvar res = res * point + (0x29eeec3cf3ff9267792e170045fcbc1358ad5b9c28b97db6f4cb5a131dd1e57); + tempvar res = res * point + (0x6d82291b429009057a7d89082c7c3ffeade1cbb4598b6bd1322c2e2d3c6819f); + tempvar res = res * point + (0x78ffe33137f03476882656c458a984b78bfe509d0ed005657860541fdd16506); + tempvar res = res * point + (0x13f6d5bd19a25ef48bb5a89c64894e9351380c31e98fcb8404c490081665acf); + tempvar res = res * point + (0x36d9f7e5746b465ccd284ac21d5cec14258587d22189b4f85ea87f9b4d7c2ef); + tempvar res = res * point + (0x54730884e1c5c7ff5bff889e8e5846f7e552f07beedb27035c0eaebfe676023); + tempvar res = res * point + (0x7344cd22ecc8029fc605bc46e5f2f60c2910130290257210f9db71f26dfbdcf); + tempvar res = res * point + (0x6a60ae65aaae41d02d6ad44360c269051a870c66a87e430eabd1c2c5dd8261f); + tempvar res = res * point + (0x639a281c19217bb79dde39d86549ffeaa0694283fa876ab39fa6b663869ac9); + tempvar res = res * point + (0x48a07a1f3adb4348f65ca07f7e1ad0b70a6024c4934df5724c35f1930befc90); + tempvar res = res * point + (0x527d59fcf4e21663d7e921cf93b705e95fca41d9d2f88720800586e03bdc283); + tempvar res = res * point + (0x1b07576ead1fa791e38995e423ee788587adb512c1bda749fc0869ac6b40c6b); + tempvar res = res * point + (0x7b59c1f0252efd3b471c3047a2060ccb98cb86148c1b1893af4f86384821b04); + tempvar res = res * point + (0x56e48833c5707aaa1e38a0d644765251c038ac3f89ed4d58fc3b24d03a83e77); + tempvar res = res * point + (0x14d1da51db79b82ff5fc48e18ad84a98b1390d8e61e1580ef5c6100d49da80a); + tempvar res = res * point + (0x6ade2f8ff114a1c0a0f108286f0f0e820073e7fee989a85fe11a97b972f077e); + tempvar res = res * point + (0x20268b11ea1f54c737a14073b8bd83a6151aa30b0d51182446adc72aa2bef83); + tempvar res = res * point + (0x937368e9df8289ef2d93e806914cc9ac730750d1ecc6ccf6c4aa6e6788d35c); + tempvar res = res * point + (0x297d16ecee6310efbcf8a2946e1f03e23ce1eaf88fa6279dced371db9dbc299); + tempvar res = res * point + (0x74d40da7c08b8fbd488137dcb60906f2004a26faf06e6ee4dbe1feceb94d98a); + tempvar res = res * point + (0x5669aa7f25c6cefb4a3e1f5491dc50af7c44ca9f8405864906b353c4c3529b6); + tempvar res = res * point + (0x4a5077d73c41429dcb66a5557cd392c5e8b64f4f93507e5e7b8f1cbe29a309a); + tempvar res = res * point + (0x5974550418ba46ba346cb87069b6c17f9a6d57ce7554827c8191072b4ff8357); + tempvar res = res * point + (0x6fb7a7f6c760b606b4f7cefa186540604099bd229b954096179a12ccd50e323); + tempvar res = res * point + (0x4fe2139f7019584c7f395a18bfca2f5ea89a9300bf208b9dc73686c76e724d6); + tempvar res = res * point + (0x4b45d3cd223171c9e2e8030a3983c2e4b6ed61a560db3a8da8a2bf1da05ae2a); + tempvar res = res * point + (0x223dbf6f82e6f2b2dce8397a7a6d00c8fe38fdd8463fe7612c1a90bb76a16c9); + tempvar res = res * point + (0x13e7cbf6809b1c282b1716db08a549825b9e1f24479288cf615c6557249f675); + tempvar res = res * point + (0x13b2e8b26fec1c97c5fac659532830270b08cc6861df86b3f3b4894175551d9); + tempvar res = res * point + (0x34a45f657061a57b808e337faed21f722e6298262a2df69d6bd34ecf2e29243); + tempvar res = res * point + (0x372a448e249504e459982c7d114b3c79270419467208096cfa6a96f3e5de755); + tempvar res = res * point + (0x5d62087a11238dba183191a31e686ffea34bd393310e7a2b11c75d63ec340); + tempvar res = res * point + (0x5f25fb2b70ae9e334bd288d6768a7b3b6b2f4672cb671f6b0ebd781134609d3); + tempvar res = res * point + (0x1025bf3b6ef4dc8e3637f4dd1cda0ea30ebba8c30ce5638b5f9b5291faa0036); + tempvar res = res * point + (0x7d2b1bf76ecca560b7409dee16ead5b2b3691ff75ef8fe5a844306a7e29b252); + tempvar res = res * point + (0x7cb9fc14dc4bbad427efdb3f5821fc9dd10fe8595577e39645ab9f62e6fa50); + tempvar res = res * point + (0x6f61949d4cbc8298879b470d1fa9aec82261a8099c448dfa4379a597ab01d03); + tempvar res = res * point + (0x336d1ccaccbef10084bc4a18f8c86f699642878a2b5d5af3a3fbe7a773e6904); + tempvar res = res * point + (0x354e8d015485a06adadbf43a6bad63e9330c4070fbf2a704c166e1d278c8d4c); + tempvar res = res * point + (0x45526e767c14a531fbc10f287b2a4203e18daad8a4883a1900a63dccc1a18f6); + tempvar res = res * point + (0x688bfd9b23436077dd139ccf0a7286444429f3a2457ce7e2cc939be2172921e); + tempvar res = res * point + (0x5dd26663ad2931b249bcf054211723be60b5b46de16a61928c0a9326874f3e0); + tempvar res = res * point + (0xaeb2689fd195377c86c55bb52ba2ee27c7c5395d8163355a3c04135b43333a); + tempvar res = res * point + (0x73ce15dc2409ac614aba33d14c4ad294a3a8136eec69e8b34b0b14b92eb240f); + tempvar res = res * point + (0x73a3905fdf4a2f53d66ca4cb99ca729e776ce66d9a474fd71da35b3fa949d34); + tempvar res = res * point + (0x1d60249bd6492637249efa94de232264fa23d62153d7a36e99aaede0be5d842); + tempvar res = res * point + (0x728595451b9c3918b04e7ce1637804c1df21495ad8f188eb46a5f1796e2e3c1); + tempvar res = res * point + (0x5dc73d8837d2fd0c754ecd371e94f0af344396efdb4337a8c7c2a0755838f46); + tempvar res = res * point + (0x7dd917167308b602914680880c9c8c8519f34be930ccafbaca3d126a30c4a45); + tempvar res = res * point + (0x1950cc259cc77027d5c86ea77f51a34cd30ad768676d77a0503f36f797eb4af); + tempvar res = res * point + (0x4d5df514fa9a8bd7515039e59bea7a1a1381a76f475a7dea23549106a7df8e2); + tempvar res = res * point + (0x1d74577e412af12fd886706cdce3c238f2761d096043a084c20d2bd087ad4e6); + tempvar res = res * point + (0x7871f7217ff1c7b739678e28908c4222f492ebf866cbcc410148ad1d143de0f); + tempvar res = res * point + (0x59a88072f92b384925c9091497269ba9f8226c24f740e928e410ae0bfb9350e); + tempvar res = res * point + (0x19c90daa3645b62f461545c7c38ce5bf8b5cdad399f417e0abbaf2b2df0ca64); + tempvar res = res * point + (0x53b86dc3cb8ef3d5920ea35c40e2d05496e45245eca4e0d058e2a0e2d583dfb); + tempvar res = res * point + (0xe00c78bcfc271dcc6556cb1cf6501e16d20b188c7412681c0b2ae0f2cbae05); + tempvar res = res * point + (0x36ac6cfd4f2ef6be5b1e83cf9e36e894b2575a8f4690c14484a17c222ec3c00); + tempvar res = res * point + (0x32cad92232ea7886b829887e6ca4ae084800803277076107b1078feb66e95bf); + tempvar res = res * point + (0x38269de0c80a2d8f4bef1d5e76805d1e412fef7b18886279e98c57a0fe64627); + tempvar res = res * point + (0x217df85b26b6b3bfc67bec919866b6e146621c30685a31e8c93eaa27d5dbaf5); + tempvar res = res * point + (0x4ee32b2ff29b0918618f173c4e5dc3b606a1ca2e0eb989257e0bf78dd2e9589); + tempvar res = res * point + (0x2d51937feb119772693523625e23756d172e996d1cfb82a258580bd51c15e33); + tempvar res = res * point + (0x7c2468c14a7ea994c89e2e4ddd6d2d624b67a96e7ccec4f27a5e0122531291c); + tempvar res = res * point + (0x602aca232b11ad63241b5f401c368acb1e9cfd4e5fc8ae699491d9c51b4db18); + tempvar res = res * point + (0x39c92f0c55d99aa6b082d21129a9402e6b0fe38a639a8140d76ebee9dc45877); + tempvar res = res * point + (0x4fff8b45f7ede0580424c4e2c75213c4c42ec6c68266c8d5d750a2863bd474a); + tempvar res = res * point + (0x3ba2c93d59d6a361b9ac28d93e54d775b040bd7fca9ac72339ea4388c533dda); + tempvar res = res * point + (0x6d567c1dbb663fb2fd92140cf66ea33a19cda580d18c10fe56a62e5bd3f47b1); + tempvar res = res * point + (0x2781266a2070c9d3f045010a32c98ce3e0765446e3ee20eacd73a0dc0c7c2c2); + tempvar res = res * point + (0x7dcfd5001e21e030b006d54c7fe0f7ca97a2c18d4e00ba92c005705a4f0563d); + tempvar res = res * point + (0x2fe4c112d7bfd4ad5f81ecdc4b30cf73aa51df4e4ba6d255a0e3eee283aff46); + tempvar res = res * point + (0x2433d40f2b8f9461b5368cb396f7604999a735414d3537ed6f1451f1fe93cb3); + tempvar res = res * point + (0x72f959288185bd36ca4e23472ed7a2577f8e5f0ef0c0d5df6f63e60f40ba307); + tempvar res = res * point + (0x4c5592288cc342232d76c80e858c08ecbfde64b747637ccc9a2734e90f85264); + tempvar res = res * point + (0x48ed57151b6dc68b039dc327f79bc2c26db62ff957809c5538360facc04d9c3); + tempvar res = res * point + (0x5ebd9b268cc66bb85a5e67a6b9d5fdbeba8b3672491068ef43b688a3a043a33); + tempvar res = res * point + (0xdf6c1013f3076e6044f0a7032e0bf80833f3c7d9eb0c3eb1f3c2a37314d19a); + tempvar res = res * point + (0x5f0cb66613216a1339c1cd15239b7f03c1d4b9098a931f65ae50b877f861880); + tempvar res = res * point + (0x5d5fbd560f7bf1e97190f888fa43b32db1e8070f046d6016b536b94d1473a57); + tempvar res = res * point + (0x33381003a653f0327cbdd8a11252ffe714e1061ee214329cb99e667c835af97); + tempvar res = res * point + (0x7b86849a979796096f7d7b46eebaf00913a082c638c5b2bfdedbcd78c480272); + tempvar res = res * point + (0x5f27bcacc10845ad41cb26244112faa8b91d46d97024445f50ced796ac5a93e); + tempvar res = res * point + (0x31cdca47c96b32e99077a96aa5cd73ec9c4da04212667805c82dff3e498f4ed); + tempvar res = res * point + (0x66a032c182ae70dd4487897d0c79dd860a25d21c61e3aeef8b9fa45349dee89); + tempvar res = res * point + (0x148523eabde5554538a1114351f3d8730d4a4d003311c7b57ce9e709afeeca5); + tempvar res = res * point + (0x62ea67803c421a4bbdc672d556bca219fd24e7145cb3e9113a625eeb4459254); + tempvar res = res * point + (0x2c2c70075ac99cfe68a7354ed29842c5207bbdbd09dbbd225ea93d0c07fd9f6); + tempvar res = res * point + (0x48b0cc6241c99407bb346db57db9cf82b2e66d1fcc1d756889a4f4b4bb8b396); + tempvar res = res * point + (0x506f990d7037060dea08ed53c5b17483ca8a7c58f94ba5e64fae258be4c78ed); + tempvar res = res * point + (0x777be5852ea7798899d4750e9decd1430bdad6a8b0d1827a7a89ce6f1afd89a); + tempvar res = res * point + (0x689fb22cd95d6f1868a4e3cd6ef1bba9f974931f76153e73038ff5ae7d09018); + tempvar res = res * point + (0x560fef0ed77bc94e16b9d9a21bec0ceadf81b26fe683b9c74b31e2d72a4c92e); + tempvar res = res * point + (0x28c74f03f409c942d16a773fde01b3f0bec544b42c1d46944db6253561e1ac2); + tempvar res = res * point + (0x4d62e1ef04cb039a58dd8cb8c37dceb78b10fd84bbec6302c964b899a957d02); + tempvar res = res * point + (0x44094c265809e3d5765071826547999dce8ba7058a7c1b1301294d8291949c); + tempvar res = res * point + (0x4e0f90743d3df3d3c4aeb80e7f6db457620430ff28475c6194c757f81927dc5); + tempvar res = res * point + (0x2cde734d2a82619ba69ca4f5ca5035f699a1e34b47560d761780546c9b04d44); + tempvar res = res * point + (0xf09069dc6a2745587b447ae03ebd6524aa9757f1090a92dc5e7ce8db848195); + tempvar res = res * point + (0x5522f48902001bf41de34be900783ac957fd867cca0f35666ca491ea89d8fb3); + tempvar res = res * point + (0x5b4be8af83915fd955ba32de729f6f2aef6c76501d82ee325d72d620bce8b7b); + tempvar res = res * point + (0x78e74ffaf944c363f3fc42cedaea8a9a450ebaac98bf1327590a11e064bd76a); + tempvar res = res * point + (0x6ade7c482d201c23145e3890086b22ab0d43495f5c83b1672316c10ca52af0b); + tempvar res = res * point + (0x79c066efe4c22c6e9e097e84401e183d3c45c645d986ed640a8faf8fd4dd096); + tempvar res = res * point + (0x21d59ca7451d83d78ab4d9d17a662367ac84b555866ae92d036d71de22872bf); + tempvar res = res * point + (0x6d100d3db14939bb442e5f5ce6a05939f201837007331536440a57c2bf2b609); + tempvar res = res * point + (0x7e5bc177982061f124cbe521c713c24438aa021fe6928d82452e44f6cdcd631); + tempvar res = res * point + (0x179e4b1e4817460085d47376a1971fdcb0287408cc7d11fb62cc3785772249c); + tempvar res = res * point + (0x2a7cd1fb12f896bff4d3db49ee74a51e970e3e386c2c8e7622412a6156a300d); + tempvar res = res * point + (0x3c5581c15733dcc4d548aa0a6e648e075e9be412680a76a556f91ae5f01e44e); + tempvar res = res * point + (0x4a4eb8f57c99e931a666de76c20173adcde82ff59fd8ecaf8b8c05e29b63fc9); + tempvar res = res * point + (0x58fa31f9a4a7e8b238898eb1296ec55e3e2000a48a2edc8e65d260d31bfd7bf); + tempvar res = res * point + (0x2c37f85ac7b1aab52ce3d28bfc65c65b7d4ffd000757c07fc493d183b7bb582); + tempvar res = res * point + (0x461b788a24347588e4f8d4f2d66640f31d6b580223a21919ccef9480987db1f); + tempvar res = res * point + (0x47c3222376f8f18dc6e82eebaab03fcf4c425acd901a7bf9841a3aba54b82a6); + tempvar res = res * point + (0xbece573771924d045b75bb992a87b26ab067a0f2dba4d1a9efbe5029963533); + tempvar res = res * point + (0x67c2a0e19b59921666716fe2b3f9c7f59c4da17d993956eb87eece7ef542269); + tempvar res = res * point + (0x8940bc9dc45fd06ce4046337963c849324bbe5f82632b94972c0ccb205480d); + tempvar res = res * point + (0x38bff358ccfd92418537a9b9858df499d2c44404c1886b109edb14c897e74fa); + tempvar res = res * point + (0x533a5a2ebd098297604e96118f2007ddd12af50edd525e9e5a0b154e620b2e5); + tempvar res = res * point + (0x312411292b7fe7eee015fcfaab65b611bc2b9f9498489fc3c1452862902bbf); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_pedersen_y(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x62b07622f501888a668440d9b856be4b0c3bf12a401fc2bebaeab4a7e1684ad); + tempvar res = res * point + (0x75a127d817aee244517479bab5c4bfc2a0035d43d673badaf64d8adf94353bd); + tempvar res = res * point + (0x14f3359ce0d2891d1bc2b6f4d2d6dd71fe22925b8a09f66147db095a9d4983); + tempvar res = res * point + (0x2d6129632b4fc43e4142abf55fe2d1f3e79dfa01c73d8fb56a465dbd07a9682); + tempvar res = res * point + (0x5115ade709c058be5dc6f406794062642086e431bab03c9a86d53c79aa83db4); + tempvar res = res * point + (0x29f6aa5fc92eab8b8b9871c8449c1f617b808ea9860717f3e5e1678672ec565); + tempvar res = res * point + (0x7e08f9d222cc0764fb5ca69e51ad4cdb7f1b612058568a142bc7a4cdd0e39c4); + tempvar res = res * point + (0x54c5dff0aed23c07edcd958ee3690e617011b87a5fec541725237d4ebf34382); + tempvar res = res * point + (0x2b7d501bedc4e7c604b0e55dd2d8166fa39a541efc24d81d8464fabfef3fa37); + tempvar res = res * point + (0x68e1d50b4d0570e357eac7bc742ec26dac1edc5b179989c7ae8d31791639103); + tempvar res = res * point + (0x707c572424682b685a1ba90dfd7e56f86254862d86e20b5a2d3ca85fe0017ad); + tempvar res = res * point + (0x2cd9a093ece61e554b2bdde3ec474900e4412775ad25456e5be6e11df7b9fff); + tempvar res = res * point + (0x7492aa940f34a027f8fb3700f29cf628c1d05d1675cb7865509f20617a90b2f); + tempvar res = res * point + (0x55e928ba557ed7fe0ecde6d1fbb83d112e6b06a087b4013b9c425fa36eb0415); + tempvar res = res * point + (0x3cdb28a913a41d597915de055aecc59f2b13079d3d8b33ab0a075eeddb1bf8e); + tempvar res = res * point + (0xfd48fb35400aaaf57d130b6143b241db8af174cada72ede8f2fac4ec6688d2); + tempvar res = res * point + (0x133b6505a6afd2e5fada0e53ea51c012e4935ea6d2d02caaa15ffc50a45079b); + tempvar res = res * point + (0x2d2d27711772cafff2cad828dd78d8b213e317e8939cf79164ae64dea577d61); + tempvar res = res * point + (0x60ac57e328ff6938a17d43e6137a55399b95459be60fe980ed8960edaeee10d); + tempvar res = res * point + (0x7b056cb6f172b25e3555d6b1422ff769fd4c07258fa16b03609f0e374012ed4); + tempvar res = res * point + (0xd21afb1901f1b3ad66587a7fb97ee06662edc3bc8c8d32b48625a135ba23a9); + tempvar res = res * point + (0x7784c2e140072fd26e95911df38f9a337107750a72b9ce05a21a0f781b92dba); + tempvar res = res * point + (0x7c1667b8d44d288c4f5150d01c5206d4d5868497630745b6916466c8a5b1228); + tempvar res = res * point + (0x491c2243a95c44528b86167a4418ff9d93a04bde8dd7a5d2b19ea579d295312); + tempvar res = res * point + (0x6aebd7a9279eba43cb1c0b14bb723dde464a86cac92518ca16ae27a8684d9cf); + tempvar res = res * point + (0x709be747b0a69a9523680ff69e6bfea4637bd570ce5c45256b39ff695557da6); + tempvar res = res * point + (0x47275cd67ff3b7637ed55ced299a6142a821ab466a897f1eecfc8bca557269); + tempvar res = res * point + (0x58ccfd44df4e339c65e1423eaad47210f2e16aa6530d3d51f38b70e5eb3a623); + tempvar res = res * point + (0x28218a1bc7586b71ec1989082b8f7ab0efba14569c6f6e5d7aeee1964ab6d70); + tempvar res = res * point + (0x660bd8049bd301d093aab9ae530bedc37467d4ff0a12c89d689d61ef9b9546a); + tempvar res = res * point + (0x4dd38543d129d0a71b1836c6e2eae47fde5d572e32ee9a5791f7ee823eab4db); + tempvar res = res * point + (0x8509234000e130c8828328ae4997d5116117716cca9490e6e63f30b7df699); + tempvar res = res * point + (0x62ad4d764ed0072a7649425270e2b210421c77d3ce98e2587ea5440a591ecc0); + tempvar res = res * point + (0x66c5222dc133e37dfa0566c49d107852d978eb7454489d3b2ada8de022125d8); + tempvar res = res * point + (0xe4d1f1f1f9b379bea473f76bc8f3c4d530335e2d6bd782b42324872767b628); + tempvar res = res * point + (0x6ac2f92bc4c04fd50ebd3e336b53b866e790ace39838aa96a4b791011455b29); + tempvar res = res * point + (0x59d753a23735a336c50466f5ccaab3671230fbdaf55101530e5f562a5efcaf5); + tempvar res = res * point + (0x166b26359c51d067955874f5612eb70806d7b8d5de4d8e0a75e0d57b39b1846); + tempvar res = res * point + (0x2dd27ce7910e44ee00ec3335bd79429846a70d92d482adf81b36a9ff1aaa30a); + tempvar res = res * point + (0x45970c86c25bc9a68f2e2a34969faa2134c95b19230fcfe7436c98f537539eb); + tempvar res = res * point + (0x539cd2c1a28df263709cf0eadef73a600f563ab3d82c27692b1424814cc3e15); + tempvar res = res * point + (0x31eb3b57e6844e3efc1e3975ea393476d8aace5f43ca62b09314c90b8ae9688); + tempvar res = res * point + (0x47359c8dd2b86e4f634a9a50950abde25942877bc5db93d62bf43d2886692e4); + tempvar res = res * point + (0x2d8ae7b28c8c3acc8bef3d4c2a9f5ef1323748de693a9a1ad3ff8601116b165); + tempvar res = res * point + (0x4538fc863186b4babe3b424b4111251bb1e20ba5516be54160cd560ec0d5a3); + tempvar res = res * point + (0x559548517b1025ad61020be3e252b6ddbf1d5d53043231f8850c0da52b8268a); + tempvar res = res * point + (0x3132d42e4a928c08a972e17b2c3b500dbcadbe6190b2e7f5b58300a0c8a38c6); + tempvar res = res * point + (0x5b02adb78afd4e219642a1fc38b2ef9f63926841ccfda072ac17326d3d50f3c); + tempvar res = res * point + (0x75971517855ffbc9657dab30657ed1e3797307bbec1ffe136cb0d8a64ed6eea); + tempvar res = res * point + (0x174a4710688db61da7559255caebf641a268b4df53d45de5e8156d36b4b2ab0); + tempvar res = res * point + (0x295fb60eec46a40a33b1a9532427b42e224c0ac6c50e3c1c5d17c2c16651a25); + tempvar res = res * point + (0x2037a7d08a1c4fa4d5d4f53436a252302840007c09163026637e9cdddc958f0); + tempvar res = res * point + (0x7e9e1c3d4bd3231686c235a495f737a9ec3d633331a95d85e17e90f99a08af5); + tempvar res = res * point + (0x218da336adf8608530fdf8320c4edc00631d36c8726430732038a369548cf56); + tempvar res = res * point + (0x78c7b0512cae47833eb6bf01c1075aafca19eef9b32e37f4f9a9eff315637c7); + tempvar res = res * point + (0x628226c46fe0bfa8aa36074ed0785cb16461ee2945ecee9deaa6399bba2742c); + tempvar res = res * point + (0x2eb6bd70a00ec26418d347df1a444f7ba0972416103f00c771e0f3d50bd8e5); + tempvar res = res * point + (0xdf82eebd6cde9b50958606c6ff83c855c43ce9613fec366c7792cb456ea913); + tempvar res = res * point + (0x4221572cf29651f508bab9eb82545b17cf6f9efd0416b65262e5491ad408e39); + tempvar res = res * point + (0x1d5fc46deed0eb9b56cba1d2bf8075227504aaf6ab1330b346cc3cb84a07cc8); + tempvar res = res * point + (0x55ee57d4096ccf0260baa2a1a2639978d965a786e4fc917cb2426f8a99591d2); + tempvar res = res * point + (0x21706619a453a544bee0ccaceda9fe69f860c894b36bc9cb7ea4455dd88a9ca); + tempvar res = res * point + (0x76ea16625d0cf0c04f096ac7d6eacafd00809ef1d1a3cf5e37dc2a13a02d303); + tempvar res = res * point + (0x6d0d885e8d2530c7a324f7b2ef47db35aa8162289a4420a54f13a82b871d850); + tempvar res = res * point + (0x471bb97187c83c0e7b51ab70022147e8d8ebe25d4081907e7d1bee8d6c6581f); + tempvar res = res * point + (0x12b9157240a237f319beefb6019bf0de1897b9e2d8e5536e3a21d8f9fd689e7); + tempvar res = res * point + (0x2ef7f1dfebad70ef549da1a143c838cea27749807efcb1a0a29cfab16420928); + tempvar res = res * point + (0x519de0df91b17442a8f60b512297d69a1b516f70f67d76eb9c287f06e37c55c); + tempvar res = res * point + (0x2a45de0b79a4e9c53d47f6126d35b1d050775d5fb17f3c3dc22c7b6476608c0); + tempvar res = res * point + (0x27e3cfc87448bc0392a0d6c1b1aa06626636fc703bbcf3717fbe6f0759c4855); + tempvar res = res * point + (0x77a45066995089dbd4072d6817397ce0c7e92b53d19338e9bd7549e954bd961); + tempvar res = res * point + (0x3139ae970d95891aa70cbbf6f172223e07eb521a5149b7e0c9202793f6dbdb); + tempvar res = res * point + (0x25dd21ff92e6f1075df6b5ddb2b774ff963b1b84a985261b1e94ca9eedaa49d); + tempvar res = res * point + (0x13eb9f5362c087af5ee758bf0b589c0e34af337b3c06c788573534e96de30b7); + tempvar res = res * point + (0x6a39a27be962632e0bfb245f65a4d70912d1572e39003d63def5f45bbcc8f7); + tempvar res = res * point + (0x2c11fa8c0ba68518942f1c686dafd32aa26545886d28cdedae00071360df674); + tempvar res = res * point + (0x7ce49a9b8d374e1174ae6ccea7cae8d743404552253f7ec854317722a5efffe); + tempvar res = res * point + (0x6bf518769635f9fa39c1258844d4f62e5fc00b70792944da0a939990492313b); + tempvar res = res * point + (0x6123efb57144c151864b4f717a44cecc667fb2ebc47bf24bda4f7d0ef8f550f); + tempvar res = res * point + (0x2c29d0056cfe7325567a9f2d09d917b37a45aa3cefe20b78c4bda2942af59bd); + tempvar res = res * point + (0x76914b565dab13e76053b7a74c24c005b0930011e48ab26db44b6b49a1e7ae5); + tempvar res = res * point + (0x648c35904fdb8bbf9c0bc9288319c248e17974fbb6616a70acdac004878bb9); + tempvar res = res * point + (0x1cc7ec07c4e1e6626b5263044071687d0ad34ad4d08996a213380e9b728585b); + tempvar res = res * point + (0x154a5ad294d41caedd8d927eac226dea1e2b78f6ed0a6901a00e45ae0ad78f6); + tempvar res = res * point + (0xbd5fd7dcc1ce2bcd7f7415a22115f0c846d16ac7458e6c531e7e44dc664962); + tempvar res = res * point + (0x2b2b08bfc4c3d5941538b2eda43b3cd009656cf83b6b23be56b3041df3dbb0b); + tempvar res = res * point + (0x5e48cfc304417473eb4e587942a76921fb007d8b11ce648d36828e8cbb5d595); + tempvar res = res * point + (0x79c11c262fc2efc9aceafe4a5886713151352e60c4db45826e0e343cc5919a9); + tempvar res = res * point + (0xe2acacfba8f832e4e3cffb6ecf4675df678403610fe91363172229444ac0c0); + tempvar res = res * point + (0x6dbd918c7623bb07b05ca515146ddd7193373250e0836062fd1c430e2b7894a); + tempvar res = res * point + (0x61b210c04a0899fe2a3dc53348507d6f53d4cd3831644e4630eb40564ee5b47); + tempvar res = res * point + (0x1e3816f2a6a4900b65d140d144225a8a81cb3ea22f56de3cbcfe3944fc0e898); + tempvar res = res * point + (0x3c99839cb11fecd878ab9efd1d2ed2a718f6e0df4caac1a070de06ddf1a6091); + tempvar res = res * point + (0x567205f3e5ec69ce7962918c41ed0309c3ddfd85fc92702ce1c207b282f17c2); + tempvar res = res * point + (0x10382fdec78a18047041629179e18ec7dd067bed125bf5fe83f13d637a8ff67); + tempvar res = res * point + (0x43aeb91e6f453d372353d9814a85c21617e6c934c694a0b06100e1e9aec4087); + tempvar res = res * point + (0x2b6a2e9d453e19e3d766f24cb7c6753f84adca0f75f7a871092688bb5ba0d37); + tempvar res = res * point + (0x1f3e3e61713ab64544b28dfcaf4da25b64e625048ca55cc783dff614f5796d0); + tempvar res = res * point + (0x364cf25e248a3f2fc2106025945389328c0ef37848a59ff2afdc685c0854822); + tempvar res = res * point + (0xf9762bf5620ec90d711f12cbe600f29906fcdcdea4f17cf51ffad2e07887e2); + tempvar res = res * point + (0x78e4cf312ec50466bfea965b655e9514d9d69bf0bae566fc88187fe730f70); + tempvar res = res * point + (0x8981cc99962f20f8814162568d9d7edb7fcc637fc6907a98b1d1eece9811c6); + tempvar res = res * point + (0x4e28bfd662fc5e09399fc49a49a622a7e845631244b9472df8c91c4a703321a); + tempvar res = res * point + (0x3085800be446839854dfb7bd9ea67ff139267fb5268faaf153db26b00368630); + tempvar res = res * point + (0x787a6c80d5a23f91cb91d2508633cce6125da76e797ed460256933a4e6a24b7); + tempvar res = res * point + (0x5ad768a2e70b4018e505bb5f6f44d249d9f5ba5f126106cde9be7726cf5c0a3); + tempvar res = res * point + (0x58afefb8e3180356e33794e20db869aba4bd4e5dfc795f8089d6f123025179b); + tempvar res = res * point + (0x4f62f4d968964e4908d16fb9412f8d10eb82e14e83f3e094a02470f27eae006); + tempvar res = res * point + (0x5ffa0d51bff335ad53cfe99165aa64f5ac1b01c360bd0101856537fb03da5ed); + tempvar res = res * point + (0x43fa3aa05db6331941265719fc1ee057d9f3dc81704f81c2ce7faece0fe86c6); + tempvar res = res * point + (0x1e836012f5509ea2f3dfdd474e9e4a96f6924e6619924ee4c6870a5294e26a9); + tempvar res = res * point + (0x41052d90f803f015bee5bd1a5f6e2f78f30439ecbe39861cdaebaa8f7c56371); + tempvar res = res * point + (0x16f6ec82023f48ea80196121afab584b9bce7f01e9515d0a3b489d68df3e2a9); + tempvar res = res * point + (0x4b7236fb7f8b72b2d369effbee5b4bebe7d2205ed72f9831b41c711680cbbf2); + tempvar res = res * point + (0x6620ec871e8a2c03933d0621b13e7f357b7349ea16bb549e7e15e2652692252); + tempvar res = res * point + (0x5b553a6606a3f01d862af22a3309a6df0aadec753fd1e0321b0eb08504c1f12); + tempvar res = res * point + (0x17a1bf17777a3b56a76df412810d05c9e222027aca604791694d3b020ea40cc); + tempvar res = res * point + (0x64fecb621f4dc18fa1b66152f28bdd15b7b12d495c496e77016bf3b979e4b1b); + tempvar res = res * point + (0x7e31ce22d2a3d776ad90e008ce82c594dab9ff2c42708f4f0676000cd86891a); + tempvar res = res * point + (0x43530eaa364a9df353dcfc154bae168e0fa9b51a3362c6cb351d47bb7f6b829); + tempvar res = res * point + (0x35fea15e2101714f172da73da6ddc2077ebd42ada067e7879bba8c2ee1d9db1); + tempvar res = res * point + (0x4509575b94136d744c8679c3028b0db514688db5338c4bcc9f50ccd7d15c95f); + tempvar res = res * point + (0xf8bd8807280892ca46c092b74f845d90f3a6b61b197a0594fa30686ca41a5f); + tempvar res = res * point + (0x51443fc9bbe11d787df4afc59f4366629cfb3a14c80cda1caa1ce6107fd063f); + tempvar res = res * point + (0x22cf3cd9fc0103158f7de369046ac0cff77c44c3f9c6ca942616fe7d59d6231); + tempvar res = res * point + (0x14714592154025f15704e279d2db4c70f545137269ccbd82c11fba275bacc85); + tempvar res = res * point + (0x1d44a3f67a1142e7922f4329f775fec5f8bd2d32ef8ab41a00821e76fbaa89f); + tempvar res = res * point + (0x2d9f309e84716b322c26aa86a3fe3cb6ff230e0968dfc58b869268c751e510d); + tempvar res = res * point + (0x64ff5a81d9e22197bb59e8cb340a0f44e22e226fed168f8b125d850bd727b7b); + tempvar res = res * point + (0x2cf1eefdbf254a549ddf4069288ea075d9aae074aac7853005b57c37c2039e5); + tempvar res = res * point + (0x20d846afc1a11dae8646d542770f294b9c9f21f1196fba567f2f74d058ebc25); + tempvar res = res * point + (0x4ce9244cd3966ce1a6fd7f8b85fb1c8751e35aa53032f8063535665ac3a69f6); + tempvar res = res * point + (0x203ddf8cbfae2898d2d2f183cd0efd1c3f7db1b84b8e96e38f2b87b4bdad1bb); + tempvar res = res * point + (0x37b40695420e59161b338e413a72daa6909f0e4f6f85426f8eeb6bd0dc3a1b5); + tempvar res = res * point + (0x8554877281326c1c7e1f3a2f5e81341554ecea862c2677fa67ab2f88b3b03f); + tempvar res = res * point + (0x619cb05e71db22ca1ef274bd0a7cdaf4fb79b3015b96f44814b490f048d2af0); + tempvar res = res * point + (0x66af1f51f840c438b502c2a5ab689f9b38c2c96df36988710951bf185cb8501); + tempvar res = res * point + (0x5486125e0ed23fdc42a4f8c96cb08d934b6f3b429c4af5f8396618e978e9811); + tempvar res = res * point + (0x41d785e118be2d27a159ed5216de66a84873e1f62088726d9607c6443a14090); + tempvar res = res * point + (0xa6117e45c1c561307d63895569d34fd7e3f2b2ea088dec37dc3a5527deffd4); + tempvar res = res * point + (0x3bfe2f1e8df44829fa27a78c46c223c7e64bda85be60d8a3a5d0e7d36c20e29); + tempvar res = res * point + (0x3daea06a4a96480c4f7fff1082d95836964b63c14281ef942fa9a9890d8754c); + tempvar res = res * point + (0x3678ebeaffc3e64d76141f41be973ff36e8398a6aa0385eddaa0c4183e3646); + tempvar res = res * point + (0x5cc1da57cf1059231e195a26b1323599c95f98e4b302d6e6f4bd41180b56d35); + tempvar res = res * point + (0x4f4cd7f9fd5b694cc5ea6154d0738cdbac3978ce74a7314bcafea3dbc1da61d); + tempvar res = res * point + (0x77bdb42e999e93273fa3cbb7ae7160522231680eccc4d38c1b8a83d2a0420a7); + tempvar res = res * point + (0x4e1cdd107e3116b4ff22720938a201eed2ea0b499bfde301562f5e39a42b066); + tempvar res = res * point + (0x513bd3eda9403f4167249972ce4947f3ac9e9da03a7b9ef557a65645b9616be); + tempvar res = res * point + (0x23d7ed01587af3b9aefeae8a627c6401d36245cafa9367631036d2bd7c47e26); + tempvar res = res * point + (0x1ec8c3c39ec4705944ffa8b3b9b61f73c9ad759cb79a107dd93a125685f5119); + tempvar res = res * point + (0x4d0db05514a8c0f152a8664579c004fb738cd3790214984bc3f21f31d494361); + tempvar res = res * point + (0x2bc791bd7e68342116218ed9bb657b8b54e550022e39af11ce55b29ae49218b); + tempvar res = res * point + (0x7ea13011e0dce5c917be4cd36c8931f5969852109a16d7c5142e8fb3c8b7650); + tempvar res = res * point + (0x11a9029a5c07557ec347592ba7181acafbaf0f0c5c9e81d7e995a4de57fe566); + tempvar res = res * point + (0x359506efbff0e2b81d91cd6a5f808a6c65255e1bf06cc03dbaba94758b3acfd); + tempvar res = res * point + (0x491899cb7600abb42ac8cd91f2c775ec410469573f57c1030ed1582327eedb8); + tempvar res = res * point + (0x7a42c4e98f014e50dba6b25fc32401b7695fadb7bf271fe0a763712ee545c2); + tempvar res = res * point + (0x2f7d26f183c54146bd83514f5459bfd95ac635649d74225c2168a8e7baec082); + tempvar res = res * point + (0x3ab952be650de0c679ddc0a35bac2907a6e58303059d4edb914e74c67d05226); + tempvar res = res * point + (0x2b7f9df93ba787a9a5a7a0a3b5daba02e2ce65df16ada37575735697eda6c1d); + tempvar res = res * point + (0xb04ac19a9f1483b8ee3b763be73814c9621fb3d23e6d874d9093d999d3d4eb); + tempvar res = res * point + (0x4f4df07e55d3ebf0ed955bd9f7c34de001f09a92c1ead17b0c1a485d48a4329); + tempvar res = res * point + (0x1522043741ba933948d7298114b71322258a3d4e7cf2496590c35683dbe2a7c); + tempvar res = res * point + (0xb489643a1aa2c181b4739d45582e2576a6f9bd51c81d300ebdc3a58b79bb2); + tempvar res = res * point + (0x4db70c63a1dac4e5ddde15e3626d009683aa8ea14face2c3fdb6ec97c8a86a); + tempvar res = res * point + (0x309bca858a0f9fc5a468a57981c9c6b7c79636b1f31284938d1c6a21f006a33); + tempvar res = res * point + (0x625a1fce22a9fb7717107b137a0f5ea4ca059008f5cc6fdfb5cb5bb1734bd17); + tempvar res = res * point + (0x6ae2e00f7827692b0d20f483d3c71594f61d50846b52abfee39f6697513c0d0); + tempvar res = res * point + (0x4b5acbaa0f7e360885677439654649256829cdd6d4a6c7ffa904a0683fb5fe7); + tempvar res = res * point + (0x66a63b8ed2255586855fb30333ce0e2ff4eb2b4cd5d2125d8d20cd3fcfc1d04); + tempvar res = res * point + (0x55351e9d60f58241736330de978242e4e40c4209a7879d7ae3823c148abd82a); + tempvar res = res * point + (0x588747248358bf8bdbd990996cb43468c89909cad0f8230cc939538b9b331df); + tempvar res = res * point + (0x67801dffe217a1a64e0b12f405157af52025266fcc391fddaebf3b6c7ab79a9); + tempvar res = res * point + (0x411556b9c89186a2f9f79e55d045295790b28af97fab64e77777e3828532be5); + tempvar res = res * point + (0x5c01501e6a113ccca7cc9c723b1fad6ba60ec5b0a85b7d09c72120d3f733bd5); + tempvar res = res * point + (0x5b0d578cb7aa59ba02b0bb894848b745440c0cf562c2e635312c9bfc305e169); + tempvar res = res * point + (0x3013a9c6094ab0086b1397621f93ac07bf45574ea26b09d3e4587afffe995ca); + tempvar res = res * point + (0x7d9c679179dfab605ca04e1993b37ddff490c440665005698a47c442a1cc10c); + tempvar res = res * point + (0x4f6e24500755d20ec5f28480a41a0cf23baa1aa24202382e9f4ec8ec6d7596); + tempvar res = res * point + (0x4e0a6e0c26f85c74373782bd2924f3bc0f6b4a2914c4f7f8850a79eab580566); + tempvar res = res * point + (0x6caac68bec6ce4eff4f74c1f33dbc027165cc02cec8f69e9470ff99c0b132c3); + tempvar res = res * point + (0x1c867fa9ae031469be012c4f201ed3ad56573a22891351012ad1f7d300361f0); + tempvar res = res * point + (0x1761abb092f6c4e3eda770480fb4ab095e786bc3f1b1f960bc4c95232308b3a); + tempvar res = res * point + (0x4a35c4582c91999a39b553248bf2a39ae5825204085a9e98bd6ddab3bfcc0a4); + tempvar res = res * point + (0x6a4efc048a81614dede6c4f6181253e84f20d4a4f95f973147ee3fcd72077fa); + tempvar res = res * point + (0x65c14f7de75359a40c5f244f78b2920b61087fdbbf59aa507644d94f5bd210); + tempvar res = res * point + (0x9be8b219ca1684dfbef720a3e9f034b319e2d233aed85063924fc60aedf20e); + tempvar res = res * point + (0x7352e8793ed3f6283e492544b2944d6fea715980d8884f6821574d36868b0c7); + tempvar res = res * point + (0x65c04013accf25a2cd1d9eb98689d71694ffb20dced009df5b9af167602b4c2); + tempvar res = res * point + (0x679bf3101f8b2112eefab47d7372f0297507511c7cceb4478f2baf0541740f5); + tempvar res = res * point + (0x162e6e8431b7280f8401ca08922c5452c7237132efe3a481a71b5c97183e9d0); + tempvar res = res * point + (0xd9da926adbb5ffa493c54223f97fa1b0d141129d8736bc4f5768426c7e82a2); + tempvar res = res * point + (0x711628cee8d673863e18f058cf82551ca8351486b9b210873b4e18447e11408); + tempvar res = res * point + (0x6f6131c193cd7b3fdb4d0848df70474ba9e80529097311cd7c13e322205a1c0); + tempvar res = res * point + (0x2512f776d1b3d212be7c2adce1cfa083d1b2b9af1c6f3cc424b266bfa19aa06); + tempvar res = res * point + (0x400330fb079fb4cc8671ea9a996de8f5442f20b9b9a3bc9df8b81e01506c5ad); + tempvar res = res * point + (0x40cfb729788e16fa80b7d937f0088157d18ff2cf7c79b748d0e150c896d348f); + tempvar res = res * point + (0x59786091e2d824242c7aa5dde34ffbac99f6a9a1aa5ecc8a395aa13e8aa55af); + tempvar res = res * point + (0x4adf53e64235d5327822ee3e584674af053e496c5d92a6c8c43e1e8e7d327fb); + tempvar res = res * point + (0xfe9d827d7e6387c7228d92f78574add4ceddddac1fbe71dec1258220c08402); + tempvar res = res * point + (0x37f1342e071f8a087c1405692443305d28d4c11b84d92bd7dedc563fc3ad329); + tempvar res = res * point + (0x74a39339d1d708a9ea407f03d8b0e5ab103c3251596258b78be1bd97ad06915); + tempvar res = res * point + (0x152c16cce8c1c782287b8908a790014fe3c51c57cefaef63e2c8dae5a7a5daa); + tempvar res = res * point + (0x5b32dadeb15d554f39f227de4ad20600eea4b763fa4c90ffa1a41812ae43479); + tempvar res = res * point + (0x3b4b0f9b88e16446a2de79c1d8c34865d5d6e581f08bbbc652ce67d8ac1d952); + tempvar res = res * point + (0x44041800e20fa7a15dd9274ea8283b09c30a0d900d9c165217004e669b39d99); + tempvar res = res * point + (0x5609324fa7ef5213591c8d36c59dd42df8f5f26f84468bb84f843707a5c9c48); + tempvar res = res * point + (0x6235547369b594514d2fa1ca9b06fd25f9d2764fe8b099c7d9671f542a01d46); + tempvar res = res * point + (0x614509129cebd380f416c4c9c7127ee7b53d878860905f047ad722a82147236); + tempvar res = res * point + (0x4f847058896f8e2727ef3b4577e62d5f6a729696b8705fe217b97c73fd1afee); + tempvar res = res * point + (0xfee20b19c4437f06eeffccb05b88c4e236d18f8e3518ba124ab4eec844c496); + tempvar res = res * point + (0x5897638208b8e9509d1128c29af87cf30c57942d47016819435b373c0a309d7); + tempvar res = res * point + (0x1fb19890707fa2e617de7dcea9ad35ce9960009f1e38aa2629c66fa5b8d5d19); + tempvar res = res * point + (0x45fb29b3ac673e9f525332c8bad73d76521985406fc09398078b30339c857b5); + tempvar res = res * point + (0x528d041bf152aa3a0205430412a196619b68c81d7a706fea0fc090e0cc6a105); + tempvar res = res * point + (0x1e149d42cd477212ab7f01fe40f76858f09ce2bdfc397df635ed8a453714e7e); + tempvar res = res * point + (0x75f781602ada44803c0ca4bc8c1bd5064700762d18c309a2b9059dcd8c3dcca); + tempvar res = res * point + (0x1571843ced13a8d342b63c63abc4b83d357eb286af04380edd1eaefcef3f1f8); + tempvar res = res * point + (0x304103a8d35f43cf87d50682e86e473fffd71d13e0c783e596a59a62b06402d); + tempvar res = res * point + (0x2849ac77a2f5398eef51aeb8312dcef8b347b690728d4eb835bf4670301e6e7); + tempvar res = res * point + (0x52a36a173c7ebc96cfc55bda4bbc73bc349657d39ebe096725e9cc4bff01def); + tempvar res = res * point + (0x43e371660fff35e52cd5dc08c9c347d8f7c64a116375d0e6e3ad3512d85a99a); + tempvar res = res * point + (0x76594f29261e2aa9cf4a90b58b0f79c2aaa99d63c4ff64b4806cb8cfb0df316); + tempvar res = res * point + (0x4cbae4979c7a1313c2d0f68b21f5734ec83f9e1a88c78b3976a6ef84a1b6dbd); + tempvar res = res * point + (0x76702a08064b5768ae2979aca07322782191172276f1bcfbc14cbaa3e758dc); + tempvar res = res * point + (0x64f8c462b308a1337bca235add2482fdc3607507b2c9c0f91b9187f5676303); + tempvar res = res * point + (0x2ef5951aae064a7357b1e4ed49f05f17f778f2e8735f8d17b5cfb82faf3b848); + tempvar res = res * point + (0x66e2651e6f5758c334d1c1451d563b2df07b424b5d0125c739ada959479890e); + tempvar res = res * point + (0xb3dd17f46d6b12bf4e5db184d6962c156bef94f9f73861e34d88503fbc517a); + tempvar res = res * point + (0x19412ccd078bf5665579cbd16035a251e08f40722eca4452eedb31732488468); + tempvar res = res * point + (0x719df2a50d9c3f2eb3f0336665f2980e432191e21fc49f488854b8352fd94fe); + tempvar res = res * point + (0x459f095ba3b70f76e493c6afe2d4b6eebd21343f74bfe3390868612fc250fdc); + tempvar res = res * point + (0xdef6a0b2b71d97a59c674c052fe23f7d000a334e180b0793b6974fe29a64c3); + tempvar res = res * point + (0x74e503d57e49daf6939077c0b4a4d68e66bc2425ce53b01b48f146295476401); + tempvar res = res * point + (0xd49f196e60ebea0eb13d85f05cffedff32477e83129bad30bd9dd555755429); + tempvar res = res * point + (0x298215f335fb63a11d31958d950d95c909bb94e144c113cc4ecc08488469097); + tempvar res = res * point + (0x6232d26f420f9b4f119e64762927b5e8a21192575b200081b0545ad4e9a2c25); + tempvar res = res * point + (0x2b51d7f94ec71f3a8e3e20d766a4a7f13d08d758a686ff86dbda48026c7ec3d); + tempvar res = res * point + (0x45fb08bc21969d5ca9b1ec473cc92a4ad911de8b0607ddc12b9ee98c286d37f); + tempvar res = res * point + (0x70c0f7da90cd889d8df06f9774de8a9a20c88e86753506c7afd0e1f6ef15e76); + tempvar res = res * point + (0x1b16d94e84ffd3ad61286f5a79d5a6f7b5b5dd6442aea9013ad21467bf1281d); + tempvar res = res * point + (0x6a81925732161d4e5dc61ed6a10726027fa66d892aabbf46a477f4455072c02); + tempvar res = res * point + (0x13ed29a84c4875ac188521bc40e9258e03d83c9ceb8716c6fbeed065a5df73b); + tempvar res = res * point + (0x184ee38f80fa532983fa248c14c0220c2a5691836e899a5c9b83c975b03608f); + tempvar res = res * point + (0x65f4a97d2b1c90582859966540e839ac2d62ad2ea960aa2af36776b2d07ce34); + tempvar res = res * point + (0xe00ac968fe5a147fef45fbd626c540a194ec3dfb2c1cca7938e037349d4f34); + tempvar res = res * point + (0x96935be4e41797417259166181bb646a619ef95cc8978ffeca81d141d062f7); + tempvar res = res * point + (0x61c61341c83517cb7d112a76864271492473e04130ce4ce23331f7300bd8c89); + tempvar res = res * point + (0x73eba0e9e52c3a93ab6dce26d5858b2d699d8401b2c43253616b5701aa803c5); + tempvar res = res * point + (0x77434256511acfd027b41e03a571a9f56b0442dc675c139a2e1476fe716102c); + tempvar res = res * point + (0x325f10662fc8bd38e591b0e8caa47b3fff46703656b2c5863d39c150d298fc8); + tempvar res = res * point + (0x3c835256339330b1c94cad78cfefda36a949b9c8553d918f3d8547cd1805ac5); + tempvar res = res * point + (0x7340540d0c9f9dd2c1142f03f408ab977afc7371934c62259fdd29f0652f8d0); + tempvar res = res * point + (0x17d8ab17e403b1925b40206c11f8a6a29ed08217e1ef303906ecb354fdda1f3); + tempvar res = res * point + (0x78562cbfb984ebea085472a1b004dbf86e7d99f4809a5020969246a84a9d165); + tempvar res = res * point + (0x60c93d3dac2628ad796e1dc80bc0796d054c991ea23094d699bffb43a630add); + tempvar res = res * point + (0x72bafd4641e6928ca65cb48e8001ee077944201f70d5bed524c69b709410d3e); + tempvar res = res * point + (0x6321e76192ba31cc63bf7c526c8ebbf4df5b705f01e4151068ee3dd658aa674); + tempvar res = res * point + (0x7caaf4f7b073af26c036d8bab5c74fc3f752f9ecc01041787e9ddf773596189); + tempvar res = res * point + (0x66ada08fe725f364ca32c1055e1ab1216967856d6cd8762dd4ea915c2ed40e9); + tempvar res = res * point + (0x5b6477413bac2f0d370c0cdcdec4cea10fd322fbcd7b202d4ccbeb0581fd34f); + tempvar res = res * point + (0x35c99bed31baaf7833ca759a9bea792965a87b42171259ac51b00d872d581fb); + tempvar res = res * point + (0x7ce96f5a3261a977f04ff70ef416a3d5c165100d19f551a6ac514e4d00fb18e); + tempvar res = res * point + (0x1c933d3449f6241d0f9d547db9e708fc2ee3e0598be5f87b675fb6736a15c39); + tempvar res = res * point + (0x687aac173963fe1e01f9e0d50eba0e95e1e8783eb21c0f6c1f45cd42408198d); + tempvar res = res * point + (0x2f2f5447e274a20d9d60615f83a18b2a4db300d5e199d7c8c6c6cfb754e8cbf); + tempvar res = res * point + (0x91cd6c3b8ddd8954a44e8a9cf6f7f183af8e6226849f05e6e6ebda2409e042); + tempvar res = res * point + (0x282ad11848887c771898b5a32ac6ca14cc2510830454aa8e194975e308fe042); + tempvar res = res * point + (0x5455d2de2d7570fbeeb431a9a21187ecc049874b64a227bb543aab4af16e27b); + tempvar res = res * point + (0x2fcabf82bfd2529eac169a520cbdb2a0f8c205c5a9b1f1ac69bd3a44b25faa9); + tempvar res = res * point + (0x33d4fbf9dae7a87cc13db3c95ed3976b50113f072e56a13e675e4af241bb864); + tempvar res = res * point + (0x3cbf28927ecbda443555c9d51f40c294fb6688a17812cb0c85fb6501cdc0709); + tempvar res = res * point + (0x4fefb86cfccbbea031f15d85033f10f92f2b6b689153e305bfa8821935979c3); + tempvar res = res * point + (0x63f4ad31c4d59ee741b1b0ac99e022959df079b5b033ec7a1ecd3b4797f94d9); + tempvar res = res * point + (0x6c74e3b74559e12949b8c3b55369b2d275b2920b4442c536d63f91debd61499); + tempvar res = res * point + (0x45a5b88744e83d901f33da0d0de869381e7a125a6d8bd104cf72ded013ea4c6); + tempvar res = res * point + (0x11243de8b4214dc3220693acfaa6b626cfc3b8c812140779af9b72dfb1b92f1); + tempvar res = res * point + (0x123f50f65a68168d6b43c464270479801376ff6979b94f60252a47d9d7d34d2); + tempvar res = res * point + (0x25446fd382a1b0f5350b91290b2dc35a6dabaf215d53cbb32d1732fc6ebfffb); + tempvar res = res * point + (0x160d7d587f3a17673bf04189e0062c7bab764fb54ebd0f042fec72f953a91da); + tempvar res = res * point + (0x1e0fcefcc1d1c5a69e81c4fdfe7de04d95b53c162a3b64b5956df8e59e1b93b); + tempvar res = res * point + (0x1925470cee5111eb991ccc8b0412be603c0b8df342d7b186a3aaeddae103bf3); + tempvar res = res * point + (0x2848af5bb20ab624881dc9244ea18b1d6939e14270714253a896e57cb0f63ea); + tempvar res = res * point + (0x6c2a98464d6eb4038d55b57632bb283ab091eac255fd6797df41612cfe3ea1b); + tempvar res = res * point + (0x31563499de399383464854a8679e0b073513c5bc46cdcc2a2107f00677e6356); + tempvar res = res * point + (0x6da4d6fb1e6b2f1b42910a9dcc4702912002d7d36ac7100e19c7f298c7948a8); + tempvar res = res * point + (0x3d368784067d457e43cb63b3f526e721fab153949b090a99a128c5744fab4a2); + tempvar res = res * point + (0x266b63657dbde655f034c014a8fb73b77138b52eb0e17eacbf402bb90305f10); + tempvar res = res * point + (0x179f2a40de3db251b95a60431e7cfe2dfa48dc8654bbf81add938e9f2f6725c); + tempvar res = res * point + (0x1118c09adef545b07e209d88b0a645673a103c9e71e8f671e74c84abf1a2a2d); + tempvar res = res * point + (0x6ebb7c4ee2d4212e6d7cea8c16f97c935f3bbbc2f400c9a738f1ebd37eec6ee); + tempvar res = res * point + (0x41d1ca4f756c80f197ba1635314a3dc756f9d8d9406af16538643d3e1021bd7); + tempvar res = res * point + (0x3129daa367a01a45fe3f0ccde215371f59c5643bfad33f4269a6478c8c8b7f8); + tempvar res = res * point + (0x1fefe6ebd886640df863e5f5c25e9b42fbc10adfa7ef07d1fda0eabafa60a6e); + tempvar res = res * point + (0x37e79bd72d714d3de7ed2b1ba79e345f75646bf67efd8ea3050ddb357802a3c); + tempvar res = res * point + (0x24eb6fb4dbac687e35d4168b970db6e7dc76c4c886dce0d4bad2e6544b8e6c6); + tempvar res = res * point + (0x6508b5fcc13191197f91407d5b1b21d321b7f311e55ede9ab8a6975308dcee); + tempvar res = res * point + (0x43e46c5f1cf3b5cac9722eeee991cbcf53af25a4a355a91ea9b8a4d4754d908); + tempvar res = res * point + (0x7393709fd08807a84ca44526a2b8ec97bce5aad1adf00560d04110de6d9eda8); + tempvar res = res * point + (0x690c8328ca161c48f3f8f37570e42095d1a0d9e101b3ec0ddc91426fc22facb); + tempvar res = res * point + (0x41354bad5cbef57b0e7eacebef8f0176f3b70992ea5a418f502242acbc4a1ff); + tempvar res = res * point + (0x3475f32b5bea9dbd19ec199ef34e531b696cac0461e644ffb41a5e99d0735fb); + tempvar res = res * point + (0x33cfe02e240929353f193c6d3387f1117d04f116889f38d9a196abdf986e48a); + tempvar res = res * point + (0x33e7ba5f7e56065e3f8b091578e8e7a7b118116de47237fa5a97e44e97b7f69); + tempvar res = res * point + (0x5526001b8a8c2c6209e40b5d380836bcf63db4ef85c25fd5b72d749b0bd36de); + tempvar res = res * point + (0x64028a3945aa2866db68b304dd0d83d75ed0ba5c2f9d0b47e80d11d8da6526d); + tempvar res = res * point + (0x378113f110b2404e7d185e920249519ded728cb1027fa8cc2843a588886a7ed); + tempvar res = res * point + (0x5f4fd7854cf7b89a3983da1a39839d85c7331c3353b0a8cd218f7f4e1f780c); + tempvar res = res * point + (0x6467afeee167ea95feb4a85c48fabb2c7067de57acd5098692855189e21c57e); + tempvar res = res * point + (0x1e4bf5029043367487394808d7ee7df5ad1ad1da2c4710a1b2444ffde106f2a); + tempvar res = res * point + (0x684a30c1084e8edf34a77bf8848fd2098459f5461bdf3352faf9c8801435b6); + tempvar res = res * point + (0xe3f2bdc2de2b623c56390eb0044adb980766ae1a58d775e003c39724d1d6f7); + tempvar res = res * point + (0x62dae59d425684ef78c1829e0454cd5e76f5d322ea8cb5ae5e911f545beeee1); + tempvar res = res * point + (0x5761ff2e0a250691a66dc36d372afbd6a8016726efe0c418d7899d60d26bde6); + tempvar res = res * point + (0x4dc27c76881bb820eb74814d1b69825e9048b1a3b064e603cca4bd4814b2243); + tempvar res = res * point + (0x5a15d718a45959d16dd6e0b98badbb086e2a9741ac04086f078bc6951506e05); + tempvar res = res * point + (0x23cf69cfd7730dd096fd485b2d8bdfcd89ca6004689bcbcacbeff288f18ff9b); + tempvar res = res * point + (0x4d6c233f7bf3ade219a8e3a89e12d05beb7faccbfa811ebd930c391523f7b4); + tempvar res = res * point + (0x5a347e7937c7a178952905f499babbeda500a820ccfdf7f3a99589687a623e7); + tempvar res = res * point + (0x43394095e27ddb7825c0671833a6ac9784f31626914c902c225f05ce42bbd9f); + tempvar res = res * point + (0x66d91bcc591c880303ee4695475e8a8e402926f0c01ade8880c7b03c76998ee); + tempvar res = res * point + (0x3348152349370ec1c4d753735ef255b50e54aa9a432f48a121c39b8887827e0); + tempvar res = res * point + (0xfa17235a82497674de45bfa59e61a329b2d0e63eb18ab9b74aa46783e04c81); + tempvar res = res * point + (0x45ffc1ad229bf52b2531afadd1c5ba120c57b34def87149880d1e5cb6c5391c); + tempvar res = res * point + (0x37f5f6b25ee428e91e886127b961856d9ebc52740ceb763baa7e71371b84364); + tempvar res = res * point + (0x58281d625ddb432caef06e485bc2b74cc077aea9ba5072198e76542f0c69dd0); + tempvar res = res * point + (0x3e35aebb590266ea1fdd8198cf3c23c77731dddd95d488a9d9f9837e3bd0f6f); + tempvar res = res * point + (0x2850977abc89355540e8abb804da7805ef88b12f40cbd9158ef330b767901eb); + tempvar res = res * point + (0x72fb3298da88c470a2f93a391063810be01078c8375183b57a024c223f2f428); + tempvar res = res * point + (0x53f792c81d26c122898d70ed7fcfd8f02a8f5a9ec8b9868fc4490d3a46b4e8e); + tempvar res = res * point + (0xa7da81afc9f3c93366b6e161b1fc7a497d6c770fb140bf4b64e5fc707cd3d3); + tempvar res = res * point + (0x26601a459facdd83458b56099975d2b7dbbc431d41b53f5dd6ca2901dfaacfe); + tempvar res = res * point + (0x4a048ce90e3a1eeedd4932ff37760fd8b1dc995aff7107bd66318652efd1032); + tempvar res = res * point + (0x287fed27ab81e5f721d2bd5aab0e69f53e94ce5dccc35c2dcc88e12465fadc2); + tempvar res = res * point + (0x414215fbcef7f5af60f320e67a845e4a17b0a0eca39b4e18ba89fbe8a189491); + tempvar res = res * point + (0x208f0c2f5a114b2342f51e919e4fe44c2a42cd06382d9edc4ef58939b249bab); + tempvar res = res * point + (0x5726e3dee7bbc5e5b4f3ad65f0fb17699efb5936d50ad380785f2b10fe8953b); + tempvar res = res * point + (0x6fa8562db8de26797e9c9905aa769e4881304b4f20cb64d718d271c182f44fc); + tempvar res = res * point + (0x2a60396cf912573be2837653283a23702037f614e33e1c6fe2834eee9a1c7a6); + tempvar res = res * point + (0x5b6b3213744858ad659c4c07c9220380d63c01f680986191c8776eb703661c3); + tempvar res = res * point + (0x709a47e72cda4fdf428bb9784f02f77c700086755d4bdb5b229d1b80a2ea4e5); + tempvar res = res * point + (0x75e9c821cdd2e754759306283aa4af8bdbb0ed31f4e978dc550141fd10da6be); + tempvar res = res * point + (0x2adfa41f72ba3b61b9dfa6f017b19682b0b0f8cd86be3d37374aba3ce990a55); + tempvar res = res * point + (0x6e313bf82c34d3af1e7fc14d811dde163ca6e57accbe476875e4a967da00b8); + tempvar res = res * point + (0x78516acc9d32f4e54f8925865c91f70b210f4ebc7533fc624685b3d5daa7b18); + tempvar res = res * point + (0x3b8cca1c3fb2b26b7e206802d52d2ed1c725b8f95407e3ef295a7dd9ee0d45e); + tempvar res = res * point + (0x287ef69d6f69ab853e4f0d24b22e4c15169d12c41706dbeede9fb49c61179c4); + tempvar res = res * point + (0x7c84837e6872bea4f0448183cecd6bb24a8574456ab91173b04b9423be8a64b); + tempvar res = res * point + (0x78f890541865c12169233143f47a056a91dbd18222c5d31bfb2db19162c204c); + tempvar res = res * point + (0x46cbc37eff4616daaa86160d5690f5473e24171441e29705ae564223a351c23); + tempvar res = res * point + (0x309f9698e38823c05e56d073d83ea551bfa80ace08e749aa4c83031a22360c2); + tempvar res = res * point + (0x1a2cd41155bbb7ceee94dbd01bd876140b1698f03b2ff8f8de3ba45b4ea14e); + tempvar res = res * point + (0x10699899068f86fa3843b06693288630b9ac4b87be7b3726fdba32b41caac2b); + tempvar res = res * point + (0x2762878a5f6665bee609c26e750cd886e239c31caf1508d5a2a185b58576b77); + tempvar res = res * point + (0x57f7a737e643bd859d8a53e1b621c09be89fcca7b96f8e42333e46426f26a20); + tempvar res = res * point + (0x7239c3b89513196e3cae91f8df8bd79f08033061ba63c089bd764644907479e); + tempvar res = res * point + (0x38cb4f77410e9a33306f8a4b92b6f76bf239ba44e0ef45dab0bfcb75dfe4141); + tempvar res = res * point + (0x382114ce9d712af864a253d29471a436b83ee4f7b8ae3fe19ec3ab315e18d8a); + tempvar res = res * point + (0x51ceb130c1908fdcfa6896756241fca8f74ab172d98c76facb7b8b931fa8812); + tempvar res = res * point + (0x4f6b918e40f8022d2bda8d53214e8fd84743bc2280231d3ae772844bbcd1aac); + tempvar res = res * point + (0x2d9af4ef0d50851ae1b0cdab3587a71728eaaa4e56e67803c5ff9126e722696); + tempvar res = res * point + (0x4640cb2cbc73d7c9fd2a1783122cb5ee8c68e7c04b0b647d43a35cd4961e4ca); + tempvar res = res * point + (0x1b3104591a23f262051182209c0f73caa30e8631fc4413a5bf97c9d51a70abb); + tempvar res = res * point + (0x2103ea7ff918748c4325a992c561b551b70fa9d97e48a52b3c157799d213693); + tempvar res = res * point + (0x69fb58adef701279dddeff71e1832aea01ae10a5128a9f744a5a945b5fff200); + tempvar res = res * point + (0x375e99f4993200342e6f6ad713711052d518e5dac24681b3999878bbad627d); + tempvar res = res * point + (0xe051fab79733dd773d13f5bec04b1c20252df512d937f6b7352e4c4fa49cb); + tempvar res = res * point + (0x5d72a87fe662c05530c3ec822f925a10c121a44c4adecf24850fa2442cb4abb); + tempvar res = res * point + (0x6f2a9f716b1fa27c35675a57273feb79ffce02286bcb1e253a8e126c2cea357); + tempvar res = res * point + (0x9b419422a2083bf174263351640e009b56d6e2278552f9e7ee6a6004d45524); + tempvar res = res * point + (0x3dee84f905f6a06940783bc3f322a0fc22a984dd244d00a85ea3a4295558377); + tempvar res = res * point + (0x3dbd68c7c5945f48515d975002a1caf1c491c6743f151df31f95c5870c90fb3); + tempvar res = res * point + (0x7d52bb08c1d72a66c3e5c60f6742675ac788ec8b4f2178ff9990a04d22c076e); + tempvar res = res * point + (0x107c8fc81a96a3c13d1ddf04b8bcce0450610c2ee6c127e0f47ce2ed2fa0613); + tempvar res = res * point + (0x6d8f39b47e79d44503aa87a3fdf101b055f89c663bd7ec377d175280f3f8db9); + tempvar res = res * point + (0x6d5a755e91ed732dcf8afd32eac3b4875843bb116430a966ef88f17aad54c16); + tempvar res = res * point + (0x64035ce25716c9c7675ecce40d3cfb65ce3121439e10367fe29f2742cc02d85); + tempvar res = res * point + (0x3e44a162d501fc521774c75994f4b55eb85878f5e867cacb75c7ff0b7efe941); + tempvar res = res * point + (0x1b2441db55dbd9b87c45b1afba238ed28d1f2dfe9725d9a4cae3a45e3d59b63); + tempvar res = res * point + (0x8b54ed775cf8f3dd5b54fcdea07e2bcefae323f6212b8f54877a60e1f8026f); + tempvar res = res * point + (0x338c001d0c722d793cc14219415d61c52de28d33ab8bfe5dd31674784f2b568); + tempvar res = res * point + (0x4ea62ac09b98dcc34b5437f6bdb4fb9a681dac12d1ca7090011c73259dcef4b); + tempvar res = res * point + (0x6a226b1dabca8ff2fbb52f0adcf4267a47e0eed089774157f318b507361a0b8); + tempvar res = res * point + (0x6ba0329f670df105c31eb665f3b6f243ab5de7ed8aa59ce9b0683e6bdfd9019); + tempvar res = res * point + (0x77f62cb2f9db71ba7a9913be0a434ca045a26704681af5353b7c7860be6e774); + tempvar res = res * point + (0x770018fe3435297b82b391a3bd2d09151dd3949545d0ef111cdf9fece9f389c); + tempvar res = res * point + (0x4279b49402fada9fcb602f909bc138c3547baf384dfef9594e2fa488cfdf8b8); + tempvar res = res * point + (0x4dabf5afe371cde17b9fa6c54c1b38d603f345c58d4f66e06fedd8948b402b0); + tempvar res = res * point + (0x15296a7d071a85f1358bb157d5e62b18a11e189415c16f594a18be7276ed2c7); + tempvar res = res * point + (0x79708fbce6bbe1c862e988648dd25347d60c9e0981540dd81ccaf78054a12f8); + tempvar res = res * point + (0x209866f9b8d946508db2df8eb9d30f65ede2c99ec8deb2e5a1b7093e9a62416); + tempvar res = res * point + (0x4ab0da9c66ca2588350bdb85cc745b4c5e7226cf7c4fb69708cddf6e8145f29); + tempvar res = res * point + (0x54578b117a58f5beb0d511ba42110c4696f4fec165acfbbde208a4705045fc0); + tempvar res = res * point + (0x55c9e37b0208bfbbb61e5e0e05c72111421b24b45ea53d3ddfad1cdfd243ff0); + tempvar res = res * point + (0x5889b4a99416f2f954450c60492129c5f7a36f875a56dde5188318e88d6032a); + tempvar res = res * point + (0x5919f2392a53f9b230145d1b5e6da28165dd1d8cc7d28d3310a805ebee721fd); + tempvar res = res * point + (0x43e49d0d9bfd165776eeab9118ea672c24a055a700e35a04426abe1b236506b); + tempvar res = res * point + (0x40e394412097f7c06183ae2997707604273b0a4ec1add0030bd7e115c20ca70); + tempvar res = res * point + (0x6337d741eb226911e37cc48087126cdd89f00941523cda2fa5e965dc4fa25e4); + tempvar res = res * point + (0x64592b7d9a6a922f5cf5f74c56e167ec000436a6b3caec299bcefea25e5fdd1); + tempvar res = res * point + (0x1d608ffab983d8aa17db9385433abb0025c77e27357285448c4ff6a8438570a); + tempvar res = res * point + (0x333793406d06dad0406a859ea2c203aff33e3cd906d6f04aabb0dffbabbc9c); + tempvar res = res * point + (0x3b5f2338d066753b2507a39884bddc2d0c5bef88e4bc3e79288331afe9a6234); + tempvar res = res * point + (0x3fa0ff20cc486bd0b43f96826c66b070a6f6e3df3359ebd2970661f9c679e2e); + tempvar res = res * point + (0x62cea6c83442875da8b98083d8bb18bce5d3d431a3301afc635600578b33506); + tempvar res = res * point + (0x4835c753d4b5059c1b4186516851f562e63e348f8810714cc393be9810a1de8); + tempvar res = res * point + (0xc230c4af49117fa614b1d4d74ef462211a5d55537ac71564ace080dd4b325); + tempvar res = res * point + (0x1917c10cc63bc9f43116c3688542cd867e1a84ce0d3e58dfb0c11c4b0828748); + tempvar res = res * point + (0x13c6580dce66b35fd24183e1635fb6008a6deb6cb507bf48d531273d5b4c2e9); + tempvar res = res * point + (0x6c6dbd58b8657f8588bae8a4d990e6f9b0525af4eabe87512c5f6a655c92028); + tempvar res = res * point + (0x59daeadc724e9c227258a56b000c6a613db617da41bbeb694521c86323c93b); + tempvar res = res * point + (0xead9e7eac2f6c388de28561955e6009f9f1ed098f70516f2bda28597c9ee03); + tempvar res = res * point + (0x54600ac31d014f7241c14e5aedefdc72b839cb0e98b84aa13f031316af48648); + tempvar res = res * point + (0x5370b38ea84ca67c75ab50a4cb8f23f4017175a98b23df9e1c92f92c279e169); + tempvar res = res * point + (0x23ae2f35a2da5ff92426d59ce066e29a525ee1207de1c370023975b4403ac6d); + tempvar res = res * point + (0x5952b292edb661874ff2d3482fb968149f09982bd7a194d2b502ee3dd32927b); + tempvar res = res * point + (0x30c7ab8fe6b61574f49c3d76b3173f76816f31beb33097d425a94beab6caaa2); + tempvar res = res * point + (0x4dbc9ceabbf1c8d5c679cf80d9bfc26ab696135792e83061e98b9c36ae6a4a0); + tempvar res = res * point + (0x3f1908469233dcf5c433790cb3574261ed6debca41fb55b912be7cf34adc187); + tempvar res = res * point + (0x51778c6b175ce13e994dc1604dac3b901990cbae0246b2cec2aecbe96dd2006); + tempvar res = res * point + (0x6a91b3677713dc15cd110c71cb8e174c8ebd8d7df1a1b4120bb4b6b1683ad5c); + tempvar res = res * point + (0x3cfdc71122fdfc7807b2efe35fb6c7691985d2727401eb8a8132d0e0df3cdd6); + tempvar res = res * point + (0x5099f832fdec91fd27af0d221e009ed6770227d63bcee6e1802cdd122751260); + tempvar res = res * point + (0x1793fa490096ddd67530e29cb3e8e9632d1885815be3f9d96375aa5946f511); + tempvar res = res * point + (0x6d4bd8c4aa4a530d965180c18062d6bc440e6e70cbf0836d6af11235c7fde2d); + tempvar res = res * point + (0x3d7587a79c4ae9c24934a10a9c1398c04f3915fb6889b72b361505a85db2b69); + tempvar res = res * point + (0x39007630deec4a6eaf806518c109f4aff9cbfb8826d86f301e562ec560ff89); + tempvar res = res * point + (0x51e4a728ecd68dc30e4a1b5867a1022af5808edafc3cb12d26d43b495528f18); + tempvar res = res * point + (0x7f921548c686f600b302290f692a66e9ececa142f691f9129c7d8bd2a06803f); + tempvar res = res * point + (0x42cdd4f6ecbfd891fedb9ecb6d320f6adafdb274ee15cc11ef4c0436a4e9afb); + tempvar res = res * point + (0x755d64434e4e4233388c34a90438764c568353cfde4311021b45e0f369b0db3); + tempvar res = res * point + (0x4b5e107dbcd02c0dbef4d3a77d66386a864d31109d0d0392847c8919d926fbe); + tempvar res = res * point + (0x373a1f2fbe36dae9a5f2c2b35febe59b53869e1678c8da23bd9e92c3c2ac0a7); + tempvar res = res * point + (0x53bad76d22e1525dcec248b73438d6f444caf75794c26144e26803fe2bc7736); + tempvar res = res * point + (0xaeb135e456ad66bb5bb2b91a4aa429915f6f9951aa15bba78576744a698016); + tempvar res = res * point + (0x111d440a13cab69043e1072b61c1736cf3901941b4c57d7602b8effa7e74b3c); + tempvar res = res * point + (0x5fb8d87e82c3547e32ce316e4439d1aaf3723e4a906c91533ba8dd9631f1661); + tempvar res = res * point + (0x1426a2050d240104b5c07a9cdaf7fce03c2accadb0ce98344ecb4942c434db); + tempvar res = res * point + (0x929eaf221c110efdaa57970581428d66d5866fb9547aab76e89e8971efc91b); + tempvar res = res * point + (0xcb3220da969b95193a25d1d4d76d1cd1ec596040a7b31da7f64164809bdc4); + tempvar res = res * point + (0x3c3ea2cbc8ce544c6c98ad9053cb2c35326f4e502214e5f72c7951474b5a84c); + tempvar res = res * point + (0x68892b41018bc73b541800d91f0bb2a8cd9fcfee8be13bacbaf7dff7aecdcd4); + tempvar res = res * point + (0x2a652d2592f5cc1197a206db79d06e3b74a55b1d4ec03c516a6957e87345cbf); + tempvar res = res * point + (0x1e0c96f0b836d1e2df4e4063d56b78f38f2ad16040d61855b0f664c066d130c); + tempvar res = res * point + (0x65d167bcce20a40b78583e4dcf7e3f44663e0c595e18f48f83ea4230b207047); + tempvar res = res * point + (0x1668b919fcdf512b5683880ed048853e00f456adde728427fcde63ac9f59611); + tempvar res = res * point + (0x1489d6012d4c9701b63f3610034fb5bfca185c7b01222907781eb104e031097); + tempvar res = res * point + (0x57ad5370b26ea1478f3fa0346d2e390e90feda8022c9820813d9ddd0f36e7ba); + tempvar res = res * point + (0x522f83a59f717f37b235c05338a02630ad83c3ed307838f6e795f9705cbc849); + tempvar res = res * point + (0xb6bca44a12ba7914e575f83cf8b9b8bcd4780622806901dcb9530ff9a454f8); + tempvar res = res * point + (0x6fb8324456f1dc4b423220d18d40de524a27dc4f35e4c780a042f6edc95f97d); + tempvar res = res * point + (0x2039c72c1c7c134fb300e82b104394f54a5b7ffe6f7f00e7c3e4ca6640841a9); + tempvar res = res * point + (0x614a280377b9dc732773d969da5ddd8cc125262313eb7b2bd38b7668cdf00b4); + tempvar res = res * point + (0x243a084aa8c82348102320b0ad19ede41b6bd7ffb3a7041339a13f34f6b5671); + tempvar res = res * point + (0x73e8c35fa646fce6bf10c33168dcf3d2e40af17ced70b1929826d0ca4ba2e99); + tempvar res = res * point + (0x64f6f50e51b19d5a90e6d2c9cfc3486dbf2b37c7f949cc4f8ac4dd988e5bdff); + tempvar res = res * point + (0x1365aaaf8c72d7e9b250bd91ee2c2264362e87679abcf2df2b7a4e1eda1575f); + tempvar res = res * point + (0x24a083b7cf164138ea0c468f33317d89c97b69378c906d918123f3ed5a02cf7); + tempvar res = res * point + (0x25ea89f2d7ad620296fda2be181b5a6be626eade8974facd81e53df842c125b); + tempvar res = res * point + (0x2d32dd179cf74693057ede607e0054fbc3e4194efd6415156f3ec909c37ead2); + tempvar res = res * point + (0x3b74f537f03a28e72bae3bf1810f1a2fde1711eacd6bc64bf55f37b3bd9940b); + tempvar res = res * point + (0x575b929bc0caa43939bfae95a6d5cd8d4082be7fe0934be4c08f7fd3cbe89c5); + tempvar res = res * point + (0x7ab2a5ce120c251b658bfe532880535e93cbf88aa60a1b384017195e6715706); + tempvar res = res * point + (0x7a7d5ce80c8498175cdd4408e08cea457517e37dcba08d0a6cd2a4defcce34d); + tempvar res = res * point + (0x6475aad2a1631a6103b238548fe8a03934779ecadeaead2bc20a677c0c71c); + tempvar res = res * point + (0x547ddf1021a2cbacc8081cbe3a5c89b8ae808942513cd6f6ad166b0306cee66); + tempvar res = res * point + (0x653405343098520984b06f707cee84ea765ecc932783cca87058b88d0f2bbe9); + tempvar res = res * point + (0x3f22422d66d77bda123b47b7f5bffe5527f95d331346f6a545c66887ad75ab9); + tempvar res = res * point + (0x1b18b73effab8a483156d16e87be4dfce1250333eafc784d76c6ee145978c48); + tempvar res = res * point + (0x2843bf3d789d84faebdd6ceb0eed3ec0acd959732178b00b4242eb5cff0ef3a); + tempvar res = res * point + (0x592d2fbca1f86935e587f6cfdacd0a221237bd378e2d1cbadc3d168c7a1756c); + tempvar res = res * point + (0x4c35c95cf7170d2ab6b9b6e3c1be66dba2de170638f27975fb5ec12c36a45d); + tempvar res = res * point + (0x405f9011670f0f202814795cdf0251b665e8f39991dfe2282a1dd2acdbaccb1); + tempvar res = res * point + (0x43b4be816239e45b4d22123c840717fe3e8f6ce53238fad4ad56e27c85f3e9); + tempvar res = res * point + (0x3a2c1769a49e0632c149dc9d3f30306f9d9cc00cdb426d58b2741c804c51af4); + tempvar res = res * point + (0x422c03b47f25f698d3dfbb02556367c97b7d8e2657af2e45ebc61845aa2c52b); + tempvar res = res * point + (0x5a47f80b2d6e8c8e89f08c23e4eee09ae23882290a4dbdc5d0b09e713297124); + tempvar res = res * point + (0x2059b2385d435959cedebbb68ab5c484441832a20d67889ff9974057cdbf874); + tempvar res = res * point + (0x6b735de6be3ab4aa1425c328c838ba09dec586718729f1e172554cac036483b); + tempvar res = res * point + (0x3c05c93a63aad66725d8d25e62f76199a1e9f5743577777caa05832f4e79acc); + tempvar res = res * point + (0x4245e03d0378593b2d4230b945a2a147b36ebfdf368f0dd5fc22e3b31ac1186); + tempvar res = res * point + (0x4de104ea20937d5d6cb02c4ab4d7c4d03ab2eb16d1b837ccf0c2a05ea2873b1); + tempvar res = res * point + (0x48876d457eaebe03383add02eb4c0c49a09923757428595a4f3ad6299d69cba); + tempvar res = res * point + (0x6d6ed610ff1347a9252bf835af9666acc415b28796d968ab76353cdc1181733); + tempvar res = res * point + (0x1da9b14257c5c5cbc1a97aff87690dfa51e82af9a11eaf5cb2538f595ea2105); + tempvar res = res * point + (0x416057baac3a1780d7d25b192188b9b3981bdcab0e2dffb2fd95456a5313201); + tempvar res = res * point + (0x1706af2f962881d86f167571fcbb909b6f1e4fa386fca8d87b674335196f44b); + tempvar res = res * point + (0x6d9c76938c974418e62166285ade6564712e6a263357e11d70f3e1f2ae531e8); + tempvar res = res * point + (0x771fefe011becb392f5c379dc9e902c41be8f1069ae3c5e0bf6016b7b1b3f55); + tempvar res = res * point + (0x40cbcae9364d8af8b767a72b260793922cf1ba2a03fedfc60d4eab1d5f00042); + tempvar res = res * point + (0x274b54e6342ced28b28c62edbc8a6cdb44d1530e0fba56e4940e55d806f437f); + tempvar res = res * point + (0x77273f7030b86a46aee79ed44f0968feb0ffccfa0964ffff141e693fd0fb6d1); + tempvar res = res * point + (0x4dbe5188f23eedad88bab99323be5ac9bf747525c23d4c0665334dafd1f0c6); + tempvar res = res * point + (0x3410d8b91297b00cf8d438bea18b9ebd55ae441a2f6bac6623a15e43ad64d4d); + tempvar res = res * point + (0x4195cb2f46ca4e1ef5d93ab3a5decbdc9e74d0bb81d56abcf59304ecf79863c); + tempvar res = res * point + (0x6581a70ec64b4268a4741b4f7de866050d31b69005c782630f4bdc51a1650b2); + tempvar res = res * point + (0x754535ea8702292678b57fbde36c97454994bed59e0d0e13cf8a6c3ef7a0324); + tempvar res = res * point + (0x71034c062fdc1b61e812617b037c5dd1e80d158a92bdae7ccaec162fff4edd3); + tempvar res = res * point + (0x297d52739d69b228b057588496920930df6ada28e5e2a431b65502750a5bad7); + tempvar res = res * point + (0x446d7e2595a1940ab7f6dec4c9f78953de9c0f4c67a130b55f1894779e73ac3); + tempvar res = res * point + (0x5b0a8465067d8f43cac5dbc1145110e1e79e0f32ba1d59d2514405a0a806860); + tempvar res = res * point + (0x5bdc50def36283e003e9ccf2f1bed188326bec8bed554815f9e49062ed6da4a); + tempvar res = res * point + (0x3b591c6de6700576abbe4b4544de71cd3266a5dbb70740762d0c16a863bead8); + tempvar res = res * point + (0x7fe75f49544ac3cf237a17e58179851f5b3e7420330e5861ec505291d9a0380); + tempvar res = res * point + (0xe09e3870dab755cabbeac23076891b510207da569b75bf32d3f63c8ce08460); + tempvar res = res * point + (0x66bb11e034bb55410211b7cd410cf076db77f008bd93f0dc938f089e853f0ee); + tempvar res = res * point + (0x630cb6b8bcbe79e58025a699d489116a875f287fef6f1677b497b8702c3777d); + tempvar res = res * point + (0x46ebc0bdf94c2f85023a0c1b29d229ef7a23e173d310b814f72c73904f6a5f9); + tempvar res = res * point + (0x3fdf21da099da6c005b076001c5a95f2fe26aeff47e2cb9e8e52166a22b643e); + tempvar res = res * point + (0x6c647f1e5e8e93fda4bc0ae5d513cb60558e2b44bf885484161bbfb5e093969); + tempvar res = res * point + (0x688dbf5c443560c219afd8c54a0b26bdc9284925f2cc0adc889c1de024d6ecd); + tempvar res = res * point + (0x3c782f4a1a6d94adf1448fd7feef975f47af9c79bbf7e2d74940673704b828a); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_ecdsa_x(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x22aac295d2c9dd7e94269a4a72b2fb3c3af04a0cb42ed1f66cfd446fc505ee2); + tempvar res = res * point + (0x2bc4092c868bab2802fe0ba3cffdb1eed98b88a2a35d8c9b94a75f695bd3323); + tempvar res = res * point + (0xf685b119593168b5dc2b7887e7f1720165a1bd180b86185590ba3393987935); + tempvar res = res * point + (0x5febf85978de1a675512012a9a5d5c89590284d93ae486a94b7bd8df0032421); + tempvar res = res * point + (0x4e1b2bc38487c21db3fcea13aaf850884b9aafee1e3a9e045f204f24f4ed900); + tempvar res = res * point + (0x324182d53af0aa949e3b5ef1cda6d56bed021853be8bcef83bf87df8b308b5a); + tempvar res = res * point + (0x5d4c38bd21ee4c36da189b6114280570d274811852ed6788ba0570f2414a914); + tempvar res = res * point + (0x529414d56e9f6bf4ce8be38c8f79ffab78b185da61d606c411098f981f139a); + tempvar res = res * point + (0x66d15398bbd83688bda1d5372e048536a27d011f0f54a6311971822f55f9c07); + tempvar res = res * point + (0x52e5e75be2c96802a958af156a9e171dc7d5cfa7f586d90ed45027e57c5fe92); + tempvar res = res * point + (0xb0e39f10e5433b2341ecef312e79ed95d5c8fe5a2e571490dd789dad41a2b9); + tempvar res = res * point + (0x703dcca99c0a4f2b2b7f1b653dbbf907dd1958c248de5dcb35be82031f7d170); + tempvar res = res * point + (0x749e86688f11d3d0ef67e4f55535c715a475ceec08547c81d11de8884436d8d); + tempvar res = res * point + (0x44a14e5af0c3454a97df201eb3e4c91b5925d06da6741c055504c10ea8a534d); + tempvar res = res * point + (0x6cd537aebc479350e63acbcf7b9da84f4b06c6c26a571d3a7dd416a94a956ca); + tempvar res = res * point + (0x5e2909b1136e1d6608663e5cbabb616b28d2fd6f5dfb7cd03c4a7e719b7c53f); + tempvar res = res * point + (0x51170abac6896de6a5b478741dd56f52b1d2a1feea59b1f26d060e09ed98b32); + tempvar res = res * point + (0x1d0f94ce5d9d3beaa42ebed05a2f172aa2227e9a9fee0bf43a3fb068c1ac345); + tempvar res = res * point + (0x785dc572a88712cb4eddcc8a167bb1b62f9a79282f21ee92a0374af76169344); + tempvar res = res * point + (0x39d9d83e0ac884a5ee0f2d227f9eda71724a55002a41938458e45251e121308); + tempvar res = res * point + (0x7fdc637318ea00385719f9ce50848d13cc955eef9f36a90b87e646dac85e3aa); + tempvar res = res * point + (0x72d82458ba49cd6c638f89d2e3a68e49944f486cdfb7d2848e51aa9f99292a4); + tempvar res = res * point + (0x4c484b2cc04747d8d812180ec716f779302231983fa17971b575274c0a9c378); + tempvar res = res * point + (0x62773dee1773834dbb324c4c0d48dcdf9bbf0511547feb1b2ab0f7af7fa2dc2); + tempvar res = res * point + (0x5b0343972ee9e17afaf76adc54e6797d54e6e47a7ea1167654ce076e3c6c360); + tempvar res = res * point + (0x3ca8d84242dd2bd2a5d6e644fa1dc9f5082ee6131b6f0db8fd7d4f87109098b); + tempvar res = res * point + (0x6f4ab1f3bccea47669a4c93da36db05bd6f5197945b5ab29191a703312ed3a8); + tempvar res = res * point + (0x2d626ebcfae2d3618e350c190fc636495fbb04dd4a4e563680fb961a3d30d8); + tempvar res = res * point + (0x42f0a74ce045e8194b7a5cac4e882b1f1a9face49c38fb3383cfd3d960806c); + tempvar res = res * point + (0x34b7ebee71c5876183407c57610a0a8a33d3138ccd6ae416651cd505e5761d9); + tempvar res = res * point + (0x150c633a21f3cfa157978e9561161f3953e180b9588347a0c819e4173afcfa8); + tempvar res = res * point + (0x4f8cecab5f743c7227a63fa7f320930ffa7cc52b0fff6c351d3e9d4c22f9f9a); + tempvar res = res * point + (0x98ad9c2080ba0663fb302025e6224cff41d1d30c5c9101ad77a48a71d8ac); + tempvar res = res * point + (0x58a6d8229d82c192f190e55d28489f621cbcc64e4ef10c1ec5663c5384e60f); + tempvar res = res * point + (0x7850ac1ef437d1b99c026a910b2437c1b877242e605c8f31a456f10e2f78743); + tempvar res = res * point + (0x337092590652e19c23b48de3629ae0bd4157a5a72ecd3fcd17bb93f05814716); + tempvar res = res * point + (0x95fd265a2a87c42af5a20a199e6730ee3f0e3352a38a5e7e84ef46c621903d); + tempvar res = res * point + (0x38ada3df52cd03154d66b7da4a8a01835a461e61a76ac9576649d8c00013610); + tempvar res = res * point + (0xc1bbae3cf2d414dc12119a0c746e3c10e148f8b522d574eff757d44d8b3a14); + tempvar res = res * point + (0x7122e4b28d4ee35902b7f7b8ad5f525b6c70a2f2bb6b4ee4b9f0008845ffacf); + tempvar res = res * point + (0x75275c33b919425b271966642fabd9ea7c917e70e96eda669040935b1d49db6); + tempvar res = res * point + (0x70af32c484244d3435bb65b0ed076f48d06abb45b7765de9c6f26c1c8e9156d); + tempvar res = res * point + (0x47c78a993a13204796a2fca3b20c0f02c0601e7cc59f84570fa026c65796dc9); + tempvar res = res * point + (0x55713c4cc9f91e9f158f70683238853d0bb7cbd8358ff72b01fb60808b5c1de); + tempvar res = res * point + (0x412fcd2551c0516392f685a62b54fb82b9a73bcffd42abecea4482b65aeea47); + tempvar res = res * point + (0x6925415cd4dbae0ea5e9f41edcb503ff6f668da1cb13ec73eab6a99cd96752a); + tempvar res = res * point + (0x3a2a902a0e43ab33c19459984fe116fb215796cb40c48e254de6126b55e9c3); + tempvar res = res * point + (0x552e18bfefab6c3362cec587f0a7433a914f1359e5767b4fe883f1ad902dd13); + tempvar res = res * point + (0x5643c5a69044bb8e86d10d3248ea3f50f8598732b0c517b256fe108294e09f3); + tempvar res = res * point + (0x542f931640d9010e906b7e1e375cd0481740157eb51500ea1e10afe77f26265); + tempvar res = res * point + (0x2a2811098d68a747bebe9ca2eae06b604bb307e5f51a9bdac1636f380feabb5); + tempvar res = res * point + (0x57d53073d66a528c88f24e40011321f74ce5bdbecd6ca319e5e770ae29b21da); + tempvar res = res * point + (0x1a4393bce3924d765902469c715fedeea69adca566859b4c8c412b7d7cb566d); + tempvar res = res * point + (0x6dfc1fb08b981f73911dc43811caa0ed99749c2f0903f87f389c9a0e2a88126); + tempvar res = res * point + (0x224fe4f546c8f999947a5864ed0dbcd64fcac6f774ebce11667c2bbb7d8603); + tempvar res = res * point + (0x1f7d548c5a6f2bc70ff6f8ee47f38221ae25dcb4f9b068054ee66227494f87); + tempvar res = res * point + (0x735f4476c2b51acb4f0dd9dbc4306108e37543538b2cd3cd2327ae5377a2e5d); + tempvar res = res * point + (0x66ec70c796374a71b6aec5520467ebed547f645d1670b990dfa680a1b415cd); + tempvar res = res * point + (0x14ac38a4b82b4c65e4993726b58f32c74988997b8e8f7729fe9032cf187896d); + tempvar res = res * point + (0x27092905558602aec9af09947b70bb974caa3dd7cb1cb991810e15d75194aa6); + tempvar res = res * point + (0x44e3645cc1b135410b2a52a5b92bcb454985033615453a51ac46377885c4309); + tempvar res = res * point + (0x352b933e5d853527d2a4317db613d07117fad8115948957515bc07d72e161f5); + tempvar res = res * point + (0x268c1e10f6f9969291b1d2f54289371a2f40a14cc67b3736e04eb891c1824ed); + tempvar res = res * point + (0xaa81707e389769aeb31cc8b45276af0370dd702ac79461bae0a4078cefb5df); + tempvar res = res * point + (0x67dec5ad6ddb1761ec61d2820533f7a2bb56d66f2fb8ecff9cbe28218990061); + tempvar res = res * point + (0x106911de08ef437acabf58d178db7c81ff4d7de25f3ef5cd2582f44176d449e); + tempvar res = res * point + (0x356591a80d5c2e14c3d8a180c030a9529a8580a4f3be00a5a9eea83d0d585f0); + tempvar res = res * point + (0x40a3ea8c4059a1b9138884234381d6d383e66dd48eac1bf05f5fcddd593c881); + tempvar res = res * point + (0x699e679a8f38a1ecb14c6695a2848c6abbab8a05003e43aa5cf4a9c6e6058f2); + tempvar res = res * point + (0x6b86f825e41b2c9934f71cc2cb08787d1bd4f2eefd2be9c44e37bf387b35940); + tempvar res = res * point + (0x4eb2786b11bc602bbf773564eb9b057d7dc02daaf4359c015295d97b74e72bb); + tempvar res = res * point + (0x7b0ed28b968689517aaa216c0203e57f1cf56b22ff1213561499ae140d37fa2); + tempvar res = res * point + (0x367ea925556a875faedf4d61bd2a95a31067bde6e682c50035bb3310cc54b03); + tempvar res = res * point + (0x781cf0ea1c0ba9cf908656aa2c5a9403d54c26c8ece401a2c13be8d3090f9c1); + tempvar res = res * point + (0x20ffc2b4c6c318bee0cdfdca40b2c10f2c629d3b52472b17c1bfd909cb7b85a); + tempvar res = res * point + (0xe5e89fde76daa211fadf1178785f0c25a94d47a468cda257a895b871a928c2); + tempvar res = res * point + (0x164344bae5b9dca8f384612e7351fecde28adee3d245c98dc2f65509b181d8e); + tempvar res = res * point + (0x4063a6202df9488fe5384aaf7be7610b3e88a9c01486c1b88767ca36355340); + tempvar res = res * point + (0x546f65cf3367a004f10e9a4e47d71f6ec80086cb2be19d7b225825e01eb323); + tempvar res = res * point + (0x72c11bd84cd54152607e4c6e558a28e480a6487e374b865682c167484f8c29b); + tempvar res = res * point + (0x7a5d11f284ee7db72bed2338784d6467e05cae85f333e05c5610c018a57c2a7); + tempvar res = res * point + (0x64c71feb673d2655bb1865f9c4bdfb16b1bcd0f278a911363056674dacb812f); + tempvar res = res * point + (0x62334e7d6094be4431aeebefc420f7e656459d6fc2cb10455123ede054f4cdf); + tempvar res = res * point + (0x5dd4b3dd252fa7eda7b46674369a2f8c5b00a891cf01ada0ea5aada8bfbf6d4); + tempvar res = res * point + (0x3373dcd7d0f0f8bb31ec396e1ec67e1f121121356dba549bce9fd4d3bbfbaad); + tempvar res = res * point + (0x42a6c571001e263b1ec8168805bf4d6cb65935cd0687c696ae3a6968fd28378); + tempvar res = res * point + (0x16f35b8d34d425a85fe48e66632d3e4af27d5d65cb180cb99047fdc2b908ea6); + tempvar res = res * point + (0x24327b5849aaae0d313870c10e8010a115b70a99cf6b92925f51d2f05686287); + tempvar res = res * point + (0x45ba7e524d75c65ab27b57a6e0b90458c9b0eb651935f84898a5d3cd0db9b8e); + tempvar res = res * point + (0x767d8839373a2e97b7e3de1be6f4c18df648806920e92fcc4da9ab6bd8525ce); + tempvar res = res * point + (0x741b0f4e1bf8ed4d6318f5dc5ebba8529089f5ef4a84cd727564c60cc11a96f); + tempvar res = res * point + (0x68682814e1b4dd639cf396a9f60efe5ca035c6ccd75054b8911e8a15230efa7); + tempvar res = res * point + (0x68edfc809bfa6534b583624db421a2cb885d2ce888e6f95eae85ad9cb38249d); + tempvar res = res * point + (0x5d6575134d1b37e610f25e65bc8b0b1ad7fd0cdcaa56fe573142a09707640b5); + tempvar res = res * point + (0x327bd35b3ec38fb121c039f777669426d3d60df3922e688a408a06d4e7ee3a1); + tempvar res = res * point + (0x29a66c93ef1fa5ac4b6f96ed329810085b294a7ab8e16c61b1e225fd7406236); + tempvar res = res * point + (0xac01d3129d24fe9b9209df8bfeb2526bc27e9c27d78f69eac16ce151b13540); + tempvar res = res * point + (0x3a967c407600baaac716275b8fa16a08c22e928d895c762b2843d00496b3390); + tempvar res = res * point + (0x4d111629c799fb16f602183ae372aee382e0b401312951eefe77a1674575242); + tempvar res = res * point + (0xa8a00bb9874fbb44ee3411814dfb9d4d6048f5e3af6f7f09fff4e9f0263901); + tempvar res = res * point + (0x3abd943152451107f59aa81194e7bbbe37c4a86a6b41e20a02f8145dd32fa87); + tempvar res = res * point + (0x580bd7107af3afc93d0cfd1f0bd39f78f06ebe3a900f5d79943c25e980e5653); + tempvar res = res * point + (0x7a615360e826e937db0c91cc1c9196086a3fd608cb01d20186ba1ce856904ed); + tempvar res = res * point + (0x21df6648e6f783b7361a20191b8d399a4373dcbcc83f6b4a9a40bf11956219c); + tempvar res = res * point + (0x2c82b2a99d198138ca2c4229a1929d044b113c1b0f693659712318ca7e7f804); + tempvar res = res * point + (0x6dd74321080cc46d816a963c8a6f5dac42cb11e66c79831efba77433cce0d23); + tempvar res = res * point + (0x1e54c3a5a3beca7932090ff58784aa43261075950feaab0e2a840f3801b81b9); + tempvar res = res * point + (0x3360af40b57c0a951da3219025643a76516f85119dfbb05f61874eb3b56b130); + tempvar res = res * point + (0x164d44fb88efb41e301934bf2c61a20e41c9bcb3f8e784ac5857063b4fc3d5a); + tempvar res = res * point + (0x46efbcd0bd7f06d59a430ddeb9f239d66a24ce1fa72f5dbcc2bab48b707b2dd); + tempvar res = res * point + (0x5ae517bdefe7b6785680842685de0b5cd972a22dae9ceb50a6ea3665feb06f0); + tempvar res = res * point + (0x51f4698c121db3db4a5244334c5180cfba256dc80a59689e2c0f1f8d946e6c); + tempvar res = res * point + (0x67d2681fae96c0b4bf22d10a73a1882c5bf4a5440f8d0458394d514ff7bd18b); + tempvar res = res * point + (0x3dab30754623b91aec7a165cc167e9003269ebab3e551781e4c8cfb73402de7); + tempvar res = res * point + (0x44be18892438118a0b3fc099da7489a89cffd4206678abfd37b1e649ad19178); + tempvar res = res * point + (0xdb0ad3bd8a33b8daf1d53ff8604bbe5259b6620e3b547d5c6f392dbc10ccd5); + tempvar res = res * point + (0x1a36f20817da4dc0c2e8b62fa08ce15cd3cb50419acf5211d6948bd6b28c8ce); + tempvar res = res * point + (0x5fa6f7f2a7a527880a5b58911dd7f3a491fc702f481cee30e67c4980092f851); + tempvar res = res * point + (0x6f682eebabbcbfa3e7084b47b2a01acb693865749df222b4b8dee0ec41903cb); + tempvar res = res * point + (0x1fd7088411b30cb5762147b1d6749942485b36c68ea32f60ab83fdcbe987d83); + tempvar res = res * point + (0x7172b43d0c88348e5453b0b26d54d4a7ad7e99e6b0c4b787341c8d89936197e); + tempvar res = res * point + (0x34369f479f013d44dd5bb0d79d8a9effdb2ca36ce8b3d7e759bf707233c5bbe); + tempvar res = res * point + (0x3054d35b59baf5b0a2078c23322de031b383033837cd6b978b6c060120b7fb3); + tempvar res = res * point + (0x23f0124cd1c3f3605fa1ec36dc4d6cb6e229f8ba8998b138a44595f96f3bf21); + tempvar res = res * point + (0x2300892e3f3c180333d091901ba99ab9e23c7947309b9e88ad47025847ec3a0); + tempvar res = res * point + (0x4182bea2ea16dcacb0194876cd5fe8c79e1a55836aff8aa6074d235af5f7b29); + tempvar res = res * point + (0x50f3e383aaf3533fc91b9633386542798abd69b79af893f47f6603d3cc35ea4); + tempvar res = res * point + (0xc37f91c81a7006d6681cb511dab2e4d83928ccb78d1dc72c4c556e4cd72db8); + tempvar res = res * point + (0x2693f31fd4bb5a1ef9cacdc4f2b33c3d6d965b76e7bf289020ab1b6c6660d70); + tempvar res = res * point + (0x2bebc90c59dc0e37e28c7c7d8254520ce08894637bf1a089aed26012690d119); + tempvar res = res * point + (0x17626d3869adf0fdd3fedd48e9fe1266bb33419bfe9046df43c6409b440980e); + tempvar res = res * point + (0x734438bc30566591da45df9366f936415d29eaeaeab392488bcccb9acf0edcf); + tempvar res = res * point + (0x22a7b1c897f54da39a1db61b345b234969e36ef6ba0ea02f8d8b3e83b5c6242); + tempvar res = res * point + (0x22eef827b9d0b57649233c5d527b4641decab31df78347a20da21c705df093b); + tempvar res = res * point + (0x193185be6e02dc0a07c0dced4ed031bf0a406219cce325e76408123406c318b); + tempvar res = res * point + (0xb10494024548b14df121b738abc7babe56c12acc0490699443426a52f3a4f9); + tempvar res = res * point + (0x375ce3766894524209e2043a150f10ad0bf4f726e3dc5453c3c757e56943a51); + tempvar res = res * point + (0x1b1c82e5c561dc42f8c9c2a9f7db6bacd729b2646892a8ecfae9ead9a338aa6); + tempvar res = res * point + (0x4b540d0085be455b24f014bf51dc7d0eceb8c93bb644a5208fa02dc58c718ae); + tempvar res = res * point + (0x17f2709d2719458a9bf72a2b04463f0a6529fd9368a47715c628ba4e006cea); + tempvar res = res * point + (0x20e468bb2828fb774d5ab538ff7f93ada201c2e392936e05cec29cd5a7a462d); + tempvar res = res * point + (0x29cc816e6be353f6ad5e2c390f37ed3940b0dd67610a7eeb0bcded94bdcf920); + tempvar res = res * point + (0x4d3b0654fd74862a92aa716af33b5ad5ac20dc0460c724d95ca94fe6d8a9d7e); + tempvar res = res * point + (0x7ba5194da963f8224987db2720f16baa604ff62351e66a63c0c9dba00fbc7c4); + tempvar res = res * point + (0x31d335bd885c9cdf2adc68ab45b8eecd2d3588cf85b93206896b2626eb1e369); + tempvar res = res * point + (0x4efcba706a8b7868e32f363efac2696ad0625d046a3ef97917c710515016386); + tempvar res = res * point + (0x56017977a273ad0e91c7c26a702ae4508343e97968295b08447b3cc7f20522f); + tempvar res = res * point + (0x16416cc193a5ced6ff213fc18c86bd6f08d17c576f26b9ebd00d2653bbd6444); + tempvar res = res * point + (0x4237c41364975eb79919303fc0a381b934befe871fdbd72c18f97627292923e); + tempvar res = res * point + (0x1b389d976c22a3bfb42424896c9b135a3794048724c729968f81e04ce414194); + tempvar res = res * point + (0x62fc206aa283139f7451e54cdac873fe86b6e7e89214a3c0318fbcaf6016fa4); + tempvar res = res * point + (0x88f6e5a835dfda9fa2e2ff248d9378352f4a89b6bf5935700da390baebadb7); + tempvar res = res * point + (0x4f9e975176d3aacd79c322d013c854c4b8829d1e469c9b242461f35e8dc6fed); + tempvar res = res * point + (0x6e1143b147dd1bcc56dd43e6a3616c9a4016d6887cf0009ebf9f9796efc944a); + tempvar res = res * point + (0x284c547c04ca83fdb01020cfc797eb362838317f09e5d25e1e4eef353ab7a7f); + tempvar res = res * point + (0x60c327ef73c8468805ecace45a33ccc375fc91ffbf01b4b10a01ffd4b7aaefe); + tempvar res = res * point + (0x59cd87f8751437900e984a009c63fdf7461b177067760f30d4f648ab271660a); + tempvar res = res * point + (0xdaf5a68420fa7ad811f6dc75c5b4e92173a5d89255dc75accb8cec80a9cd91); + tempvar res = res * point + (0x1f573af6e3ad146eeaa582f540de6a8db237ff2f28423660de998a4275bf4d0); + tempvar res = res * point + (0x2830a6edb344b7fa86506557a0b2b0bd900429218fb35e7990951fe4fe869c6); + tempvar res = res * point + (0x58f2e18613b3b25529935a623e7d5c8318ca9ff3fb180f16f7454ca9e348e35); + tempvar res = res * point + (0x42c8f0b5507417eb48ffeb1a7df8808633f193c27df8e2f44ee7bd62cb2c3bf); + tempvar res = res * point + (0x50d603bf9c2a456b828ae476092affde072ecd878877ec3f99ba8f574d263a2); + tempvar res = res * point + (0x413fda31150aa8462deae8a6043fc5624599fb7f638c4d5c5f89472e1223c28); + tempvar res = res * point + (0x13fe84c8ecc2e3fd289560c0ada7a251fdd5fba24c076be4be465feec4262e6); + tempvar res = res * point + (0x2b2a0768e9a5f59e7f33ea449690794c8b409bacd1c808f7ee8065ed9d8648c); + tempvar res = res * point + (0x3030332e9cf430f72159914e59ab9af532bdfdafedc1be39691256c8084954e); + tempvar res = res * point + (0x16617a52bfe5d2fd0eedb0d6411f5fafeb14a4ac17da0cc828c914acb500ce9); + tempvar res = res * point + (0x553f8ab49053432bab53835480b6f4c416eeffb3470fb6bcf122741cac3d71d); + tempvar res = res * point + (0x3939ef0e572dcc3b67f0cb819fffc521df26e50814281621fa6982b1465f786); + tempvar res = res * point + (0x520b18e79de342aa7095ffe56be6222b0d2e44fc3c676a5c994f24e427b45e2); + tempvar res = res * point + (0x3f3ae3871460ac578f5030d925e91c138f3290f8f3cb6d4b560b4b16fbacd64); + tempvar res = res * point + (0xbffb0e4f7ccfff0cee519edd1004eefbc47024f92c4409bbdf688c133ad285); + tempvar res = res * point + (0x62d6874b6dcb1c4dc8ed797b9158da4359c6c49f27af4851a12908ecad2092e); + tempvar res = res * point + (0x511c0ad7c0bfdcfcfaf925895a8ef5e8c5e0d147e29c9cdae45fbc998fce346); + tempvar res = res * point + (0x25199c11f7193e07191cd9b9108aa8b440ce1972dd1cbe5f0cc33b7783203a8); + tempvar res = res * point + (0x3cf3b95ba351a72019ed1bcadab32116adcf079e72800a9d88f15244e7743e0); + tempvar res = res * point + (0x19cf240d04f4859941f9b6af4a7088729aa10307cd08aa75f01cb22e872543d); + tempvar res = res * point + (0x1cd528d070930aef19e0f928fc744e79ff57e227b6aa1bbfce15a79166aefd8); + tempvar res = res * point + (0x475f8af086f7aa4ec3739f754f7dd291dc50decc7c7fb03de8aee3cf06824f); + tempvar res = res * point + (0x28f86fe2d71f9410e14c17195ae19c2c5e623c525c979f4f74dec3ef8848eb5); + tempvar res = res * point + (0x508243aa19e23cdb8ca0154055c05130462908c6a2691ae522e37ab9d6168f2); + tempvar res = res * point + (0x37cf9640e321e7bccf1926d5fea92918d6888c5805e27193722995233a4adc5); + tempvar res = res * point + (0x66336e2e2eeb939818f861fa4aa9b2576936470f511786f8fa3417850a6c2d); + tempvar res = res * point + (0x19a0ff21908842e412addb744b0ca384a54bdde819f6337c4c672f682fea9cb); + tempvar res = res * point + (0x44147236daf669f8a94b7ea353c3dd7e64312ece01ccc1d4dad67916591d50b); + tempvar res = res * point + (0x1d6cb5a655919a581078aa2f8a21d300425026ccd7d047302443d78dbc67abd); + tempvar res = res * point + (0x4d8d9b92b38a45147bc9c87c071672edd93cbf5bdc8d85e608f26f1d82d172b); + tempvar res = res * point + (0x4acd125e74056ca611a1b07369166eb5c02af7a4cbf387b2bd584a362fa9e60); + tempvar res = res * point + (0x3b4fdc8d965de1761e445ee88cb406f707f9d0b1ea3c069d12084c0ccba9b44); + tempvar res = res * point + (0x1f27c20f47daaf01d4627d5e9bee0e9bd2aa5b75807064cd60ed87e307f677a); + tempvar res = res * point + (0x4758304a75f149e24563c2b22459151389b86d36108f5dfe11ea1fc7a64fd7); + tempvar res = res * point + (0x1c1216fe648d287c2645dfc5152e171f25483df5ef112b745c2e59b5d9ee07c); + tempvar res = res * point + (0x24adf288d61c113e28d9a298d2642eb67586019adcb952abf274ebe1d30e24a); + tempvar res = res * point + (0x3e09706cb43c83143c9dc46f97e0e1ab4327de19ced69badaa8b2c80f68fb9b); + tempvar res = res * point + (0x589a2e11637d0c90fe91bb9f4d55a80cd1a2df7f3431e8b8bdce8fe7d35126c); + tempvar res = res * point + (0x5f506aaae7ce6d94712c9e0ab02bd2a4ae09600608d54a8ca381b8e96222cf7); + tempvar res = res * point + (0x3f64b3a307276c6a7169c54297bb12aaeebadec98df6ba1184492a82effe353); + tempvar res = res * point + (0xc3e0400cbde1da659381240d9c84b977eef3cd70e3e4a1a8763a05e682eb3b); + tempvar res = res * point + (0x1fdb038204ac50e87e3e7239d8c1c0572893ba98e031c982e545e6de64cb8e0); + tempvar res = res * point + (0xe0b21e37008355c35f7aee295a8b2b72465866b2bd68e72d36f032c34b38a0); + tempvar res = res * point + (0x2cc90219912af16cf9a39f57f8b8c514f797dd5d49dfed5eabdc278e31106a2); + tempvar res = res * point + (0xab2147a23a826d5f7c6fea5bf889eaafb5531721f31ee0a9f02fd58f09f65c); + tempvar res = res * point + (0xa5d4606609371577b0d17fadcd85ce659885b00245a67b038f902176d99a7c); + tempvar res = res * point + (0xfc76b77f717a5b3ecafafadf29e7f886c8ae67a3a2bb30467c440472349953); + tempvar res = res * point + (0x40fb948f8a4a10d2b2e928a5d77b481f8d3068b47fa388a3ee65609aade1a41); + tempvar res = res * point + (0x13d322a0ecbe1e785921a7aa6f4d1135e0798e72f4c055226205314b8348144); + tempvar res = res * point + (0x20096a7aa30c6c42f1d5f1ed88de275d1d1610f2548711a75fbbd72d373a50e); + tempvar res = res * point + (0x18f9cfeaf2c33e21d7c6fd9e15a3601a2fb3905588868167566e8c1f1dd30fa); + tempvar res = res * point + (0x3e3aa48bb5db9e2b0dc6d294009ecd5d4ff6255dfcdde3f5b4e545032ea9b68); + tempvar res = res * point + (0x425b03b0356b92e66ca816869a76110d68862a0d8ad76f950fdb1d5c03279d1); + tempvar res = res * point + (0x7cdb723061223f33289237c7476e737ef0bbc5e2c1ed9a70566511fc2036ba5); + tempvar res = res * point + (0x18b8b8d0f393950c9a2e674052150a328d214618049c7e2f58cbad76adbfbd5); + tempvar res = res * point + (0xf19faf3accc43b56369dccdec35dc7b49c5b8f8976764886bd16dd2e155f92); + tempvar res = res * point + (0xe08853aabc9eb934b4470bb4ae1dbbe90c61d2093516df998ca7adc98afe10); + tempvar res = res * point + (0x7736291268c775a82caea06004d53edb829be2566fc7c4053b1d850a8116cac); + tempvar res = res * point + (0x1bc1186238f0d39e1c56185a8d2bf00c90c9c89647917d60a5b762932856524); + tempvar res = res * point + (0x6cf772fa8050ad8eb87bc8f0c8fc511622b416fdb084cbc93b79501c96b0bda); + tempvar res = res * point + (0x7417da24519b4c55ec0d698ecaceeb49711aa1e7f7d907102351e73388a0fa5); + tempvar res = res * point + (0x66e1e25d1bcea87acd136f2c33498e3223fbf78bc6cc816ad6aaf68e961da0d); + tempvar res = res * point + (0x60db5bf6f060d82c169a1c4ed6c548d5e8cdb6cfd2e3257c155bf11f48ca609); + tempvar res = res * point + (0x2d5447623584d3a19e9993814622d6369248bc61813f067c4825c9b0a81551f); + tempvar res = res * point + (0xac068a1aae938e26e125b35c88a87130044bf3637bf1acd797103e7388b33a); + tempvar res = res * point + (0x3ab2d353537697d4de9c5c4c0bc31e5e776cb93181029144f6c6d4b5ea4317b); + tempvar res = res * point + (0x6ca2dd473297a2852e68ea2b83faf8f71e5cb471adcc74a858132c6a823f0c0); + tempvar res = res * point + (0x1ec5264a5287f1c6de79b3df3adbfa157e8430e594078c3fba7002a077db447); + tempvar res = res * point + (0x50ee695deb5a4e63c5dd6de35621d1c0c5a496bf41fecbaa929b2b3e23f174a); + tempvar res = res * point + (0x36f446f7e5a51114cbdd3b460431bacb5a42cd61f4690cf5e9d9f13e488318d); + tempvar res = res * point + (0x195f98a85cfe403a7d229a6eb4533a1fea641c331db75a5807711fdf1e27dac); + tempvar res = res * point + (0x63d4964faab567e795024a17032ec564ff221a421bd2e42632d3770c73dbba1); + tempvar res = res * point + (0x68d729620eca6b4d904198a0e6d241953b9b8c874a10b5ede5596146d560979); + tempvar res = res * point + (0x1137975bab819ce0cbc73714305030fcd4a185f71d46c169908460390d56d18); + tempvar res = res * point + (0xf639bcd7777c1ffd41a693ac9f5a051bd124b7edce3d568f14304c9fd90a67); + tempvar res = res * point + (0x2322f8d96071356feee538e0c53d857b1924134b94377af20ed5d0e8b3925b); + tempvar res = res * point + (0x22cf65c6bbbf76765555748cc1ae91c83ea93ca2c8b34a59332567b5b3b0cd2); + tempvar res = res * point + (0xd62eb553de83e5d51f78ddd9480d65870dc426f61153e732eb6cd62cee09cd); + tempvar res = res * point + (0x6afb39d46d5a846e9d58a6ae27e6cdd83bee29c72754cd4cd3d3cae423f5c9d); + tempvar res = res * point + (0x364889e46da58b66c827835a0c2807338eeb4431f2099f490d13bbad0777a01); + tempvar res = res * point + (0xaea6f7f915e4aec612029a9d02316baa3f6297ea4cfd38897f4c9859ec485e); + tempvar res = res * point + (0x5c180e2fbb2b51e053941d0e1611424fe60ced6d439115dd98530c8d79cca4a); + tempvar res = res * point + (0x1ab93f16e576b6a54598582eff5e2cfc33baeeb607826579680636b05046d16); + tempvar res = res * point + (0x4de47e973af27fde9ad29f812de8a04855110118eb73fcdb46865390486a287); + tempvar res = res * point + (0x50be25e516e30f96d8b420a7c494506d2cd21d64f4d5ecb67d58c2ae99bf5e0); + tempvar res = res * point + (0x2aa45ec320ea12beb804e35af3684dc981324dc9bd044592d1c408c052a4322); + tempvar res = res * point + (0x26701dfe3cc76754a4ab893fef59886a43013ea6ba648efd82fd03941fa2910); + tempvar res = res * point + (0x1773ba95dbeaab6e5e9fc79ac153d46be1e57828e92287d698a3f4f87ef4984); + tempvar res = res * point + (0x4e92d5f575fcaac9adedb4e0c3549dc18f61bc40e3752e3506f3761c32c6e3); + tempvar res = res * point + (0x580f9d95c2bd746c9210a87b0f9ed275afee1dde7a41d9ad5e69861ec0e43f6); + tempvar res = res * point + (0x3e2dbef5f162784e13b5ff4c33bcbc444ad1546922b293d6783b5de5c5aba78); + tempvar res = res * point + (0x596f89b6ca79194eb6a87c17692aa491f5b014da3cc7e5f05caf4fc1779c2dc); + tempvar res = res * point + (0x7e84842d5fff1666e01505f62661bcc822dd3fa530ebd1e4089230a4045a04f); + tempvar res = res * point + (0x5626d2ae9581d1d335bfc3863a4eaf3568ec8e70fcdae93f50a15b0cf601b6b); + tempvar res = res * point + (0x68371fc7cb3e0670a73eb3a7e773ddb63f231c26bf25bb1fc1fe6e93a7e3bd0); + tempvar res = res * point + (0x4d215dd42f87632a9cce2cb95081dc731e36796c3d2847dc96a3554231c6aef); + tempvar res = res * point + (0x421fac0e48da8e6355c07f6a64bcea96384848e8ea9a7113ab45f15b1dd15aa); + tempvar res = res * point + (0x679061e5f453c8bb1855dce8f7d61f2cb64b15d2c4e70b969ec4ead3fc6a226); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_ecdsa_y(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x23a2994e807cd40717d68f37e1d765f4354a81b12374c82f481f09f9faff31a); + tempvar res = res * point + (0x49d16d6e3720b63f7d1e74ed7fd8ea759132735c094c112c0e9dd8cc4653820); + tempvar res = res * point + (0x6c930134c99ac7200d41939eb29fb4f4e380b3f2a11437dd01d12fd9ebe8909); + tempvar res = res * point + (0x347dfb13aea22cacbef33972ad3017a5a9bab04c296295d5d372bad5e076a80); + tempvar res = res * point + (0x62e62fafc55013ee6450e33e81f6ba8524e37558ea7df7c06785f3784a3d9a8); + tempvar res = res * point + (0x23b940cd5c4f2e13c6df782f88cce6294315a1b406fda6137ed4a330bd80e37); + tempvar res = res * point + (0xf524ffcb160c3dfcc72d40b12754e2dc26433a37b8207934f489a203628137); + tempvar res = res * point + (0x603e3a8698c5c3a0b0b40a79ba0fdff25e5971f0ef0d3242ead1d1a413e443b); + tempvar res = res * point + (0xa401d8071183f0c7b4801d57de9ba6cda7bd67d7941b4507eab5a851a51b09); + tempvar res = res * point + (0x37d720cf4c846de254d76df8b6f92e93b839ee34bf528d059c3112d87080a38); + tempvar res = res * point + (0x5057b804cff6566354ca744df3686abec58eda846cafdc361a7757f58bd336e); + tempvar res = res * point + (0x76b4883fd523dff46e4e330a3dd140c3eded71524a67a56a75bd51d01d6b6ca); + tempvar res = res * point + (0x1058ff85f121d7902521abfa5f3f5c953fee83e0f58e069545f2fc0f4eda1ba); + tempvar res = res * point + (0x4eac8ffa98cdea2259f5c8ad87a797b29c9dccc28996aed0b545c075c17ebe1); + tempvar res = res * point + (0x6e7240c4a94fa3e10de72070fd2bf611af5429b7e83d53cfe1a758dee7d2a79); + tempvar res = res * point + (0x59fef071cf1eeff5303f28f4fe10b16471a2230766915d70b525d62871f6bc6); + tempvar res = res * point + (0x480d06bb4222e222e39ab600b8aadf591db4c70bae30fe756b61564eec6c7e); + tempvar res = res * point + (0x7d2292c8660492e8a1ce3db5c80b743d60cdaac7f438b6feab02f8e2aade260); + tempvar res = res * point + (0x5a593d928542a100c16f3dc5344734c9ef474609bd7099257675cef0392fab8); + tempvar res = res * point + (0x761717d47600662a250116e2403b5115f4071de6e26e8dc231840eeb4484ec3); + tempvar res = res * point + (0x4b74b468c4ef808ddcc6e582393940111941abece8a285da201171dc50525c7); + tempvar res = res * point + (0x14ef999212f88ca277747cc57dca607a1e7049232becedf47e98aca47c1d3fe); + tempvar res = res * point + (0x47b2a5ef58d331c30cfcd098ee011aaeae87781fd8ce2d7427c6b859229c523); + tempvar res = res * point + (0x59bd7fe1c9553495b493f875799d79fc86d0c26e794cce09c659c397c5c4778); + tempvar res = res * point + (0x3ede75d46d49ceb580d53f8f0553a2e370138eb76ac5e734b39a55b958c847d); + tempvar res = res * point + (0x6e0bed1b41ee1cf8667c2924ebd460772a0cd97d68eaea63c6fa77bf73f9a9e); + tempvar res = res * point + (0x739edb8cdd16692deaba7fb1bb03f55dd417891bacb39c7927969551f29cb37); + tempvar res = res * point + (0x247573f2f3fbd5386eac2d26851f9512cd57ad19773b8ca119d20852b9b6538); + tempvar res = res * point + (0x2f6efb89f27d2c0a86ec1e6f231b225caf2af9be01aca173a15fa02b11fdf24); + tempvar res = res * point + (0x75a0f99a4dec1988f19db3f8b29eeef87836eb0c3d8493913b7502cfedcef28); + tempvar res = res * point + (0x278a7c68986adbe634d44c882a1242147e276fee7962d4c69ca4c8747b3e497); + tempvar res = res * point + (0x675532b80f5aaa605219de7fe8650e24fee1c3b0d36cdf4fb605f6215afacee); + tempvar res = res * point + (0x5599e790bd325b322395d63d96cd0bd1494d4648e3d1991d54c23d24a714342); + tempvar res = res * point + (0x43545892bb5a364c0b9acd28e36371bede7fd05e59a9dcd875c44ff68275b2b); + tempvar res = res * point + (0x38db61aa2a2b03053f5c51b155bc757b0634ce89baace113391369682fc1f74); + tempvar res = res * point + (0x71b2b6b03e8cc0365ac26c4dbf71e8d426167d79f8bd1af44738890c563062a); + tempvar res = res * point + (0x3a663fc27ec3ad56da89d407089bcec0971cebcb3edf0c393112501919643d7); + tempvar res = res * point + (0x1030d58878296e14b1c5bcafe7e817ebe4aa1039aa96b9d0dd7fc915b23f42a); + tempvar res = res * point + (0xcb3335374cc2a2350fe53d2389f04952c4d634f489031742dfccca17be2e09); + tempvar res = res * point + (0x6ae3ee97ea5dcfbb7c36cffd89665baf114fae391c0367be688db09861a8ca1); + tempvar res = res * point + (0x7b16c33c4a8ffcecbd83f382469e1d00a340ceab5e7d9c0bd4fd010b83f4310); + tempvar res = res * point + (0x10f236430f20aafda49d1c3e3759c510fdf0c0c19f89df6d5d71deac88b547b); + tempvar res = res * point + (0x104b04e96151f5103118c4eb556cd79899148fd6656e73cb62f41b41d65e4d8); + tempvar res = res * point + (0x253bf2869135f4bda4029cae2819b2f468ae88530f3ea771090b2727814c494); + tempvar res = res * point + (0x65d50aa3c1d84a3deee14057eec98656a1296cdcbe32250bfdaa50ffac4c5dc); + tempvar res = res * point + (0x76323f8567119897f10d58e1552c98f5a62f03a16d3737e20fc2b0a31a3a843); + tempvar res = res * point + (0xdaee1c7b34ecb34717b7313dc4a299dd1a161447e2e0249426a6fc33a72289); + tempvar res = res * point + (0x2bfd1294f111a5a90842d19cffb97481aefbc09ab6c47d7dcf91ba228019c07); + tempvar res = res * point + (0x4f63db02e10fbe428a5dda8d9093feef46cc19568a3c8ad2fce7e7519004095); + tempvar res = res * point + (0x761a240cd8aa2f135daf0760bfc2c9d5e896e93a45426571cdad9118722e2b0); + tempvar res = res * point + (0x30a2e8ac9e6605fd722dffb4caca8c06dd4a8968a7bf41a5371cb1a07d11c00); + tempvar res = res * point + (0x5ba89e0eb3830039d0f8a9ca00acef15db22374c965b01abc49dee46270a7d); + tempvar res = res * point + (0x7e8659c39d7a102a198f0e7c3814060926ec0410330dd1a13dfadeab4e74593); + tempvar res = res * point + (0x5a00feeb391114d7b976654ab16ddf8360f05671b34d4a97da278c0aef34d76); + tempvar res = res * point + (0x33ff2d848bf237f536524da818598ae0f2516ebee526b77957448973eefacd3); + tempvar res = res * point + (0x4e0a5dd802deed7cb8d06527beb15dad32547bae77141c32473f4c8148912e3); + tempvar res = res * point + (0x776459dfedbbdfcef7a31e0f60c6480fc0676b280fdb6290859fe586d6e6106); + tempvar res = res * point + (0x59d0d8ca9ecda81081dfcae7580ab3c08a72195438c1556000c0c1dbdc08174); + tempvar res = res * point + (0x6eb66d366da57e4ae717307dfc3351579fe857c51aa82b95044473c9ed14377); + tempvar res = res * point + (0xa758a70ba6a0cbcbc65abfeca51359904f790752c3df55d42707253d8dea70); + tempvar res = res * point + (0x2046e1b4fd4c108e8f832f5bcc4dd46abf0d19ef0237beaec29d6c12fb9832e); + tempvar res = res * point + (0x472d99d1a6e1a6aef339eab1af3d53af7a8326e4d0a6bac73c3a159031c3686); + tempvar res = res * point + (0x1b0fa36439192f135c239918bf47ad14b55ced699f4582d929a60dd227b34ff); + tempvar res = res * point + (0x728dd423dbf134972cbc7c934407424743843dd438e0f229afbcca6ce34d07d); + tempvar res = res * point + (0x4e42531395d8b35bf28ccc6fab19ea1f63c635e5a3683ac9147306c1640e887); + tempvar res = res * point + (0x1ea9bd78c80641dbf20eddd35786028691180ddcf8df7c87552dee1525368ba); + tempvar res = res * point + (0x68a8c6f86a8c1ebaeb6aa72acef7fb5357b40700af043ce66d3dccee116510a); + tempvar res = res * point + (0x25c5f348c260177cd57b483694290574a936a4d585ea7cf55d114a8005b17d0); + tempvar res = res * point + (0x339b405bffb6dbb25bc0432e9c726b7f94e18cf1332ec7adfeb613345e935ab); + tempvar res = res * point + (0x23590dabe53e4ef12cba4a89b4741fcfaa232b7713d89df162031c8a627011e); + tempvar res = res * point + (0x534a4f3cf71c93023e473f12e407558b6c24b712204fd59ddc18c7bcddd571e); + tempvar res = res * point + (0x2e1b2a3c32aebc0be30addd8929c01714783aaf01be8a1d35e830646e8a54f0); + tempvar res = res * point + (0x605a244f646a825602891bf9ddffef80525010517b32625759b0bf5a7f2c386); + tempvar res = res * point + (0x4f81a946bb92416d212e4d54f2be5fa8043be6fa482b417d772bfa90be4e273); + tempvar res = res * point + (0x655038ca08eba87484bc562e7fd50ce0584363278f9d716e31c650ee6989a2b); + tempvar res = res * point + (0x44938959c2e944eb6e5c52fc4ee40b34df37905fa348fa109f6875c1aa18000); + tempvar res = res * point + (0x30b11c32e8aab0c5908651a8d445395de52d5ce6a1efe75f2ad5e2c8c854a30); + tempvar res = res * point + (0x4a92733a733f225226a3d7f69297e7ff378b62c8a369e1bbf0accfd7fb0977e); + tempvar res = res * point + (0x1345876a6ab567477c15bf37cc95b4ec39ac287887b4407593203d76f853334); + tempvar res = res * point + (0x580550e76557c8ff3368e6578a0e3bed0bac53b88fefdde88f00d7089bc175d); + tempvar res = res * point + (0x7d7faca17be1da74cf132dda889a05fce6e710af72897a941625ea07caa8b01); + tempvar res = res * point + (0x62be425458d26cfedf8ec23961cdfd9f4abeb21f1debbe87bd51469013358fe); + tempvar res = res * point + (0xd77a8e8eed7ce4931a6d2a4774c21864e2c9f468d080af9aba6756433a1a8d); + tempvar res = res * point + (0x3e850e31c0345726c1ace38537dd88a50c85d6819ae98add1bbd62b618f7a1c); + tempvar res = res * point + (0x375a5d9b11c83d06a04dc9f1908b8183adc6f04e5b2ceeaa23d3b68c973ee77); + tempvar res = res * point + (0x76640613af9ed1a125624e0c38252bee457ce87badb24fc4f961e55883d9077); + tempvar res = res * point + (0x5428ff423f2bbabcb5f54aafa03d99a320b4b255115351f50b229eae5522178); + tempvar res = res * point + (0x6dcfc3a99563a5ba4368ac4f11f43e830c5b620a7273330e841bedec0bfb5a); + tempvar res = res * point + (0x2652523cbbec2f84fae1a17397dac1965127650479e1d5ccfc6bfbfcbb67996); + tempvar res = res * point + (0xa737d6916aa6a869252d8ff294a55706e95e0844e6b047755704e37d978e09); + tempvar res = res * point + (0x2833391a62030808228d14437d6f91b31c0038c14988a23742b45e16f9b84b5); + tempvar res = res * point + (0x284f7815a7eabc1dcf56da511f7d739f1a199f8ffaf3474f645d2fc93327dc); + tempvar res = res * point + (0x1e141c5429a369996563573bf61d7f713cb7d25baadff636ba2756c65a910ee); + tempvar res = res * point + (0x60bdb98c079bd5cef216803b056afce03f6ea41934275c965d6e196240fb953); + tempvar res = res * point + (0x7f2abefac9e7f8109b0a2d25d0bd297059e45dd66798ac8b299f0a3e442dd2c); + tempvar res = res * point + (0x41776c662b44a36c7075097c14b6010cb321591a4eca2866d58252eaf9471ac); + tempvar res = res * point + (0x573b13b32161c11c9b16eff7cf93fa770a3ef667547a27503e39092aeabf73e); + tempvar res = res * point + (0x327319fcc0d34a0d64f5acab00244b43674a60bef754844fb2920c87c90cff0); + tempvar res = res * point + (0x755f0e4c374e2fa4aa7eda10041e2139a4a7793eea44f415c73ad4fcba1758); + tempvar res = res * point + (0x7b9cd3b277f00a75a17961d2d8e46e6a1838c8500c569cdcad08bd4e0cbae84); + tempvar res = res * point + (0x21f5ea8660d290f28b9300e02ed84e110d7338a74503b369ad144a11cf79f63); + tempvar res = res * point + (0x5e4b0ecc6a6c15ed16c1c04e96538880785ff9b5bff350f37e83b6fed446f14); + tempvar res = res * point + (0x3d8506e792fa9ac86ac9739d3d5bf63cfc13c456a99c8581adf590c8d9b72eb); + tempvar res = res * point + (0x1e3b6498f0daba2fd99c2ac65461c3fa519cb738b53cd6f002e97199fa4161c); + tempvar res = res * point + (0x70930735d913d54915fba20c97f07cba8f33eb8f4f81fd869699a10e83264cd); + tempvar res = res * point + (0x16a36769ee50227c564bebce3d9cd7c4ca55702a7c7ccf403075f68f05a0c2); + tempvar res = res * point + (0x3aa748723229eb8b33354e0901f50ad052b6c1006916790c979133c4442be90); + tempvar res = res * point + (0x5db8c52b6adb520496f9edd7105c92df67e8605ff4e0cc59992c3eb651ac7a4); + tempvar res = res * point + (0x4b2222d0aee638c7e5efd8ada791638ac155a01b78f3b532283574653998bb2); + tempvar res = res * point + (0x26a4b2a61f40c1ad77737b99cb27d2f3118622be64f0120907e2589d2f25ebf); + tempvar res = res * point + (0x5820792f23a13d58ddef0607950d422598bb1f21888dace88929fbe7d4828c4); + tempvar res = res * point + (0x3678de28b6896959edf5c9dc0caec59b02dfbbf54811f87939b32d0523f58bb); + tempvar res = res * point + (0x3cd13f84bb7ae6eeccc1012837d2f3e017f069e66cf047172bc70371f5aed38); + tempvar res = res * point + (0x7af8995e2ceed8841e34d44365c7ca14f5980a6a5c67b9813fa7bfd74a9c1b1); + tempvar res = res * point + (0x6d7af6524127a117184a0c12a6ff30d28b14933a4e96bb3b738d2a36db72e84); + tempvar res = res * point + (0x73200d12e733294b5cbb8ffe7fb3977088135d0b0e335135f9076d04a653c58); + tempvar res = res * point + (0x229d7fc2a1bcfbe00d5773f8dadd70a2641d8578fa73e66263b3512d3e40491); + tempvar res = res * point + (0x29889daac66c404d6491ec3a435d810a2877d885df1a3a193697b79b4af39c4); + tempvar res = res * point + (0x171f0638dedf0b69655fa9930bcbc91b257e299a6717bd8ea23ef550c8faff5); + tempvar res = res * point + (0xded0f75cd0a6a5401a954d26880eaf12050ce6458d3254c9dd6354bf66278); + tempvar res = res * point + (0x7fc7d854c9d0b3bfbf826c384b3521af0f29f975613e8ea6dc14f37d8beb54c); + tempvar res = res * point + (0x6d1c3edcf1de16a4e0ad7d8aa099a31fa2cfbf81f6d1a5798bd1ef93ff906af); + tempvar res = res * point + (0x3444c0f008988c8f600270b365ff926f016e49a54ab35bac4f3b3a42a5879b1); + tempvar res = res * point + (0x2a48058c77edcd75dd4323d9bb9eccb854009b1184fd716a8202f8627bb5447); + tempvar res = res * point + (0x56cbe248ebbc2f57ca8b943b219ba245791592f687815293a4499ef598fa9b7); + tempvar res = res * point + (0x658160ea7b654d786dc624b258c691f594e080610c2d41d6ebea0d8e3396849); + tempvar res = res * point + (0x6fcc261ded0ba97b4defc7c9bcd32b5dac89e4c08cb55cef98c6b50f5a3a289); + tempvar res = res * point + (0x7b74edd15d97b289da4040272cfc573f69a8c9a8b36d05e3e50b598508b7f9d); + tempvar res = res * point + (0x19637a12aa8b822c4a3f3551ef6c538043371a12a962de1dc25d67e0a5ee561); + tempvar res = res * point + (0x4c05a7abaaf08f21d93b2257d4f4a3ab2b44f4ac44ce0444418c864ca18470b); + tempvar res = res * point + (0x657060a10db73c4a9b6aa6288dd6164e0b50a4e6efbc2ee599a0cf4fda33b81); + tempvar res = res * point + (0x688c61ee887c1497ffcef82163f1a81bf7778f2c314ffbd325627bf0b25dc5a); + tempvar res = res * point + (0x54ab13ae1984dcc7d38c867a47f4a8cf786079ee07cc94ab5ec1962c21f638b); + tempvar res = res * point + (0xccee381472bb7dcae008316038c87a44fd9295f730e389eff14e86442c41b8); + tempvar res = res * point + (0x610bf9b7ea4557d72411ec90fb677f9a2ccb84c76f003954da4e7f439c9a84c); + tempvar res = res * point + (0x51d6322f7d582892421e977464b49c4e6e64af2438da9a7f21a061c77712dc); + tempvar res = res * point + (0x7d92a463e2aec09eb86f4647dc9ec241904135b5eb53ea272e809e58c0a271e); + tempvar res = res * point + (0x17ab90241b58bd3bd90b8a5c7f30aa9e5afeedbe1c31f21ca86c46c497b573c); + tempvar res = res * point + (0x199d80ad30b4b330fc8a063d1e87307993e1d98822a1729488ba8a586045691); + tempvar res = res * point + (0x601a139ed75acbecf557cd6513171385a119087585111c30bbc1b65cd6d30d); + tempvar res = res * point + (0x77b10e23b08892ab18cc6b14dfda6f4be5c2fec94a12e3622622376edd0d6a8); + tempvar res = res * point + (0x2a17a5c34f9f598deb5bec334fde606eaa5601df908eb5825ecf70f9cecec3f); + tempvar res = res * point + (0x7e176a66dcfd58e240c4546cd760b7e5ad02e4f0265c6a2f38d710bbdf99d55); + tempvar res = res * point + (0x27e76848780aba5b12061bffefff1710995586618a2f32792d62771d31ed519); + tempvar res = res * point + (0x43f51dfe0f1cf290c9a522e2a5e734f79d220be80348438c676295c3d429e); + tempvar res = res * point + (0xf1f93c3d919653f02fba06fcba1ab89497fff53eceff6a7d129887d5a9e3b); + tempvar res = res * point + (0x79fd6f5f9b042ece36af6b10eae2eef9de9c9dd18752eb66868a0c301015dd9); + tempvar res = res * point + (0x1958435eb08883bd69b6a56a8f3103c22f8ae206a3d4deaf4a04118b4dd6a6c); + tempvar res = res * point + (0x329230075f64ffbf631eb0c40b97d71b4dc38a08bd18b638f57e5644680068c); + tempvar res = res * point + (0x219557f1604be8622e697e986c03d2a49e40cce558a264bf4f1ebe06493eceb); + tempvar res = res * point + (0x7238f034b8c57c8b59b0f744ababf9da8229152a051d4f3b3c4995233ac1111); + tempvar res = res * point + (0x201019c76d9aa29a00e6b18a4eeac7b1322b44285c57cf4c0b68a87120b1d31); + tempvar res = res * point + (0x69d95f3c7892a1cf65b45c324be2294c4c5459e05e0feaa0b8bb98cd8bc958f); + tempvar res = res * point + (0x78aafbe80fa5ee9a846e991bf35b81567a6dcbb1b190e7ee47e53fc66422e84); + tempvar res = res * point + (0x15ba3c5a882d4dfe3e23db18368ade6b2d10ef52e34f12ce0d62e7183c10f7e); + tempvar res = res * point + (0x1a4bdaf2bff969eff8cef73e762b6346492b8d0f17b2e42956c526f625241ea); + tempvar res = res * point + (0x4adaabee9ab3c6ee7fc67a2ddc09c5185755dcc76cc3b814a6b71aa7ae542ea); + tempvar res = res * point + (0x2f47cde744314dc0502faffb0387a2e765e4354b0516ee9ab0b97a1b6c33ec2); + tempvar res = res * point + (0x90b2b18b3fc2919a55b71ad6d6fa67dda752bd02c985b59e6554f557fe4a2e); + tempvar res = res * point + (0x6eba866251e1dca38a21c8b3fad0aa3c22a45dd89884c4c68bd7ef67de64f52); + tempvar res = res * point + (0xb8dd33ef8726747fb368aedf80c2f4a720bc1b5220f4a3f0e56e2fafb7e243); + tempvar res = res * point + (0x1fac2f441d05a3b483675200cb1ebc6f4ca6ecc5ae60118fe8745f95217bf8b); + tempvar res = res * point + (0x6d28879c6f75c4ede18e1b94ffff964d08c79038fd9ba2e7873cbefb5f323db); + tempvar res = res * point + (0x28b38e0334fc06af4c94ec4f9434923d4149cc51817526597423fd4692c59ad); + tempvar res = res * point + (0x84add7269e2e41ea57aaed996f4c012ba7003ea2b994670cc0d554b7a8bd2a); + tempvar res = res * point + (0x64d672ca00300ddd5e9c9d2db433d7623bb54c8eb2db51b235a07616f1517e5); + tempvar res = res * point + (0x7f71cb5526600d15d3413ec971ee3b133718224b3cbdc68171a53d7c8684382); + tempvar res = res * point + (0x38e5702bb10256e1856a5bfb03a06b231b89a36e2f84af80bcd2d027153d847); + tempvar res = res * point + (0x1a8d4b2044b8e03b325c353f3f92283013920b92f479064b6e93159d2ed3ba0); + tempvar res = res * point + (0x68384718bd3bb23f32999f1edcb2dbddd8136259e676c4492d0cafe80ffd856); + tempvar res = res * point + (0x31a77aa370bb597dbdd0422612a7dd947aae09a5b0b17d1996f13a85103d150); + tempvar res = res * point + (0x40a9cea0394d15ef057c2923d4185f290fe2347e00529d92f927ef506e3b5e7); + tempvar res = res * point + (0x2a427d70a34b6b5237894f065ef5d60a9872ba444d47d98648b080b8ddb2a68); + tempvar res = res * point + (0xe505592d606917f898c54a7afc45b328be3cd48121aee2e8f05185a3e23e5f); + tempvar res = res * point + (0x45b4e74f19b293bc3d3d172a101e344558fcf4ccfe5eecefe31f45a45614df7); + tempvar res = res * point + (0x68486394265c9dc8fae42c8fd39605d3179c981cb44cbe33740a3deb907bc59); + tempvar res = res * point + (0x2868a08eae382c069047152ee964ac5ebd242b44267e97e578802440ef764f5); + tempvar res = res * point + (0x3159144c85f2c515eb806e5aedd908553057b69c556d226adc6e4511a35423c); + tempvar res = res * point + (0x4387edee6899d4a85883d2f8524978a4634ff82779f150b7b0c861bb315ed3f); + tempvar res = res * point + (0x68c5830832f6270a189b074d7675fcbc1d1c5cc06ce9c478bf8f4d5ac1bf40); + tempvar res = res * point + (0x399c00b8ebb398248bb1f52528d5241e7366b73c2d89f57a11dc82c530cc57c); + tempvar res = res * point + (0x3238aeb8f6bea8bcaaa1bdd5b4f917ccfad8eab031785ccdc648b47d7ea4be8); + tempvar res = res * point + (0x357bf5d87c973292381fa4320114551a837a1d6cb6e2bb0eeba534fb2e01742); + tempvar res = res * point + (0x360274f27df6eeec0b7b65fbb227a8214ac3e55cb37b1970e18489ef5b574e1); + tempvar res = res * point + (0x1cb6e2fba23730f5bf9d8e726569b6e8bf6b5ffe8520339503c5469cc3713a2); + tempvar res = res * point + (0x3924324af1994280f87f289fdae0b9a2d8cb9914ec37d319c18daf029211815); + tempvar res = res * point + (0x3c4ad04a5a057e4411487858dbe16af8e3fc065ef7400749ffdc248bdb25bc5); + tempvar res = res * point + (0x50c92b3e6848a21001be2a268615e1e26cb4918ecb09640efaaf1d8b71568fb); + tempvar res = res * point + (0x47d21828025d0cbab84084965a49dd14c7833aac562b55de808a94777df2ea3); + tempvar res = res * point + (0x6207c6a2fd70c19a10430566c9efaad95eab8cbddf308f0057c81f3155a25a0); + tempvar res = res * point + (0x2d4acebd804035257147ad8d8419a5f5762b4b543c4846ef9acf41856e672ee); + tempvar res = res * point + (0x78f49c214872b5cce18ead0207a165fb741ea818a69cfe9647737323f70f4f5); + tempvar res = res * point + (0x22aa8c5c5ff26f9a0edc768ae32ff4f71a71205b4e83cfa0cc687a1e02566ba); + tempvar res = res * point + (0x5dd2e0680c7eff25211f31d3c30a9f454500d6eb09d46d87a75a42b190203cb); + tempvar res = res * point + (0x5ac4bcdb9c14634ab83c13a30822ddbabc54248cf1177b11cc2aed24d2d32f5); + tempvar res = res * point + (0x77dee5f03389585fad0d1f2a8accfa4cb985344891b8befaee42f3462cb48a); + tempvar res = res * point + (0x737dba18eb055a12d842bfae32fd146dcd2d7bb932a2591aa864458d6d652); + tempvar res = res * point + (0x23bf372b0b59abf250463697ef4b2096eb1c9674613918b4d0c79aa10d9fd59); + tempvar res = res * point + (0x73724274fdd351c378e597da1615dc51058e14994464cb7b318766199ac2a35); + tempvar res = res * point + (0x2e14e83be58cde3ed5f3fec8ba6462493a4a2f0f7d6c846006220eccd49ef25); + tempvar res = res * point + (0x4846d310812d81ffda3731e8289005e2f0e05411e76b1c84332c3ee9e831afb); + tempvar res = res * point + (0x160abeb38bc4f22af5fe618c19c77c39903007900722bdbdeaee059f31544c8); + tempvar res = res * point + (0x264a535ae10091157ed59b04955dff66897af74cae20456bb830336b803ae47); + tempvar res = res * point + (0x316ce6b23e720b8302e2d4bd968c0f140f69930e46a54784a7cee7e0b8a0c8); + tempvar res = res * point + (0x775d95a0beb287c98663a3f9a9c577ffc67c1fe6fbe2db5b08829a2c3eac922); + tempvar res = res * point + (0x2353c4a418bdc1e461be162140cc69c26eb9d99f08924991f85058f87f6df41); + tempvar res = res * point + (0x181ef9cde124459dc0e2aaf93512abd49a10328fb93dfc4d49ab671db64bbc4); + tempvar res = res * point + (0x7ff76956e0cd2b490b47a0a0497df5f874cf47f54c45f08101256429b48460); + tempvar res = res * point + (0x318e5a52d685eaa06e0f39159a344b3d97b52688b671d133954aeff0bc17707); + tempvar res = res * point + (0x7616cfc6834643d4b95ed1cfec036f816a7c3d3b9800f301f98ddf341712ebf); + tempvar res = res * point + (0x59869515fb57ea7733567e5d849bcaa00c00e0f86f4ebbd2c7a6f4c0c77692b); + tempvar res = res * point + (0xb806f4e19770279fab5427b8eaf5bc68bf984d6ccea1e878a7aaf32c9975d9); + tempvar res = res * point + (0x4fb0c93fe30da048576fe5e839483636218dfdda3d05f1d68847a4c0167597f); + tempvar res = res * point + (0x685af2d7bbf30cd0c5c3d41c430a8657eeafeeb4596165faaa73d802087ad80); + tempvar res = res * point + (0x6f617dce150ea148cb8c7488fe4caa920b2000bc8122cce1891e4b76cddc9d4); + tempvar res = res * point + (0x47f02fc512b153462379f4f793c7cab9e659bfdb07d3439d29039f566b7236d); + tempvar res = res * point + (0x4ce0a14a5a9c30a38062eb8870eeb4ff3562db743c0f3eede2e3d3862a2eb7c); + tempvar res = res * point + (0x7b077d27c7007656025224fa4e528b4c4261f43c3da1e42bd1349403af55cbb); + tempvar res = res * point + (0x50f5f6adbf0b9abc6e231b855018f4ec806a4f199cc511bed5c423ebef298e4); + tempvar res = res * point + (0x5fcfeb78685abb1ce610e516ab7e2aa210fd90844c8d1c89cd798f3d71bbcb3); + tempvar res = res * point + (0x4255a568f4597862e1dfe0c391b97059d179d7eb4d868f61364835e5028f9dd); + tempvar res = res * point + (0x206d7f23d0fe1b1c0967486ebb792d7fdf5b1691d2c2f9306e211d3b849526b); + tempvar res = res * point + (0xc61c74cc988663ee09f4c725d5b1f04549bd342d3550ce17427ac75592b637); + tempvar res = res * point + (0x175a904681c7a91856bf7fcf8410d2c19eb8705267914489664a1ea2af5b8fe); + tempvar res = res * point + (0x1bd842a4ec97e1489ceb542bd3161e5a00ce431547bfadfbced954d993b0a11); + tempvar res = res * point + (0x14899e0f97aac917d46ce5e9ddf11194fb846d2c52726af4085f27c570a98a9); + tempvar res = res * point + (0x842955243a56778a332ba9be0b22b2af62efaa50068d3078675fb76c225e76); + tempvar res = res * point + (0x6dff267c3bbce68474294da908df4f5cf2a4160c638f7cb45c098057e968f44); + tempvar res = res * point + (0x72c0dd24a576b47a84cdd1a20227773b5621f85b781c288625e3368e1cf738a); + tempvar res = res * point + (0x728771890334d0c9b0f400543bdc13ea6890497bc87c509a04f8014916c13a5); + tempvar res = res * point + (0x30632b3865a272a1a00270430744ee90b40ff16e1fc44515876ce8e36215ca0); + tempvar res = res * point + (0x76d656560dac569683063278ea2dee47d935501c2195ff53b741efe81509892); + tempvar res = res * point + (0x1dbdc2ea2e555309578eeb2352fbc47c8fd5ed77cc09903b577700f9a4d1be1); + tempvar res = res * point + (0x119bcf6402ad9953851bac8e318d50af699b0cc75e2597aff0a2cc521975aa4); + tempvar res = res * point + (0x7c3234094dff9a45064a5b9abd0667c04dd76c62722984f7f8475e7cc344c06); + tempvar res = res * point + (0x1495d40cf3f13c5fc90653c2b2f02e0b833790c07576286d3127f745ea920ae); + tempvar res = res * point + (0x40f019a18b8097235264cb8efee7d149321a199ccd32ffac43b5a778dfadda1); + tempvar res = res * point + (0x4e23809ce49747990e43b2d976083dc84d67e75cf22e5a76ad5b7a2dca50b3d); + tempvar res = res * point + (0x7f0a3bec1d34f2fd632993a3d9c6432401cec25ad9d6196b909f3672980bd05); + tempvar res = res * point + (0x9460aa25f77fc10cfcc4579e2011e39ce477a32a768aa553201e556ed2bbe1); + tempvar res = res * point + (0x611384709c407d85c93256b6aff04c4ac515450c70cf507994165abfe2347b); + tempvar res = res * point + (0x2065bc7a4aa38d5fe86f9b593ccd060f8d4a5a19a9ca8b182c32199a4bd27be); + tempvar res = res * point + (0x9969a08d753e885857a5696d1cafd39f62bb193acc99089df76c240acd2fc0); + tempvar res = res * point + (0x6df73a948c95439f3230282814ba7e26203cfdc725901e4971ad9cff4db4396); + tempvar res = res * point + (0x1cdf0446663046f35c26d51e45a5233a93c51f4f7f1985dfe130dd67addefa3); + tempvar res = res * point + (0x59cbe680183d1dc3161ee7f945f38ab9461a5293748b2b7be84899e62c9860b); + tempvar res = res * point + (0x5030fda0c29a929e6cd634b9f3d1bf975c363012cfb439cae13495f8ce10225); + tempvar res = res * point + (0x49aadcf98ef59c0e5d2097845949988862b96194abc8c5453f056f232482892); + tempvar res = res * point + (0x319c68159cdf104c2543486ff784860f302187d77effb9a5fefe4e16f0ddc2c); + tempvar res = res * point + (0x575531b404cdba72a63dbbd17aef7d9ae00f73eca7c6dcdaf5e0778c921be41); + tempvar res = res * point + (0x35ca7fa56aa38486833a976804899ba3c97fdaa0a23056cd2dc9bfdbcdd2e31); + tempvar res = res * point + (0x47dc0e209ee8d0b67f63d9e63837ff2ab462c4839bc14a1a3e802327ff0e31f); + tempvar res = res * point + (0x744bdf0c2894072564f6eca2d26efc03ef001bc6e78b34bf6be3a1a91fd90fc); + tempvar res = res * point + (0x73c57ecea0c64a9bc087e50a97a28df974b294c52a0ef5854f53f69ef6773af); + tempvar res = res * point + (0x7dd14b0299ff6064a96fe97e086df3f64a4c7e8b4a58a5bd5fe1b9cf7c61e7c); + tempvar res = res * point + (0x562f636b49796e469dfe9e6748c4468f340e8f69e3f79cfe6925a261198dbb3); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_keccak__keccak__keccak_round_key0(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x25257ecfcf301b18da64254e59b151a549668b8c150b39f71eb3e3508224fbb); + tempvar res = res * point + (0x13342c1639906e1ef17847fdf16d032ea663fdc4fed28da92f88381ebfa626b); + tempvar res = res * point + (0x12125a111c43e7a0819677f13fcfb3d15bf9921cb098a11db3cac22813437ce); + tempvar res = res * point + (0x15c58abecd948a965601dc451075b0c1dcbfe1ad91c086e0f43865ebfeca111); + tempvar res = res * point + (0x73960e722af010fc2cbc3012de9ae4bc357e8728e7d6a15b0cb10b12bbebeeb); + tempvar res = res * point + (0x5cb77e4fe2751fb9cf145aea5d07503c518440d7bc7b85c91b6799f14fa0b82); + tempvar res = res * point + (0x624263f4821e9fd3af946554a890b0e20ee21c5db0eb4742f547f049d7265a5); + tempvar res = res * point + (0x601b3d8d8eeed4743cab5f121b1c30874e95ad5883c331aa0fef0b8d9c4b17a); + tempvar res = res * point + (0x50e3e5f09b36a9055c9992f6b89471bd122b785b6071483279bf6c45263f18b); + tempvar res = res * point + (0x6687d6c2e62115cff5db20d04e5fbcdf28e85d6acfab9e7b8869f46f388b16d); + tempvar res = res * point + (0x3fb1f146e0af9750e5d66c46244aa96306b4c4518e6311ccc4a730f289d4493); + tempvar res = res * point + (0x4ea9551cbcfe5f18614ae86e485adba9f70255f312eb4386020432c1169a03b); + tempvar res = res * point + (0x1cae942c39310c3913c33d6e0c10c4db313621d4e70baf4ab17a4b71a0a2336); + tempvar res = res * point + (0x186c97cc34ee93808f32336d2afe9ca74ce30b932b416ed662b0287c7db52eb); + tempvar res = res * point + (0x754e8d183db530c59c19c447e1b0fa66cac465db9ed0bec3576fe8723a88d5); + tempvar res = res * point + (0x70000000000000ee00000000000000000000000000000000222222222222223); + tempvar res = res * point + (0x5bbf43b8bcde1f233ee3b725e768ddbef1d6ee4e272c2cc365cf9d58b2cec06); + tempvar res = res * point + (0x322981f5cfa5a7aac59428b3062bad8dc08145c68082d791cce8fdf2287fbd2); + tempvar res = res * point + (0x3318691be977dcb75f1fac814c8d42814e8fae2640bb483f5ce5fab2fa9f063); + tempvar res = res * point + (0x3a70f05c50491d642354e1df25c2b04cc06b790375c5dc7309838f0d17a9fc0); + tempvar res = res * point + (0x5d870d9e97b879e273beec4b5ea076338bebca91d4104ff4a5fa8a51cab1348); + tempvar res = res * point + (0x3fb0c6c8b229297ff6644fdf9bb36a659c4a91dd060d65f243d23308fd2765a); + tempvar res = res * point + (0x749e7d5e4eee9f1220ed1c8991d70dae19b3f742417b23c5acec221e971ff46); + tempvar res = res * point + (0x2fe4c27271112cbdc354a0ede4e3cf78b16a52a77c3cce55cdeed2504192c65); + tempvar res = res * point + (0x3a3cd9702057cb220459e07f39c2db92ef07599d1016c02a8f028c6a13572ab); + tempvar res = res * point + (0x53ad84fad4ed87e5606af2364d96d04735dba9a7a1f235a13b68a7496e22a73); + tempvar res = res * point + (0x2b91e359964f3f5cc62de8673b400cd968e983184fccf3d2f71da3d4a0f442b); + tempvar res = res * point + (0x21202fc82523fa85255e596d816cc3476bd24f5be58e592577b74fbd4a6966d); + tempvar res = res * point + (0x462ecdd9bc89bf4cd186564983426380d0ef409db04df04e971d2e59f2bf32d); + tempvar res = res * point + (0xb981951722e737e9e029e1148b76ad3ffa4d71a21426c17065ac1482f379a8); + tempvar res = res * point + (0x315b9e0e2e5cd6c0490268bd5b95853a50961e5584289a0ee467e5f6bdee9dd); + tempvar res = res * point + (0x1111111111111111); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_keccak__keccak__keccak_round_key1(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x46c20a61e3dd5f8e8d4085bfcf8e52c9c50152285742b9ba783a4edb6608353); + tempvar res = res * point + (0x62db2649e22e5c49b68354e9a3801a9b695f7d1c8d03854b1edfa0e322ef902); + tempvar res = res * point + (0x3420050a4dc6c773aa43eb3a5c8b2b88b3e33bc739775bc375933e2ff8e3846); + tempvar res = res * point + (0x4bc9ed4ab2622c0cad2c8111a9a5598ddac8d9e1a89766c0bf0bfd7b750538c); + tempvar res = res * point + (0x2df8e6211399d12f3d33874172e235e92aae15d062516b5c1641ce309354f2); + tempvar res = res * point + (0xb63ac706fb9d207b59fa7456f07c71fb193932810c68fd454a98d89d96e97a); + tempvar res = res * point + (0x523ed890c4e0e53b280afa7ecfc9d32182829c79f4f90ee5352b2b1671933a8); + tempvar res = res * point + (0x401b3d8d8eeed4303cab5f121b1c30874e95ad5883c331aa54334fd1e08f5be); + tempvar res = res * point + (0x44670acb048727d509f4189ff2322439252d747f2a78570bb8c20b28f8e8c1b); + tempvar res = res * point + (0x5c6bd13190fe93c3c7535bade15bf685833e3f846aafbe531aedf5e448bf4f6); + tempvar res = res * point + (0x4e9d1c063aa65b8d301ab440c23f7489eddf4d4d1d049fd6f817fbea9b9b843); + tempvar res = res * point + (0x73531922feb3a6f79490f130de30f0c2fadd1afe367970c43540a32112a5e8c); + tempvar res = res * point + (0x40dfd1db116746967a4792685c8eb61ea90a2de3f9aa80975d4c6dc52e7025b); + tempvar res = res * point + (0x1a3b463bdc8408051f1aac5b7c31cecefcd32c6a6dc13b9b9cfee72fb3dad69); + tempvar res = res * point + (0xadc55da564cf8859d120b02ab9fb09ed6ae934330c42084a392a9688723630); + tempvar res = res * point + (0x70000000000000ee00000000000000000000000000000000222222222222223); + tempvar res = res * point + (0x4481ca3e932177631ec3ceed8ffc6372aa9cf54186ed4be4ff4641a7807c127); + tempvar res = res * point + (0x592a0b7fa0c98ab8930a5ca88ac1cbac0dfa16ae244d58745171ce70fda046); + tempvar res = res * point + (0x6cc4bd7e3e47730c6f03f139e48f03db875a3e1302c00af6caabfe34f7cbf37); + tempvar res = res * point + (0x2392a163f404deefe6cf4481b3b183464db5160b40d56f427af356cc7ad1d37); + tempvar res = res * point + (0x740152f0bfd3a106dcae496a23399b3195eb3242ec4154529c8bb14120ccbb4); + tempvar res = res * point + (0x2a6899691636dd2f8e27428b7478962bcf7938103e12c462ebb4b1a0bed9d28); + tempvar res = res * point + (0x309e897530d9e68ebd3e9938bf89553a7fa2c5f8a26090b3cf280a70dd89e77); + tempvar res = res * point + (0xfe4c27271112c79c354a0ede4e3cf78b16a52a77c3cce561233169485d70a9); + tempvar res = res * point + (0x20c3b86201349cc6d6c20bd29a2ad219855bcbc3c6db925113aa6d6dd0b57d2); + tempvar res = res * point + (0x3b935e02ce81c807eba625e65ee894418cd957563514ad82c0d77a87f5a37a9); + tempvar res = res * point + (0x5c83a35a80e818de30d8bf353017d8c6135384ab53836885cc65b88059b67af); + tempvar res = res * point + (0x1d50582e5ae5502bd773493bc4783268dca4f514e019b93890c00896fd830b3); + tempvar res = res * point + (0x17d0b504a0d0e37a287c72997d21dec2143836cf446b2563784e32746ee2c13); + tempvar res = res * point + (0x6f8b7db461cffbbaaa70ed8b33dd11c847c952fb3458a9845a5e22e6ba27d89); + tempvar res = res * point + (0x6640c6366c5b918d0369115b919baa50eabbbe778b22d0cacad4a7b7bb357be); + tempvar res = res * point + (0x1111111111111111); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_keccak__keccak__keccak_round_key3(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x4a025b231a318123295e4fc2ad69f9552eec69c64066fac264b1cfcdd7d3158); + tempvar res = res * point + (0x5460b40a6b82eea400c5f65223403b791182933281ab2654f3762718ea7272a); + tempvar res = res * point + (0x577c87daa8b61681534eabd0626b9e6b73e5152876c214cd16515b620f42de); + tempvar res = res * point + (0x42cae55f34098448653815d656a3fe1e71f0b843a3a978717f2f02f69ec80c7); + tempvar res = res * point + (0x54dbe71eb9ae525a52abca43b7aadeeac9664a351d711d8d43ed87957535f19); + tempvar res = res * point + (0x57276cf88395452ddfb9ecf810e6b6407e3f757e0186097c3484de9195304d7); + tempvar res = res * point + (0x1ea216e7fa1188997bf294ce196ff23a97bed74a3a74820555d2aee1819c839); + tempvar res = res * point + (0x601b3d8d8eeed4743cab5f121b1c30874e95ad5883c331aa0fef0b8d9c4b17a); + tempvar res = res * point + (0x75d25626915653ec90adc5178d4a32f65ed1857d70c0a737b9fb5535837c9d0); + tempvar res = res * point + (0x559b4e49955b69058393ead11679baa4ceebadafcd17d1214cd1fb92c9a67de); + tempvar res = res * point + (0x844af79594ffe6ea50d5c9e6ee3287cd7871390cca63a0797c3f2d2d3f53f3); + tempvar res = res * point + (0xc52210e7d0c4dcddc855c6c31324c3263b53c9c3b675f1352fb7b83c6c0f2e); + tempvar res = res * point + (0x4fdd57886595821090659b2a53a9dc377a2a90315c901d58677c17a0a4cfb60); + tempvar res = res * point + (0x77b6d8762a4c0870d48f1bf7d4ef0674e1b51ca1a5f23186babfc02837bbac0); + tempvar res = res * point + (0x71b4d4ca13e1018d2b54993a3950f29b7ffbd7f317e8186338bf32e552c2ae2); + tempvar res = res * point + (0x1000000000000021ffffffffffffffffffffffffffffffffdddddddddddddde); + tempvar res = res * point + (0x6bd6af7759bad5fe5748f2ffe9d4cb5319aef5a5e59df200aa3df034cc06941); + tempvar res = res * point + (0xdd3d6e7af0c08df08799e48b8fadc745d590aba8fb7199d89ffc2e9d87bf31); + tempvar res = res * point + (0x1b0a352b349c7cf1a5cb6b4faec5eaca91a91b99e1f633c145c994cd3cf8a58); + tempvar res = res * point + (0x6cc8246a903b2e8ca81a6de13ceb3fc453b8925a4d49c0e5daae686c89a52ef); + tempvar res = res * point + (0x24bb40b69d54b9ce773c98f82908afd7181b1187d5051669025874cb5401c72); + tempvar res = res * point + (0x66a4081561dbc5b317067e6d12de31d212e4ec94ed17b69109c0f327639d08c); + tempvar res = res * point + (0x59926196b781e5f56e60c792946b8853ef6ce8c17b5f3da6fcc8ede489bafb3); + tempvar res = res * point + (0x2fe4c27271112cbdc354a0ede4e3cf78b16a52a77c3cce55cdeed2504192c65); + tempvar res = res * point + (0x705bc2bf83594f7602f344e78e5f6f8774d43933d67103708446fabf41e59cb); + tempvar res = res * point + (0x683026c45015a1db732c80940d4b2d6dc238b4632185eeebf173d6262f26d85); + tempvar res = res * point + (0x341a62cac79ab855999592a767fa1e3270800864554795a6a6405796a23b15b); + tempvar res = res * point + (0x641ad527beaf01c116281fdc3b3e75ead6a178c5d3a567950ee2d4d4cc8d8da); + tempvar res = res * point + (0x59aa70b54354dfd8ac0ebc473fd8a9a613658b3025a989f4fd0af711bddb694); + tempvar res = res * point + (0x6a7db27bf042f02234b078a3074c11788d26814b6b700e6bc2b629da8b32b9c); + tempvar res = res * point + (0x7a0f8f36b1ef9bbfd60fbda365eb2bafdc9749e3c50d90852773205d38a9f04); + tempvar res = res * point + (0x1111111111111111); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_keccak__keccak__keccak_round_key7(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x279b1137fbe58a227ed345e6b3136ea36aa5eabb7ebaac5f226c318ef599e60); + tempvar res = res * point + (0x63355b4be0dccf93a1fa0f44f29a9ddd83c010b942d979a530cecd6c74ba8c8); + tempvar res = res * point + (0x2a1210c6928cd6a942ae59da3af2423896f30acfc1174f1611cd90922303f40); + tempvar res = res * point + (0x2950c0942b252300fdf68871a455ed05549929a79037834d6faa1d2dab1e731); + tempvar res = res * point + (0x5b2ede5b73c60003b027071c1f36a59ff339069eccddc28f143ad374c13c67a); + tempvar res = res * point + (0x2bfbed668244b9211d0023eaf227f0a8a9a8aea53ba93b84d35be4acaf5e0b7); + tempvar res = res * point + (0x6d8c656cba303fd802db54d6b43bfcec1e4db34d0ee27d5bdd23686e5f50760); + tempvar res = res * point + (0xf9309c9c444b1810d5283b7938f3de2c5a94a9df0f339579e21afa76cb17f9); + tempvar res = res * point + (0x5b5d5cc26ebb21f4a1851a39f0e5f5df99c9304ceacdb7f10d81344a3d781dd); + tempvar res = res * point + (0x21cf87a7632c50d1d9c0477a319cf769e77bb36db2f4848848c7caea274d289); + tempvar res = res * point + (0x734b0fdf3a990e5ccec5ff6f72d41000033dfbd57586901e7ce5a9ce071992); + tempvar res = res * point + (0x76af3f6bd4dade530209778e5baa12faab66d6586fc87cb24c119e8e109d48c); + tempvar res = res * point + (0x48639d021d476bb451319356bf88a82456f69947e4f11c446d5e847136e5ad8); + tempvar res = res * point + (0xeff2fa639b2281167458555e9a07a0feb1b8d33ce88c64d2a84fa742c11b71); + tempvar res = res * point + (0x493fd6f738b14dbb2866f8dfb966aa9963463ab1edfae1b39749c44b8713519); + tempvar res = res * point + (0x60000000000000cc00000000000000000000000000000000444444444444445); + tempvar res = res * point + (0x1e9cf906f9fbdf8e75a43cdad43c3f7e2aa6645eedb45f02d6c87332ca5b8a4); + tempvar res = res * point + (0xeff2fa639b2281167458555e9a07a0feb1b8d33ce88c64d2a84fa742c11b71); + tempvar res = res * point + (0x7df59f05447f800e840bac0aeba642399305955df706f73e5f11e645104258d); + tempvar res = res * point + (0x571c35a210962caff4b6f3d6c81ad517e5bd8bba7ed5435ad0121108c60deb5); + tempvar res = res * point + (0x16e29756eb5894d70e07ac474fd109610d3721dcd6dc8020d85a5c9832a1d7b); + tempvar res = res * point + (0x21cf87a7632c50d1d9c0477a319cf769e77bb36db2f4848848c7caea274d289); + tempvar res = res * point + (0x7a49136d756e1c2773a7c78b098e94291c2d1d10608723b18b334f988feb421); + tempvar res = res * point + (0x506cf6363bbb4f4af2ad7c486c70c21d3a56b5620f0cc6a8a622949cd792c4c); + tempvar res = res * point + (0x5e6a98fe9b63767a6a03630487ca5bfed0ea8098a8c33cacf94a26f40292721); + tempvar res = res * point + (0x2bfbed668244b9211d0023eaf227f0a8a9a8aea53ba93b84d35be4acaf5e0b7); + tempvar res = res * point + (0x50c39f36354a1a826c599a23e23a3a8dd5d38014f08950a9a7522e8bec481a3); + tempvar res = res * point + (0x48e3ca5def69d4a40b490c2937e52ae81a427445812abca4eba9aab2f5add08); + tempvar res = res * point + (0x458aed4b839a0190f09fb945d16fa8daa8993e3c7754a10ba60c4b81d53c135); + tempvar res = res * point + (0x63355b4be0dccf93a1fa0f44f29a9ddd83c010b942d979a530cecd6c74ba8c8); + tempvar res = res * point + (0x4eeab02e97b059756115eabe88cec451623ef4f0a29b7d3f005f83ad89b0f69); + tempvar res = res * point + (0x1111111111111111); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_keccak__keccak__keccak_round_key15(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x24ec7e1a7b8bcb5b138102f4131d7fa12dd5fc5278251892aa929a46b50dec4); + tempvar res = res * point + (0x6fab9476126a16ec91fb0071a673f7c8b65b1dbd3d04502cbc915a3db9e8a1f); + tempvar res = res * point + (0x12f9d780e40408e85cfd757fc76df0883a6aeb39adb7626b2ff9b582c551d3e); + tempvar res = res * point + (0x76e0a1037b5bac3527a824fe3e4eb1f1841619c97aad3b04461cd97010cd690); + tempvar res = res * point + (0x51d69b95d84bf6cb03ae28cd575fd8b1c2fde0263a9cbb33b0c2d281d6593e5); + tempvar res = res * point + (0x637549dd8a31e6eb931f74c374ae94c1344727397e1baa82702b01ca6765a5f); + tempvar res = res * point + (0x259a0178365605d693f8d60441444981aa3782845295b3c795504192c100bd5); + tempvar res = res * point + (0x501b3d8d8eeed4523cab5f121b1c30874e95ad5883c331aa32112dafbe6d39c); + tempvar res = res * point + (0x4cf3d65c0b542463ffbade568e57a5562c15810c7050d7fa1cffd718c535167); + tempvar res = res * point + (0xe735942acb168306ebc477871555c572af3741c59332ca97f034aaa040eef3); + tempvar res = res * point + (0x231af732a4a2d73dd564d92560c1b4387d641e999f139c35a49dce4b95c40a8); + tempvar res = res * point + (0x6bc84bb37162e162131f843a2a2e6f1bfaf80796e8203e6c98b9007613eceea); + tempvar res = res * point + (0x34701ae77a897e00aecf2472198c4bbb5d7e5568c3b4439be3a5872607c4674); + tempvar res = res * point + (0x2b785b28d1c810d0ae9d9ff6be5830d87f9eab4199991d2982faacbfee350f1); + tempvar res = res * point + (0x9e00b3dfda8e20537eb42e591413bf4f6b41ff1af4904634a41461a23c0033); + tempvar res = res * point + (0x70000000000000ee00000000000000000000000000000000222222222222223); + tempvar res = res * point + (0x3a3f52e03867160939f19be537d98bcc8972a660111194aa12ac42a7ec61d96); + tempvar res = res * point + (0x388bb770abf3374034623c1e4f7fde7ed6b8a6192abda75187874c71404ac37); + tempvar res = res * point + (0x2fc8f5dccdd25a5950fbc1514105c89273300b1a94541a69944e88356b5a664); + tempvar res = res * point + (0x78e8e3e166c6ae785f011cdd8b78ecffdebe8b857dcc61a7339ea90e5036019); + tempvar res = res * point + (0x5b858dbd345e2432e03866bcde0f9bc4e720c6c79f303f462219f77397d4815); + tempvar res = res * point + (0x728d7717199c70f029fe3331a50a2998e9f0feafd8440d09345598bfadbd37b); + tempvar res = res * point + (0x2d5b04f1e90c33a30180d67ba63c239c6b5eee519be4e624aa37fbd973a73b2); + tempvar res = res * point + (0x1fe4c27271112c9bc354a0ede4e3cf78b16a52a77c3cce55f010f47263b4e87); + tempvar res = res * point + (0x544d4edf7c744af8a57fff189322115956f891a315854171657d7a2f0a87826); + tempvar res = res * point + (0x49555ad694f14bc2cae67bf798b6cd6147f8c80d3f0adbd83ce40ea701bdab9); + tempvar res = res * point + (0x59b545396dcb787789f473c12a59d08f9aaa35b00fd4204cced53d3d3fdad4a); + tempvar res = res * point + (0x646e2f67ac7ac7a8663739ea0c09f1f2a233531a1f6624e76502f48302871e8); + tempvar res = res * point + (0x1ea0b1fbb487b7c25ff7c84c1d7501eb32b9b90b718b88928939dd1afb3a379); + tempvar res = res * point + (0x7e84e3e28a699a839444b81427ef10cd62292ed510072b4ad884b8b5fca8138); + tempvar res = res * point + (0x62bdf821a73997783fed94521acd94cfb95eb9d6532f9b07adf1c5baade31da); + tempvar res = res * point + (0x60000000000000cc00000000000000000000000000000001555555555555556); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_keccak__keccak__keccak_round_key31(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x5852cb7312b6299275e11e7bf04e6a604038b1398d93ed46cdfa41cb9503116); + tempvar res = res * point + (0x3645c0d194b9983bc9c138a6e57651551a16c071ad1f5b0fc37946aa5b6a2cf); + tempvar res = res * point + (0x40c0d849a4523e6379cddf0bb9f7220b4ad778b81a7e873876700bc9d276ec4); + tempvar res = res * point + (0x211f5efc84a4550dd857db01c1b14e0e7be9e6368552c4fb86aff35cbbff63e); + tempvar res = res * point + (0x59c8aeb2a0ac85c5c13da60be839d4171a4a2c8808ecdf75ba6490bb81a9079); + tempvar res = res * point + (0x22aeb7c2e8c9fc5f1819601d752141f60e5e894d854be8a2bc8cd9791bb115e); + tempvar res = res * point + (0x691f1c1adfc25c7591030cc775b01c76d305e385ef6528a6b2f29d656d8d181); + tempvar res = res * point + (0x851b8a8accc7b09b6021d3651549195ebc108098b4994fe630055dc081479f); + tempvar res = res * point + (0x1a8f201c55f7facb0cc93566ad5194662a91b7372cf67f0fd9c6bc400b89de1); + tempvar res = res * point + (0x3a3014183373f80fc4185542958defd2e934de274c76e6e4faf6922f7c26ca); + tempvar res = res * point + (0x5471f4be94ccf3bb7be211193c1827b4070e4f2eea1ed7e828d4d4ca4a703f8); + tempvar res = res * point + (0x2c37b44c8e9d1fe0ece07bc5d5d190e40507f86917dfc1933413cc56b8dfde4); + tempvar res = res * point + (0x3ef97a843574486d4a4ca50dfea986f767c7fdd2a8ba4c9217eae4746ef650); + tempvar res = res * point + (0x507518e91a5aa1f164583e8bc6dfa7713e2bccb306b992611ac085e76070526); + tempvar res = res * point + (0x5646153d03a487c880a5e3b7005a996b45570b60a5be6c4a0a8f545fa9900f0); + tempvar res = res * point + (0x800000000000010ffffffffffffffffffffffffffffffffeeeeeeeeeeeeeef); + tempvar res = res * point + (0x32a29bfc37f6ff30148ef2f00017fecc0b8c87f6f22227f97ee3df56d231b3d); + tempvar res = res * point + (0x5d887530f485c860ea1cdab3580755179545c78a97de1c891f4d2598b28606c); + tempvar res = res * point + (0x265b35f9701f2ec4b9f0c2ebc4aa23c969d376930985a63729470320ba328df); + tempvar res = res * point + (0x1f171c1e993952caa0fee322748713002141747a82339e58992e23be7c96cb5); + tempvar res = res * point + (0x198a2a2108558f4d2a79ee44f9de100d3c12f49fb5d3614a63091db177c83fd); + tempvar res = res * point + (0x67bd1f15f0224840b783710d5d0dac3eed90d875f3d84ece0501b738a170b52); + tempvar res = res * point + (0x4b95badd4e47e63f49ff64ccced083d700959b8009f8dceda07f2b04cc47ed7); + tempvar res = res * point + (0x77ae47575333860649fde2c9aeab6e6a143ef7f674b66b019cffaa23f7eb862); + tempvar res = res * point + (0x167f58c665f83f3d48f50c40164294afe64889203f9bb2731e2b7cce7890efe); + tempvar res = res * point + (0x88ec8bbf38961364fe0675199297a9622102a21463b19f88945e655b6091b8); + tempvar res = res * point + (0x86e1cac50243f817030f9dc914c0034e7a747fe0594b3e4f2a3c21a3d96b36); + tempvar res = res * point + (0x3391d0985385399a99c8c615f3f60e0d5dccace5e099db1867c9d849ca45ae6); + tempvar res = res * point + (0xd939b9e847fe38544d046dc62e475644b3450374885610484442e103f3105d); + tempvar res = res * point + (0x451f103e0cb91bd2cc0af04966f16a59c5e4d1898022362ddf6ca5229e299e8); + tempvar res = res * point + (0x702f07b05d77fca39f2b0536963dd44eceff845d2f124793dece58719d09399); + tempvar res = res * point + (0x180000000000003300000000000000000000000000000000dddddddddddddde); + return (res=res); +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +func eval_keccak__keccak__keccak_round_key63(point: felt) -> (res: felt) { + let res = 0; + tempvar res = res * point + (0x13c65642d180be37bf6db1ca47e2884a87a9c17aaa35744910c1b0fccc4c50f); + tempvar res = res * point + (0x4dff8ed2557436c17e52a86eb24e65fcef37d2d5d0df503f27351b9fb114deb); + tempvar res = res * point + (0x5f4717961bc9bb0c1996dabb3c74988f05f5107081b80ff8c4c4299d22048f0); + tempvar res = res * point + (0x581b3d8d8eeed4633cab5f121b1c30874e95ad5883c331aa21001c9ead5c28b); + tempvar res = res * point + (0x216dc3dbb9063124640a3d5f603ca702781ff5264ef23cc5dfcec751f4a33d1); + tempvar res = res * point + (0x3ad1ff12fccb50a5de8e7672380cda75ed5bf08fe3d3cbecd1195b32d881025); + tempvar res = res * point + (0x1d5c1c42d8ec54a42b1632618314889f63c11a24b80b67b9f587da4d671640f); + tempvar res = res * point + (0x38367b1b1ddda7c77956be243638610e9d2b5ab10786635430ef282c49a7404); + tempvar res = res * point + (0x6cc4bb82d7803f17da904038c2212dcef110ebbaa6234e67c5718db62a14207); + tempvar res = res * point + (0x69204e331102a9fadf461be4a4a5b34cf06aa4ce4167589c0dd4f22cc888ffe); + tempvar res = res * point + (0x45d4b9d9009554d081839e925dfddc46033bb5347b940cb21555dd388c66a56); + tempvar res = res * point + (0x27e4c27271112cacc354a0ede4e3cf78b16a52a77c3cce55deffe36152a3d76); + tempvar res = res * point + (0x1ad6ca03d6d5422e58017c5e3cc08f74ddc9ad8bcca0774dd78b592dc16b98b); + tempvar res = res * point + (0x722178334a9327c73bca71705e5c459530198bdca5be25f1d95c98d7190bf96); + tempvar res = res * point + (0x6b62a10a0b8411be1c13352de351dbe55e625cf2569f2c61613d6c57d7039cc); + tempvar res = res * point + (0x800000000000010ffffffffffffffffffffffffffffffffeeeeeeeeeeeeeef); + tempvar res = res * point + (0x477aaaf598b4391c108cc2b3cf8fd238e20c8224820c59847541d59d2b5c101); + tempvar res = res * point + (0x5bfdb03906bd7492c48faf9c33f8dba8f2900740d8c0f835344a49d639c843e); + tempvar res = res * point + (0x653211d3237934d10c7bbcffcba0673cf8919f3d5695d32c1d40749e82bfc3f); + tempvar res = res * point + (0x581b3d8d8eeed4633cab5f121b1c30874e95ad5883c331aa21001c9ead5c28b); + tempvar res = res * point + (0x1e2c6706b58c375bedd4d71b850b928686714f3c74987aced96858048d7f05f); + tempvar res = res * point + (0x1cf6b50644d7634d5b144cfdd1ff4f4285904b99b46a3c94eacdfe1e2d4b987); + tempvar res = res * point + (0x715d1152348922f2f7f84c0dbd3622bf0537cda35bb2dc2dc23bb5c6a103680); + tempvar res = res * point + (0x57c984e4e222596a86a941dbc9c79ef162d4a54ef8799cabaceeb5b194369db); + tempvar res = res * point + (0x3bf31fc435aed4a4412cfe877384108788f7b288c0644c5f2314977430c3576); + tempvar res = res * point + (0x6ce272c192cbade0ddd78c1075130b0d2dcd811b14f85eef96aba85d4c99ddc); + tempvar res = res * point + (0x38d10cd0c01529a85ec684600e23388d6d4f123c20cdeb6c6f2e4b5ab6739b6); + tempvar res = res * point + (0x27e4c27271112cacc354a0ede4e3cf78b16a52a77c3cce55deffe36152a3d76); + tempvar res = res * point + (0x22701b06baaaeab34fc2b47969c12262b49396f2fb24f5d9802c38244c4b085); + tempvar res = res * point + (0x3615d3b373ca26658a92cb1f979790b25cfa37f9c203d18c6abc0dd7e1276c0); + tempvar res = res * point + (0x41eb54e16fa27062d52699248f4bdfe254e5d96302d92721efeccf4745da594); + tempvar res = res * point + (0x68000000000000dd00000000000000000000000000000001444444444444445); + return (res=res); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/recursive/public_verify.cairo b/src/starkware/cairo/stark_verifier/air/layouts/recursive/public_verify.cairo new file mode 100644 index 00000000..e63f8e7e --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/recursive/public_verify.cairo @@ -0,0 +1,114 @@ +from starkware.cairo.common.math import assert_le, assert_nn, assert_nn_le +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layouts.recursive.autogenerated import ( + BITWISE__RATIO, + CPU_COMPONENT_HEIGHT, + KECCAK__RATIO, + LAYOUT_CODE, + PEDERSEN_BUILTIN_RATIO, + RC_BUILTIN_RATIO, +) +from starkware.cairo.stark_verifier.air.public_input import PublicInput, SegmentInfo +from starkware.cairo.stark_verifier.air.public_memory import AddrValue +from starkware.cairo.stark_verifier.core.domains import StarkDomains + +const MAX_LOG_N_STEPS = 50; +const MAX_RANGE_CHECK = 2 ** 16 - 1; + +namespace segments { + const PROGRAM = 0; + const EXECUTION = 1; + const OUTPUT = 2; + const PEDERSEN = 3; + const RANGE_CHECK = 4; + const BITWISE = 5; + const KECCAK = 6; + const N_SEGMENTS = 7; +} + +const INITIAL_PC = 1; +const FINAL_PC = INITIAL_PC + 4; + +// Returns a zero-terminated list of builtins supported by this layout. +func get_layout_builtins() -> (n_builtins: felt, builtins: felt*) { + let (builtins_address) = get_label_location(data); + let n_builtins = 5; + assert builtins_address[n_builtins] = 0; + return (n_builtins=n_builtins, builtins=builtins_address); + + data: + dw 'output'; + dw 'pedersen'; + dw 'range_check'; + dw 'bitwise'; + dw 'keccak'; + dw 0; +} + +// Verifies that the public input represents a valid Cairo statement: there exists a memory +// assignment and a valid corresponding program trace satisfying the public memory requirements. +// +// This function verifies that: +// * The 16-bit range-checks are properly configured (0 <= rc_min <= rc_max < 2^16). +// * The layout is valid. +// * The segments for the builtins do not exceed their maximum length (thus, +// when these builtins are properly used in the program, they will function correctly). +// +// This function DOES NOT verify anything regarding the public memory. This should be verified +// by the user. In particular, it is not validated that: +// * [initial_fp - 2] = initial_fp, which is required to guarantee the "safe call" +// feature (that is, all "call" instructions will return, even if the called function is +// malicious). It guarantees that it's not possible to create a cycle in the call stack. +// * the arguments and return values for main() are properly set (e.g., the segment +// pointers). +// * the requested program is loaded, starting from initial_pc. +// * final_pc points to the end of the program. +// * program output is valid in any sense. +// * The continuous pages are consistent. See public_memory.cairo. +func public_input_validate{range_check_ptr}( + air: felt*, public_input: PublicInput*, stark_domains: StarkDomains* +) { + assert_nn_le(public_input.log_n_steps, MAX_LOG_N_STEPS); + let (n_steps) = pow(2, public_input.log_n_steps); + assert n_steps * CPU_COMPONENT_HEIGHT = stark_domains.trace_domain_size; + + assert_le(0, public_input.rc_min); + assert_le(public_input.rc_min, public_input.rc_max); + assert_le(public_input.rc_max, MAX_RANGE_CHECK); + + assert public_input.layout = LAYOUT_CODE; + + // Segments. + tempvar n_output_uses = ( + public_input.segments[segments.OUTPUT].stop_ptr - + public_input.segments[segments.OUTPUT].begin_addr); + assert_nn(n_output_uses); + + assert public_input.n_segments = segments.N_SEGMENTS; + tempvar n_pedersen_copies = n_steps / PEDERSEN_BUILTIN_RATIO; + tempvar n_pedersen_uses = ( + public_input.segments[segments.PEDERSEN].stop_ptr - + public_input.segments[segments.PEDERSEN].begin_addr) / 3; + // Note that the following call implies that n_steps is divisible by PEDERSEN_BUILTIN_RATIO. + assert_nn_le(n_pedersen_uses, n_pedersen_copies); + + tempvar n_range_check_copies = n_steps / RC_BUILTIN_RATIO; + tempvar n_range_check_uses = ( + public_input.segments[segments.RANGE_CHECK].stop_ptr - + public_input.segments[segments.RANGE_CHECK].begin_addr); + assert_nn_le(n_range_check_uses, n_range_check_copies); + + tempvar n_bitwise_copies = n_steps / BITWISE__RATIO; + tempvar n_bitwise_uses = ( + public_input.segments[segments.BITWISE].stop_ptr - + public_input.segments[segments.BITWISE].begin_addr) / 5; + assert_nn_le(n_bitwise_uses, n_bitwise_copies); + + tempvar n_keccak_copies = n_steps / KECCAK__RATIO; + tempvar n_keccak_uses = ( + public_input.segments[segments.KECCAK].stop_ptr - + public_input.segments[segments.KECCAK].begin_addr) / 16; + assert_nn_le(n_keccak_uses, n_keccak_copies); + return (); +} diff --git a/src/starkware/cairo/stark_verifier/air/layouts/recursive/verify.cairo b/src/starkware/cairo/stark_verifier/air/layouts/recursive/verify.cairo new file mode 100644 index 00000000..15cab0e1 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/layouts/recursive/verify.cairo @@ -0,0 +1,71 @@ +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.hash import HashBuiltin +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.air.layout import AirWithLayout, Layout +from starkware.cairo.stark_verifier.air.layouts.recursive.autogenerated import ( + CONSTRAINT_DEGREE, + MASK_SIZE, + N_CONSTRAINTS, + N_INTERACTION_COLUMNS, + N_ORIGINAL_COLUMNS, + eval_oods_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.recursive.composition import ( + traces_eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.air.layouts.recursive.global_values import InteractionElements +from starkware.cairo.stark_verifier.air.layouts.recursive.public_verify import public_input_validate +from starkware.cairo.stark_verifier.air.oods import eval_oods_boundary_poly_at_points +from starkware.cairo.stark_verifier.air.public_input import public_input_hash +from starkware.cairo.stark_verifier.air.traces import ( + traces_commit, + traces_config_validate, + traces_decommit, +) +from starkware.cairo.stark_verifier.core.air_interface import AirInstance +from starkware.cairo.stark_verifier.core.stark import StarkProof, verify_stark_proof + +// Builds an AirInstance object to use for STARK verification. See AirInstance at +// air_interface.cairo. +func build_air() -> (air: AirWithLayout*) { + let (arg_public_input_hash) = get_label_location(public_input_hash); + let (arg_public_input_validate) = get_label_location(public_input_validate); + let (arg_traces_config_validate) = get_label_location(traces_config_validate); + let (arg_traces_commit) = get_label_location(traces_commit); + let (arg_traces_decommit) = get_label_location(traces_decommit); + let (arg_traces_eval_composition_polynomial) = get_label_location( + traces_eval_composition_polynomial + ); + let (arg_eval_oods_boundary_poly_at_points) = get_label_location( + eval_oods_boundary_poly_at_points + ); + let (arg_eval_oods_polynomial) = get_label_location(eval_oods_polynomial); + + tempvar air = new AirWithLayout(air=AirInstance( + public_input_hash=arg_public_input_hash, + public_input_validate=arg_public_input_validate, + traces_config_validate=arg_traces_config_validate, + traces_commit=arg_traces_commit, + traces_decommit=arg_traces_decommit, + traces_eval_composition_polynomial=arg_traces_eval_composition_polynomial, + eval_oods_boundary_poly_at_points=arg_eval_oods_boundary_poly_at_points, + n_constraints=N_CONSTRAINTS, + constraint_degree=CONSTRAINT_DEGREE, + mask_size=MASK_SIZE, + ), + layout=Layout( + eval_oods_polynomial=arg_eval_oods_polynomial, + n_original_columns=N_ORIGINAL_COLUMNS, + n_interaction_columns=N_INTERACTION_COLUMNS, + n_interaction_elements=InteractionElements.SIZE, + ), + ); + return (air=air); +} + +func verify_proof{range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*}( + proof: StarkProof*, security_bits: felt +) -> () { + let (air) = build_air(); + return verify_stark_proof(air=&air.air, proof=proof, security_bits=security_bits); +} diff --git a/src/starkware/cairo/stark_verifier/air/oods.cairo b/src/starkware/cairo/stark_verifier/air/oods.cairo new file mode 100644 index 00000000..40e12119 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/oods.cairo @@ -0,0 +1,103 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.memcpy import memcpy +from starkware.cairo.stark_verifier.air.layout import ( + AirWithLayout, + Layout, + OodsGlobalValues, + eval_oods_polynomial, +) +from starkware.cairo.stark_verifier.air.traces import ( + CONSTRAINT_DEGREE, + N_COMPOSITION_COLUMNS, + TracesDecommitment, +) +from starkware.cairo.stark_verifier.core.air_interface import OodsEvaluationInfo +from starkware.cairo.stark_verifier.core.table_commitment import TableDecommitment + +// Evaluates the OODS polynomial at a list of points, given a decommitment of the traces, and the +// composition commitment. +func eval_oods_boundary_poly_at_points{range_check_ptr}( + air: AirWithLayout*, + eval_info: OodsEvaluationInfo*, + n_points: felt, + points: felt*, + decommitment: TracesDecommitment*, + composition_decommitment: TableDecommitment*, +) -> (evaluations: felt*) { + alloc_locals; + local n_original_columns = air.layout.n_original_columns; + assert decommitment.original.n_values = n_points * n_original_columns; + local n_interaction_columns = air.layout.n_interaction_columns; + assert decommitment.interaction.n_values = n_points * n_interaction_columns; + assert composition_decommitment.n_values = n_points * N_COMPOSITION_COLUMNS; + let (evaluations: felt*) = alloc(); + eval_oods_boundary_poly_at_points_inner( + layout=&air.layout, + eval_info=eval_info, + n_points=n_points, + points=points, + n_original_columns=n_original_columns, + original_values=decommitment.original.values, + interaction_values=decommitment.interaction.values, + composition_values=composition_decommitment.values, + evaluations=evaluations, + ); + return (evaluations=evaluations); +} + +func eval_oods_boundary_poly_at_points_inner{range_check_ptr}( + layout: Layout*, + eval_info: OodsEvaluationInfo*, + n_points: felt, + points: felt*, + n_original_columns: felt, + original_values: felt*, + interaction_values: felt*, + composition_values: felt*, + evaluations: felt*, +) { + alloc_locals; + if (n_points == 0) { + return (); + } + + // Concatenate the values from the 3 traces into a single array of column_values. + local n_interaction_columns = layout.n_interaction_columns; + let (column_values) = alloc(); + memcpy(column_values, original_values, n_original_columns); + memcpy(column_values + n_original_columns, interaction_values, n_interaction_columns); + memcpy( + column_values + n_original_columns + n_interaction_columns, + composition_values, + N_COMPOSITION_COLUMNS, + ); + + // In general, the oods polynomial might use global expressions. In Cairo's air, + // it doesn't. + let global_values = cast(0, OodsGlobalValues*); + + // Call autogenerated evaluation function. + let (res) = eval_oods_polynomial( + layout=layout, + column_values=column_values, + oods_values=eval_info.oods_values, + constraint_coefficients=eval_info.constraint_coefficients, + point=points[0], + oods_point=eval_info.oods_point, + trace_generator=eval_info.trace_generator, + global_values=global_values, + ); + assert evaluations[0] = res; + + return eval_oods_boundary_poly_at_points_inner( + layout=layout, + eval_info=eval_info, + n_points=n_points - 1, + points=&points[1], + n_original_columns=n_original_columns, + original_values=&original_values[n_original_columns], + interaction_values=&interaction_values[n_interaction_columns], + composition_values=&composition_values[N_COMPOSITION_COLUMNS], + evaluations=&evaluations[1], + ); +} diff --git a/src/starkware/cairo/stark_verifier/air/params.cairo b/src/starkware/cairo/stark_verifier/air/params.cairo new file mode 100644 index 00000000..23d6ee01 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/params.cairo @@ -0,0 +1,2 @@ +const CONSTRAINT_DEGREE = 2; +const N_COMPOSITION_COLUMNS = CONSTRAINT_DEGREE; diff --git a/src/starkware/cairo/stark_verifier/air/parser.py b/src/starkware/cairo/stark_verifier/air/parser.py new file mode 100644 index 00000000..4b15b243 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/parser.py @@ -0,0 +1,289 @@ +import itertools +import re +from typing import List, Sequence + +from starkware.cairo.common.structs import CairoStructFactory +from starkware.cairo.lang.compiler.identifier_definition import ConstDefinition +from starkware.cairo.lang.compiler.identifier_manager import IdentifierManager +from starkware.cairo.lang.compiler.scoped_name import ScopedName +from starkware.cairo.lang.instances import recursive_instance as INSTANCE +from starkware.cairo.lang.vm.air_public_input import PublicInput, extract_z_and_alpha +from starkware.cairo.stark_verifier.air.utils import public_input_to_cairo +from starkware.python.math_utils import safe_log2 +from starkware.python.utils import safe_zip + +COMPONENT_HEIGHT = 16 +SUPPORTED_LAYOUTS = ["bitwise", "dex", "perpetual_with_bitwise", "recursive"] +ADDITIONAL_IMPORTS = [ + "starkware.cairo.stark_verifier.air.config.TracesConfig", + "starkware.cairo.stark_verifier.air.public_input.PublicInput", + "starkware.cairo.stark_verifier.air.public_input.SegmentInfo", + "starkware.cairo.stark_verifier.air.public_memory.ContinuousPageHeader", + "starkware.cairo.stark_verifier.air.traces.TracesDecommitment", + "starkware.cairo.stark_verifier.air.traces.TracesUnsentCommitment", + "starkware.cairo.stark_verifier.air.traces.TracesWitness", + "starkware.cairo.stark_verifier.core.config.StarkConfig", + "starkware.cairo.stark_verifier.core.fri.config.FriConfig", + "starkware.cairo.stark_verifier.core.fri.fri.FriLayerWitness", + "starkware.cairo.stark_verifier.core.fri.fri.FriUnsentCommitment", + "starkware.cairo.stark_verifier.core.fri.fri.FriWitness", + "starkware.cairo.stark_verifier.core.proof_of_work.ProofOfWorkConfig", + "starkware.cairo.stark_verifier.core.proof_of_work.ProofOfWorkUnsentCommitment", + "starkware.cairo.stark_verifier.core.stark.StarkProof", + "starkware.cairo.stark_verifier.core.stark.StarkUnsentCommitment", + "starkware.cairo.stark_verifier.core.stark.StarkWitness", + "starkware.cairo.stark_verifier.core.table_commitment.TableCommitmentConfig", + "starkware.cairo.stark_verifier.core.table_commitment.TableCommitmentWitness", + "starkware.cairo.stark_verifier.core.table_commitment.TableDecommitment", + "starkware.cairo.stark_verifier.core.vector_commitment.VectorCommitmentConfig", + "starkware.cairo.stark_verifier.core.vector_commitment.VectorCommitmentWitness", +] + + +def extract_annotations(annotations: Sequence[str], prefix: str, kind: str) -> List[int]: + """ + Extracts annotations from a proof JSON with a specific prefix, of a specific kind. + Examples for prefix: "STARK/Original/Commit on Trace". + Examples for kind: "Data", "Hash", "FieldElement", "Field Elements". + """ + res: List[int] = [] + pattern = f"P->V\\[(\\d+):(\\d+)\\]: /cpu air/{prefix}: .*{kind}\\((.+)\\)" + for line in annotations: + match = re.match(pattern=pattern, string=line) + if match is None: + continue + _from_pos, _to_pos, str_value = match.groups() + if kind == "Field Elements": + res += [int(x, 16) for x in str_value.split(",")] + continue + value = int(str_value, 16) + if kind == "Hash": + # Make sure hash is truncated. + assert value % 2**96 == 0 + res.append(value) + return res + + +def to_uint256(x): + return (x % (2**128), x >> 128) + + +def parse_proof(identifiers: IdentifierManager, proof_json: dict): + """ + Generates a Cairo StarkProof struct from a proof JSON. + """ + + structs = CairoStructFactory( + identifiers=identifiers, additional_imports=ADDITIONAL_IMPORTS + ).structs + + def annotations(prefix: str, kind: str): + return extract_annotations(proof_json["annotations"], prefix, kind) + + # Parse JSON. + public_input: PublicInput = PublicInput.Schema().load(proof_json["public_input"]) + z, alpha = extract_z_and_alpha(proof_json["annotations"]) + cairo_public_input = public_input_to_cairo(structs, public_input=public_input, z=z, alpha=alpha) + + # Extract elements from annotations. + (original_commitment_hash,) = annotations("STARK/Original/Commit on Trace", "Hash") + (interaction_commitment_hash,) = annotations("STARK/Interaction/Commit on Trace", "Hash") + (composition_commitment_hash,) = annotations( + "STARK/Out Of Domain Sampling/Commit on Trace", "Hash" + ) + oods_values = annotations("STARK/Out Of Domain Sampling/OODS values", "Field Element") + fri_layers_commitments = [ + x >> 96 for x in annotations("STARK/FRI/Commitment/Layer [0-9]+", "Hash") + ] + fri_last_layer_coefficients = annotations("STARK/FRI/Commitment/Last Layer", "Field Elements") + (proof_of_work_nonce,) = annotations("STARK/FRI/Proof of Work", "Data") + + def get_authentications(prefix: str): + # Collect authentication (siblings) values. + # In the case of 1 column, the first authentication values come as Data. + return annotations(prefix, "Data") + annotations(prefix, "Hash") + + original_witness_leaves = annotations( + "STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0", "Field Element" + ) + original_witness_authentications = get_authentications( + "STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 0" + ) + interaction_witness_leaves = annotations( + "STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1", "Field Element" + ) + interaction_witness_authentications = get_authentications( + "STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 1" + ) + composition_witness_leaves = annotations( + "STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2", "Field Element" + ) + composition_witness_authentications = get_authentications( + "STARK/FRI/Decommitment/Layer 0/Virtual Oracle/Trace 2" + ) + + fri_step_list = proof_json["proof_parameters"]["stark"]["fri"]["fri_step_list"] + n_fri_layers = len(fri_step_list) + fri_witnesses = [] + for i in range(1, n_fri_layers): + leaves = annotations(f"STARK/FRI/Decommitment/Layer {i}", "Field Element") + authentications = annotations(f"STARK/FRI/Decommitment/Layer {i}", "Hash") + fri_witnesses.append( + structs.FriLayerWitness( + n_leaves=len(leaves), + leaves=leaves, + table_witness=structs.TableCommitmentWitness( + vector=structs.VectorCommitmentWitness( + n_authentications=len(authentications), + authentications=list(itertools.chain(*map(to_uint256, authentications))), + ), + ), + ) + ) + + # Extract details for config. + effective_component_height = COMPONENT_HEIGHT * INSTANCE.cpu_component_step + log_trace_domain_size = safe_log2(effective_component_height * public_input.n_steps) + log_n_cosets = proof_json["proof_parameters"]["stark"]["log_n_cosets"] + log_last_layer_degree_bound = safe_log2( + proof_json["proof_parameters"]["stark"]["fri"]["last_layer_degree_bound"] + ) + + # FRI layers. + assert len(fri_layers_commitments) == n_fri_layers - 1 # Inner layers. + + log_eval_domain_size = log_trace_domain_size + log_n_cosets + layer_log_sizes = [log_eval_domain_size] + for layer_step in fri_step_list: + layer_log_sizes.append(layer_log_sizes[-1] - layer_step) + assert len(layer_log_sizes) == n_fri_layers + 1 # Inner layers, input and last layer. + assert layer_log_sizes[-1] == log_last_layer_degree_bound + log_n_cosets + assert len(fri_last_layer_coefficients) == 2**log_last_layer_degree_bound + + def get_const_value(name: str): + res = identifiers.root.get(ScopedName.from_string(name)).identifier_definition + assert isinstance(res, ConstDefinition) + return res.value + + layout_name = public_input.layout + module_name = f"starkware.cairo.stark_verifier.air.layouts.{layout_name}.autogenerated" + N_ORIGINAL_COLUMNS = get_const_value(f"{module_name}.N_ORIGINAL_COLUMNS") + N_INTERACTION_COLUMNS = get_const_value(f"{module_name}.N_INTERACTION_COLUMNS") + CONSTRAINT_DEGREE = get_const_value(f"{module_name}.CONSTRAINT_DEGREE") + # Build the Cairo structs. + stark_config = structs.StarkConfig( + traces=structs.TracesConfig( + original=structs.TableCommitmentConfig( + n_columns=N_ORIGINAL_COLUMNS, + vector=structs.VectorCommitmentConfig( + height=log_eval_domain_size, + ), + ), + interaction=structs.TableCommitmentConfig( + n_columns=N_INTERACTION_COLUMNS, + vector=structs.VectorCommitmentConfig( + height=log_eval_domain_size, + ), + ), + ), + composition=structs.TableCommitmentConfig( + n_columns=CONSTRAINT_DEGREE, + vector=structs.VectorCommitmentConfig( + height=log_eval_domain_size, + ), + ), + fri=structs.FriConfig( + log_input_size=layer_log_sizes[0], + n_layers=n_fri_layers, + inner_layers=list( + itertools.chain( + *( + structs.TableCommitmentConfig( + n_columns=2**layer_steps, + vector=structs.VectorCommitmentConfig( + height=layer_log_rows, + ), + ) + for layer_steps, layer_log_rows in safe_zip( + fri_step_list[1:], layer_log_sizes[2:] + ) + ) + ) + ), + fri_step_sizes=fri_step_list, + log_last_layer_degree_bound=log_last_layer_degree_bound, + ), + proof_of_work=structs.ProofOfWorkConfig( + n_bits=proof_json["proof_parameters"]["stark"]["fri"]["proof_of_work_bits"], + ), + log_trace_domain_size=log_trace_domain_size, + n_queries=proof_json["proof_parameters"]["stark"]["fri"]["n_queries"], + log_n_cosets=log_n_cosets, + ) + stark_unsent_commitment = structs.StarkUnsentCommitment( + traces=structs.TracesUnsentCommitment( + original=original_commitment_hash >> 96, + interaction=interaction_commitment_hash >> 96, + ), + composition=composition_commitment_hash >> 96, + oods_values=oods_values, + fri=structs.FriUnsentCommitment( + inner_layers=fri_layers_commitments, last_layer_coefficients=fri_last_layer_coefficients + ), + proof_of_work=structs.ProofOfWorkUnsentCommitment( + nonce=proof_of_work_nonce, + ), + ) + stark_witness = structs.StarkWitness( + traces_decommitment=structs.TracesDecommitment( + original=structs.TableDecommitment( + n_values=len(original_witness_leaves), + values=original_witness_leaves, + ), + interaction=structs.TableDecommitment( + n_values=len(interaction_witness_leaves), + values=interaction_witness_leaves, + ), + ), + traces_witness=structs.TracesWitness( + original=structs.TableCommitmentWitness( + vector=structs.VectorCommitmentWitness( + n_authentications=len(original_witness_authentications), + authentications=list( + itertools.chain(*map(to_uint256, original_witness_authentications)) + ), + ), + ), + interaction=structs.TableCommitmentWitness( + vector=structs.VectorCommitmentWitness( + n_authentications=len(interaction_witness_authentications), + authentications=list( + itertools.chain(*map(to_uint256, interaction_witness_authentications)) + ), + ), + ), + ), + composition_decommitment=structs.TableDecommitment( + n_values=len(composition_witness_leaves), + values=composition_witness_leaves, + ), + composition_witness=structs.TableCommitmentWitness( + vector=structs.VectorCommitmentWitness( + n_authentications=len(composition_witness_authentications), + authentications=list( + itertools.chain(*map(to_uint256, composition_witness_authentications)) + ), + ), + ), + fri_witness=structs.FriWitness( + layers=list(itertools.chain(*fri_witnesses)), + ), + ) + proof = structs.StarkProof( + config=stark_config, + public_input=cairo_public_input, + unsent_commitment=stark_unsent_commitment, + witness=stark_witness, + ) + + return proof diff --git a/src/starkware/cairo/stark_verifier/air/public_input.cairo b/src/starkware/cairo/stark_verifier/air/public_input.cairo new file mode 100644 index 00000000..5aa23490 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/public_input.cairo @@ -0,0 +1,157 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_blake2s.blake2s import ( + blake2s_add_felt, + blake2s_add_felts, + blake2s_add_uint256_bigend, + blake2s_bigend, + blake2s_felts, +) +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.hash import HashBuiltin +from starkware.cairo.common.hash_state import hash_finalize, hash_init, hash_update +from starkware.cairo.common.math import assert_le, assert_nn, assert_nn_le +from starkware.cairo.common.pow import pow +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.air.public_memory import ( + AddrValue, + ContinuousPageHeader, + get_continuous_pages_product, + get_page_product, +) + +struct PublicInput { + // Base 2 log of the number of steps. + log_n_steps: felt, + // Minimum value of range check component. + rc_min: felt, + // Maximum value of range check component. + rc_max: felt, + // Layout ID. + layout: felt, + // Memory segment infos array. + n_segments: felt, + segments: SegmentInfo*, + + // Public memory section. + // Address and value of the padding memory access. + padding_addr: felt, + padding_value: felt, + + // Main page. + main_page_len: felt, + main_page: AddrValue*, + + // Page header array. + n_continuous_pages: felt, + continuous_page_headers: ContinuousPageHeader*, +} + +struct SegmentInfo { + // Start address of the memory segment. + begin_addr: felt, + // Stop pointer of the segment - not necessarily the end of the segment. + stop_ptr: felt, +} + +// Computes the hash of the public input, which is used as the initial seed for the Fiat-Shamir +// heuristic. +func public_input_hash{ + range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, blake2s_ptr: felt* +}(air: AirWithLayout*, public_input: PublicInput*) -> (res: Uint256) { + alloc_locals; + + // Main page hash. + let (hash_state_ptr) = hash_init(); + let (hash_state_ptr) = hash_update{hash_ptr=pedersen_ptr}( + hash_state_ptr=hash_state_ptr, + data_ptr=public_input.main_page, + data_length=public_input.main_page_len * AddrValue.SIZE, + ); + let (main_page_hash) = hash_finalize{hash_ptr=pedersen_ptr}(hash_state_ptr=hash_state_ptr); + + let (data: felt*) = alloc(); + let data_start = data; + with data { + blake2s_add_felt(num=public_input.log_n_steps, bigend=1); + blake2s_add_felt(num=public_input.rc_min, bigend=1); + blake2s_add_felt(num=public_input.rc_max, bigend=1); + blake2s_add_felt(num=public_input.layout, bigend=1); + // n_segments is not written, it is assumed to be fixed. + blake2s_add_felts( + n_elements=public_input.n_segments * SegmentInfo.SIZE, + elements=public_input.segments, + bigend=1, + ); + blake2s_add_felt(num=public_input.padding_addr, bigend=1); + blake2s_add_felt(num=public_input.padding_value, bigend=1); + blake2s_add_felt(num=1 + public_input.n_continuous_pages, bigend=1); + + // Main page. + blake2s_add_felt(num=public_input.main_page_len, bigend=1); + blake2s_add_felt(num=main_page_hash, bigend=1); + + // Add the rest of the pages. + add_continuous_page_headers( + n_pages=public_input.n_continuous_pages, pages=public_input.continuous_page_headers + ); + } + // Each word in data is 4 bytes. This is specific to the blake implementation. + let n_bytes = (data - data_start) * 4; + let (res) = blake2s_bigend(data=data_start, n_bytes=n_bytes); + return (res=res); +} + +func add_continuous_page_headers{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, data: felt*}( + n_pages: felt, pages: ContinuousPageHeader* +) { + if (n_pages == 0) { + return (); + } + + blake2s_add_felt(num=pages.start_address, bigend=1); + blake2s_add_felt(num=pages.size, bigend=1); + blake2s_add_uint256_bigend(pages.hash); + + return add_continuous_page_headers(n_pages=n_pages - 1, pages=&pages[1]); +} + +// Returns the product of all public memory cells. +func get_public_memory_product(public_input: PublicInput*, z: felt, alpha: felt) -> ( + res: felt, total_length: felt +) { + alloc_locals; + // Compute total product. + let (main_page_prod) = get_page_product( + z=z, alpha=alpha, data_len=public_input.main_page_len, data=public_input.main_page + ); + let (continuous_pages_prod, continuous_pages_total_length) = get_continuous_pages_product( + n_pages=public_input.n_continuous_pages, page_headers=public_input.continuous_page_headers + ); + return ( + res=main_page_prod * continuous_pages_prod, + total_length=continuous_pages_total_length + public_input.main_page_len, + ); +} + +// Returns the ratio between the product of all public memory cells and z^|public_memory|. +// This is the value that needs to be at the memory__multi_column_perm__perm__public_memory_prod +// member expression. +func get_public_memory_product_ratio{range_check_ptr}( + public_input: PublicInput*, z: felt, alpha: felt, public_memory_column_size: felt +) -> (res: felt) { + alloc_locals; + + // Compute total product. + let (pages_product, total_length) = get_public_memory_product( + public_input=public_input, z=z, alpha=alpha + ); + + // Pad and divide. + let (numerator) = pow(z, public_memory_column_size); + tempvar padded_value = z - (public_input.padding_addr + alpha * public_input.padding_value); + assert_le(total_length, public_memory_column_size); + let (denominator_pad) = pow(padded_value, public_memory_column_size - total_length); + + return (res=numerator / pages_product / denominator_pad); +} diff --git a/src/starkware/cairo/stark_verifier/air/public_memory.cairo b/src/starkware/cairo/stark_verifier/air/public_memory.cairo new file mode 100644 index 00000000..d552710f --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/public_memory.cairo @@ -0,0 +1,49 @@ +from starkware.cairo.common.uint256 import Uint256 + +// Information about a continuous page (a consecutive section of the public memory).. +// Each such page must be verified externally to the verifier: +// hash = Hash( +// memory[start_address], memory[start_address + 1], ..., memory[start_address + size - 1]). +// prod = prod_i (z - ((start_address + i) + alpha * (memory[start_address + i])). +// z, alpha are taken from the interaction values, and can be obtained directly from the +// StarkProof object. +// z = interaction_elements.memory__multi_column_perm__perm__interaction_elm. +// alpha = interaction_elements.memory__multi_column_perm__hash_interaction_elm0. +struct ContinuousPageHeader { + // Start address. + start_address: felt, + // Size of the page. + size: felt, + // Hash of the page. + hash: Uint256, + // Cumulative product of the page. + prod: felt, +} + +struct AddrValue { + address: felt, + value: felt, +} + +// Returns the product of (z - (addr + alpha * val)) over a single page. +func get_page_product(z: felt, alpha: felt, data_len: felt, data: AddrValue*) -> (res: felt) { + if (data_len == 0) { + return (res=1); + } + let (res) = get_page_product(z=z, alpha=alpha, data_len=data_len - 1, data=&data[1]); + let val = z - (data.address + alpha * data.value); + return (res=res * val); +} + +// Returns the product of all continuous pages. +func get_continuous_pages_product(n_pages: felt, page_headers: ContinuousPageHeader*) -> ( + res: felt, total_length: felt +) { + if (n_pages == 0) { + return (res=1, total_length=0); + } + let (res, total_length) = get_continuous_pages_product( + n_pages=n_pages - 1, page_headers=&page_headers[1] + ); + return (res=res * page_headers.prod, total_length=total_length + page_headers.size); +} diff --git a/src/starkware/cairo/stark_verifier/air/stark_test.py b/src/starkware/cairo/stark_verifier/air/stark_test.py new file mode 100644 index 00000000..bca56e03 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/stark_test.py @@ -0,0 +1,49 @@ +import json +import os + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.common.validate_utils import validate_builtin_usage +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files +from starkware.cairo.lang.compiler.program import Program +from starkware.cairo.lang.compiler.scoped_name import ScopedName +from starkware.cairo.stark_verifier.air.parser import parse_proof + +PROOF_FILE = os.path.join(os.path.dirname(__file__), "example_proof.json") + + +def get_program_for_layout(layout: str) -> Program: + return compile_cairo_files( + [os.path.join(os.path.dirname(__file__), f"layouts/{layout}/verify.cairo")], + prime=DEFAULT_PRIME, + debug_info=True, + main_scope=ScopedName.from_string( + f"starkware.cairo.stark_verifier.air.layouts.{layout}.verify" + ), + ) + + +def run_test(proof_file: str, layout: str): + with open(proof_file, "r") as fp: + proof_json = json.load(fp) + program = get_program_for_layout(layout) + proof = parse_proof(identifiers=program.identifiers, proof_json=proof_json) + + runner = CairoFunctionRunner(program, layout="small") + runner.run( + "verify_proof", + range_check_ptr=runner.range_check_builtin.base, + pedersen_ptr=runner.pedersen_builtin.base, + bitwise_ptr=runner.bitwise_builtin.base, + proof=proof, + security_bits=80, + ) + print("Steps:", runner.vm.current_step) + (range_check_ptr, pedersen_ptr, bitwise_ptr) = runner.get_return_values(3) + validate_builtin_usage(runner.range_check_builtin, range_check_ptr) + validate_builtin_usage(runner.pedersen_builtin, pedersen_ptr) + validate_builtin_usage(runner.bitwise_builtin, bitwise_ptr) + + +def test_stark(): + run_test(proof_file=PROOF_FILE, layout="recursive") diff --git a/src/starkware/cairo/stark_verifier/air/traces.cairo b/src/starkware/cairo/stark_verifier/air/traces.cairo new file mode 100644 index 00000000..4d48e84f --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/traces.cairo @@ -0,0 +1,130 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.stark_verifier.air.config import TracesConfig, traces_config_validate +from starkware.cairo.stark_verifier.air.layout import AirWithLayout +from starkware.cairo.stark_verifier.air.public_input import PublicInput +from starkware.cairo.stark_verifier.core.channel import ( + Channel, + ChannelUnsentFelt, + random_felts_to_prover, +) +from starkware.cairo.stark_verifier.core.table_commitment import ( + TableCommitment, + TableCommitmentConfig, + TableCommitmentWitness, + TableDecommitment, + TableUnsentCommitment, + table_commit, + table_decommit, +) + +// A protocol component (see stark.cairo for details about protocol components) for the traces +// of the CPU AIR. +// This component is commonly right before the FRI component. +// In this case: +// n_queries = n_fri_queries * 2^first_fri_step. +// decommitment.original.n_queries = n_original_columns * n_queries. +// decommitment.interaction.n_queries = n_interaction_columns * n_queries. + +// Columns sizes. +const CONSTRAINT_DEGREE = 2; +const N_COMPOSITION_COLUMNS = CONSTRAINT_DEGREE; + +// Commitment values for the Traces component. Used to generate a commitment by "reading" these +// values from the channel. +struct TracesUnsentCommitment { + original: TableUnsentCommitment, + interaction: TableUnsentCommitment, +} + +// Commitment for the Traces component. +struct TracesCommitment { + public_input: PublicInput*, + // Commitment to the first trace. + original: TableCommitment*, + // The interaction elements that were sent to the prover after the first trace commitment (e.g. + // memory interaction). + interaction_elements: felt*, + // Commitment to the second (interaction) trace. + interaction: TableCommitment*, +} + +// Responses for queries to the AIR commitment. +// The queries are usually generated by the next component down the line (e.g. FRI). +struct TracesDecommitment { + // Responses for queries to the original trace. + original: TableDecommitment*, + // Responses for queries to the interaction trace. + interaction: TableDecommitment*, +} + +// A witness for a decommitment of the AIR traces over queries. +struct TracesWitness { + original: TableCommitmentWitness*, + interaction: TableCommitmentWitness*, +} + +// Reads the traces commitment from the channel. +// Returns the commitment, along with GlobalValue required to evaluate the constraint polynomial. +func traces_commit{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}( + air: AirWithLayout*, + public_input: PublicInput*, + unsent_commitment: TracesUnsentCommitment*, + config: TracesConfig*, +) -> (commitment: TracesCommitment*) { + alloc_locals; + + // Read original commitment. + let (original_commitment) = table_commit( + unsent_commitment=unsent_commitment.original, config=config.original + ); + + // Generate interaction elements for the first interaction. + let (interaction_elements: felt*) = alloc(); + random_felts_to_prover( + n_elements=air.layout.n_interaction_elements, elements=interaction_elements + ); + + // Read interaction commitment. + let (interaction_commitment) = table_commit( + unsent_commitment=unsent_commitment.interaction, config=config.interaction + ); + + return ( + commitment=new TracesCommitment( + public_input=public_input, + original=original_commitment, + interaction_elements=interaction_elements, + interaction=interaction_commitment, + ), + ); +} + +// Verifies a decommitment for the traces at the query indices. +// decommitment - holds the commited values of the leaves at the query_indices. +func traces_decommit{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + air: AirWithLayout*, + n_queries: felt, + queries: felt*, + commitment: TracesCommitment*, + decommitment: TracesDecommitment*, + witness: TracesWitness*, +) { + table_decommit( + commitment=commitment.original, + n_queries=n_queries, + queries=queries, + decommitment=decommitment.original, + witness=witness.original, + ); + table_decommit( + commitment=commitment.interaction, + n_queries=n_queries, + queries=queries, + decommitment=decommitment.interaction, + witness=witness.interaction, + ); + return (); +} diff --git a/src/starkware/cairo/stark_verifier/air/utils.py b/src/starkware/cairo/stark_verifier/air/utils.py new file mode 100644 index 00000000..f642a6f2 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/air/utils.py @@ -0,0 +1,98 @@ +import itertools +from collections import defaultdict +from typing import Dict, List, Mapping, MutableMapping, Tuple + +from starkware.cairo.common.hash_state import compute_hash_on_elements +from starkware.cairo.lang.vm.air_public_input import ( + PublicInput, + PublicMemoryEntry, + get_pages_and_products, +) +from starkware.cairo.lang.vm.utils import sort_segments +from starkware.python.math_utils import safe_log2 + + +def compute_continuous_page_headers( + public_memory: List[PublicMemoryEntry], + z: int, + alpha: int, +) -> List[Tuple[int, int, int, int, int]]: + """ + Computes continuous page headers from a list of public memory entries. + Returns a list of tuples for each page: (start_address, size, hash_low, hash_high, product). + """ + start_address: Dict[int, int] = {} + size: MutableMapping[int, int] = defaultdict(int) + data: Mapping[int, List[int]] = defaultdict(list) + + _, page_prods = get_pages_and_products(public_memory=public_memory, z=z, alpha=alpha) + for access in public_memory: + start_address.setdefault(access.page, access.address) + if access.page == 0: + continue + + assert access.address == (start_address[access.page] + len(data[access.page])) + data[access.page].append(access.value) + size[access.page] += 1 + n_pages = 1 + len(size) + assert len(page_prods) == n_pages + + headers = [] + for i, page in enumerate(sorted(size), start=1): + assert i == page + hash_value = compute_hash_on_elements(data[page]) + headers.append( + ( + start_address[page], + size[page], + hash_value % 2**128, + hash_value >> 128, + page_prods[page], + ) + ) + + return headers + + +def get_main_page( + public_memory: List[PublicMemoryEntry], +) -> List[Tuple[int, int]]: + res = [] + for access in public_memory: + if access.page != 0: + continue + res.append((access.address, access.value)) + return res + + +def public_input_to_cairo(structs, public_input: PublicInput, z: int, alpha: int): + continuous_page_headers = compute_continuous_page_headers( + public_memory=public_input.public_memory, z=z, alpha=alpha + ) + main_page = get_main_page(public_memory=public_input.public_memory) + + memory_segments = sort_segments(public_input.memory_segments) + cairo_public_input = structs.PublicInput( + log_n_steps=safe_log2(public_input.n_steps), + rc_min=public_input.rc_min, + rc_max=public_input.rc_max, + layout=int.from_bytes(public_input.layout.encode("ascii"), "big"), + n_segments=len(public_input.memory_segments), + segments=list( + itertools.chain( + *( + structs.SegmentInfo(begin_addr=elm.begin_addr, stop_ptr=elm.stop_ptr) + for elm in memory_segments.values() + ) + ) + ), + # Public memory. + padding_addr=public_input.public_memory[0].address, + padding_value=public_input.public_memory[0].value, + main_page_len=len(main_page), + main_page=list(itertools.chain(*main_page)), + n_continuous_pages=len(continuous_page_headers), + continuous_page_headers=list(itertools.chain(*continuous_page_headers)), + ) + + return cairo_public_input diff --git a/src/starkware/cairo/stark_verifier/core/CMakeLists.txt b/src/starkware/cairo/stark_verifier/core/CMakeLists.txt new file mode 100644 index 00000000..91d0e7ff --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/CMakeLists.txt @@ -0,0 +1,52 @@ +add_subdirectory(fri) + +python_lib(starkware_cairo_stark_verifier_core_lib + PREFIX starkware/cairo/stark_verifier/core + FILES + air_interface.cairo + channel.cairo + proof_of_work.cairo + queries.cairo + table_commitment.cairo + utils.cairo + vector_commitment.cairo + + LIBS + cairo_common_lib +) + +python_lib(starkware_cairo_stark_verifier_core_stark_lib + PREFIX starkware/cairo/stark_verifier/core + FILES + config.cairo + domains.cairo + stark.cairo + + LIBS + cairo_common_lib + starkware_cairo_stark_verifier_core_fri_lib + starkware_cairo_stark_verifier_core_lib +) + +full_python_test(starkware_cairo_stark_verifier_core_test + PREFIX starkware/cairo/stark_verifier/core + PYTHON python3.9 + + FILES + channel_test.cairo + channel_test.py + merkle_test_data.json + proof_of_work_test.py + table_commitment_test.py + utils_test.py + vector_commitment_test.py + + LIBS + cairo_common_lib + cairo_common_validate_utils_lib + cairo_compile_lib + cairo_function_runner_lib + starkware_cairo_stark_verifier_core_lib + starkware_python_test_utils_lib + pip_pytest +) diff --git a/src/starkware/cairo/stark_verifier/core/__init__.py b/src/starkware/cairo/stark_verifier/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/starkware/cairo/stark_verifier/core/air_interface.cairo b/src/starkware/cairo/stark_verifier/core/air_interface.cairo new file mode 100644 index 00000000..86ba074d --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/air_interface.cairo @@ -0,0 +1,110 @@ +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.hash import HashBuiltin +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.stark_verifier.core.channel import Channel +from starkware.cairo.stark_verifier.core.domains import StarkDomains +from starkware.cairo.stark_verifier.core.table_commitment import TableDecommitment + +struct PublicInput { +} + +struct TracesConfig { +} + +struct TracesUnsentCommitment { +} + +struct TracesCommitment { +} + +struct TracesDecommitment { +} + +struct TracesWitness { +} + +struct OodsEvaluationInfo { + oods_values: felt*, + oods_point: felt, + trace_generator: felt, + constraint_coefficients: felt*, +} + +struct AirInstance { + // Virtual functions. + // Each should be a pointer to a function with the same interface as the function in this file. + public_input_hash: felt*, + public_input_validate: felt*, + traces_config_validate: felt*, + traces_commit: felt*, + traces_decommit: felt*, + traces_eval_composition_polynomial: felt*, + eval_oods_boundary_poly_at_points: felt*, + // Constants. + n_constraints: felt, + constraint_degree: felt, + mask_size: felt, +} + +func public_input_hash{ + range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, blake2s_ptr: felt* +}(air: AirInstance*, public_input: PublicInput*) -> (res: Uint256) { + jmp abs air.public_input_hash; +} + +func public_input_validate{range_check_ptr}( + air: AirInstance*, public_input: PublicInput*, stark_domains: StarkDomains* +) { + jmp abs air.public_input_validate; +} + +func traces_config_validate{range_check_ptr}( + air: AirInstance*, config: TracesConfig*, log_eval_domain_size: felt +) { + jmp abs air.traces_config_validate; +} + +func traces_commit{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}( + air: AirInstance*, + public_input: PublicInput*, + unsent_commitment: TracesUnsentCommitment*, + config: TracesConfig*, +) -> (commitment: TracesCommitment*) { + jmp abs air.traces_commit; +} + +func traces_decommit{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + air: AirInstance*, + n_queries: felt, + queries: felt*, + commitment: TracesCommitment*, + decommitment: TracesDecommitment*, + witness: TracesWitness*, +) { + jmp abs air.traces_decommit; +} + +func traces_eval_composition_polynomial{range_check_ptr}( + air: AirInstance*, + commitment: TracesCommitment*, + mask_values: felt*, + constraint_coefficients: felt*, + point: felt, + trace_domain_size: felt, + trace_generator: felt, +) -> (res: felt) { + jmp abs air.traces_eval_composition_polynomial; +} + +func eval_oods_boundary_poly_at_points{range_check_ptr}( + air: AirInstance*, + eval_info: OodsEvaluationInfo*, + n_points: felt, + points: felt*, + decommitment: TracesDecommitment*, + composition_decommitment: TableDecommitment*, +) -> (evaluations: felt*) { + jmp abs air.eval_oods_boundary_poly_at_points; +} diff --git a/src/starkware/cairo/stark_verifier/core/channel.cairo b/src/starkware/cairo/stark_verifier/core/channel.cairo new file mode 100644 index 00000000..3e826601 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/channel.cairo @@ -0,0 +1,197 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_blake2s.blake2s import ( + blake2s_add_felt, + blake2s_add_uint256_bigend, + blake2s_bigend, +) +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.math import ( + assert_nn, + assert_nn_le, + assert_not_equal, + split_felt, + unsigned_div_rem, +) +from starkware.cairo.common.uint256 import Uint256, uint256_lt + +// The Prover uses Montgomery form with R = 2**256 for field elements. This effects the +// non-interactive communication in several places. +const MONTGOMERY_R = 2 ** 256; + +// Represents a non-interactive communication channel using the Fiat Shamir heuristic. +// In this context, "reading from the prover" means hashing a value into the state. +struct Channel { + digest: Uint256, + counter: felt, +} + +// A wrapper around felt with a guarantee that the felt must be read from the channel before +// use. +struct ChannelUnsentFelt { + value: felt, +} + +// A wrapper around felt with a guarantee that the felt was read from the channel as data from the +// prover. +struct ChannelSentFelt { + value: felt, +} + +func channel_new(digest: Uint256) -> (res: Channel) { + return (res=Channel(digest=digest, counter=0)); +} + +// Generate randomness. +func random_uint256_to_prover{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}() -> (res: Uint256) { + alloc_locals; + let (data: felt*) = alloc(); + let data_start = data; + blake2s_add_uint256_bigend{data=data}(channel.digest); + blake2s_add_uint256_bigend{data=data}(Uint256(low=channel.counter, high=0)); + let (res) = blake2s_bigend(data=data_start, n_bytes=64); + let channel = Channel(digest=channel.digest, counter=channel.counter + 1); + + return (res=res); +} + +func random_felts_to_prover{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}(n_elements: felt, elements: felt*) -> () { + alloc_locals; + if (n_elements == 0) { + return (); + } + + let (local num: Uint256) = random_uint256_to_prover(); + local channel: Channel = channel; + + // To ensure a uniform distribution over field elements, if the generated 256-bit number x is in + // range [0, C * PRIME), take x % PRIME. Otherwise, regenerate. + // The maximal possible C is 2**256//PRIME = 31. + + const C_PRIME_AS_UINT256_LOW = 31 * 1; + const C_PRIME_AS_UINT256_HIGH = 31 * 0x8000000000000110000000000000000; + let (is_felt) = uint256_lt( + num, Uint256(low=C_PRIME_AS_UINT256_LOW, high=C_PRIME_AS_UINT256_HIGH) + ); + if (is_felt != 0) { + // Note: This may overflow, but the computation should be done mod PRIME anyway. + assert [elements] = (num.low + num.high * 2 ** 128) / MONTGOMERY_R; + return random_felts_to_prover(n_elements=n_elements - 1, elements=&elements[1]); + } else { + return random_felts_to_prover(n_elements=n_elements, elements=elements); + } +} + +// Reads a truncated hash from the prover. See Channel. +func read_truncated_hash_from_prover{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}(value: ChannelUnsentFelt) -> (value: ChannelSentFelt) { + alloc_locals; + let (data: felt*) = alloc(); + let data_start = data; + assert_not_equal(channel.digest.low, 2 ** 128 - 1); + blake2s_add_uint256_bigend{data=data}( + Uint256(low=channel.digest.low + 1, high=channel.digest.high) + ); + + // value encodes the 160 most significant bits of a 256-bit hash. + let (high, low) = unsigned_div_rem(value.value, 2 ** 32); + assert_nn(high); + blake2s_add_uint256_bigend{data=data}(Uint256(low=low * 2 ** 96, high=high)); + let (digest) = blake2s_bigend(data=data_start, n_bytes=64); + let channel = Channel(digest=digest, counter=0); + return (value=ChannelSentFelt(value.value)); +} + +// Reads a field element from the prover. See Channel. +func read_felt_from_prover{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}(value: ChannelUnsentFelt) -> (value: ChannelSentFelt) { + alloc_locals; + let (data: felt*) = alloc(); + let data_start = data; + assert_not_equal(channel.digest.low, 2 ** 128 - 1); + blake2s_add_uint256_bigend{data=data}( + Uint256(low=channel.digest.low + 1, high=channel.digest.high) + ); + // The prover uses Montgomery form to generate randomness. + blake2s_add_felt{data=data}(num=value.value * MONTGOMERY_R, bigend=1); + let (digest) = blake2s_bigend(data=data_start, n_bytes=64); + let channel = Channel(digest=digest, counter=0); + return (value=ChannelSentFelt(value.value)); +} + +// Reads a 64bit integer from the prover. See Channel. +func read_uint64_from_prover{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}(value: ChannelUnsentFelt) -> (value: ChannelSentFelt) { + alloc_locals; + assert_nn_le(value.value, 2 ** 64 - 1); + let (data: felt*) = alloc(); + let data_start = data; + assert_not_equal(channel.digest.low, 2 ** 128 - 1); + blake2s_add_uint256_bigend{data=data}( + Uint256(low=channel.digest.low + 1, high=channel.digest.high) + ); + // Align 64 bit value to MSB. + blake2s_add_uint256_bigend{data=data}( + Uint256( + low=0, + high=value.value * 2 ** 64, + ) + ); + let (digest) = blake2s_bigend(data=data_start, n_bytes=0x28); + let channel = Channel(digest=digest, counter=0); + return (value=ChannelSentFelt(value.value)); +} + +// Reads multiple field elements from the prover. Repeats read_felt_from_prover. See Channel. +func read_felts_from_prover{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}(n_values: felt, values: ChannelUnsentFelt*) -> (values: ChannelSentFelt*) { + read_felts_from_prover_inner(n_values=n_values, values=values); + return (values=cast(values, ChannelSentFelt*)); +} + +func read_felts_from_prover_inner{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}(n_values: felt, values: ChannelUnsentFelt*) -> () { + if (n_values == 0) { + return (); + } + + let (value) = read_felt_from_prover(values[0]); + return read_felts_from_prover_inner(n_values=n_values - 1, values=&values[1]); +} + +// Reads a field element vector from the prover. Unlike read_felts_from_prover, this hashes all the +// field elements at once. See Channel. +func read_felt_vector_from_prover{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}(n_values: felt, values: ChannelUnsentFelt*) -> (values: ChannelSentFelt*) { + alloc_locals; + let (data: felt*) = alloc(); + let data_start = data; + assert_not_equal(channel.digest.low, 2 ** 128 - 1); + blake2s_add_uint256_bigend{data=data}( + Uint256(low=channel.digest.low + 1, high=channel.digest.high) + ); + read_felt_vector_from_prover_inner{data=data}(n_values=n_values, values=values); + let (digest) = blake2s_bigend(data=data_start, n_bytes=32 * (1 + n_values)); + let channel = Channel(digest=digest, counter=0); + return (values=cast(values, ChannelSentFelt*)); +} + +func read_felt_vector_from_prover_inner{ + range_check_ptr, bitwise_ptr: BitwiseBuiltin*, channel: Channel, data: felt* +}(n_values: felt, values: ChannelUnsentFelt*) -> () { + alloc_locals; + if (n_values == 0) { + return (); + } + blake2s_add_felt(num=values[0].value * MONTGOMERY_R, bigend=1); + return read_felt_vector_from_prover_inner(n_values=n_values - 1, values=&values[1]); +} diff --git a/src/starkware/cairo/stark_verifier/core/channel_test.cairo b/src/starkware/cairo/stark_verifier/core/channel_test.cairo new file mode 100644 index 00000000..1a2040f8 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/channel_test.cairo @@ -0,0 +1,86 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.stark_verifier.core.channel import ( + Channel, + ChannelSentFelt, + ChannelUnsentFelt, + channel_new, + random_felts_to_prover, + random_uint256_to_prover, + read_felt_vector_from_prover, + read_felts_from_prover, + read_truncated_hash_from_prover, +) + +func test_to{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, blake2s_ptr: felt*}() { + alloc_locals; + let channel = Channel( + digest=Uint256(0xf7685ebd40e852b164633a4acbd3244c, 0xe8e77626586f73b955364c7b4bbf0bb7), + counter=0, + ); + with channel { + let (local elements) = alloc(); + random_felts_to_prover(n_elements=3, elements=elements); + assert elements[0] = ( + 3199910790894706855027093840383592257502485581126271436027309705477370004002); + assert elements[1] = ( + 2678311171676075552444787698918310126938416157877134200897080931937186268438); + assert elements[2] = ( + 2409925148191156067407217062797240658947927224212800962983204460004996362724); + } + return (); +} + +func test_from{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, blake2s_ptr: felt*}() { + alloc_locals; + let (channel) = channel_new(digest=Uint256(0, 0)); + local original_channel: Channel = channel; + with channel { + let (unsent_values: ChannelUnsentFelt*) = alloc(); + + read_felts_from_prover(n_values=0, values=unsent_values); + assert channel.digest = original_channel.digest; + assert channel.counter = original_channel.counter; + + let (value) = read_truncated_hash_from_prover(ChannelUnsentFelt(2 ** 160 - 1)); + assert value = ChannelSentFelt(2 ** 160 - 1); + assert channel.digest = Uint256( + 264245158129643438725130805500698377532, 273487178329072845015974259185110443467); + assert channel.counter = 0; + + // Read multiple felts. + let (local unsent_values: ChannelUnsentFelt*) = alloc(); + %{ segments.write_arg(ids.unsent_values.address_, [2, 3, -1]) %} + let (values: ChannelSentFelt*) = read_felts_from_prover(n_values=3, values=unsent_values); + assert channel.digest = Uint256( + 242546666571867849760234496042176867468, 276032264349006147573126117370612632439); + assert channel.counter = 0; + %{ + assert memory[ids.values.address_ + 0] == 2 + assert memory[ids.values.address_ + 1] == 3 + assert memory[ids.values.address_ + 2] == PRIME - 1 + %} + + // Read a felt vector. + let (values: ChannelSentFelt*) = read_felt_vector_from_prover( + n_values=3, values=unsent_values + ); + assert channel.digest = Uint256( + 47489586150803289593519442158772964707, 295510913258162813848457591889478884574); + assert channel.counter = 0; + %{ + assert memory[ids.values.address_ + 0] == 2 + assert memory[ids.values.address_ + 1] == 3 + assert memory[ids.values.address_ + 2] == PRIME - 1 + %} + ap += 0; + } + return (); +} + +func main_test{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, blake2s_ptr: felt*}() -> () { + test_to(); + test_from(); + return (); +} diff --git a/src/starkware/cairo/stark_verifier/core/channel_test.py b/src/starkware/cairo/stark_verifier/core/channel_test.py new file mode 100644 index 00000000..035455bc --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/channel_test.py @@ -0,0 +1,27 @@ +import os + +import pytest + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.common.validate_utils import validate_builtin_usage +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files + +CAIRO_FILE = os.path.join(os.path.dirname(__file__), "channel_test.cairo") + + +@pytest.fixture(scope="session") +def program(): + return compile_cairo_files([CAIRO_FILE], prime=DEFAULT_PRIME, debug_info=True) + + +def test_channel(program): + runner = CairoFunctionRunner(program, layout="small") + blake2s_ptr = runner.segments.add() + runner.run( + "main_test", runner.range_check_builtin.base, runner.bitwise_builtin.base, blake2s_ptr + ) + res_range_check_ptr, res_bitwise_ptr, res_blake2s_ptr = runner.get_return_values(3) + validate_builtin_usage(runner.range_check_builtin, res_range_check_ptr) + validate_builtin_usage(runner.bitwise_builtin, res_bitwise_ptr) + assert res_blake2s_ptr.segment_index == blake2s_ptr.segment_index diff --git a/src/starkware/cairo/stark_verifier/core/config.cairo b/src/starkware/cairo/stark_verifier/core/config.cairo new file mode 100644 index 00000000..3ca958c9 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/config.cairo @@ -0,0 +1,99 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.math import assert_in_range, assert_le, assert_nn, assert_nn_le +from starkware.cairo.common.pow import pow +from starkware.cairo.stark_verifier.core.air_interface import ( + AirInstance, + TracesConfig, + traces_config_validate, +) +from starkware.cairo.stark_verifier.core.domains import StarkDomains +from starkware.cairo.stark_verifier.core.fri.config import FriConfig, fri_config_validate +from starkware.cairo.stark_verifier.core.proof_of_work import ( + ProofOfWorkConfig, + proof_of_work_config_validate, +) +from starkware.cairo.stark_verifier.core.table_commitment import TableCommitmentConfig +from starkware.cairo.stark_verifier.core.utils import FIELD_GENERATOR +from starkware.cairo.stark_verifier.core.vector_commitment import VectorCommitmentConfig + +const MAX_LOG_TRACE = 64; +const MAX_LOG_BLOWUP_FACTOR = 16; +const MAX_N_QUERIES = 48; + +struct StarkConfig { + traces: TracesConfig*, + composition: TableCommitmentConfig*, + fri: FriConfig*, + proof_of_work: ProofOfWorkConfig*, + + // Log2 of the trace domain size. + log_trace_domain_size: felt, + // Number of queries to the last component, FRI. + n_queries: felt, + // Log2 of the number of cosets composing the evaluation domain, where the coset size is the + // trace length. + log_n_cosets: felt, +} + +// Validates the StarkConfig object. +func stark_config_validate{range_check_ptr}( + air: AirInstance*, config: StarkConfig*, security_bits: felt +) { + alloc_locals; + + // Proof of work. + proof_of_work_config_validate(config=config.proof_of_work); + + // Sanity checks for the configuration. Many of the bounds are somewhat arbitrary. + assert_in_range(config.log_trace_domain_size, 1, MAX_LOG_TRACE + 1); + assert_nn(security_bits); + assert_in_range(config.log_n_cosets, 1, MAX_LOG_BLOWUP_FACTOR + 1); + assert_le(config.proof_of_work.n_bits, security_bits); + assert_in_range(config.n_queries, 1, MAX_N_QUERIES + 1); + + // Check security bits. + assert_nn_le( + security_bits, config.n_queries * config.log_n_cosets + config.proof_of_work.n_bits + ); + + // Validate traces config. + let log_eval_domain_size = config.log_trace_domain_size + config.log_n_cosets; + traces_config_validate( + air=air, config=config.traces, log_eval_domain_size=log_eval_domain_size + ); + + // Validate composition config. + assert config.composition.n_columns = air.constraint_degree; + assert [config.composition.vector] = VectorCommitmentConfig(height=log_eval_domain_size); + + // Validate Fri config. + let (log_expected_degree) = fri_config_validate( + config=config.fri, log_n_cosets=config.log_n_cosets + ); + assert log_expected_degree = config.log_trace_domain_size; + + return (); +} + +// Returns a StarkDomains object with information about the domains. +func stark_domains_create{range_check_ptr}(config: StarkConfig*) -> (stark_domains: StarkDomains*) { + alloc_locals; + + // Compute stark_domains. + local log_eval_domain_size = config.log_trace_domain_size + config.log_n_cosets; + let (eval_domain_size) = pow(2, log_eval_domain_size); + let (eval_generator) = pow(FIELD_GENERATOR, (-1) / eval_domain_size); + let (trace_domain_size) = pow(2, config.log_trace_domain_size); + let (trace_generator) = pow(FIELD_GENERATOR, (-1) / trace_domain_size); + + return ( + stark_domains=new StarkDomains( + log_eval_domain_size=log_eval_domain_size, + eval_domain_size=eval_domain_size, + eval_generator=eval_generator, + log_trace_domain_size=config.log_trace_domain_size, + trace_domain_size=trace_domain_size, + trace_generator=trace_generator, + ), + ); +} diff --git a/src/starkware/cairo/stark_verifier/core/domains.cairo b/src/starkware/cairo/stark_verifier/core/domains.cairo new file mode 100644 index 00000000..08eee5e5 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/domains.cairo @@ -0,0 +1,15 @@ +// Information about the domains that are used in the stark proof. +struct StarkDomains { + // Log2 of the evaluation domain size. + log_eval_domain_size: felt, + // The evaluation domain size. + eval_domain_size: felt, + // The generator of the evaluation domain (a primitive root of unity of order eval_domain_size). + eval_generator: felt, + // Log2 of the trace domain size. + log_trace_domain_size: felt, + // The trace domain size. + trace_domain_size: felt, + // The generator of the trace domain (a primitive root of unity of order trace_domain_size). + trace_generator: felt, +} diff --git a/src/starkware/cairo/stark_verifier/core/fri/CMakeLists.txt b/src/starkware/cairo/stark_verifier/core/fri/CMakeLists.txt new file mode 100644 index 00000000..bb6eb14d --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/CMakeLists.txt @@ -0,0 +1,30 @@ +python_lib(starkware_cairo_stark_verifier_core_fri_lib + PREFIX starkware/cairo/stark_verifier/core/fri + FILES + config.cairo + fri.cairo + fri_formula.cairo + fri_layer.cairo + + LIBS + cairo_common_lib + starkware_cairo_stark_verifier_core_lib +) + +full_python_test(starkware_cairo_stark_verifier_core_fri_test + PREFIX starkware/cairo/stark_verifier/core/fri + PYTHON python3.9 + + FILES + fri_formula_test.py + fri_layer_test.py + fri_test.py + test_utils.py + + LIBS + cairo_compile_lib + cairo_function_runner_lib + starkware_cairo_stark_verifier_core_fri_lib + starkware_python_test_utils_lib + pip_pytest +) diff --git a/src/starkware/cairo/stark_verifier/core/fri/__init__.py b/src/starkware/cairo/stark_verifier/core/fri/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/starkware/cairo/stark_verifier/core/fri/config.cairo b/src/starkware/cairo/stark_verifier/core/fri/config.cairo new file mode 100644 index 00000000..605d2bec --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/config.cairo @@ -0,0 +1,63 @@ +from starkware.cairo.common.math import assert_in_range, assert_nn, assert_nn_le +from starkware.cairo.common.pow import pow +from starkware.cairo.stark_verifier.core.table_commitment import TableCommitmentConfig + +// Constants. +const MAX_LAST_LAYER_LOG_DEGREE_BOUND = 15; +const MAX_FRI_LAYERS = 15; +const MAX_FRI_STEP = 4; + +// Configuration for the FRI component. +struct FriConfig { + // Log2 of the size of the input layer to FRI. + log_input_size: felt, + // Number of layers in the FRI. Inner + last layer. + n_layers: felt, + // Array of size n_layers - 1, each entry is a configuration of a table commitment for the + // corresponding inner layer. + inner_layers: TableCommitmentConfig*, + // Array of size n_layers, each entry represents the FRI step size, + // i.e. the number of FRI-foldings between layer i and i+1. + fri_step_sizes: felt*, + log_last_layer_degree_bound: felt, +} + +func fri_config_validate{range_check_ptr}(config: FriConfig*, log_n_cosets: felt) -> ( + log_expected_degree: felt +) { + assert_nn_le(config.log_last_layer_degree_bound, MAX_LAST_LAYER_LOG_DEGREE_BOUND); + assert_in_range(config.n_layers, 2, MAX_FRI_LAYERS + 1); + assert config.fri_step_sizes[0] = 0; + let (sum_of_step_sizes) = fri_layers_config_validate( + n_layers=config.n_layers - 1, + layers=config.inner_layers, + fri_step_sizes=&config.fri_step_sizes[1], + log_input_size=config.log_input_size - config.fri_step_sizes[0], + ); + tempvar log_expected_input_degree = sum_of_step_sizes + config.log_last_layer_degree_bound; + assert log_expected_input_degree + log_n_cosets = config.log_input_size; + return (log_expected_degree=log_expected_input_degree); +} + +func fri_layers_config_validate{range_check_ptr}( + n_layers: felt, layers: TableCommitmentConfig*, fri_step_sizes: felt*, log_input_size: felt +) -> (sum_of_step_sizes: felt) { + alloc_locals; + if (n_layers == 0) { + assert_nn(log_input_size); + return (sum_of_step_sizes=0); + } + + local fri_step = fri_step_sizes[0]; + assert_in_range(fri_step, 1, MAX_FRI_STEP + 1); + let (sum_of_step_sizes) = fri_layers_config_validate( + n_layers=n_layers - 1, + layers=&layers[1], + fri_step_sizes=&fri_step_sizes[1], + log_input_size=log_input_size - fri_step, + ); + let (n_columns) = pow(2, fri_step); + assert layers.n_columns = n_columns; + assert layers.vector.height = log_input_size - fri_step; + return (sum_of_step_sizes=sum_of_step_sizes + fri_step); +} diff --git a/src/starkware/cairo/stark_verifier/core/fri/fri.cairo b/src/starkware/cairo/stark_verifier/core/fri/fri.cairo new file mode 100644 index 00000000..2684bc56 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/fri.cairo @@ -0,0 +1,325 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.math import horner_eval +from starkware.cairo.common.pow import pow +from starkware.cairo.stark_verifier.core.channel import ( + Channel, + ChannelSentFelt, + ChannelUnsentFelt, + random_felts_to_prover, + read_felt_vector_from_prover, +) +from starkware.cairo.stark_verifier.core.fri.config import FriConfig, fri_config_validate +from starkware.cairo.stark_verifier.core.fri.fri_layer import ( + FriLayerComputationParams, + FriLayerQuery, + compute_next_layer, + get_fri_group, +) +from starkware.cairo.stark_verifier.core.table_commitment import ( + TableCommitment, + TableCommitmentConfig, + TableCommitmentWitness, + TableDecommitment, + TableUnsentCommitment, + table_commit, + table_decommit, +) +from starkware.cairo.stark_verifier.core.utils import FIELD_GENERATOR + +// A FRI phase with N layers starts with a single input layer. +// Afterwards, there are N - 1 inner layers resulting from FRI-folding each preceding layer. +// Each such layer has a separate table commitment, for a total of N - 1 commitments. +// Lastly, there is another FRI-folding resulting in the last FRI layer, that is commited by +// sending the polynomial coefficients, instead of a table commitment. +// Each folding has a step size. +// Illustration: +// InputLayer, no commitment. +// fold step 0 +// InnerLayer 0, Table commitment +// fold step 1 +// ... +// InnerLayer N - 2, Table commitment +// fold step N - 1 +// LastLayer, Polynomial coefficients +// +// N steps. +// N - 1 inner layers. + +// Commitment values for FRI. Used to generate a commitment by "reading" these values +// from the channel. +struct FriUnsentCommitment { + // Array of size n_layers - 1 containing unsent table commitments for each inner layer. + inner_layers: TableUnsentCommitment*, + // Array of size 2**log_last_layer_degree_bound containing coefficients for the last layer + // polynomial. + last_layer_coefficients: ChannelUnsentFelt*, +} + +struct FriCommitment { + config: FriConfig*, + // Array of size n_layers - 1 containing table commitments for each inner layer. + inner_layers: TableCommitment**, + // Array of size n_layers, of one evaluation point for each layer. + eval_points: felt*, + // Array of size 2**log_last_layer_degree_bound containing coefficients for the last layer + // polynomial. + last_layer_coefficients: ChannelSentFelt*, +} + +struct FriDecommitment { + // Number of queries. + n_values: felt, + // Array of size n_values, containing the values of the input layer at query indices. + values: felt*, + // Array of size n_values, containing the field elements that correspond to the query indices + // (See queries_to_points). + points: felt*, +} + +// A witness for the decommitment of the FRI layers over queries. +struct FriWitness { + // An array of size n_layers - 1, containing a witness for each inner layer. + layers: FriLayerWitness*, +} + +// A witness for a single FRI layer. This witness is required to verify the transition from an +// inner layer to the following layer. +struct FriLayerWitness { + // Values for the sibling leaves required for decommitment. + n_leaves: felt, + leaves: felt*, + // Table commitment witnesses for decommiting all the leaves. + table_witness: TableCommitmentWitness*, +} + +// Commit function of the FRI component. +// Implements the commit phase of the FRI protocol. +func fri_commit{ + blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel, range_check_ptr +}(unsent_commitment: FriUnsentCommitment*, config: FriConfig*) -> (commitment: FriCommitment*) { + alloc_locals; + let (inner_layer_commitments: TableCommitment**) = alloc(); + let (eval_points: felt*) = alloc(); + + // The first step should be 0, and thus we don't need a point for it. + assert config.fri_step_sizes[0] = 0; + assert eval_points[0] = 0; + + // Read inner layer commitments and eval_points. + fri_commit_rounds( + n_layers=config.n_layers - 1, + configs=config.inner_layers, + unsent_commitments=unsent_commitment.inner_layers, + step_sizes=config.fri_step_sizes, + commitments=inner_layer_commitments, + eval_points=&eval_points[1], + ); + + // Read last layer coefficients. + let (n_coefficients) = pow(2, config.log_last_layer_degree_bound); + let (coefficients) = read_felt_vector_from_prover( + n_values=n_coefficients, values=unsent_commitment.last_layer_coefficients + ); + + return ( + commitment=new FriCommitment( + config=config, + inner_layers=inner_layer_commitments, + eval_points=eval_points, + last_layer_coefficients=coefficients), + ); +} + +// Performs FRI commitment phase rounds. Each round reads a commitment on a layer, and sends an +// evaluation point for the next round. +func fri_commit_rounds{ + blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel, range_check_ptr +}( + n_layers: felt, + configs: TableCommitmentConfig*, + unsent_commitments: TableUnsentCommitment*, + step_sizes: felt*, + commitments: TableCommitment**, + eval_points: felt*, +) { + alloc_locals; + if (n_layers == 0) { + return (); + } + + // Read commitments. + let (table_commitment) = table_commit(unsent_commitment=unsent_commitments[0], config=configs); + assert commitments[0] = table_commitment; + + // Send the next eval_points. + random_felts_to_prover(n_elements=1, elements=eval_points); + + return fri_commit_rounds( + n_layers=n_layers - 1, + configs=&configs[1], + unsent_commitments=&unsent_commitments[1], + step_sizes=&step_sizes[1], + commitments=&commitments[1], + eval_points=&eval_points[1], + ); +} + +// FRI protocol component decommitment. +func fri_decommit{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + n_queries: felt, + queries: felt*, + commitment: FriCommitment*, + decommitment: FriDecommitment*, + witness: FriWitness*, +) { + alloc_locals; + + assert n_queries = decommitment.n_values; + let fri_first_layer_evaluations = decommitment.values; + + // Compute first FRI layer queries. + let (fri_queries: FriLayerQuery*) = alloc(); + gather_first_layer_queries( + n_queries=n_queries, + queries=queries, + evaluations=decommitment.values, + x_values=decommitment.points, + fri_queries=fri_queries, + ); + + // Compute fri_group. + let (fri_group) = get_fri_group(); + + // Decommit inner layers. + let (n_last_queries, last_queries) = fri_decommit_layers( + fri_group=fri_group, + n_layers=commitment.config.n_layers - 1, + commitment=commitment.inner_layers, + layer_witness=witness.layers, + eval_points=&commitment.eval_points[1], + step_sizes=&commitment.config.fri_step_sizes[1], + n_queries=n_queries, + queries=fri_queries, + ); + + // Last layer. + let (n_coefficients) = pow(2, commitment.config.log_last_layer_degree_bound); + verify_last_layer( + n_queries=n_last_queries, + queries=last_queries, + n_coefficients=n_coefficients, + coefficients=commitment.last_layer_coefficients, + ); + return (); +} + +func gather_first_layer_queries( + n_queries: felt, + queries: felt*, + evaluations: felt*, + x_values: felt*, + fri_queries: FriLayerQuery*, +) { + if (n_queries == 0) { + return (); + } + + // Translate the coset to the homogenous group to have simple FRI equations. + let shifted_x_value = x_values[0] / FIELD_GENERATOR; + assert fri_queries[0] = FriLayerQuery( + index=queries[0], + y_value=evaluations[0], + x_inv_value=1 / shifted_x_value, + ); + + return gather_first_layer_queries( + n_queries=n_queries - 1, + queries=&queries[1], + evaluations=&evaluations[1], + x_values=&x_values[1], + fri_queries=&fri_queries[1], + ); +} + +func fri_decommit_layers{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + fri_group: felt*, + n_layers: felt, + commitment: TableCommitment**, + layer_witness: FriLayerWitness*, + eval_points: felt*, + step_sizes: felt*, + n_queries: felt, + queries: FriLayerQuery*, +) -> (n_last_queries: felt, last_queries: FriLayerQuery*) { + if (n_layers == 0) { + return (n_last_queries=n_queries, last_queries=queries); + } + + alloc_locals; + // Params. + let (coset_size) = pow(2, step_sizes[0]); + tempvar params: FriLayerComputationParams* = new FriLayerComputationParams( + coset_size=coset_size, fri_group=fri_group, eval_point=eval_points[0]); + + // Allocate values for the next layer computation. + let (next_queries: FriLayerQuery*) = alloc(); + let next_queries_start = next_queries; + let sibling_witness = layer_witness.leaves; + let (verify_indices) = alloc(); + let verify_indices_start = verify_indices; + let (verify_y_values) = alloc(); + let verify_y_values_start = verify_y_values; + + // Compute next layer queries. + with n_queries, queries, sibling_witness, next_queries, verify_indices, verify_y_values { + compute_next_layer(params=params); + } + let n_next_queries = (next_queries - next_queries_start) / FriLayerQuery.SIZE; + + // Table decommitment. + tempvar decommitment: TableDecommitment* = new TableDecommitment( + n_values=verify_y_values - verify_y_values_start, + values=verify_y_values_start, + ); + table_decommit( + commitment=commitment[0], + n_queries=verify_indices - verify_indices_start, + queries=verify_indices_start, + decommitment=decommitment, + witness=layer_witness.table_witness, + ); + + return fri_decommit_layers( + fri_group=fri_group, + n_layers=n_layers - 1, + commitment=&commitment[1], + layer_witness=&layer_witness[1], + eval_points=&eval_points[1], + step_sizes=&step_sizes[1], + n_queries=n_next_queries, + queries=next_queries_start, + ); +} + +// Verifies FRI last layer by evaluating the given polynomial on the given points (=inverses of +// x_inv_values), and comparing the results to the given values. +func verify_last_layer( + n_queries: felt, queries: FriLayerQuery*, n_coefficients: felt, coefficients: felt* +) { + if (n_queries == 0) { + return (); + } + + let (value) = horner_eval( + n_coefficients=n_coefficients, coefficients=coefficients, point=1 / queries[0].x_inv_value + ); + assert value = queries[0].y_value; + + return verify_last_layer( + n_queries=n_queries - 1, + queries=&queries[1], + n_coefficients=n_coefficients, + coefficients=coefficients, + ); +} diff --git a/src/starkware/cairo/stark_verifier/core/fri/fri_formula.cairo b/src/starkware/cairo/stark_verifier/core/fri/fri_formula.cairo new file mode 100644 index 00000000..cf0d8f1f --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/fri_formula.cairo @@ -0,0 +1,81 @@ +// Primitive roots of unity of orders 2, 4, 8 and 16. +// Use 1 / 3^((PRIME - 1) / 16) as the primitive root of order 16 (3 is a generator of the +// multiplicative group of the field). +const OMEGA_16 = 0x5c3ed0c6f6ac6dd647c9ba3e4721c1eb14011ea3d174c52d7981c5b8145aa75; +const OMEGA_8 = OMEGA_16 * OMEGA_16; +const OMEGA_4 = OMEGA_8 * OMEGA_8; +const OMEGA_2 = OMEGA_4 * OMEGA_4; + +// Folds 2 elements into one using one layer of FRI. +func fri_formula2(f_x, f_minus_x, eval_point, x_inv) -> (res: felt) { + return (res=f_x + f_minus_x + eval_point * x_inv * (f_x - f_minus_x)); +} + +// Folds 4 elements into one using 2 layers of FRI. +func fri_formula4(values: felt*, eval_point, x_inv) -> (res: felt) { + // First layer. + let (g0) = fri_formula2(f_x=values[0], f_minus_x=values[1], eval_point=eval_point, x_inv=x_inv); + let (g1) = fri_formula2( + f_x=values[2], f_minus_x=values[3], eval_point=eval_point, x_inv=x_inv * OMEGA_4 + ); + + // Second layer. + return fri_formula2( + f_x=g0, f_minus_x=g1, eval_point=eval_point * eval_point, x_inv=x_inv * x_inv + ); +} + +// Folds 8 elements into one using 3 layers of FRI. +func fri_formula8(values: felt*, eval_point, x_inv) -> (res: felt) { + // First two layers. + let (g0) = fri_formula4(values=values, eval_point=eval_point, x_inv=x_inv); + let (g1) = fri_formula4(values=&values[4], eval_point=eval_point, x_inv=x_inv * OMEGA_8); + + // Last layer. + tempvar eval_point2 = eval_point * eval_point; + let eval_point4 = eval_point2 * eval_point2; + + tempvar x_inv2 = x_inv * x_inv; + let x_inv4 = x_inv2 * x_inv2; + return fri_formula2(f_x=g0, f_minus_x=g1, eval_point=eval_point4, x_inv=x_inv4); +} + +// Folds 16 elements into one using 4 layers of FRI. +func fri_formula16(values: felt*, eval_point, x_inv) -> (res: felt) { + // First three layers. + let (g0) = fri_formula8(values=values, eval_point=eval_point, x_inv=x_inv); + let (g1) = fri_formula8(values=&values[8], eval_point=eval_point, x_inv=x_inv * OMEGA_16); + + // Last layer. + tempvar eval_point2 = eval_point * eval_point; + tempvar eval_point4 = eval_point2 * eval_point2; + let eval_point8 = eval_point4 * eval_point4; + + tempvar x_inv2 = x_inv * x_inv; + tempvar x_inv4 = x_inv2 * x_inv2; + let x_inv8 = x_inv4 * x_inv4; + + return fri_formula2(f_x=g0, f_minus_x=g1, eval_point=eval_point8, x_inv=x_inv8); +} + +// Folds 'coset_size' elements into one using log2(coset_size) layers of FRI. +// 'coset_size' can be 2, 4, 8, or 16. +func fri_formula(values: felt*, eval_point, x_inv, coset_size) -> (res: felt) { + // Sort by usage frequency. + if (coset_size == 8) { + return fri_formula8(values, eval_point, x_inv); + } + if (coset_size == 4) { + return fri_formula4(values, eval_point, x_inv); + } + if (coset_size == 16) { + return fri_formula16(values, eval_point, x_inv); + } + if (coset_size == 2) { + return fri_formula2(values[0], values[1], eval_point, x_inv); + } + + // Fail. + assert 1 = 0; + return (res=0); +} diff --git a/src/starkware/cairo/stark_verifier/core/fri/fri_formula_test.py b/src/starkware/cairo/stark_verifier/core/fri/fri_formula_test.py new file mode 100644 index 00000000..c7993be9 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/fri_formula_test.py @@ -0,0 +1,58 @@ +import os +import random + +import pytest + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files +from starkware.cairo.lang.compiler.program import Program +from starkware.cairo.stark_verifier.core.fri.test_utils import ( + apply_fri_steps_on_coset, + evaluate_polynomial_on_coset, +) +from starkware.python.math_utils import safe_div + +CAIRO_FILE = os.path.join(os.path.dirname(__file__), "fri_formula.cairo") + + +@pytest.fixture(scope="session") +def program() -> Program: + return compile_cairo_files([CAIRO_FILE], prime=DEFAULT_PRIME, debug_info=True) + + +def test_omega(program: Program): + assert (program.get_const("OMEGA_2") + 1) % DEFAULT_PRIME == 0 + + +@pytest.mark.parametrize("fri_step", range(1, 5)) +def test_fri(program: Program, fri_step: int): + # Choose a random polynomial of degree < 256: sum(poly[i] * x^i). + poly = [random.randrange(DEFAULT_PRIME) for i in range(256)] + + # Choose random eval_point and random x. + eval_point = random.randrange(DEFAULT_PRIME) + x = random.randrange(DEFAULT_PRIME) + + # Compute the values of the polynomial on the coset. + coset_size = 2**fri_step + coset_gen = pow(3, safe_div(DEFAULT_PRIME - 1, coset_size), DEFAULT_PRIME) + _, coset_values = evaluate_polynomial_on_coset( + poly=poly, x=x, coset_gen=coset_gen, coset_size_log2=fri_step + ) + + # Apply fri_step layers of FRI and evaluate the result on y=x^coset_size. + expected_res = apply_fri_steps_on_coset( + poly=poly, x=x, coset_size=coset_size, eval_point=eval_point + ) + + # The fri_formula function returns the result multiplied by coset_size for efficiency. + expected_res = (expected_res * coset_size) % DEFAULT_PRIME + + runner = CairoFunctionRunner(program) + x_inv = pow(x, DEFAULT_PRIME - 2, DEFAULT_PRIME) + runner.run(f"fri_formula", coset_values, eval_point, x_inv, coset_size) + (res,) = runner.get_return_values(1) + print(f"fri_formula{coset_size} took {runner.vm.current_step} steps.") + + assert res == expected_res diff --git a/src/starkware/cairo/stark_verifier/core/fri/fri_layer.cairo b/src/starkware/cairo/stark_verifier/core/fri/fri_layer.cairo new file mode 100644 index 00000000..3818b01e --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/fri_layer.cairo @@ -0,0 +1,175 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.math import assert_nn, assert_not_equal +from starkware.cairo.common.pow import pow +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.stark_verifier.core.fri.fri_formula import fri_formula + +// Constant parameters for computing the next FRI layer. +struct FriLayerComputationParams { + coset_size: felt, + fri_group: felt*, + eval_point: felt, +} + +struct FriLayerQuery { + index: felt, + y_value: felt, + x_inv_value: felt, +} + +// Computes the elements of the coset starting at coset_start_index. +// +// Inputs: +// - n_queries: the number of input queries. +// - queries: an iterator over the input queries. +// - sibling_witness: a list of all the query's siblings. +// - coset_size: the number of elements in the coset. +// - coset_start_index: the index of the first element of the coset being calculated. +// - offset_within_coset: the offset of the current processed element within the coset. +// - fri_group: holds the group in bit reversed order, where g is the generator of the coset. +// +// Outputs: +// - coset_elements: the values of the coset elements. +// - coset_x_inv: x_inv of the first element in the coset. This value is set only if at least one +// query was consumed by this function. +func compute_coset_elements{n_queries: felt, queries: FriLayerQuery*, sibling_witness: felt*}( + coset_size: felt, + coset_start_index: felt, + offset_within_coset: felt, + fri_group: felt*, + coset_elements: felt*, + coset_x_inv: felt*, +) { + if (offset_within_coset == coset_size) { + return (); + } + + if (n_queries != 0) { + if (queries.index == coset_start_index + offset_within_coset) { + assert [coset_elements] = queries.y_value; + assert [coset_x_inv] = queries.x_inv_value * [fri_group]; + + let n_queries = n_queries - 1; + let queries = &queries[1]; + return compute_coset_elements( + coset_size=coset_size, + coset_start_index=coset_start_index, + offset_within_coset=offset_within_coset + 1, + fri_group=&fri_group[1], + coset_elements=&coset_elements[1], + coset_x_inv=coset_x_inv, + ); + } + } + + assert [coset_elements] = [sibling_witness]; + let sibling_witness = &sibling_witness[1]; + return compute_coset_elements( + coset_size=coset_size, + coset_start_index=coset_start_index, + offset_within_coset=offset_within_coset + 1, + fri_group=&fri_group[1], + coset_elements=&coset_elements[1], + coset_x_inv=coset_x_inv, + ); +} + +// Computes FRI next layer for the given queries. I.e., takes the given i-th layer queries +// and produces queries for layer i+1 (a single query for each coset in the i-th layer). +// +// Inputs: +// - n_queries: the number of input queries. +// - queries: input queries. +// - sibling_witness: a list of all the query's siblings. +// - params: the parameters to use for the layer computation. +// +// Outputs: +// - next_queries: queries for the next layer. +// - verify_indices: query indices of the given layer for Merkle verification. +// - verify_y_values: query y values of the given layer for Merkle verification. +func compute_next_layer{ + range_check_ptr, + n_queries: felt, + queries: FriLayerQuery*, + sibling_witness: felt*, + next_queries: FriLayerQuery*, + verify_indices: felt*, + verify_y_values: felt*, +}(params: FriLayerComputationParams*) { + if (n_queries == 0) { + return (); + } + + alloc_locals; + local coset_size = params.coset_size; + + // Guess coset_index. + // Note that compute_coset_elements() consumes queries, and it is verified + // that it consumed at least one query. This will imply that coset_index is correct. + local coset_index = nondet %{ ids.queries.index // ids.params.coset_size %}; + assert_nn(coset_index); + + // Write verification query. + assert [verify_indices] = coset_index; + let verify_indices = &verify_indices[1]; + let coset_elements = verify_y_values; + let verify_y_values = &verify_y_values[coset_size]; + + // Store n_queries in order to verify at least one query was consumed. + local n_queries_before = n_queries; + let (coset_x_inv: felt*) = alloc(); + compute_coset_elements( + coset_size=coset_size, + coset_start_index=coset_index * coset_size, + offset_within_coset=0, + fri_group=params.fri_group, + coset_elements=coset_elements, + coset_x_inv=coset_x_inv, + ); + + // Verify that at least one query was consumed. + assert_not_equal(n_queries_before, n_queries); + + let (fri_formula_res) = fri_formula( + values=coset_elements, + eval_point=params.eval_point, + x_inv=[coset_x_inv], + coset_size=coset_size, + ); + + // Write next layer query. + let (next_x_inv) = pow([coset_x_inv], params.coset_size); + assert next_queries[0] = FriLayerQuery( + index=coset_index, + y_value=fri_formula_res, + x_inv_value=next_x_inv); + let next_queries = &next_queries[1]; + + return compute_next_layer(params=params); +} + +// Returns the elements of the multiplicative subgroup of order 16, in bit-reversed order for the +// cairo prime field. Note that the first 2^k elements correspond to the group of size 2^k. +func get_fri_group() -> (address: felt*) { + alloc_locals; + let (address) = get_label_location(data); + return (address=address); + + data: + dw 0x1; + dw 0x800000000000011000000000000000000000000000000000000000000000000; + dw 0x625023929a2995b533120664329f8c7c5268e56ac8320da2a616626f41337e3; + dw 0x1dafdc6d65d66b5accedf99bcd607383ad971a9537cdf25d59e99d90becc81e; + dw 0x63365fe0de874d9c90adb1e2f9c676e98c62155e4412e873ada5e1dee6feebb; + dw 0x1cc9a01f2178b3736f524e1d06398916739deaa1bbed178c525a1e211901146; + dw 0x3b912c31d6a226e4a15988c6b7ec1915474043aac68553537192090b43635cd; + dw 0x446ed3ce295dda2b5ea677394813e6eab8bfbc55397aacac8e6df6f4bc9ca34; + dw 0x5ec467b88826aba4537602d514425f3b0bdf467bbf302458337c45f6021e539; + dw 0x213b984777d9556bac89fd2aebbda0c4f420b98440cfdba7cc83ba09fde1ac8; + dw 0x5ce3fa16c35cb4da537753675ca3276ead24059dddea2ca47c36587e5a538d1; + dw 0x231c05e93ca34c35ac88ac98a35cd89152dbfa622215d35b83c9a781a5ac730; + dw 0x00b54759e8c46e1258dc80f091e6f3be387888015452ce5f0ca09ce9e571f52; + dw 0x7f4ab8a6173b92fda7237f0f6e190c41c78777feabad31a0f35f63161a8e0af; + dw 0x23c12f3909539339b83645c1b8de3e14ebfee15c2e8b3ad2867e3a47eba558c; + dw 0x5c3ed0c6f6ac6dd647c9ba3e4721c1eb14011ea3d174c52d7981c5b8145aa75; +} diff --git a/src/starkware/cairo/stark_verifier/core/fri/fri_layer_test.py b/src/starkware/cairo/stark_verifier/core/fri/fri_layer_test.py new file mode 100644 index 00000000..023bc4aa --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/fri_layer_test.py @@ -0,0 +1,160 @@ +import itertools +import os +import random +from typing import List + +import pytest + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.common.structs import CairoStructFactory, CairoStructProxy +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files +from starkware.cairo.lang.compiler.program import Program +from starkware.cairo.stark_verifier.core.fri.test_utils import ( + apply_fri_steps_on_coset, + evaluate_polynomial_on_coset, +) +from starkware.python.math_utils import div_mod, safe_div + +CAIRO_FILE = os.path.join(os.path.dirname(__file__), "fri_layer.cairo") + +MAX_COSET_GEN = pow(3, safe_div(DEFAULT_PRIME - 1, 16), DEFAULT_PRIME) + + +def fri_group() -> List[int]: + """ + Returns the elements of the multiplicative subgroup of size 16 in bit-reversed order. + """ + result = [] + for i in [0, 4, 2, 6, 1, 5, 3, 7]: + val = pow(MAX_COSET_GEN, i, DEFAULT_PRIME) + result.append(val) + result.append(DEFAULT_PRIME - val) + return result + + +@pytest.fixture(scope="session") +def program() -> Program: + return compile_cairo_files([CAIRO_FILE], prime=DEFAULT_PRIME, debug_info=True) + + +@pytest.fixture +def structs(program): + return CairoStructFactory.from_program( + program, + ).structs + + +@pytest.mark.parametrize("fri_step", range(1, 5)) +@pytest.mark.parametrize("num_queries", range(0, 5)) +def test_fri(program: Program, structs: CairoStructProxy, fri_step: int, num_queries: int): + layer_size_log2 = 5 + layer_size = 2**layer_size_log2 + + # Choose a random polynomial of degree < 256: sum(poly[i] * x^i). + poly = [random.randrange(DEFAULT_PRIME) for i in range(256)] + + # Choose random eval_point and random x. + eval_point = random.randrange(DEFAULT_PRIME) + rand_x = random.randrange(DEFAULT_PRIME) + + # Compute the values of the polynomial on the coset. + coset_gen = pow(3, safe_div(DEFAULT_PRIME - 1, layer_size), DEFAULT_PRIME) + coset_x_values, coset_values = evaluate_polynomial_on_coset( + poly=poly, x=rand_x, coset_gen=coset_gen, coset_size_log2=layer_size_log2 + ) + + # Choose random points in the coset that will be used as queries for the layer. + indices = sorted(random.sample(range(layer_size), num_queries)) + coset_size = 2**fri_step + queried_cosets = sorted(set(i // coset_size for i in indices)) + + # Prepare inputs and expected outputs. + queries = [] + for i in indices: + queries.append( + structs.FriLayerQuery( + index=i, + y_value=coset_values[i], + x_inv_value=div_mod(1, coset_x_values[i], DEFAULT_PRIME), + ) + ) + + sibling_witness = [] + expected_verify_indices = [] + expected_verify_y_values = [] + for coset_index in sorted(queried_cosets): + expected_verify_indices.append(coset_index) + coset_start_index = coset_index * coset_size + for i in range(coset_start_index, coset_start_index + coset_size): + expected_verify_y_values.append(coset_values[i]) + if i not in indices: + sibling_witness.append(coset_values[i]) + + # Apply fri_step layers of FRI to evaluate the results on y=x^coset_size for each queried + # coset. + expected_next_queries = [] + for coset_index in sorted(queried_cosets): + coset_start_index = coset_index * coset_size + x = coset_x_values[coset_start_index] + expected_val = apply_fri_steps_on_coset(poly, x, coset_size, eval_point) + # The fri_formula function returns the result multiplied by coset_size for + # efficiency. + expected_val = (expected_val * coset_size) % DEFAULT_PRIME + expected_next_queries.append( + structs.FriLayerQuery( + index=coset_index, + y_value=expected_val, + x_inv_value=div_mod(1, pow(x, coset_size, DEFAULT_PRIME), DEFAULT_PRIME), + ) + ) + + runner = CairoFunctionRunner(program) + next_queries = runner.segments.add() + verify_indices = runner.segments.add() + verify_y_values = runner.segments.add() + + runner.run( + f"compute_next_layer", + range_check_ptr=runner.range_check_builtin.base, + n_queries=len(queries), + queries=list(itertools.chain(*queries)), + sibling_witness=sibling_witness, + next_queries=next_queries, + verify_indices=verify_indices, + verify_y_values=verify_y_values, + params=structs.FriLayerComputationParams( + coset_size=coset_size, + fri_group=fri_group(), + eval_point=eval_point, + ), + ) + + ( + res_range_check_ptr, + res_n_queries, + res_queries, + res_sibling_witness, + res_next_queries, + res_verify_indices, + res_verify_y_values, + ) = runner.get_return_values(7) + + assert res_range_check_ptr.segment_index == runner.range_check_builtin.base.segment_index + assert res_n_queries == 0 + assert res_sibling_witness.offset == len(sibling_witness) + assert res_queries.offset == len(queries) * structs.FriLayerQuery.size + assert ( + res_next_queries == next_queries + len(expected_next_queries) * structs.FriLayerQuery.size + ) + for i, expected_next_query in enumerate(expected_next_queries): + res_next_query = structs.FriLayerQuery.from_ptr( + memory=runner.memory, addr=next_queries + i * structs.FriLayerQuery.size + ) + assert res_next_query == expected_next_query + assert expected_verify_indices == runner.memory.get_range( + verify_indices, res_verify_indices - verify_indices + ) + assert expected_verify_y_values == runner.memory.get_range( + verify_y_values, res_verify_y_values - verify_y_values + ) diff --git a/src/starkware/cairo/stark_verifier/core/fri/fri_test.py b/src/starkware/cairo/stark_verifier/core/fri/fri_test.py new file mode 100644 index 00000000..20ecd5a0 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/fri_test.py @@ -0,0 +1,71 @@ +import itertools +import os +import random + +import pytest + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.common.structs import CairoStructFactory, CairoStructProxy +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files +from starkware.cairo.lang.compiler.program import Program +from starkware.cairo.lang.vm.vm_exceptions import VmException +from starkware.python.math_utils import div_mod, horner_eval +from starkware.python.test_utils import maybe_raises + +CAIRO_FILE = os.path.join(os.path.dirname(__file__), "fri.cairo") + + +@pytest.fixture(scope="session") +def program() -> Program: + return compile_cairo_files([CAIRO_FILE], prime=DEFAULT_PRIME, debug_info=True) + + +@pytest.fixture +def structs(program): + return CairoStructFactory.from_program(program).structs + + +@pytest.mark.parametrize( + "success_verification", + [True, False], +) +def test_last_layer_verification( + program: Program, structs: CairoStructProxy, success_verification: bool +): + n_points = 8 + + # Choose a random polynomial of degree < 256: sum(poly[i] * x^i). + poly = [random.randrange(DEFAULT_PRIME) for _ in range(256)] + + # Choose random points and evaluate the polynomial on each of the points. + points = [random.randrange(DEFAULT_PRIME) for _ in range(n_points)] + values = [horner_eval(poly, x, DEFAULT_PRIME) for x in points] + + if not success_verification: + # Set one of the values/points to a wrong value. + index = random.randrange(n_points) + if random.randrange(2) == 0: + values[index] = values[index] - 1 + else: + points[index] = points[index] - 1 + + queries = [ + structs.FriLayerQuery( + index=0, # Irrelevant. + y_value=values[i], + x_inv_value=div_mod(1, points[i], DEFAULT_PRIME), + ) + for i in range(len(points)) + ] + runner = CairoFunctionRunner(program) + with maybe_raises( + VmException, None if success_verification else "ASSERT_EQ instruction failed" + ): + runner.run( + f"verify_last_layer", + n_queries=len(values), + queries=list(itertools.chain(*queries)), + n_coefficients=len(poly), + coefficients=poly, + ) diff --git a/src/starkware/cairo/stark_verifier/core/fri/test_utils.py b/src/starkware/cairo/stark_verifier/core/fri/test_utils.py new file mode 100644 index 00000000..88b99310 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/fri/test_utils.py @@ -0,0 +1,44 @@ +from typing import List, Tuple + +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.python.math_utils import horner_eval + + +def evaluate_polynomial_on_coset( + poly: List[int], x: int, coset_gen: int, coset_size_log2: int +) -> Tuple[List[int], List[int]]: + """ + Evaluates the given polynomial on the coset x* in bit reversed order. + Returns 2 lists: a list of the x values in the coset, and a list of the corresponding poly(x) + values. + """ + coset_size = 2**coset_size_log2 + coset_x_vals = [] + coset_poly_x_vals = [] + for i in range(coset_size): + # The input should be given in bit-reversed order. + # Convert i to its binary representation and reverse its bits. + rev_i = int(bin(i)[2:].rjust(coset_size_log2, "0")[::-1], 2) + x1 = x * pow(coset_gen, rev_i, DEFAULT_PRIME) + value = horner_eval(poly, x1, DEFAULT_PRIME) + coset_x_vals.append(x1) + coset_poly_x_vals.append(value) + + return (coset_x_vals, coset_poly_x_vals) + + +def apply_fri_steps_on_coset(poly: List[int], x: int, coset_size: int, eval_point: int) -> int: + """ + Applies log2(coset_szie) layers of FRI and evaluates the result on y=x^coset_size. + """ + result = 0 + y = pow(x, coset_size, DEFAULT_PRIME) + for i in range(coset_size): + # Take the coefficients of x^(coset_size * j + i). + coefs = poly[i::coset_size] + # Substitute x^coset_size in the resulting polynomial. + eval_x = horner_eval(coefs, y, DEFAULT_PRIME) + # Multiply by eval_point^i and sum the results. + result += eval_x * pow(eval_point, i, DEFAULT_PRIME) + + return result diff --git a/src/starkware/cairo/stark_verifier/core/merkle_test_data.json b/src/starkware/cairo/stark_verifier/core/merkle_test_data.json new file mode 100644 index 00000000..1fb3587c --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/merkle_test_data.json @@ -0,0 +1,301 @@ +{ + "expected_root": "0xc7621e7ee038de818a9e9b21d6c6bcc29c1f16b6000000000000000000000000", + "n_unique_queries": 15, + "merkle_height": 22, + "merkle_queue_indices": [ + 4990431, + 5345027, + 5377595, + 5466599, + 6126793, + 6265125, + 6590499, + 6865278, + 7233457, + 7269624, + 7315590, + 7414678, + 7614120, + 7961102, + 8110258 + ], + "merkle_queue_values": [ + "0x5b929e4ac28f9da99c07a6b273c700a32edb45fd000000000000000000000000", + "0xab4b1bfd52882a7af441888ad2e84ce3d1df3b24000000000000000000000000", + "0xa2f385a7545e4f60fb8667e92b83ce41404ef9bc000000000000000000000000", + "0x404a3e7837a5bf42cc43159f27f11d476aa67129000000000000000000000000", + "0xcb78d80a6117ab77cca3b60c6e12ee84eae7ead5000000000000000000000000", + "0x07ff99777899f62a8e896a28cad29542d5c9114a000000000000000000000000", + "0xe9f389884972b82d81d79a487abcdeb703b310ee000000000000000000000000", + "0x82c14adf65194f51a16326c336e0bb7aa7ca2cef000000000000000000000000", + "0x3a8fca9e5ec479e93adce03e90f8f273020b8322000000000000000000000000", + "0xdf58c21da7db339847d4cd11ec209195777a9e2b000000000000000000000000", + "0x4f08bc6372a7cc35057c6d808c36983566880fc6000000000000000000000000", + "0x9c5d6b9b2add4ac4850d87b062885d552a9aa5eb000000000000000000000000", + "0x46fe3756fb8014cabcfb6a015ff44b89ac4c8836000000000000000000000000", + "0x6d297cb1100d577b4f58835aa1bfca94f0182a1f000000000000000000000000", + "0xd2cfbca2467465f4a26ac5bb2fe90af20cf8e045000000000000000000000000" + ], + "proof": [ + "0x208301823101b37bdff7b2109afac02d3e80f215000000000000000000000000", + "0x0e975ca960c8498656c50dd83b63b847f6ee9d70000000000000000000000000", + "0x8a7bd7f525d3b0e3be4fb11e7c3320f0f11e1b8e000000000000000000000000", + "0x672989c4078e99bf55bf01fdc185e0a82bd07113000000000000000000000000", + "0x5ebe94cef0b524635e66cfdebefbbabce1f32db4000000000000000000000000", + "0x6b6735fdae06f5ecab9d087e547890f343221d90000000000000000000000000", + "0xbb9885b469b8cf75fe281ccbc3e4dd380f48e97c000000000000000000000000", + "0x7d09be18299e24c3e711e4ce34ab0ed14b9dacaf000000000000000000000000", + "0xa3f39bdf373e99dc221bbd9e45f6fbe7778c0a09000000000000000000000000", + "0x4759d187e595c09795b6459167a8d258148c1b58000000000000000000000000", + "0xef0d3f78eddb4c65840ee22a7915f9471ef68932000000000000000000000000", + "0x7dca9d73afb4871f54f14041ed8910bb8657b8a4000000000000000000000000", + "0x3c7faa4ee3a7e09857071adacf191c6fa1971ce8000000000000000000000000", + "0x43c15bb9a21d039f5191695473a8da970a1816e6000000000000000000000000", + "0x89607305fd53e9aaa136a580017a73f923c9e68e000000000000000000000000", + "0x64683fbff4c2600c382b86604ccc7da49cba9464000000000000000000000000", + "0x72b701ba533658f1e9751a5da9c3e5352a21b4e3000000000000000000000000", + "0x2d6c7a99e36ec855f1dea12cb14d9c3be393c7e3000000000000000000000000", + "0xf4614db054462e507aa390ed26e8594c6713b9b0000000000000000000000000", + "0x5ec31d4f8f3ce605cba229555c849cb43c765201000000000000000000000000", + "0x58645bba2d8dec6d2c2b32fe6557c452b1992df9000000000000000000000000", + "0xdf257a907fa4232d074326755ccae00109cf3873000000000000000000000000", + "0xa0daacfafb88c20a19fb03dcd712505880fb8889000000000000000000000000", + "0x7591d8b6753280500b1fb9693a59ec5115630d31000000000000000000000000", + "0xde9fe7e289c6aee1d0a6a765452bbbe668045af7000000000000000000000000", + "0x3cf39d984e99e16ef017c61996a189cde9c5d089000000000000000000000000", + "0x8b2a58a75f67ff437d1ced67327fbc82d39ac4af000000000000000000000000", + "0x011e017aaffcf9ab6babec04a797389a2325ab39000000000000000000000000", + "0xcd637d3c55241b52f4209d829a46482dd61dcb4d000000000000000000000000", + "0x87e38a3974f4093f74b7893c20285f53519d6dd2000000000000000000000000", + "0x2784a8eb55d81dd03c3e26047e1158d2d3df5276000000000000000000000000", + "0x4b2bfdad51e6e91f5f2cf250485a5620dbeeaaeb000000000000000000000000", + "0xdaa6daf2d911c6e2a208d0602fd6fdaa5e918f20000000000000000000000000", + "0xfdf0076cf1846a121d3c08aabb1116234e567744000000000000000000000000", + "0x88ab90ce50c6dddf9fd8cb9f8b0ed7e184c57f9a000000000000000000000000", + "0xdccdb25fe8db43b5ba79d14ca1488a3a7edf12f7000000000000000000000000", + "0xcbeb27ea13ba62f0d0fc321f273a586590be66cc000000000000000000000000", + "0x88d0752670c9d0a90ad6edff7b682e5ad416fee7000000000000000000000000", + "0x362e610bde5fc5ca8119270362e0c5669015fbe8000000000000000000000000", + "0xd16505f9688206bb2c08a29e9ef2e21dee3031d9000000000000000000000000", + "0x019be3a8e101d8d8e6e77e8adb7b95dc40f88e68000000000000000000000000", + "0x8c9b593c2283deb8108e75229d67e50c56bc146c000000000000000000000000", + "0xb503ac30476b39fe55be8a45d6b2ab44904c7ef9000000000000000000000000", + "0xc8701fd867e0936a45844278fcc075ba2ff907d6000000000000000000000000", + "0xe0763304a3b3eafec91a0fc16b2c900937291202000000000000000000000000", + "0xfed101a1aee27a579b408acfaa45f651bf4fdd2d000000000000000000000000", + "0x8f93be97c6121a915f21c68b48524294d86bcfc6000000000000000000000000", + "0x2d73d7509bde283b701558ee4ec282aeea3675a3000000000000000000000000", + "0x310f17e300c021c17707881eb6825f08329fcb67000000000000000000000000", + "0x9703fed4c6abddacf03705c27782769459e6c2ee000000000000000000000000", + "0x4c42eb4eb9e7c35432da811c071bfd1e877479f9000000000000000000000000", + "0x455680e6c383a8103b260d432217f822e50f9ef6000000000000000000000000", + "0x0dcfbdcddd7a5fa1578055158f277965be021a8b000000000000000000000000", + "0x82ca366130c48c900858f305c51272c8944fc644000000000000000000000000", + "0x91c97f1086e9e88053beb81410a29255610e6322000000000000000000000000", + "0x760886e2be938f09005e4e7a85fb69ee2277eb50000000000000000000000000", + "0x70069a1bb4700604bacb023fdd760644c7bc1c45000000000000000000000000", + "0x840078a8bb41cf966b60168e748ca3d265b9c771000000000000000000000000", + "0xbd1b332db44ccd42ebf880c2f4745fbe5dfa5ecd000000000000000000000000", + "0x4a5e7630bd5161a61de9b070c6dc10aa7007e910000000000000000000000000", + "0x4f57c9845115e3d3652a575ee8f097701e831b74000000000000000000000000", + "0xd34bbeba56445d7720b8e7f994e15c6f1826971b000000000000000000000000", + "0x1dad6050cbd403fbe5970029db7d672a995ca16a000000000000000000000000", + "0xa3b68ec4e3d8fde8029e65090e0b0a25b121f87d000000000000000000000000", + "0x906ddf76731ee83e7f861e3e5df311e7dddb192a000000000000000000000000", + "0xebb5db8935ed0f314633a964e6df9013acbf13b4000000000000000000000000", + "0x695f18643560553f070f59ca41c4246670cb737d000000000000000000000000", + "0x46368573293f2707b75682fabecc43df2f98e5e3000000000000000000000000", + "0x5ae2428989faa10aaf9ff06027d4db0769c847d1000000000000000000000000", + "0xb1c7de2837c5872f54f6f6848b78bc66c79a6ada000000000000000000000000", + "0x6f1f061cdfb89922172c351b545036d9c532a48b000000000000000000000000", + "0x762ade3ec9d836e447f7da82d182a1b73f0f3634000000000000000000000000", + "0x16a8c99e413f47d2a7811e1bc70f843d7b8f0433000000000000000000000000", + "0x073c277699370feff90926a9519424d577a7ed96000000000000000000000000", + "0xe88735dc2fdff70f5826a66f674373f41e6394e5000000000000000000000000", + "0xf3b94f9d84ad8f48d8cdb4d34b330d9d5c72248c000000000000000000000000", + "0xc768625d05923a94d00bfc9839a58ab373f1ee80000000000000000000000000", + "0x6f1d0ab1a535366fd1ded4a73145f8bf38c7e932000000000000000000000000", + "0xb311074987b801d4d1bb70365cb94996c75cb8cc000000000000000000000000", + "0xdd1d1635028dc522d09f8e9cb44fc176544b208e000000000000000000000000", + "0x70af8e3e5a5458a7f787495d4fb3238a6800defa000000000000000000000000", + "0xe4c3d4e28191cb6a4414ce363965c9ec886ca49f000000000000000000000000", + "0xd199ff9db20a5a7c19e4c2531f0627db09c62618000000000000000000000000", + "0x9096befc118f7e27101d2411fe7f939421cb2379000000000000000000000000", + "0x7533c195fc05853727c3b0b0188f84329b509ea2000000000000000000000000", + "0x0d37e3ff30252c62123807d85fe49a768c76aa16000000000000000000000000", + "0xdbc74146b06daf2a2d99b870bc46edaaf92ea6a6000000000000000000000000", + "0xebf8d07ce2b0ee8d5fe5c650db258b8de6be6353000000000000000000000000", + "0x9be137ba586d8c68b83c79f27de0a16871df8d09000000000000000000000000", + "0xc2ac76296e547b2044bffdd0bc8b08a0b5d76b07000000000000000000000000", + "0x530cd7d72a4a8b388563018eded1c2f0ca56a4e0000000000000000000000000", + "0xb4c77430887ce666b62f511b1ba8e3cbaad48ee0000000000000000000000000", + "0xb4a3a82873522e46065773ae45b00a3b5ab7d2c8000000000000000000000000", + "0x3fcc392c111a50e08d75a6a7c4626899125b73fc000000000000000000000000", + "0x2deeb5013eab779a579eb279275c44f6d9446275000000000000000000000000", + "0x7ecb355bc95303b367f738a7764d41a77f03cd4d000000000000000000000000", + "0xdcb2afb749e6ed810b8f93d5d8e1afac3b02d898000000000000000000000000", + "0xe76e05ed44d79d6a2651ca21f37fca7e22110fd1000000000000000000000000", + "0x11dc534bdf951fc249a10e56af4709d39d5da35f000000000000000000000000", + "0xa78a48098b9f4fd1fd5579d36f10ddbb06316195000000000000000000000000", + "0x815394d997b7530342ad8ff808e716f3635b32e8000000000000000000000000", + "0xe6b88671ac8c66e9700637f01b31564a6aedc236000000000000000000000000", + "0x1a931d81c1ed4c9a85a102580b4da294d6ab52db000000000000000000000000", + "0x1f052b581e80db5eb9e68bf12caab0afd802d630000000000000000000000000", + "0x490da7daa7724f18003c56b404572b50047e17f0000000000000000000000000", + "0xa51f186bbfe7e3317e41bdfb9d17413dac048320000000000000000000000000", + "0x6f66d99dc6398639c50524d0e8cd8908a255f1c7000000000000000000000000", + "0xc4ff5685510ad1ba515f4e382049813f78bf087b000000000000000000000000", + "0xe453e7a6ae181f82498403e6cee513e1ac950952000000000000000000000000", + "0x56ef2e86625cf375d7d99ac9d27eba77bc8c2588000000000000000000000000", + "0x65128da6d65a95db9a33d4b2f4f2fcb25bfa2c55000000000000000000000000", + "0x89489568701976f3c55dad5f339d7075b02f2743000000000000000000000000", + "0x63ba21b28b5b3c5203b5497f6a93893055e27bb2000000000000000000000000", + "0x326a96c9918048febe0fd46f53088c62b582cd7e000000000000000000000000", + "0x2559e8fd906db71dcc557e64971f6897b4874113000000000000000000000000", + "0x3f6121e75ef3b3b2f2b41f80cf86a6b6a7c2d733000000000000000000000000", + "0xef5a251bf433bff740f68dc4603a3607ed9ba860000000000000000000000000", + "0x6205bce260caff43e74a23d8d251024af48c7ef7000000000000000000000000", + "0x86a471cefeebf9ef60cfac35423097b7ef3a7c8c000000000000000000000000", + "0xe53f383cd8c46f7165bc275ea9eb2306e59826a2000000000000000000000000", + "0xd875313abc6e5b4506b3f61ccab489900a9cb862000000000000000000000000", + "0x39cea358896bec7bce80652838eadaa13c029f3a000000000000000000000000", + "0x1146bff84c1b1ac7ffe8246a8b0c409b41aa19cb000000000000000000000000", + "0x0ca7cd312e0f5b4d49a29601093c21dcc0d7e64a000000000000000000000000", + "0x3dfe808002041cbacfcf35797a567612c7c6ad16000000000000000000000000", + "0xc1bc600ff6cf65e5086313ffee50ac1b5c827fd6000000000000000000000000", + "0x64278cb5aba70c1c22e416e01863a32062edd638000000000000000000000000", + "0x2d8e70ec7ed66f1d266392e551e3c1ff590a19f0000000000000000000000000", + "0x78cf7cca8191b221c6ae7976d8554d82e94210a3000000000000000000000000", + "0xf06d91af5d48ef9b19f3a1db0380bb6ce9028c77000000000000000000000000", + "0x40a66880d2fd3c1b5ee646ea64938e4bb1f1974d000000000000000000000000", + "0x54b6079e9de8ec34781043e44a30fc331c7530d5000000000000000000000000", + "0xc08950ab0f81c70e184d9bfa77e746c34c6631bb000000000000000000000000", + "0x2c2ae9ba6fee430b7f44b156eb97de42c6ae3cb3000000000000000000000000", + "0x75451b506257ccb6237133a45d71c3193c09003f000000000000000000000000", + "0xeafd5d5c19ab80ae25fdd14a19099f5758dad24a000000000000000000000000", + "0xf6b91aa2e9dedeae4907b658a5f1ac1eac365f40000000000000000000000000", + "0x189b2a43465a6319cc2cdd1535292d29ade4ee62000000000000000000000000", + "0x9b104d55ceb86abfd9daeaffc2d257ad5e221ae6000000000000000000000000", + "0x3d6608e6b065365f7d25f35c15902eecf39a4bb5000000000000000000000000", + "0x771a562e6bbb1bf010f2d49f734c65c31763630a000000000000000000000000", + "0x3099f93d4321dfcc1237732c6d3a4fc1710306ee000000000000000000000000", + "0x6a680c13e56c1f09cf56f05d25222482be28d8a4000000000000000000000000", + "0xf74bd6b2d9321479749af048d7ac5227027148b1000000000000000000000000", + "0x3ede64a0756be63a3e9871c7658c555d3a1f937c000000000000000000000000", + "0xcc1e91947739b78c60f15ee3d0382ba085efab27000000000000000000000000", + "0x6673aa4a58d6f978ecfae2192890f66df0e6a1c5000000000000000000000000", + "0x6c6c0612d02aa05205b20be8329db6205c832bfe000000000000000000000000", + "0x93b4becf945d1893e78e40af6f5a5430b3c5d53b000000000000000000000000", + "0x0df8758a1af3a8b59f595415ab50a565473b20e5000000000000000000000000", + "0x15407c2845cbf4549e35ccc483fd351eaadf1f1b000000000000000000000000", + "0x7e06df62474cc1dc7fe03567d85e0fc939bc61b7000000000000000000000000", + "0x7e3caa9beaa54a8b45a23da01938f944f38afa3e000000000000000000000000", + "0x6bb1e7e476316d47162316786edc89a7cfbeae27000000000000000000000000", + "0x443d4e4bf67f5c31e7e97f0e0115cd68be4e4c89000000000000000000000000", + "0x304061be79e8a0a7f64dd8b765758b92f35a7813000000000000000000000000", + "0xe930f1754c7f085336606d46cd0fceb001daaa90000000000000000000000000", + "0x90bca252338fb194b3d6325f3470deed3771d855000000000000000000000000", + "0x9bcd7b51a56767abd7262a7798297bdad96d3a12000000000000000000000000", + "0xd371da4be0fec8be9b4c152c954cc2d6c19fa917000000000000000000000000", + "0x1cebcdda1bc726586c296040bf4f8b7b36b402ba000000000000000000000000", + "0x5cfa5e3bbc654e8a236d02ed02c200923a56d4a4000000000000000000000000", + "0x8733f2f336438bd06bf6951f6bff90fc678e9b56000000000000000000000000", + "0x2b3030c68bc717748f946bb2d3cbc14c1f3a200b000000000000000000000000", + "0x16924b9fa1f4b4dad636bac6129d08b097d6ffaa000000000000000000000000", + "0x7bfe468a3f1d893be2d311ad9416eabac14c49f4000000000000000000000000", + "0xb020a751db1979a69f7079584c22a1b545f139c7000000000000000000000000", + "0xf9669e77360742f4af7516d07907052c6ee9414d000000000000000000000000", + "0x75df9fc38aa093af20e1c81d9246d641bd0822f0000000000000000000000000", + "0x9b88306e18d7cdac317dcad3b31b306ee7e830fe000000000000000000000000", + "0xd1706952e02031ada2bb7add6510ada51ec03d15000000000000000000000000", + "0x3a539a83a412395dd84dbcbb59a8f8dbd0fd401a000000000000000000000000", + "0x6e47ef66fbb40a393f407c468a4a9eb9de021a3e000000000000000000000000", + "0x8f26f0b941b4641b8d6d15912e17535d4888a3e9000000000000000000000000", + "0x4a962d8d41e95e17bfffd98cac3822f81c0b9e2f000000000000000000000000", + "0x93a72d6ad2cd46e5be43a757a8a223129006ff46000000000000000000000000", + "0x29288511c727b94e43b71b510c953ed61478ff9b000000000000000000000000", + "0xac3cb403b61fdcac294b9bbe624cb2a2fb1a042d000000000000000000000000", + "0x05030d1810b3fee261024e842d21112c27c78410000000000000000000000000", + "0xa9c1f7bd2da007eaee9698df73d9c3a239f8d9e4000000000000000000000000", + "0xa928a5d55b6c886fa6d030fbb6d2cd9f5524cd99000000000000000000000000", + "0x33137a2e8559858919722e50a2cc62eded0ca023000000000000000000000000", + "0xf2859c35195ebcdd4e143ead79f30920d9d4dc4e000000000000000000000000", + "0xca34e2699f1831b2e1109ca9332cd9d7bdac55f4000000000000000000000000", + "0xdbbd93be537c376c4e0d9c92b8e863ac86c16711000000000000000000000000", + "0x0f9f2be7b0484dee2a25d5c2181e840c8dedcb5d000000000000000000000000", + "0xb6e54d3841db2b396f348640f16dfb75dafd934b000000000000000000000000", + "0xfcb13d675b0f25471ffe27c4e78f8f4a0c670dbe000000000000000000000000", + "0x8f49242d5b9b1e877ca860a99ceb01e46926357e000000000000000000000000", + "0xa2b1f5ce32770b8c7a3b58262d5ca97cb169e8a6000000000000000000000000", + "0x313bbb053703d5b3d23beebcd2d91b01a047af12000000000000000000000000", + "0xdd189274228e0712fe774bf2ed686e07235fdfa2000000000000000000000000", + "0xbd2bb7fda528da2da3d990ceddd014abe3c6a78f000000000000000000000000", + "0x6db0a6fc7f4ba0aec8369f532d170bea7ba7f719000000000000000000000000", + "0x5901c7adcd693f0ed8d335f9356d2ebeab0d7a05000000000000000000000000", + "0x7e9880256d9026f7a5958a51ecd4a6dc18ac2c56000000000000000000000000", + "0xce8fbbaa3957deddc6155308b4322f7ae3a32501000000000000000000000000", + "0xf015927d5a6a9c5fb96991c0ed7bfafc9d5ffb16000000000000000000000000", + "0xef17cd158863ca434b50abfb4f71ae1f9dd565b1000000000000000000000000", + "0x94a83fba7579237989b929ea6e31cee9aab0a586000000000000000000000000", + "0xc1191b4015a75f2b4137e8e1d7b49536df2276c4000000000000000000000000", + "0x980c7d43fa3ef83982a59163923a1a460a54f7fb000000000000000000000000", + "0xf694acc55ba1b9ae45374607ac2c0413be53e6b9000000000000000000000000", + "0x1316adbd2330fe7282285920f862ec5d5d71ef00000000000000000000000000", + "0x93ac80bfe68b60de90bb464ea2dd3b0a27f23756000000000000000000000000", + "0xb828bc0395ba6edeaa0efa13d7ff3662282615ac000000000000000000000000", + "0x2b63aaf927a3325936f604b7778577b78a7def9d000000000000000000000000", + "0x32a8e635c19bd2cf8ac1ed43ebdb4410bd299a81000000000000000000000000", + "0xa131baf88317f3a4e6d29292c9f5d8ab5db344fb000000000000000000000000", + "0xb7fa9de2dddb9d96c52a30a5965c73bf3915262e000000000000000000000000", + "0x4bb771b3d4018672c2a2af747231a9dfd75bf8b3000000000000000000000000", + "0x7ed8a0705e3a073da06ac648c3d02ee734e9cf95000000000000000000000000", + "0x577b345e05f02df4d211882d2b0022cc5ff9155f000000000000000000000000", + "0x598f52ceb74f7db9943553bedc0ee913ff877f61000000000000000000000000", + "0x46cd98372b1da4e03a10731ae7ea4b7d36419eec000000000000000000000000", + "0x10417e19de4b40b9211b7ce00272e99a08c1c9bd000000000000000000000000", + "0xac42d91d06eeb9a8947e6e1241ce7f5bc3d56881000000000000000000000000", + "0xf19cd1266ef8219e0f7915879af56fa46a2845c4000000000000000000000000", + "0xfe00ca0d816cd1ecb8adcf7da8f0d6c5a49a9524000000000000000000000000", + "0x4a3e824cdb5f958190d4165adb01036ee2ef23eb000000000000000000000000", + "0xc8d397312d706bdd769623d38fcf78df1fe4ff71000000000000000000000000", + "0x57186167eddac6f4c5fadd69213e9d8d99742f12000000000000000000000000", + "0x57cb027801f160640ec694b8723ce65ef66b8c9d000000000000000000000000", + "0x523e5bfd21284686ceb339f7813b514278ebba93000000000000000000000000", + "0xfdb6e43fd04fa3b513fad0585112080ca3414b3c000000000000000000000000", + "0x1699908faa4e1f33f73a6fd6aff390d5227e7b8a000000000000000000000000", + "0x59741060d03c33f2b17676c7a0b49a14149e3da5000000000000000000000000", + "0xdbdd07cc692a8140d1e159872dc64f5aa3264b18000000000000000000000000", + "0x69e483478bdcaca84dc952ff1f5ca291d0c934c3000000000000000000000000", + "0xeabbea663b20369227ef981cef1639d8393ab897000000000000000000000000", + "0x765efafbf226e43e9da5c4c15cb8468e2866cc0c000000000000000000000000", + "0xc125ff45f68bb520764ce6606c51986ae0af4ef4000000000000000000000000", + "0x6812a7594ba048be7329acacd430fe105c5f94a1000000000000000000000000", + "0x01a3e192bfe449390fb863108ad683da9f382592000000000000000000000000", + "0x2d9564b00721d68a5d25e1b2670ab14be5ca8812000000000000000000000000", + "0x4ca8ec2ab658f8c44afa01957d93a4e946203c63000000000000000000000000", + "0x8cb27c11dcfac70dbe517e0601326c2f997650d2000000000000000000000000", + "0x50916801c60ff374f8a1fcfab92c91805114fe48000000000000000000000000", + "0x30c0ee3133b60fb745e0ba3502ddb54473104ad1000000000000000000000000", + "0x9d4b247386d2424e2d672cec4f525956468ff35b000000000000000000000000", + "0xb8ca9b29a221d141337bf9025653cd06a5b5b386000000000000000000000000", + "0x6171cfee0f75f2b6c3fff357bbb28f200886fc5b000000000000000000000000", + "0x3a602807cd7f43ba28c4e8d162d45144a895e85f000000000000000000000000", + "0x9f12a4754e2f08d3b5e568080289b156e1ebed6c000000000000000000000000", + "0x7c2da885c1b179de5b11d931319c5db64ea63ed1000000000000000000000000", + "0xfb733e2e5ef31bc67c2328cafee4d0baf6f73e4c000000000000000000000000", + "0xcf920aad1a4de8042893ebd94ca97fc68fa89d1f000000000000000000000000", + "0xf5ac845d1da8eb342c011b3e95fbe7d603cfea32000000000000000000000000", + "0xabfc1a8c9ae541f58813c996bdb8f1b934161907000000000000000000000000", + "0xcf9cb187fe22796f4ef485c607b9a5883f1649ea000000000000000000000000", + "0xbca35177c9876e49a1a7fa3251d813543d01496f000000000000000000000000", + "0xf2d1da2ad1152b1e94580b19224a85c2aa80b29e000000000000000000000000", + "0x23b4da9c87282ea45a94eac96df24ec4a8c85eb7000000000000000000000000", + "0x113afbe5d030fcef074eed02db8f26138a7a350a000000000000000000000000", + "0xa5880edfb4c9ff30570c3dd32c9ca223dea2b944000000000000000000000000", + "0xa2340051ec5d95c63fbe1dab22081a44f1d3993a000000000000000000000000", + "0xbdc16019df3335165fd285bf384652a4aaf5eea8000000000000000000000000", + "0x22cd8438af5a2be32ce1a75e277ceb228bb88092000000000000000000000000", + "0x9ac45212aa1db93a48b8b74dd243e42a378afefa000000000000000000000000", + "0x676759f4e6ea768a80f62d116c6d7b7738a06c39000000000000000000000000" + ] +} diff --git a/src/starkware/cairo/stark_verifier/core/proof_of_work.cairo b/src/starkware/cairo/stark_verifier/core/proof_of_work.cairo new file mode 100644 index 00000000..eb706aa2 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/proof_of_work.cairo @@ -0,0 +1,92 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_blake2s.blake2s import blake2s_add_uint256_bigend, blake2s_bigend +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.math import assert_in_range, assert_lt, assert_nn_le, unsigned_div_rem +from starkware.cairo.common.pow import pow +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.stark_verifier.core.channel import ( + Channel, + ChannelSentFelt, + ChannelUnsentFelt, + read_uint64_from_prover, +) + +const MAX_PROOF_OF_WORK_BITS = 50; +const MAX_NONCE = 2 ** 64 - 1; +const BYTE_UPPER_BOUND = 256; +const WORD_UPPER_BOUND = BYTE_UPPER_BOUND ** 8; + +struct ProofOfWorkConfig { + // Proof of work difficulty (number of bits required to be 0). + n_bits: felt, +} + +struct ProofOfWorkUnsentCommitment { + nonce: ChannelUnsentFelt, +} + +func proof_of_work_config_validate{range_check_ptr}(config: ProofOfWorkConfig*) { + assert_in_range(config.n_bits, 1, MAX_PROOF_OF_WORK_BITS + 1); + return (); +} + +// Assumption: 0 < n_bits <= 64. +func proof_of_work_commit{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}(unsent_commitment: ProofOfWorkUnsentCommitment*, config: ProofOfWorkConfig*) { + alloc_locals; + let digest = channel.digest; + let (nonce) = read_uint64_from_prover(unsent_commitment.nonce); + verify_proof_of_work(digest=digest, n_bits=config.n_bits, nonce=nonce); + return (); +} + +func verify_proof_of_work{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + digest: Uint256, n_bits: felt, nonce: ChannelSentFelt +) { + alloc_locals; + // Validate ranges. + assert_nn_le(nonce.value, MAX_NONCE); + + // Compute the initial hash. + // Hash(0123456789abcded || digest_h || digest_l || n_bits). + // 0x8 bytes || 0x10 bytes || 0x10 bytes || 1 byte. + // Total of 0x29 bytes. + // Arrange the hash input according to the keccak requirement of 0x10 byte chunks. + let (digest_hh, digest_hl) = unsigned_div_rem(digest.high, WORD_UPPER_BOUND); + let (digest_lh, digest_ll) = unsigned_div_rem(digest.low, WORD_UPPER_BOUND); + let (data) = alloc(); + let data_start = data; + blake2s_add_uint256_bigend{data=data}( + Uint256( + low=digest_hl * WORD_UPPER_BOUND + digest_lh, + high=0x123456789abcded * WORD_UPPER_BOUND + digest_hh), + ); + // Align 72 bit value to MSB. + blake2s_add_uint256_bigend{data=data}( + Uint256( + low=0, + high=(digest_ll * BYTE_UPPER_BOUND + n_bits) * 2 ** 56 + ) + ); + let (init_hash) = blake2s_bigend(data=data_start, n_bytes=0x29); + + // Compute Hash(init_hash_high || init_hash_low || nonce) + // 0x10 bytes || 0x10 bytes || 8 bytes + // Total of 0x28 bytes. + let (data) = alloc(); + let data_start = data; + blake2s_add_uint256_bigend{data=data}(init_hash); + // Align 64 bit value to MSB. + static_assert MAX_NONCE == 2 ** 64 - 1; + blake2s_add_uint256_bigend{data=data}(Uint256( + low=0, + high=nonce.value * 2 ** 64 + )); + let (result) = blake2s_bigend(data=data_start, n_bytes=0x28); + let (work_limit) = pow(2, 128 - n_bits); + + // Check. + assert_lt(result.high, work_limit); + return (); +} diff --git a/src/starkware/cairo/stark_verifier/core/proof_of_work_test.py b/src/starkware/cairo/stark_verifier/core/proof_of_work_test.py new file mode 100644 index 00000000..3c427e19 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/proof_of_work_test.py @@ -0,0 +1,58 @@ +import os + +import pytest + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.common.structs import CairoStructFactory +from starkware.cairo.common.validate_utils import validate_builtin_usage +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files +from starkware.cairo.lang.compiler.program import Program +from starkware.cairo.lang.vm.vm_exceptions import VmException +from starkware.python.test_utils import maybe_raises + +CAIRO_FILE = os.path.join(os.path.dirname(__file__), "proof_of_work.cairo") + +# These values were taken from the C++ implementation. +DIGEST = 0x1C5A5F4381DF1F5CD7CA1D48A19D8FF802A71D94169DE38382621FDC5514A10A +NONCE = 0x1683B +N_BITS = 20 + + +@pytest.fixture(scope="session") +def program() -> Program: + return compile_cairo_files([CAIRO_FILE], prime=DEFAULT_PRIME, debug_info=True) + + +@pytest.fixture +def structs(program): + return CairoStructFactory.from_program( + program, additional_imports=["starkware.cairo.common.uint256.Uint256"] + ).structs + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "nonce, error_message", + [ + (NONCE, None), + (NONCE + 1, "out of range"), + ], +) +def test_proof_of_work(program: Program, structs, nonce, error_message): + runner = CairoFunctionRunner(program) + blake2s_start = runner.segments.add() + with maybe_raises(expected_exception=VmException, error_message=error_message): + runner.run( + "verify_proof_of_work", + range_check_ptr=runner.range_check_builtin.base, + blake2s_ptr=blake2s_start, + bitwise_ptr=runner.bitwise_builtin.base, + digest=structs.Uint256(low=DIGEST % 2**128, high=DIGEST >> 128), + n_bits=N_BITS, + nonce=structs.ChannelSentFelt(value=nonce), + ) + (range_check_ptr, blake2s_ptr, bitwise_ptr) = runner.get_return_values(3) + validate_builtin_usage(runner.range_check_builtin, range_check_ptr) + assert blake2s_ptr.segment_index == blake2s_start.segment_index + validate_builtin_usage(runner.bitwise_builtin, bitwise_ptr) diff --git a/src/starkware/cairo/stark_verifier/core/queries.cairo b/src/starkware/cairo/stark_verifier/core/queries.cairo new file mode 100644 index 00000000..e1b04dce --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/queries.cairo @@ -0,0 +1,97 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.math import assert_le, unsigned_div_rem +from starkware.cairo.common.pow import pow +from starkware.cairo.common.usort import usort +from starkware.cairo.stark_verifier.core.channel import Channel, random_uint256_to_prover +from starkware.cairo.stark_verifier.core.config import FIELD_GENERATOR, StarkDomains +from starkware.cairo.stark_verifier.core.utils import bit_reverse_u64 + +// Samples random queries from the verifier. +func generate_queries{ + blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel, range_check_ptr +}(n_samples: felt, stark_domains: StarkDomains*) -> (n_queries: felt, queries: felt*) { + alloc_locals; + + // Sample query indices from the channel. + let (samples: felt*) = alloc(); + sample_random_queries( + n_samples=n_samples, samples=samples, query_upper_bound=stark_domains.eval_domain_size + ); + + let (n_queries, queries: felt*, multiplicities: felt*) = usort( + input_len=n_samples, input=samples + ); + + return (n_queries=n_queries, queries=queries); +} + +func sample_random_queries{ + blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel, range_check_ptr +}(n_samples: felt, samples: felt*, query_upper_bound: felt) { + // Since samples are generated in quadruplets, we might generate up to 3 extra query indices. + // Return if we n_samples is 0, -1, -2 or -3. + if (n_samples * (n_samples + 1) * (n_samples + 2) * (n_samples + 3) == 0) { + return (); + } + let (res) = random_uint256_to_prover(); + let (hh, hl) = unsigned_div_rem(res.high, 2 ** 64); + let (lh, ll) = unsigned_div_rem(res.low, 2 ** 64); + let (_, r0) = unsigned_div_rem(hh, query_upper_bound); + let (_, r1) = unsigned_div_rem(hl, query_upper_bound); + let (_, r2) = unsigned_div_rem(lh, query_upper_bound); + let (_, r3) = unsigned_div_rem(ll, query_upper_bound); + assert samples[0] = r0; + assert samples[1] = r1; + assert samples[2] = r2; + assert samples[3] = r3; + return sample_random_queries( + n_samples=n_samples - 4, samples=&samples[4], query_upper_bound=query_upper_bound + ); +} + +// Computes the corresponding field element for each query index. +// I.e., index -> eval_generator ^ bit_revese(index). +func queries_to_points{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + n_queries: felt, queries: felt*, stark_domains: StarkDomains* +) -> (points: felt*) { + alloc_locals; + // Evaluation domains of size greater than 2**64 are not supported. + assert_le(stark_domains.log_eval_domain_size, 64); + + // A 'log_eval_domain_size' bits index can be bit reversed using bit_reverse_u64 if it is + // multiplied by 2**(64 - log_eval_domain_size) first. + let (shift) = pow(2, 64 - stark_domains.log_eval_domain_size); + let (points: felt*) = alloc(); + queries_to_points_inner( + n_queries=n_queries, + queries=queries, + points=points, + shift=shift, + eval_generator=stark_domains.eval_generator, + ); + return (points=points); +} + +func queries_to_points_inner{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + n_queries: felt, queries: felt*, points: felt*, shift: felt, eval_generator: felt +) { + alloc_locals; + if (n_queries == 0) { + return (); + } + let (reversed_index) = bit_reverse_u64(queries[0] * shift); + + // Compute the x value of the query in the evaluation domain coset: + // FIELD_GENERATOR * eval_generator ^ reversed_index. + let (point) = pow(eval_generator, reversed_index); + let point = point * FIELD_GENERATOR; + assert points[0] = point; + return queries_to_points_inner( + n_queries=n_queries - 1, + queries=&queries[1], + points=&points[1], + shift=shift, + eval_generator=eval_generator, + ); +} diff --git a/src/starkware/cairo/stark_verifier/core/stark.cairo b/src/starkware/cairo/stark_verifier/core/stark.cairo new file mode 100644 index 00000000..01333a2a --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/stark.cairo @@ -0,0 +1,376 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_blake2s.blake2s import finalize_blake2s +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.hash import HashBuiltin +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.stark_verifier.core.air_interface import ( + AirInstance, + OodsEvaluationInfo, + PublicInput, + TracesCommitment, + TracesConfig, + TracesDecommitment, + TracesUnsentCommitment, + TracesWitness, + eval_oods_boundary_poly_at_points, + public_input_hash, + public_input_validate, + traces_commit, + traces_decommit, + traces_eval_composition_polynomial, +) +from starkware.cairo.stark_verifier.core.channel import ( + Channel, + ChannelSentFelt, + ChannelUnsentFelt, + channel_new, + random_felts_to_prover, + read_felts_from_prover, +) +from starkware.cairo.stark_verifier.core.config import ( + StarkConfig, + StarkDomains, + stark_config_validate, + stark_domains_create, +) +from starkware.cairo.stark_verifier.core.fri.fri import ( + FriCommitment, + FriConfig, + FriDecommitment, + FriUnsentCommitment, + FriWitness, + fri_commit, + fri_decommit, +) +from starkware.cairo.stark_verifier.core.proof_of_work import ( + ProofOfWorkUnsentCommitment, + proof_of_work_commit, +) +from starkware.cairo.stark_verifier.core.queries import generate_queries, queries_to_points +from starkware.cairo.stark_verifier.core.table_commitment import ( + TableCommitment, + TableCommitmentWitness, + TableDecommitment, + TableUnsentCommitment, + table_commit, + table_decommit, +) + +// Protocol components: +// ====================== +// The verifier is built from protocol components. Each component is responsible for commitment +// and decommitment phase. The decommitment part can be regarded as proving a statement with certain +// parameters that are known only after the commitment phase. The XDecommitment struct holds these +// parameters. +// The XWitness struct is the witness required to prove this statement. +// +// For example, VectorDecommitment holds some indices to the committed vector and the corresponding +// values. +// The VectorWitness struct has the authentication paths of the merkle tree, required to prove the +// validity of the values. +// +// The Stark protocol itself is a component, with the statement having no parameters known only +// after the commitment phase, and thus, there is no StarkDecommitment. +// +// The interface of a component named X is: +// +// Structs: +// * XConfig: Configuration for the component. +// * XUnsentCommitment: Commitment values (e.g. hashes), before sending in the channel. +// Those values shouldn't be used directly (only by the channel). +// Used by x_commit() to generate a commitment XCommitment. +// * XCommitment: Represents the commitment after it is read from the channel. +// * XDecommitment: Responses for queries. +// * XWitness: Auxiliary information for proving the decommitment. +// +// Functions: +// * x_commit() - The commitment phase. Takes XUnsentCommitment and returns XCommitment. +// * x_decommit() - The decommitment phase. Verifies a decommitment. Uses the commitment and the +// witness. + +// n_oods_values := air.mask_size + air.constraint_degree. +struct StarkUnsentCommitment { + traces: TracesUnsentCommitment*, + composition: TableUnsentCommitment, + // n_oods_values elements. The i-th value is the evaluation of the i-th mask item polynomial at + // the OODS point, where the mask item polynomial is the interpolation polynomial of the + // corresponding column shifted by the corresponding row_offset. + oods_values: ChannelUnsentFelt*, + fri: FriUnsentCommitment*, + proof_of_work: ProofOfWorkUnsentCommitment*, +} + +struct StarkCommitment { + traces: TracesCommitment*, + composition: TableCommitment*, + interaction_after_composition: InteractionValuesAfterComposition*, + // n_oods_values elements. See StarkUnsentCommitment. + oods_values: ChannelSentFelt*, + interaction_after_oods: InteractionValuesAfterOods*, + fri: FriCommitment*, +} + +struct StarkWitness { + traces_decommitment: TracesDecommitment*, + traces_witness: TracesWitness*, + composition_decommitment: TableDecommitment*, + composition_witness: TableCommitmentWitness*, + fri_witness: FriWitness*, +} + +struct StarkProof { + config: StarkConfig*, + public_input: PublicInput*, + unsent_commitment: StarkUnsentCommitment*, + witness: StarkWitness*, +} + +// Interaction elements after each STARK phase. +struct InteractionValuesAfterTraces { + // n_constraints Coefficients for the AIR constraints. + coefficients: felt*, +} + +struct InteractionValuesAfterComposition { + // Out of domain sampling point. + oods_point: felt, +} + +struct InteractionValuesAfterOods { + // n_oods_values coefficients for the boundary polynomial validating the OODS values. + coefficients: felt*, +} + +// Verifies a STARK proof. +func verify_stark_proof{range_check_ptr, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*}( + air: AirInstance*, proof: StarkProof*, security_bits: felt +) -> () { + alloc_locals; + + // Validate config. + let config = proof.config; + stark_config_validate(air=air, config=config, security_bits=security_bits); + let (stark_domains) = stark_domains_create(config=config); + + // Validate the public input. + public_input_validate(air=air, public_input=proof.public_input, stark_domains=stark_domains); + + // Initialize blake2s. + let (blake2s_ptr: felt*) = alloc(); + local blake2s_ptr_start: felt* = blake2s_ptr; + + // Compute the initial hash seed for the Fiat-Shamir channel. + let (digest) = public_input_hash{blake2s_ptr=blake2s_ptr}( + air=air, public_input=proof.public_input + ); + + // Construct the channel. + let (channel: Channel) = channel_new(digest=digest); + + with blake2s_ptr, channel { + let (stark_commitment) = stark_commit( + air=air, + public_input=proof.public_input, + unsent_commitment=proof.unsent_commitment, + config=config, + stark_domains=stark_domains, + ); + // Generate queries. + let (n_queries, queries) = generate_queries( + n_samples=config.n_queries, stark_domains=stark_domains + ); + + stark_decommit( + air=air, + n_queries=n_queries, + queries=queries, + commitment=stark_commitment, + witness=proof.witness, + config=config, + stark_domains=stark_domains, + ); + } + + finalize_blake2s(blake2s_ptr_start, blake2s_ptr); + + return (); +} + +// STARK commitment phase. +func stark_commit{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel +}( + air: AirInstance*, + public_input: PublicInput*, + unsent_commitment: StarkUnsentCommitment*, + config: StarkConfig*, + stark_domains: StarkDomains*, +) -> (res: StarkCommitment*) { + alloc_locals; + + // Read the commitment of the 'traces' component. + let (traces_commitment) = traces_commit( + air=air, + public_input=public_input, + unsent_commitment=unsent_commitment.traces, + config=config.traces, + ); + + // Generate interaction values after traces commitment. + let (traces_coefficients: felt*) = alloc(); + random_felts_to_prover(n_elements=air.n_constraints, elements=traces_coefficients); + let (interaction_after_traces: InteractionValuesAfterTraces*) = alloc(); + assert [interaction_after_traces] = InteractionValuesAfterTraces( + coefficients=traces_coefficients); + + // Read composition commitment. + let (composition_commitment: TableCommitment*) = table_commit( + unsent_commitment=unsent_commitment.composition, config=config.composition + ); + + // Generate interaction values after composition. + let (interaction_after_composition: InteractionValuesAfterComposition*) = alloc(); + random_felts_to_prover( + n_elements=InteractionValuesAfterComposition.SIZE, + elements=cast(interaction_after_composition, felt*), + ); + + // Read OODS values. + local n_oods_values = air.mask_size + air.constraint_degree; + let (sent_oods_values) = read_felts_from_prover( + n_values=n_oods_values, values=unsent_commitment.oods_values + ); + + // Check that the trace and the composition agree at oods_point. + verify_oods( + air=air, + oods_values=sent_oods_values, + traces_commitment=traces_commitment, + traces_coefficients=traces_coefficients, + oods_point=interaction_after_composition.oods_point, + trace_domain_size=stark_domains.trace_domain_size, + trace_generator=stark_domains.trace_generator, + ); + + // Generate interaction values after OODS. + let (oods_coefficients: felt*) = alloc(); + random_felts_to_prover(n_elements=n_oods_values, elements=oods_coefficients); + tempvar interaction_after_oods = new InteractionValuesAfterOods( + coefficients=oods_coefficients); + + // Read fri commitment. + let (fri_commitment) = fri_commit(unsent_commitment=unsent_commitment.fri, config=config.fri); + + // Proof of work commitment phase. + proof_of_work_commit( + unsent_commitment=unsent_commitment.proof_of_work, config=config.proof_of_work + ); + + // Return commitment. + return ( + res=new StarkCommitment( + traces=traces_commitment, + composition=composition_commitment, + interaction_after_composition=interaction_after_composition, + oods_values=sent_oods_values, + interaction_after_oods=interaction_after_oods, + fri=fri_commitment), + ); +} + +// Checks that the trace and the compostion agree at oods_point, assuming the prover provided us +// with the proper evaluations. +func verify_oods{range_check_ptr}( + air: AirInstance*, + oods_values: ChannelSentFelt*, + traces_commitment: TracesCommitment*, + traces_coefficients: felt*, + oods_point: felt, + trace_domain_size: felt, + trace_generator: felt, +) { + let (composition_from_trace_values) = traces_eval_composition_polynomial( + air=air, + commitment=traces_commitment, + mask_values=cast(oods_values, felt*), + constraint_coefficients=traces_coefficients, + point=oods_point, + trace_domain_size=trace_domain_size, + trace_generator=trace_generator, + ); + + // This verification is currently only implemented for constraint degree 2. + assert air.constraint_degree = 2; + tempvar claimed_composition = ( + oods_values[air.mask_size + 0].value + oods_values[air.mask_size + 1].value * oods_point); + + assert composition_from_trace_values = claimed_composition; + + return (); +} + +// STARK decommitment phase. +func stark_decommit{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + air: AirInstance*, + n_queries: felt, + queries: felt*, + commitment: StarkCommitment*, + witness: StarkWitness*, + config: StarkConfig*, + stark_domains: StarkDomains*, +) { + alloc_locals; + + // First layer decommit. + traces_decommit( + air=air, + n_queries=n_queries, + queries=queries, + commitment=commitment.traces, + decommitment=witness.traces_decommitment, + witness=witness.traces_witness, + ); + table_decommit( + commitment=commitment.composition, + n_queries=n_queries, + queries=queries, + decommitment=witness.composition_decommitment, + witness=witness.composition_witness, + ); + + // Compute query points. + let (points) = queries_to_points( + n_queries=n_queries, queries=queries, stark_domains=stark_domains + ); + + // Evaluate the FRI input layer at query points. + tempvar eval_info = new OodsEvaluationInfo( + oods_values=commitment.oods_values, + oods_point=commitment.interaction_after_composition.oods_point, + trace_generator=stark_domains.trace_generator, + constraint_coefficients=commitment.interaction_after_oods.coefficients, + ); + let (oods_poly_evals) = eval_oods_boundary_poly_at_points( + air=air, + eval_info=eval_info, + n_points=n_queries, + points=points, + decommitment=witness.traces_decommitment, + composition_decommitment=witness.composition_decommitment, + ); + + // Decommit FRI. + tempvar fri_decommitment = new FriDecommitment( + n_values=n_queries, + values=oods_poly_evals, + points=points); + fri_decommit( + n_queries=n_queries, + queries=queries, + commitment=commitment.fri, + decommitment=fri_decommitment, + witness=witness.fri_witness, + ); + + return (); +} diff --git a/src/starkware/cairo/stark_verifier/core/table_commitment.cairo b/src/starkware/cairo/stark_verifier/core/table_commitment.cairo new file mode 100644 index 00000000..a61af2c6 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/table_commitment.cairo @@ -0,0 +1,160 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_blake2s.blake2s import blake2s_add_felts, blake2s_bigend +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.math import assert_nn, split_felt, unsigned_div_rem +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.stark_verifier.core.channel import MONTGOMERY_R, Channel, ChannelUnsentFelt +from starkware.cairo.stark_verifier.core.vector_commitment import ( + VectorCommitment, + VectorCommitmentConfig, + VectorCommitmentWitness, + VectorQuery, + VectorUnsentCommitment, + vector_commit, + vector_commitment_decommit, +) + +// Commitment values for a table commitment protocol. Used to generate a commitment by "reading" +// these values from the channel. +struct TableUnsentCommitment { + vector: VectorUnsentCommitment, +} + +// Commitment for a table (n_rows x n_columns) of field elements in montgomery form. +struct TableCommitment { + config: TableCommitmentConfig*, + vector_commitment: VectorCommitment*, +} + +struct TableCommitmentConfig { + n_columns: felt, + vector: VectorCommitmentConfig*, +} + +// Responses for queries to the table commitment. +// Each query corresponds to a full row of the table. +struct TableDecommitment { + // n_columns * n_queries values to decommit. + n_values: felt, + values: felt*, +} + +// Witness for a decommitment over queries. +struct TableCommitmentWitness { + vector: VectorCommitmentWitness*, +} + +func table_commit{ + blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel, range_check_ptr +}(unsent_commitment: TableUnsentCommitment, config: TableCommitmentConfig*) -> ( + res: TableCommitment* +) { + let (vector_commitment: VectorCommitment*) = vector_commit( + unsent_commitment=unsent_commitment.vector, config=config.vector + ); + return (res=new TableCommitment(config=config, vector_commitment=vector_commitment)); +} + +// Decommits a TableCommitment at multiple indices. +// rows must be sorted and unique. +// Args: +// commitment - the table commitment. +// n_queries - number of queries to decommit. +// queries - the claimed indices. +// decommitment - the claimed values at those indices. +// witness - the decommitment witness. +func table_decommit{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + commitment: TableCommitment*, + n_queries: felt, + queries: felt*, + decommitment: TableDecommitment*, + witness: TableCommitmentWitness*, +) { + alloc_locals; + + // Must have at least 1 column. + local n_columns = commitment.config.n_columns; + assert_nn(n_columns - 1); + assert decommitment.n_values = n_queries * n_columns; + + // Convert decommitment values to Montgomery form, since the commitment is in that form. + let (montgomery_values: felt*) = alloc(); + to_montgomery( + n_values=decommitment.n_values, values=decommitment.values, output=montgomery_values + ); + + // Generate queries to the underlying vector commitment. + let (vector_queries: VectorQuery*) = alloc(); + generate_vector_queries( + n_queries=n_queries, + queries=queries, + values=montgomery_values, + vector_queries=vector_queries, + n_columns=n_columns, + ); + + vector_commitment_decommit( + commitment=commitment.vector_commitment, + n_queries=n_queries, + queries=vector_queries, + witness=witness.vector, + ); + + return (); +} + +// Converts an array of felts to their montgomery representation. +func to_montgomery(n_values: felt, values: felt*, output: felt*) { + if (n_values == 0) { + return (); + } + assert output[0] = values[0] * MONTGOMERY_R; + return to_montgomery(n_values=n_values - 1, values=&values[1], output=&output[1]); +} + +// Generates vector queries to the underlying vector commitment from the table queries. +// Args: +// n_queries - number of table queries. Also the number of resulting vector queries. +// queries - input table queries (indices). +// decommitment - input table values. +// vector_queries - output vector queries. +// n_columns - number of columns in table. +func generate_vector_queries{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + n_queries: felt, queries: felt*, values: felt*, vector_queries: VectorQuery*, n_columns: felt +) { + if (n_queries == 0) { + return (); + } + + alloc_locals; + assert vector_queries.index = queries[0]; + if (n_columns == 1) { + let (high, low) = split_felt(values[0]); + assert vector_queries.value = Uint256(low=low, high=high); + + return generate_vector_queries( + n_queries=n_queries - 1, + queries=&queries[1], + values=&values[n_columns], + vector_queries=&vector_queries[1], + n_columns=n_columns, + ); + } + + let (data: felt*) = alloc(); + let data_start = data; + blake2s_add_felts{data=data}(n_elements=n_columns, elements=values, bigend=1); + let (hash) = blake2s_bigend(data=data_start, n_bytes=32 * n_columns); + + // Truncate hash. + let (low_h, low_l) = unsigned_div_rem(hash.low, 2 ** 96); + assert vector_queries.value = Uint256(low=low_h * 2 ** 96, high=hash.high); + + return generate_vector_queries( + n_queries=n_queries - 1, + queries=&queries[1], + values=&values[n_columns], + vector_queries=&vector_queries[1], + n_columns=n_columns, + ); +} diff --git a/src/starkware/cairo/stark_verifier/core/table_commitment_test.py b/src/starkware/cairo/stark_verifier/core/table_commitment_test.py new file mode 100644 index 00000000..4d04303f --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/table_commitment_test.py @@ -0,0 +1,86 @@ +import os + +import pytest + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.common.structs import CairoStructFactory +from starkware.cairo.common.validate_utils import validate_builtin_usage +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files +from starkware.cairo.lang.compiler.scoped_name import ScopedName + +CAIRO_FILE = os.path.join(os.path.dirname(__file__), "table_commitment.cairo") + + +@pytest.fixture(scope="session") +def program(): + return compile_cairo_files( + [CAIRO_FILE], + prime=DEFAULT_PRIME, + debug_info=True, + main_scope=ScopedName.from_string("starkware.cairo.stark_verifier.core.table_commitment"), + ) + + +@pytest.fixture +def structs(program): + return CairoStructFactory.from_program( + program, + additional_imports=[ + "starkware.cairo.stark_verifier.core.table_commitment.TableCommitment", + "starkware.cairo.stark_verifier.core.table_commitment.TableCommitmentConfig", + "starkware.cairo.stark_verifier.core.table_commitment.TableCommitmentWitness", + "starkware.cairo.stark_verifier.core.vector_commitment.VectorCommitment", + "starkware.cairo.stark_verifier.core.vector_commitment.VectorCommitmentConfig", + "starkware.cairo.stark_verifier.core.vector_commitment.VectorCommitmentWitness", + ], + ).structs + + +def test_table_commitment(program, structs): + vector_commitment_config = ( + structs.VectorCommitmentConfig( + height=5, + ), + ) + commitment = structs.TableCommitment( + vector_commitment=structs.VectorCommitment( + config=structs.VectorCommitmentConfig( + height=5, + ), + commitment_hash=575056728485645732317951179216147002053792710986, + ), + config=structs.TableCommitmentConfig( + n_columns=4, + vector=vector_commitment_config, + ), + ) + + queries = [1, 4] + values = [10] * 4 + [20] * 4 + + runner = CairoFunctionRunner(program, layout="small") + blake2s_ptr = runner.segments.add() + runner.run( + "table_decommit", + range_check_ptr=runner.range_check_builtin.base, + blake2s_ptr=blake2s_ptr, + bitwise_ptr=runner.bitwise_builtin.base, + commitment=commitment, + n_queries=len(queries), + queries=queries, + decommitment=structs.TableDecommitment( + n_values=len(values), + values=values, + ), + witness=structs.TableCommitmentWitness( + vector=structs.VectorCommitmentWitness( + n_authentications=6, + authentications=[8] * 12, + ), + ), + ) + (res_range_check_ptr, res_blake2s_ptr, res_bitwise_ptr) = runner.get_return_values(3) + validate_builtin_usage(runner.range_check_builtin, res_range_check_ptr) + assert res_blake2s_ptr.segment_index == blake2s_ptr.segment_index + validate_builtin_usage(runner.bitwise_builtin, res_bitwise_ptr) diff --git a/src/starkware/cairo/stark_verifier/core/utils.cairo b/src/starkware/cairo/stark_verifier/core/utils.cairo new file mode 100644 index 00000000..bab705c0 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/utils.cairo @@ -0,0 +1,32 @@ +from starkware.cairo.common.bitwise import bitwise_and +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.registers import get_label_location + +const FIELD_GENERATOR = 3; + +// Bit reverses a uint64 number. Assumes the input is known to be in [0, 2**64). +func bit_reverse_u64{bitwise_ptr: BitwiseBuiltin*}(num: felt) -> (res: felt) { + alloc_locals; + + // Swap 1 bit chunks, and shift left by 1. + let (masked) = bitwise_and(num, 0x5555555555555555); + let num = masked * (2 ** 2 - 1) + num; + // Swap 2 bit chunks, and shift left by 2. + let (masked) = bitwise_and(num, 0x6666666666666666); + let num = masked * (2 ** 4 - 1) + num; + // Swap 4 bit chunks, and shift left by 4. + let (masked) = bitwise_and(num, 0x7878787878787878); + let num = masked * (2 ** 8 - 1) + num; + // Swap 8 bit chunks, and shift left by 8. + let (masked) = bitwise_and(num, 0x7f807f807f807f80); + let num = masked * (2 ** 16 - 1) + num; + // Swap 16 bit chunks, and shift left by 16. + let (masked) = bitwise_and(num, 0x7fff80007fff8000); + let num = masked * (2 ** 32 - 1) + num; + // Swap 16 bit chunks, and shift left by 32. + let (masked) = bitwise_and(num, 0x7fffffff80000000); + let num = masked * (2 ** 64 - 1) + num; + + // Combine in reverse. + return (res=num / 2 ** 63); +} diff --git a/src/starkware/cairo/stark_verifier/core/utils_test.py b/src/starkware/cairo/stark_verifier/core/utils_test.py new file mode 100644 index 00000000..258f0986 --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/utils_test.py @@ -0,0 +1,35 @@ +import os + +import pytest + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.lang.builtins.bitwise.instance_def import CELLS_PER_BITWISE +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files +from starkware.cairo.lang.compiler.scoped_name import ScopedName + +CAIRO_FILE = os.path.join(os.path.dirname(__file__), "utils.cairo") + + +@pytest.fixture(scope="session") +def program(): + return compile_cairo_files( + [CAIRO_FILE], + prime=DEFAULT_PRIME, + debug_info=True, + main_scope=ScopedName.from_string("starkware.cairo.stark_verifier.core.utils"), + ) + + +@pytest.mark.parametrize("num", [0, 1, 2**64 - 1, 0x123456789ABCDEF0]) +def test_bit_reverse_u64(program, num): + expected_res = int(bin(num)[2:].zfill(64)[::-1], 2) + runner = CairoFunctionRunner(program, layout="small") + runner.run( + "bit_reverse_u64", + bitwise_ptr=runner.bitwise_builtin.base, + num=num, + ) + (bitwise_ptr, res) = runner.get_return_values(2) + assert bitwise_ptr == runner.bitwise_builtin.base + 6 * CELLS_PER_BITWISE + assert hex(res) == hex(expected_res) diff --git a/src/starkware/cairo/stark_verifier/core/vector_commitment.cairo b/src/starkware/cairo/stark_verifier/core/vector_commitment.cairo new file mode 100644 index 00000000..476b453b --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/vector_commitment.cairo @@ -0,0 +1,164 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_blake2s.blake2s import blake2s_add_uint256_bigend, blake2s_bigend +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.math import assert_nn, assert_nn_le, unsigned_div_rem +from starkware.cairo.common.pow import pow +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.stark_verifier.core.channel import ( + Channel, + ChannelSentFelt, + ChannelUnsentFelt, + read_truncated_hash_from_prover, +) + +// Commitment values for a vector commitment. Used to generate a commitment by "reading" these +// values from the channel. +struct VectorUnsentCommitment { + commitment_hash: ChannelUnsentFelt, +} + +// Commitment for a vector of field elements. +struct VectorCommitment { + config: VectorCommitmentConfig*, + commitment_hash: ChannelSentFelt, +} + +struct VectorCommitmentConfig { + height: felt, +} + +// Witness for a decommitment over queries. +struct VectorCommitmentWitness { + // The authentication values: all the siblings of the subtree generated by the queried indices, + // bottom layer up, left to right. + n_authentications: felt, + authentications: Uint256*, +} + +// A query to the vector commitment. +struct VectorQuery { + index: felt, + value: Uint256, +} + +func vector_commit{ + blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, channel: Channel, range_check_ptr +}(unsent_commitment: VectorUnsentCommitment, config: VectorCommitmentConfig*) -> ( + res: VectorCommitment* +) { + let (commitment_hash_value) = read_truncated_hash_from_prover( + value=unsent_commitment.commitment_hash + ); + return (res=new VectorCommitment(config=config, commitment_hash=commitment_hash_value)); +} + +// Decommits a VectorCommitment at multiple indices. +// Indices must be sorted and unique. +func vector_commitment_decommit{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + commitment: VectorCommitment*, + n_queries: felt, + queries: VectorQuery*, + witness: VectorCommitmentWitness*, +) { + alloc_locals; + + // Shift query indices. + let (shift) = pow(2, commitment.config.height); + let (shifted_queries: VectorQuery*) = alloc(); + shift_queries( + n_queries=n_queries, queries=queries, shifted_queries=shifted_queries, shift=shift + ); + + let authentications = witness.authentications; + let (expected_commitment) = verify_authentications{authentications=authentications}( + queue_head=shifted_queries, queue_tail=&shifted_queries[n_queries] + ); + assert authentications = &witness.authentications[witness.n_authentications]; + + // Make sure hash is truncated. + assert_nn(expected_commitment.low / 2 ** 96); + tempvar expected_truncated_hash = ( + expected_commitment.low + expected_commitment.high * 2 ** 128) / 2 ** 96; + assert expected_truncated_hash = commitment.commitment_hash.value; + return (); +} + +// Shifts the query indices by 2**height, to convert index representation to heap-like. +// Validates the query index range. +func shift_queries{range_check_ptr}( + n_queries: felt, queries: VectorQuery*, shifted_queries: VectorQuery*, shift: felt +) { + if (n_queries == 0) { + return (); + } + assert_nn_le(queries.index, shift - 1); + assert [shifted_queries] = VectorQuery( + index=queries.index + shift, + value=queries.value); + return shift_queries( + n_queries=n_queries - 1, + queries=&queries[1], + shifted_queries=&shifted_queries[1], + shift=shift, + ); +} + +// Verifies a queue of merkle queries. [queue_head, queue_tail) is a queue, where each element +// represents a node index (given in a heap-like indexing) and value (either an inner +// node or a leaf). +func verify_authentications{ + range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, authentications: Uint256* +}(queue_head: VectorQuery*, queue_tail: VectorQuery*) -> (hash: Uint256) { + alloc_locals; + + let current: VectorQuery = queue_head[0]; + let next: VectorQuery* = &queue_head[1]; + + // Check if we're at the root. + if (current.index == 1) { + // Make sure the queue is empty. + assert next = queue_tail; + return (hash=current.value); + } + + // Extract parent. + local bit; + %{ ids.bit = ids.current.index & 1 %} + assert bit = bit * bit; + local parent = (current.index - bit) / 2; + assert [range_check_ptr] = parent; + let range_check_ptr = range_check_ptr + 1; + + // Write parent to queue. + assert queue_tail.index = parent; + if (bit == 0) { + if (next != queue_tail and current.index + 1 == next.index) { + // next holds the sibling. + let (hash) = truncated_blake2s(current.value, next.value); + assert queue_tail.value = hash; + return verify_authentications(queue_head=&queue_head[2], queue_tail=&queue_tail[1]); + } + let (hash) = truncated_blake2s(current.value, authentications[0]); + } else { + let (hash) = truncated_blake2s(authentications[0], current.value); + } + + assert queue_tail.value = hash; + let authentications = &authentications[1]; + return verify_authentications(queue_head=&queue_head[1], queue_tail=&queue_tail[1]); +} + +// A 160 MSB truncated version of blake2s. +// hash: +// blake2s(x, y) & ~((1<<96) - 1). +func truncated_blake2s{range_check_ptr, blake2s_ptr: felt*, bitwise_ptr: BitwiseBuiltin*}( + x: Uint256, y: Uint256 +) -> (res: Uint256) { + let (data: felt*) = alloc(); + let data_start = data; + blake2s_add_uint256_bigend{data=data}(x); + blake2s_add_uint256_bigend{data=data}(y); + let (hash) = blake2s_bigend(data=data_start, n_bytes=64); + let (low_h, low_l) = unsigned_div_rem(hash.low, 2 ** 96); + return (res=Uint256(low=low_h * 2 ** 96, high=hash.high)); +} diff --git a/src/starkware/cairo/stark_verifier/core/vector_commitment_test.py b/src/starkware/cairo/stark_verifier/core/vector_commitment_test.py new file mode 100644 index 00000000..f58d282e --- /dev/null +++ b/src/starkware/cairo/stark_verifier/core/vector_commitment_test.py @@ -0,0 +1,93 @@ +import itertools +import json +import os + +import pytest + +from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.common.structs import CairoStructFactory +from starkware.cairo.common.validate_utils import validate_builtin_usage +from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files +from starkware.cairo.lang.compiler.scoped_name import ScopedName + +CAIRO_FILE = os.path.join(os.path.dirname(__file__), "vector_commitment.cairo") +TEST_DATA_FILE = os.path.join(os.path.dirname(__file__), "merkle_test_data.json") + + +@pytest.fixture(scope="session") +def program(): + return compile_cairo_files( + [CAIRO_FILE], + prime=DEFAULT_PRIME, + debug_info=True, + main_scope=ScopedName.from_string("starkware.cairo.stark_verifier.core.vector_commitment"), + ) + + +@pytest.fixture +def structs(program): + return CairoStructFactory.from_program( + program, + additional_imports=[ + "starkware.cairo.stark_verifier.core.vector_commitment.VectorUnsentCommitment", + "starkware.cairo.stark_verifier.core.vector_commitment.VectorCommitment", + "starkware.cairo.stark_verifier.core.vector_commitment.VectorCommitmentWitness", + "starkware.cairo.stark_verifier.core.vector_commitment.VectorCommitmentConfig", + ], + ).structs + + +def to_uint256(s): + x = int(s, 16) + return (x % (2**128), x >> 128) + + +def test_vector_commitment(program, structs): + with open( + TEST_DATA_FILE, + "r", + ) as fp: + data = json.load(fp) + commitment = structs.VectorCommitment( + config=structs.VectorCommitmentConfig( + height=data["merkle_height"], + ), + commitment_hash=int(data["expected_root"], 16) >> 96, + ) + + runner = CairoFunctionRunner(program, layout="small") + query_indices = data["merkle_queue_indices"] + query_values = data["merkle_queue_values"] + n_queries = len(query_indices) + queries = list( + itertools.chain( + *[ + runner.segments.gen_typed_args( + structs.VectorQuery( + index=index - 2 ** data["merkle_height"], + value=structs.Uint256(*to_uint256(value)), + ) + ) + for index, value in zip(query_indices, query_values) + ] + ) + ) + blake2s_ptr = runner.segments.add() + runner.run( + "vector_commitment_decommit", + range_check_ptr=runner.range_check_builtin.base, + blake2s_ptr=blake2s_ptr, + bitwise_ptr=runner.bitwise_builtin.base, + commitment=commitment, + n_queries=n_queries, + queries=queries, + witness=structs.VectorCommitmentWitness( + n_authentications=len(data["proof"]), + authentications=list(itertools.chain(*map(to_uint256, data["proof"]))), + ), + ) + (res_range_check_ptr, res_blake2s_ptr, res_bitwise_ptr) = runner.get_return_values(3) + validate_builtin_usage(runner.range_check_builtin, res_range_check_ptr) + assert res_blake2s_ptr.segment_index == blake2s_ptr.segment_index + validate_builtin_usage(runner.bitwise_builtin, res_bitwise_ptr) diff --git a/src/starkware/crypto/CMakeLists.txt b/src/starkware/crypto/CMakeLists.txt index c9106ab8..5cfadd51 100644 --- a/src/starkware/crypto/CMakeLists.txt +++ b/src/starkware/crypto/CMakeLists.txt @@ -1,16 +1,16 @@ python_lib(starkware_crypto_lib + PREFIX starkware/crypto + FILES - starkware/crypto/signature/fast_pedersen_hash.py - starkware/crypto/signature/math_utils.py - starkware/crypto/signature/nothing_up_my_sleeve_gen.py - starkware/crypto/signature/pedersen_params.json - starkware/crypto/signature/signature.py - ${STARKWARE_CRYPTO_LIB_ADDITIONAL_FILES} + signature/fast_pedersen_hash.py + signature/math_utils.py + signature/nothing_up_my_sleeve_gen.py + signature/pedersen_params.json + signature/signature.py LIBS pip_ecdsa pip_fastecdsa pip_mpmath pip_sympy - ${STARKWARE_CRYPTO_LIB_ADDITIONAL_LIBS} ) diff --git a/src/starkware/crypto/__init__.py b/src/starkware/crypto/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/starkware/crypto/signature/__init__.py b/src/starkware/crypto/signature/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/starkware/crypto/starkware/crypto/signature/fast_pedersen_hash.py b/src/starkware/crypto/signature/fast_pedersen_hash.py similarity index 95% rename from src/starkware/crypto/starkware/crypto/signature/fast_pedersen_hash.py rename to src/starkware/crypto/signature/fast_pedersen_hash.py index 67c20158..c1ecc4e0 100644 --- a/src/starkware/crypto/starkware/crypto/signature/fast_pedersen_hash.py +++ b/src/starkware/crypto/signature/fast_pedersen_hash.py @@ -24,7 +24,7 @@ def process_single_element(element: int, p1, p2) -> Point: - assert element < FIELD_PRIME, "Element integer value >= FIELD_PRIME" + assert 0 <= element < FIELD_PRIME, "Element integer value is out of range" high_nibble = element >> LOW_PART_BITS low_part = element & LOW_PART_MASK diff --git a/src/starkware/crypto/starkware/crypto/signature/math_utils.py b/src/starkware/crypto/signature/math_utils.py similarity index 100% rename from src/starkware/crypto/starkware/crypto/signature/math_utils.py rename to src/starkware/crypto/signature/math_utils.py diff --git a/src/starkware/crypto/starkware/crypto/signature/nothing_up_my_sleeve_gen.py b/src/starkware/crypto/signature/nothing_up_my_sleeve_gen.py similarity index 100% rename from src/starkware/crypto/starkware/crypto/signature/nothing_up_my_sleeve_gen.py rename to src/starkware/crypto/signature/nothing_up_my_sleeve_gen.py diff --git a/src/starkware/crypto/starkware/crypto/signature/pedersen_params.json b/src/starkware/crypto/signature/pedersen_params.json similarity index 100% rename from src/starkware/crypto/starkware/crypto/signature/pedersen_params.json rename to src/starkware/crypto/signature/pedersen_params.json diff --git a/src/starkware/crypto/starkware/crypto/signature/signature.py b/src/starkware/crypto/signature/signature.py similarity index 100% rename from src/starkware/crypto/starkware/crypto/signature/signature.py rename to src/starkware/crypto/signature/signature.py diff --git a/src/starkware/eth/eth_test_utils.py b/src/starkware/eth/eth_test_utils.py index 9cf76f2b..fedb7195 100644 --- a/src/starkware/eth/eth_test_utils.py +++ b/src/starkware/eth/eth_test_utils.py @@ -58,6 +58,9 @@ def advance_time(self, n_seconds: int): def get_block_by_hash(self, block_hash: str) -> "EthBlock": return EthBlock(w3_block=self.w3.eth.getBlock(block_hash)) + def get_balance(self, address: str) -> int: + return self.w3.eth.getBalance(address) + class Ganache: """ diff --git a/src/starkware/python/CMakeLists.txt b/src/starkware/python/CMakeLists.txt index de2c20b8..097e9ada 100644 --- a/src/starkware/python/CMakeLists.txt +++ b/src/starkware/python/CMakeLists.txt @@ -12,6 +12,7 @@ python_lib(starkware_python_utils_lib LIBS pip_pyyaml pip_sympy + pip_typing_extensions ) python_lib(starkware_expression_string_lib diff --git a/src/starkware/python/math_utils.py b/src/starkware/python/math_utils.py index 73bc4386..0735f75c 100644 --- a/src/starkware/python/math_utils.py +++ b/src/starkware/python/math_utils.py @@ -205,23 +205,58 @@ def horner_eval(coefs, point, prime): return res +class NotOnCurveException(Exception): + pass + + +def recover_y(x: int, alpha: int, beta: int, field_prime: int) -> int: + """ + Recovers the corresponding y coordinate on the elliptic curve + y^2 = x^3 + alpha * x + beta (mod field_prime) + of a given x coordinate. + """ + y_squared = pow(x, 3, field_prime) + alpha * x + beta + if is_quad_residue(y_squared, field_prime): + return sqrt(y_squared, field_prime) + raise NotOnCurveException(f"{x} does not represent the x coordinate of a point on the curve.") + + def random_ec_point( field_prime: int, alpha: int, beta: int, seed: Optional[bytes] = None ) -> Tuple[int, int]: """ - Returns a random point on the elliptic curve y^2 = x^3 + alpha * x + beta (mod field_prime). + Returns a random non-zero point on the elliptic curve + y^2 = x^3 + alpha * x + beta (mod field_prime). If `seed` is not None, the point is created deterministically from the seed. """ if seed is not None: # If a seed is given, the function currently only extracts a 256-bit number from it. assert field_prime < 2**256, "Field prime must be less than 2^256." + seed = sha256(seed).digest() for i in range(100): x = ( random.randrange(field_prime) if seed is None - else int(sha256(seed + i.to_bytes(10, "little")).hexdigest(), 16) + else int(sha256(seed[1:] + i.to_bytes(10, "little")).hexdigest(), 16) ) - y_squared = pow(x, 3, field_prime) + alpha * x + beta - if is_quad_residue(y_squared, field_prime): - return x, (random.choice([-1, 1]) * sqrt(y_squared, field_prime)) % field_prime + y_coef = (-1) ** (seed[0] & 1 if seed is not None else random.randrange(2)) + try: + y = recover_y(x, alpha, beta, field_prime) + return x, (y_coef * y) % field_prime + except NotOnCurveException: + continue raise Exception("Could not find a point on the curve.") + + +def safe_random_ec_point( + prime: int, alpha: int, generator: Tuple[int, int], curve_order: int +) -> Tuple[int, int]: + """ + A version of `random_ec_point` that never raises an exception. + Assumptions: + * `generator` is a generator point of a curve y^2 = x^3 + alpha * x + beta, for some beta. + * `curve_order` is the order of the same curve. + """ + res = ec_safe_mult(m=random.randrange(1, curve_order), point=generator, alpha=alpha, p=prime) + assert not isinstance(res, EcInfinity) + return res diff --git a/src/starkware/python/math_utils_test.py b/src/starkware/python/math_utils_test.py index 3b9ec376..bdf29b76 100644 --- a/src/starkware/python/math_utils_test.py +++ b/src/starkware/python/math_utils_test.py @@ -15,8 +15,10 @@ isqrt, next_power_of_2, prev_power_of_2, + random_ec_point, safe_div, safe_log2, + safe_random_ec_point, sqrt, ) @@ -143,3 +145,29 @@ def test_horner_eval(): assert sum(coef * pow(point, i, PRIME) for i, coef in enumerate(coefs)) % PRIME == horner_eval( coefs, point, PRIME ) + + +def test_random_ec_point(): + PRIME = (1 << 251) + (17 << 192) + 1 + ALPHA = 1 + BETA = 3141592653589793238462643383279502884197169399375105820974944592307816406665 + seed = random.randrange(1 << 256).to_bytes(32, "little") + ec_point = random_ec_point(field_prime=PRIME, alpha=ALPHA, beta=BETA, seed=seed) + x, y = ec_point + # Check that the returned point is on the curve. + assert pow(y, 2, PRIME) == (pow(x, 3, PRIME) + x * ALPHA + BETA) % PRIME + # Make sure the returned point is deterministic when the seed is constant. + for i in range(10): + assert ec_point == random_ec_point(PRIME, ALPHA, BETA, seed) + + +def test_safe_random_ec_point(): + PRIME = (1 << 251) + (17 << 192) + 1 + ALPHA = 1 + BETA = 3141592653589793238462643383279502884197169399375105820974944592307816406665 + EC_ORDER = 3618502788666131213697322783095070105526743751716087489154079457884512865583 + # Pick a random EC point and use it as the generator. + generator = random_ec_point(field_prime=PRIME, alpha=ALPHA, beta=BETA) + x, y = safe_random_ec_point(prime=PRIME, alpha=ALPHA, generator=generator, curve_order=EC_ORDER) + # Check that the returned point is on the curve. + assert pow(y, 2, PRIME) == (pow(x, 3, PRIME) + x * ALPHA + BETA) % PRIME diff --git a/src/starkware/python/utils.py b/src/starkware/python/utils.py index 531ece4c..d2346abb 100644 --- a/src/starkware/python/utils.py +++ b/src/starkware/python/utils.py @@ -1,4 +1,5 @@ import asyncio +import bisect import contextlib import itertools import logging @@ -6,31 +7,92 @@ import random import re import subprocess +import threading import time from collections import UserDict from typing import ( Any, + AsyncGenerator, AsyncIterable, Awaitable, Callable, + Coroutine, Dict, + Generic, Iterable, Iterator, List, Mapping, Optional, + Sequence, TypeVar, ) import yaml +from typing_extensions import Literal, Protocol # All functions with stubs are imported from this module. from starkware.python.utils_stub_module import * # noqa T = TypeVar("T") +TYield = TypeVar("TYield") +TSend = TypeVar("TSend") NumType = TypeVar("NumType", int, float) HASH_BYTES = 32 +# If more shared types start popping up here extract to types.py. +Endianness = Literal["big", "little"] +TComparable = TypeVar("TComparable", bound="Comparable") + + +class Comparable(Protocol): + """ + A protocol for comparable classes. + Used for type annotation. + """ + + def __eq__(self, other: Any) -> bool: + pass + + def __lt__(self: TComparable, other: TComparable) -> bool: + pass + + def __gt__(self: TComparable, other: TComparable) -> bool: + pass + + def __le__(self: TComparable, other: TComparable) -> bool: + pass + + def __ge__(self: TComparable, other: TComparable) -> bool: + pass + + +class TriviallyCopyable: + """ + Implements trivially the '__copy__' and the '__deepcopy__' methods. I.e., the following holds: + obj is copy(obj) and obj is deepcopy(obj). + """ + + def __deepcopy__(self, memo): + return self + + def __copy__(self): + return self + + +class TriviallyCopyableCallback(TriviallyCopyable, Generic[T]): + """ + Pypy's deepcopy has a bug with copying some objects, such as functions. + This class wrapps callable objects and implements the expected behaviour of the copy + functions on functions (which is trivial; see copy.py documentation). + """ + + def __init__(self, callback: Callable[..., T]): + self._callback = callback + + def __call__(self, *args: Any, **kwargs: Any) -> T: + return self._callback(*args, **kwargs) + def get_package_path(): """ @@ -46,18 +108,34 @@ def get_build_dir_path(rel_path=""): Returns a path to a file inside the build directory (or the docker). rel_path is the relative path of the file with respect to the build directory. """ - build_root = os.environ["BUILD_ROOT"] - return os.path.join(build_root, rel_path) + if "BUILD_ROOT" in os.environ: + return os.path.join(os.environ["BUILD_ROOT"], rel_path) + + from bazel_tools.tools.python.runfiles import runfiles + + return runfiles.Create().Rlocation(os.path.join("__main__", rel_path)) -def get_source_dir_path(rel_path=""): +def get_source_dir_path(rel_path: str = "", default_value: Optional[str] = None): """ Returns a path to a file inside the source directory. Does not work in docker. rel_path is the relative path of the file with respect to the source directory. """ - source_root = os.path.join(os.environ["BUILD_ROOT"], "../../") - assert os.path.exists(os.path.join(source_root, "src")) - return os.path.join(source_root, rel_path) + if "BUILD_ROOT" in os.environ: + source_root = os.path.join(os.environ["BUILD_ROOT"], "../../") + assert os.path.exists(os.path.join(source_root, "src")) + return os.path.join(source_root, rel_path) + + if "BUILD_WORKSPACE_DIRECTORY" in os.environ: + source_root = os.environ["BUILD_WORKSPACE_DIRECTORY"] + assert os.path.exists(os.path.join(source_root, "src")) + return os.path.join(source_root, rel_path) + + # If both BUILD_ROOT and BUILD_WORKSPACE_DIRECTORY are missing, return the default value. + if default_value is not None: + return default_value + + raise Exception(f"Failed to get source path for {rel_path}.") def assert_same_and_get(*args): @@ -123,6 +201,17 @@ def multiply_counter_by_scalar(scalar: NumType, counter: Mapping[T, NumType]) -> return {k: scalar * v for k, v in counter.items()} +def is_in_sorted_sequence(sorted_sequence: Sequence[TComparable], item: TComparable) -> bool: + """ + Returns True if and only if the given item is in the given sorted sequence. + """ + index = bisect.bisect_left(sorted_sequence, item) + if index == len(sorted_sequence): + return False + + return sorted_sequence[index] == item or sorted_sequence[index] is item + + def indent(code, indentation): """ Indent code by 'indentation' spaces. @@ -274,7 +363,7 @@ def composition_function(*args, **kwargs): def to_bytes( value: int, length: Optional[int] = None, - byte_order: Optional[str] = None, + byte_order: Optional[Endianness] = None, signed: Optional[bool] = None, ) -> bytes: """ @@ -294,7 +383,9 @@ def to_bytes( def from_bytes( - value: bytes, byte_order: Optional[str] = None, signed: Optional[bool] = None + value: bytes, + byte_order: Optional[Endianness] = None, + signed: Optional[bool] = None, ) -> int: """ Converts the given bytes object (parsed according to the given byte order) to an integer. @@ -429,3 +520,40 @@ def update_yaml_file(file_path: str, data: Dict[str, Any]): with open(file_path, "w") as fp: fp.write(yaml.dump(data=data, default_flow_style=False, width=400)) fp.flush() + + +def execute_coroutine_threadsafe( + coroutine: Coroutine[Any, Any, T], loop: asyncio.AbstractEventLoop +) -> T: + """ + Submits a coroutine object to a given event loop and returns the result. + """ + # Verify we are not inside the main thread (as this will block it). + coroutine_name = coroutine.__name__ # type: ignore[attr-defined] + assert ( + threading.current_thread() is not threading.main_thread() + ), f"Cannot run {coroutine_name} synchronously in main thread." + + future = asyncio.run_coroutine_threadsafe(coro=coroutine, loop=loop) + return future.result() + + +class aclosing(contextlib.AbstractAsyncContextManager, Generic[TYield, TSend]): + """ + Async context manager for safely finalizing an asynchronously cleaned-up resource such as an + async generator, calling its 'aclose()' method. + + This cleanup does not necessarily happen implicitly if a break (or exception) is coming from + the external loop. For example, see the test of this object. + + See https://peps.python.org/pep-0533/ for more info. + """ + + def __init__(self, agen: AsyncGenerator[TYield, TSend]): + self.agen = agen + + async def __aenter__(self) -> AsyncGenerator[TYield, TSend]: + return self.agen + + async def __aexit__(self, *exc_info): + await self.agen.aclose() diff --git a/src/starkware/python/utils_test.py b/src/starkware/python/utils_test.py index 2ae3555c..d5a405f3 100644 --- a/src/starkware/python/utils_test.py +++ b/src/starkware/python/utils_test.py @@ -1,3 +1,5 @@ +import asyncio +import functools import random import re import string @@ -7,13 +9,16 @@ from starkware.python.utils import ( WriteOnceDict, + aclosing, all_subclasses, as_non_optional, assert_exhausted, blockify, composite, + execute_coroutine_threadsafe, gather_in_chunks, indent, + is_in_sorted_sequence, iter_blockify, multiply_counter_by_scalar, safe_zip, @@ -185,3 +190,73 @@ def test_multiply_counter_by_scalar(): assert multiply_counter_by_scalar(scalar=5, counter=dict(a=1, b=2)) == dict(a=5, b=10) assert multiply_counter_by_scalar(scalar=0, counter=dict(a=1, b=2)) == dict(a=0, b=0) assert multiply_counter_by_scalar(scalar=-2, counter=dict(a=7, b=-1)) == dict(a=-14, b=2) + + +def test_is_in_sorted_sequence(): + sorted_list = [-1, 0, 1, 3, 7, 8, 15] + # In. + assert is_in_sorted_sequence(sorted_sequence=sorted_list, item=-1) + assert is_in_sorted_sequence(sorted_sequence=sorted_list, item=7) + + # Not in. + assert not is_in_sorted_sequence(sorted_sequence=sorted_list, item=-10) + assert not is_in_sorted_sequence(sorted_sequence=sorted_list, item=4) + assert not is_in_sorted_sequence(sorted_sequence=sorted_list, item=20) + + # Should work for special cases. + nan = float("nan") + + # Demo. + assert nan != nan + assert nan is nan + + # In. + assert is_in_sorted_sequence(sorted_sequence=[nan], item=nan) + + +@pytest.mark.asyncio +async def test_execute_coroutine_threadsafe(): + loop = asyncio.get_running_loop() + + async def foo(x: int) -> int: + return x + + def sync_foo(x: int) -> int: + return execute_coroutine_threadsafe(coroutine=foo(x), loop=loop) + + # Positive flow - run in a separate thread. + x = 5 + assert x == await loop.run_in_executor(executor=None, func=functools.partial(sync_foo, x=x)) + + # Negative flow - try to run in the main thread. + with pytest.raises(AssertionError, match="Cannot run foo synchronously in main thread."): + sync_foo(x=x) + + +@pytest.mark.asyncio +async def test_aclosing(): + closed: bool + + async def gen_foo(): + nonlocal closed + closed = False + try: + for i in range(5): + yield i + finally: + closed = True + + # Break an async loop before fully exhausting the generator, under the context manager. + async with aclosing(gen_foo()) as gen: + async for _ in gen: + break + + assert closed + + # Same, but without the context manager - the generator is expected to be alive after the break. + gen = gen_foo() + async for _ in gen: + break + + assert not closed + await gen.aclose() # Close properly. diff --git a/src/starkware/solidity/CMakeLists.txt b/src/starkware/solidity/CMakeLists.txt index 754af12e..ba9227d8 100644 --- a/src/starkware/solidity/CMakeLists.txt +++ b/src/starkware/solidity/CMakeLists.txt @@ -1,3 +1,5 @@ include(utils.cmake) +add_subdirectory(components) +add_subdirectory(interfaces) add_subdirectory(libraries) diff --git a/src/starkware/solidity/components/CMakeLists.txt b/src/starkware/solidity/components/CMakeLists.txt new file mode 100644 index 00000000..2381d081 --- /dev/null +++ b/src/starkware/solidity/components/CMakeLists.txt @@ -0,0 +1,24 @@ +python_lib(solidity_contracts_components_sol + PREFIX starkware/solidity/components + FILES + FactRegistry.sol + GovernedFinalizable.sol + OnchainDataFactTreeEncoder.sol + + LIBS + governance_interface_sol + named_storage_sol + solidity_contracts_interfaces_sol +) + +python_lib(governance_contract_sol + PREFIX starkware/solidity/components + FILES + GenericGovernance.sol + Governance.sol + GovernanceStorage.sol + Operator.sol + + LIBS + governance_interface_sol +) diff --git a/src/starkware/solidity/components/FactRegistry.sol b/src/starkware/solidity/components/FactRegistry.sol new file mode 100644 index 00000000..7b6400c0 --- /dev/null +++ b/src/starkware/solidity/components/FactRegistry.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "../interfaces/IQueryableFactRegistry.sol"; + +contract FactRegistry is IQueryableFactRegistry { + // Mapping: fact hash -> true. + mapping(bytes32 => bool) private verifiedFact; + + // Indicates whether the Fact Registry has at least one fact registered. + bool anyFactRegistered = false; + + /* + Checks if a fact has been verified. + */ + function isValid(bytes32 fact) external view override returns (bool) { + return _factCheck(fact); + } + + /* + This is an internal method to check if the fact is already registered. + In current implementation of FactRegistry it's identical to isValid(). + But the check is against the local fact registry, + So for a derived referral fact registry, it's not the same. + */ + function _factCheck(bytes32 fact) internal view returns (bool) { + return verifiedFact[fact]; + } + + function registerFact(bytes32 factHash) internal { + // This function stores the fact hash in the mapping. + verifiedFact[factHash] = true; + + // Mark first time off. + if (!anyFactRegistered) { + anyFactRegistered = true; + } + } + + /* + Indicates whether at least one fact was registered. + */ + function hasRegisteredFact() external view override returns (bool) { + return anyFactRegistered; + } +} diff --git a/src/starkware/solidity/components/GenericGovernance.sol b/src/starkware/solidity/components/GenericGovernance.sol new file mode 100644 index 00000000..73d21ce8 --- /dev/null +++ b/src/starkware/solidity/components/GenericGovernance.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "./Governance.sol"; + +contract GenericGovernance is Governance { + bytes32 immutable GOVERNANCE_INFO_TAG_HASH; + + constructor(string memory governanceContext) public { + GOVERNANCE_INFO_TAG_HASH = keccak256(abi.encodePacked(governanceContext)); + } + + /* + Returns the GovernanceInfoStruct associated with the governance tag. + */ + function getGovernanceInfo() internal view override returns (GovernanceInfoStruct storage gub) { + bytes32 location = GOVERNANCE_INFO_TAG_HASH; + assembly { + gub_slot := location + } + } + + function isGovernor(address user) external view returns (bool) { + return _isGovernor(user); + } + + function nominateNewGovernor(address newGovernor) external { + _nominateNewGovernor(newGovernor); + } + + function removeGovernor(address governorForRemoval) external { + _removeGovernor(governorForRemoval); + } + + function acceptGovernance() external { + _acceptGovernance(); + } + + function cancelNomination() external { + _cancelNomination(); + } +} diff --git a/src/starkware/solidity/components/Governance.sol b/src/starkware/solidity/components/Governance.sol new file mode 100644 index 00000000..8c56e8fb --- /dev/null +++ b/src/starkware/solidity/components/Governance.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "../interfaces/MGovernance.sol"; + +/* + Implements Generic Governance, applicable for both proxy and main contract, and possibly others. + Notes: + The use of the same function names by both the Proxy and a delegated implementation + is not possible since calling the implementation functions is done via the default function + of the Proxy. For this reason, for example, the implementation of MainContract (MainGovernance) + exposes mainIsGovernor, which calls the internal _isGovernor method. +*/ +struct GovernanceInfoStruct { + mapping(address => bool) effectiveGovernors; + address candidateGovernor; + bool initialized; +} + +abstract contract Governance is MGovernance { + event LogNominatedGovernor(address nominatedGovernor); + event LogNewGovernorAccepted(address acceptedGovernor); + event LogRemovedGovernor(address removedGovernor); + event LogNominationCancelled(); + + function getGovernanceInfo() internal view virtual returns (GovernanceInfoStruct storage); + + /* + Current code intentionally prevents governance re-initialization. + This may be a problem in an upgrade situation, in a case that the upgrade-to implementation + performs an initialization (for real) and within that calls initGovernance(). + + Possible workarounds: + 1. Clearing the governance info altogether by changing the MAIN_GOVERNANCE_INFO_TAG. + This will remove existing main governance information. + 2. Modify the require part in this function, so that it will exit quietly + when trying to re-initialize (uncomment the lines below). + */ + function initGovernance() internal { + GovernanceInfoStruct storage gub = getGovernanceInfo(); + require(!gub.initialized, "ALREADY_INITIALIZED"); + gub.initialized = true; // to ensure acceptNewGovernor() won't fail. + // Add the initial governer. + acceptNewGovernor(msg.sender); + } + + function _isGovernor(address user) internal view override returns (bool) { + GovernanceInfoStruct storage gub = getGovernanceInfo(); + return gub.effectiveGovernors[user]; + } + + /* + Cancels the nomination of a governor candidate. + */ + function _cancelNomination() internal onlyGovernance { + GovernanceInfoStruct storage gub = getGovernanceInfo(); + if (gub.candidateGovernor != address(0x0)) { + gub.candidateGovernor = address(0x0); + emit LogNominationCancelled(); + } + } + + function _nominateNewGovernor(address newGovernor) internal onlyGovernance { + GovernanceInfoStruct storage gub = getGovernanceInfo(); + require(newGovernor != address(0x0), "BAD_ADDRESS"); + require(!_isGovernor(newGovernor), "ALREADY_GOVERNOR"); + require(gub.candidateGovernor == address(0x0), "OTHER_CANDIDATE_PENDING"); + gub.candidateGovernor = newGovernor; + emit LogNominatedGovernor(newGovernor); + } + + /* + The acceptNewGovernor is called in two cases: + 1. by _acceptGovernance when a new governor accepts its role. + 2. by initGovernance to add the initial governor. + The difference is that the init path skips the nominate step + that would fail because of the onlyGovernance modifier. + */ + function acceptNewGovernor(address newGovernor) private { + require(!_isGovernor(newGovernor), "ALREADY_GOVERNOR"); + GovernanceInfoStruct storage gub = getGovernanceInfo(); + gub.effectiveGovernors[newGovernor] = true; + + // Emit governance information. + emit LogNewGovernorAccepted(newGovernor); + } + + function _acceptGovernance() internal { + // The new governor was proposed as a candidate by the current governor. + GovernanceInfoStruct storage gub = getGovernanceInfo(); + require(msg.sender == gub.candidateGovernor, "ONLY_CANDIDATE_GOVERNOR"); + + // Update state. + acceptNewGovernor(gub.candidateGovernor); + gub.candidateGovernor = address(0x0); + } + + /* + Remove a governor from office. + */ + function _removeGovernor(address governorForRemoval) internal onlyGovernance { + require(msg.sender != governorForRemoval, "GOVERNOR_SELF_REMOVE"); + GovernanceInfoStruct storage gub = getGovernanceInfo(); + require(_isGovernor(governorForRemoval), "NOT_GOVERNOR"); + gub.effectiveGovernors[governorForRemoval] = false; + emit LogRemovedGovernor(governorForRemoval); + } +} diff --git a/src/starkware/solidity/components/GovernanceStorage.sol b/src/starkware/solidity/components/GovernanceStorage.sol new file mode 100644 index 00000000..33f3a6bd --- /dev/null +++ b/src/starkware/solidity/components/GovernanceStorage.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; +import {GovernanceInfoStruct} from "./Governance.sol"; + +/* + Holds the governance slots for ALL entities, including proxy and the main contract. +*/ +contract GovernanceStorage { + // A map from a Governor tag to its own GovernanceInfoStruct. + mapping(string => GovernanceInfoStruct) internal governanceInfo; //NOLINT uninitialized-state. +} diff --git a/src/starkware/solidity/components/GovernedFinalizable.sol b/src/starkware/solidity/components/GovernedFinalizable.sol new file mode 100644 index 00000000..79d0804c --- /dev/null +++ b/src/starkware/solidity/components/GovernedFinalizable.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "starkware/solidity/interfaces/MGovernance.sol"; +import "starkware/solidity/libraries/NamedStorage.sol"; + +/** + A Governor controlled finalizable contract. + The inherited contract (the one that is GovernedFinalizable) implements the Governance. +*/ +abstract contract GovernedFinalizable is MGovernance { + event Finalized(); + + string constant STORAGE_TAG = "STARKWARE_CONTRACTS_GOVERENED_FINALIZABLE_1.0_TAG"; + + function isFinalized() public view returns (bool) { + return NamedStorage.getBoolValue(STORAGE_TAG); + } + + modifier notFinalized() { + require(!isFinalized(), "FINALIZED"); + _; + } + + function finalize() external onlyGovernance notFinalized { + NamedStorage.setBoolValue(STORAGE_TAG, true); + emit Finalized(); + } +} diff --git a/src/starkware/solidity/components/OnchainDataFactTreeEncoder.sol b/src/starkware/solidity/components/OnchainDataFactTreeEncoder.sol new file mode 100644 index 00000000..0554c9e6 --- /dev/null +++ b/src/starkware/solidity/components/OnchainDataFactTreeEncoder.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +library OnchainDataFactTreeEncoder { + struct DataAvailabilityFact { + uint256 onchainDataHash; + uint256 onchainDataSize; + } + + // The number of additional words appended to the public input when using the + // OnchainDataFactTreeEncoder format. + uint256 internal constant ONCHAIN_DATA_FACT_ADDITIONAL_WORDS = 2; + + /* + Encodes a GPS fact Merkle tree where the root has two children. + The left child contains the data we care about and the right child contains + on-chain data for the fact. + */ + function encodeFactWithOnchainData( + uint256[] calldata programOutput, + DataAvailabilityFact memory factData + ) internal pure returns (bytes32) { + // The state transition fact is computed as a Merkle tree, as defined in + // GpsOutputParser. + // + // In our case the fact tree looks as follows: + // The root has two children. + // The left child is a leaf that includes the main part - the information regarding + // the state transition required by this contract. + // The right child contains the onchain-data which shouldn't be accessed by this + // contract, so we are only given its hash and length + // (it may be a leaf or an inner node, this has no effect on this contract). + + // Compute the hash without the two additional fields. + uint256 mainPublicInputLen = programOutput.length; + bytes32 mainPublicInputHash = keccak256(abi.encodePacked(programOutput)); + + // Compute the hash of the fact Merkle tree. + bytes32 hashResult = keccak256( + abi.encodePacked( + mainPublicInputHash, + mainPublicInputLen, + factData.onchainDataHash, + mainPublicInputLen + factData.onchainDataSize + ) + ); + // Add one to the hash to indicate it represents an inner node, rather than a leaf. + return bytes32(uint256(hashResult) + 1); + } +} diff --git a/src/starkware/solidity/components/Operator.sol b/src/starkware/solidity/components/Operator.sol new file mode 100644 index 00000000..7880d89d --- /dev/null +++ b/src/starkware/solidity/components/Operator.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "../interfaces/MOperator.sol"; +import "../interfaces/MGovernance.sol"; + +/** + The Operator of the contract is the entity entitled to submit state update requests + by calling :sol:func:`updateState`. + + An Operator may be instantly appointed or removed by the contract Governor + (see :sol:mod:`Governance`). Typically, the Operator is the hot wallet of the service + submitting proofs for state updates. +*/ +abstract contract Operator is MGovernance, MOperator { + function registerOperator(address newOperator) external override onlyGovernance { + if (!isOperator(newOperator)) { + getOperators()[newOperator] = true; + emit LogOperatorAdded(newOperator); + } + } + + function unregisterOperator(address removedOperator) external override onlyGovernance { + if (isOperator(removedOperator)) { + getOperators()[removedOperator] = false; + emit LogOperatorRemoved(removedOperator); + } + } + + function isOperator(address user) public view override returns (bool) { + return getOperators()[user]; + } +} diff --git a/src/starkware/solidity/interfaces/BlockDirectCall.sol b/src/starkware/solidity/interfaces/BlockDirectCall.sol new file mode 100644 index 00000000..4f5860a9 --- /dev/null +++ b/src/starkware/solidity/interfaces/BlockDirectCall.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +/* + This contract provides means to block direct call of an external function. + A derived contract (e.g. MainDispatcherBase) should decorate sensitive functions with the + notCalledDirectly modifier, thereby preventing it from being called directly, and allowing only + calling using delegate_call. +*/ +abstract contract BlockDirectCall { + address immutable this_; + + constructor() internal { + this_ = address(this); + } + + modifier notCalledDirectly() { + require(this_ != address(this), "DIRECT_CALL_DISALLOWED"); + _; + } +} diff --git a/src/starkware/solidity/interfaces/CMakeLists.txt b/src/starkware/solidity/interfaces/CMakeLists.txt new file mode 100644 index 00000000..d083379a --- /dev/null +++ b/src/starkware/solidity/interfaces/CMakeLists.txt @@ -0,0 +1,28 @@ +python_lib(solidity_contracts_interfaces_sol + PREFIX starkware/solidity/interfaces + FILES + BlockDirectCall.sol + IFactRegistry.sol + Identity.sol + IQueryableFactRegistry.sol +) + +python_lib(governance_interface_sol + PREFIX starkware/solidity/interfaces + FILES + MGovernance.sol + MOperator.sol +) + +python_lib(solidity_contract_initializer_sol + PREFIX starkware/solidity/interfaces + FILES + ExternalInitializer.sol + ContractInitializer.sol + ProxySupport.sol + + LIBS + common_library_sol + governance_contract_sol + solidity_contracts_interfaces_sol +) diff --git a/src/starkware/solidity/interfaces/ContractInitializer.sol b/src/starkware/solidity/interfaces/ContractInitializer.sol new file mode 100644 index 00000000..ec01f988 --- /dev/null +++ b/src/starkware/solidity/interfaces/ContractInitializer.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +/** + Interface for contract initialization. + The functions it exposes are the app specific parts of the contract initialization, + and are called by the ProxySupport contract that implement the generic part of behind-proxy + initialization. +*/ +abstract contract ContractInitializer { + /* + The number of sub-contracts that the proxied contract consists of. + */ + function numOfSubContracts() internal pure virtual returns (uint256); + + /* + Indicates if the proxied contract has already been initialized. + Used to prevent re-init. + */ + function isInitialized() internal view virtual returns (bool); + + /* + Validates the init data that is passed into the proxied contract. + */ + function validateInitData(bytes calldata data) internal view virtual; + + /* + For a proxied contract that consists of sub-contracts, this function processes + the sub-contract addresses, e.g. validates them, stores them etc. + */ + function processSubContractAddresses(bytes calldata subContractAddresses) internal virtual; + + /* + This function applies the logic of initializing the proxied contract state, + e.g. setting root values etc. + */ + function initializeContractState(bytes calldata data) internal virtual; +} diff --git a/src/starkware/solidity/interfaces/ExternalInitializer.sol b/src/starkware/solidity/interfaces/ExternalInitializer.sol new file mode 100644 index 00000000..91652177 --- /dev/null +++ b/src/starkware/solidity/interfaces/ExternalInitializer.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +interface ExternalInitializer { + event LogExternalInitialize(bytes data); + + function initialize(bytes calldata data) external; +} diff --git a/src/starkware/solidity/interfaces/IFactRegistry.sol b/src/starkware/solidity/interfaces/IFactRegistry.sol new file mode 100644 index 00000000..94537e6a --- /dev/null +++ b/src/starkware/solidity/interfaces/IFactRegistry.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +/* + The Fact Registry design pattern is a way to separate cryptographic verification from the + business logic of the contract flow. + + A fact registry holds a hash table of verified "facts" which are represented by a hash of claims + that the registry hash check and found valid. This table may be queried by accessing the + isValid() function of the registry with a given hash. + + In addition, each fact registry exposes a registry specific function for submitting new claims + together with their proofs. The information submitted varies from one registry to the other + depending of the type of fact requiring verification. + + For further reading on the Fact Registry design pattern see this + `StarkWare blog post `_. +*/ +interface IFactRegistry { + /* + Returns true if the given fact was previously registered in the contract. + */ + function isValid(bytes32 fact) external view returns (bool); +} diff --git a/src/starkware/solidity/interfaces/IQueryableFactRegistry.sol b/src/starkware/solidity/interfaces/IQueryableFactRegistry.sol new file mode 100644 index 00000000..2ecfe369 --- /dev/null +++ b/src/starkware/solidity/interfaces/IQueryableFactRegistry.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "./IFactRegistry.sol"; + +/* + Extends the IFactRegistry interface with a query method that indicates + whether the fact registry has successfully registered any fact or is still empty of such facts. +*/ +interface IQueryableFactRegistry is IFactRegistry { + /* + Returns true if at least one fact has been registered. + */ + function hasRegisteredFact() external view returns (bool); +} diff --git a/src/starkware/solidity/interfaces/Identity.sol b/src/starkware/solidity/interfaces/Identity.sol new file mode 100644 index 00000000..d540c8d6 --- /dev/null +++ b/src/starkware/solidity/interfaces/Identity.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +interface Identity { + /* + Allows a caller to ensure that the provided address is of the expected type and version. + */ + function identify() external pure returns (string memory); +} diff --git a/src/starkware/solidity/interfaces/MGovernance.sol b/src/starkware/solidity/interfaces/MGovernance.sol new file mode 100644 index 00000000..33b3a5ab --- /dev/null +++ b/src/starkware/solidity/interfaces/MGovernance.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +abstract contract MGovernance { + function _isGovernor(address user) internal view virtual returns (bool); + + /* + Allows calling the function only by a Governor. + */ + modifier onlyGovernance() { + require(_isGovernor(msg.sender), "ONLY_GOVERNANCE"); + _; + } +} diff --git a/src/starkware/solidity/interfaces/MOperator.sol b/src/starkware/solidity/interfaces/MOperator.sol new file mode 100644 index 00000000..17f2c832 --- /dev/null +++ b/src/starkware/solidity/interfaces/MOperator.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "./MGovernance.sol"; + +abstract contract MOperator { + event LogOperatorAdded(address operator); + event LogOperatorRemoved(address operator); + + function isOperator(address user) public view virtual returns (bool); + + modifier onlyOperator() { + require(isOperator(msg.sender), "ONLY_OPERATOR"); + _; + } + + function registerOperator(address newOperator) external virtual; + + function unregisterOperator(address removedOperator) external virtual; + + function getOperators() internal view virtual returns (mapping(address => bool) storage); +} diff --git a/src/starkware/solidity/interfaces/ProxySupport.sol b/src/starkware/solidity/interfaces/ProxySupport.sol new file mode 100644 index 00000000..a2d049ab --- /dev/null +++ b/src/starkware/solidity/interfaces/ProxySupport.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "../components/Governance.sol"; +import "../libraries/Addresses.sol"; +import "./BlockDirectCall.sol"; +import "./ContractInitializer.sol"; + +/** + This contract contains the code commonly needed for a contract to be deployed behind + an upgradability proxy. + It perform the required semantics of the proxy pattern, + but in a generic manner. + Instantiation of the Governance and of the ContractInitializer, that are the app specific + part of initialization, has to be done by the using contract. +*/ +abstract contract ProxySupport is Governance, BlockDirectCall, ContractInitializer { + using Addresses for address; + + // The two function below (isFrozen & initialize) needed to bind to the Proxy. + function isFrozen() external view virtual returns (bool) { + return false; + } + + /* + The initialize() function serves as an alternative constructor for a proxied deployment. + + Flow and notes: + 1. This function cannot be called directly on the deployed contract, but only via + delegate call. + 2. If an EIC is provided - init is passed onto EIC and the standard init flow is skipped. + This true for both first intialization or a later one. + 3. The data passed to this function is as follows: + [sub_contracts addresses, eic address, initData]. + + When calling on an initialized contract (no EIC scenario), initData.length must be 0. + */ + function initialize(bytes calldata data) external notCalledDirectly { + uint256 eicOffset = 32 * numOfSubContracts(); + uint256 expectedBaseSize = eicOffset + 32; + require(data.length >= expectedBaseSize, "INIT_DATA_TOO_SMALL"); + address eicAddress = abi.decode(data[eicOffset:expectedBaseSize], (address)); + + bytes calldata subContractAddresses = data[:eicOffset]; + + processSubContractAddresses(subContractAddresses); + + bytes calldata initData = data[expectedBaseSize:]; + + // EIC Provided - Pass initData to EIC and the skip standard init flow. + if (eicAddress != address(0x0)) { + callExternalInitializer(eicAddress, initData); + return; + } + + if (isInitialized()) { + require(initData.length == 0, "UNEXPECTED_INIT_DATA"); + } else { + // Contract was not initialized yet. + validateInitData(initData); + initializeContractState(initData); + initGovernance(); + } + } + + function callExternalInitializer(address externalInitializerAddr, bytes calldata eicData) + private + { + require(externalInitializerAddr.isContract(), "EIC_NOT_A_CONTRACT"); + + // NOLINTNEXTLINE: low-level-calls, controlled-delegatecall. + (bool success, bytes memory returndata) = externalInitializerAddr.delegatecall( + abi.encodeWithSelector(this.initialize.selector, eicData) + ); + require(success, string(returndata)); + require(returndata.length == 0, string(returndata)); + } +} diff --git a/src/starkware/solidity/libraries/Addresses.sol b/src/starkware/solidity/libraries/Addresses.sol new file mode 100644 index 00000000..4aed72dc --- /dev/null +++ b/src/starkware/solidity/libraries/Addresses.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +/* + Common Utility Libraries. + I. Addresses (extending address). +*/ +library Addresses { + /* + Note: isContract function has some known limitation. + See https://github.com/OpenZeppelin/ + openzeppelin-contracts/blob/master/contracts/utils/Address.sol. + */ + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { + size := extcodesize(account) + } + return size > 0; + } + + function performEthTransfer(address recipient, uint256 amount) internal { + (bool success, ) = recipient.call{value: amount}(""); // NOLINT: low-level-calls. + require(success, "ETH_TRANSFER_FAILED"); + } + + /* + Safe wrapper around ERC20/ERC721 calls. + This is required because many deployed ERC20 contracts don't return a value. + See https://github.com/ethereum/solidity/issues/4116. + */ + function safeTokenContractCall(address tokenAddress, bytes memory callData) internal { + require(isContract(tokenAddress), "BAD_TOKEN_ADDRESS"); + // NOLINTNEXTLINE: low-level-calls. + (bool success, bytes memory returndata) = tokenAddress.call(callData); + require(success, string(returndata)); + + if (returndata.length > 0) { + require(abi.decode(returndata, (bool)), "TOKEN_OPERATION_FAILED"); + } + } +} diff --git a/src/starkware/solidity/libraries/CMakeLists.txt b/src/starkware/solidity/libraries/CMakeLists.txt index 0d701b14..500be57c 100644 --- a/src/starkware/solidity/libraries/CMakeLists.txt +++ b/src/starkware/solidity/libraries/CMakeLists.txt @@ -3,3 +3,9 @@ python_lib(named_storage_sol FILES NamedStorage.sol ) + +python_lib(common_library_sol + PREFIX starkware/solidity/libraries + FILES + Addresses.sol +) diff --git a/src/starkware/solidity/utils.py b/src/starkware/solidity/utils.py index e1f4acda..be0dc5ca 100644 --- a/src/starkware/solidity/utils.py +++ b/src/starkware/solidity/utils.py @@ -1,14 +1,18 @@ import inspect import json -import os +from pathlib import Path -def load_nearby_contract(name) -> dict: +def load_nearby_contract(name: str) -> dict: """ Loads a contract json from the directory of the caller module. """ frame = inspect.stack()[1] module = inspect.getmodule(frame[0]) - filename = module.__file__ # type: ignore - with open(os.path.join(os.path.dirname(filename), f"{name}.json")) as fp: + assert module is not None + filename = module.__file__ + assert filename is not None + + path = Path(filename).parent / f"{name}.json" + with path.open() as fp: return json.load(fp) diff --git a/src/starkware/starknet/apps/amm_sample/amm_sample.cairo b/src/starkware/starknet/apps/amm_sample/amm_sample.cairo index 8b53730e..04d6050d 100644 --- a/src/starkware/starknet/apps/amm_sample/amm_sample.cairo +++ b/src/starkware/starknet/apps/amm_sample/amm_sample.cairo @@ -3,148 +3,153 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.hash import hash2 from starkware.cairo.common.math import assert_le, assert_nn_le, unsigned_div_rem -from starkware.starknet.common.syscalls import storage_read, storage_write +from starkware.starknet.common.syscalls import get_caller_address, storage_read, storage_write -# The maximum amount of each token that belongs to the AMM. -const BALANCE_UPPER_BOUND = 2 ** 64 +// The maximum amount of each token that belongs to the AMM. +const BALANCE_UPPER_BOUND = 2 ** 64; -const TOKEN_TYPE_A = 1 -const TOKEN_TYPE_B = 2 +const TOKEN_TYPE_A = 1; +const TOKEN_TYPE_B = 2; -# Ensure the user's balances are much smaller than the pool's balance. -const POOL_UPPER_BOUND = 2 ** 30 -const ACCOUNT_BALANCE_BOUND = 1073741 # 2**30 // 1000. +// Ensure the user's balances are much smaller than the pool's balance. +const POOL_UPPER_BOUND = 2 ** 30; +const ACCOUNT_BALANCE_BOUND = 1073741; // 2**30 // 1000. -# A map from account and token type to the corresponding balance of that account. +// A map from account and token type to the corresponding balance of that account. @storage_var -func account_balance(account_id : felt, token_type : felt) -> (balance : felt): -end +func account_balance(account_id: felt, token_type: felt) -> (balance: felt) { +} -# A map from token type to the corresponding balance of the pool. +// A map from token type to the corresponding balance of the pool. @storage_var -func pool_balance(token_type : felt) -> (balance : felt): -end - -# Adds amount to the account's balance for the given token. -# amount may be positive or negative. -# Assert before setting that the balance does not exceed the upper bound. -func modify_account_balance{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - account_id : felt, token_type : felt, amount : felt -): - let (current_balance) = account_balance.read(account_id, token_type) - tempvar new_balance = current_balance + amount - assert_nn_le(new_balance, BALANCE_UPPER_BOUND - 1) - account_balance.write(account_id=account_id, token_type=token_type, value=new_balance) - return () -end - -# Returns the account's balance for the given token. +func pool_balance(token_type: felt) -> (balance: felt) { +} + +// Adds amount to the account's balance for the given token. +// amount may be positive or negative. +// Assert before setting that the balance does not exceed the upper bound. +func modify_account_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + account_id: felt, token_type: felt, amount: felt +) { + let (current_balance) = account_balance.read(account_id, token_type); + tempvar new_balance = current_balance + amount; + assert_nn_le(new_balance, BALANCE_UPPER_BOUND - 1); + account_balance.write(account_id=account_id, token_type=token_type, value=new_balance); + return (); +} + +// Returns the account's balance for the given token. @view -func get_account_token_balance{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - account_id : felt, token_type : felt -) -> (balance : felt): - return account_balance.read(account_id, token_type) -end - -# Sets the pool's balance for the given token. -# Asserts before setting that the balance does not exceed the upper bound. -func set_pool_token_balance{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - token_type : felt, balance : felt -): - assert_nn_le(balance, BALANCE_UPPER_BOUND - 1) - pool_balance.write(token_type, balance) - return () -end - -# Returns the pool's balance. +func get_account_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + account_id: felt, token_type: felt +) -> (balance: felt) { + return account_balance.read(account_id, token_type); +} + +// Sets the pool's balance for the given token. +// Asserts before setting that the balance does not exceed the upper bound. +func set_pool_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + token_type: felt, balance: felt +) { + assert_nn_le(balance, BALANCE_UPPER_BOUND - 1); + pool_balance.write(token_type, balance); + return (); +} + +// Returns the pool's balance. @view -func get_pool_token_balance{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - token_type : felt -) -> (balance : felt): - return pool_balance.read(token_type) -end - -# Swaps tokens between the given account and the pool. -func do_swap{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - account_id : felt, token_from : felt, token_to : felt, amount_from : felt -) -> (amount_to : felt): - alloc_locals - - # Get pool balance. - let (local amm_from_balance) = get_pool_token_balance(token_type=token_from) - let (local amm_to_balance) = get_pool_token_balance(token_type=token_to) - - # Calculate swap amount. +func get_pool_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + token_type: felt +) -> (balance: felt) { + return pool_balance.read(token_type); +} + +// Swaps tokens between the given account and the pool. +func do_swap{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + account_id: felt, token_from: felt, token_to: felt, amount_from: felt +) -> (amount_to: felt) { + alloc_locals; + + // Get pool balance. + let (local amm_from_balance) = get_pool_token_balance(token_type=token_from); + let (local amm_to_balance) = get_pool_token_balance(token_type=token_to); + + // Calculate swap amount. let (local amount_to, _) = unsigned_div_rem( amm_to_balance * amount_from, amm_from_balance + amount_from - ) - - # Update token_from balances. - modify_account_balance(account_id=account_id, token_type=token_from, amount=-amount_from) - set_pool_token_balance(token_type=token_from, balance=amm_from_balance + amount_from) - - # Update token_to balances. - modify_account_balance(account_id=account_id, token_type=token_to, amount=amount_to) - set_pool_token_balance(token_type=token_to, balance=amm_to_balance - amount_to) - return (amount_to=amount_to) -end - -func get_opposite_token(token_type : felt) -> (t : felt): - if token_type == TOKEN_TYPE_A: - return (TOKEN_TYPE_B) - else: - return (TOKEN_TYPE_A) - end -end - -# Swaps tokens between the given account and the pool. + ); + + // Update token_from balances. + modify_account_balance(account_id=account_id, token_type=token_from, amount=-amount_from); + set_pool_token_balance(token_type=token_from, balance=amm_from_balance + amount_from); + + // Update token_to balances. + modify_account_balance(account_id=account_id, token_type=token_to, amount=amount_to); + set_pool_token_balance(token_type=token_to, balance=amm_to_balance - amount_to); + return (amount_to=amount_to); +} + +func get_opposite_token(token_type: felt) -> (t: felt) { + if (token_type == TOKEN_TYPE_A) { + return (t=TOKEN_TYPE_B); + } else { + return (t=TOKEN_TYPE_A); + } +} + +// Swaps tokens between the given account and the pool. @external -func swap{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - account_id : felt, token_from : felt, amount_from : felt -) -> (amount_to : felt): - # Verify that token_from is either TOKEN_TYPE_A or TOKEN_TYPE_B. - assert (token_from - TOKEN_TYPE_A) * (token_from - TOKEN_TYPE_B) = 0 - - # Check requested amount_from is valid. - assert_nn_le(amount_from, BALANCE_UPPER_BOUND - 1) - # Check user has enough funds. +func swap{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + token_from: felt, amount_from: felt +) -> (amount_to: felt) { + let (account_id) = get_caller_address(); + + // Verify that token_from is either TOKEN_TYPE_A or TOKEN_TYPE_B. + assert (token_from - TOKEN_TYPE_A) * (token_from - TOKEN_TYPE_B) = 0; + + // Check requested amount_from is valid. + assert_nn_le(amount_from, BALANCE_UPPER_BOUND - 1); + // Check user has enough funds. let (account_from_balance) = get_account_token_balance( account_id=account_id, token_type=token_from - ) - assert_le(amount_from, account_from_balance) + ); + assert_le(amount_from, account_from_balance); - let (token_to) = get_opposite_token(token_type=token_from) + let (token_to) = get_opposite_token(token_type=token_from); let (amount_to) = do_swap( account_id=account_id, token_from=token_from, token_to=token_to, amount_from=amount_from - ) + ); - return (amount_to=amount_to) -end + return (amount_to=amount_to); +} -# Adds demo tokens to the given account. +// Adds demo tokens to the given account. @external -func add_demo_token{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - account_id : felt, token_a_amount : felt, token_b_amount : felt -): - # Make sure the account's balance is much smaller then pool init balance. - assert_nn_le(token_a_amount, ACCOUNT_BALANCE_BOUND - 1) - assert_nn_le(token_b_amount, ACCOUNT_BALANCE_BOUND - 1) - - modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_A, amount=token_a_amount) - modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_B, amount=token_b_amount) - return () -end - -# Until we have LPs, for testing, we'll need to initialize the AMM somehow. +func add_demo_token{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + token_a_amount: felt, token_b_amount: felt +) { + let (account_id) = get_caller_address(); + + // Make sure the account's balance is much smaller than + // the pool init balance. + assert_nn_le(token_a_amount, ACCOUNT_BALANCE_BOUND - 1); + assert_nn_le(token_b_amount, ACCOUNT_BALANCE_BOUND - 1); + + modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_A, amount=token_a_amount); + modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_B, amount=token_b_amount); + return (); +} + +// Until we have LPs, for testing, we'll need to initialize the AMM somehow. @external -func init_pool{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - token_a : felt, token_b : felt -): - assert_nn_le(token_a, POOL_UPPER_BOUND - 1) - assert_nn_le(token_b, POOL_UPPER_BOUND - 1) +func init_pool{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + token_a: felt, token_b: felt +) { + assert_nn_le(token_a, POOL_UPPER_BOUND - 1); + assert_nn_le(token_b, POOL_UPPER_BOUND - 1); - set_pool_token_balance(token_type=TOKEN_TYPE_A, balance=token_a) - set_pool_token_balance(token_type=TOKEN_TYPE_B, balance=token_b) + set_pool_token_balance(token_type=TOKEN_TYPE_A, balance=token_a); + set_pool_token_balance(token_type=TOKEN_TYPE_B, balance=token_b); - return () -end + return (); +} diff --git a/src/starkware/starknet/business_logic/CMakeLists.txt b/src/starkware/starknet/business_logic/CMakeLists.txt index f6f0ec70..fd7054a6 100644 --- a/src/starkware/starknet/business_logic/CMakeLists.txt +++ b/src/starkware/starknet/business_logic/CMakeLists.txt @@ -1,5 +1,7 @@ add_subdirectory(execution) +add_subdirectory(fact_state) add_subdirectory(state) +add_subdirectory(transaction) python_lib(starknet_business_logic_utils_lib PREFIX starkware/starknet/business_logic @@ -9,89 +11,18 @@ python_lib(starknet_business_logic_utils_lib LIBS cairo_function_runner_lib - starknet_abi_lib - starknet_business_logic_state_lib - starknet_contract_class_lib - starknet_definitions_lib - starknet_execution_usage_lib - starknet_general_config_lib - starknet_transaction_execution_objects_lib - starknet_transaction_hash_lib - starkware_error_handling_lib - starkware_storage_lib -) - -python_lib(starknet_internal_transaction_interface_lib - PREFIX starkware/starknet/business_logic - - FILES - internal_transaction_interface.py - - LIBS cairo_vm_lib - everest_business_logic_lib - everest_internal_transaction_lib - everest_transaction_lib - starknet_business_logic_state_lib - starknet_definitions_lib - starknet_general_config_lib - starknet_transaction_lib - starknet_transaction_execution_objects_lib - starkware_config_utils_lib - starkware_error_handling_lib -) - -python_lib(starknet_internal_transaction_lib - PREFIX starkware/starknet/business_logic - - FILES - internal_transaction.py - - LIBS - cairo_vm_lib - everest_business_logic_lib - everest_internal_transaction_lib - everest_transaction_lib starknet_abi_lib + starknet_business_logic_fact_state_lib + starknet_business_logic_patricia_state_lib starknet_business_logic_state_lib - starknet_business_logic_utils_lib - starknet_contract_address_lib starknet_contract_class_lib starknet_definitions_lib - starknet_execute_entry_point_lib + starknet_execution_usage_lib starknet_general_config_lib - starknet_internal_transaction_interface_lib - starknet_os_abi_lib - starknet_os_utils_lib starknet_transaction_execution_objects_lib - starknet_transaction_fee_lib starknet_transaction_hash_lib - starknet_transaction_lib - starkware_config_utils_lib - starkware_dataclasses_utils_lib starkware_error_handling_lib starkware_python_utils_lib starkware_storage_lib - pip_marshmallow - pip_marshmallow_dataclass - pip_marshmallow_enum - pip_marshmallow_oneofschema -) - -python_lib(starknet_transaction_fee_lib - PREFIX starkware/starknet/business_logic - - FILES - transaction_fee.py - - LIBS - starknet_abi_lib - starknet_business_logic_state_lib - starknet_business_logic_utils_lib - starknet_contract_class_lib - starknet_definitions_lib - starknet_execute_entry_point_lib - starknet_general_config_lib - starknet_transaction_execution_objects_lib - starkware_error_handling_lib ) diff --git a/src/starkware/starknet/business_logic/execution/CMakeLists.txt b/src/starkware/starknet/business_logic/execution/CMakeLists.txt index 15d161dd..4df9db40 100644 --- a/src/starkware/starknet/business_logic/execution/CMakeLists.txt +++ b/src/starkware/starknet/business_logic/execution/CMakeLists.txt @@ -8,11 +8,15 @@ python_lib(starknet_transaction_execution_objects_lib cairo_vm_lib everest_definitions_lib everest_internal_transaction_lib + starknet_abi_lib + starknet_business_logic_patricia_state_lib starknet_business_logic_state_lib starknet_contract_class_lib starknet_definitions_lib starknet_transaction_lib + starkware_dataclasses_field_utils_lib starkware_dataclasses_utils_lib + starkware_python_utils_lib pip_marshmallow pip_marshmallow_dataclass ) @@ -24,6 +28,7 @@ python_lib(starknet_execute_entry_point_base_lib execute_entry_point_base.py LIBS + starknet_business_logic_fact_state_lib starknet_business_logic_state_lib starknet_contract_class_lib starknet_definitions_lib @@ -43,6 +48,7 @@ python_lib(starknet_execute_entry_point_lib cairo_relocatable_lib cairo_vm_lib starknet_abi_lib + starknet_business_logic_fact_state_lib starknet_business_logic_state_lib starknet_business_logic_utils_lib starknet_contract_class_lib @@ -66,10 +72,8 @@ python_lib(starknet_execution_usage_lib LIBS cairo_vm_lib services_eth_gas_constants_lib - starknet_business_logic_state_lib starknet_definitions_lib starknet_transaction_execution_objects_lib starkware_dataclasses_utils_lib - starkware_python_utils_lib pip_marshmallow_dataclass ) diff --git a/src/starkware/starknet/business_logic/execution/execute_entry_point.py b/src/starkware/starknet/business_logic/execution/execute_entry_point.py index 9e46ab9f..5272e6da 100644 --- a/src/starkware/starknet/business_logic/execution/execute_entry_point.py +++ b/src/starkware/starknet/business_logic/execution/execute_entry_point.py @@ -17,8 +17,14 @@ CallType, TransactionExecutionContext, ) -from starkware.starknet.business_logic.state.state import CarriedState -from starkware.starknet.business_logic.utils import get_return_values +from starkware.starknet.business_logic.fact_state.state import ExecutionResourcesManager +from starkware.starknet.business_logic.state.state import StateSyncifier +from starkware.starknet.business_logic.state.state_api import State, SyncState +from starkware.starknet.business_logic.utils import ( + get_deployed_class_hash_at_address, + get_return_values, + validate_contract_deployed, +) from starkware.starknet.core.os import os_utils, syscall_utils from starkware.starknet.definitions import fields from starkware.starknet.definitions.error_codes import StarknetErrorCode @@ -29,7 +35,6 @@ ContractEntryPoint, EntryPointType, ) -from starkware.starknet.storage.starknet_storage import BusinessLogicStarknetStorage from starkware.starkware_utils.error_handling import ( StarkException, stark_assert, @@ -45,22 +50,43 @@ class ExecuteEntryPoint(ExecuteEntryPointBase): """ @classmethod - def create_for_testing( + def create( cls, contract_address: int, calldata: List[int], entry_point_selector: int, - entry_point_type: Optional[EntryPointType] = None, - caller_address: int = 0, + caller_address: int, + entry_point_type: EntryPointType, call_type: Optional[CallType] = None, class_hash: Optional[bytes] = None, ): return cls( call_type=CallType.CALL if call_type is None else call_type, contract_address=contract_address, + calldata=calldata, code_address=None, class_hash=class_hash, entry_point_selector=entry_point_selector, + entry_point_type=entry_point_type, + caller_address=caller_address, + ) + + @classmethod + def create_for_testing( + cls, + contract_address: int, + calldata: List[int], + entry_point_selector: int, + entry_point_type: Optional[EntryPointType] = None, + caller_address: int = 0, + call_type: Optional[CallType] = None, + class_hash: Optional[bytes] = None, + ): + return cls.create( + call_type=call_type, + contract_address=contract_address, + class_hash=class_hash, + entry_point_selector=entry_point_selector, entry_point_type=( EntryPointType.EXTERNAL if entry_point_type is None else entry_point_type ), @@ -70,8 +96,9 @@ def create_for_testing( async def execute_for_testing( self, - state: CarriedState, + state: State, general_config: StarknetGeneralConfig, + resources_manager: Optional[ExecutionResourcesManager] = None, tx_execution_context: Optional[TransactionExecutionContext] = None, ) -> CallInfo: if tx_execution_context is None: @@ -79,30 +106,15 @@ async def execute_for_testing( n_steps=general_config.invoke_tx_max_n_steps ) - return await self.execute( - state=state, general_config=general_config, tx_execution_context=tx_execution_context - ) + if resources_manager is None: + resources_manager = ExecutionResourcesManager.empty() - async def execute( - self, - state: CarriedState, - general_config: StarknetGeneralConfig, - tx_execution_context: TransactionExecutionContext, - ) -> CallInfo: - """ - Executes the selected entry point with the given calldata in the specified contract. - The information collected from this run (number of steps required, modifications to the - contract storage, etc.) is saved on the carried state argument. - Returns a CallInfo object that represents the execution. - """ - # Pass the running loop before entering to it. It will be used to run asynchronous - # tasks, such as fetching data from storage. - loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() + loop: asyncio.AbstractEventLoop = asyncio.get_running_loop() sync_execute = functools.partial( - self.sync_execute, - state=state, + self.execute, + state=StateSyncifier(async_state=state, loop=loop), + resources_manager=resources_manager, general_config=general_config, - loop=loop, tx_execution_context=tx_execution_context, ) @@ -111,38 +123,30 @@ async def execute( func=sync_execute, ) - def sync_execute( + def execute( self, - state: CarriedState, + state: SyncState, + resources_manager: ExecutionResourcesManager, general_config: StarknetGeneralConfig, - loop: asyncio.AbstractEventLoop, tx_execution_context: TransactionExecutionContext, ) -> CallInfo: """ - Synchronous version of execute_entry_point with a given TransactionExecutionContext object; - needed since this function also runs inside Cairo hints (when processing internal contract - calls). - Should be called from whithin the given loop. + Executes the selected entry point with the given calldata in the specified contract. + The information collected from this run (number of steps required, modifications to the + contract storage, etc.) is saved on the resources manager. + Returns a CallInfo object that represents the execution. """ - previous_cairo_usage = state.cairo_usage + previous_cairo_usage = resources_manager.cairo_usage runner, syscall_handler = self._run( state=state, + resources_manager=resources_manager, general_config=general_config, - loop=loop, tx_execution_context=tx_execution_context, ) - # Apply modifications to the contract storage. - state.update_contract_storage( - contract_address=self.contract_address, - modifications=syscall_handler.starknet_storage.get_modifications(), - ) - # Update resources usage (for bouncer). - state.cairo_usage += runner.get_execution_resources() - if "ec_op_builtin" in state.cairo_usage.builtin_instance_counter: - del state.cairo_usage.builtin_instance_counter["ec_op_builtin"] + resources_manager.cairo_usage += runner.get_execution_resources() # Build and return call info. return self._build_call_info( @@ -153,9 +157,9 @@ def sync_execute( def _run( self, - state: CarriedState, + state: SyncState, + resources_manager: ExecutionResourcesManager, general_config: StarknetGeneralConfig, - loop: asyncio.AbstractEventLoop, tx_execution_context: TransactionExecutionContext, ) -> Tuple[CairoFunctionRunner, syscall_utils.BusinessLogicSysCallHandler]: """ @@ -167,39 +171,29 @@ def _run( retrieve the execution information. """ # Prepare input for Cairo function runner. - class_hash = self._get_class_hash(state=state) + class_hash = self._get_code_class_hash(state=state) contract_class = state.get_contract_class(class_hash=class_hash) contract_class.validate() - entry_point = self._get_selected_entry_point(contract_class=contract_class, state=state) + entry_point = self._get_selected_entry_point( + contract_class=contract_class, class_hash=class_hash + ) # Run the specified contract entry point with given calldata. with wrap_with_stark_exception(code=StarknetErrorCode.SECURITY_ERROR): runner = CairoFunctionRunner(program=contract_class.program, layout="all") os_context = os_utils.prepare_os_context(runner=runner) - # Extract pre-fetched contract state from carried state. - pre_run_contract_carried_state = state.contract_states[self.contract_address] - contract_state = pre_run_contract_carried_state.state - contract_state.assert_initialized(contract_address=self.contract_address) - - starknet_storage = BusinessLogicStarknetStorage( - commitment_tree=contract_state.storage_commitment_tree, - ffc=state.ffc, - # Pass a copy of the carried storage updates (instead of a reference) - note that - # pending_modifications may be modified during the run as a result of an internal call. - pending_modifications=dict(pre_run_contract_carried_state.storage_updates), - loop=loop, - ) + validate_contract_deployed(state=state, contract_address=self.contract_address) initial_syscall_ptr = cast(RelocatableValue, os_context[starknet_abi.SYSCALL_PTR_OFFSET]) syscall_handler = syscall_utils.BusinessLogicSysCallHandler( execute_entry_point_cls=ExecuteEntryPoint, tx_execution_context=tx_execution_context, state=state, + resources_manager=resources_manager, caller_address=self.caller_address, contract_address=self.contract_address, - starknet_storage=starknet_storage, general_config=general_config, initial_syscall_ptr=initial_syscall_ptr, ) @@ -209,7 +203,8 @@ def _run( self.entry_point_selector, os_context, len(self.calldata), - self.calldata, + # Allocate and mark the segment as read-only (to mark every input array as read-only). + syscall_handler._allocate_segment(segments=runner.segments, data=self.calldata), ] try: @@ -217,7 +212,6 @@ def _run( entry_point.offset, *entry_points_args, hint_locals={ - "__storage": starknet_storage, "syscall_handler": syscall_handler, }, static_locals={ @@ -225,6 +219,7 @@ def _run( "__squash_dict_max_size": 2**20, "__keccak_max_size": 2**20, "__usort_max_size": 2**20, + "__chained_ec_op_max_len": 1000, }, run_resources=tx_execution_context.run_resources, verify_secure=True, @@ -247,17 +242,21 @@ def _run( if isinstance(exception.inner_exc, ResourcesError): code = StarknetErrorCode.OUT_OF_RESOURCES - raise StarkException(code=code, message=str(exception)) + raise StarkException(code=code, message=str(exception)) from exception except VmExceptionBase as exception: - raise StarkException(code=StarknetErrorCode.TRANSACTION_FAILED, message=str(exception)) + raise StarkException( + code=StarknetErrorCode.TRANSACTION_FAILED, message=str(exception) + ) from exception except SecurityError as exception: - raise StarkException(code=StarknetErrorCode.SECURITY_ERROR, message=str(exception)) - except Exception: + raise StarkException( + code=StarknetErrorCode.SECURITY_ERROR, message=str(exception) + ) from exception + except Exception as exception: logger.error("Got an unexpected exception.", exc_info=True) raise StarkException( code=StarknetErrorCode.UNEXPECTED_FAILURE, message="Got an unexpected exception during the execution of the transaction.", - ) + ) from exception # Complete handler validations. os_utils.validate_and_process_os_context( @@ -277,7 +276,7 @@ def _run( return runner, syscall_handler def _get_selected_entry_point( - self, contract_class: ContractClass, state: CarriedState + self, contract_class: ContractClass, class_hash: bytes ) -> ContractEntryPoint: """ Returns the entry point with selector corresponding with self.entry_point_selector. @@ -304,7 +303,7 @@ def _get_selected_entry_point( code=StarknetErrorCode.ENTRY_POINT_NOT_FOUND_IN_CONTRACT, message=( f"Entry point {selector_formatter(self.entry_point_selector)} not found in contract" - f" with class hash {hash_formatter(self._get_class_hash(state=state))}." + f" with class hash {hash_formatter(class_hash)}." ), ) @@ -317,25 +316,26 @@ def _build_call_info( syscall_handler: syscall_utils.BusinessLogicSysCallHandler, retdata: List[int], ) -> CallInfo: + execution_resources = syscall_handler.resources_manager.cairo_usage - previous_cairo_usage return CallInfo( caller_address=self.caller_address, call_type=self.call_type, contract_address=self.contract_address, code_address=self.code_address, - class_hash=self._get_class_hash(state=syscall_handler.state), + class_hash=self._get_code_class_hash(state=syscall_handler.sync_state), entry_point_selector=self.entry_point_selector, entry_point_type=self.entry_point_type, calldata=self.calldata, retdata=retdata, - execution_resources=syscall_handler.state.cairo_usage - previous_cairo_usage, + execution_resources=execution_resources.filter_unused_builtins(), events=syscall_handler.events, l2_to_l1_messages=syscall_handler.l2_to_l1_messages, storage_read_values=syscall_handler.starknet_storage.read_values, - accessed_storage_keys=syscall_handler.starknet_storage.accessed_addresses, + accessed_storage_keys=syscall_handler.starknet_storage.accessed_keys, internal_calls=syscall_handler.internal_calls, ) - def _get_class_hash(self, state: CarriedState) -> bytes: + def _get_code_class_hash(self, state: SyncState) -> bytes: """ Returns the hash of the executed contract class. """ @@ -354,7 +354,4 @@ def _get_class_hash(self, state: CarriedState) -> bytes: raise NotImplementedError(f"Call type {self.call_type} not implemented.") # Extract pre-fetched contract code from carried state. - code_contract_state = state.contract_states[code_address].state - code_contract_state.assert_initialized(contract_address=code_address) - - return code_contract_state.contract_hash + return get_deployed_class_hash_at_address(state=state, contract_address=code_address) diff --git a/src/starkware/starknet/business_logic/execution/execute_entry_point_base.py b/src/starkware/starknet/business_logic/execution/execute_entry_point_base.py index 67c358ab..1b90e441 100644 --- a/src/starkware/starknet/business_logic/execution/execute_entry_point_base.py +++ b/src/starkware/starknet/business_logic/execution/execute_entry_point_base.py @@ -1,4 +1,3 @@ -import asyncio import dataclasses from abc import ABC, abstractmethod from dataclasses import field @@ -9,7 +8,8 @@ CallType, TransactionExecutionContext, ) -from starkware.starknet.business_logic.state.state import CarriedState, StateSelector +from starkware.starknet.business_logic.fact_state.state import ExecutionResourcesManager +from starkware.starknet.business_logic.state.state_api import SyncState from starkware.starknet.definitions import fields from starkware.starknet.definitions.general_config import StarknetGeneralConfig from starkware.starknet.services.api.contract_class import EntryPointType @@ -40,26 +40,14 @@ class ExecuteEntryPointBase(ABC, ValidatedDataclass): # The caller contract address. caller_address: int = field(metadata=fields.caller_address_metadata) - def get_state_selector(self) -> StateSelector: - """ - Returns the state selector of the call (i.e., subset of state commitment tree leaves - it affects). - """ - contract_addresses = {self.contract_address} - if self.code_address is not None: - contract_addresses.add(self.code_address) - class_hashes = set() if self.class_hash is None else {self.class_hash} - - return StateSelector(contract_addresses=contract_addresses, class_hashes=class_hashes) - @abstractmethod - def sync_execute( + def execute( self, - state: CarriedState, + state: SyncState, + resources_manager: ExecutionResourcesManager, general_config: StarknetGeneralConfig, - loop: asyncio.AbstractEventLoop, tx_execution_context: TransactionExecutionContext, ) -> CallInfo: """ - Executes the entry point. Should be called from within the given loop. + Executes the entry point. """ diff --git a/src/starkware/starknet/business_logic/execution/gas_usage.py b/src/starkware/starknet/business_logic/execution/gas_usage.py index 3cdf747c..a7c76aef 100644 --- a/src/starkware/starknet/business_logic/execution/gas_usage.py +++ b/src/starkware/starknet/business_logic/execution/gas_usage.py @@ -10,7 +10,6 @@ def calculate_tx_gas_usage( n_modified_contracts: int, n_storage_writes: int, l1_handler_payload_size: Optional[int], - constructor_calldata_total_length: int, n_deployments: int, ) -> int: """ @@ -21,10 +20,9 @@ def calculate_tx_gas_usage( Arguments: l1_handler_payload_size should be an int if and only if we calculate the gas usage of an - InternalInvokeFunction of type L1 handler. Otherwise the payload size is irrelevent, and should - be None. constructor_calldata_total_length is the sum of the lengths of constructor calldata - of all the contracts deployed by the transaction. n_deployments is the number of the - contracts deployed by the transaction. + InternalInvokeFunction of type L1 handler. Otherwise the payload size is irrelevant, and should + be None. + n_deployments is the number of the contracts deployed by the transaction. """ # Calculate the addition of the transaction to the output messages segment. residual_message_segment_length = get_message_segment_length( @@ -36,7 +34,6 @@ def calculate_tx_gas_usage( residual_da_segment_length = get_da_segment_length( n_modified_contracts=n_modified_contracts, n_storage_writes=n_storage_writes, - constructor_calldata_total_length=constructor_calldata_total_length, n_deployments=n_deployments, ) @@ -92,14 +89,13 @@ def get_message_segment_length( def get_da_segment_length( n_modified_contracts: int, n_storage_writes: int, - constructor_calldata_total_length: int, n_deployments: int, ) -> int: """ Returns the number of felts added to the output data availability segment as a result of adding a transaction to a batch. Note that constant cells - such as the one that holds the number of modified contracts - are not counted. - This segment consists of deployment info. (of contracts deployed by the transaction) and + This segment consists of deployment info (of contracts deployed by the transaction) and storage updates. """ # For each newly modified contract: contract address, number of modified storage cells. @@ -107,9 +103,7 @@ def get_da_segment_length( # For each modified storage cell: key, new value. da_segment_length += n_storage_writes * 2 # Add size of deployment info. - da_segment_length += ( - n_deployments * constants.DEPLOYMENT_INFO_HEADER_SIZE + constructor_calldata_total_length - ) + da_segment_length += n_deployments * constants.DEPLOYMENT_INFO_SIZE return da_segment_length diff --git a/src/starkware/starknet/business_logic/execution/objects.py b/src/starkware/starknet/business_logic/execution/objects.py index 61ef76a4..f89297c2 100644 --- a/src/starkware/starknet/business_logic/execution/objects.py +++ b/src/starkware/starknet/business_logic/execution/objects.py @@ -4,7 +4,7 @@ import operator from dataclasses import field from enum import Enum, auto -from typing import Iterable, Iterator, List, Optional, Set, cast +from typing import FrozenSet, Iterable, Iterator, List, Mapping, Optional, Set, cast import marshmallow.fields as mfields import marshmallow_dataclass @@ -13,23 +13,28 @@ from services.everest.definitions import fields as everest_fields from starkware.cairo.lang.vm.cairo_pie import ExecutionResources from starkware.cairo.lang.vm.utils import RunResources -from starkware.starknet.business_logic.state.state import StateSelector +from starkware.python.utils import as_non_optional +from starkware.starknet.business_logic.fact_state.contract_state_objects import StateSelector +from starkware.starknet.business_logic.state.state import StorageEntry from starkware.starknet.definitions import constants, fields -from starkware.starknet.services.api.contract_class import CONSTRUCTOR_SELECTOR, EntryPointType -from starkware.starknet.services.api.gateway.transaction import DECLARE_SENDER_ADDRESS +from starkware.starknet.public.abi import CONSTRUCTOR_ENTRY_POINT_SELECTOR +from starkware.starknet.services.api.contract_class import EntryPointType +from starkware.starknet.services.api.gateway.transaction import DEFAULT_DECLARE_SENDER_ADDRESS from starkware.starkware_utils.marshmallow_dataclass_fields import ( SetField, + additional_metadata, nonrequired_list_metadata, nonrequired_optional_metadata, ) +from starkware.starkware_utils.marshmallow_fields_metadata import sequential_id_metadata from starkware.starkware_utils.serializable_dataclass import SerializableMarshmallowDataclass from starkware.starkware_utils.validated_dataclass import ( ValidatedDataclass, ValidatedMarshmallowDataclass, ) -from starkware.starkware_utils.validated_fields import sequential_id_metadata logger = logging.getLogger(__name__) +ResourcesMapping = Mapping[str, int] class CallType(Enum): @@ -51,7 +56,10 @@ class TransactionExecutionContext(ValidatedDataclass): transaction_hash: int = field(metadata=fields.transaction_hash_metadata) # The signature of the transaction. signature: List[int] = field(metadata=fields.signature_metadata) + # The maximal fee to be paid in Wei for the execution. max_fee: int = field(metadata=fields.fee_metadata) + # The nonce of the transaction. + nonce: int version: int = field(metadata=fields.tx_version_metadata) run_resources: RunResources # Used for tracking global events order. @@ -66,14 +74,17 @@ def create( transaction_hash: int, signature: List[int], max_fee: int, + nonce: Optional[int], n_steps: int, version: int, ) -> "TransactionExecutionContext": + nonce = 0 if version in [0, constants.QUERY_VERSION_BASE] else as_non_optional(nonce) return cls( account_contract_address=account_contract_address, transaction_hash=transaction_hash, signature=signature, max_fee=max_fee, + nonce=nonce, version=version, run_resources=RunResources(n_steps=n_steps), n_emitted_events=0, @@ -85,6 +96,7 @@ def create_for_testing( cls, account_contract_address: int = 0, max_fee: int = 0, + nonce: int = 0, n_steps: int = 100000, version: int = constants.TRANSACTION_VERSION, ) -> "TransactionExecutionContext": @@ -93,6 +105,7 @@ def create_for_testing( transaction_hash=0, signature=[], max_fee=max_fee, + nonce=nonce, version=version, run_resources=RunResources(n_steps=n_steps), n_emitted_events=0, @@ -202,7 +215,7 @@ class CallInfo(SerializableMarshmallowDataclass): # A set of storage keys accessed by this call, **excluding** keys from nested calls; # kept in order to calculate and prepare the commitment tree facts before the StarkNet OS run. accessed_storage_keys: Set[int] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=SetField( everest_fields.felt_metadata("storage_accessed_address")["marshmallow_field"] ) @@ -212,7 +225,9 @@ class CallInfo(SerializableMarshmallowDataclass): # Internal calls made by this call. internal_calls: List["CallInfo"] = field( - metadata=dict(marshmallow_field=mfields.List(mfields.Nested(lambda: CallInfo.Schema()))) + metadata=additional_metadata( + marshmallow_field=mfields.List(mfields.Nested(lambda: CallInfo.Schema())) + ) ) # Deprecated fields. @@ -220,20 +235,34 @@ class CallInfo(SerializableMarshmallowDataclass): # it may differ from the code of the to_address contract. code_address: Optional[int] + def get_visited_storage_entries(self) -> Set[StorageEntry]: + storage_entries = {(self.contract_address, key) for key in self.accessed_storage_keys} + internal_visited_storage_entries = CallInfo.get_visited_storage_entries_of_many( + call_infos=self.internal_calls + ) + return storage_entries | internal_visited_storage_entries + def get_state_selector(self) -> StateSelector: code_address = self.contract_address if self.code_address is None else self.code_address - class_hashes = set() if self.class_hash is None else {self.class_hash} - selector = StateSelector( - contract_addresses={self.contract_address, code_address} - {DECLARE_SENDER_ADDRESS}, - class_hashes=class_hashes, + assert self.class_hash is not None, "Class hash is missing from call info." + selector = StateSelector.create( + contract_addresses={self.contract_address, code_address} + - {DEFAULT_DECLARE_SENDER_ADDRESS}, + class_hashes=[self.class_hash], ) return selector | CallInfo.get_state_selector_of_many(call_infos=self.internal_calls) @staticmethod - def get_state_selector_of_many( - call_infos: Iterable["CallInfo"], - ) -> StateSelector: + def get_visited_storage_entries_of_many(call_infos: Iterable["CallInfo"]) -> Set[StorageEntry]: + return functools.reduce( + operator.__or__, + (call_info.get_visited_storage_entries() for call_info in call_infos), + set(), + ) + + @staticmethod + def get_state_selector_of_many(call_infos: Iterable["CallInfo"]) -> StateSelector: return functools.reduce( operator.__or__, (call_info.get_state_selector() for call_info in call_infos), @@ -278,7 +307,7 @@ def empty( @classmethod def empty_for_testing(cls) -> "CallInfo": - return cls.empty(contract_address=0, caller_address=0, class_hash=None) + return cls.empty(contract_address=1, caller_address=0, class_hash=None) @classmethod def empty_constructor_call( @@ -290,7 +319,7 @@ def empty_constructor_call( class_hash=class_hash, call_type=CallType.CALL, entry_point_type=EntryPointType.CONSTRUCTOR, - entry_point_selector=CONSTRUCTOR_SELECTOR, + entry_point_selector=CONSTRUCTOR_ENTRY_POINT_SELECTOR, ) def get_sorted_events(self) -> List[Event]: @@ -350,18 +379,47 @@ class TransactionExecutionInfo(EverestTransactionExecutionInfo): 2. Stores useful information for users; e.g., L2-to-L1 messages and emitted events. """ - call_info: CallInfo - # Fee transfer call info, executed by the BE for external InvokeFunction transactions; - # Optional since currently Deploy transactions do not have fee (and backward compatibility). + # Transaction-specific validation call info. + validate_info: Optional[CallInfo] + # Transaction-specific execution call info, None for Declare. + call_info: Optional[CallInfo] + # Fee transfer call info, executed by the BE for account contract transactions (e.g., declare + # and invoke). fee_transfer_info: Optional[CallInfo] + # The actual fee that was charged in Wei. actual_fee: int = field(metadata=fields.FeeField.metadata(field_name="actual_fee")) + # Actual resources the transaction is charged for, including L1 gas + # and OS additional resources estimation. + actual_resources: ResourcesMapping = field(metadata=fields.name_to_resources_metadata) + + @property + def non_optional_calls(self) -> Iterable[CallInfo]: + ordered_optional_calls = (self.validate_info, self.call_info, self.fee_transfer_info) + return tuple(call for call in ordered_optional_calls if call is not None) def get_state_selector(self) -> StateSelector: - call_info_selector = self.call_info.get_state_selector() - if self.fee_transfer_info is None: - return call_info_selector + return CallInfo.get_state_selector_of_many(call_infos=self.non_optional_calls) + + def get_executed_class_hashes(self) -> FrozenSet[bytes]: + return frozenset(self.get_state_selector().class_hashes) - return call_info_selector | self.fee_transfer_info.get_state_selector() + def get_visited_storage_entries(self) -> Set[StorageEntry]: + return CallInfo.get_visited_storage_entries_of_many(call_infos=self.non_optional_calls) + + @classmethod + def from_call_infos( + cls, + execute_call_info: Optional[CallInfo], + validate_info: Optional[CallInfo] = None, + fee_transfer_info: Optional[CallInfo] = None, + ) -> "TransactionExecutionInfo": + return cls( + validate_info=validate_info, + call_info=execute_call_info, + fee_transfer_info=fee_transfer_info, + actual_fee=0, + actual_resources={}, + ) def gen_call_iterator(self) -> Iterator[CallInfo]: """ @@ -369,11 +427,8 @@ def gen_call_iterator(self) -> Iterator[CallInfo]: (Preorder of the original call tree followed by the preorder of the call tree that was generated while charging the fee). """ - yield from self.call_info.gen_call_topology() - if self.fee_transfer_info is None: - return - - yield from self.fee_transfer_info.gen_call_topology() + for call_info in self.non_optional_calls: + yield from call_info.gen_call_topology() @staticmethod def get_state_selector_of_many( @@ -385,11 +440,29 @@ def get_state_selector_of_many( StateSelector.empty(), ) + @staticmethod + def get_visited_storage_entries_of_many( + execution_infos: Iterable["TransactionExecutionInfo"], + ) -> Set[StorageEntry]: + return functools.reduce( + operator.__or__, + (execution_info.get_visited_storage_entries() for execution_info in execution_infos), + set(), + ) + def get_sorted_events(self) -> List[Event]: - return self.call_info.get_sorted_events() + return [ + event + for call_info in self.non_optional_calls + for event in call_info.get_sorted_events() + ] def get_sorted_l2_to_l1_messages(self) -> List[L2ToL1MessageInfo]: - return self.call_info.get_sorted_l2_to_l1_messages() + return [ + message + for call_info in self.non_optional_calls + for message in call_info.get_sorted_l2_to_l1_messages() + ] # Deprecated classes. @@ -441,7 +514,7 @@ class ContractCall(ValidatedMarshmallowDataclass): # A set of storage addresses accessed by this call, **excluding** addresses from nested calls; # kept in order to calculate and prepare the commitment tree facts before the StarkNet OS run. storage_accessed_addresses: Set[int] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=SetField( everest_fields.felt_metadata("storage_accessed_address")["marshmallow_field"] ) @@ -469,7 +542,9 @@ def empty(cls, to_address: int) -> "ContractCall": @property def state_selector(self) -> StateSelector: code_address = self.to_address if self.code_address is None else self.code_address - return StateSelector(contract_addresses={self.to_address, code_address}, class_hashes=set()) + return StateSelector.create( + contract_addresses=[self.to_address, code_address], class_hashes=[] + ) @marshmallow_dataclass.dataclass(frozen=True) diff --git a/src/starkware/starknet/business_logic/execution/os_resources.json b/src/starkware/starknet/business_logic/execution/os_resources.json index 8115d683..078e13ab 100644 --- a/src/starkware/starknet/business_logic/execution/os_resources.json +++ b/src/starkware/starknet/business_logic/execution/os_resources.json @@ -2,197 +2,111 @@ "execute_syscalls": { "call_contract": { "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 22 + "range_check_builtin": 17 }, "n_memory_holes": 0, - "n_steps": 598 + "n_steps": 543 }, "delegate_call": { "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 22 + "range_check_builtin": 17 }, "n_memory_holes": 0, - "n_steps": 620 + "n_steps": 565 }, "delegate_l1_handler": { "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 15 + "range_check_builtin": 13 }, "n_memory_holes": 0, - "n_steps": 549 + "n_steps": 544 }, "deploy": { "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, "pedersen_builtin": 7, - "range_check_builtin": 19 + "range_check_builtin": 16 }, "n_memory_holes": 0, - "n_steps": 815 + "n_steps": 796 }, "emit_event": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 18 }, "get_block_number": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 38 }, "get_block_timestamp": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 36 }, "get_caller_address": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 30 }, "get_contract_address": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 34 }, "get_sequencer_address": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 32 }, "get_tx_info": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 28 }, "get_tx_signature": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 43 }, "library_call": { "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 22 + "range_check_builtin": 17 }, "n_memory_holes": 0, - "n_steps": 588 + "n_steps": 533 }, "library_call_l1_handler": { "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 15 + "range_check_builtin": 13 }, "n_memory_holes": 0, - "n_steps": 517 + "n_steps": 512 }, "send_message_to_l1": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, "n_steps": 81 }, "storage_read": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, - "n_steps": 40 + "n_steps": 42 }, "storage_write": { - "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 0, - "range_check_builtin": 0 - }, + "builtin_instance_counter": {}, "n_memory_holes": 0, - "n_steps": 42 + "n_steps": 44 } }, "execute_txs_inner": { "DECLARE": { - "builtin_instance_counter": {}, + "builtin_instance_counter": { + "pedersen_builtin": 15, + "range_check_builtin": 57 + }, "n_memory_holes": 0, - "n_steps": 0 + "n_steps": 2330 }, "DEPLOY": { "builtin_instance_counter": {}, @@ -201,14 +115,19 @@ }, "INVOKE_FUNCTION": { "builtin_instance_counter": { - "bitwise_builtin": 0, - "ecdsa_builtin": 0, - "output_builtin": 0, - "pedersen_builtin": 15, - "range_check_builtin": 60 + "pedersen_builtin": 16, + "range_check_builtin": 70 + }, + "n_memory_holes": 0, + "n_steps": 2833 + }, + "L1_HANDLER": { + "builtin_instance_counter": { + "pedersen_builtin": 11, + "range_check_builtin": 13 }, "n_memory_holes": 0, - "n_steps": 2314 + "n_steps": 875 } } } diff --git a/src/starkware/starknet/business_logic/execution/os_usage.py b/src/starkware/starknet/business_logic/execution/os_usage.py index a16dd352..92c722d2 100644 --- a/src/starkware/starknet/business_logic/execution/os_usage.py +++ b/src/starkware/starknet/business_logic/execution/os_usage.py @@ -5,8 +5,6 @@ import marshmallow_dataclass from starkware.cairo.lang.vm.cairo_pie import ExecutionResources -from starkware.python.utils import sub_counters -from starkware.starknet.business_logic.state.state import CarriedState from starkware.starknet.definitions.transaction_type import TransactionType from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass @@ -28,12 +26,12 @@ class OsResources(ValidatedMarshmallowDataclass): ) -def calculate_syscall_resources(syscall_counter: Mapping[str, int]) -> ExecutionResources: - """ - Calculates and returns the additional resources needed for the OS to run the given syscalls; - i.e., the resources of the function execute_syscalls(). - """ - return functools.reduce( +def get_additional_os_resources( + syscall_counter: Mapping[str, int], tx_type: TransactionType +) -> ExecutionResources: + # Calculate the additional resources needed for the OS to run the given syscalls; + # i.e., the resources of the function execute_syscalls(). + os_additional_resources = functools.reduce( ExecutionResources.__add__, ( os_resources.execute_syscalls[syscall_name] * syscall_counter[syscall_name] @@ -42,22 +40,8 @@ def calculate_syscall_resources(syscall_counter: Mapping[str, int]) -> Execution ExecutionResources.empty(), ) - -def calculate_execute_txs_inner_resources(tx_type: TransactionType) -> ExecutionResources: - """ - Calculates and returns the additional resources needed for the OS to run the given transaction; - i.e., the resources of the StarkNet OS function execute_transactions_inner(). - """ - return ( - ExecutionResources.empty() - if tx_type not in os_resources.execute_txs_inner - else os_resources.execute_txs_inner[tx_type] + # Calculate the additional resources needed for the OS to run the given transaction; + # i.e., the resources of the StarkNet OS function execute_transactions_inner(). + return os_additional_resources + os_resources.execute_txs_inner.get( + tx_type, ExecutionResources.empty() ) - - -def get_tx_syscall_counter(state: CarriedState) -> Mapping[str, int]: - """ - Returns the most-recent transaction's syscall counter (recent w.r.t. application on the given - state). - """ - return sub_counters(state.syscall_counter, state.non_optional_parent_state.syscall_counter) diff --git a/src/starkware/starknet/business_logic/fact_state/CMakeLists.txt b/src/starkware/starknet/business_logic/fact_state/CMakeLists.txt new file mode 100644 index 00000000..ec9dfda3 --- /dev/null +++ b/src/starkware/starknet/business_logic/fact_state/CMakeLists.txt @@ -0,0 +1,47 @@ +python_lib(starknet_business_logic_fact_state_lib + PREFIX starkware/starknet/business_logic/fact_state + + FILES + state.py + + LIBS + cairo_vm_lib + everest_business_logic_lib + starknet_business_logic_patricia_state_lib + starknet_business_logic_state_lib + starknet_contract_class_lib + starknet_definitions_lib + starknet_general_config_lib + starknet_storage_lib + starknet_transaction_lib + starkware_config_utils_lib + starkware_error_handling_lib + starkware_python_utils_lib + starkware_storage_lib + starkware_utils_lib + pip_marshmallow_dataclass +) + +python_lib(starknet_business_logic_patricia_state_lib + PREFIX starkware/starknet/business_logic/fact_state + + FILES + contract_state_objects.py + patricia_state.py + + LIBS + everest_business_logic_lib + starknet_business_logic_state_lib + starknet_contract_class_lib + starknet_definitions_lib + starknet_general_config_lib + starknet_os_abi_lib + starknet_storage_lib + starkware_commitment_tree_facts_lib + starkware_dataclasses_utils_lib + starkware_error_handling_lib + starkware_python_utils_lib + starkware_storage_lib + starkware_utils_lib + pip_marshmallow_dataclass +) diff --git a/src/starkware/starknet/business_logic/state/objects.py b/src/starkware/starknet/business_logic/fact_state/contract_state_objects.py similarity index 61% rename from src/starkware/starknet/business_logic/state/objects.py rename to src/starkware/starknet/business_logic/fact_state/contract_state_objects.py index 07599b0a..ea37e36b 100644 --- a/src/starkware/starknet/business_logic/state/objects.py +++ b/src/starkware/starknet/business_logic/fact_state/contract_state_objects.py @@ -1,10 +1,11 @@ import dataclasses from dataclasses import field -from typing import ClassVar, Dict, Iterable, Mapping, Set +from typing import ClassVar, FrozenSet, Iterable, Mapping, Optional import marshmallow_dataclass -from starkware.python.utils import gather_in_chunks, safe_zip, to_bytes +from services.everest.business_logic.state import StateSelectorBase +from starkware.python.utils import to_bytes from starkware.starknet.core.os.class_hash import compute_class_hash from starkware.starknet.definitions import fields from starkware.starknet.definitions.error_codes import StarknetErrorCode @@ -13,7 +14,7 @@ from starkware.starkware_utils.commitment_tree.leaf_fact import LeafFact from starkware.starkware_utils.commitment_tree.patricia_tree.nodes import EmptyNodeFact from starkware.starkware_utils.commitment_tree.patricia_tree.patricia_tree import PatriciaTree -from starkware.starkware_utils.error_handling import StarkException, stark_assert +from starkware.starkware_utils.error_handling import stark_assert from starkware.starkware_utils.validated_dataclass import ( ValidatedDataclass, ValidatedMarshmallowDataclass, @@ -46,20 +47,25 @@ class ContractState(ValidatedMarshmallowDataclass, LeafFact): """ Represents the state of a single contract (sub-commitment tree) in the full StarkNet state commitment tree. - The contract state containts the contract object (None if the contract was not yet deployed) + The contract state contains the contract object (None if the contract was not yet deployed) and the commitment tree root of the contract storage. """ contract_hash: bytes = field(metadata=fields.class_hash_metadata) storage_commitment_tree: PatriciaTree + nonce: int = field(metadata=fields.non_required_nonce_metadata) UNINITIALIZED_CLASS_HASH: ClassVar[bytes] = b"\x00" * HASH_BYTES @classmethod async def create( - cls, contract_hash: bytes, storage_commitment_tree: PatriciaTree + cls, contract_hash: bytes, storage_commitment_tree: PatriciaTree, nonce: int ) -> "ContractState": - return cls(storage_commitment_tree=storage_commitment_tree, contract_hash=contract_hash) + return cls( + storage_commitment_tree=storage_commitment_tree, + contract_hash=contract_hash, + nonce=nonce, + ) @classmethod async def empty( @@ -69,7 +75,11 @@ async def empty( ffc=ffc, height=storage_commitment_tree_height, leaf_fact=StorageLeaf.empty() ) - return cls(storage_commitment_tree=empty_tree, contract_hash=cls.UNINITIALIZED_CLASS_HASH) + return cls( + storage_commitment_tree=empty_tree, + contract_hash=cls.UNINITIALIZED_CLASS_HASH, + nonce=0, + ) @property def is_empty(self) -> bool: @@ -84,57 +94,15 @@ def _hash(self, hash_func: HashFunctionType) -> bytes: return EmptyNodeFact.EMPTY_NODE_HASH CONTRACT_STATE_HASH_VERSION = 0 - RESERVED = 0 # Set hash_value = H(H(contract_hash, storage_root), RESERVED). hash_value = hash_func(self.contract_hash, self.storage_commitment_tree.root) - hash_value = hash_func(hash_value, to_bytes(RESERVED)) + hash_value = hash_func(hash_value, to_bytes(self.nonce)) # Return H(hash_value, CONTRACT_STATE_HASH_VERSION). CONTRACT_STATE_HASH_VERSION must be in # the outermost hash to guarantee unique "decoding". return hash_func(hash_value, to_bytes(CONTRACT_STATE_HASH_VERSION)) - @staticmethod - async def fetch_contract_classes( - contract_states: Iterable["ContractState"], - class_hashes: Set[bytes], - ffc: FactFetchingContext, - ) -> Dict[bytes, ContractClass]: - """ - Fetches requested contract classes from storage and returns a dictionary mapping their - hashes to fetched classes. - The hashes are a union of the hashes from the given contract states and the given set of - class hashes. - - If a hash matches no declared contract class, an error is raised. - This can only happen in the context of a library call. - """ - # Gather all distinct hashes. - class_hashes = class_hashes | set(contract.contract_hash for contract in contract_states) - # Discard empty hash for not yet deployed contracts. - class_hashes -= {ContractState.UNINITIALIZED_CLASS_HASH} - - # Fetch corresponding contract classes from storage. - contract_class_facts = await gather_in_chunks( - awaitables=( - ContractClassFact.get(storage=ffc.storage, suffix=class_hash) - for class_hash in class_hashes - ) - ) - - contract_classes: Dict[bytes, ContractClass] = {} - for class_hash, fact in safe_zip(class_hashes, contract_class_facts): - if fact is None: - formatted_class_hash = fields.class_hash_from_bytes(class_hash) - raise StarkException( - code=StarknetErrorCode.UNDECLARED_CLASS, - message=f"Class with hash {formatted_class_hash} is not declared.", - ) - - contract_classes[class_hash] = fact.contract_definition - - return contract_classes - @property def initialized(self) -> bool: uninitialized = self.contract_hash == self.UNINITIALIZED_CLASS_HASH @@ -159,19 +127,38 @@ def assert_initialized(self, contract_address: int): ) async def update( - self, ffc: FactFetchingContext, updates: Mapping[int, StorageLeaf] + self, + ffc: FactFetchingContext, + updates: Mapping[int, StorageLeaf], + nonce: Optional[int], + class_hash: Optional[bytes] = None, ) -> "ContractState": """ Returns a new ContractState object with the same contract object and a newly calculated root, according to the given updates of its leaves. + In a case of an empty contract - it is possible to update the class hash as well. """ + if class_hash is None: + class_hash = self.contract_hash + elif class_hash != self.contract_hash: + assert self.is_empty, "Cannot override an assigned contract state." + + if nonce is None: + nonce = self.nonce + + if len(updates) > 0 or nonce != self.nonce: + assert ( + class_hash != ContractState.UNINITIALIZED_CLASS_HASH + ), "Cannot update the state of an uninitialized contract." + updated_storage_commitment_tree = await self.storage_commitment_tree.update( ffc=ffc, modifications=updates.items() ) return ContractState( - contract_hash=self.contract_hash, + contract_hash=class_hash, storage_commitment_tree=updated_storage_commitment_tree, + nonce=nonce, ) @@ -184,6 +171,7 @@ class ContractCarriedState(ValidatedDataclass): state: ContractState storage_updates: Mapping[int, StorageLeaf] + nonce: int @property def has_pending_updates(self) -> bool: @@ -195,7 +183,7 @@ def has_pending_updates(self) -> bool: @classmethod def from_state(cls, state: ContractState) -> "ContractCarriedState": - return cls(state=state, storage_updates={}) + return cls(state=state, storage_updates={}, nonce=state.nonce) @classmethod async def empty( @@ -205,9 +193,59 @@ async def empty( storage_commitment_tree_height=storage_commitment_tree_height, ffc=ffc ) - return cls(state=empty_state, storage_updates={}) + return cls(state=empty_state, storage_updates={}, nonce=0) async def update(self, ffc: FactFetchingContext) -> "ContractCarriedState": - updated_state = await self.state.update(ffc=ffc, updates=self.storage_updates) + updated_state = await self.state.update( + ffc=ffc, updates=self.storage_updates, nonce=self.nonce + ) return ContractCarriedState.from_state(state=updated_state) + + +@dataclasses.dataclass(frozen=True) +class StateSelector(StateSelectorBase): + """ + A class that contains a set of StarkNet contract addresses (sub-commitment tree root IDs) + and a set of hashes of relevant contract classes + affected by one/many transaction(s). + Used for fetching those sub-trees and classes from storage before transaction(s) processing. + """ + + contract_addresses: FrozenSet[int] + class_hashes: FrozenSet[bytes] + + @classmethod + def empty(cls) -> "StateSelector": + return cls(contract_addresses=frozenset(), class_hashes=frozenset()) + + @classmethod + def create( + cls, contract_addresses: Iterable[int], class_hashes: Iterable[bytes] + ) -> "StateSelector": + return cls( + contract_addresses=frozenset(contract_addresses), class_hashes=frozenset(class_hashes) + ) + + def __and__(self, other: "StateSelector") -> "StateSelector": + return StateSelector( + contract_addresses=self.contract_addresses & other.contract_addresses, + class_hashes=self.class_hashes & other.class_hashes, + ) + + def __or__(self, other: "StateSelector") -> "StateSelector": + return StateSelector( + contract_addresses=self.contract_addresses | other.contract_addresses, + class_hashes=self.class_hashes | other.class_hashes, + ) + + def __sub__(self, other: "StateSelector") -> "StateSelector": + return StateSelector( + contract_addresses=self.contract_addresses - other.contract_addresses, + class_hashes=self.class_hashes - other.class_hashes, + ) + + def __le__(self, other: "StateSelector") -> bool: + return (self.contract_addresses <= other.contract_addresses) and ( + self.class_hashes <= other.class_hashes + ) diff --git a/src/starkware/starknet/business_logic/fact_state/patricia_state.py b/src/starkware/starknet/business_logic/fact_state/patricia_state.py new file mode 100644 index 00000000..2450047c --- /dev/null +++ b/src/starkware/starknet/business_logic/fact_state/patricia_state.py @@ -0,0 +1,90 @@ +from typing import Dict + +from starkware.starknet.business_logic.fact_state.contract_state_objects import ( + ContractClassFact, + ContractState, +) +from starkware.starknet.business_logic.state.state_api import StateReader +from starkware.starknet.definitions import fields +from starkware.starknet.definitions.error_codes import StarknetErrorCode +from starkware.starknet.services.api.contract_class import ContractClass +from starkware.starknet.storage.starknet_storage import StorageLeaf +from starkware.starkware_utils.commitment_tree.patricia_tree.patricia_tree import PatriciaTree +from starkware.starkware_utils.error_handling import StarkException +from starkware.storage.storage import FactFetchingContext + + +class PatriciaStateReader(StateReader): + """ + A Patricia implementation of StateReader. + """ + + def __init__(self, global_state_root: PatriciaTree, ffc: FactFetchingContext): + # Members related to dynamic retrieval of facts during transaction execution. + self.ffc = ffc + # The last committed state; the one this state was created from. + self.global_state_root = global_state_root + # A mapping from contract address to its cached state. + self.contract_states: Dict[int, ContractState] = {} + + # StateReader API. + + async def get_contract_class(self, class_hash: bytes) -> ContractClass: + return await self._fetch_contract_class(class_hash=class_hash) + + async def get_class_hash_at(self, contract_address: int) -> bytes: + contract_state = await self._get_contract_state(contract_address=contract_address) + return contract_state.contract_hash + + async def get_nonce_at(self, contract_address: int) -> int: + contract_state = await self._get_contract_state(contract_address=contract_address) + return contract_state.nonce + + async def get_storage_at(self, contract_address: int, key: int) -> int: + contract_state = await self._get_contract_state(contract_address=contract_address) + + contract_storage_tree_height = contract_state.storage_commitment_tree.height + assert ( + 0 <= key < 2**contract_storage_tree_height + ), f"The address {key} is out of range: [0, 2**{contract_storage_tree_height})." + + storage_leaf = await self._fetch_storage_leaf(contract_state=contract_state, key=key) + + return storage_leaf.value + + # Internal utilities. + + async def _get_contract_state(self, contract_address: int) -> ContractState: + if contract_address not in self.contract_states: + self.contract_states[contract_address] = await self._fetch_contract_state( + contract_address=contract_address + ) + + return self.contract_states[contract_address] + + async def _fetch_contract_class(self, class_hash: bytes) -> ContractClass: + contract_class_fact = await ContractClassFact.get( + storage=self.ffc.storage, suffix=class_hash + ) + + if contract_class_fact is None: + formatted_class_hash = fields.class_hash_from_bytes(class_hash=class_hash) + raise StarkException( + code=StarknetErrorCode.UNDECLARED_CLASS, + message=f"Class with hash {formatted_class_hash} is not declared.", + ) + + contract_class = contract_class_fact.contract_definition + contract_class.validate() + + return contract_class + + async def _fetch_contract_state(self, contract_address: int) -> ContractState: + return await self.global_state_root.get_leaf( + ffc=self.ffc, index=contract_address, fact_cls=ContractState + ) + + async def _fetch_storage_leaf(self, contract_state: ContractState, key: int) -> StorageLeaf: + return await contract_state.storage_commitment_tree.get_leaf( + ffc=self.ffc, index=key, fact_cls=StorageLeaf + ) diff --git a/src/starkware/starknet/business_logic/fact_state/state.py b/src/starkware/starknet/business_logic/fact_state/state.py new file mode 100644 index 00000000..c4d1b386 --- /dev/null +++ b/src/starkware/starknet/business_logic/fact_state/state.py @@ -0,0 +1,427 @@ +import copy +import logging +from typing import Dict, Mapping, MutableMapping, Optional + +import marshmallow_dataclass + +from services.everest.business_logic.state import ( + CarriedStateBase, + EverestStateDiff, + SharedStateBase, + StateSelectorBase, +) +from starkware.cairo.lang.vm.cairo_pie import ExecutionResources +from starkware.python.utils import gather_in_chunks, safe_zip +from starkware.starknet.business_logic.fact_state.contract_state_objects import ( + ContractCarriedState, + ContractState, +) +from starkware.starknet.business_logic.fact_state.patricia_state import PatriciaStateReader +from starkware.starknet.business_logic.state.state import CachedState, StorageEntry +from starkware.starknet.business_logic.state.state_api import SyncState +from starkware.starknet.business_logic.state.state_api_objects import BlockInfo +from starkware.starknet.definitions.general_config import StarknetGeneralConfig +from starkware.starknet.services.api.contract_class import ContractClass +from starkware.starknet.storage.starknet_storage import ContractStorageMapping, StorageLeaf +from starkware.starkware_utils.commitment_tree.binary_fact_tree import BinaryFactDict +from starkware.starkware_utils.commitment_tree.patricia_tree.patricia_tree import PatriciaTree +from starkware.starkware_utils.config_base import Config +from starkware.storage.storage import FactFetchingContext + +logger = logging.getLogger(__name__) +state_objects_logger = logging.getLogger(f"{__name__}:state_objects_logger") + +ContractCarriedStateMapping = MutableMapping[int, ContractCarriedState] + + +class ExecutionResourcesManager: + """ + Aggregates execution resources throughout transaction stream processing. + """ + + def __init__( + self, + cairo_usage: ExecutionResources, + modified_contracts: Dict[int, None], + syscall_counter: Dict[str, int], + ): + # The accumulated Cairo usage. + self.cairo_usage = cairo_usage + + # Addresses of contracts whose storage has changed. + self.modified_contracts = modified_contracts + + # A mapping from system call to the cumulative times it was invoked. + self.syscall_counter = syscall_counter + + # Alternative constructors. + + @classmethod + def empty(cls) -> "ExecutionResourcesManager": + return cls( + cairo_usage=ExecutionResources.empty(), + modified_contracts={}, + syscall_counter={}, + ) + + +class CarriedState(CarriedStateBase): + """ + A state containing a mapping from contract addresses to their states and the accumulated + modifications to the contract storage across transactions. + + This will be a sub-state of the total state (SharedState). It is carried and maintained by + the Batcher, as each pending transaction is applied to it during the attempt to include it in + a block. After a block is created the carried state is applied to the shared state. + """ + + def __init__( + self, + parent_state: Optional["CarriedState"], + state: CachedState, + resources_manager: ExecutionResourcesManager, + ): + """ + Private constructor. + Should only be called by _create_from_parent_state and create_unfilled class methods. + """ + super().__init__(parent_state=parent_state) + + self.state = state + + self._sync_state: Optional[SyncState] = None + + # The resources used throughout transaction stream processing. + self.resources_manager = resources_manager + + @property + def sync_state(self) -> SyncState: + assert self._sync_state is not None + return self._sync_state + + # Alternative constructors. + + @classmethod + def _create_from_parent_state(cls, parent_state: "CarriedState") -> "CarriedState": + """ + Instantiates a CarriedState object that acts as proxy to given parent_state. + """ + assert ( + parent_state.state is not None + ), "Parent cached state must be concrete when creating a child state." + + return cls( + # Parent carried state - must not be modified. + parent_state=parent_state, + # Cached state. + state=parent_state.state._copy(), + # Immutable objects. + # Chain maps - changes are inserted to the first map (at index 0); parent maps must not + # be modified. + resources_manager=copy.deepcopy(parent_state.resources_manager), + ) + + @classmethod + def create_unfilled( + cls, shared_state: "SharedState", ffc: FactFetchingContext + ) -> "CarriedState": + """ + Creates a carried state based on the given shared state, where the fields related to the + commitment leaves (e.g., contract states) are kept unfilled. + """ + state = CachedState( + block_info=shared_state.block_info, + state_reader=PatriciaStateReader( + global_state_root=shared_state.contract_states, ffc=ffc + ), + ) + + return cls( + parent_state=None, + state=state, + resources_manager=ExecutionResourcesManager.empty(), + ) + + @classmethod + async def empty_for_testing( + cls, + shared_state: Optional["SharedState"], + ffc: FactFetchingContext, + general_config: StarknetGeneralConfig, + ) -> "CarriedState": + """ + Creates an empty carried state allowing accessing all possible contract addresses (by + using defaultdict). This constructor should only be used in tests. + """ + if shared_state is None: + shared_state = await SharedState.empty(ffc=ffc, general_config=general_config) + + return cls.create_unfilled(ffc=ffc, shared_state=shared_state) + + @classmethod + def from_contracts( + cls, + shared_state: "SharedState", + ffc: FactFetchingContext, + contract_definitions: MutableMapping[bytes, ContractClass], + contract_states: ContractCarriedStateMapping, + ) -> "CarriedState": + """ + Returns a carried state object, containing the given contracts. + Other members are initialized with the empty object values. + This is a utility function and should not be used in the regular flow. + """ + state_reader = PatriciaStateReader(global_state_root=shared_state.contract_states, ffc=ffc) + state = CachedState(block_info=shared_state.block_info, state_reader=state_reader) + state.cache.update_writes( + contract_classes=contract_definitions, + address_to_class_hash={ + address: state.state.contract_hash for address, state in contract_states.items() + }, + address_to_nonce={address: state.nonce for address, state in contract_states.items()}, + storage_updates={ + (address, key): leaf.value + for address, state in contract_states.items() + for key, leaf in state.storage_updates.items() + }, + ) + return cls( + parent_state=None, + state=state, + resources_manager=ExecutionResourcesManager.empty(), + ) + + @property + def block_info(self) -> BlockInfo: + return self.state.block_info + + def create_child_state_for_querying(self) -> "CarriedState": + """ + Creates a lazy copy of self. + Used for transaction queries, where we want to have a separation from the parent state + (e.g., using the chain map mechanism to extract the most recent transaction's affect on the + state) and do not need to apply the changes. + Must not be used on regular flow. + """ + return CarriedState._create_from_parent_state(parent_state=self) + + @property + def state_selector(self) -> StateSelectorBase: + raise NotImplementedError("state_selector() is not implemented on StarkNet CarriedState.") + + def select(self, state_selector: StateSelectorBase) -> "CarriedState": + raise NotImplementedError("select() is not implemented on StarkNet CarriedState.") + + def _fill_missing(self, other: "CarriedState"): + raise NotImplementedError("_fill_missing() is not implemented on StarkNet CarriedState.") + + def __eq__(self, other: object) -> bool: + raise NotImplementedError + + def subtract_merkle_facts(self, previous_state: "CarriedState") -> "CarriedState": + """ + Subtraction of contract states from current carried state to previous one is unnecessary, + since it is very unlikely contract state will not change throughout a block. + """ + raise NotImplementedError( + "subtract_merkle_facts() is not implemented on StarkNet CarriedState." + ) + + def _apply(self): + """ + Applies state updates to self.parent_state. + This method should not be directly used; use copy_and_apply instead. + """ + # Apply state updates. + parent_state = self.non_optional_parent_state + parent_state.resources_manager = self.resources_manager + + # Update CachedState. + self.state._apply(parent=parent_state.state) + + # Update additional entire block-related information. + parent_state.state.block_info = self.state.block_info + + +@marshmallow_dataclass.dataclass(frozen=True) +class SharedState(SharedStateBase): + """ + A class representing a combination of the onchain and offchain state. + """ + + contract_states: PatriciaTree + block_info: BlockInfo + + @classmethod + async def empty(cls, ffc: FactFetchingContext, general_config: Config) -> "SharedState": + """ + Returns an empty state. This is called before creating very first block. + """ + # Downcast arguments to application-specific types. + assert isinstance(general_config, StarknetGeneralConfig) + + empty_contract_state = await ContractState.empty( + storage_commitment_tree_height=general_config.contract_storage_commitment_tree_height, + ffc=ffc, + ) + empty_contract_states = await PatriciaTree.empty_tree( + ffc=ffc, + height=general_config.global_state_commitment_tree_height, + leaf_fact=empty_contract_state, + ) + + return cls( + contract_states=empty_contract_states, + block_info=BlockInfo.empty(sequencer_address=general_config.sequencer_address), + ) + + def to_carried_state(self, ffc: FactFetchingContext) -> CarriedState: + """ + Returns an unfilled CarriedState. + """ + return CarriedState.create_unfilled(ffc=ffc, shared_state=self) + + async def get_filled_carried_state( + self, ffc: FactFetchingContext, state_selector: StateSelectorBase + ) -> CarriedState: + raise NotImplementedError( + "get_filled_carried_state() is not implemented on StarkNet SharedState." + ) + + async def apply_state_updates( + self, + ffc: FactFetchingContext, + previous_carried_state: CarriedStateBase, + current_carried_state: CarriedStateBase, + facts: Optional[BinaryFactDict] = None, + ) -> "SharedState": + # Note that previous_carried_state is part of the API of + # SharedStateBase.apply_state_updates(). + + # Downcast arguments to application-specific types. + assert isinstance(previous_carried_state, CarriedState) + assert isinstance(current_carried_state, CarriedState) + + state_objects_logger.debug( + f"Updating state from previous carried state: {previous_carried_state} " + f"to current carried state: {current_carried_state}" + ) + + # Prepare storage updates to apply. + state_cache = current_carried_state.state.cache + return await self.apply_updates( + ffc=ffc, + address_to_class_hash=state_cache._class_hash_writes, + address_to_nonce=state_cache._nonce_writes, + storage_updates=state_cache._storage_writes, + block_info=current_carried_state.state.block_info, + ) + + async def apply_updates( + self, + ffc: FactFetchingContext, + address_to_class_hash: Mapping[int, bytes], + address_to_nonce: Mapping[int, int], + storage_updates: Mapping[StorageEntry, int], + block_info: BlockInfo, + ) -> "SharedState": + address_to_storage_updates: Dict[int, ContractStorageMapping] = {} + for (address, key), value in storage_updates.items(): + contract_storage_updates = address_to_storage_updates.setdefault(address, {}) + contract_storage_updates[key] = StorageLeaf(value=value) + + accessed_addresses = ( + set(address_to_class_hash.keys()) + | set(address_to_nonce.keys()) + | {address for address, _ in storage_updates.keys()} + ) + current_contract_states = await self.contract_states.get_leaves( + ffc=ffc, indices=accessed_addresses, fact_cls=ContractState + ) + + # Update contract storage roots with cached changes. + updated_contract_states = await gather_in_chunks( + awaitables=( + current_contract_states[address].update( + ffc=ffc, + updates=address_to_storage_updates.get(address, {}), + nonce=address_to_nonce.get(address, None), + class_hash=address_to_class_hash.get(address, None), + ) + for address in accessed_addresses + ) + ) + + # Apply contract changes on global root. + updated_global_contract_root = await self.contract_states.update( + ffc=ffc, modifications=list(safe_zip(accessed_addresses, updated_contract_states)) + ) + + return SharedState(contract_states=updated_global_contract_root, block_info=block_info) + + +@marshmallow_dataclass.dataclass(frozen=True) +class StateDiff(EverestStateDiff): + """ + Holds uncommitted changes induced on StarkNet contracts. + """ + + class_hash_to_class: Mapping[bytes, ContractClass] + address_to_class_hash: Mapping[int, bytes] + address_to_nonce: Mapping[int, int] + storage_updates: Mapping[StorageEntry, int] + block_info: BlockInfo + + @classmethod + def from_cached_state(cls, cached_state: CachedState) -> "StateDiff": + state_cache = cached_state.cache + return cls( + class_hash_to_class=state_cache.contract_classes, + address_to_class_hash=state_cache._class_hash_writes, + address_to_nonce=state_cache._nonce_writes, + storage_updates=state_cache._storage_writes, + block_info=cached_state.block_info, + ) + + def to_cached_state(self, ffc: FactFetchingContext, state: SharedState) -> CachedState: + cached_state = CachedState( + block_info=self.block_info, + state_reader=PatriciaStateReader(global_state_root=state.contract_states, ffc=ffc), + ) + cached_state.cache.update_writes( + contract_classes=self.class_hash_to_class, + address_to_class_hash=self.address_to_class_hash, + address_to_nonce=self.address_to_nonce, + storage_updates=self.storage_updates, + ) + + return cached_state + + def squash(self, other: "StateDiff") -> "StateDiff": + class_hash_to_class = {**self.class_hash_to_class, **other.class_hash_to_class} + address_to_class_hash = {**self.address_to_class_hash, **other.address_to_class_hash} + address_to_nonce = {**self.address_to_nonce, **other.address_to_nonce} + storage_updates = {**self.storage_updates, **other.storage_updates} + self.block_info.validate_legal_progress(next_block_info=other.block_info) + + return StateDiff( + class_hash_to_class=class_hash_to_class, + address_to_class_hash=address_to_class_hash, + address_to_nonce=address_to_nonce, + storage_updates=storage_updates, + block_info=other.block_info, + ) + + async def commit( + self, ffc: FactFetchingContext, previous_state: SharedStateBase + ) -> SharedState: + # Downcast argument to application-specific type. + assert isinstance(previous_state, SharedState) + + return await previous_state.apply_updates( + ffc=ffc, + address_to_class_hash=self.address_to_class_hash, + address_to_nonce=self.address_to_nonce, + storage_updates=self.storage_updates, + block_info=self.block_info, + ) diff --git a/src/starkware/starknet/business_logic/internal_transaction_interface.py b/src/starkware/starknet/business_logic/internal_transaction_interface.py deleted file mode 100644 index 5c4a9e29..00000000 --- a/src/starkware/starknet/business_logic/internal_transaction_interface.py +++ /dev/null @@ -1,72 +0,0 @@ -import logging -from abc import abstractmethod -from typing import Iterable, Optional, cast - -from services.everest.business_logic.internal_transaction import EverestInternalStateTransaction -from services.everest.business_logic.state import CarriedStateBase -from starkware.starknet.business_logic.execution.objects import TransactionExecutionInfo -from starkware.starknet.business_logic.state.state import CarriedState, StateSelector -from starkware.starknet.definitions.error_codes import StarknetErrorCode -from starkware.starknet.definitions.general_config import StarknetGeneralConfig -from starkware.starkware_utils.config_base import Config -from starkware.starkware_utils.error_handling import StarkException - -logger = logging.getLogger(__name__) - - -class InternalStateTransaction(EverestInternalStateTransaction): - """ - StarkNet internal state transaction. - This is the API of transactions that update the state, - but do not necessarily have an external transaction counterpart. - See for example, SyntheticTransaction. - """ - - @staticmethod - def get_state_selector_of_many( - txs: Iterable["EverestInternalStateTransaction"], general_config: Config - ) -> StateSelector: - """ - Returns the state selector of a collection of transactions (i.e., union of selectors). - """ - # Downcast arguments to application-specific types. - assert isinstance(general_config, StarknetGeneralConfig) - - state_selector = EverestInternalStateTransaction._get_state_selector_of_many( - txs=txs, general_config=general_config, state_selector_cls=StateSelector - ) - return cast(StateSelector, state_selector) - - async def apply_state_updates( - self, state: CarriedStateBase, general_config: Config - ) -> Optional[TransactionExecutionInfo]: - """ - Applies the transaction on the commitment tree state in an atomic manner. - """ - # Downcast arguments to application-specific types. - assert isinstance(state, CarriedState) - assert isinstance(general_config, StarknetGeneralConfig) - - with state.copy_and_apply() as state_to_update: - try: - execution_info = await self._apply_specific_state_updates( - state=state_to_update, general_config=general_config - ) - except StarkException: - # Raise StarkException-s as-is, so failure information is not lost. - raise - except Exception as exception: - # Wrap all exceptions with StarkException, so the Batcher can continue running - # even after unexpected errors. - logger.error(f"Unexpected failure; exception details: {exception}.", exc_info=True) - raise StarkException( - code=StarknetErrorCode.UNEXPECTED_FAILURE, message=str(exception) - ) - - return execution_info - - @abstractmethod - async def _apply_specific_state_updates( - self, state: CarriedState, general_config: StarknetGeneralConfig - ) -> Optional[TransactionExecutionInfo]: - pass diff --git a/src/starkware/starknet/business_logic/state/CMakeLists.txt b/src/starkware/starknet/business_logic/state/CMakeLists.txt index 7ab855a5..fc785af2 100644 --- a/src/starkware/starknet/business_logic/state/CMakeLists.txt +++ b/src/starkware/starknet/business_logic/state/CMakeLists.txt @@ -3,26 +3,18 @@ python_lib(starknet_business_logic_state_lib FILES state.py - objects.py + state_api.py + state_api_objects.py LIBS cairo_version_lib - cairo_vm_lib - everest_business_logic_lib - everest_definitions_lib + everest_business_logic_state_api_lib starknet_contract_class_lib starknet_definitions_lib starknet_general_config_lib - starknet_os_abi_lib - starknet_storage_lib - starknet_transaction_lib - starkware_commitment_tree_facts_lib - starkware_config_utils_lib starkware_dataclasses_utils_lib starkware_error_handling_lib starkware_python_utils_lib - starkware_storage_lib starkware_utils_lib - pip_marshmallow pip_marshmallow_dataclass ) diff --git a/src/starkware/starknet/business_logic/state/state.py b/src/starkware/starknet/business_logic/state/state.py index 98b5fe0a..458facf3 100644 --- a/src/starkware/starknet/business_logic/state/state.py +++ b/src/starkware/starknet/business_logic/state/state.py @@ -1,538 +1,348 @@ -import copy -import dataclasses -import logging -import typing -from collections import ChainMap, defaultdict -from dataclasses import field -from typing import Mapping, MutableMapping, Optional, Set, Tuple - -import marshmallow_dataclass - -from services.everest.business_logic.state import ( - CarriedStateBase, - SharedStateBase, - StateSelectorBase, +import asyncio +import contextlib +from collections import ChainMap +from typing import Dict, Iterator, List, Mapping, Set, Tuple + +from starkware.python.utils import execute_coroutine_threadsafe +from starkware.starknet.business_logic.state.state_api import ( + State, + StateReader, + SyncState, + SyncStateReader, ) -from starkware.cairo.lang.version import __version__ as STARKNET_VERSION -from starkware.cairo.lang.vm.cairo_pie import ExecutionResources -from starkware.python.utils import gather_in_chunks, safe_zip -from starkware.starknet.business_logic.state.objects import ContractCarriedState, ContractState -from starkware.starknet.definitions import fields +from starkware.starknet.business_logic.state.state_api_objects import BlockInfo +from starkware.starknet.definitions import constants from starkware.starknet.definitions.error_codes import StarknetErrorCode -from starkware.starknet.definitions.general_config import ( - DEFAULT_GAS_PRICE, - DEFAULT_SEQUENCER_ADDRESS, - StarknetGeneralConfig, -) from starkware.starknet.services.api.contract_class import ContractClass -from starkware.starknet.services.api.gateway.transaction import DECLARE_SENDER_ADDRESS -from starkware.starknet.storage.starknet_storage import StorageLeaf -from starkware.starkware_utils.commitment_tree.binary_fact_tree import BinaryFactDict -from starkware.starkware_utils.commitment_tree.patricia_tree.patricia_tree import PatriciaTree -from starkware.starkware_utils.config_base import Config -from starkware.starkware_utils.error_handling import ( - StarkException, - stark_assert_eq, - stark_assert_le, -) -from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass -from starkware.storage.storage import FactFetchingContext +from starkware.starkware_utils.error_handling import stark_assert -logger = logging.getLogger(__name__) -state_objects_logger = logging.getLogger(f"{__name__}:state_objects_logger") +StorageEntry = Tuple[int, int] # (contract_address, key). -ContractCarriedStateMapping = MutableMapping[int, ContractCarriedState] -ContractCarriedStateChainMapping = typing.ChainMap[int, ContractCarriedState] +class StateSyncifier(SyncState): + """ + Acts as a synchronous variant of a given (asynchronous) State object. + Should be used only from within the given loop. + """ -@marshmallow_dataclass.dataclass(frozen=True) -class BlockInfo(ValidatedMarshmallowDataclass): - # The sequence number of the last block created. - block_number: int = field(metadata=fields.block_number_metadata) + def __init__(self, async_state: State, loop: asyncio.AbstractEventLoop): + # State to sychronize. + self.async_state = async_state - # Timestamp of the beginning of the last block creation attempt. - block_timestamp: int = field(metadata=fields.timestamp_metadata) + # Current running event loop; used for running async tasks in a synchronous context. + self.loop = loop - # L1 gas price (in Wei) measured at the beginning of the last block creation attempt. - gas_price: int = field(metadata=fields.gas_price_metadata) + @property + def block_info(self) -> BlockInfo: + return self.async_state.block_info - # The sequencer address of this block. - sequencer_address: Optional[int] = field(metadata=fields.optional_sequencer_address_metadata) + def update_block_info(self, block_info: BlockInfo): + self.async_state.block_info = block_info - # The version of StarkNet system (e.g., "0.9.1"). - starknet_version: Optional[str] = field(metadata=fields.starknet_version_metadata) + def get_contract_class(self, class_hash: bytes) -> ContractClass: + return execute_coroutine_threadsafe( + coroutine=self.async_state.get_contract_class(class_hash=class_hash), loop=self.loop + ) - @classmethod - def empty(cls, sequencer_address: Optional[int]) -> "BlockInfo": - """ - Returns an empty BlockInfo object; i.e., the one before the first in the chain. - """ - return cls( - block_number=-1, - block_timestamp=0, - gas_price=0, - sequencer_address=sequencer_address, - starknet_version=STARKNET_VERSION, + def get_class_hash_at(self, contract_address: int) -> bytes: + return execute_coroutine_threadsafe( + coroutine=self.async_state.get_class_hash_at(contract_address=contract_address), + loop=self.loop, ) - @classmethod - def create_for_testing(cls, block_number: int, block_timestamp: int) -> "BlockInfo": - """ - Returns a BlockInfo object with default gas_price. - """ - return cls( - block_number=block_number, - block_timestamp=block_timestamp, - gas_price=DEFAULT_GAS_PRICE, - sequencer_address=DEFAULT_SEQUENCER_ADDRESS, - starknet_version=STARKNET_VERSION, + def get_nonce_at(self, contract_address: int) -> int: + return execute_coroutine_threadsafe( + coroutine=self.async_state.get_nonce_at(contract_address=contract_address), + loop=self.loop, ) - def validate_legal_progress(self, next_block_info: "BlockInfo"): - """ - Validates that next_block_info is a legal progress of self. - """ - # Check that the block number increases by 1. - stark_assert_eq( - next_block_info.block_number, - self.block_number + 1, - code=StarknetErrorCode.INVALID_BLOCK_NUMBER, - message="Block number must increase by 1.", + def get_storage_at(self, contract_address: int, key: int) -> int: + return execute_coroutine_threadsafe( + coroutine=self.async_state.get_storage_at(contract_address=contract_address, key=key), + loop=self.loop, ) - # Check that block timestamp in not decreasing. - stark_assert_le( - self.block_timestamp, - next_block_info.block_timestamp, - code=StarknetErrorCode.INVALID_BLOCK_TIMESTAMP, - message="Block timestamp must not decrease.", + def set_contract_class(self, class_hash: bytes, contract_class: ContractClass): + return execute_coroutine_threadsafe( + coroutine=self.async_state.set_contract_class( + class_hash=class_hash, contract_class=contract_class + ), + loop=self.loop, ) + def deploy_contract(self, contract_address: int, class_hash: bytes): + return execute_coroutine_threadsafe( + coroutine=self.async_state.deploy_contract( + class_hash=class_hash, contract_address=contract_address + ), + loop=self.loop, + ) + + def increment_nonce(self, contract_address: int): + return execute_coroutine_threadsafe( + coroutine=self.async_state.increment_nonce(contract_address=contract_address), + loop=self.loop, + ) + + def set_storage_at(self, contract_address: int, key: int, value: int): + return execute_coroutine_threadsafe( + coroutine=self.async_state.set_storage_at( + contract_address=contract_address, key=key, value=value + ), + loop=self.loop, + ) -@dataclasses.dataclass(frozen=True) -class StateSelector(StateSelectorBase): + +class StateCache: """ - A class that contains a set of StarkNet contract addresses (sub-commitment tree root IDs) - and a set of hashes of relevant contract classes - affected by one/many transaction(s). - Used for fetching those sub-trees and classes from storage before transaction(s) processing. + Holds read and write requests. """ - contract_addresses: Set[int] - class_hashes: Set[bytes] + def __init__(self): + self.contract_classes: Dict[bytes, ContractClass] = {} - @classmethod - def empty(cls) -> "StateSelector": - return cls(contract_addresses=set(), class_hashes=set()) + # Reader's cached information. + self._class_hash_reads: Dict[int, bytes] = {} + self._nonce_reads: Dict[int, int] = {} + self._storage_reads: Dict[StorageEntry, int] = {} - def __and__(self, other: "StateSelector") -> "StateSelector": - return StateSelector( - contract_addresses=self.contract_addresses & other.contract_addresses, - class_hashes=self.class_hashes & other.class_hashes, - ) + # Writer's cached information. + self._class_hash_writes: Dict[int, bytes] = {} + self._nonce_writes: Dict[int, int] = {} + self._storage_writes: Dict[StorageEntry, int] = {} - def __or__(self, other: "StateSelector") -> "StateSelector": - return StateSelector( - contract_addresses=self.contract_addresses | other.contract_addresses, - class_hashes=self.class_hashes | other.class_hashes, - ) + # State view. - def __sub__(self, other: "StateSelector") -> "StateSelector": - return StateSelector( - contract_addresses=self.contract_addresses - other.contract_addresses, - class_hashes=self.class_hashes - other.class_hashes, + # Mappings from contract address to different attributes. + self.address_to_class_hash: Mapping[int, bytes] = ChainMap( + self._class_hash_writes, self._class_hash_reads ) - - def __le__(self, other: "StateSelector") -> bool: - return (self.contract_addresses <= other.contract_addresses) and ( - self.class_hashes <= other.class_hashes + self.address_to_nonce: Mapping[int, int] = ChainMap(self._nonce_writes, self._nonce_reads) + # Mapping from (contract_address, key) to a value in the contract's storage. + self.storage_view: Mapping[StorageEntry, int] = ChainMap( + self._storage_writes, self._storage_reads ) + def update_writes_from_other(self, other: "StateCache"): + self.contract_classes.update(other.contract_classes) + self._class_hash_writes.update(other._class_hash_writes) + self._nonce_writes.update(other._nonce_writes) + self._storage_writes.update(other._storage_writes) -class CarriedState(CarriedStateBase): - """ - A state containing a mapping from contract addresses to their states and the accumulated - modifications to the contract storage across transactions. - - This will be a sub-state of the total state (SharedState). It is carried and maintained by - the Batcher, as each pending transaction is applied to it during the attempt to include it in - a block. After a block is created the carried state is applied to the shared state. - """ - - def __init__( + def update_writes( self, - parent_state: Optional["CarriedState"], - shared_state: "SharedState", - ffc: FactFetchingContext, - contract_definitions: typing.ChainMap[bytes, ContractClass], - contract_states: ContractCarriedStateChainMapping, - cairo_usage: ExecutionResources, - modified_contracts: typing.ChainMap[int, None], - block_info: BlockInfo, - syscall_counter: typing.ChainMap[str, int], + contract_classes: Mapping[bytes, ContractClass], + address_to_class_hash: Mapping[int, bytes], + address_to_nonce: Mapping[int, int], + storage_updates: Mapping[Tuple[int, int], int], ): - """ - Private constructor. - Should only be called by _create_from_parent_state and create_unfilled class methods. - """ - super().__init__(parent_state=parent_state) + self.contract_classes.update(contract_classes) + self._class_hash_writes.update(address_to_class_hash) + self._nonce_writes.update(address_to_nonce) + self._storage_writes.update(storage_updates) + + def get_accessed_contract_addresses(self) -> Set[int]: + return { + *self.address_to_class_hash.keys(), + *self.address_to_nonce.keys(), + *[address for address, _key in self.storage_view.keys()], + } - # The last committed state; the one this carried state was created from. - # Used for dynamic retrieval of facts during transaction execution. - self.shared_state = shared_state + def get_accessed_class_hashes(self) -> Set[bytes]: + return set(self.contract_classes.keys()) - # A mapping from class hash to contract class. - self.contract_definitions = contract_definitions - # A mapping from contract address to its carried state. - self.contract_states = contract_states +class CachedState(State): + """ + A cached implementation of the State API. See State's documentation. + """ - # The accumulated Cairo usage. - self.cairo_usage = cairo_usage + def __init__(self, block_info: BlockInfo, state_reader: StateReader): + self.block_info = block_info + self.state_reader = state_reader + self.cache = StateCache() - # Carried state fetches commitment tree leaves from storage during transaction processing. - self.ffc = ffc + def update_block_info(self, block_info: BlockInfo): + self.block_info = block_info - # Addresses of contracts whose storage has changed. - self.modified_contracts = modified_contracts + async def get_contract_class(self, class_hash: bytes) -> ContractClass: + if class_hash not in self.cache.contract_classes: + self.cache.contract_classes[class_hash] = await self.state_reader.get_contract_class( + class_hash=class_hash + ) - self.block_info = block_info + return self.cache.contract_classes[class_hash] - # A mapping from system call to the cumulative times it was invoked. - self.syscall_counter = syscall_counter + async def get_class_hash_at(self, contract_address: int) -> bytes: + if contract_address not in self.cache.address_to_class_hash: + class_hash = await self.state_reader.get_class_hash_at( + contract_address=contract_address + ) + self.cache._class_hash_reads[contract_address] = class_hash - @classmethod - def _create_from_parent_state(cls, parent_state: "CarriedState") -> "CarriedState": - """ - Instantiates a CarriedState object that acts as proxy to given parent_state. - """ - return cls( - # Parent state - must not be modified. - parent_state=parent_state, - # Immutable objects. - shared_state=parent_state.shared_state, - ffc=parent_state.ffc, - cairo_usage=parent_state.cairo_usage, - block_info=parent_state.block_info, - # Chain maps - changes are inserted to the first map (at index 0); parent maps must not - # be modified. - contract_definitions=parent_state.contract_definitions.new_child(), - contract_states=parent_state.contract_states.new_child(), - modified_contracts=(parent_state.modified_contracts.new_child()), - syscall_counter=parent_state.syscall_counter.new_child(), - ) + return self.cache.address_to_class_hash[contract_address] - @classmethod - def create_unfilled( - cls, shared_state: "SharedState", ffc: FactFetchingContext - ) -> "CarriedState": - """ - Creates a carried state based on the given shared state, where the fields related to the - commitment leaves (e.g., contract states) are kept unfilled. - """ - return cls( - parent_state=None, - ffc=ffc, - shared_state=shared_state, - contract_definitions=ChainMap(), - contract_states=ChainMap(), - cairo_usage=ExecutionResources.empty(), - modified_contracts=ChainMap(), - block_info=shared_state.block_info, - syscall_counter=ChainMap(), - ) + async def get_nonce_at(self, contract_address: int) -> int: + if contract_address not in self.cache.address_to_nonce: + self.cache._nonce_reads[contract_address] = await self.state_reader.get_nonce_at( + contract_address=contract_address + ) - @classmethod - async def empty_for_testing( - cls, - shared_state: Optional["SharedState"], - ffc: FactFetchingContext, - general_config: StarknetGeneralConfig, - ) -> "CarriedState": - """ - Creates an empty carried state allowing accessing all possible contract addresses (by - using defaultdict). This constructor should only be used in tests. - """ - empty_contract_state = await ContractState.empty( - storage_commitment_tree_height=general_config.contract_storage_commitment_tree_height, - ffc=ffc, - ) + return self.cache.address_to_nonce[contract_address] - if shared_state is None: - shared_state = await SharedState.empty(ffc=ffc, general_config=general_config) + async def get_storage_at(self, contract_address: int, key: int) -> int: + address_key_pair = (contract_address, key) + if address_key_pair not in self.cache.storage_view: + self.cache._storage_reads[address_key_pair] = await self.state_reader.get_storage_at( + contract_address=contract_address, key=key + ) - return cls.from_contracts( - ffc=ffc, - contract_definitions={}, - shared_state=shared_state, - contract_states=defaultdict( - lambda: ContractCarriedState.from_state(state=copy.deepcopy(empty_contract_state)) - ), - ) + return self.cache.storage_view[address_key_pair] - @classmethod - def from_contracts( - cls, - shared_state: "SharedState", - ffc: FactFetchingContext, - contract_definitions: MutableMapping[bytes, ContractClass], - contract_states: ContractCarriedStateMapping, - ) -> "CarriedState": - """ - Returns a carried state object, containing the given contracts. - Other members are initialized with the empty object values. - This is a utility function and should not be used in the regular flow. - """ - return cls( - parent_state=None, - ffc=ffc, - shared_state=shared_state, - contract_definitions=ChainMap(contract_definitions), - contract_states=ChainMap(contract_states), - cairo_usage=ExecutionResources.empty(), - modified_contracts=ChainMap(), - block_info=shared_state.block_info, - syscall_counter=ChainMap(), - ) + async def set_contract_class(self, class_hash: bytes, contract_class: ContractClass): + self.cache.contract_classes[class_hash] = contract_class - @property - def state_selector(self) -> StateSelector: - """ - Returns the state selector of this CarriedState, containing: - 1. The contract addresses that serve as the commitment tree leaf IDs of the full StarkNet - state commitment tree. - 2. The hashes of the contract classes relevant for execution, - not including class hashes of any class instance (i.e., contract state). - """ - all_class_hashes = set(self.contract_definitions.keys()) - class_hashes_of_instances = set( - self.contract_states[contract_address].state.contract_hash - for contract_address in self.contract_states + async def deploy_contract(self, contract_address: int, class_hash: bytes): + stark_assert( + contract_address != 0, + code=StarknetErrorCode.OUT_OF_RANGE_ADDRESS, + message=f"Cannot deploy contract at address 0.", ) - # Keep the hashes that do not appear in a contract instance, - # in order for those sets to be disjoint. - independent_class_hashes = all_class_hashes - class_hashes_of_instances - return StateSelector( - contract_addresses=set(self.contract_states.keys()) - {DECLARE_SENDER_ADDRESS}, - class_hashes=independent_class_hashes, + current_class_hash = await self.get_class_hash_at(contract_address=contract_address) + stark_assert( + current_class_hash == constants.UNINITIALIZED_CLASS_HASH, + code=StarknetErrorCode.CONTRACT_ADDRESS_UNAVAILABLE, + message=f"Requested contract address {contract_address} is unavailable for deployment.", ) - def create_child_state_for_querying(self) -> "CarriedState": - """ - Creates a lazy copy of self. - Used for transaction queries, where we want to have a separation from the parent state - (e.g., using the chain map mechanism to extract the most recent transaction's affect on the - state) and do not need to apply the changes. - Must not be used on regular flow. - """ - return CarriedState._create_from_parent_state(parent_state=self) + self.cache._class_hash_writes[contract_address] = class_hash - def select(self, state_selector: StateSelectorBase) -> "CarriedState": - raise NotImplementedError("select() is not implemented on StarkNet CarriedState.") + async def increment_nonce(self, contract_address: int): + current_nonce = await self.get_nonce_at(contract_address=contract_address) + self.cache._nonce_writes[contract_address] = current_nonce + 1 - def _fill_missing(self, other: "CarriedState"): + async def set_storage_at(self, contract_address: int, key: int, value: int): + self.cache._storage_writes[(contract_address, key)] = value + + def _copy(self) -> "CachedState": + # Note that the reader's cache may be updated by this copy's read requests. + return CachedState(block_info=self.block_info, state_reader=self) + + def _apply(self, parent: "CachedState"): """ - Enriches state with the missing information from another CarriedState instance. - This is a private method, only to be called from public fill_missing method. + Apply updates to parent state. """ - self.contract_states.update(other.contract_states) - self.contract_definitions.update(other.contract_definitions) + assert self.state_reader is parent, "Current reader expected to be the parent state." - def __eq__(self, other: object) -> bool: - if not isinstance(other, CarriedState): - return NotImplemented + parent.block_info = self.block_info + parent.cache.update_writes_from_other(other=self.cache) - return self.contract_states == other.contract_states and self.block_info == other.block_info + @contextlib.contextmanager + def copy_and_apply(self: "CachedState") -> Iterator["CachedState"]: + copied_state = self._copy() + # The exit logic will not be called in case an exception is raised inside the context. + yield copied_state + copied_state._apply(parent=self) # Apply to self. - def update_contract_storage( - self, contract_address: int, modifications: Mapping[int, StorageLeaf] - ): - """ - Applies the given storage modifications to the given contract storage. - """ - contract_carried_state = self.contract_states[contract_address] - self.contract_states[contract_address] = dataclasses.replace( - contract_carried_state, - storage_updates={ - **contract_carried_state.storage_updates, - **modifications, - }, - ) - def subtract_merkle_facts(self, previous_state: "CarriedState") -> "CarriedState": - """ - Subtraction of contract states from current carried state to previous one is unnecessary, - since it is very unlikely contract state will not change throughout a block. - """ - raise NotImplementedError +class CachedSyncState(SyncState): + """ + A cached implementation of the SyncState API. See CachedState's documentation. + """ + + def __init__(self, block_info: BlockInfo, state_reader: SyncStateReader): + self._block_info = block_info + self.state_reader = state_reader + self.cache = StateCache() @property - def chain_maps(self) -> Tuple[typing.ChainMap, ...]: - return ( - self.contract_states, - self.contract_definitions, - self.modified_contracts, - self.syscall_counter, - ) + def block_info(self) -> BlockInfo: + return self._block_info - def _validate_references_of_chain_maps(self): - assert self.parent_state is not None - for child_chain_map, parent_chain_map in zip(self.chain_maps, self.parent_state.chain_maps): - # Verify that the child's parent maps are all references to its (expected) parent maps. - assert all( - child_map is parent_map - # safe_zip also verifies that the lists are of the same length. - for child_map, parent_map in safe_zip( - child_chain_map.parents.maps, parent_chain_map.maps - ) - ), "Child ChainMap does not hold a reference to its parent." - - def _apply(self): - """ - Applies state updates to self.parent_state. - This method should not be directly used; use copy_and_apply instead. - """ - assert self.parent_state is not None - self._validate_references_of_chain_maps() + def update_block_info(self, block_info: BlockInfo): + self._block_info = block_info - # Apply state updates. - self.parent_state.cairo_usage = self.cairo_usage - for child_chain_map, parent_chain_map in zip(self.chain_maps, self.parent_state.chain_maps): - parent_chain_map.update(child_chain_map.maps[0]) + def get_contract_class(self, class_hash: bytes) -> ContractClass: + if class_hash not in self.cache.contract_classes: + self.cache.contract_classes[class_hash] = self.state_reader.get_contract_class( + class_hash=class_hash + ) - # Update additional entire block-related information. - self.parent_state.block_info = self.block_info + return self.cache.contract_classes[class_hash] - def get_contract_class(self, class_hash: bytes) -> ContractClass: - """ - Returns the contract class with the given hash. - Raises an exception if the contract class is not declared. - """ - contract_class = self.contract_definitions.get(class_hash, None) + def get_class_hash_at(self, contract_address: int) -> bytes: + if contract_address not in self.cache.address_to_class_hash: + self.cache._class_hash_reads[contract_address] = self.state_reader.get_class_hash_at( + contract_address=contract_address + ) - if contract_class is not None: - return contract_class + return self.cache.address_to_class_hash[contract_address] - formatted_class_hash = fields.class_hash_from_bytes(class_hash) - raise StarkException( - code=StarknetErrorCode.UNEXPECTED_FAILURE, - message=f"Class with hash {formatted_class_hash} is missing from state.", - ) + def get_nonce_at(self, contract_address: int) -> int: + if contract_address not in self.cache.address_to_nonce: + self.cache._nonce_reads[contract_address] = self.state_reader.get_nonce_at( + contract_address=contract_address + ) + return self.cache.address_to_nonce[contract_address] -@marshmallow_dataclass.dataclass(frozen=True) -class SharedState(SharedStateBase): - """ - A class representing a combination of the onchain and offchain state. - """ + def get_storage_at(self, contract_address: int, key: int) -> int: + address_key_pair = (contract_address, key) + if address_key_pair not in self.cache.storage_view: + self.cache._storage_reads[address_key_pair] = self.state_reader.get_storage_at( + contract_address=contract_address, key=key + ) - contract_states: PatriciaTree - block_info: BlockInfo + return self.cache.storage_view[address_key_pair] - @classmethod - async def empty(cls, ffc: FactFetchingContext, general_config: Config) -> "SharedState": - """ - Returns an empty state. This is called before creating very first block. - """ - # Downcast arguments to application-specific types. - assert isinstance(general_config, StarknetGeneralConfig) + def set_contract_class(self, class_hash: bytes, contract_class: ContractClass): + self.cache.contract_classes[class_hash] = contract_class - empty_contract_state = await ContractState.empty( - storage_commitment_tree_height=general_config.contract_storage_commitment_tree_height, - ffc=ffc, - ) - empty_contract_states = await PatriciaTree.empty_tree( - ffc=ffc, - height=general_config.global_state_commitment_tree_height, - leaf_fact=empty_contract_state, + def deploy_contract(self, contract_address: int, class_hash: bytes): + stark_assert( + class_hash != constants.UNINITIALIZED_CLASS_HASH, + code=StarknetErrorCode.OUT_OF_RANGE_ADDRESS, + message=f"Cannot deploy contract address 0.", ) - return cls( - contract_states=empty_contract_states, - block_info=BlockInfo.empty(sequencer_address=general_config.sequencer_address), + current_class_hash = self.get_class_hash_at(contract_address=contract_address) + stark_assert( + current_class_hash == constants.UNINITIALIZED_CLASS_HASH, + code=StarknetErrorCode.CONTRACT_ADDRESS_UNAVAILABLE, + message=f"Requested contract address {contract_address} is unavailable for deployment.", ) - def to_carried_state(self, ffc: FactFetchingContext) -> CarriedState: - """ - Returns an unfilled CarriedState. Its contract states should be filled using - get_filled_carried_state() method. - """ - return CarriedState.create_unfilled(ffc=ffc, shared_state=self) + self.cache._class_hash_writes[contract_address] = class_hash - async def get_filled_carried_state( - self, ffc: FactFetchingContext, state_selector: StateSelectorBase - ) -> CarriedState: - # Downcast arguments to application-specific types. - assert isinstance(state_selector, StateSelector) + def increment_nonce(self, contract_address: int): + current_nonce = self.get_nonce_at(contract_address=contract_address) + self.cache._nonce_writes[contract_address] = current_nonce + 1 - # Fetch required data from DB, according to the state selector. - contract_states = await self.contract_states.get_leaves( - ffc=ffc, indices=state_selector.contract_addresses, fact_cls=ContractState - ) - contract_classes = await ContractState.fetch_contract_classes( - contract_states=contract_states.values(), - class_hashes=state_selector.class_hashes, - ffc=ffc, - ) + def set_storage_at(self, contract_address: int, key: int, value: int): + self.cache._storage_writes[(contract_address, key)] = value - # Fill carried_state with fetched data. - contract_carried_states = { - contract_address: ContractCarriedState.from_state(state=contract_state) - for contract_address, contract_state in contract_states.items() - } - return CarriedState.from_contracts( - ffc=ffc, - shared_state=self, - contract_definitions=contract_classes, - contract_states=contract_carried_states, - ) +class ContractStorageState: + """ + Defines the API for accessing StarkNet single contract storage state. + """ - async def apply_state_updates( - self, - ffc: FactFetchingContext, - previous_carried_state: CarriedStateBase, - current_carried_state: CarriedStateBase, - facts: Optional[BinaryFactDict] = None, - ) -> "SharedState": - # Note that previous_carried_state is part of the API of - # SharedStateBase.apply_state_updates(). - - # Downcast arguments to application-specific types. - assert isinstance(previous_carried_state, CarriedState) - assert isinstance(current_carried_state, CarriedState) - - # Verify the carried states originated from this shared state. - assert previous_carried_state.shared_state is self - assert current_carried_state.shared_state is self - - state_objects_logger.debug( - f"Updating state from previous carried state: {previous_carried_state} " - f"to current carried state: {current_carried_state}" - ) + def __init__(self, state: SyncState, contract_address: int): + self.state = state + self.contract_address = contract_address - # Update contract storage roots with cached changes. - updated_contract_states = await gather_in_chunks( - awaitables=( - contract_state.update(ffc=ffc) - for contract_state in current_carried_state.contract_states.values() - ) - ) - contract_states: typing.ChainMap[int, ContractCarriedState] = ChainMap( - dict(safe_zip(current_carried_state.contract_states.keys(), updated_contract_states)) - ) + # Maintain all read request values in chronological order. + self.read_values: List[int] = [] + self.accessed_keys: Set[int] = set() - # Apply changes. - contract_state_modifications = { - contract_address: contract_carried_state.state - for contract_address, contract_carried_state in (contract_states.items()) - } - updated_global_contract_root = await self.contract_states.update( - ffc=ffc, modifications=list(contract_state_modifications.items()) - ) + def read(self, address: int) -> int: + self.accessed_keys.add(address) + value = self.state.get_storage_at(contract_address=self.contract_address, key=address) + self.read_values.append(value) - return SharedState( - contract_states=updated_global_contract_root, - block_info=current_carried_state.block_info, - ) + return value + + def write(self, address: int, value: int): + self.accessed_keys.add(address) + self.state.set_storage_at(contract_address=self.contract_address, key=address, value=value) diff --git a/src/starkware/starknet/business_logic/state/state_api.py b/src/starkware/starknet/business_logic/state/state_api.py new file mode 100644 index 00000000..6f7b6143 --- /dev/null +++ b/src/starkware/starknet/business_logic/state/state_api.py @@ -0,0 +1,135 @@ +from abc import ABC, abstractmethod + +from services.everest.business_logic.state_api import StateProxy +from starkware.starknet.business_logic.state.state_api_objects import BlockInfo +from starkware.starknet.services.api.contract_class import ContractClass + + +class StateReader(ABC): + """ + A read-only API for accessing StarkNet global state. + """ + + @abstractmethod + async def get_contract_class(self, class_hash: bytes) -> ContractClass: + """ + Returns the contract class of the given class hash. + Raises an exception if said class was not declared. + """ + + @abstractmethod + async def get_class_hash_at(self, contract_address: int) -> bytes: + """ + Returns the class hash of the contract class at the given address. + """ + + @abstractmethod + async def get_nonce_at(self, contract_address: int) -> int: + """ + Returns the nonce of the given contract instance. + """ + + @abstractmethod + async def get_storage_at(self, contract_address: int, key: int) -> int: + """ + Returns the storage value under the given key in the given contract instance. + """ + + +class State(StateProxy, StateReader): + """ + A class defining the API for accessing StarkNet global state. + + Reader functionality is injected through dependency, rather than inherited (only the abstract + API is inherited). + """ + + block_info: BlockInfo + state_reader: StateReader # Reader functionality. + + @abstractmethod + def update_block_info(self, block_info: BlockInfo): + """ + Updates the block info. + """ + + @abstractmethod + async def set_contract_class(self, class_hash: bytes, contract_class: ContractClass): + """ + Sets the given contract class under the given class hash. + """ + + @abstractmethod + async def deploy_contract(self, contract_address: int, class_hash: bytes): + """ + Allocates the given address to the given class hash. + Raises an exception if the address is already assigned; + meaning: this is a write once action. + """ + + @abstractmethod + async def increment_nonce(self, contract_address: int): + """ + Increments the nonce of the given contract instance. + """ + + @abstractmethod + async def set_storage_at(self, contract_address: int, key: int, value: int): + """ + Sets the storage value under the given key in the given contract instance. + """ + + +class SyncStateReader(ABC): + """ + See StateReader's documentation. + """ + + @abstractmethod + def get_contract_class(self, class_hash: bytes) -> ContractClass: + pass + + @abstractmethod + def get_class_hash_at(self, contract_address: int) -> bytes: + pass + + @abstractmethod + def get_nonce_at(self, contract_address: int) -> int: + pass + + @abstractmethod + def get_storage_at(self, contract_address: int, key: int) -> int: + pass + + +class SyncState(SyncStateReader, StateProxy): + """ + See State's documentation. + """ + + @property + @abstractmethod + def block_info(self) -> BlockInfo: + pass + + @abstractmethod + def set_contract_class(self, class_hash: bytes, contract_class: ContractClass): + pass + + @abstractmethod + def deploy_contract(self, contract_address: int, class_hash: bytes): + pass + + @abstractmethod + def increment_nonce(self, contract_address: int): + pass + + @abstractmethod + def update_block_info(self, block_info: BlockInfo): + """ + Updates the block info. + """ + + @abstractmethod + def set_storage_at(self, contract_address: int, key: int, value: int): + pass diff --git a/src/starkware/starknet/business_logic/state/state_api_objects.py b/src/starkware/starknet/business_logic/state/state_api_objects.py new file mode 100644 index 00000000..55dc1d1b --- /dev/null +++ b/src/starkware/starknet/business_logic/state/state_api_objects.py @@ -0,0 +1,84 @@ +from dataclasses import field +from typing import Optional + +import marshmallow_dataclass + +from starkware.cairo.lang.version import __version__ as STARKNET_VERSION +from starkware.starknet.definitions import fields +from starkware.starknet.definitions.error_codes import StarknetErrorCode +from starkware.starknet.definitions.general_config import ( + DEFAULT_GAS_PRICE, + DEFAULT_SEQUENCER_ADDRESS, +) +from starkware.starkware_utils.error_handling import stark_assert_eq, stark_assert_le +from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass + + +@marshmallow_dataclass.dataclass(frozen=True) +class BlockInfo(ValidatedMarshmallowDataclass): + # The sequence number of the last block created. + block_number: int = field(metadata=fields.block_number_metadata) + + # Timestamp of the beginning of the last block creation attempt. + block_timestamp: int = field(metadata=fields.timestamp_metadata) + + # L1 gas price (in Wei) measured at the beginning of the last block creation attempt. + gas_price: int = field(metadata=fields.gas_price_metadata) + + # The sequencer address of this block. + sequencer_address: Optional[int] = field(metadata=fields.optional_sequencer_address_metadata) + + # The version of StarkNet system (e.g. "0.10.0"). + starknet_version: Optional[str] = field(metadata=fields.starknet_version_metadata) + + @classmethod + def empty(cls, sequencer_address: Optional[int]) -> "BlockInfo": + """ + Returns an empty BlockInfo object; i.e., the one before the first in the chain. + """ + return cls( + block_number=-1, + block_timestamp=0, + gas_price=0, + sequencer_address=sequencer_address, + starknet_version=STARKNET_VERSION, + ) + + @classmethod + def create_for_testing( + cls, + block_number: int, + block_timestamp: int, + gas_price: int = DEFAULT_GAS_PRICE, + sequencer_address: int = DEFAULT_SEQUENCER_ADDRESS, + ) -> "BlockInfo": + """ + Returns a BlockInfo object with default gas_price. + """ + return cls( + block_number=block_number, + block_timestamp=block_timestamp, + gas_price=gas_price, + sequencer_address=sequencer_address, + starknet_version=STARKNET_VERSION, + ) + + def validate_legal_progress(self, next_block_info: "BlockInfo"): + """ + Validates that next_block_info is a legal progress of self. + """ + # Check that the block number increases by 1. + stark_assert_eq( + next_block_info.block_number, + self.block_number + 1, + code=StarknetErrorCode.INVALID_BLOCK_NUMBER, + message="Block number must increase by 1.", + ) + + # Check that block timestamp in not decreasing. + stark_assert_le( + self.block_timestamp, + next_block_info.block_timestamp, + code=StarknetErrorCode.INVALID_BLOCK_TIMESTAMP, + message="Block timestamp must not decrease.", + ) diff --git a/src/starkware/starknet/business_logic/transaction/CMakeLists.txt b/src/starkware/starknet/business_logic/transaction/CMakeLists.txt new file mode 100644 index 00000000..af0ade34 --- /dev/null +++ b/src/starkware/starknet/business_logic/transaction/CMakeLists.txt @@ -0,0 +1,80 @@ +python_lib(starknet_transaction_objects_lib + PREFIX starkware/starknet/business_logic/transaction + + FILES + objects.py + + LIBS + everest_business_logic_lib + everest_business_logic_state_api_lib + everest_internal_transaction_lib + everest_transaction_lib + starknet_abi_lib + starknet_business_logic_fact_state_lib + starknet_business_logic_patricia_state_lib + starknet_business_logic_state_lib + starknet_business_logic_utils_lib + starknet_contract_address_lib + starknet_contract_class_lib + starknet_definitions_lib + starknet_execute_entry_point_lib + starknet_general_config_lib + starknet_transaction_state_objects_lib + starknet_os_abi_lib + starknet_os_utils_lib + starknet_transaction_execution_objects_lib + starknet_transaction_fee_lib + starknet_transaction_hash_lib + starknet_transaction_lib + starkware_config_utils_lib + starkware_dataclasses_field_utils_lib + starkware_error_handling_lib + starkware_python_utils_lib + starkware_storage_lib + pip_marshmallow + pip_marshmallow_dataclass + pip_marshmallow_enum + pip_marshmallow_oneofschema +) + +python_lib(starknet_transaction_state_objects_lib + PREFIX starkware/starknet/business_logic/transaction + + FILES + state_objects.py + + LIBS + cairo_vm_lib + everest_business_logic_lib + everest_business_logic_state_api_lib + everest_internal_transaction_lib + everest_transaction_lib + starknet_business_logic_fact_state_lib + starknet_business_logic_patricia_state_lib + starknet_business_logic_state_lib + starknet_definitions_lib + starknet_general_config_lib + starknet_transaction_lib + starknet_transaction_execution_objects_lib + starkware_config_utils_lib + starkware_error_handling_lib +) + +python_lib(starknet_transaction_fee_lib + PREFIX starkware/starknet/business_logic/transaction + + FILES + fee.py + + LIBS + starknet_abi_lib + starknet_business_logic_fact_state_lib + starknet_business_logic_state_lib + starknet_business_logic_utils_lib + starknet_contract_class_lib + starknet_definitions_lib + starknet_execute_entry_point_lib + starknet_general_config_lib + starknet_transaction_execution_objects_lib + starkware_error_handling_lib +) diff --git a/src/starkware/starknet/business_logic/transaction_fee.py b/src/starkware/starknet/business_logic/transaction/fee.py similarity index 57% rename from src/starkware/starknet/business_logic/transaction_fee.py rename to src/starkware/starknet/business_logic/transaction/fee.py index 0e78e952..9acaa73a 100644 --- a/src/starkware/starknet/business_logic/transaction_fee.py +++ b/src/starkware/starknet/business_logic/transaction/fee.py @@ -1,14 +1,14 @@ import math -from typing import Mapping from starkware.starknet.business_logic.execution.execute_entry_point import ExecuteEntryPoint from starkware.starknet.business_logic.execution.objects import ( CallInfo, - CallType, + ResourcesMapping, TransactionExecutionContext, ) -from starkware.starknet.business_logic.state.state import CarriedState -from starkware.starknet.business_logic.utils import get_invoke_tx_total_resources +from starkware.starknet.business_logic.fact_state.state import ExecutionResourcesManager +from starkware.starknet.business_logic.state.state_api import SyncState +from starkware.starknet.business_logic.utils import extract_l1_gas_and_cairo_usage from starkware.starknet.definitions.error_codes import StarknetErrorCode from starkware.starknet.definitions.general_config import StarknetGeneralConfig from starkware.starknet.public import abi as starknet_abi @@ -16,9 +16,9 @@ from starkware.starkware_utils.error_handling import StarkException, stark_assert_le -async def execute_fee_transfer( +def execute_fee_transfer( general_config: StarknetGeneralConfig, - state: CarriedState, + state: SyncState, tx_execution_context: TransactionExecutionContext, actual_fee: int, ) -> CallInfo: @@ -34,37 +34,36 @@ async def execute_fee_transfer( ) fee_token_address = general_config.fee_token_address - fee_transfer_call = ExecuteEntryPoint( - call_type=CallType.CALL, + fee_transfer_call = ExecuteEntryPoint.create( caller_address=tx_execution_context.account_contract_address, - class_hash=None, contract_address=fee_token_address, - code_address=None, entry_point_selector=starknet_abi.TRANSFER_ENTRY_POINT_SELECTOR, entry_point_type=EntryPointType.EXTERNAL, calldata=[general_config.sequencer_address, actual_fee, 0], # Recipient, amount (128-bit). ) try: - fee_transfer_info = await fee_transfer_call.execute( - state=state, general_config=general_config, tx_execution_context=tx_execution_context + fee_transfer_info = fee_transfer_call.execute( + state=state, + resources_manager=ExecutionResourcesManager.empty(), + general_config=general_config, + tx_execution_context=tx_execution_context, ) except StarkException as exception: - raise StarkException(code=StarknetErrorCode.FEE_TRANSFER_FAILURE, message=str(exception)) + raise StarkException( + code=StarknetErrorCode.FEE_TRANSFER_FAILURE, message=str(exception) + ) from exception return fee_transfer_info -def calculate_tx_fee_by_cairo_usage( +def calculate_l1_gas_by_cairo_usage( general_config: StarknetGeneralConfig, - cairo_resource_usage: Mapping[str, int], - l1_gas_usage: int, - gas_price: int, -) -> int: + cairo_resource_usage: ResourcesMapping, +) -> float: """ - Calculates the transaction fee by considering the heaviest Cairo resource (in terms of L1 gas), - as the size of a proof is determined similarly - by the (normalized) largest segment. - We add to that the given l1_gas_usage (which may include, for example, the direct cost of - L2-to-L1 messages) and multiply by the L1 gas price. + Calculates the L1 gas consumed when submitting the underlying Cairo program to SHARP. + I.e., returns the heaviest Cairo resource weight (in terms of L1 gas), as the size of + a proof is determined similarly - by the (normalized) largest segment. """ cairo_resource_fee_weights = general_config.cairo_resource_fee_weights cairo_resource_names = set(cairo_resource_usage.keys()) @@ -78,26 +77,21 @@ def calculate_tx_fee_by_cairo_usage( for key in cairo_resource_fee_weights ) - total_l1_gas_usage = cairo_l1_gas_usage + l1_gas_usage - return math.ceil(total_l1_gas_usage) * gas_price + return cairo_l1_gas_usage def calculate_tx_fee( - state: CarriedState, - call_info: CallInfo, - general_config: StarknetGeneralConfig, + resources: ResourcesMapping, gas_price: int, general_config: StarknetGeneralConfig ) -> int: """ - Calculates the fee of the most recent - InvokeFunction transaction (recent w.r.t. application on the given state). - Assumes entry point of type EXTERNAL, since only those may be charged. + Calculates the fee of a transaction given its execution resources. + We add the l1_gas_usage (which may include, for example, the direct cost of L2-to-L1 + messages) to the gas consumed by Cairo resource and multiply by the L1 gas price. """ - l1_gas_usage, cairo_resource_usage = get_invoke_tx_total_resources( - state=state, call_info=call_info - ) - return calculate_tx_fee_by_cairo_usage( + l1_gas_usage, cairo_resource_usage = extract_l1_gas_and_cairo_usage(resources=resources) + l1_gas_by_cairo_usage = calculate_l1_gas_by_cairo_usage( general_config=general_config, cairo_resource_usage=cairo_resource_usage, - l1_gas_usage=l1_gas_usage, - gas_price=state.block_info.gas_price, ) + total_l1_gas_usage = l1_gas_usage + l1_gas_by_cairo_usage + return math.ceil(total_l1_gas_usage) * gas_price diff --git a/src/starkware/starknet/business_logic/internal_transaction.py b/src/starkware/starknet/business_logic/transaction/objects.py similarity index 53% rename from src/starkware/starknet/business_logic/internal_transaction.py rename to src/starkware/starknet/business_logic/transaction/objects.py index ba206c3a..ea712ad0 100644 --- a/src/starkware/starknet/business_logic/internal_transaction.py +++ b/src/starkware/starknet/business_logic/transaction/objects.py @@ -10,33 +10,34 @@ from services.everest.api.gateway.transaction import EverestTransaction from services.everest.business_logic.internal_transaction import EverestInternalTransaction -from services.everest.business_logic.state import CarriedStateBase -from starkware.cairo.lang.vm.cairo_pie import ExecutionResources -from starkware.python.utils import to_bytes +from services.everest.business_logic.state_api import StateProxy +from starkware.python.utils import as_non_optional, from_bytes, to_bytes from starkware.starknet.business_logic.execution.execute_entry_point import ExecuteEntryPoint from starkware.starknet.business_logic.execution.objects import ( CallInfo, - CallType, + ResourcesMapping, TransactionExecutionContext, TransactionExecutionInfo, ) -from starkware.starknet.business_logic.internal_transaction_interface import ( - InternalStateTransaction, -) -from starkware.starknet.business_logic.state.state import BlockInfo, CarriedState, StateSelector -from starkware.starknet.business_logic.transaction_fee import calculate_tx_fee, execute_fee_transfer +from starkware.starknet.business_logic.fact_state.contract_state_objects import StateSelector +from starkware.starknet.business_logic.fact_state.state import ExecutionResourcesManager +from starkware.starknet.business_logic.state.state_api import SyncState +from starkware.starknet.business_logic.state.state_api_objects import BlockInfo +from starkware.starknet.business_logic.transaction.fee import calculate_tx_fee, execute_fee_transfer +from starkware.starknet.business_logic.transaction.state_objects import InternalStateTransaction from starkware.starknet.business_logic.utils import ( + calculate_tx_resources, preprocess_invoke_function_fields, - read_contract_class, - validate_version, + verify_no_calls_to_other_contracts, + verify_version, write_contract_class_fact, ) from starkware.starknet.core.os.class_hash import compute_class_hash from starkware.starknet.core.os.contract_address.contract_address import ( calculate_contract_address_from_hash, ) -from starkware.starknet.core.os.syscall_utils import initialize_contract_state from starkware.starknet.core.os.transaction_hash.transaction_hash import ( + TransactionHashPrefix, calculate_declare_transaction_hash, calculate_deploy_transaction_hash, calculate_transaction_hash_common, @@ -46,13 +47,9 @@ from starkware.starknet.definitions.general_config import StarknetGeneralConfig from starkware.starknet.definitions.transaction_type import TransactionType from starkware.starknet.public import abi as starknet_abi -from starkware.starknet.services.api.contract_class import ( - CONSTRUCTOR_SELECTOR, - ContractClass, - EntryPointType, -) +from starkware.starknet.services.api.contract_class import ContractClass, EntryPointType from starkware.starknet.services.api.gateway.transaction import ( - DECLARE_SENDER_ADDRESS, + DEFAULT_DECLARE_SENDER_ADDRESS, Declare, Deploy, InvokeFunction, @@ -60,24 +57,22 @@ ) from starkware.starkware_utils.config_base import Config from starkware.starkware_utils.error_handling import stark_assert, stark_assert_eq -from starkware.storage.storage import FactFetchingContext, Storage +from starkware.storage.storage import FactFetchingContext logger = logging.getLogger(__name__) # Mypy has a problem with dataclasses that contain unimplemented abstract methods. # See https://github.com/python/mypy/issues/5374 for details on this problem. +# Do not use __post_init__ on internal transactions. An inconsistency may happen during upgrade. +# A transaction may pass the Gateway, then an upgrade happens, then reach the Batcher. +# When a transaction reaches the Batcher - we do not want it to fail while being built. @marshmallow_dataclass.dataclass(frozen=True) # type: ignore[misc] class InternalTransaction(InternalStateTransaction, EverestInternalTransaction): """ StarkNet internal transaction base class. """ - # The version of the transaction. It is fixed (currently, 0) in the OS, and should be - # signed by the account contract. - # This field allows invalidating old transactions, whenever the meaning of the other - # transaction fields is changed (in the OS). - version: int = field(metadata=fields.tx_version_metadata) # A unique identifier of the transaction in the StarkNet network. hash_value: int = field(metadata=fields.transaction_hash_metadata) @@ -169,7 +164,7 @@ def verify_signatures(self): """ async def apply_state_updates( - self, state: CarriedStateBase, general_config: Config + self, state: StateProxy, general_config: Config ) -> TransactionExecutionInfo: # super().apply_state_updates calls InternalStateTransaction.apply_state_updates # that calls self._apply_specific_state_updates and therefore does not return None. @@ -179,12 +174,6 @@ async def apply_state_updates( assert isinstance(tx_execution_info, TransactionExecutionInfo) return tx_execution_info - @abstractmethod - async def _apply_specific_state_updates( - self, state: CarriedState, general_config: StarknetGeneralConfig - ) -> TransactionExecutionInfo: - pass - class SyntheticTransaction(InternalStateTransaction): """ @@ -214,18 +203,14 @@ class InitializeBlockInfo(SyntheticTransaction): block_info: BlockInfo tx_type: ClassVar[TransactionType] = TransactionType.INITIALIZE_BLOCK_INFO - async def _apply_specific_state_updates( - self, state: CarriedStateBase, general_config: Config + def _apply_specific_state_updates( + self, state: SyncState, general_config: StarknetGeneralConfig ) -> Optional[TransactionExecutionInfo]: - # Downcast arguments to application-specific types. - assert isinstance(general_config, StarknetGeneralConfig) - assert isinstance(state, CarriedState) - # Validate progress is legal. state.block_info.validate_legal_progress(next_block_info=self.block_info) # Update entire block-related information. - state.block_info = self.block_info + state.update_block_info(block_info=self.block_info) return None @@ -233,46 +218,199 @@ def get_state_selector(self, general_config: Config) -> StateSelector: return StateSelector.empty() +@dataclasses.dataclass(frozen=True) # type: ignore[misc] +class InternalAccountTransaction(InternalTransaction): + """ + Represents a transaction that originated from an action of an account. + """ + + # The version of the transaction. It is fixed in the OS, and should be + # signed by the account contract. + # This field allows invalidating old transactions, whenever the meaning of the other + # transaction fields is changed (in the OS). + version: int = field(metadata=fields.tx_version_metadata) + # The maximal fee to be paid in Wei for the execution. + max_fee: int = field(metadata=fields.fee_metadata) + signature: List[int] = field(metadata=fields.signature_metadata) + # The nonce of the transaction, a sequential number attached to the account contract. Guarantees + # a unique hash_value of transactions. + nonce: Optional[int] = field(metadata=fields.optional_nonce_metadata) + + @property + @abstractmethod + def account_contract_address(self) -> int: + """ + The address of the account contract initiating this transaction. + """ + + @property + @abstractmethod + def validate_entrypoint_calldata(self) -> List[int]: + """ + The calldata input to the transaction-specific validation function. + """ + + # Class variables. + + @property + @classmethod + @abstractmethod + def validate_entry_point_selector(cls) -> int: + """ + The entry point selector of the transaction-specific validation function. + """ + + def verify_version(self): + verify_version(version=self.version, only_query=False) + + def run_validate_entrypoint( + self, + state: SyncState, + resources_manager: ExecutionResourcesManager, + general_config: StarknetGeneralConfig, + ) -> Optional[CallInfo]: + """ + Runs the transaction-specific validation function. + """ + if self.version in [0, constants.QUERY_VERSION_BASE]: + return None + + call = ExecuteEntryPoint.create( + contract_address=self.account_contract_address, + entry_point_selector=self.validate_entry_point_selector, + entry_point_type=EntryPointType.EXTERNAL, + calldata=self.validate_entrypoint_calldata, + caller_address=0, + ) + + call_info = call.execute( + state=state, + resources_manager=resources_manager, + general_config=general_config, + tx_execution_context=self.get_execution_context( + n_steps=general_config.validate_max_n_steps + ), + ) + verify_no_calls_to_other_contracts(call_info=call_info) + + return call_info + + def get_execution_context(self, n_steps: int) -> TransactionExecutionContext: + return TransactionExecutionContext.create( + account_contract_address=self.account_contract_address, + transaction_hash=self.hash_value, + signature=self.signature, + max_fee=self.max_fee, + nonce=self.nonce, + n_steps=n_steps, + version=self.version, + ) + + def charge_fee( + self, state: SyncState, resources: ResourcesMapping, general_config: StarknetGeneralConfig + ) -> Tuple[Optional[CallInfo], int]: + """ + Calculates and charges the actual fee. + """ + if self.max_fee == 0: + # Fee charging is not enforced in some tests. + return None, 0 + + actual_fee = calculate_tx_fee( + gas_price=state.block_info.gas_price, general_config=general_config, resources=resources + ) + fee_transfer_info = execute_fee_transfer( + general_config=general_config, + state=state, + tx_execution_context=self.get_execution_context( + n_steps=general_config.invoke_tx_max_n_steps + ), + actual_fee=actual_fee, + ) + + return fee_transfer_info, actual_fee + + def _handle_nonce(self, state: SyncState): + """ + Verifies that the transaction's nonce matches the contract's nonce and increments the + latter (modifies state). + """ + # Don't handle nonce for version 0. + if self.version in [0, constants.QUERY_VERSION_BASE]: + return + + current_nonce = state.get_nonce_at(contract_address=self.account_contract_address) + stark_assert( + current_nonce == self.nonce, + code=StarknetErrorCode.INVALID_TRANSACTION_NONCE, + message=f"Invalid transaction nonce. Expected: {current_nonce}, got: {self.nonce}.", + ) + + # Increment nonce. + # Note that changing contract_state.nonce directly will bypass the proxy used to revert + # transactions. + state.increment_nonce(contract_address=self.account_contract_address) + + @marshmallow_dataclass.dataclass(frozen=True) -class InternalDeclare(InternalTransaction): +class InternalDeclare(InternalAccountTransaction): """ Represents an internal transaction in the StarkNet network that is a declaration of a Cairo contract class. """ + # The hash of the declared class. class_hash: bytes = field(metadata=fields.class_hash_metadata) sender_address: int = field(metadata=fields.contract_address_metadata) - max_fee: int = field(metadata=fields.fee_metadata) - signature: List[int] = field(metadata=fields.signature_metadata) - nonce: int = field(metadata=fields.nonce_metadata) # Class variables. tx_type: ClassVar[TransactionType] = TransactionType.DECLARE related_external_cls: ClassVar[Type[Transaction]] = Declare + validate_entry_point_selector: ClassVar[ + int + ] = starknet_abi.VALIDATE_DECLARE_ENTRY_POINT_SELECTOR + + @property + def account_contract_address(self) -> int: + return self.sender_address - def __post_init__(self): - super().__post_init__() + @property + def validate_entrypoint_calldata(self) -> List[int]: + # '__validate_declare__' is expected to get one parameter: 'class_hash'. + return [from_bytes(self.class_hash)] + + def verify_version(self): + super().verify_version() + + if self.version not in [0, constants.QUERY_VERSION_BASE]: + return stark_assert_eq( - DECLARE_SENDER_ADDRESS, + DEFAULT_DECLARE_SENDER_ADDRESS, self.sender_address, code=StarknetErrorCode.OUT_OF_RANGE_CONTRACT_ADDRESS, message=( - "The sender_address field in Declare transactions must be" - f"{DECLARE_SENDER_ADDRESS}." + "The sender_address field in Declare transactions of version 0 " + f"must be {DEFAULT_DECLARE_SENDER_ADDRESS}." ), ) stark_assert_eq( 0, self.max_fee, code=StarknetErrorCode.OUT_OF_RANGE_FEE, - message="The max_fee field in Declare transactions must be 0.", + message="The max_fee field in Declare transactions of version 0 must be 0.", ) stark_assert_eq( 0, self.nonce, code=StarknetErrorCode.OUT_OF_RANGE_NONCE, - message="The nonce field in Declare transactions must be 0.", + message="The nonce field in Declare transactions of version 0 must be 0.", + ) + stark_assert_eq( + 0, + len(self.signature), + code=StarknetErrorCode.NON_EMPTY_SIGNATURE, + message="The signature field in Declare transactions must be an empty list.", ) @classmethod @@ -286,10 +424,8 @@ def create( signature: List[int], nonce: int, ): - validate_version(version=version, only_query=False) - class_hash = compute_class_hash(contract_class=contract_class) - return cls( + internal_declare = cls( class_hash=to_bytes(class_hash), sender_address=sender_address, max_fee=max_fee, @@ -302,8 +438,11 @@ def create( sender_address=sender_address, max_fee=max_fee, version=version, + nonce=nonce, ), ) + internal_declare.verify_version() + return internal_declare @classmethod async def create_for_testing( @@ -311,19 +450,28 @@ async def create_for_testing( ffc: FactFetchingContext, contract_class: ContractClass, chain_id: Optional[int] = None, + max_fee: int = 0, + sender_address: Optional[int] = None, + signature: Optional[List[int]] = None, ) -> "InternalDeclare": """ Creates an InternalDeclare transaction and writes its contract class to the DB. This constructor should only be used in tests. """ await write_contract_class_fact(contract_class=contract_class, ffc=ffc) + if sender_address is None: + version = 0 + sender_address = DEFAULT_DECLARE_SENDER_ADDRESS + else: + version = constants.TRANSACTION_VERSION + return InternalDeclare.create( contract_class=contract_class, chain_id=0 if chain_id is None else chain_id, - sender_address=DECLARE_SENDER_ADDRESS, - max_fee=0, - version=constants.TRANSACTION_VERSION, - signature=[], + sender_address=sender_address, + max_fee=max_fee, + version=version, + signature=[] if signature is None else signature, nonce=0, ) @@ -346,20 +494,44 @@ def to_external(self) -> Declare: raise NotImplementedError("Cannot convert internal declare transaction to external object.") def get_state_selector(self, general_config: Config) -> StateSelector: - return StateSelector.empty() + if self.version in [0, constants.QUERY_VERSION_BASE]: + return StateSelector.empty() + + return StateSelector.create( + contract_addresses=[self.sender_address], + class_hashes=[self.class_hash], + ) - async def _apply_specific_state_updates( - self, state: CarriedState, general_config: StarknetGeneralConfig + def _apply_specific_state_updates( + self, state: SyncState, general_config: StarknetGeneralConfig ) -> TransactionExecutionInfo: - # Declare transaction does not change the state. + # Reject unsupported versions. This is necessary (in addition to the gateway's check) + # since an old transaction might still reach here, e.g., in case of a re-org. + self.verify_version() + + # Validate transaction. + self._handle_nonce(state=state) + resources_manager = ExecutionResourcesManager.empty() + validate_info = self.run_validate_entrypoint( + state=state, + resources_manager=resources_manager, + general_config=general_config, + ) + + # Handle fee. + actual_resources = calculate_tx_resources( + resources_manager=resources_manager, call_infos=[validate_info], tx_type=self.tx_type + ) + fee_transfer_info, actual_fee = self.charge_fee( + state=state, general_config=general_config, resources=actual_resources + ) + return TransactionExecutionInfo( - call_info=CallInfo.empty( - contract_address=self.sender_address, - caller_address=0, - class_hash=self.class_hash, - ), - fee_transfer_info=None, - actual_fee=0, + validate_info=validate_info, + call_info=None, + fee_transfer_info=fee_transfer_info, + actual_fee=actual_fee, + actual_resources=actual_resources, ) @@ -370,6 +542,11 @@ class InternalDeploy(InternalTransaction): contract. """ + # The version of the transaction. It is fixed (currently, 1) in the OS, and should be + # signed by the account contract. + # This field allows invalidating old transactions, whenever the meaning of the other + # transaction fields is changed (in the OS). + version: int = field(metadata=fields.tx_version_metadata) contract_address: int = field(metadata=fields.contract_address_metadata) contract_address_salt: int = field(metadata=fields.contract_address_salt_metadata) contract_hash: bytes = field(metadata=fields.non_required_class_hash_metadata) @@ -379,7 +556,6 @@ class InternalDeploy(InternalTransaction): # Class variables. tx_type: ClassVar[TransactionType] = TransactionType.DEPLOY related_external_cls: ClassVar[Type[Transaction]] = Deploy - n_cairo_steps_estimation: ClassVar[int] = 100 @marshmallow.decorators.pre_load def replace_contract_definition_with_contract_hash( @@ -399,14 +575,14 @@ def replace_contract_definition_with_contract_hash( def create( cls, contract_address_salt: int, - contract_definition: ContractClass, + contract_class: ContractClass, constructor_calldata: List[int], chain_id: int, version: int, ): - validate_version(version=version, only_query=False) + verify_version(version=version, only_query=False) - class_hash = compute_class_hash(contract_class=contract_definition) + class_hash = compute_class_hash(contract_class=contract_class) contract_address = calculate_contract_address_from_hash( salt=contract_address_salt, class_hash=class_hash, @@ -443,15 +619,12 @@ async def create_for_testing( await write_contract_class_fact(contract_class=contract_class, ffc=ffc) return InternalDeploy.create( contract_address_salt=contract_address_salt, - contract_definition=contract_class, + contract_class=contract_class, constructor_calldata=constructor_calldata, chain_id=0 if chain_id is None else chain_id, version=constants.TRANSACTION_VERSION, ) - async def get_contract_class(self, storage: Storage) -> ContractClass: - return await read_contract_class(class_hash=self.contract_hash, storage=storage) - @classmethod def _specific_from_external( cls, external_tx: Transaction, general_config: StarknetGeneralConfig @@ -459,7 +632,7 @@ def _specific_from_external( assert isinstance(external_tx, Deploy) return cls.create( contract_address_salt=external_tx.contract_address_salt, - contract_definition=external_tx.contract_definition, + contract_class=external_tx.contract_definition, constructor_calldata=external_tx.constructor_calldata, chain_id=general_config.chain_id.value, version=external_tx.version, @@ -473,78 +646,94 @@ def get_state_selector(self, general_config: Config) -> StateSelector: Returns the state selector of the transaction (i.e., subset of state commitment tree leaves it affects). """ - return StateSelector(contract_addresses={self.contract_address}, class_hashes=set()) + return StateSelector.create(contract_addresses=[self.contract_address], class_hashes=[]) - async def _apply_specific_state_updates( - self, state: CarriedState, general_config: StarknetGeneralConfig + def _apply_specific_state_updates( + self, state: SyncState, general_config: StarknetGeneralConfig ) -> TransactionExecutionInfo: """ Adds the deployed contract to the global commitment tree state. """ - allowed_versions = [constants.TRANSACTION_VERSION] - assert self.version in allowed_versions, f"Invalid transaction version: {self.version}." + # Reject unsupported versions. This is necessary (in addition to the gateway's check) + # since an old transaction might still reach here, e.g., in case of a re-org. + verify_version(version=self.version, only_query=False) + + # Execute transaction. + state.deploy_contract(contract_address=self.contract_address, class_hash=self.contract_hash) + contract_class = state.get_contract_class(class_hash=self.contract_hash) + n_ctors = len(contract_class.entry_points_by_type[EntryPointType.CONSTRUCTOR]) + if n_ctors == 0: + return self.handle_empty_constructor() + else: + return self.invoke_constructor(state=state, general_config=general_config) + + def handle_empty_constructor(self) -> TransactionExecutionInfo: + stark_assert( + len(self.constructor_calldata) == 0, + code=StarknetErrorCode.TRANSACTION_FAILED, + message="Cannot pass calldata to a contract with no constructor.", + ) - await initialize_contract_state( - state=state, - class_hash=self.contract_hash, + call_info = CallInfo.empty_constructor_call( contract_address=self.contract_address, + caller_address=0, + class_hash=self.contract_hash, ) - - # Update Cairo usage. - cairo_usage = dataclasses.replace( - ExecutionResources.empty(), n_steps=self.n_cairo_steps_estimation + resources_manager = ExecutionResourcesManager.empty() + actual_resources = calculate_tx_resources( + resources_manager=resources_manager, call_infos=[call_info], tx_type=self.tx_type ) - state.cairo_usage += cairo_usage - return await self.invoke_constructor(state=state, general_config=general_config) + return TransactionExecutionInfo( + validate_info=None, + call_info=call_info, + fee_transfer_info=None, + actual_fee=0, + actual_resources=actual_resources, + ) - async def invoke_constructor( - self, state: CarriedState, general_config: StarknetGeneralConfig + def invoke_constructor( + self, state: SyncState, general_config: StarknetGeneralConfig ) -> TransactionExecutionInfo: - contract_class = await self.get_contract_class(storage=state.ffc.storage) - if len(contract_class.entry_points_by_type[EntryPointType.CONSTRUCTOR]) == 0: - stark_assert( - len(self.constructor_calldata) == 0, - code=StarknetErrorCode.TRANSACTION_FAILED, - message="Cannot pass calldata to a contract with no constructor.", - ) - return TransactionExecutionInfo( - call_info=CallInfo.empty_constructor_call( - contract_address=self.contract_address, - caller_address=0, - class_hash=self.contract_hash, - ), - fee_transfer_info=None, - actual_fee=0, - ) - - call = ExecuteEntryPoint( - call_type=CallType.CALL, - class_hash=None, + call = ExecuteEntryPoint.create( contract_address=self.contract_address, - code_address=None, - entry_point_selector=CONSTRUCTOR_SELECTOR, + entry_point_selector=starknet_abi.CONSTRUCTOR_ENTRY_POINT_SELECTOR, entry_point_type=EntryPointType.CONSTRUCTOR, calldata=self.constructor_calldata, caller_address=0, ) - tx_execution_context = TransactionExecutionContext.create( account_contract_address=0, transaction_hash=self.hash_value, signature=[], max_fee=0, + nonce=0, n_steps=general_config.invoke_tx_max_n_steps, version=self.version, ) - call_info = await call.execute( - state=state, general_config=general_config, tx_execution_context=tx_execution_context + + resources_manager = ExecutionResourcesManager.empty() + call_info = call.execute( + state=state, + resources_manager=resources_manager, + general_config=general_config, + tx_execution_context=tx_execution_context, + ) + actual_resources = calculate_tx_resources( + resources_manager=resources_manager, call_infos=[call_info], tx_type=self.tx_type + ) + + return TransactionExecutionInfo( + validate_info=None, + call_info=call_info, + fee_transfer_info=None, + actual_fee=0, + actual_resources=actual_resources, ) - return TransactionExecutionInfo(call_info=call_info, fee_transfer_info=None, actual_fee=0) @marshmallow_dataclass.dataclass(frozen=True) -class InternalInvokeFunction(InternalTransaction): +class InternalInvokeFunction(InternalAccountTransaction): """ Represents an internal transaction in the StarkNet network that is an invocation of a Cairo contract function. @@ -556,17 +745,34 @@ class InternalInvokeFunction(InternalTransaction): # multiple decorators and this member specifies which one. entry_point_type: EntryPointType calldata: List[int] = field(metadata=fields.call_data_metadata) - max_fee: int = field(metadata=fields.fee_metadata) - signature: List[int] = field(metadata=fields.signature_metadata) - # A unique nonce, added by the StarkNet core contract on L1. - # This nonce is used to make the hash_value of transactions that service L1 messages unique. - # This field may be set only when entry_point_type is EntryPointType.L1_HANDLER. - nonce: Optional[int] = field(metadata=fields.optional_nonce_metadata) - caller_address: int = field(metadata=fields.caller_address_metadata) # Class variables. tx_type: ClassVar[TransactionType] = TransactionType.INVOKE_FUNCTION related_external_cls: ClassVar[Type[Transaction]] = InvokeFunction + validate_entry_point_selector: ClassVar[int] = starknet_abi.VALIDATE_ENTRY_POINT_SELECTOR + + @property + def account_contract_address(self) -> int: + return self.contract_address + + @property + def validate_entrypoint_calldata(self) -> List[int]: + # '__validate__' is expected to get the same calldata as '__execute__'. + return self.calldata + + def verify_version(self): + super().verify_version() + + if self.version not in [0, constants.QUERY_VERSION_BASE]: + stark_assert_eq( + self.entry_point_selector, + starknet_abi.EXECUTE_ENTRY_POINT_SELECTOR, + code=StarknetErrorCode.UNAUTHORIZED_ENTRY_POINT_FOR_INVOKE, + message=( + "The entry_point_selector field in InvokeFunction transactions " + f"must be {starknet_abi.EXECUTE_ENTRY_POINT_NAME}." + ), + ) @marshmallow.decorators.pre_load def remove_deprecated_fields( @@ -576,6 +782,12 @@ def remove_deprecated_fields( assert data["code_address"] == data["contract_address"] del data["code_address"] + if "caller_address" in data: + assert data["caller_address"] == fields.AddressField.format( + 0 + ), "The `caller_address` of an external transaction must be 0." + del data["caller_address"] + return data @classmethod @@ -583,28 +795,49 @@ def create_for_testing( cls, contract_address: int, calldata: List[int], - entry_point_selector: int, - max_fee: Optional[int] = None, - entry_point_type: Optional[EntryPointType] = None, + nonce: int, signature: Optional[List[int]] = None, - caller_address: Optional[int] = None, - nonce: Optional[int] = None, + max_fee: Optional[int] = None, chain_id: Optional[int] = None, ): return cls.create( contract_address=contract_address, - entry_point_selector=entry_point_selector, + entry_point_selector=starknet_abi.EXECUTE_ENTRY_POINT_SELECTOR, max_fee=0 if max_fee is None else max_fee, version=constants.TRANSACTION_VERSION, - entry_point_type=( - EntryPointType.EXTERNAL if entry_point_type is None else entry_point_type - ), calldata=calldata, + nonce=nonce, signature=[] if signature is None else signature, - caller_address=0 if caller_address is None else caller_address, + chain_id=0 if chain_id is None else chain_id, + ) + + @classmethod + def create_wrapped_with_account( + cls, + account_address: int, + contract_address: int, + calldata: List[int], + entry_point_selector: int, + nonce: Optional[int], + signature: Optional[List[int]] = None, + max_fee: Optional[int] = None, + chain_id: Optional[int] = None, + version: Optional[int] = None, + ): + """ + Creates an account contract invocation to the 'dummy_account' + test contract at address 'account_address'. + """ + + return cls.create( + contract_address=account_address, + entry_point_selector=starknet_abi.EXECUTE_ENTRY_POINT_SELECTOR, + max_fee=0 if max_fee is None else max_fee, + version=constants.TRANSACTION_VERSION if version is None else version, + calldata=[contract_address, entry_point_selector, len(calldata), *calldata], nonce=nonce, + signature=[] if signature is None else signature, chain_id=0 if chain_id is None else chain_id, - only_query=False, ) @classmethod @@ -612,36 +845,34 @@ def _specific_from_external( cls, external_tx: Transaction, general_config: StarknetGeneralConfig ) -> "InternalInvokeFunction": assert isinstance(external_tx, InvokeFunction) + return cls.create( contract_address=external_tx.contract_address, - entry_point_selector=external_tx.entry_point_selector, + entry_point_selector=cls._get_selector_from_external_tx(tx=external_tx), max_fee=external_tx.max_fee, - entry_point_type=EntryPointType.EXTERNAL, calldata=external_tx.calldata, + nonce=external_tx.nonce, signature=external_tx.signature, - nonce=None, chain_id=general_config.chain_id.value, version=external_tx.version, ) @classmethod - def from_external_query_tx( - cls, - tx: InvokeFunction, - general_config: StarknetGeneralConfig, - ) -> "InternalInvokeFunction": - return cls.create( - contract_address=tx.contract_address, - entry_point_selector=tx.entry_point_selector, - max_fee=tx.max_fee, - entry_point_type=EntryPointType.EXTERNAL, - calldata=tx.calldata, - signature=tx.signature, - nonce=None, - chain_id=general_config.chain_id.value, - version=tx.version, - only_query=True, + def _get_selector_from_external_tx(cls, tx: InvokeFunction) -> int: + if tx.version in [0, constants.QUERY_VERSION_BASE]: + stark_assert( + tx.entry_point_selector is not None, + code=StarknetErrorCode.MISSING_ENTRY_POINT_FOR_INVOKE, + message="Entry point selector must be specified for version 0.", + ) + return as_non_optional(tx.entry_point_selector) + + stark_assert( + tx.entry_point_selector is None, + code=StarknetErrorCode.UNAUTHORIZED_ENTRY_POINT_FOR_INVOKE, + message="Entry point selector must not be specified for version 1 one and above.", ) + return starknet_abi.EXECUTE_ENTRY_POINT_SELECTOR @classmethod def create( @@ -649,51 +880,43 @@ def create( contract_address: int, entry_point_selector: int, max_fee: int, - entry_point_type: EntryPointType, calldata: List[int], signature: List[int], nonce: Optional[int], chain_id: int, version: int, - # The caller_address of an external transaction or L1 handler is always 0. - # The caller_address is passed as paramater to allow the testing framework to initiate - # transactions with a user specified caller_address. - caller_address: int = 0, - # Used to distinguish between query and other transactions. - only_query: bool = False, ) -> "InternalInvokeFunction": - tx_hash_prefix, additional_data = preprocess_invoke_function_fields( - entry_point_type=entry_point_type, + (entry_point_selector_field, additional_data) = preprocess_invoke_function_fields( entry_point_selector=entry_point_selector, - message_from_l1_nonce=nonce, + nonce=nonce, max_fee=max_fee, version=version, - only_query=only_query, ) hash_value = calculate_transaction_hash_common( - tx_hash_prefix=tx_hash_prefix, + tx_hash_prefix=TransactionHashPrefix.INVOKE, version=version, contract_address=contract_address, - entry_point_selector=entry_point_selector, + entry_point_selector=entry_point_selector_field, calldata=calldata, max_fee=max_fee, chain_id=chain_id, additional_data=additional_data, ) - return cls( + internal_invoke = cls( contract_address=contract_address, entry_point_selector=entry_point_selector, max_fee=max_fee, version=version, - entry_point_type=entry_point_type, + entry_point_type=EntryPointType.EXTERNAL, calldata=calldata, + nonce=nonce, signature=signature, hash_value=hash_value, - caller_address=caller_address, - nonce=nonce, ) + internal_invoke.verify_version() + return internal_invoke def to_external(self) -> InvokeFunction: assert self.entry_point_type is EntryPointType.EXTERNAL, ( @@ -703,10 +926,13 @@ def to_external(self) -> InvokeFunction: return InvokeFunction( contract_address=self.contract_address, - entry_point_selector=self.entry_point_selector, + entry_point_selector=self.entry_point_selector + if self.version in [0, constants.QUERY_VERSION_BASE] + else None, calldata=self.calldata, max_fee=self.max_fee, version=self.version, + nonce=self.nonce, signature=self.signature, ) @@ -721,99 +947,235 @@ def get_state_selector(self, general_config: Config) -> StateSelector: assert isinstance(general_config, StarknetGeneralConfig) contract_addresses.add(general_config.fee_token_address) - return StateSelector(contract_addresses=contract_addresses, class_hashes=set()) + return StateSelector.create(contract_addresses=contract_addresses, class_hashes=[]) - async def _apply_specific_state_updates( - self, state: CarriedState, general_config: StarknetGeneralConfig + def _apply_specific_state_updates( + self, state: SyncState, general_config: StarknetGeneralConfig ) -> TransactionExecutionInfo: """ Applies self to 'state' by executing the entry point and charging fee for it (if needed). """ - call_info = await self.execute(state=state, general_config=general_config) - fee_transfer_info, actual_fee = await self.charge_fee( - state=state, general_config=general_config, call_info=call_info + # Reject unsupported versions. This is necessary (in addition to the gateway's check) + # since an old transaction might still reach here, e.g., in case of a re-org. + self.verify_version() + + # Validate transaction. + self._handle_nonce(state=state) + resources_manager = ExecutionResourcesManager.empty() + validate_info = self.run_validate_entrypoint( + state=state, + resources_manager=resources_manager, + general_config=general_config, + ) + + # Execute transaction. + call_info = self.run_execute_entrypoint( + state=state, + resources_manager=resources_manager, + general_config=general_config, + ) + + # Handle fee. + actual_resources = calculate_tx_resources( + resources_manager=resources_manager, + call_infos=[call_info, validate_info], + tx_type=self.tx_type, + ) + fee_transfer_info, actual_fee = self.charge_fee( + state=state, + general_config=general_config, + resources=actual_resources, ) return TransactionExecutionInfo( - call_info=call_info, fee_transfer_info=fee_transfer_info, actual_fee=actual_fee + validate_info=validate_info, + call_info=call_info, + fee_transfer_info=fee_transfer_info, + actual_fee=actual_fee, + actual_resources=actual_resources, ) - async def execute( - self, state: CarriedState, general_config: StarknetGeneralConfig, only_query: bool = False + def run_validate_entrypoint( + self, + state: SyncState, + resources_manager: ExecutionResourcesManager, + general_config: StarknetGeneralConfig, + ) -> Optional[CallInfo]: + """ + Runs the '__validate__' entry point. + """ + if self.entry_point_selector != starknet_abi.EXECUTE_ENTRY_POINT_SELECTOR: + return None + + return super().run_validate_entrypoint( + state=state, resources_manager=resources_manager, general_config=general_config + ) + + def run_execute_entrypoint( + self, + state: SyncState, + resources_manager: ExecutionResourcesManager, + general_config: StarknetGeneralConfig, ) -> CallInfo: """ Builds the transaction execution context and executes the entry point. Returns the CallInfo. """ - # Sanity check for query mode. - validate_version(version=self.version, only_query=only_query) - - call = ExecuteEntryPoint( - call_type=CallType.CALL, - class_hash=None, + call = ExecuteEntryPoint.create( contract_address=self.contract_address, - code_address=None, entry_point_selector=self.entry_point_selector, - entry_point_type=self.entry_point_type, + entry_point_type=EntryPointType.EXTERNAL, calldata=self.calldata, - caller_address=self.caller_address, + caller_address=0, ) - return await call.execute( + return call.execute( state=state, + resources_manager=resources_manager, general_config=general_config, tx_execution_context=self.get_execution_context( n_steps=general_config.invoke_tx_max_n_steps ), ) - async def charge_fee( - self, state: CarriedState, general_config: StarknetGeneralConfig, call_info: CallInfo - ) -> Tuple[Optional[CallInfo], int]: + +@marshmallow_dataclass.dataclass(frozen=True) +class InternalL1Handler(InternalTransaction): + """ + Represents an internal transaction in the StarkNet network that is an invocation of a Cairo + contract L1 handler. + """ + + contract_address: int = field(metadata=fields.contract_address_metadata) + entry_point_selector: int = field(metadata=fields.entry_point_selector_metadata) + calldata: List[int] = field(metadata=fields.call_data_metadata) + # A unique nonce, added by the StarkNet core contract on L1. Guarantees a unique + # hash_value of transactions. + nonce: int = field(metadata=fields.nonce_metadata) + + # Class variables. + tx_type: ClassVar[TransactionType] = TransactionType.L1_HANDLER + + @property + @classmethod + def related_external_cls(cls) -> Type[Transaction]: + raise NotImplementedError("InternalL1Handler does not have a corresponding external class.") + + @classmethod + def _specific_from_external( + cls, external_tx: Transaction, general_config: StarknetGeneralConfig + ) -> "InternalTransaction": + raise NotImplementedError("InternalL1Handler does not have a corresponding external class.") + + def to_external(self) -> Transaction: + raise NotImplementedError("InternalL1Handler does not have a corresponding external class.") + + @classmethod + def create_for_testing( + cls, + contract_address: int, + calldata: List[int], + entry_point_selector: int, + nonce: int, + chain_id: Optional[int] = None, + ): + return cls.create( + contract_address=contract_address, + entry_point_selector=entry_point_selector, + calldata=calldata, + nonce=nonce, + chain_id=0 if chain_id is None else chain_id, + ) + + @classmethod + def create( + cls, + contract_address: int, + entry_point_selector: int, + calldata: List[int], + nonce: int, + chain_id: int, + ) -> "InternalL1Handler": + hash_value = calculate_transaction_hash_common( + tx_hash_prefix=TransactionHashPrefix.L1_HANDLER, + version=constants.L1_HANDLER_VERSION, + contract_address=contract_address, + entry_point_selector=entry_point_selector, + calldata=calldata, + max_fee=0, + chain_id=chain_id, + additional_data=[nonce], + ) + + return cls( + contract_address=contract_address, + entry_point_selector=entry_point_selector, + calldata=calldata, + nonce=nonce, + hash_value=hash_value, + ) + + def get_state_selector(self, general_config: Config) -> StateSelector: """ - Calculates and charges the actual fee. + Returns the state selector of the transaction (i.e., subset of state commitment tree leaves + it affects). """ - if self.max_fee == 0: - # Fee charging is not enforced in some tests. - return None, 0 + return StateSelector.create(contract_addresses=[self.contract_address], class_hashes=[]) - # Should always pass on regular flows (verified in the create() method). - assert self.entry_point_selector == starknet_abi.EXECUTE_ENTRY_POINT_SELECTOR - assert self.entry_point_type is EntryPointType.EXTERNAL + def _apply_specific_state_updates( + self, state: SyncState, general_config: StarknetGeneralConfig + ) -> TransactionExecutionInfo: + """ + Applies self to 'state' by executing the L1-handler entry point. + """ + call = ExecuteEntryPoint.create( + contract_address=self.contract_address, + entry_point_selector=self.entry_point_selector, + entry_point_type=EntryPointType.L1_HANDLER, + calldata=self.calldata, + caller_address=0, + ) - actual_fee = calculate_tx_fee( + # Execute transaction. + resources_manager = ExecutionResourcesManager.empty() + call_info = call.execute( state=state, - call_info=call_info, - general_config=general_config, - ) - fee_transfer_info = await execute_fee_transfer( + resources_manager=resources_manager, general_config=general_config, - state=state, tx_execution_context=self.get_execution_context( n_steps=general_config.invoke_tx_max_n_steps ), - actual_fee=actual_fee, + ) + actual_resources = calculate_tx_resources( + resources_manager=resources_manager, + call_infos=[call_info], + tx_type=self.tx_type, + l1_handler_payload_size=self.get_payload_size(), ) - return fee_transfer_info, actual_fee + return TransactionExecutionInfo( + validate_info=None, + call_info=call_info, + fee_transfer_info=None, + actual_fee=0, + actual_resources=actual_resources, + ) def get_execution_context(self, n_steps: int) -> TransactionExecutionContext: return TransactionExecutionContext.create( account_contract_address=self.contract_address, transaction_hash=self.hash_value, - signature=self.signature, - max_fee=self.max_fee, + signature=[], + max_fee=0, + nonce=self.nonce, n_steps=n_steps, - version=self.version, + version=constants.L1_HANDLER_VERSION, ) - def get_l1_handler_payload_size(self) -> Optional[int]: + def get_payload_size(self) -> int: """ - Returns the payload size of the corresponding L1-to-L2 message if the transaction is an L1 - handler. Otherwise returns None. + Returns the payload size of the corresponding L1-to-L2 message. """ - if self.entry_point_type is not EntryPointType.L1_HANDLER: - return None # The calldata includes the "from" field, which is not a part of the payload. # We thus subtract 1. return len(self.calldata) - 1 @@ -834,9 +1196,10 @@ class InternalTransactionSchema(OneOfSchema): TransactionType.DECLARE.name: InternalDeclare.Schema, TransactionType.DEPLOY.name: InternalDeploy.Schema, TransactionType.INVOKE_FUNCTION.name: InternalInvokeFunction.Schema, + TransactionType.L1_HANDLER.name: InternalL1Handler.Schema, } - def get_obj_type(self, obj: Transaction) -> str: + def get_obj_type(self, obj: InternalTransaction) -> str: return obj.tx_type.name diff --git a/src/starkware/starknet/business_logic/transaction/state_objects.py b/src/starkware/starknet/business_logic/transaction/state_objects.py new file mode 100644 index 00000000..d294a9a9 --- /dev/null +++ b/src/starkware/starknet/business_logic/transaction/state_objects.py @@ -0,0 +1,96 @@ +import asyncio +import functools +import logging +from abc import abstractmethod +from typing import Iterable, Optional, cast + +from services.everest.business_logic.internal_transaction import EverestInternalStateTransaction +from services.everest.business_logic.state_api import StateProxy +from starkware.starknet.business_logic.execution.objects import TransactionExecutionInfo +from starkware.starknet.business_logic.fact_state.contract_state_objects import StateSelector +from starkware.starknet.business_logic.state.state import StateSyncifier +from starkware.starknet.business_logic.state.state_api import State, SyncState +from starkware.starknet.definitions.error_codes import StarknetErrorCode +from starkware.starknet.definitions.general_config import StarknetGeneralConfig +from starkware.starkware_utils.config_base import Config +from starkware.starkware_utils.error_handling import StarkException + +logger = logging.getLogger(__name__) + + +class InternalStateTransaction(EverestInternalStateTransaction): + """ + StarkNet internal state transaction. + This is the API of transactions that update the state, + but do not necessarily have an external transaction counterpart. + See for example, SyntheticTransaction. + """ + + @staticmethod + def get_state_selector_of_many( + txs: Iterable["EverestInternalStateTransaction"], general_config: Config + ) -> StateSelector: + """ + Returns the state selector of a collection of transactions (i.e., union of selectors). + """ + # Downcast arguments to application-specific types. + assert isinstance(general_config, StarknetGeneralConfig) + + state_selector = EverestInternalStateTransaction._get_state_selector_of_many( + txs=txs, general_config=general_config, state_selector_cls=StateSelector + ) + return cast(StateSelector, state_selector) + + async def apply_state_updates( + self, state: StateProxy, general_config: Config + ) -> Optional[TransactionExecutionInfo]: + """ + Applies the transaction on the commitment tree state in an atomic manner. + """ + loop = asyncio.get_running_loop() + + # Downcast arguments to application-specific types. + assert isinstance(state, State) + + sync_state = StateSyncifier(async_state=state, loop=loop) + sync_apply_state_updates = functools.partial( + self.sync_apply_state_updates, + state=sync_state, + general_config=general_config, + ) + execution_info = await loop.run_in_executor(executor=None, func=sync_apply_state_updates) + + return execution_info + + def sync_apply_state_updates( + self, state: StateProxy, general_config: Config + ) -> Optional[TransactionExecutionInfo]: + """ + Applies the transaction on the commitment tree state in an atomic manner. + """ + # Downcast arguments to application-specific types. + assert isinstance(state, SyncState) + assert isinstance(general_config, StarknetGeneralConfig) + + try: + execution_info = self._apply_specific_state_updates( + state=state, general_config=general_config + ) + except StarkException: + # Raise StarkException-s as-is, so failure information is not lost. + raise + except Exception as exception: + # Wrap all exceptions with StarkException, so the Batcher can continue running + # even after unexpected errors. + logger.error(f"Unexpected failure; exception details: {exception}.", exc_info=True) + raise StarkException( + code=StarknetErrorCode.UNEXPECTED_FAILURE, message=str(exception) + ) from exception + + return execution_info + + @abstractmethod + def _apply_specific_state_updates( + self, state: SyncState, general_config: StarknetGeneralConfig + ) -> Optional[TransactionExecutionInfo]: + pass diff --git a/src/starkware/starknet/business_logic/utils.py b/src/starkware/starknet/business_logic/utils.py index 3ddcaa26..b4075495 100644 --- a/src/starkware/starknet/business_logic/utils.py +++ b/src/starkware/starknet/business_logic/utils.py @@ -1,24 +1,31 @@ +import contextlib import logging -from typing import List, Mapping, Optional, Tuple, cast +from typing import Dict, Iterable, List, Optional, Tuple, cast from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner +from starkware.cairo.lang.vm.cairo_pie import ExecutionResources +from starkware.python.utils import sub_counters from starkware.starknet.business_logic.execution.gas_usage import calculate_tx_gas_usage -from starkware.starknet.business_logic.execution.objects import CallInfo -from starkware.starknet.business_logic.execution.os_usage import ( - calculate_execute_txs_inner_resources, - calculate_syscall_resources, - get_tx_syscall_counter, +from starkware.starknet.business_logic.execution.objects import ( + CallInfo, + ResourcesMapping, + TransactionExecutionInfo, ) -from starkware.starknet.business_logic.state.objects import ContractClassFact -from starkware.starknet.business_logic.state.state import CarriedState -from starkware.starknet.core.os.transaction_hash.transaction_hash import TransactionHashPrefix -from starkware.starknet.definitions import constants +from starkware.starknet.business_logic.execution.os_usage import get_additional_os_resources +from starkware.starknet.business_logic.fact_state.contract_state_objects import ContractClassFact +from starkware.starknet.business_logic.fact_state.state import ExecutionResourcesManager +from starkware.starknet.business_logic.state.state_api import SyncState +from starkware.starknet.definitions import constants, fields from starkware.starknet.definitions.error_codes import StarknetErrorCode from starkware.starknet.definitions.transaction_type import TransactionType from starkware.starknet.public import abi as starknet_abi from starkware.starknet.services.api.contract_class import ContractClass, EntryPointType -from starkware.starkware_utils.error_handling import stark_assert, wrap_with_stark_exception -from starkware.storage.storage import FactFetchingContext, Storage +from starkware.starkware_utils.error_handling import ( + StarkException, + stark_assert, + wrap_with_stark_exception, +) +from starkware.storage.storage import FactFetchingContext logger = logging.getLogger(__name__) @@ -26,6 +33,8 @@ # Exclude the sequencer balance update, since it's charged once throughout the batch. FEE_TRANSFER_N_STORAGE_CHANGES_TO_CHARGE = FEE_TRANSFER_N_STORAGE_CHANGES - 1 +VALIDATE_BLACKLISTED_SYSCALLS: Tuple[str, ...] = ("call_contract",) + def get_return_values(runner: CairoFunctionRunner) -> List[int]: """ @@ -49,8 +58,16 @@ def get_return_values(runner: CairoFunctionRunner) -> List[int]: return cast(List[int], values) -def validate_version(version: int, only_query: bool): - allowed_versions = [constants.TRANSACTION_VERSION] +def verify_version(version: int, only_query: bool): + """ + Validates the given transaction version. + + The query flag is used to determine the transaction's type. + If True, the transaction is assumed to be used for query rather than + being invoked in the StarkNet OS. + """ + assert constants.TRANSACTION_VERSION == 1 + allowed_versions = [0, constants.TRANSACTION_VERSION] if only_query: error_code = StarknetErrorCode.INVALID_TRANSACTION_QUERYING_VERSION allowed_versions += [constants.QUERY_VERSION_BASE + v for v in allowed_versions] @@ -68,40 +85,38 @@ def validate_version(version: int, only_query: bool): def preprocess_invoke_function_fields( - entry_point_type: EntryPointType, entry_point_selector: int, - message_from_l1_nonce: Optional[int], + nonce: Optional[int], max_fee: int, version: int, - only_query: bool, -) -> Tuple[TransactionHashPrefix, List[int]]: +) -> Tuple[int, List[int]]: """ Performs validation on fields related to function invocation transaction. - Deduces and returns entry point type-related fields required for hash calculation of - InvokeFunction transaction. The query flag is used to determine the transaction's type. - If True, the transaction is assumed to be used for query rather than - being invoked in the StarkNet OS. + Deduces and returns fields required for hash calculation of + InvokeFunction transaction. """ - # Validate version. - validate_version(version=version, only_query=only_query) - # Validate entry point type-related fields. - if entry_point_type is EntryPointType.EXTERNAL: - assert message_from_l1_nonce is None, "An InvokeFunction transaction cannot have a nonce." - validate_selector_for_fee(selector=entry_point_selector, max_fee=max_fee) - - tx_hash_prefix = TransactionHashPrefix.INVOKE + additional_data: List[int] + validate_selector_for_fee(selector=entry_point_selector, max_fee=max_fee) + + if version in [0, constants.QUERY_VERSION_BASE]: + stark_assert( + nonce is None, + code=StarknetErrorCode.INVALID_TRANSACTION_NONCE, + message="An InvokeFunction transaction (version = 0) cannot have a nonce.", + ) additional_data = [] - elif entry_point_type is EntryPointType.L1_HANDLER: - assert message_from_l1_nonce is not None, "An L1 handler transaction must have a nonce." - assert max_fee == 0, "An L1 handler transaction must have max_fee=0." - - tx_hash_prefix = TransactionHashPrefix.L1_HANDLER - additional_data = [message_from_l1_nonce] + entry_point_selector_field = entry_point_selector else: - raise NotImplementedError(f"Entry point type {entry_point_type.name} is not supported.") + stark_assert( + nonce is not None, + code=StarknetErrorCode.INVALID_TRANSACTION_NONCE, + message="An InvokeFunction transaction (version != 0) must have a nonce.", + ) + additional_data = [cast(int, nonce)] + entry_point_selector_field = 0 - return tx_hash_prefix, additional_data + return entry_point_selector_field, additional_data def validate_selector_for_fee(selector: int, max_fee: int): @@ -110,7 +125,7 @@ def validate_selector_for_fee(selector: int, max_fee: int): stark_assert( selector == starknet_abi.EXECUTE_ENTRY_POINT_SELECTOR, - code=StarknetErrorCode.UNSUPPORTED_SELECTOR_FOR_FEE, + code=StarknetErrorCode.UNAUTHORIZED_ENTRY_POINT_FOR_INVOKE, message=( "All transactions should go through the " f"{starknet_abi.EXECUTE_ENTRY_POINT_NAME} entrypoint." @@ -118,49 +133,87 @@ def validate_selector_for_fee(selector: int, max_fee: int): ) -def get_invoke_tx_total_resources( - state: CarriedState, call_info: CallInfo -) -> Tuple[int, Mapping[str, int]]: +def total_cairo_usage_from_execution_infos( + execution_infos: Iterable[TransactionExecutionInfo], +) -> ExecutionResources: """ - Returns the total resources needed to include the most recent InvokeFunction transaction in - a StarkNet batch (recent w.r.t. application on the given state) - L1 gas usage and Cairo - execution resources. + Returns the sum of the Cairo usage (pure Cairo of the EP run, without OS cost) of calls in + the given execution Infos. Excludes the fee_transfer_info resources, + since it is part of the OS additional cost. + """ + cairo_usage = ExecutionResources.empty() + + for execution_info in execution_infos: + if execution_info.validate_info is not None: + cairo_usage += execution_info.validate_info.execution_resources + if execution_info.call_info is not None: + cairo_usage += execution_info.call_info.execution_resources + + return cairo_usage + + +def calculate_tx_resources( + resources_manager: ExecutionResourcesManager, + call_infos: Iterable[Optional[CallInfo]], + tx_type: TransactionType, + l1_handler_payload_size: Optional[int] = None, +) -> ResourcesMapping: + """ + Returns the total resources needed to include the most recent transaction in a StarkNet batch + (recent w.r.t. application on the given state) i.e., L1 gas usage and Cairo execution resources. Used for transaction fee; calculation is made as if the transaction is the first in batch, for consistency. """ - assert state.parent_state is not None, "State is expected to be a child of another state." - # Number of modified contracts by the most recently applied-on-state transaction. - n_modified_contracts_by_tx = len(state.modified_contracts.maps[0].keys()) + n_modified_contracts_by_tx = len(resources_manager.modified_contracts.keys()) + + non_optional_call_infos = [call for call in call_infos if call is not None] + tx_syscall_counter = resources_manager.syscall_counter + n_deployments = 0 + for call_info in non_optional_call_infos: + n_deployments += get_call_n_deployments(call_info=call_info) - tx_syscall_counter = get_tx_syscall_counter(state=state) - constructor_calldata_total_length, n_deployments = get_call_deployment_info(call_info=call_info) - assert n_deployments == tx_syscall_counter.get("deploy", 0) + l2_to_l1_messages = [] + for call_info in non_optional_call_infos: + l2_to_l1_messages += call_info.get_sorted_l2_to_l1_messages() l1_gas_usage = calculate_tx_gas_usage( - l2_to_l1_messages=call_info.get_sorted_l2_to_l1_messages(), + l2_to_l1_messages=l2_to_l1_messages, n_modified_contracts=n_modified_contracts_by_tx, n_storage_writes=tx_syscall_counter.get("storage_write", 0) + FEE_TRANSFER_N_STORAGE_CHANGES_TO_CHARGE, - # L1 handlers cannot be called. - l1_handler_payload_size=None, - constructor_calldata_total_length=constructor_calldata_total_length, + l1_handler_payload_size=l1_handler_payload_size, n_deployments=n_deployments, ) + cairo_usage = resources_manager.cairo_usage # Add additional Cairo resources needed for the OS to run the transaction. - execution_resources = call_info.execution_resources - execution_resources += calculate_syscall_resources(syscall_counter=tx_syscall_counter) - execution_resources += calculate_execute_txs_inner_resources( - tx_type=TransactionType.INVOKE_FUNCTION + cairo_usage += get_additional_os_resources(syscall_counter=tx_syscall_counter, tx_type=tx_type) + + return dict(l1_gas_usage=l1_gas_usage, **cairo_usage.filter_unused_builtins().to_dict()) + + +def extract_l1_gas_and_cairo_usage(resources: ResourcesMapping) -> Tuple[int, ResourcesMapping]: + cairo_resource_usage = dict(resources) + return cairo_resource_usage.pop("l1_gas_usage"), cairo_resource_usage + + +def get_deployed_class_hash_at_address(state: SyncState, contract_address: int) -> bytes: + class_hash = state.get_class_hash_at(contract_address=contract_address) + stark_assert( + class_hash != constants.UNINITIALIZED_CLASS_HASH, + code=StarknetErrorCode.UNINITIALIZED_CONTRACT, + message=( + "Requested contract address " + f"{fields.L2AddressField.format(contract_address)} is not deployed." + ), ) - return l1_gas_usage, execution_resources.to_dict() + return class_hash -async def read_contract_class(class_hash: bytes, storage: Storage) -> ContractClass: - contract_class_fact = await ContractClassFact.get_or_fail(storage=storage, suffix=class_hash) - return contract_class_fact.contract_definition +def validate_contract_deployed(state: SyncState, contract_address: int): + get_deployed_class_hash_at_address(state=state, contract_address=contract_address) async def write_contract_class_fact( @@ -170,15 +223,60 @@ async def write_contract_class_fact( return await contract_class_fact.set_fact(ffc=ffc) -def get_call_deployment_info(call_info: CallInfo) -> Tuple[int, int]: - # The sum of all constructor calldata lengths deployed in the transaction. - constructor_calldata_total_length = 0 +def get_call_n_deployments(call_info: CallInfo) -> int: # The number of the contracts deployed in the transaction. n_deployments = 0 for call_info in call_info.gen_call_topology(): if call_info.entry_point_type is EntryPointType.CONSTRUCTOR: - constructor_calldata_total_length += len(call_info.calldata) n_deployments += 1 - return constructor_calldata_total_length, n_deployments + return n_deployments + + +def get_validate_entrypoint_blacklisted_syscall_counter( + resources_manager: ExecutionResourcesManager, +) -> Dict[str, int]: + return { + syscall_name: resources_manager.syscall_counter.get(syscall_name, 0) + for syscall_name in VALIDATE_BLACKLISTED_SYSCALLS + } + + +@contextlib.contextmanager +def validate_entrypoint_execution_context(resources_manager: ExecutionResourcesManager): + """ + Context manager for assuring a proper validate. + """ + syscalls_before_execute = get_validate_entrypoint_blacklisted_syscall_counter( + resources_manager=resources_manager + ) + + # Exceptions being thrown by this yield are allowed and propagated up. + yield + + syscalls_after_execute = get_validate_entrypoint_blacklisted_syscall_counter( + resources_manager=resources_manager + ) + if syscalls_after_execute == syscalls_before_execute: + return + + diff = sub_counters(syscalls_after_execute, syscalls_before_execute) + + raise StarkException( + code=StarknetErrorCode.UNAUTHORIZED_ACTION_ON_VALIDATE, + message=( + "One or more unauthorized system calls were performed during 'validate' execution: " + f"{[name for name, count in diff.items() if count > 0]}." + ), + ) + + +def verify_no_calls_to_other_contracts(call_info: CallInfo): + invoked_contract_address = call_info.contract_address + for internal_call in call_info.gen_call_topology(): + if internal_call.contract_address != invoked_contract_address: + raise StarkException( + code=StarknetErrorCode.UNAUTHORIZED_ACTION_ON_VALIDATE, + message="Calling other contracts during `validate` execution is forbidden.", + ) diff --git a/src/starkware/starknet/cli/CMakeLists.txt b/src/starkware/starknet/cli/CMakeLists.txt index 30c7196c..992cf233 100644 --- a/src/starkware/starknet/cli/CMakeLists.txt +++ b/src/starkware/starknet/cli/CMakeLists.txt @@ -19,9 +19,11 @@ python_lib(starknet_cli_lib starknet_contract_class_lib starknet_definitions_lib starknet_feeder_gateway_client_lib + starknet_feeder_gateway_request_objects_lib starknet_feeder_gateway_response_objects_lib starknet_gateway_client_lib starknet_general_config_lib + starknet_standard_wallets_lib starknet_transaction_lib starknet_wallets_lib starkware_error_handling_lib diff --git a/src/starkware/starknet/cli/reconstruct_starknet_traceback_test.py b/src/starkware/starknet/cli/reconstruct_starknet_traceback_test.py index 2df68618..e5a7195e 100644 --- a/src/starkware/starknet/cli/reconstruct_starknet_traceback_test.py +++ b/src/starkware/starknet/cli/reconstruct_starknet_traceback_test.py @@ -5,18 +5,18 @@ def test_reconstruct_traceback(): code1 = """ -func main(): - assert 1 = 2 - return () -end - """ +func main() { + assert 1 = 2; + return (); +} +""" code2 = """ -func main(): - assert 2 = 3 - return () -end - """ +func main() { + assert 2 = 3; + return (); +} +""" traceback_txt = """ Error at pc=0:0: @@ -43,7 +43,7 @@ def test_reconstruct_traceback(): ) expected_res = """ filename:3:16: Error at pc=0:0: - assert 1 = 2 + assert 1 = 2; ^ Error message 1 Error in the called contract (0x1234): @@ -51,7 +51,7 @@ def test_reconstruct_traceback(): Error message 2 Error in the called contract (0x5678): filename:3:16: Error at pc=0:0: - assert 2 = 3 + assert 2 = 3; ^ Error message 3 """ @@ -67,7 +67,7 @@ def test_reconstruct_traceback(): Error message 1 Error in the called contract (0x1234): filename:3:16: Error at pc=0:0: - assert 1 = 2 + assert 1 = 2; ^ Error message 2 Error in the called contract (0x5678): diff --git a/src/starkware/starknet/cli/starknet_cli.py b/src/starkware/starknet/cli/starknet_cli.py index 4f83385f..24d321f1 100755 --- a/src/starkware/starknet/cli/starknet_cli.py +++ b/src/starkware/starknet/cli/starknet_cli.py @@ -3,13 +3,12 @@ import argparse import asyncio import dataclasses -import functools import json import math import os import sys import traceback -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Awaitable, Callable, Dict, List, Literal, Optional, Tuple, Union from web3 import Web3 @@ -28,21 +27,31 @@ from starkware.starknet.cli.reconstruct_starknet_traceback import reconstruct_starknet_traceback from starkware.starknet.definitions import constants, fields from starkware.starknet.definitions.general_config import StarknetChainId, StarknetGeneralConfig -from starkware.starknet.public.abi import get_selector_from_name +from starkware.starknet.public.abi import ( + EXECUTE_ENTRY_POINT_NAME, + EXECUTE_ENTRY_POINT_SELECTOR, + get_selector_from_name, +) from starkware.starknet.public.abi_structs import identifier_manager_from_abi from starkware.starknet.services.api.contract_class import ContractClass from starkware.starknet.services.api.feeder_gateway.feeder_gateway_client import ( CastableToHash, FeederGatewayClient, ) +from starkware.starknet.services.api.feeder_gateway.request_objects import ( + CallFunction, + CallL1Handler, +) from starkware.starknet.services.api.feeder_gateway.response_objects import ( LATEST_BLOCK_ID, PENDING_BLOCK_ID, BlockIdentifier, + FeeEstimationInfo, + TransactionSimulationInfo, ) from starkware.starknet.services.api.gateway.gateway_client import GatewayClient from starkware.starknet.services.api.gateway.transaction import ( - DECLARE_SENDER_ADDRESS, + AccountTransaction, Declare, Deploy, InvokeFunction, @@ -83,6 +92,13 @@ class InvokeFunctionArgs: signature: List[int] +@dataclasses.dataclass +class DeclareArgs: + contract_class: ContractClass + sender: Optional[int] + signature: List[int] + + # Utilities. @@ -229,7 +245,7 @@ def parse_hex_arg(arg: str, arg_name: str) -> int: try: return int(arg, 16) except ValueError: - raise ValueError(f"Invalid {arg_name} format: '{arg}'.") + raise ValueError(f"Invalid {arg_name} format: '{arg}'.") from None def get_salt(salt: Optional[str]) -> int: @@ -243,25 +259,29 @@ def get_salt(salt: Optional[str]) -> int: return parse_hex_arg(arg=salt, arg_name="salt") +def validate_max_fee(max_fee: Optional[int]): + if max_fee is None: + return + assert max_fee >= 0, f"The 'max_fee' argument, --max_fee, must be non-negative, got {max_fee}." + + async def compute_max_fee( - args: argparse.Namespace, invoke_tx: InvokeFunction, is_account_contract_invocation: bool + args: argparse.Namespace, tx: AccountTransaction, is_account_contract_invocation: bool ) -> int: """ Returns max_fee argument if passed, and estimates and returns the max fee otherwise. """ if args.max_fee is not None: - assert ( - args.max_fee >= 0 - ), f"The 'max_fee' argument, --max_fee, must be non-negative, got {args.max_fee}." + validate_max_fee(max_fee=args.max_fee) return args.max_fee if is_account_contract_invocation: - fee_info = await estimate_fee_inner( + simulate_tx_info = await simulate_tx_inner( args=args, - invoke_tx=invoke_tx, + tx=tx, has_block_info=False, ) - max_fee = math.ceil(fee_info["overall_fee"] * FEE_MARGIN_OF_ESTIMATION) + max_fee = math.ceil(simulate_tx_info.fee_estimation.overall_fee * FEE_MARGIN_OF_ESTIMATION) max_fee_eth = float(Web3.fromWei(max_fee, "ether")) print(f"Sending the transaction with max_fee: {max_fee_eth:.6f} ETH.") @@ -403,11 +423,14 @@ def handle_network_param(args): return 0 -def parse_invoke_tx_args(args: argparse.Namespace) -> InvokeFunctionArgs: +def validate_call_function_args( + args: argparse.Namespace, + abi_entry_type: Union[Literal["function"], Literal["l1_handler"]], + inputs: List[int], +): """ - Parses the arguments and validates that the function name is in the abi. + Validates that the function name is in the ABI and that the inputs match the required structure. """ - inputs = cast_to_felts(values=args.inputs) try: abi = json.load(args.abi) except Exception as ex: @@ -418,11 +441,13 @@ def parse_invoke_tx_args(args: argparse.Namespace) -> InvokeFunctionArgs: if "type" not in abi_entry: raise AbiFormatError(ABI_TYPE_NOT_FOUND_ERROR) - if abi_entry["type"] == "function": - # ABI function entry validation. + if abi_entry["type"] == abi_entry_type: + # ABI entry validation. # Note that not all ABI entries contain the 'name' entry, e.g., a constructor entry. if "name" not in abi_entry: - raise AbiFormatError("An ABI entry of type 'function' is missing a 'name' entry.") + raise AbiFormatError( + f"An ABI entry of type '{abi_entry_type}' is missing a 'name' entry." + ) if abi_entry["name"] == args.function: validate_arguments( @@ -432,16 +457,65 @@ def parse_invoke_tx_args(args: argparse.Namespace) -> InvokeFunctionArgs: ) break else: - raise AbiFormatError(f"Function '{args.function}' not found.") + raise AbiFormatError( + f"{abi_entry_type.capitalize().replace('_',' ')} '{args.function}' not found." + ) - return InvokeFunctionArgs( - signature=cast_to_felts(values=args.signature), - address=parse_hex_arg(arg=args.address, arg_name="address"), - selector=get_selector_from_name(args.function), + +def parse_call_function_args(args: argparse.Namespace) -> CallFunction: + """ + Parses the arguments and validates that the function name is in the ABI. + """ + inputs = cast_to_felts(values=args.inputs) + validate_call_function_args(args=args, abi_entry_type="function", inputs=inputs) + + return CallFunction( + contract_address=parse_hex_arg(arg=args.address, arg_name="address"), + entry_point_selector=get_selector_from_name(args.function), calldata=inputs, ) +def parse_call_l1_handler_args(args: argparse.Namespace) -> CallL1Handler: + """ + Parses the arguments and validates that the l1_handler name is in the ABI. + """ + inputs = cast_to_felts(values=args.inputs) + from_address = parse_hex_arg(arg=args.from_address, arg_name="from_address") + validate_call_function_args( + args=args, abi_entry_type="l1_handler", inputs=[from_address] + inputs + ) + + return CallL1Handler( + from_address=from_address, + to_address=parse_hex_arg(arg=args.address, arg_name="address"), + entry_point_selector=get_selector_from_name(args.function), + payload=inputs, + ) + + +def parse_invoke_tx_args(args: argparse.Namespace) -> InvokeFunctionArgs: + validate_max_fee(max_fee=args.max_fee) + call_function_args = parse_call_function_args(args) + invoke_tx_args = InvokeFunctionArgs( + address=call_function_args.contract_address, + selector=call_function_args.entry_point_selector, + calldata=call_function_args.calldata, + signature=cast_to_felts(values=args.signature), + ) + return invoke_tx_args + + +def parse_declare_tx_args(args: argparse.Namespace) -> DeclareArgs: + validate_max_fee(max_fee=args.max_fee) + sender = parse_hex_arg(arg=args.sender, arg_name="sender") if args.sender is not None else None + return DeclareArgs( + sender=sender, + signature=cast_to_felts(values=args.signature), + contract_class=ContractClass.loads(data=args.contract.read()), + ) + + async def create_invoke_tx_for_deploy( args: argparse.Namespace, salt: int, @@ -464,15 +538,15 @@ async def create_invoke_tx_for_deploy( chain_id=get_chain_id(args), max_fee=max_fee, version=version, - nonce=args.nonce, + nonce_callback=create_get_nonce_callback(args=args), ) tx = InvokeFunction( contract_address=wrapped_method.address, - entry_point_selector=wrapped_method.selector, calldata=wrapped_method.calldata, max_fee=wrapped_method.max_fee, version=version, signature=wrapped_method.signature, + nonce=wrapped_method.nonce, ) return tx, contract_address @@ -482,21 +556,24 @@ async def create_invoke_tx( invoke_tx_args: InvokeFunctionArgs, max_fee: int, has_wallet: bool, - call: bool, + query: bool, ) -> InvokeFunction: """ Creates and returns an InvokeFunction transaction with the given parameters. If a wallet provider was provided in args, that transaction will be wrapped and signed. """ - version = constants.QUERY_VERSION if call else constants.TRANSACTION_VERSION + version = constants.QUERY_VERSION if query else constants.TRANSACTION_VERSION if not has_wallet: - assert args.nonce is None, "--nonce cannot be used in direct calls." + assert invoke_tx_args.selector == EXECUTE_ENTRY_POINT_SELECTOR, ( + f"'--function' can only be {EXECUTE_ENTRY_POINT_NAME} " + "when invoking with the '--no_wallet' flag." + ) return InvokeFunction( contract_address=invoke_tx_args.address, - entry_point_selector=invoke_tx_args.selector, calldata=invoke_tx_args.calldata, max_fee=max_fee, version=version, + nonce=await create_get_nonce_callback(args=args)(invoke_tx_args.address), signature=invoke_tx_args.signature, ) @@ -512,63 +589,190 @@ async def create_invoke_tx( chain_id=get_chain_id(args), max_fee=max_fee, version=version, - nonce=args.nonce, + nonce_callback=create_get_nonce_callback(args=args), dry_run=args.dry_run, ) return InvokeFunction( contract_address=wrapped_method.address, - entry_point_selector=wrapped_method.selector, calldata=wrapped_method.calldata, max_fee=wrapped_method.max_fee, version=version, + nonce=wrapped_method.nonce, + signature=wrapped_method.signature, + ) + + +async def create_declare_tx( + args: argparse.Namespace, + declare_tx_args: DeclareArgs, + max_fee: int, + has_wallet: bool, + query: bool, +) -> Declare: + """ + Creates and returns a Declare transaction with the given parameters. + If a wallet provider was provided in args, that transaction will be wrapped and signed. + """ + version = constants.QUERY_VERSION if query else constants.TRANSACTION_VERSION + if not has_wallet: + # Declare directly. + assert ( + declare_tx_args.sender is not None + ), "Sender must be passed explicitly when making a direct declaration using --no_wallet." + return Declare( + contract_class=declare_tx_args.contract_class, + sender_address=declare_tx_args.sender, + max_fee=max_fee, + version=version, + signature=declare_tx_args.signature, + nonce=await create_get_nonce_callback(args=args)(declare_tx_args.sender), + ) + + # Declare through the account contract. + account = await load_account_from_args(args=args) + assert declare_tx_args.sender is None, ( + "Sender cannot be passed explicitly when using an account contract. " + "Consider making a direct declaration using --no_wallet." + ) + assert declare_tx_args.signature == [], ( + "Signature cannot be passed explicitly when using an account contract. " + "Consider making a direct declaration using --no_wallet." + ) + wrapped_method = await account.declare( + contract_class=declare_tx_args.contract_class, + chain_id=get_chain_id(args), + max_fee=max_fee, + version=version, + nonce_callback=create_get_nonce_callback(args=args), + ) + return Declare( + contract_class=declare_tx_args.contract_class, + sender_address=wrapped_method.address, + max_fee=wrapped_method.max_fee, + version=version, signature=wrapped_method.signature, + nonce=wrapped_method.nonce, ) -async def estimate_fee_inner( +async def simulate_tx_inner( args: argparse.Namespace, - invoke_tx: InvokeFunction, + tx: AccountTransaction, has_block_info: bool, -) -> Dict[str, Any]: +) -> TransactionSimulationInfo: """ - Estimates the fee of a transaction with the given parameters. - Returns a response of the form: - {"amount": , "unit": "wei"} + Simulates a transaction with the given parameters. + Returns a TransactionSimulationInfo object. """ feeder_client = get_feeder_gateway_client(args=args) - return await feeder_client.estimate_fee( - invoke_tx=invoke_tx, + return await feeder_client.simulate_transaction( + tx=tx, block_hash=args.block_hash if has_block_info else None, block_number=args.block_number if has_block_info else PENDING_BLOCK_ID, ) +def print_fee_info(fee_info: FeeEstimationInfo): + """ + Prints the fee information based on the FeeEstimationInfo object. + """ + fee_wei = fee_info.overall_fee + fee_eth = float(Web3.fromWei(fee_wei, "ether")) + print( + f"""\ +The estimated fee is: {fee_wei} WEI ({fee_eth:.6f} ETH). +Gas usage: {fee_info.gas_usage} +Gas price: {fee_info.gas_price} WEI""" + ) + + +def create_get_nonce_callback(args: argparse.Namespace) -> Callable[[int], Awaitable[int]]: + async def get_nonce(address: int) -> int: + if args.nonce is not None: + return args.nonce + + # Obtain the current nonce. Note that you can't invoke a function again before the + # previous transaction was accepted. + feeder_gateway_client = get_feeder_gateway_client(args) + return await feeder_gateway_client.get_nonce( + contract_address=address, block_hash=None, block_number=PENDING_BLOCK_ID + ) + + return get_nonce + + def assert_tx_received(gateway_response: Dict[str, str]): assert ( gateway_response["code"] == StarkErrorCode.TRANSACTION_RECEIVED.name ), f"Failed to send transaction. Response: {gateway_response}." +async def estimate_fee(args: argparse.Namespace, tx: AccountTransaction): + tx_simulate_info = await simulate_tx_inner(args=args, tx=tx, has_block_info=True) + print_fee_info(fee_info=tx_simulate_info.fee_estimation) + + +async def simulate_transaction(args: argparse.Namespace, tx: AccountTransaction): + tx_simulate_info = await simulate_tx_inner(args=args, tx=tx, has_block_info=True) + print_fee_info(fee_info=tx_simulate_info.fee_estimation) + print() + print(tx_simulate_info.trace.dumps(indent=4, sort_keys=True)) + + +async def simulate_or_estimate_fee(args: argparse.Namespace, tx: AccountTransaction): + args.block_hash, args.block_number = parse_block_identifiers(args.block_hash, args.block_number) + if args.simulate: + await simulate_transaction(args=args, tx=tx) + else: + await estimate_fee(args=args, tx=tx) + + # Subparsers. -async def declare(args, command_args): +async def declare( + args: argparse.Namespace, + command_args: List[str], +): + """ + Creates a Declare transaction and sends it to the gateway. In case a wallet is provided, the + transaction is wrapped and signed by the wallet provider. Otherwise, a sender address and a + valid signature must be provided as arguments. + """ + parser = argparse.ArgumentParser(description="Sends a declare transaction to StarkNet.") add_declare_tx_arguments(parser=parser) parser.parse_args(command_args, namespace=args) - assert args.sender == DECLARE_SENDER_ADDRESS, f"--sender must be {DECLARE_SENDER_ADDRESS}." - assert args.max_fee == 0, "--max_fee must be 0." - assert args.nonce == 0, "--nonce must be 0." + declare_tx_args = parse_declare_tx_args(args=args) + has_wallet = get_wallet_provider(args=args) is not None - tx = Declare( - contract_class=ContractClass.loads(data=args.contract.read()), - sender_address=args.sender, - max_fee=args.max_fee, - version=constants.TRANSACTION_VERSION, - signature=args.signature, - nonce=args.nonce, + declare_tx_for_simulate = await create_declare_tx( + args=args, + declare_tx_args=declare_tx_args, + max_fee=args.max_fee if args.max_fee is not None else 0, + has_wallet=has_wallet, + query=True, + ) + + if args.simulate or args.estimate_fee: + await simulate_or_estimate_fee(args=args, tx=declare_tx_for_simulate) + return + + assert args.block_hash is None and args.block_number is None, ( + "--block_hash and --block_number should only be passed when either --simulate or " + "--estimate_fee flag are used." + ) + max_fee = await compute_max_fee( + args=args, tx=declare_tx_for_simulate, is_account_contract_invocation=has_wallet ) + tx = await create_declare_tx( + args=args, + declare_tx_args=declare_tx_args, + max_fee=max_fee, + has_wallet=has_wallet, + query=False, + ) gateway_client = get_gateway_client(args) gateway_response = await gateway_client.add_transaction(tx=tx, token=args.token) assert_tx_received(gateway_response=gateway_response) @@ -664,7 +868,9 @@ async def deploy_tx(args): ) break except AbiFormatError as abi_error: - raise AbiFormatError(f"Failed to parse the contract ABI: {abi_error}") + raise AbiFormatError( + f"Failed to parse the contract ABI: {abi_error}" + ) from abi_error else: assert len(inputs) == 0, "--inputs cannot be specified for contracts without a constructor." @@ -692,7 +898,7 @@ async def deploy_with_invoke(args: argparse.Namespace): salt = get_salt(salt=args.salt) class_hash = parse_hex_arg(arg=args.class_hash, arg_name="class_hash") constructor_calldata = cast_to_felts(values=args.inputs) - invoke_tx, _ = await create_invoke_tx_for_deploy( + invoke_tx_for_fee_estimation, _ = await create_invoke_tx_for_deploy( args=args, salt=salt, class_hash=class_hash, @@ -701,7 +907,7 @@ async def deploy_with_invoke(args: argparse.Namespace): call=True, ) max_fee = await compute_max_fee( - args=args, invoke_tx=invoke_tx, is_account_contract_invocation=True + args=args, tx=invoke_tx_for_fee_estimation, is_account_contract_invocation=True ) tx, contract_address = await create_invoke_tx_for_deploy( args=args, @@ -734,58 +940,79 @@ async def deploy_account(args, command_args): await account.deploy() -async def invoke_or_call(args: argparse.Namespace, command_args: List[str], call: bool): - parser = argparse.ArgumentParser(description="Sends an invoke transaction to StarkNet.") - add_invoke_tx_arguments(parser=parser, call=call) - parser.add_argument( - "--max_fee", type=int, help="The maximal fee to be paid for the function invocation." +async def call(args: argparse.Namespace, command_args: List[str]): + parser = argparse.ArgumentParser(description="Calls a function on a StarkNet contract.") + add_call_function_arguments(parser=parser) + add_block_identifier_arguments( + parser=parser, block_role_description="be used as the context for the call operation" + ) + parser.parse_args(command_args, namespace=args) + call_function_args = parse_call_function_args(args=args) + args.block_hash, args.block_number = parse_block_identifiers(args.block_hash, args.block_number) + + feeder_client = get_feeder_gateway_client(args) + gateway_response = await feeder_client.call_contract( + call_function=call_function_args, block_hash=args.block_hash, block_number=args.block_number ) + print(*map(felt_formatter, gateway_response["result"])) + + +async def invoke(args: argparse.Namespace, command_args: List[str]): + parser = argparse.ArgumentParser(description="Sends an invoke transaction to StarkNet.") + add_invoke_tx_arguments(parser=parser) parser.parse_args(command_args, namespace=args) invoke_tx_args = parse_invoke_tx_args(args=args) has_wallet = get_wallet_provider(args=args) is not None - is_account_contract_invocation = has_wallet and not call + invoke_tx_for_simulate = await create_invoke_tx( + args=args, + invoke_tx_args=invoke_tx_args, + max_fee=args.max_fee if args.max_fee is not None else 0, + has_wallet=has_wallet, + query=True, + ) + + if args.simulate or args.estimate_fee: + await simulate_or_estimate_fee(args=args, tx=invoke_tx_for_simulate) + return + + assert args.block_hash is None and args.block_number is None, ( + "--block_hash and --block_number should only be passed when --simulate or " + "--estimate_fee flag is used." + ) + + is_account_contract_invocation = has_wallet if args.dry_run: assert ( is_account_contract_invocation - ), "--dry_run can only be used for account contract invoke." - invoke_tx = await create_invoke_tx( - args=args, invoke_tx_args=invoke_tx_args, max_fee=0, has_wallet=has_wallet, call=True - ) + ), "--dry_run can only be used for invocation through an account contract." + max_fee = await compute_max_fee( args=args, - invoke_tx=invoke_tx, + tx=invoke_tx_for_simulate, is_account_contract_invocation=is_account_contract_invocation, ) - tx = await create_invoke_tx( - args=args, invoke_tx_args=invoke_tx_args, max_fee=max_fee, has_wallet=has_wallet, call=call - ) - gateway_response: dict - if call: - args.block_hash, args.block_number = parse_block_identifiers( - args.block_hash, args.block_number - ) - - feeder_client = get_feeder_gateway_client(args) - gateway_response = await feeder_client.call_contract( - invoke_tx=tx, block_hash=args.block_hash, block_number=args.block_number - ) - print(*map(felt_formatter, gateway_response["result"])) - else: - if not args.dry_run: - gateway_client = get_gateway_client(args) - gateway_response = await gateway_client.add_transaction(tx=tx) - assert_tx_received(gateway_response=gateway_response) - # Don't end sentences with '.', to allow easy double-click copy-pasting of the values. - print( - f"""\ + tx = await create_invoke_tx( + args=args, + invoke_tx_args=invoke_tx_args, + max_fee=max_fee, + has_wallet=has_wallet, + query=False, + ) + if not args.dry_run: + gateway_client = get_gateway_client(args) + gateway_response = await gateway_client.add_transaction(tx=tx) + assert_tx_received(gateway_response=gateway_response) + # Don't end sentences with '.', to allow easy double-click copy-pasting of the values. + print( + f"""\ Invoke transaction was sent. Contract address: 0x{invoke_tx_args.address:064x} Transaction hash: {gateway_response['transaction_hash']}""" - ) - else: - print_invoke_tx(tx=tx, chain_id=get_chain_id(args)) + ) + else: + print_invoke_tx(tx=tx, chain_id=get_chain_id(args)) def print_invoke_tx(tx: InvokeFunction, chain_id: int): @@ -800,31 +1027,28 @@ def print_invoke_tx(tx: InvokeFunction, chain_id: int): print(json.dumps(out_dict, indent=4)) -async def estimate_fee(args: argparse.Namespace, command_args: List[str]): - parser = argparse.ArgumentParser(description="Estimates the fee of a transaction.") - add_invoke_tx_arguments(parser=parser, call=True) +async def estimate_message_fee(args: argparse.Namespace, command_args: List[str]): + parser = argparse.ArgumentParser(description="Estimates the fee of an L1-to-L2 message.") + add_block_identifier_arguments( + parser=parser, block_role_description="be used as the context for the call operation" + ) + add_call_l1_handler_arguments(parser=parser) parser.parse_args(command_args, namespace=args) - invoke_tx_args = parse_invoke_tx_args(args=args) - has_wallet = get_wallet_provider(args=args) is not None - invoke_tx = await create_invoke_tx( - args=args, invoke_tx_args=invoke_tx_args, max_fee=0, has_wallet=has_wallet, call=True - ) - fee_info = await estimate_fee_inner(args=args, invoke_tx=invoke_tx, has_block_info=True) + args.block_hash, args.block_number = parse_block_identifiers(args.block_hash, args.block_number) + call_l1_handler = parse_call_l1_handler_args(args=args) - fee_wei = fee_info["overall_fee"] - fee_eth = float(Web3.fromWei(fee_wei, "ether")) - print( - f"""\ -The estimated fee is: {fee_wei} WEI ({fee_eth:.6f} ETH). -Gas usage: {fee_info["gas_usage"]} -Gas price: {fee_info["gas_price"]} WEI""" + feeder_client = get_feeder_gateway_client(args=args) + fee_info = await feeder_client.estimate_message_fee( + call_l1_handler=call_l1_handler, block_hash=args.block_hash, block_number=args.block_number ) + print_fee_info(fee_info=fee_info) + async def tx_status(args, command_args): parser = argparse.ArgumentParser( - description="Queries the status of a transaction given its ID." + description="Queries the status of a transaction given its hash." ) parser.add_argument( "--hash", type=str, required=True, help="The hash of the transaction to query." @@ -880,7 +1104,7 @@ async def tx_status(args, command_args): async def get_transaction(args, command_args): parser = argparse.ArgumentParser( - description="Outputs the transaction information given its ID." + description="Outputs the transaction information given its hash." ) parser.add_argument( "--hash", type=str, required=True, help="The hash of the transaction to query." @@ -893,7 +1117,7 @@ async def get_transaction(args, command_args): async def get_transaction_trace(args, command_args): - parser = argparse.ArgumentParser(description="Outputs the transaction trace given its ID.") + parser = argparse.ArgumentParser(description="Outputs the transaction trace given its hash.") parser.add_argument( "--hash", type=str, required=True, help="The hash of the transaction to query." ) @@ -905,7 +1129,7 @@ async def get_transaction_trace(args, command_args): async def get_transaction_receipt(args, command_args): - parser = argparse.ArgumentParser(description="Outputs the transaction receipt given its ID.") + parser = argparse.ArgumentParser(description="Outputs the transaction receipt given its hash.") parser.add_argument( "--hash", type=str, required=True, help="The hash of the transaction to query." ) @@ -1062,7 +1286,7 @@ async def get_class_hash_at(args, command_args): block_hash=args.block_hash, block_number=args.block_number, ) - print(json.dumps(class_hash, indent=4, sort_keys=True)) + print(class_hash) async def get_contract_addresses(args, command_args): @@ -1073,6 +1297,30 @@ async def get_contract_addresses(args, command_args): print(json.dumps(contract_addresses, indent=4, sort_keys=True)) +async def get_nonce(args, command_args): + parser = argparse.ArgumentParser( + description=( + "Outputs the nonce of a contract with respect to a specific block. " + "In case no block identifier is given, uses the pending block." + ) + ) + parser.add_argument( + "--contract_address", type=str, help="The address of the contract.", required=True + ) + add_block_identifier_arguments(parser=parser, block_role_description="extract information from") + + parser.parse_args(command_args, namespace=args) + args.block_hash, args.block_number = parse_block_identifiers(args.block_hash, args.block_number) + + feeder_gateway_client = get_feeder_gateway_client(args) + nonce = await feeder_gateway_client.get_nonce( + contract_address=parse_hex_arg(args.contract_address, "contract_address"), + block_hash=args.block_hash, + block_number=args.block_number, + ) + print(nonce) + + async def get_storage_at(args, command_args): parser = argparse.ArgumentParser( description=( @@ -1105,9 +1353,26 @@ async def get_storage_at(args, command_args): # Add arguments. +def add_simulate_tx_arguments(parser: argparse.ArgumentParser): + """ + Adds the arguments: simulate, estimate_fee. + """ + parser.add_argument( + "--simulate", + action="store_true", + help="Simulates the transaction and prints its trace and its estimated cost.", + ) + parser.add_argument( + "--estimate_fee", + action="store_true", + help="Estimates the fee of the transaction.", + ) + + def add_declare_tx_arguments(parser: argparse.ArgumentParser): """ - Adds the arguments: contract, sender, max_fee, signature, nonce, token. + Adds the arguments: contract, sender, max_fee, signature, nonce, token and the simulate + arguments and the block identifier arguments. """ parser.add_argument( "--contract", @@ -1118,13 +1383,11 @@ def add_declare_tx_arguments(parser: argparse.ArgumentParser): parser.add_argument( "--sender", type=str, - default=DECLARE_SENDER_ADDRESS, help="The address of the account contract sending the transaction.", ) parser.add_argument( "--max_fee", type=int, - default=0, help="The maximal fee to be paid for the declaration.", ) parser.add_argument( @@ -1137,7 +1400,6 @@ def add_declare_tx_arguments(parser: argparse.ArgumentParser): parser.add_argument( "--nonce", type=int, - default=0, help=( "Used for explicitly specifying the transaction nonce. " "If not specified, the current nonce of the account contract " @@ -1147,11 +1409,16 @@ def add_declare_tx_arguments(parser: argparse.ArgumentParser): parser.add_argument( "--token", type=str, help="Used for declaring contracts in Alpha MainNet.", required=False ) + add_simulate_tx_arguments(parser=parser) + add_block_identifier_arguments( + parser=parser, + block_role_description="be used as the context for the transaction simulation", + ) -def add_invoke_tx_arguments(parser: argparse.ArgumentParser, call: bool): +def add_call_function_arguments(parser: argparse.ArgumentParser): """ - Adds the arguments: address, abi, function, inputs, nonce, signature. + Adds the arguments: address, abi, function, inputs. """ parser.add_argument( "--address", type=str, required=True, help="The address of the invoked contract." @@ -1165,6 +1432,25 @@ def add_invoke_tx_arguments(parser: argparse.ArgumentParser, call: bool): parser.add_argument( "--inputs", type=str, nargs="*", default=[], help="The inputs to the invoked function." ) + + +def add_call_l1_handler_arguments(parser: argparse.ArgumentParser): + """ + Adds the argument 'from_address' and the call_function arguments. + """ + parser.add_argument( + "--from_address", type=str, required=True, help="The L1 address of the caller." + ) + + add_call_function_arguments(parser=parser) + + +def add_invoke_tx_arguments(parser: argparse.ArgumentParser): + """ + Adds the arguments: address, abi, function, inputs, nonce, signature, the simulate arguments and + the block identifier arguments. + """ + add_call_function_arguments(parser=parser) parser.add_argument( "--nonce", type=int, @@ -1186,24 +1472,27 @@ def add_invoke_tx_arguments(parser: argparse.ArgumentParser, call: bool): default=[], help="The signature information for the invoked function.", ) - - if call: - add_block_identifier_arguments( - parser=parser, block_role_description="be used as the context for the call operation" - ) + parser.add_argument( + "--max_fee", type=int, help="The maximal fee to be paid for the function invocation." + ) + add_simulate_tx_arguments(parser=parser) + add_block_identifier_arguments( + parser=parser, + block_role_description="be used as the context for the transaction simulation", + ) def add_block_identifier_arguments( parser: argparse.ArgumentParser, block_role_description: str, with_block_prefix: bool = True ): identifier_prefix = "block_" if with_block_prefix else "" - block_identifier_arguments = parser.add_mutually_exclusive_group(required=False) - block_identifier_arguments.add_argument( + block_identifier_parser_group = parser.add_mutually_exclusive_group(required=False) + block_identifier_parser_group.add_argument( f"--{identifier_prefix}hash", type=str, help=(f"The hash of the block to {block_role_description}. "), ) - block_identifier_arguments.add_argument( + block_identifier_parser_group.add_argument( f"--{identifier_prefix}number", help=( f"The number of the block to {block_role_description}; " @@ -1214,11 +1503,11 @@ def add_block_identifier_arguments( async def main(): subparsers = { - "call": functools.partial(invoke_or_call, call=True), + "call": call, "declare": declare, "deploy": deploy, "deploy_account": deploy_account, - "estimate_fee": estimate_fee, + "estimate_message_fee": estimate_message_fee, "get_block": get_block, "get_block_traces": get_block_traces, "get_class_by_hash": get_class_by_hash, @@ -1226,12 +1515,13 @@ async def main(): "get_code": get_code, "get_contract_addresses": get_contract_addresses, "get_full_contract": get_full_contract, + "get_nonce": get_nonce, "get_state_update": get_state_update, "get_storage_at": get_storage_at, "get_transaction": get_transaction, "get_transaction_receipt": get_transaction_receipt, "get_transaction_trace": get_transaction_trace, - "invoke": functools.partial(invoke_or_call, call=False), + "invoke": invoke, "tx_status": tx_status, } parser = argparse.ArgumentParser(description="A tool to communicate with StarkNet.") @@ -1247,12 +1537,13 @@ async def main(): type=str, help="The chain id (either as a hex number or as a string).", ) - parser.add_argument( + wallet_parser_group = parser.add_mutually_exclusive_group(required=False) + wallet_parser_group.add_argument( "--wallet", type=str, help="The name of the wallet, including the python module and wallet class.", ) - parser.add_argument( + wallet_parser_group.add_argument( "--no_wallet", dest="wallet", action="store_const", diff --git a/src/starkware/starknet/common/CMakeLists.txt b/src/starkware/starknet/common/CMakeLists.txt index b7c2de99..85ab380c 100644 --- a/src/starkware/starknet/common/CMakeLists.txt +++ b/src/starkware/starknet/common/CMakeLists.txt @@ -2,10 +2,11 @@ python_lib(starknet_common_lib PREFIX starkware/starknet/common FILES + constants.cairo + eth_utils.cairo messages.cairo storage.cairo syscalls.cairo - eth_utils.cairo LIBS cairo_common_lib diff --git a/src/starkware/starknet/common/constants.cairo b/src/starkware/starknet/common/constants.cairo new file mode 100644 index 00000000..a77dd532 --- /dev/null +++ b/src/starkware/starknet/common/constants.cairo @@ -0,0 +1,8 @@ +// The dummy caller address of an externally originated transaction. +const ORIGIN_ADDRESS = 0; + +// Transaction hash prefixes. +const DECLARE_HASH_PREFIX = 'declare'; +const DEPLOY_HASH_PREFIX = 'deploy'; +const INVOKE_HASH_PREFIX = 'invoke'; +const L1_HANDLER_HASH_PREFIX = 'l1_handler'; diff --git a/src/starkware/starknet/common/eth_utils.cairo b/src/starkware/starknet/common/eth_utils.cairo index fe08ca25..4341e9fb 100644 --- a/src/starkware/starknet/common/eth_utils.cairo +++ b/src/starkware/starknet/common/eth_utils.cairo @@ -1,14 +1,14 @@ from starkware.cairo.common.math import assert_lt_felt, assert_not_zero -const ETH_ADDRESS_BOUND = 2 ** 160 +const ETH_ADDRESS_BOUND = 2 ** 160; -func assert_valid_eth_address{range_check_ptr}(address : felt): - with_attr error_message("Invalid Ethereum address - value is more than 160 bits"): - assert_lt_felt(address, ETH_ADDRESS_BOUND) - end +func assert_eth_address_range{range_check_ptr}(address: felt) { + with_attr error_message("Invalid Ethereum address - value is more than 160 bits") { + assert_lt_felt(address, ETH_ADDRESS_BOUND); + } - with_attr error_message("Invalid Ethereum address - value is zero"): - assert_not_zero(address) - end - return () -end + with_attr error_message("Invalid Ethereum address - value is zero") { + assert_not_zero(address); + } + return (); +} diff --git a/src/starkware/starknet/common/eth_utils_test.py b/src/starkware/starknet/common/eth_utils_test.py index 63cba706..d5fe2ddc 100644 --- a/src/starkware/starknet/common/eth_utils_test.py +++ b/src/starkware/starknet/common/eth_utils_test.py @@ -32,10 +32,10 @@ def runner(program: Program) -> CairoFunctionRunner: (DEFAULT_PRIME - 1, "Invalid Ethereum address - value is more than 160 bits"), ], ) -def test_assert_valid_eth_address(runner: CairoFunctionRunner, address, error_message): +def test_assert_eth_address_range(runner: CairoFunctionRunner, address, error_message): with maybe_raises(expected_exception=VmException, error_message=error_message): runner.run( - "assert_valid_eth_address", + "assert_eth_address_range", range_check_ptr=runner.range_check_builtin.base, address=address, ) diff --git a/src/starkware/starknet/common/messages.cairo b/src/starkware/starknet/common/messages.cairo index 065c66b0..ab23bf6e 100644 --- a/src/starkware/starknet/common/messages.cairo +++ b/src/starkware/starknet/common/messages.cairo @@ -1,15 +1,13 @@ from starkware.starknet.common.syscalls import SEND_MESSAGE_TO_L1_SELECTOR, SendMessageToL1SysCall -# Sends a message to an L1 contract at 'l1_address' with given payload. -func send_message_to_l1{syscall_ptr : felt*}( - to_address : felt, payload_size : felt, payload : felt* -): +// Sends a message to an L1 contract at 'l1_address' with given payload. +func send_message_to_l1{syscall_ptr: felt*}(to_address: felt, payload_size: felt, payload: felt*) { assert [cast(syscall_ptr, SendMessageToL1SysCall*)] = SendMessageToL1SysCall( selector=SEND_MESSAGE_TO_L1_SELECTOR, to_address=to_address, payload_size=payload_size, - payload_ptr=payload) + payload_ptr=payload); %{ syscall_handler.send_message_to_l1(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + SendMessageToL1SysCall.SIZE - return () -end + let syscall_ptr = syscall_ptr + SendMessageToL1SysCall.SIZE; + return (); +} diff --git a/src/starkware/starknet/common/storage.cairo b/src/starkware/starknet/common/storage.cairo index 08beec56..ee5636f0 100644 --- a/src/starkware/starknet/common/storage.cairo +++ b/src/starkware/starknet/common/storage.cairo @@ -1,16 +1,16 @@ from starkware.cairo.common.math import assert_250_bit -const MAX_STORAGE_ITEM_SIZE = 256 -# Valid storage addresses should satisfy address + offset < 2**251 where -# offset < MAX_STORAGE_ITEM_SIZE and address < ADDR_BOUND. -const ADDR_BOUND = 2 ** 251 - 256 +const MAX_STORAGE_ITEM_SIZE = 256; +// Valid storage addresses should satisfy address + offset < 2**251 where +// offset < MAX_STORAGE_ITEM_SIZE and address < ADDR_BOUND. +const ADDR_BOUND = 2 ** 251 - 256; -# Computes addr % ADDR_BOUND so that the result will form a valid storage item address in the -# storage tree. In particular, we need the result + MAX_STORAGE_ITEM_SIZE to be less that -# 2**251. +// Computes addr % ADDR_BOUND so that the result will form a valid storage item address in the +// storage tree. In particular, we need the result + MAX_STORAGE_ITEM_SIZE to be less that +// 2**251. @known_ap_change -func normalize_address{range_check_ptr}(addr : felt) -> (res : felt): - tempvar is_small +func normalize_address{range_check_ptr}(addr: felt) -> (res: felt) { + tempvar is_small; %{ # Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME. ADDR_BOUND = ids.ADDR_BOUND % PRIME @@ -19,36 +19,36 @@ func normalize_address{range_check_ptr}(addr : felt) -> (res : felt): 'normalize_address() cannot be used with the current constants.' ids.is_small = 1 if ids.addr < ADDR_BOUND else 0 %} - if is_small != 0: - tempvar is_250 + if (is_small != 0) { + tempvar is_250; %{ ids.is_250 = 1 if ids.addr < 2**250 else 0 %} - if is_250 != 0: - ap += 11 - # In this case addr < 2**250 < ADDR_BOUND, so addr % ADDR_BOUND = addr. - assert_250_bit(addr) - else: - ap += 10 - # In this case 0 <= ADDR_BOUND - 1 - addr < 2**250, so addr < ADDR_BOUND. - assert_250_bit(ADDR_BOUND - 1 - addr) - end - return (res=addr) - else: - # The first call to assert_250_bit() checks that 0 <= (addr - ADDR_BOUND) % PRIME < 2**250. - # The second call checks that 0 <= (-1 - addr) % PRIME < 2**250. - # Let x = (addr - ADDR_BOUND) % PRIME and y = (-1 - addr) % PRIME. Then, - # x + y = (addr - ADDR_BOUND) + (-1 - addr) = PRIME - 1 - ADDR_BOUND (mod PRIME). - # So we have: - # x + y = PRIME - 1 - ADDR_BOUND (mod PRIME). - # Since both hands are in the range [0, PRIME) (since 2 * 2**250 < PRIME), - # they must be equal as integers. - # In particular, x + ADDR_BOUND = PRIME - 1 - y < PRIME. - # Since addr = x + ADDR_BOUND (mod PRIME) and both sides are in the range [0, PRIME) - # we have addr = x + ADDR_BOUND (as integers). - # Therefore, we should subtract ADDR_BOUND to get addr % ADDR_BOUND. - let x = addr - ADDR_BOUND - let y = (-1) - addr - assert_250_bit(x) - assert_250_bit(y) - return (res=addr - ADDR_BOUND) - end -end + if (is_250 != 0) { + ap += 11; + // In this case addr < 2**250 < ADDR_BOUND, so addr % ADDR_BOUND = addr. + assert_250_bit(addr); + } else { + ap += 10; + // In this case 0 <= ADDR_BOUND - 1 - addr < 2**250, so addr < ADDR_BOUND. + assert_250_bit(ADDR_BOUND - 1 - addr); + } + return (res=addr); + } else { + // The first call to assert_250_bit() checks that 0 <= (addr - ADDR_BOUND) % PRIME < 2**250. + // The second call checks that 0 <= (-1 - addr) % PRIME < 2**250. + // Let x = (addr - ADDR_BOUND) % PRIME and y = (-1 - addr) % PRIME. Then, + // x + y = (addr - ADDR_BOUND) + (-1 - addr) = PRIME - 1 - ADDR_BOUND (mod PRIME). + // So we have: + // x + y = PRIME - 1 - ADDR_BOUND (mod PRIME). + // Since both hands are in the range [0, PRIME) (since 2 * 2**250 < PRIME), + // they must be equal as integers. + // In particular, x + ADDR_BOUND = PRIME - 1 - y < PRIME. + // Since addr = x + ADDR_BOUND (mod PRIME) and both sides are in the range [0, PRIME) + // we have addr = x + ADDR_BOUND (as integers). + // Therefore, we should subtract ADDR_BOUND to get addr % ADDR_BOUND. + let x = addr - ADDR_BOUND; + let y = (-1) - addr; + assert_250_bit(x); + assert_250_bit(y); + return (res=addr - ADDR_BOUND); + } +} diff --git a/src/starkware/starknet/common/syscalls.cairo b/src/starkware/starknet/common/syscalls.cairo index c83a2375..c0a752cd 100644 --- a/src/starkware/starknet/common/syscalls.cairo +++ b/src/starkware/starknet/common/syscalls.cairo @@ -1,442 +1,445 @@ from starkware.cairo.common.dict_access import DictAccess -const SEND_MESSAGE_TO_L1_SELECTOR = 'SendMessageToL1' - -# Describes the SendMessageToL1 system call format. -struct SendMessageToL1SysCall: - member selector : felt - member to_address : felt - member payload_size : felt - member payload_ptr : felt* -end - -const CALL_CONTRACT_SELECTOR = 'CallContract' -const DELEGATE_CALL_SELECTOR = 'DelegateCall' -const DELEGATE_L1_HANDLER_SELECTOR = 'DelegateL1Handler' - -# Describes the CallContract system call format. -struct CallContractRequest: - # The system call selector - # (= CALL_CONTRACT_SELECTOR, DELEGATE_CALL_SELECTOR or DELEGATE_L1_HANDLER_SELECTOR). - member selector : felt - # The address of the L2 contract to call. - member contract_address : felt - # The selector of the function to call. - member function_selector : felt - # The size of the calldata. - member calldata_size : felt - # The calldata. - member calldata : felt* -end - -struct CallContractResponse: - member retdata_size : felt - member retdata : felt* -end - -struct CallContract: - member request : CallContractRequest - member response : CallContractResponse -end - -func call_contract{syscall_ptr : felt*}( - contract_address : felt, function_selector : felt, calldata_size : felt, calldata : felt* -) -> (retdata_size : felt, retdata : felt*): - let syscall = [cast(syscall_ptr, CallContract*)] +const SEND_MESSAGE_TO_L1_SELECTOR = 'SendMessageToL1'; + +// Describes the SendMessageToL1 system call format. +struct SendMessageToL1SysCall { + selector: felt, + to_address: felt, + payload_size: felt, + payload_ptr: felt*, +} + +const CALL_CONTRACT_SELECTOR = 'CallContract'; +const DELEGATE_CALL_SELECTOR = 'DelegateCall'; +const DELEGATE_L1_HANDLER_SELECTOR = 'DelegateL1Handler'; + +// Describes the CallContract system call format. +struct CallContractRequest { + // The system call selector + // (= CALL_CONTRACT_SELECTOR, DELEGATE_CALL_SELECTOR or DELEGATE_L1_HANDLER_SELECTOR). + selector: felt, + // The address of the L2 contract to call. + contract_address: felt, + // The selector of the function to call. + function_selector: felt, + // The size of the calldata. + calldata_size: felt, + // The calldata. + calldata: felt*, +} + +struct CallContractResponse { + retdata_size: felt, + retdata: felt*, +} + +struct CallContract { + request: CallContractRequest, + response: CallContractResponse, +} + +func call_contract{syscall_ptr: felt*}( + contract_address: felt, function_selector: felt, calldata_size: felt, calldata: felt* +) -> (retdata_size: felt, retdata: felt*) { + let syscall = [cast(syscall_ptr, CallContract*)]; assert syscall.request = CallContractRequest( selector=CALL_CONTRACT_SELECTOR, contract_address=contract_address, function_selector=function_selector, calldata_size=calldata_size, - calldata=calldata) + calldata=calldata); %{ syscall_handler.call_contract(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let response = syscall.response - - let syscall_ptr = syscall_ptr + CallContract.SIZE - return (retdata_size=response.retdata_size, retdata=response.retdata) -end - -const LIBRARY_CALL_SELECTOR = 'LibraryCall' -const LIBRARY_CALL_L1_HANDLER_SELECTOR = 'LibraryCallL1Handler' - -# Describes the LibraryCall system call format. -struct LibraryCallRequest: - # The system library call selector - # (= LIBRARY_CALL_SELECTOR or LIBRARY_CALL_L1_HANDLER_SELECTOR). - member selector : felt - # The hash of the class to run. - member class_hash : felt - # The selector of the function to call. - member function_selector : felt - # The size of the calldata. - member calldata_size : felt - # The calldata. - member calldata : felt* -end - -struct LibraryCall: - member request : LibraryCallRequest - member response : CallContractResponse -end - -# Performs a library call: Runs an entry point of another contract class -# on the current contract state. -func library_call{syscall_ptr : felt*}( - class_hash : felt, function_selector : felt, calldata_size : felt, calldata : felt* -) -> (retdata_size : felt, retdata : felt*): - let syscall = [cast(syscall_ptr, LibraryCall*)] + let response = syscall.response; + + let syscall_ptr = syscall_ptr + CallContract.SIZE; + return (retdata_size=response.retdata_size, retdata=response.retdata); +} + +const LIBRARY_CALL_SELECTOR = 'LibraryCall'; +const LIBRARY_CALL_L1_HANDLER_SELECTOR = 'LibraryCallL1Handler'; + +// Describes the LibraryCall system call format. +struct LibraryCallRequest { + // The system library call selector + // (= LIBRARY_CALL_SELECTOR or LIBRARY_CALL_L1_HANDLER_SELECTOR). + selector: felt, + // The hash of the class to run. + class_hash: felt, + // The selector of the function to call. + function_selector: felt, + // The size of the calldata. + calldata_size: felt, + // The calldata. + calldata: felt*, +} + +struct LibraryCall { + request: LibraryCallRequest, + response: CallContractResponse, +} + +// Performs a library call: Runs an entry point of another contract class +// on the current contract state. +func library_call{syscall_ptr: felt*}( + class_hash: felt, function_selector: felt, calldata_size: felt, calldata: felt* +) -> (retdata_size: felt, retdata: felt*) { + let syscall = [cast(syscall_ptr, LibraryCall*)]; assert syscall.request = LibraryCallRequest( selector=LIBRARY_CALL_SELECTOR, class_hash=class_hash, function_selector=function_selector, calldata_size=calldata_size, - calldata=calldata) + calldata=calldata); %{ syscall_handler.library_call(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let response = syscall.response - - let syscall_ptr = syscall_ptr + LibraryCall.SIZE - return (retdata_size=response.retdata_size, retdata=response.retdata) -end - -# Simialr to library_call(), except that the entry point is an L1 handler, -# rather than an external function. -# Note that this function does not consume an L1 message, -# and thus it should only be called from a corresponding L1 handler. -func library_call_l1_handler{syscall_ptr : felt*}( - class_hash : felt, function_selector : felt, calldata_size : felt, calldata : felt* -) -> (retdata_size : felt, retdata : felt*): - let syscall = [cast(syscall_ptr, LibraryCall*)] + let response = syscall.response; + + let syscall_ptr = syscall_ptr + LibraryCall.SIZE; + return (retdata_size=response.retdata_size, retdata=response.retdata); +} + +// Simialr to library_call(), except that the entry point is an L1 handler, +// rather than an external function. +// Note that this function does not consume an L1 message, +// and thus it should only be called from a corresponding L1 handler. +func library_call_l1_handler{syscall_ptr: felt*}( + class_hash: felt, function_selector: felt, calldata_size: felt, calldata: felt* +) -> (retdata_size: felt, retdata: felt*) { + let syscall = [cast(syscall_ptr, LibraryCall*)]; assert syscall.request = LibraryCallRequest( selector=LIBRARY_CALL_L1_HANDLER_SELECTOR, class_hash=class_hash, function_selector=function_selector, calldata_size=calldata_size, - calldata=calldata) + calldata=calldata); %{ syscall_handler.library_call_l1_handler(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let response = syscall.response - - let syscall_ptr = syscall_ptr + LibraryCall.SIZE - return (retdata_size=response.retdata_size, retdata=response.retdata) -end - -const DEPLOY_SELECTOR = 'Deploy' - -# Describes the Deploy system call format. -struct DeployRequest: - # The system call selector (= DEPLOY_SELECTOR). - member selector : felt - # The hash of the class to deploy. - member class_hash : felt - # A salt for the new contract address calculation. - member contract_address_salt : felt - # The size of the calldata for the constructor. - member constructor_calldata_size : felt - # The calldata for the constructor. - member constructor_calldata : felt* - # Used for deterministic contract address deployment. - member deploy_from_zero : felt -end - -struct DeployResponse: - member contract_address : felt - member constructor_retdata_size : felt - member constructor_retdata : felt* -end - -struct Deploy: - member request : DeployRequest - member response : DeployResponse -end - -# Deploys a contract with the given class, and returns its address. -# Fails if a contract with the same parameters was already deployed. -# If 'deploy_from_zero' is 1, the contract address is not affected by the deployer's address. -func deploy{syscall_ptr : felt*}( - class_hash : felt, - contract_address_salt : felt, - constructor_calldata_size : felt, - constructor_calldata : felt*, - deploy_from_zero : felt, -) -> (contract_address : felt): - let syscall = [cast(syscall_ptr, Deploy*)] + let response = syscall.response; + + let syscall_ptr = syscall_ptr + LibraryCall.SIZE; + return (retdata_size=response.retdata_size, retdata=response.retdata); +} + +const DEPLOY_SELECTOR = 'Deploy'; + +// Describes the Deploy system call format. +struct DeployRequest { + // The system call selector (= DEPLOY_SELECTOR). + selector: felt, + // The hash of the class to deploy. + class_hash: felt, + // A salt for the new contract address calculation. + contract_address_salt: felt, + // The size of the calldata for the constructor. + constructor_calldata_size: felt, + // The calldata for the constructor. + constructor_calldata: felt*, + // Used for deterministic contract address deployment. + deploy_from_zero: felt, +} + +struct DeployResponse { + contract_address: felt, + constructor_retdata_size: felt, + constructor_retdata: felt*, +} + +struct Deploy { + request: DeployRequest, + response: DeployResponse, +} + +// Deploys a contract with the given class, and returns its address. +// Fails if a contract with the same parameters was already deployed. +// If 'deploy_from_zero' is 1, the contract address is not affected by the deployer's address. +func deploy{syscall_ptr: felt*}( + class_hash: felt, + contract_address_salt: felt, + constructor_calldata_size: felt, + constructor_calldata: felt*, + deploy_from_zero: felt, +) -> (contract_address: felt) { + let syscall = [cast(syscall_ptr, Deploy*)]; assert syscall.request = DeployRequest( selector=DEPLOY_SELECTOR, class_hash=class_hash, contract_address_salt=contract_address_salt, constructor_calldata_size=constructor_calldata_size, constructor_calldata=constructor_calldata, - deploy_from_zero=deploy_from_zero) + deploy_from_zero=deploy_from_zero); %{ syscall_handler.deploy(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let response = syscall.response - let syscall_ptr = syscall_ptr + Deploy.SIZE - - return (contract_address=response.contract_address) -end - -const GET_CALLER_ADDRESS_SELECTOR = 'GetCallerAddress' - -# Describes the GetCallerAddress system call format. -struct GetCallerAddressRequest: - # The system call selector (= GET_CALLER_ADDRESS_SELECTOR). - member selector : felt -end - -struct GetCallerAddressResponse: - member caller_address : felt -end - -struct GetCallerAddress: - member request : GetCallerAddressRequest - member response : GetCallerAddressResponse -end - -# Returns the address of the calling contract or 0 if this transaction was not initiated by another -# contract. -func get_caller_address{syscall_ptr : felt*}() -> (caller_address : felt): - let syscall = [cast(syscall_ptr, GetCallerAddress*)] - assert syscall.request = GetCallerAddressRequest(selector=GET_CALLER_ADDRESS_SELECTOR) + let response = syscall.response; + let syscall_ptr = syscall_ptr + Deploy.SIZE; + + return (contract_address=response.contract_address); +} + +const GET_CALLER_ADDRESS_SELECTOR = 'GetCallerAddress'; + +// Describes the GetCallerAddress system call format. +struct GetCallerAddressRequest { + // The system call selector (= GET_CALLER_ADDRESS_SELECTOR). + selector: felt, +} + +struct GetCallerAddressResponse { + caller_address: felt, +} + +struct GetCallerAddress { + request: GetCallerAddressRequest, + response: GetCallerAddressResponse, +} + +// Returns the address of the calling contract or 0 if this transaction was not initiated by another +// contract. +func get_caller_address{syscall_ptr: felt*}() -> (caller_address: felt) { + let syscall = [cast(syscall_ptr, GetCallerAddress*)]; + assert syscall.request = GetCallerAddressRequest(selector=GET_CALLER_ADDRESS_SELECTOR); %{ syscall_handler.get_caller_address(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + GetCallerAddress.SIZE - return (caller_address=syscall.response.caller_address) -end - -const GET_SEQUENCER_ADDRESS_SELECTOR = 'GetSequencerAddress' - -# Describes the GetSequencerAddress system call format. -struct GetSequencerAddressRequest: - # The system call selector (= GET_SEQUENCER_ADDRESS_SELECTOR). - member selector : felt -end - -struct GetSequencerAddressResponse: - member sequencer_address : felt -end - -struct GetSequencerAddress: - member request : GetSequencerAddressRequest - member response : GetSequencerAddressResponse -end - -# Returns the address of the sequencer contract. -func get_sequencer_address{syscall_ptr : felt*}() -> (sequencer_address : felt): - let syscall = [cast(syscall_ptr, GetSequencerAddress*)] - assert syscall.request = GetSequencerAddressRequest(selector=GET_SEQUENCER_ADDRESS_SELECTOR) + let syscall_ptr = syscall_ptr + GetCallerAddress.SIZE; + return (caller_address=syscall.response.caller_address); +} + +const GET_SEQUENCER_ADDRESS_SELECTOR = 'GetSequencerAddress'; + +// Describes the GetSequencerAddress system call format. +struct GetSequencerAddressRequest { + // The system call selector (= GET_SEQUENCER_ADDRESS_SELECTOR). + selector: felt, +} + +struct GetSequencerAddressResponse { + sequencer_address: felt, +} + +struct GetSequencerAddress { + request: GetSequencerAddressRequest, + response: GetSequencerAddressResponse, +} + +// Returns the address of the sequencer contract. +func get_sequencer_address{syscall_ptr: felt*}() -> (sequencer_address: felt) { + let syscall = [cast(syscall_ptr, GetSequencerAddress*)]; + assert syscall.request = GetSequencerAddressRequest(selector=GET_SEQUENCER_ADDRESS_SELECTOR); %{ syscall_handler.get_sequencer_address(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + GetSequencerAddress.SIZE - return (sequencer_address=syscall.response.sequencer_address) -end + let syscall_ptr = syscall_ptr + GetSequencerAddress.SIZE; + return (sequencer_address=syscall.response.sequencer_address); +} -const GET_BLOCK_NUMBER_SELECTOR = 'GetBlockNumber' +const GET_BLOCK_NUMBER_SELECTOR = 'GetBlockNumber'; -struct GetBlockNumberRequest: - member selector : felt -end +struct GetBlockNumberRequest { + selector: felt, +} -struct GetBlockNumberResponse: - member block_number : felt -end +struct GetBlockNumberResponse { + block_number: felt, +} -struct GetBlockNumber: - member request : GetBlockNumberRequest - member response : GetBlockNumberResponse -end +struct GetBlockNumber { + request: GetBlockNumberRequest, + response: GetBlockNumberResponse, +} -func get_block_number{syscall_ptr : felt*}() -> (block_number : felt): - let syscall = [cast(syscall_ptr, GetBlockNumber*)] - assert syscall.request = GetBlockNumberRequest(selector=GET_BLOCK_NUMBER_SELECTOR) +func get_block_number{syscall_ptr: felt*}() -> (block_number: felt) { + let syscall = [cast(syscall_ptr, GetBlockNumber*)]; + assert syscall.request = GetBlockNumberRequest(selector=GET_BLOCK_NUMBER_SELECTOR); %{ syscall_handler.get_block_number(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + GetBlockNumber.SIZE - return (block_number=syscall.response.block_number) -end - -const GET_CONTRACT_ADDRESS_SELECTOR = 'GetContractAddress' - -# Describes the GetContractAddress system call format. -struct GetContractAddressRequest: - # The system call selector (= GET_CONTRACT_ADDRESS_SELECTOR). - member selector : felt -end - -struct GetContractAddressResponse: - member contract_address : felt -end - -struct GetContractAddress: - member request : GetContractAddressRequest - member response : GetContractAddressResponse -end - -func get_contract_address{syscall_ptr : felt*}() -> (contract_address : felt): - let syscall = [cast(syscall_ptr, GetContractAddress*)] - assert syscall.request = GetContractAddressRequest(selector=GET_CONTRACT_ADDRESS_SELECTOR) + let syscall_ptr = syscall_ptr + GetBlockNumber.SIZE; + return (block_number=syscall.response.block_number); +} + +const GET_CONTRACT_ADDRESS_SELECTOR = 'GetContractAddress'; + +// Describes the GetContractAddress system call format. +struct GetContractAddressRequest { + // The system call selector (= GET_CONTRACT_ADDRESS_SELECTOR). + selector: felt, +} + +struct GetContractAddressResponse { + contract_address: felt, +} + +struct GetContractAddress { + request: GetContractAddressRequest, + response: GetContractAddressResponse, +} + +func get_contract_address{syscall_ptr: felt*}() -> (contract_address: felt) { + let syscall = [cast(syscall_ptr, GetContractAddress*)]; + assert syscall.request = GetContractAddressRequest(selector=GET_CONTRACT_ADDRESS_SELECTOR); %{ syscall_handler.get_contract_address(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + GetContractAddress.SIZE - return (contract_address=syscall.response.contract_address) -end + let syscall_ptr = syscall_ptr + GetContractAddress.SIZE; + return (contract_address=syscall.response.contract_address); +} -const GET_BLOCK_TIMESTAMP_SELECTOR = 'GetBlockTimestamp' +const GET_BLOCK_TIMESTAMP_SELECTOR = 'GetBlockTimestamp'; -struct GetBlockTimestampRequest: - # The system call selector (= GET_BLOCK_TIMESTAMP_SELECTOR). - member selector : felt -end +struct GetBlockTimestampRequest { + // The system call selector (= GET_BLOCK_TIMESTAMP_SELECTOR). + selector: felt, +} -struct GetBlockTimestampResponse: - member block_timestamp : felt -end +struct GetBlockTimestampResponse { + block_timestamp: felt, +} -struct GetBlockTimestamp: - member request : GetBlockTimestampRequest - member response : GetBlockTimestampResponse -end +struct GetBlockTimestamp { + request: GetBlockTimestampRequest, + response: GetBlockTimestampResponse, +} -func get_block_timestamp{syscall_ptr : felt*}() -> (block_timestamp : felt): - let syscall = [cast(syscall_ptr, GetBlockTimestamp*)] - assert syscall.request = GetBlockTimestampRequest(selector=GET_BLOCK_TIMESTAMP_SELECTOR) +func get_block_timestamp{syscall_ptr: felt*}() -> (block_timestamp: felt) { + let syscall = [cast(syscall_ptr, GetBlockTimestamp*)]; + assert syscall.request = GetBlockTimestampRequest(selector=GET_BLOCK_TIMESTAMP_SELECTOR); %{ syscall_handler.get_block_timestamp(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + GetBlockTimestamp.SIZE - return (block_timestamp=syscall.response.block_timestamp) -end - -const GET_TX_SIGNATURE_SELECTOR = 'GetTxSignature' - -struct GetTxSignatureRequest: - # The system call selector (= GET_TX_SIGNATURE_SELECTOR). - member selector : felt -end - -struct GetTxSignatureResponse: - member signature_len : felt - member signature : felt* -end - -struct GetTxSignature: - member request : GetTxSignatureRequest - member response : GetTxSignatureResponse -end - -# Returns the signature information of the transaction. -# -# NOTE: This function is deprecated. Use get_tx_info() instead. -func get_tx_signature{syscall_ptr : felt*}() -> (signature_len : felt, signature : felt*): - let syscall = [cast(syscall_ptr, GetTxSignature*)] - assert syscall.request = GetTxSignatureRequest(selector=GET_TX_SIGNATURE_SELECTOR) + let syscall_ptr = syscall_ptr + GetBlockTimestamp.SIZE; + return (block_timestamp=syscall.response.block_timestamp); +} + +const GET_TX_SIGNATURE_SELECTOR = 'GetTxSignature'; + +struct GetTxSignatureRequest { + // The system call selector (= GET_TX_SIGNATURE_SELECTOR). + selector: felt, +} + +struct GetTxSignatureResponse { + signature_len: felt, + signature: felt*, +} + +struct GetTxSignature { + request: GetTxSignatureRequest, + response: GetTxSignatureResponse, +} + +// Returns the signature information of the transaction. +// +// NOTE: This function is deprecated. Use get_tx_info() instead. +func get_tx_signature{syscall_ptr: felt*}() -> (signature_len: felt, signature: felt*) { + let syscall = [cast(syscall_ptr, GetTxSignature*)]; + assert syscall.request = GetTxSignatureRequest(selector=GET_TX_SIGNATURE_SELECTOR); %{ syscall_handler.get_tx_signature(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + GetTxSignature.SIZE - return (signature_len=syscall.response.signature_len, signature=syscall.response.signature) -end - -const STORAGE_READ_SELECTOR = 'StorageRead' - -# Describes the StorageRead system call format. -struct StorageReadRequest: - # The system call selector (= STORAGE_READ_SELECTOR). - member selector : felt - member address : felt -end - -struct StorageReadResponse: - member value : felt -end - -struct StorageRead: - member request : StorageReadRequest - member response : StorageReadResponse -end - -func storage_read{syscall_ptr : felt*}(address : felt) -> (value : felt): - let syscall = [cast(syscall_ptr, StorageRead*)] - assert syscall.request = StorageReadRequest(selector=STORAGE_READ_SELECTOR, address=address) + let syscall_ptr = syscall_ptr + GetTxSignature.SIZE; + return (signature_len=syscall.response.signature_len, signature=syscall.response.signature); +} + +const STORAGE_READ_SELECTOR = 'StorageRead'; + +// Describes the StorageRead system call format. +struct StorageReadRequest { + // The system call selector (= STORAGE_READ_SELECTOR). + selector: felt, + address: felt, +} + +struct StorageReadResponse { + value: felt, +} + +struct StorageRead { + request: StorageReadRequest, + response: StorageReadResponse, +} + +func storage_read{syscall_ptr: felt*}(address: felt) -> (value: felt) { + let syscall = [cast(syscall_ptr, StorageRead*)]; + assert syscall.request = StorageReadRequest(selector=STORAGE_READ_SELECTOR, address=address); %{ syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let response = syscall.response - let syscall_ptr = syscall_ptr + StorageRead.SIZE - return (value=response.value) -end + let response = syscall.response; + let syscall_ptr = syscall_ptr + StorageRead.SIZE; + return (value=response.value); +} -const STORAGE_WRITE_SELECTOR = 'StorageWrite' +const STORAGE_WRITE_SELECTOR = 'StorageWrite'; -# Describes the StorageWrite system call format. -struct StorageWrite: - member selector : felt - member address : felt - member value : felt -end +// Describes the StorageWrite system call format. +struct StorageWrite { + selector: felt, + address: felt, + value: felt, +} -func storage_write{syscall_ptr : felt*}(address : felt, value : felt): +func storage_write{syscall_ptr: felt*}(address: felt, value: felt) { assert [cast(syscall_ptr, StorageWrite*)] = StorageWrite( - selector=STORAGE_WRITE_SELECTOR, address=address, value=value) + selector=STORAGE_WRITE_SELECTOR, address=address, value=value); %{ syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + StorageWrite.SIZE - return () -end - -const EMIT_EVENT_SELECTOR = 'EmitEvent' - -# Describes the EmitEvent system call format. -struct EmitEvent: - member selector : felt - member keys_len : felt - member keys : felt* - member data_len : felt - member data : felt* -end - -func emit_event{syscall_ptr : felt*}(keys_len : felt, keys : felt*, data_len : felt, data : felt*): + let syscall_ptr = syscall_ptr + StorageWrite.SIZE; + return (); +} + +const EMIT_EVENT_SELECTOR = 'EmitEvent'; + +// Describes the EmitEvent system call format. +struct EmitEvent { + selector: felt, + keys_len: felt, + keys: felt*, + data_len: felt, + data: felt*, +} + +func emit_event{syscall_ptr: felt*}(keys_len: felt, keys: felt*, data_len: felt, data: felt*) { assert [cast(syscall_ptr, EmitEvent*)] = EmitEvent( - selector=EMIT_EVENT_SELECTOR, keys_len=keys_len, keys=keys, data_len=data_len, data=data) + selector=EMIT_EVENT_SELECTOR, keys_len=keys_len, keys=keys, data_len=data_len, data=data); %{ syscall_handler.emit_event(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let syscall_ptr = syscall_ptr + EmitEvent.SIZE - return () -end - -struct TxInfo: - # The version of the transaction. It is fixed (currently, 0) in the OS, and should be - # signed by the account contract. - # This field allows invalidating old transactions, whenever the meaning of the other - # transaction fields is changed (in the OS). - member version : felt - - # The account contract from which this transaction originates. - member account_contract_address : felt - - # The max_fee field of the transaction. - member max_fee : felt - - # The signature of the transaction. - member signature_len : felt - member signature : felt* - - # The hash of the transaction. - member transaction_hash : felt - - # The identifier of the chain. - # This field can be used to prevent replay of testnet transactions on mainnet. - member chain_id : felt -end - -const GET_TX_INFO_SELECTOR = 'GetTxInfo' - -# Describes the GetTxInfo system call format. -struct GetTxInfoRequest: - # The system call selector (= GET_TX_INFO_SELECTOR). - member selector : felt -end - -struct GetTxInfoResponse: - member tx_info : TxInfo* -end - -struct GetTxInfo: - member request : GetTxInfoRequest - member response : GetTxInfoResponse -end - -func get_tx_info{syscall_ptr : felt*}() -> (tx_info : TxInfo*): - let syscall = [cast(syscall_ptr, GetTxInfo*)] - assert syscall.request = GetTxInfoRequest(selector=GET_TX_INFO_SELECTOR) + let syscall_ptr = syscall_ptr + EmitEvent.SIZE; + return (); +} + +struct TxInfo { + // The version of the transaction. It is fixed (currently, 1) in the OS, and should be + // signed by the account contract. + // This field allows invalidating old transactions, whenever the meaning of the other + // transaction fields is changed (in the OS). + version: felt, + + // The account contract from which this transaction originates. + account_contract_address: felt, + + // The max_fee field of the transaction. + max_fee: felt, + + // The signature of the transaction. + signature_len: felt, + signature: felt*, + + // The hash of the transaction. + transaction_hash: felt, + + // The identifier of the chain. + // This field can be used to prevent replay of testnet transactions on mainnet. + chain_id: felt, + + // The transaction's nonce. + nonce: felt, +} + +const GET_TX_INFO_SELECTOR = 'GetTxInfo'; + +// Describes the GetTxInfo system call format. +struct GetTxInfoRequest { + // The system call selector (= GET_TX_INFO_SELECTOR). + selector: felt, +} + +struct GetTxInfoResponse { + tx_info: TxInfo*, +} + +struct GetTxInfo { + request: GetTxInfoRequest, + response: GetTxInfoResponse, +} + +func get_tx_info{syscall_ptr: felt*}() -> (tx_info: TxInfo*) { + let syscall = [cast(syscall_ptr, GetTxInfo*)]; + assert syscall.request = GetTxInfoRequest(selector=GET_TX_INFO_SELECTOR); %{ syscall_handler.get_tx_info(segments=segments, syscall_ptr=ids.syscall_ptr) %} - let response = syscall.response - let syscall_ptr = syscall_ptr + GetTxInfo.SIZE - return (tx_info=response.tx_info) -end + let response = syscall.response; + let syscall_ptr = syscall_ptr + GetTxInfo.SIZE; + return (tx_info=response.tx_info); +} diff --git a/src/starkware/starknet/compiler/CMakeLists.txt b/src/starkware/starknet/compiler/CMakeLists.txt index ab1875e7..b36ec9ac 100644 --- a/src/starkware/starknet/compiler/CMakeLists.txt +++ b/src/starkware/starknet/compiler/CMakeLists.txt @@ -1,7 +1,3 @@ -if (NOT DEFINED CAIRO_PYTHON_INTERPRETER) - set(CAIRO_PYTHON_INTERPRETER python3.7) -endif() - python_lib(starknet_compile_lib PREFIX starkware/starknet/compiler @@ -30,6 +26,9 @@ python_lib(starknet_compile_lib pip_typing_extensions ) +set(STARKNET_COMPILE_LIB starknet_compile_lib) +include(compiler.cmake) + python_lib(starknet_compile_test_utils_lib PREFIX starkware/starknet/compiler @@ -44,9 +43,9 @@ python_lib(starknet_compile_test_utils_lib ) full_python_test(starknet_compile_test + PREFIX starkware/starknet/compiler PYTHON ${CAIRO_PYTHON_INTERPRETER} TESTED_MODULES starkware/starknet/compiler - PREFIX starkware/starknet/compiler FILES data_encoder_test.py @@ -55,6 +54,7 @@ full_python_test(starknet_compile_test external_wrapper_test.py starknet_preprocessor_test.py storage_var_test.py + validation_utils_test.py LIBS cairo_compile_test_utils_lib @@ -62,15 +62,3 @@ full_python_test(starknet_compile_test starknet_compile_lib pip_pytest ) - -python_venv(starknet_compile_venv - PYTHON ${CAIRO_PYTHON_INTERPRETER} - - LIBS - starknet_compile_lib -) - -python_exe(starknet_compile_exe - VENV starknet_compile_venv - MODULE starkware.starknet.compiler.compile -) diff --git a/src/starkware/starknet/compiler/compile.py b/src/starkware/starknet/compiler/compile.py index 30c0b20e..bc8f6d1b 100644 --- a/src/starkware/starknet/compiler/compile.py +++ b/src/starkware/starknet/compiler/compile.py @@ -108,10 +108,12 @@ def compile_starknet_files( debug_info: bool = False, disable_hint_validation: bool = False, cairo_path: Optional[List[str]] = None, + opt_unused_functions: bool = True, filter_identifiers: bool = True, ) -> ContractClass: return compile_starknet_codes( codes=get_codes(files), + opt_unused_functions=opt_unused_functions, debug_info=debug_info, disable_hint_validation=disable_hint_validation, cairo_path=cairo_path, @@ -124,6 +126,7 @@ def compile_starknet_codes( debug_info: bool = False, disable_hint_validation: bool = False, cairo_path: Optional[List[str]] = None, + opt_unused_functions: bool = True, filter_identifiers: bool = True, ) -> ContractClass: if cairo_path is None: @@ -134,6 +137,7 @@ def compile_starknet_codes( prime=DEFAULT_PRIME, read_module=module_reader.read, disable_hint_validation=disable_hint_validation, + opt_unused_functions=opt_unused_functions, ) program, preprocessed = compile_cairo_ex( diff --git a/src/starkware/starknet/compiler/compiler.cmake b/src/starkware/starknet/compiler/compiler.cmake new file mode 100644 index 00000000..cdf9ac4e --- /dev/null +++ b/src/starkware/starknet/compiler/compiler.cmake @@ -0,0 +1,18 @@ +if (NOT DEFINED CAIRO_PYTHON_INTERPRETER) + set(CAIRO_PYTHON_INTERPRETER python3.9) +endif() +if (NOT DEFINED STARKNET_COMPILE_LIB) + set(STARKNET_COMPILE_LIB pip_cairo_lang) +endif() + +python_venv(starknet_compile_venv + PYTHON ${CAIRO_PYTHON_INTERPRETER} + + LIBS + ${STARKNET_COMPILE_LIB} +) + +python_exe(starknet_compile_exe + VENV starknet_compile_venv + MODULE starkware.starknet.compiler.compile +) diff --git a/src/starkware/starknet/compiler/contract_interface.py b/src/starkware/starknet/compiler/contract_interface.py index 3353a811..16dbbe84 100644 --- a/src/starkware/starknet/compiler/contract_interface.py +++ b/src/starkware/starknet/compiler/contract_interface.py @@ -3,6 +3,7 @@ from typing_extensions import Protocol +from starkware.cairo.lang.compiler.ast.cairo_types import TypeTuple from starkware.cairo.lang.compiler.ast.code_elements import ( CodeBlock, CodeElementEmptyLine, @@ -19,6 +20,7 @@ autogen_parse_code_block, verify_empty_code_block, ) +from starkware.python.utils import as_non_optional from starkware.starknet.compiler.data_encoder import ArgumentInfo, EncodingType, decode_data from starkware.starknet.compiler.validation_utils import ( encode_calldata_arguments, @@ -148,7 +150,7 @@ def from_code_element(elm: CodeElementFunction) -> "ContractInterfaceInfo": def process_function_selector(function_info: ContractFunctionInfo) -> List[CommentedCodeElement]: code = f"""\ -const {function_info.selector} = {get_selector_from_name(function_info.name)} +const {function_info.selector} = {get_selector_from_name(function_info.name)}; """ code_block = autogen_parse_code_block( path=function_info.autogen_code_name, @@ -167,9 +169,9 @@ def process_contract_function( func_name = f"{'library_call_' if is_library_call else ''}{function_info.name}" argument_name = _get_argument_name(is_library_call=is_library_call) code = f"""\ -func {func_name}{{syscall_ptr : felt*, range_check_ptr}}( - {argument_name} : felt): -end +func {func_name}{{syscall_ptr: felt*, range_check_ptr}}( + {argument_name}: felt) {{ +}} """ code_block = autogen_parse_code_block( @@ -202,11 +204,11 @@ def generate_contract_interface_namespace( ) -> CodeElementFunction: contract_name = contract_info.name code = f"""\ -namespace {contract_name}: +namespace {contract_name} {{ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.memcpy import memcpy from starkware.starknet.common.syscalls import call_contract, library_call -end +}} """ code_block = autogen_parse_code_block( @@ -271,12 +273,12 @@ def generate_contract_function_body( # and the dependency graph. # Those statements will later be replaced by the real implementation. code = f""" -let calldata_ptr_start = 0 -let retdata_size = 0 -let retdata = 0 -call alloc -call memcpy -call {_get_syscall_name(is_library_call=is_library_call)} +let calldata_ptr_start = 0; +let retdata_size = 0; +let retdata = 0; +call alloc; +call memcpy; +call {_get_syscall_name(is_library_call=is_library_call)}; """ return autogen_parse_code_block( path=function_info.autogen_code_name, @@ -324,9 +326,9 @@ def get_code_elements(code: str) -> List[CommentedCodeElement]: code_elements: List[CommentedCodeElement] = [] code_elements += get_code_elements( code=f""" -alloc_locals -let (local calldata_ptr_start : felt*) = alloc() -let __calldata_ptr = calldata_ptr_start +alloc_locals; +let (local calldata_ptr_start: felt*) = alloc(); +let __calldata_ptr = calldata_ptr_start; """ ) @@ -342,7 +344,7 @@ def get_code_elements(code: str) -> List[CommentedCodeElement]: {argument_name}={argument_name}, function_selector={function_info.selector}, calldata_size=__calldata_ptr - calldata_ptr_start, - calldata=calldata_ptr_start) + calldata=calldata_ptr_start); """ ) @@ -350,13 +352,25 @@ def get_code_elements(code: str) -> List[CommentedCodeElement]: return_str = "" if function_info.elm.returns is not None: + returns = self.resolve_type(cairo_type=function_info.elm.returns) + if not isinstance(returns, TypeTuple): + raise PreprocessorError( + "Only tuple types are supported as the return type of external functions.", + location=returns.location, + ) + + for item in returns.members: + if item.name is None: + raise PreprocessorError( + "A return value in an interface must be named.", location=item.location + ) rets = [ ArgumentInfo( - name=typed_identifier.identifier.name, - cairo_type=self.resolve_type(typed_identifier.get_type()), - location=non_optional_location(typed_identifier.identifier.location), + name=as_non_optional(item.name), + cairo_type=self.resolve_type(item.typ), + location=non_optional_location(item.location), ) - for typed_identifier in function_info.elm.returns.identifiers + for item in returns.members ] ret_elements, ret_arg_list = decode_data( data_ptr="retdata", @@ -373,7 +387,7 @@ def get_code_elements(code: str) -> List[CommentedCodeElement]: code_elements += get_code_elements( code=f""" -return ({return_str}) +return ({return_str}); """ ) diff --git a/src/starkware/starknet/compiler/contract_interface_test.py b/src/starkware/starknet/compiler/contract_interface_test.py index 4c87f55b..8901ab97 100644 --- a/src/starkware/starknet/compiler/contract_interface_test.py +++ b/src/starkware/starknet/compiler/contract_interface_test.py @@ -7,20 +7,30 @@ def test_contract_interface_success(): selector = get_selector_from_name("foo") usage_code = """ -struct MyStruct: - member a: felt - member b: (felt, felt) -end +struct MyStruct { + a: felt, + b: (felt, felt), +} -func main{syscall_ptr : felt*, range_check_ptr}(): +func main{syscall_ptr: felt*, range_check_ptr}() { let (y0, y1) = Contract.foo( - contract_address=0, x=0, arr_len=0, arr=cast(0, felt*), struct_arr_len=1, - struct_arr=cast(0, MyStruct*)) + contract_address=0, + x=0, + arr_len=0, + arr=cast(0, felt*), + struct_arr_len=1, + struct_arr=cast(0, MyStruct*), + ); let (y2, y3) = Contract.library_call_foo( - class_hash=0, x=0, arr_len=0, arr=cast(0, felt*), struct_arr_len=1, - struct_arr=cast(0, MyStruct*)) - return () -end + class_hash=0, + x=0, + arr_len=0, + arr=cast(0, felt*), + struct_arr_len=1, + struct_arr=cast(0, MyStruct*), + ); + return (); +} """ code = f""" @@ -29,55 +39,55 @@ def test_contract_interface_success(): {usage_code} @contract_interface -namespace Contract: +namespace Contract {{ func foo( - x : felt, arr_len : felt, arr : felt*, struct_arr_len : felt, - struct_arr : MyStruct*) -> (y0 : felt, y1 : felt): - end -end + x: felt, arr_len: felt, arr: felt*, struct_arr_len: felt, + struct_arr: MyStruct*) -> (y0: felt, y1: felt) {{ + }} +}} """ expected_array_encoding = """ - assert [__calldata_ptr] = {arr_name}_len - let __calldata_ptr = __calldata_ptr + 1 - # Check that the length is non-negative. - assert [range_check_ptr] = {arr_name}_len - # Store the updated range_check_ptr as a local variable to keep it available after - # the memcpy. - local range_check_ptr = range_check_ptr + 1 - # Keep a reference to __calldata_ptr. - let __calldata_ptr_copy = __calldata_ptr - # Store the updated __calldata_ptr as a local variable to keep it available after - # the memcpy. - local __calldata_ptr : felt* = __calldata_ptr + {arr_name}_len * {elm_size} - memcpy(dst=__calldata_ptr_copy, src={arr_name}, len={arr_name}_len * {elm_size}) + assert [__calldata_ptr] = {arr_name}_len; + let __calldata_ptr = __calldata_ptr + 1; + // Check that the length is non-negative. + assert [range_check_ptr] = {arr_name}_len; + // Store the updated range_check_ptr as a local variable to keep it available after + // the memcpy. + local range_check_ptr = range_check_ptr + 1; + // Keep a reference to __calldata_ptr. + let __calldata_ptr_copy = __calldata_ptr; + // Store the updated __calldata_ptr as a local variable to keep it available after + // the memcpy. + local __calldata_ptr: felt* = __calldata_ptr + {arr_name}_len * {elm_size}; + memcpy(dst=__calldata_ptr_copy, src={arr_name}, len={arr_name}_len * {elm_size}); """ expected_function_code = """ - func {library_call_prefix}foo{{syscall_ptr : felt*, range_check_ptr}}( - {argument_name} : felt, x : felt, arr_len : felt, arr : felt*, - struct_arr_len : felt, struct_arr : MyStruct*) -> (y0 : felt, y1 : felt): - alloc_locals - let (local calldata_ptr_start : felt*) = alloc() - let __calldata_ptr = calldata_ptr_start - assert [__calldata_ptr] = x - let __calldata_ptr = __calldata_ptr + 1 + func {library_call_prefix}foo{{syscall_ptr: felt*, range_check_ptr}}( + {argument_name}: felt, x: felt, arr_len: felt, arr: felt*, + struct_arr_len: felt, struct_arr: MyStruct*) -> (y0: felt, y1: felt) {{ + alloc_locals; + let (local calldata_ptr_start: felt*) = alloc(); + let __calldata_ptr = calldata_ptr_start; + assert [__calldata_ptr] = x; + let __calldata_ptr = __calldata_ptr + 1; {felt_array_encoding} {struct_array_encoding} let (retdata_size, retdata) = {syscall_function}( {argument_name}={argument_name}, function_selector={selector}, calldata_size=__calldata_ptr - calldata_ptr_start, - calldata=calldata_ptr_start) - let __return_value_ptr = retdata - let y0 = [__return_value_ptr] - let __return_value_ptr = __return_value_ptr + 1 - let y1 = [__return_value_ptr] - let __return_value_ptr = __return_value_ptr + 1 - let __return_value_actual_size = __return_value_ptr - cast(retdata, felt*) - assert retdata_size = __return_value_actual_size - return (y0, y1) - end + calldata=calldata_ptr_start); + let __return_value_ptr = retdata; + let y0 = [__return_value_ptr]; + let __return_value_ptr = __return_value_ptr + 1; + let y1 = [__return_value_ptr]; + let __return_value_ptr = __return_value_ptr + 1; + let __return_value_actual_size = __return_value_ptr - cast(retdata, felt*); + assert retdata_size = __return_value_actual_size; + return (y0, y1); + }} """ expected_function_code_format = functools.partial( @@ -89,32 +99,32 @@ def test_contract_interface_success(): expected_code = f""" %lang starknet -# Dummy library functions. +// Dummy library functions. -func alloc() -> (ptr : felt*): - ret -end +func alloc() -> (ptr: felt*) {{ + ret; +}} -func memcpy(dst : felt*, src : felt*, len): - ap += [ap] - ret -end +func memcpy(dst: felt*, src: felt*, len) {{ + ap += [ap]; + ret; +}} -func call_contract{{syscall_ptr : felt*}}( - contract_address : felt, function_selector : felt, calldata_size : felt, - calldata : felt*) -> (retdata_size : felt, retdata : felt*): - ret -end +func call_contract{{syscall_ptr: felt*}}( + contract_address: felt, function_selector: felt, calldata_size: felt, + calldata: felt*) -> (retdata_size: felt, retdata: felt*) {{ + ret; +}} -func library_call{{syscall_ptr : felt*}}( - class_hash : felt, function_selector : felt, calldata_size : felt, - calldata : felt*) -> (retdata_size : felt, retdata : felt*): - ret -end +func library_call{{syscall_ptr: felt*}}( + class_hash: felt, function_selector: felt, calldata_size: felt, + calldata: felt*) -> (retdata_size: felt, retdata: felt*) {{ + ret; +}} {usage_code} -namespace Contract: +namespace Contract {{ {expected_function_code_format( library_call_prefix='', syscall_function='call_contract', @@ -128,7 +138,7 @@ def test_contract_interface_success(): argument_name='class_hash', selector=selector )} -end +}} """ program = preprocess_str(code) expected_program = preprocess_str(expected_code) @@ -140,8 +150,8 @@ def test_contract_interface_failures(): verify_exception( """ @contract_interface -namespace Contract: -end +namespace Contract { +} """, """ file:?:?: @contract_interface can only be used in source files that contain the \ @@ -155,12 +165,12 @@ def test_contract_interface_failures(): %lang starknet @contract_interface @another_decorator -func f(): -end +func f() { +} """, """ file:?:?: @contract_interface can only be used with namespaces. -func f(): +func f() { ^ """, ) @@ -169,8 +179,8 @@ def test_contract_interface_failures(): %lang starknet @contract_interface @another_decorator -namespace f: -end +namespace f { +} """, """ file:?:?: Unexpected decorator for a contract interface. @@ -182,14 +192,14 @@ def test_contract_interface_failures(): """ %lang starknet @contract_interface -namespace f: - const X = 0 -end +namespace f { + const X = 0; +} """, """ file:?:?: Only functions are supported within a contract interface. - const X = 0 - ^*********^ + const X = 0; + ^**********^ """, ) @@ -198,16 +208,16 @@ def test_contract_interface_function_failures(): template = """ %lang starknet @contract_interface -namespace f: +namespace f {{ {} -end +}} """ verify_exception( template.format( """ @decorator -func foo(): -end +func foo() { +} """ ), """ @@ -219,41 +229,41 @@ def test_contract_interface_function_failures(): verify_exception( template.format( """ -func foo(): - # Empty line. - const X = 0 -end +func foo() { + // Empty line. + const X = 0; +} """ ), """ file:?:?: Contract interface functions must have an empty body. - const X = 0 - ^*********^ + const X = 0; + ^**********^ """, ) verify_exception( template.format( """ -func foo{x}(): -end +func foo{x}() { +} """ ), """ file:?:?: Contract interface functions must have no implicit arguments. -func foo{x}(): +func foo{x}() { ^ """, ) verify_exception( template.format( """ -func foo(arr : felt*): -end +func foo(arr: felt*) { +} """ ), """ file:?:?: Array argument "arr" must be preceded by a length argument named "arr_len" of type felt. -func foo(arr : felt*): +func foo(arr: felt*) { ^*^ """, ) @@ -265,25 +275,103 @@ def test_missing_range_check_ptr(): %lang starknet @contract_interface -namespace Contract: - func foo(): - end -end - -func test{syscall_ptr : felt*}(): - Contract.foo(contract_address=0) - return() -end +namespace Contract { + func foo() { + } +} + +func test{syscall_ptr: felt*}() { + Contract.foo(contract_address=0); + return (); +} """, """ file:?:?: While trying to retrieve the implicit argument 'range_check_ptr' in: - Contract.foo(contract_address=0) + Contract.foo(contract_address=0); ^******************************^ file:?:?: While handling contract interface function: - func foo(): + func foo() { ^*^ file:?:?: Unknown identifier 'range_check_ptr'. -func foo{syscall_ptr : felt*, range_check_ptr}( - ^*************^ +func foo{syscall_ptr: felt*, range_check_ptr}( + ^*************^ +""", + ) + + +def test_unnamed_return_type_in_interface(): + verify_exception( + """ +%lang starknet + +@contract_interface +namespace Contract { + func fc() -> (felt, felt) { + } +} +""", + """ +file:?:?: A return value in an interface must be named. + func fc() -> (felt, felt) { + ^**^ +""", + ) + + +def test_non_tuple_return_in_interface(): + verify_exception( + """ +%lang starknet + +@contract_interface +namespace Contract { + func fc() -> felt { + } +} +""", + """ +file:?:?: Only tuple types are supported as the return type of external functions. + func fc() -> felt { + ^**^ """, ) + + +def test_returned_type_alias_in_interface(): + program1 = preprocess_str( + """ +%lang starknet + +using A = (a: felt, b: (felt, felt)); + +@contract_interface +namespace Contract { + func f() -> A { + } +} + +func foo{syscall_ptr: felt*, range_check_ptr}() -> (val: felt) { + let res = Contract.f(contract_address=0); + return (val=res.b[0]); +} +""" + ) + + program2 = preprocess_str( + """ +%lang starknet + +@contract_interface +namespace Contract { + func f() -> (a: felt, b: (felt, felt)) { + } +} + +func foo{syscall_ptr: felt*, range_check_ptr}() -> (val: felt) { + let res = Contract.f(contract_address=0); + return (val=res.b[0]); +} +""" + ) + + assert program1.format() == program2.format() diff --git a/src/starkware/starknet/compiler/data_encoder.py b/src/starkware/starknet/compiler/data_encoder.py index 78d2913c..93e4adb1 100644 --- a/src/starkware/starknet/compiler/data_encoder.py +++ b/src/starkware/starknet/compiler/data_encoder.py @@ -59,7 +59,8 @@ def tuple_type_to_argument_info_list(cairo_type: TypeTuple) -> List[ArgumentInfo res = [] for member in cairo_type.members: assert member.location is not None - assert member.name is not None + assert member.name is not None, "tuple_type_to_argument_info_list expects a named tuple." + res.append(ArgumentInfo(name=member.name, cairo_type=member.typ, location=member.location)) return res @@ -253,7 +254,7 @@ def __init__( def pre_process(self): self.add_code( f"""\ -let __{self.var_name}_ptr : felt* = cast({self.data_ptr}, felt*) +let __{self.var_name}_ptr: felt* = cast({self.data_ptr}, felt*); """, parent_location=self.struct_parent_location, ) @@ -261,21 +262,21 @@ def pre_process(self): def post_process(self): self.add_code( f"""\ -let __{self.var_name}_actual_size = __{self.var_name}_ptr - cast({self.data_ptr}, felt*) +let __{self.var_name}_actual_size = __{self.var_name}_ptr - cast({self.data_ptr}, felt*); """, parent_location=self.struct_parent_location, ) self.add_code( f"""\ -assert {self.data_size} = __{self.var_name}_actual_size +assert {self.data_size} = __{self.var_name}_actual_size; """, parent_location=self.struct_parent_location, ) def process_felt(self, arg_info: ArgumentInfo): return f"""\ -let __{self.var_name}_arg_{arg_info.name} = [__{self.var_name}_ptr] -let __{self.var_name}_ptr = __{self.var_name}_ptr + 1 +let __{self.var_name}_arg_{arg_info.name} = [__{self.var_name}_ptr]; +let __{self.var_name}_ptr = __{self.var_name}_ptr + 1; """ def process_array(self, arg_info: ArgumentInfo, elm_size: int): @@ -283,21 +284,21 @@ def process_array(self, arg_info: ArgumentInfo, elm_size: int): var = f"__{self.var_name}_arg_{arg_info.name}" len_var = f"__{self.var_name}_arg_{arg_info.name}_len" return f"""\ -# Check that the length is non-negative. -assert [range_check_ptr] = {len_var} -let range_check_ptr = range_check_ptr + 1 -# Create the reference. -let {var} = cast(__{self.var_name}_ptr, {type_str}) -# Use 'tempvar' instead of 'let' to avoid repeating this computation for the -# following arguments. -tempvar __{self.var_name}_ptr = __{self.var_name}_ptr + {len_var} * {elm_size} +// Check that the length is non-negative. +assert [range_check_ptr] = {len_var}; +let range_check_ptr = range_check_ptr + 1; +// Create the reference. +let {var} = cast(__{self.var_name}_ptr, {type_str}); +// Use 'tempvar' instead of 'let' to avoid repeating this computation for the +// following arguments. +tempvar __{self.var_name}_ptr = __{self.var_name}_ptr + {len_var} * {elm_size}; """ def process_felts_object(self, arg_info: ArgumentInfo, size: int): return f"""\ let __{self.var_name}_arg_{arg_info.name} = [ - cast(__{self.var_name}_ptr, {TypePointer(pointee=arg_info.cairo_type).format()})] -let __{self.var_name}_ptr = __{self.var_name}_ptr + {size} + cast(__{self.var_name}_ptr, {TypePointer(pointee=arg_info.cairo_type).format()})]; +let __{self.var_name}_ptr = __{self.var_name}_ptr + {size}; """ @@ -363,40 +364,40 @@ def __init__( def process_felt(self, arg_info: ArgumentInfo): return f"""\ -assert [__{self.var_name}_ptr] = {self.arg_name_func(arg_info)} -let __{self.var_name}_ptr = __{self.var_name}_ptr + 1 +assert [__{self.var_name}_ptr] = {self.arg_name_func(arg_info)}; +let __{self.var_name}_ptr = __{self.var_name}_ptr + 1; """ def process_array(self, arg_info: ArgumentInfo, elm_size: int): len_var = f"{self.arg_name_func(arg_info)}_len" self.known_ap_change = False return f"""\ -# Check that the length is non-negative. -assert [range_check_ptr] = {len_var} -# Store the updated range_check_ptr as a local variable to keep it available after -# the memcpy. -local range_check_ptr = range_check_ptr + 1 -# Keep a reference to __{self.var_name}_ptr. -let __{self.var_name}_ptr_copy = __{self.var_name}_ptr -# Store the updated __{self.var_name}_ptr as a local variable to keep it available after -# the memcpy. -local __{self.var_name}_ptr : felt* = __{self.var_name}_ptr + {len_var} * {elm_size} +// Check that the length is non-negative. +assert [range_check_ptr] = {len_var}; +// Store the updated range_check_ptr as a local variable to keep it available after +// the memcpy. +local range_check_ptr = range_check_ptr + 1; +// Keep a reference to __{self.var_name}_ptr. +let __{self.var_name}_ptr_copy = __{self.var_name}_ptr; +// Store the updated __{self.var_name}_ptr as a local variable to keep it available after +// the memcpy. +local __{self.var_name}_ptr: felt* = __{self.var_name}_ptr + {len_var} * {elm_size}; memcpy( dst=__{self.var_name}_ptr_copy, src={self.arg_name_func(arg_info)}, - len={len_var} * {elm_size}) + len={len_var} * {elm_size}); """ def process_felts_object(self, arg_info: ArgumentInfo, size: int): body = "\n".join( - f"assert [__{self.var_name}_ptr + {i}] = [__{self.var_name}_tmp + {i}]" + f"assert [__{self.var_name}_ptr + {i}] = [__{self.var_name}_tmp + {i}];" for i in range(size) ) return f"""\ -# Create a reference to {self.arg_name_func(arg_info)} as felt*. -let __{self.var_name}_tmp : felt* = cast(&{self.arg_name_func(arg_info)}, felt*) +// Create a reference to {self.arg_name_func(arg_info)} as felt*. +let __{self.var_name}_tmp: felt* = cast(&{self.arg_name_func(arg_info)}, felt*); {body} -let __{self.var_name}_ptr = __{self.var_name}_ptr + {size} +let __{self.var_name}_ptr = __{self.var_name}_ptr + {size}; """ diff --git a/src/starkware/starknet/compiler/data_encoder_test.py b/src/starkware/starknet/compiler/data_encoder_test.py index ed26605d..e07ebf09 100644 --- a/src/starkware/starknet/compiler/data_encoder_test.py +++ b/src/starkware/starknet/compiler/data_encoder_test.py @@ -41,10 +41,10 @@ def dummy_location(): def identifiers_for_testing() -> IdentifierManager: return preprocess_str( """ -struct MyStruct: - member x : felt - member y : felt -end +struct MyStruct { + x: felt, + y: felt, +} """, prime=DEFAULT_PRIME, ).identifiers @@ -87,29 +87,29 @@ def test_decode_data_flow(): assert ( "".join(code_element.format(100) + "\n" for code_element in code_elements) == """\ -let __calldata_ptr : felt* = cast(data_ptr, felt*) +let __calldata_ptr: felt* = cast(data_ptr, felt*); -let __calldata_arg_a_len = [__calldata_ptr] -let __calldata_ptr = __calldata_ptr + 1 +let __calldata_arg_a_len = [__calldata_ptr]; +let __calldata_ptr = __calldata_ptr + 1; -# Check that the length is non-negative. -assert [range_check_ptr] = __calldata_arg_a_len -let range_check_ptr = range_check_ptr + 1 -# Create the reference. -let __calldata_arg_a = cast(__calldata_ptr, (test_scope.MyStruct, (felt, felt))*) -# Use 'tempvar' instead of 'let' to avoid repeating this computation for the -# following arguments. -tempvar __calldata_ptr = __calldata_ptr + __calldata_arg_a_len * 4 +// Check that the length is non-negative. +assert [range_check_ptr] = __calldata_arg_a_len; +let range_check_ptr = range_check_ptr + 1; +// Create the reference. +let __calldata_arg_a = cast(__calldata_ptr, (test_scope.MyStruct, (felt, felt))*); +// Use 'tempvar' instead of 'let' to avoid repeating this computation for the +// following arguments. +tempvar __calldata_ptr = __calldata_ptr + __calldata_arg_a_len * 4; -let __calldata_arg_b = [__calldata_ptr] -let __calldata_ptr = __calldata_ptr + 1 +let __calldata_arg_b = [__calldata_ptr]; +let __calldata_ptr = __calldata_ptr + 1; let __calldata_arg_c = [ - cast(__calldata_ptr, (felt, (felt, felt))*)] -let __calldata_ptr = __calldata_ptr + 3 + cast(__calldata_ptr, (felt, (felt, felt))*)]; +let __calldata_ptr = __calldata_ptr + 3; -let __calldata_actual_size = __calldata_ptr - cast(data_ptr, felt*) -assert data_size = __calldata_actual_size +let __calldata_actual_size = __calldata_ptr - cast(data_ptr, felt*); +assert data_size = __calldata_actual_size; """.replace( "\n\n", "\n" ) @@ -130,8 +130,8 @@ def test_decode_data_flow(): code_elements, expr = run_decode_data(arguments, encoding_type=EncodingType.RETURN) assert "".join(code_element.format(100) + "\n" for code_element in code_elements).startswith( """\ -let __return_value_ptr : felt* = cast(data_ptr, felt*) -let __return_value_arg_a_len = [__return_value_ptr] +let __return_value_ptr: felt* = cast(data_ptr, felt*); +let __return_value_arg_a_len = [__return_value_ptr]; """ ) assert code_elements[0].code_elm.expr.location.parent_location == ( @@ -205,30 +205,30 @@ def test_encode_data_for_return(): assert ( "".join(code_element.format(100) + "\n" for code_element in code_elements) == """\ -assert [__return_value_ptr] = x.a -let __return_value_ptr = __return_value_ptr + 1 - -assert [__return_value_ptr] = x.b_len -let __return_value_ptr = __return_value_ptr + 1 - -# Check that the length is non-negative. -assert [range_check_ptr] = x.b_len -# Store the updated range_check_ptr as a local variable to keep it available after -# the memcpy. -local range_check_ptr = range_check_ptr + 1 -# Keep a reference to __return_value_ptr. -let __return_value_ptr_copy = __return_value_ptr -# Store the updated __return_value_ptr as a local variable to keep it available after -# the memcpy. -local __return_value_ptr : felt* = __return_value_ptr + x.b_len * 3 -memcpy(dst=__return_value_ptr_copy, src=x.b, len=x.b_len * 3) - -# Create a reference to x.c as felt*. -let __return_value_tmp : felt* = cast(&x.c, felt*) -assert [__return_value_ptr + 0] = [__return_value_tmp + 0] -assert [__return_value_ptr + 1] = [__return_value_tmp + 1] -assert [__return_value_ptr + 2] = [__return_value_tmp + 2] -let __return_value_ptr = __return_value_ptr + 3 +assert [__return_value_ptr] = x.a; +let __return_value_ptr = __return_value_ptr + 1; + +assert [__return_value_ptr] = x.b_len; +let __return_value_ptr = __return_value_ptr + 1; + +// Check that the length is non-negative. +assert [range_check_ptr] = x.b_len; +// Store the updated range_check_ptr as a local variable to keep it available after +// the memcpy. +local range_check_ptr = range_check_ptr + 1; +// Keep a reference to __return_value_ptr. +let __return_value_ptr_copy = __return_value_ptr; +// Store the updated __return_value_ptr as a local variable to keep it available after +// the memcpy. +local __return_value_ptr: felt* = __return_value_ptr + x.b_len * 3; +memcpy(dst=__return_value_ptr_copy, src=x.b, len=x.b_len * 3); + +// Create a reference to x.c as felt*. +let __return_value_tmp: felt* = cast(&x.c, felt*); +assert [__return_value_ptr + 0] = [__return_value_tmp + 0]; +assert [__return_value_ptr + 1] = [__return_value_tmp + 1]; +assert [__return_value_ptr + 2] = [__return_value_tmp + 2]; +let __return_value_ptr = __return_value_ptr + 3; """.replace( "\n\n", "\n" ) diff --git a/src/starkware/starknet/compiler/event.py b/src/starkware/starknet/compiler/event.py index ed9a1f9b..49d1b989 100644 --- a/src/starkware/starknet/compiler/event.py +++ b/src/starkware/starknet/compiler/event.py @@ -99,13 +99,13 @@ def generate_event_namespace( ) -> CodeElementFunction: event_name = event_info.elm.identifier.name code = f"""\ -namespace {event_name}: +namespace {event_name} {{ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.memcpy import memcpy from starkware.starknet.common.syscalls import emit_event - const SELECTOR = {get_selector_from_name(event_name)} -end + const SELECTOR = {get_selector_from_name(event_name)}; +}} """ # Generate the namespace without the functions. @@ -125,8 +125,8 @@ def generate_event_namespace( def process_event(event_info: EventInfo, emit_func_body: CodeBlock) -> List[CommentedCodeElement]: code = """\ -func emit{syscall_ptr : felt*, range_check_ptr}(): -end +func emit{syscall_ptr: felt*, range_check_ptr}() { +} """ # Generate an empty emit function. @@ -171,11 +171,11 @@ def generate_emit_function_body(self, event_info: EventInfo) -> CodeBlock: # and the dependency graph. # Those statements will later be replaced by the real implementation. code = """\ -let __keys_ptr = 0 -let __data_ptr = 0 -call alloc -call memcpy -call emit_event +let __keys_ptr = 0; +let __data_ptr = 0; +call alloc; +call memcpy; +call emit_event; """ return event_info.parse_code_block(code=code) @@ -202,11 +202,11 @@ def visit_CodeElementFunction(self, elm: CodeElementFunction): def generate_emit_function_body(self, event_info: EventInfo) -> CodeBlock: code_elements = event_info.parse_code_block( code="""\ -alloc_locals -let (local __keys_ptr : felt*) = alloc() -assert [__keys_ptr] = SELECTOR -let (local __data_ptr : felt*) = alloc() -let __calldata_ptr = __data_ptr +alloc_locals; +let (local __keys_ptr: felt*) = alloc(); +assert [__keys_ptr] = SELECTOR; +let (local __data_ptr: felt*) = alloc(); +let __calldata_ptr = __data_ptr; """ ).code_elements @@ -215,8 +215,8 @@ def generate_emit_function_body(self, event_info: EventInfo) -> CodeBlock: # Add the emit_event system call. code_elements += event_info.parse_code_block( code="""\ -emit_event(keys_len=1, keys=__keys_ptr, data_len=__calldata_ptr - __data_ptr, data=__data_ptr) -return () +emit_event(keys_len=1, keys=__keys_ptr, data_len=__calldata_ptr - __data_ptr, data=__data_ptr); +return (); """ ).code_elements diff --git a/src/starkware/starknet/compiler/event_test.py b/src/starkware/starknet/compiler/event_test.py index 2d5752e3..b533a80b 100644 --- a/src/starkware/starknet/compiler/event_test.py +++ b/src/starkware/starknet/compiler/event_test.py @@ -4,69 +4,69 @@ def test_event_success(): usage_code = """ -func main{syscall_ptr : felt*, range_check_ptr}(): - foo.emit(arr_len=0, arr=cast(0, felt*), x=0) - return () -end +func main{syscall_ptr: felt*, range_check_ptr}() { + foo.emit(arr_len=0, arr=cast(0, felt*), x=0); + return (); +} """ code = f""" %lang starknet {usage_code} @event -func foo(arr_len : felt, arr : felt*, x : felt): -end +func foo(arr_len: felt, arr: felt*, x: felt) {{ +}} """ expected_emit_function_code = f""" -namespace foo: - func emit{{syscall_ptr : felt*, range_check_ptr}}(arr_len : felt, arr : felt*, x : felt): - alloc_locals - - let (local __keys_ptr : felt*) = alloc() - assert [__keys_ptr] = {get_selector_from_name("foo")} - let (local __data_ptr : felt*) = alloc() - let __calldata_ptr = __data_ptr - assert [__calldata_ptr] = arr_len - let __calldata_ptr = __calldata_ptr + 1 - - # Check that the length is non-negative. - assert [range_check_ptr] = arr_len - # Store the updated range_check_ptr as a local variable to keep it available after - # the memcpy. - local range_check_ptr = range_check_ptr + 1 - # Keep a reference to __calldata_ptr. - let __calldata_ptr_copy = __calldata_ptr - # Store the updated __calldata_ptr as a local variable to keep it available after - # the memcpy. - local __calldata_ptr : felt* = __calldata_ptr + arr_len - memcpy(dst=__calldata_ptr_copy, src=arr, len=arr_len) - - assert [__calldata_ptr] = x - let __calldata_ptr = __calldata_ptr + 1 +namespace foo {{ + func emit{{syscall_ptr: felt*, range_check_ptr}}(arr_len: felt, arr: felt*, x: felt) {{ + alloc_locals; + + let (local __keys_ptr: felt*) = alloc(); + assert [__keys_ptr] = {get_selector_from_name("foo")}; + let (local __data_ptr: felt*) = alloc(); + let __calldata_ptr = __data_ptr; + assert [__calldata_ptr] = arr_len; + let __calldata_ptr = __calldata_ptr + 1; + + // Check that the length is non-negative. + assert [range_check_ptr] = arr_len; + // Store the updated range_check_ptr as a local variable to keep it available after + // the memcpy. + local range_check_ptr = range_check_ptr + 1; + // Keep a reference to __calldata_ptr. + let __calldata_ptr_copy = __calldata_ptr; + // Store the updated __calldata_ptr as a local variable to keep it available after + // the memcpy. + local __calldata_ptr: felt* = __calldata_ptr + arr_len; + memcpy(dst=__calldata_ptr_copy, src=arr, len=arr_len); + + assert [__calldata_ptr] = x; + let __calldata_ptr = __calldata_ptr + 1; emit_event( - keys_len=1, keys=__keys_ptr, data_len=__calldata_ptr - __data_ptr, data=__data_ptr) - return () - end -end + keys_len=1, keys=__keys_ptr, data_len=__calldata_ptr - __data_ptr, data=__data_ptr); + return (); + }} +}} """ expected_code = f""" %lang starknet -# Dummy library functions. -func alloc() -> (ptr : felt*): - ret -end -func memcpy(dst : felt*, src : felt*, len): - ap += [ap] - ret -end -func emit_event{{syscall_ptr : felt*}}( - keys_len : felt, keys : felt*, data_len : felt, data : felt*): - ret -end +// Dummy library functions. +func alloc() -> (ptr: felt*) {{ + ret; +}} +func memcpy(dst: felt*, src: felt*, len) {{ + ap += [ap]; + ret; +}} +func emit_event{{syscall_ptr: felt*}}( + keys_len: felt, keys: felt*, data_len: felt, data: felt*) {{ + ret; +}} {usage_code} @@ -82,8 +82,8 @@ def test_event_declaration_failures(): verify_exception( """ @event -func f(): -end +func f() { +} """, """ file:?:?: @event can only be used in source files that contain the \ @@ -96,12 +96,12 @@ def test_event_declaration_failures(): """ %lang starknet @event -namespace f: -end +namespace f { +} """, """ file:?:?: @event can only be used with functions. -namespace f: +namespace f { ^ """, ) @@ -110,8 +110,8 @@ def test_event_declaration_failures(): %lang starknet @event @another_decorator -func f(): -end +func f() { +} """, """ file:?:?: Unexpected decorator for an event. @@ -124,27 +124,27 @@ def test_event_declaration_failures(): """ %lang starknet @event -func f(): - # Empty line. - const X = 0 -end +func f() { + // Empty line. + const X = 0; +} """, """ file:?:?: Events must have an empty body. - const X = 0 - ^*********^ + const X = 0; + ^**********^ """, ) verify_exception( """ %lang starknet @event -func f{x}(): -end +func f{x}() { +} """, """ file:?:?: Events must have no implicit arguments. -func f{x}(): +func f{x}() { ^ """, ) @@ -152,13 +152,13 @@ def test_event_declaration_failures(): """ %lang starknet @event -func f() -> (res : felt): -end +func f() -> (res: felt) { +} """, """ file:?:?: Events must have no return values. -func f() -> (res : felt): - ^********^ +func f() -> (res: felt) { + ^*********^ """, ) @@ -167,13 +167,28 @@ def test_event_declaration_failures(): %lang starknet @event -func f() -> (res : felt): -end +func f() -> (res: felt) { +} """, """ file:?:?: Events must have no return values. -func f() -> (res : felt): - ^********^ +func f() -> (res: felt) { + ^*********^ +""", + ) + + verify_exception( + """ +%lang starknet + +@event +func f() -> felt { +} +""", + """ +file:?:?: Events must have no return values. +func f() -> felt { + ^**^ """, ) @@ -183,12 +198,12 @@ def test_event_implementation_failures(): """ %lang starknet @event -func f(arr : felt*): -end +func f(arr: felt*) { +} """, """ file:?:?: Array argument "arr" must be preceded by a length argument named "arr_len" of type felt. -func f(arr : felt*): +func f(arr: felt*) { ^*^ """, ) @@ -197,23 +212,23 @@ def test_event_implementation_failures(): """\ %lang starknet @event -func foo(): -end -func test{syscall_ptr : felt*}(): - foo.emit() - return() -end +func foo() { +} +func test{syscall_ptr: felt*}() { + foo.emit(); + return (); +} """, """ file:?:?: While trying to retrieve the implicit argument 'range_check_ptr' in: - foo.emit() + foo.emit(); ^********^ file:?:?: While handling event: -func foo(): +func foo() { ^*^ file:?:?: Unknown identifier 'range_check_ptr'. -func emit{syscall_ptr : felt*, range_check_ptr}(): - ^*************^ +func emit{syscall_ptr: felt*, range_check_ptr}() { + ^*************^ """, ) @@ -223,11 +238,11 @@ def test_event_preprocessor_failures(): """ %lang starknet -namespace foo: +namespace foo { @event - func bar(): - end -end + func bar() { + } +} """, """ file:?:?: Unsupported decorator: 'event'. diff --git a/src/starkware/starknet/compiler/external_wrapper.py b/src/starkware/starknet/compiler/external_wrapper.py index 1abe4971..11484898 100644 --- a/src/starkware/starknet/compiler/external_wrapper.py +++ b/src/starkware/starknet/compiler/external_wrapper.py @@ -1,9 +1,10 @@ import dataclasses -from typing import Dict, List, Optional, Tuple +from typing import Dict, List, Optional, Set, Tuple from starkware.cairo.lang.compiler.ast.cairo_types import CairoType, TypeFelt, TypeTuple from starkware.cairo.lang.compiler.ast.code_elements import ( CodeElementFunction, + CodeElementImport, CodeElementReturnValueReference, CodeElementScoped, CodeElementWith, @@ -22,7 +23,7 @@ from starkware.cairo.lang.compiler.identifier_definition import AliasDefinition, MemberDefinition from starkware.cairo.lang.compiler.identifier_manager import IdentifierManager from starkware.cairo.lang.compiler.instruction import Register -from starkware.cairo.lang.compiler.parser import ParserContext +from starkware.cairo.lang.compiler.parser import ParserContext, parse_type from starkware.cairo.lang.compiler.preprocessor.identifier_aware_visitor import ( IdentifierAwareVisitor, ) @@ -48,6 +49,7 @@ RAW_INPUT_DECORATOR = "raw_input" RAW_OUTPUT_DECORATOR = "raw_output" +RAW_OUTPUT_RETURNS = parse_type("(retdata_size: felt, retdata: felt*)") EXTERNAL_DECORATOR = "external" L1_HANDLER_DECORATOR = "l1_handler" @@ -71,24 +73,27 @@ def parse_entry_point_decorators( elm: CodeElementFunction, -) -> Tuple[Optional[ExprIdentifier], bool, bool]: +) -> Tuple[Optional[ExprIdentifier], bool, bool, List[ExprIdentifier]]: """ If the function has one of the external decorators, returns - (external_decorator, is_raw_input, is_raw_output). + (external_decorator, is_raw_input, is_raw_output, other_decorators). Otherwise, returns None. """ is_raw_input = False is_raw_output = False external_decorator = None + other_decorators = [] for decorator in elm.decorators: if decorator.name in ENTRY_POINT_DECORATORS and external_decorator is None: external_decorator = decorator - if decorator.name == RAW_INPUT_DECORATOR: + elif decorator.name == RAW_INPUT_DECORATOR: is_raw_input = True - if decorator.name == RAW_OUTPUT_DECORATOR: + elif decorator.name == RAW_OUTPUT_DECORATOR: is_raw_output = True + else: + other_decorators.append(decorator) - return external_decorator, is_raw_input, is_raw_output + return external_decorator, is_raw_input, is_raw_output, other_decorators def get_abi_entry_type(external_decorator_name: str) -> str: @@ -102,13 +107,25 @@ def get_abi_entry_type(external_decorator_name: str) -> str: raise NotImplementedError(f"Unsupported decorator {external_decorator_name}") +@dataclasses.dataclass +class ExternalWrapperResources: + # A list of pairs (path, name) of entities (directly) imported by the main module. + # External functions from other modules will be wrapped only if they appear in this set. + directly_imported_names: Set[Tuple[str, str]] = dataclasses.field(default_factory=set) + + class PreExternalWrapperVisitor(Visitor): """ Scans the external wrappers before ExternalWrapperVisitor, runs some validations and collects the used builtins. """ - def __init__(self, builtins: Optional[List[str]]): + def __init__( + self, + builtins: Optional[List[str]], + main_scope: ScopedName, + external_wrapper_resources: ExternalWrapperResources, + ): super().__init__() # The list of builtins in the %builtins directive, or None if the %builtins directive is # missing. @@ -121,15 +138,29 @@ def __init__(self, builtins: Optional[List[str]]): # The constructor definition. Only one constructor is allowed. self.constructor: Optional[CodeElementFunction] = None + self.external_wrapper_resources = external_wrapper_resources + self.main_scope = main_scope + def _visit_default(self, obj): return obj + def visit_CodeElementImport(self, elm: CodeElementImport): + if self.current_scope != self.main_scope: + return elm + + # This is an import statement that appears in the main module, + # add the imported items to directly_imported_names. + directly_imported_names = self.external_wrapper_resources.directly_imported_names + for item in elm.import_items: + directly_imported_names.add((elm.path.name, item.orig_identifier.name)) + return elm + def visit_CodeElementFunction(self, elm: CodeElementFunction): is_default_entry_point = elm.name in [DEFAULT_ENTRY_POINT_NAME, DEFAULT_L1_ENTRY_POINT_NAME] if is_default_entry_point: self.validate_default_entry_point_signature(elm) - external_decorator, is_raw_input, is_raw_output = parse_entry_point_decorators(elm=elm) + external_decorator, is_raw_input, is_raw_output, _ = parse_entry_point_decorators(elm=elm) if external_decorator is None: return super().visit_CodeElementFunction(elm=elm) @@ -284,21 +315,16 @@ def validate_raw_input_signature(self, elm: CodeElementFunction): if args != expected_args: raise PreprocessorError( f"@{RAW_INPUT_DECORATOR} requires the following arguments:\n" - "(selector : felt, calldata_size : felt, calldata : felt*).", + "(selector: felt, calldata_size: felt, calldata: felt*).", location=elm.arguments.location, ) def validate_raw_output_signature(self, elm: CodeElementFunction): - expected_returns = [ - TypedIdentifier(identifier=ExprIdentifier("retdata_size"), expr_type=TypeFelt()), - TypedIdentifier(identifier=ExprIdentifier("retdata"), expr_type=FELT_STAR), - ] - returns = elm.returns - if returns is None or returns.identifiers != expected_returns: + if returns != RAW_OUTPUT_RETURNS: raise PreprocessorError( f"@{RAW_OUTPUT_DECORATOR} requires the following return values:\n" - "(retdata_size : felt, retdata : felt*).", + f"{RAW_OUTPUT_RETURNS.format()}.", location=elm.identifier.location if returns is None else returns.location, ) @@ -311,7 +337,11 @@ def get_collected_builtins(self): class PreExternalWrapperStage(Stage): def run(self, context: PassManagerContext): - visitor = PreExternalWrapperVisitor(builtins=context.builtins) + visitor = PreExternalWrapperVisitor( + builtins=context.builtins, + main_scope=context.main_scope, + external_wrapper_resources=context.get_resource(ExternalWrapperResources), + ) for module in context.modules: visitor.visit(module) if context.builtins is None: @@ -324,9 +354,18 @@ class ExternalWrapperVisitor(IdentifierAwareVisitor): that converts between the StarkNet contract ABI and the Cairo calling convention. """ - def __init__(self, builtins: List[str], identifiers: Optional[IdentifierManager] = None): + def __init__( + self, + builtins: List[str], + external_wrapper_resources: ExternalWrapperResources, + main_scope: ScopedName, + identifiers: Optional[IdentifierManager] = None, + ): super().__init__(identifiers=identifiers) + self.external_wrapper_resources = external_wrapper_resources + self.main_scope = main_scope + # A mapping from name to offset in the os_context that is passed to the contract. self.os_context: Dict[str, int] = self.get_os_context(builtins=builtins) @@ -463,7 +502,7 @@ def create_func_wrapper( path=f"autogen/starknet/external/{elm.name}", code=( f"let {ptr_name} = [cast({os_context_ptr.format()} + {index}, " - f"{cairo_type.format()}*)]\n" + f"{cairo_type.format()}*)];\n" ), parser_context=ParserContext( parent_location=( @@ -476,7 +515,7 @@ def create_func_wrapper( assert index == len(return_args_exprs), "Unexpected index." - return_args_decl.append(f"{ptr_name} : {cairo_type.format()}") + return_args_decl.append(f"{ptr_name}: {cairo_type.format()}") return_args_exprs.append(ptr_name) arg_struct_def = self.get_struct_definition( @@ -517,7 +556,11 @@ def create_func_wrapper( ret_tuple_type = self.get_type_definition( name=ret_struct_name, location=func_location ).cairo_type - assert isinstance(ret_tuple_type, TypeTuple) + if not isinstance(ret_tuple_type, TypeTuple): + raise PreprocessorError( + "Only tuple types are supported as the return type of external functions.", + location=ret_tuple_type.location, + ) encode_return_func, known_ap_change = self.process_retdata( func_name=elm.name, @@ -527,20 +570,20 @@ def create_func_wrapper( # Prepare code for calling the original function. call_code = f"""\ -let ret_value = {func_alias_name}{{{implicit_arguments}}}({call_args.format()}) +let ret_value = {func_alias_name}{{{implicit_arguments}}}({call_args.format()}); """ if encode_return_func is None: if is_raw_output: call_code += """\ -let retdata_size = ret_value.retdata_size -let retdata = ret_value.retdata +let retdata_size = ret_value.retdata_size; +let retdata = ret_value.retdata; """ else: call_code += """\ -%{ memory[ap] = segments.add() %} # Allocate memory for return value. -tempvar retdata : felt* -let retdata_size = 0 +%{ memory[ap] = segments.add() %} // Allocate memory for return value. +tempvar retdata: felt*; +let retdata_size = 0; """ else: if not known_ap_change: @@ -557,7 +600,7 @@ def create_func_wrapper( location=func_location, ) call_code += f"""\ -let (range_check_ptr, retdata_size, retdata) = {elm.name}_encode_return(ret_value, range_check_ptr) +let (range_check_ptr, retdata_size, retdata) = {elm.name}_encode_return(ret_value, range_check_ptr); """ call_code_elements = autogen_parse_code_block( @@ -578,11 +621,11 @@ def create_func_wrapper( code_elements += decode_code_elements code_elements += call_code_elements - return_args_decl += ["size", "retdata : felt*"] + return_args_decl += ["size: felt", "retdata: felt*"] return_args_exprs += ["retdata_size", "retdata"] code = f"""\ -return ({",".join(return_args_exprs)}) +return ({",".join(return_args_exprs)}); """ code_elements += autogen_parse_code_block( @@ -597,9 +640,9 @@ def create_func_wrapper( # Generate the function skeleton code. return_str = ", ".join(return_args_decl) code = f"""\ -func {elm.name}() -> ({return_str}): - {"alloc_locals" if using_locals else ""} -end +func {elm.name}() -> ({return_str}) {{ + {"alloc_locals;" if using_locals else ""} +}} """ func_code_block = autogen_parse_code_block( @@ -648,6 +691,12 @@ def process_retdata( if len(ret_tuple_type.members) == 0: return None, True + for item in ret_tuple_type.members: + if item.name is None: + raise PreprocessorError( + "A return value in an external function must be named.", location=item.location + ) + data_encoder = DataEncoder( arg_name_func=lambda arg_info: f"ret_value.{arg_info.name}", encoding_type=EncodingType.RETURN, @@ -676,19 +725,19 @@ def prepare_return_function( location: Location, ) -> CodeElementFunction: code = f"""\ -func {func_name}_encode_return(ret_value : {ret_tuple_type.format()}, range_check_ptr) -> ( - range_check_ptr, data_len : felt, data : felt*): +func {func_name}_encode_return(ret_value: {ret_tuple_type.format()}, range_check_ptr) -> ( + range_check_ptr: felt, data_len: felt, data: felt*) {{ %{{ memory[ap] = segments.add() %}} - alloc_locals - local __return_value_ptr_start : felt* - let __return_value_ptr = __return_value_ptr_start - with range_check_ptr: - end + alloc_locals; + local __return_value_ptr_start: felt*; + let __return_value_ptr = __return_value_ptr_start; + with range_check_ptr {{ + }} return ( range_check_ptr=range_check_ptr, data_len=__return_value_ptr - __return_value_ptr_start, - data=__return_value_ptr_start) -end + data=__return_value_ptr_start); +}} """ code_elements = autogen_parse_code_block( @@ -710,10 +759,24 @@ def prepare_return_function( return func_elm def visit_CodeElementFunction(self, elm: CodeElementFunction): - external_decorator, is_raw_input, is_raw_output = parse_entry_point_decorators(elm=elm) + ( + external_decorator, + is_raw_input, + is_raw_output, + other_decorators, + ) = parse_entry_point_decorators(elm=elm) if external_decorator is None: return super().visit_CodeElementFunction(elm=elm) + directly_imported_names = self.external_wrapper_resources.directly_imported_names + is_directly_imported = (str(self.current_scope), elm.name) in directly_imported_names + is_in_main_module = self.current_scope == self.main_scope + if not (is_in_main_module or is_directly_imported): + # Remove the external-related decorators, so that the function will not appear in the + # ABI. + return super().visit_CodeElementFunction( + elm=dataclasses.replace(elm, decorators=other_decorators) + ) location = elm.identifier.location # Retrieve the canonical name of the function before switching scopes. diff --git a/src/starkware/starknet/compiler/external_wrapper_test.py b/src/starkware/starknet/compiler/external_wrapper_test.py index 505d3897..a6ba313f 100644 --- a/src/starkware/starknet/compiler/external_wrapper_test.py +++ b/src/starkware/starknet/compiler/external_wrapper_test.py @@ -14,13 +14,13 @@ def test_missing_range_check_in_builtin_directive(): %lang starknet %builtins pedersen @external -func foo() -> (res): -end +func foo() -> (res: felt) { +} """, - f""" + """ file:?:?: In order to use external functions, the '%builtins' directive must include the \ 'range_check' builtin. -func foo() -> (res): +func foo() -> (res: felt) { ^*^ """, ) @@ -32,13 +32,13 @@ def test_bad_implicit_arg_name(): %lang starknet %builtins pedersen range_check ecdsa @external -func f{hello}(): - return() -end +func f{hello}() { + return (); +} """, """ file:?:?: Unexpected implicit argument 'hello' in an external function. -func f{hello}(): +func f{hello}() { ^***^ """, ) @@ -51,13 +51,13 @@ def test_wrapper_with_implicit_args(builtins_directive: bool): %lang starknet {"%builtins pedersen range_check ecdsa" if builtins_directive else ""} -struct HashBuiltin: -end +struct HashBuiltin {{ +}} @external -func f{{ecdsa_ptr, pedersen_ptr : HashBuiltin*}}(a : felt, b : felt): - return () -end +func f{{ecdsa_ptr, pedersen_ptr: HashBuiltin*}}(a: felt, b: felt) {{ + return (); +}} """ ) @@ -65,28 +65,28 @@ def test_wrapper_with_implicit_args(builtins_directive: bool): expected_result = "%builtins pedersen range_check ecdsa\n\n" + strip_comments_and_linebreaks( """\ -# Implementation of f -[ap] = [fp + (-6)]; ap++ # Return ecdsa_ptr. -[ap] = [fp + (-5)]; ap++ # Return pedersen_ptr. -ret - -# Implementation of __wrappers__.f -[ap] = [fp + (-3)] + 2; ap++ # Compute effective calldata end. -[fp + (-4)] = [ap + (-1)] - [fp + (-3)] # Verify calldata size (2). -[ap] = [[fp + (-5)] + 3]; ap++ # Pass ecdsa_ptr. -[ap] = [[fp + (-5)] + 1]; ap++ # Pass pedersen_ptr. -[ap] = [[fp + (-3)]]; ap++ # Pass a. -[ap] = [[fp + (-3)] + 1]; ap++ # Pass b. -call rel -10 # Call f. -%{ memory[ap] = segments.add() %} # Allocate memory for return value. -ap += 1 -[ap] = [[fp + (-5)]]; ap++ # Return syscall_ptr. -[ap] = [ap + (-3)]; ap++ # Return pedersen_ptr. -[ap] = [[fp + (-5)] + 2]; ap++ # Return range_check. -[ap] = [ap + (-6)]; ap++ # Return ecdsa. -[ap] = 0; ap++ # Return retdata_size=0. -[ap] = [ap + (-6)]; ap++ # Return retdata_ptr. -ret +// Implementation of f +[ap] = [fp + (-6)], ap++; // Return ecdsa_ptr. +[ap] = [fp + (-5)], ap++; // Return pedersen_ptr. +ret; + +// Implementation of __wrappers__.f +[ap] = [fp + (-3)] + 2, ap++; // Compute effective calldata end. +[fp + (-4)] = [ap + (-1)] - [fp + (-3)]; // Verify calldata size (2). +[ap] = [[fp + (-5)] + 3], ap++; // Pass ecdsa_ptr. +[ap] = [[fp + (-5)] + 1], ap++; // Pass pedersen_ptr. +[ap] = [[fp + (-3)]], ap++; // Pass a. +[ap] = [[fp + (-3)] + 1], ap++; // Pass b. +call rel -10; // Call f. +%{ memory[ap] = segments.add() %} // Allocate memory for return value. +ap += 1; +[ap] = [[fp + (-5)]], ap++; // Return syscall_ptr. +[ap] = [ap + (-3)], ap++; // Return pedersen_ptr. +[ap] = [[fp + (-5)] + 2], ap++; // Return range_check. +[ap] = [ap + (-6)], ap++; // Return ecdsa. +[ap] = 0, ap++; // Return retdata_size=0. +[ap] = [ap + (-6)], ap++; // Return retdata_ptr. +ret; """ ) assert program.format() == expected_result @@ -104,26 +104,26 @@ def test_wrapper_with_return_values(builtins_directive: bool): %lang starknet {"%builtins pedersen range_check ecdsa" if builtins_directive else ""} -struct Point: - member x : felt - member y : felt -end +struct Point {{ + x: felt, + y: felt, +}} -struct EcdsaBuiltin: -end +struct EcdsaBuiltin {{ +}} -struct HashBuiltin: -end +struct HashBuiltin {{ +}} @external -func f{{ecdsa_ptr : EcdsaBuiltin*}}(a : felt, b : felt) -> (c_len : felt, c : felt*, d : Point): - return (c_len=1, c=cast(0, felt*), d=Point(2, 3)) -end +func f{{ecdsa_ptr: EcdsaBuiltin*}}(a: felt, b: felt) -> (c_len: felt, c: felt*, d: Point) {{ + return (c_len=1, c=cast(0, felt*), d=Point(2, 3)); +}} @view -func g{{pedersen_ptr : HashBuiltin*}}(): - return () -end +func g{{pedersen_ptr: HashBuiltin*}}() {{ + return (); +}} """ ) @@ -131,74 +131,74 @@ def test_wrapper_with_return_values(builtins_directive: bool): expected_result = "%builtins pedersen range_check ecdsa\n\n" + strip_comments_and_linebreaks( """\ -# A dummy memcpy(). -ap += [ap] -ret - -# Implementation of f. -[ap] = [fp + (-5)]; ap++ # Return ecdsa_ptr. -[ap] = 1; ap++ # Return c_len=1 -[ap] = 0; ap++ # Return c=0 -[ap] = 2; ap++ # Return d.x=2 -[ap] = 3; ap++ # Return d.y=3 -ret - -# Implementation of __wrappers__.f_encode_return. -%{ memory[ap] = segments.add() %} # Allocate memory for return value. -ap += 3 -[[fp]] = [fp + (-7)] # [retdata_ptr] = c_len -[[fp + (-3)]] = [fp + (-7)] # Range check c_len. -[fp + 1] = [fp + (-3)] + 1 # Updated range_check_ptr. -[ap] = [fp] + 1; ap++ # Updated __return_value_ptr. -[fp + 2] = [ap + (-1)] + [fp + (-7)] # Updated __return_value_ptr. -[ap] = [fp] + 1; ap++ # Pass old __return_value_ptr. -[ap] = [fp + (-6)]; ap++ # Pass c. -[ap] = [fp + (-7)]; ap++ # Pass c_len. -call rel -25 # Call memcpy. -[[fp + 2]] = [fp + (-5)] # [retdata_ptr + 1] = d.x. -[[fp + 2] + 1] = [fp + (-4)] # [retdata_ptr + 2] = d.y. -[ap] = [fp + 2] + 2; ap++ # Updated __return_value_ptr. -[ap] = [fp + 1]; ap++ # Return range_check. -[ap] = [ap + (-2)] - [fp]; ap++ # Return data_len. -[ap] = [fp]; ap++ # Return data. -ret - -# Implementation of __wrappers__.f. -ap += 1 -[ap] = [fp + (-3)] + 2; ap++ # Compute effective calldata end. -[fp + (-4)] = [ap + (-1)] - [fp + (-3)] # Verify calldata size (2). -[ap] = [[fp + (-5)] + 3]; ap++ # Pass ecdsa_ptr. -[ap] = [[fp + (-3)]]; ap++ # Pass a. -[ap] = [[fp + (-3)] + 1]; ap++ # Pass b. -call rel -41 # Call f. -[fp] = [ap + (-5)] # Copy ecdsa_ptr to a local variable. -[ap] = [[fp + (-5)] + 2]; ap++ # Pass range_check_ptr. -call rel -35 # Call f_encode_return. -[ap] = [[fp + (-5)]]; ap++ # Return syscall_ptr. -[ap] = [[fp + (-5)] + 1]; ap++ # Return pedersen_ptr. -[ap] = [ap + (-5)]; ap++ # Return range_check_ptr. -[ap] = [fp]; ap++ # Return ecdsa_ptr. -[ap] = [ap + (-6)]; ap++ # Return retdata_size. -[ap] = [ap + (-6)]; ap++ # Return retdata_ptr (__return_value_ptr_start). -ret - -# Implementation of g. -[ap] = [fp + (-3)]; ap++ # Return pedersen_ptr. -ret - -# Implementation of __wrappers__.g. -[fp + (-4)] = [fp + (-3)] - [fp + (-3)] # Verify calldata size (0). -[ap] = [[fp + (-5)] + 1]; ap++ # Pass pedersen_ptr. -call rel -4 # Call g. -%{ memory[ap] = segments.add() %} # Allocate memory for return value. -ap += 1 -[ap] = [[fp + (-5)]]; ap++ # Return syscall_ptr. -[ap] = [ap + (-3)]; ap++ # Return pedersen_ptr. -[ap] = [[fp + (-5)] + 2]; ap++ # Return range_check_ptr -[ap] = [[fp + (-5)] + 3]; ap++ # Return ecdsa_ptr. -[ap] = 0; ap++ # Return retdata_size. -[ap] = [ap + (-6)]; ap++ # Return retdata_ptr. -ret +// A dummy memcpy(). +ap += [ap]; +ret; + +// Implementation of f. +[ap] = [fp + (-5)], ap++; // Return ecdsa_ptr. +[ap] = 1, ap++; // Return c_len=1 +[ap] = 0, ap++; // Return c=0 +[ap] = 2, ap++; // Return d.x=2 +[ap] = 3, ap++; // Return d.y=3 +ret; + +// Implementation of __wrappers__.f_encode_return. +%{ memory[ap] = segments.add() %} // Allocate memory for return value. +ap += 3; +[[fp]] = [fp + (-7)]; // [retdata_ptr] = c_len +[[fp + (-3)]] = [fp + (-7)]; // Range check c_len. +[fp + 1] = [fp + (-3)] + 1; // Updated range_check_ptr. +[ap] = [fp] + 1, ap++; // Updated __return_value_ptr. +[fp + 2] = [ap + (-1)] + [fp + (-7)]; // Updated __return_value_ptr. +[ap] = [fp] + 1, ap++; // Pass old __return_value_ptr. +[ap] = [fp + (-6)], ap++; // Pass c. +[ap] = [fp + (-7)], ap++; // Pass c_len. +call rel -25; // Call memcpy. +[[fp + 2]] = [fp + (-5)]; // [retdata_ptr + 1] = d.x. +[[fp + 2] + 1] = [fp + (-4)]; // [retdata_ptr + 2] = d.y. +[ap] = [fp + 2] + 2, ap++; // Updated __return_value_ptr. +[ap] = [fp + 1], ap++; // Return range_check. +[ap] = [ap + (-2)] - [fp], ap++; // Return data_len. +[ap] = [fp], ap++; // Return data. +ret; + +// Implementation of __wrappers__.f. +ap += 1; +[ap] = [fp + (-3)] + 2, ap++; // Compute effective calldata end. +[fp + (-4)] = [ap + (-1)] - [fp + (-3)]; // Verify calldata size (2). +[ap] = [[fp + (-5)] + 3], ap++; // Pass ecdsa_ptr. +[ap] = [[fp + (-3)]], ap++; // Pass a. +[ap] = [[fp + (-3)] + 1], ap++; // Pass b. +call rel -41; // Call f. +[fp] = [ap + (-5)]; // Copy ecdsa_ptr to a local variable. +[ap] = [[fp + (-5)] + 2], ap++; // Pass range_check_ptr. +call rel -35; // Call f_encode_return. +[ap] = [[fp + (-5)]], ap++; // Return syscall_ptr. +[ap] = [[fp + (-5)] + 1], ap++; // Return pedersen_ptr. +[ap] = [ap + (-5)], ap++; // Return range_check_ptr. +[ap] = [fp], ap++; // Return ecdsa_ptr. +[ap] = [ap + (-6)], ap++; // Return retdata_size. +[ap] = [ap + (-6)], ap++; // Return retdata_ptr (__return_value_ptr_start). +ret; + +// Implementation of g. +[ap] = [fp + (-3)], ap++; // Return pedersen_ptr. +ret; + +// Implementation of __wrappers__.g. +[fp + (-4)] = [fp + (-3)] - [fp + (-3)]; // Verify calldata size (0). +[ap] = [[fp + (-5)] + 1], ap++; // Pass pedersen_ptr. +call rel -4; // Call g. +%{ memory[ap] = segments.add() %} // Allocate memory for return value. +ap += 1; +[ap] = [[fp + (-5)]], ap++; // Return syscall_ptr. +[ap] = [ap + (-3)], ap++; // Return pedersen_ptr. +[ap] = [[fp + (-5)] + 2], ap++; // Return range_check_ptr +[ap] = [[fp + (-5)] + 3], ap++; // Return ecdsa_ptr. +[ap] = 0, ap++; // Return retdata_size. +[ap] = [ap + (-6)], ap++; // Return retdata_ptr. +ret; """ ) assert program.format() == expected_result @@ -211,9 +211,9 @@ def test_fallback_wrapper(): %builtins ecdsa @external -func f(): - return () -end +func f() { + return (); +} """ ) @@ -221,16 +221,16 @@ def test_fallback_wrapper(): expected_result = "%builtins ecdsa\n\n" + strip_comments_and_linebreaks( """\ -ret -[fp + (-4)] = [fp + (-3)] - [fp + (-3)] # Verify calldata size (0). -call rel -2 # Call f. -%{ memory[ap] = segments.add() %} # Allocate memory for return value. -ap += 1 -[ap] = [[fp + (-5)]]; ap++ # Return syscall_ptr. -[ap] = [[fp + (-5)] + 1]; ap++ # Return ecdsa. -[ap] = 0; ap++ # Return retdata_size=0. -[ap] = [ap + (-4)]; ap++ # Return retdata_ptr. -ret +ret; +[fp + (-4)] = [fp + (-3)] - [fp + (-3)]; // Verify calldata size (0). +call rel -2; // Call f. +%{ memory[ap] = segments.add() %} // Allocate memory for return value. +ap += 1; +[ap] = [[fp + (-5)]], ap++; // Return syscall_ptr. +[ap] = [[fp + (-5)] + 1], ap++; // Return ecdsa. +[ap] = 0, ap++; // Return retdata_size=0. +[ap] = [ap + (-4)], ap++; // Return retdata_ptr. +ret; """ ) assert program.format() == expected_result @@ -246,10 +246,10 @@ def test_valid_default_entry_point(): @raw_input @raw_output func __default__{syscall_ptr, range_check_ptr}( - selector : felt, calldata_size : felt, calldata : felt*) -> ( - retdata_size : felt, retdata : felt*): - return (retdata_size=1, retdata=cast([fp], felt*)) -end + selector: felt, calldata_size: felt, calldata: felt* +) -> (retdata_size: felt, retdata: felt*) { + return (retdata_size=1, retdata=cast([fp], felt*)); +} """ ) @@ -259,25 +259,25 @@ def test_valid_default_entry_point(): expected_result = "%builtins pedersen range_check\n\n" + strip_comments_and_linebreaks( """\ -[ap] = [fp + (-7)]; ap++ # Return syscall_ptr. -[ap] = [fp + (-6)]; ap++ # Return range_check_ptr. -[ap] = 1; ap++ # Return retdata_len=1. -[ap] = [fp]; ap++ # Return retdata = [fp]. -ret -# Implementation of __wrappers__.__default__ -[ap] = [[fp + (-5)]]; ap++ # Push syscall_ptr. -[ap] = [[fp + (-5)] + 2]; ap++ # Push range_check_ptr. -[ap] = [fp + (-6)]; ap++ # Push selector. -[ap] = [fp + (-4)]; ap++ # Push calldata_size. -[ap] = [fp + (-3)]; ap++ # Push calldata. -# Call __default__ -call rel -11 -[ap] = [ap + (-4)]; ap++ # Return syscall_ptr. -[ap] = [[fp + (-5)] + 1]; ap++ # Return pedersen_ptr. -[ap] = [ap + (-5)]; ap++ # Return range_check_ptr. -[ap] = [ap + (-5)]; ap++ # Return retdata_size. -[ap] = [ap + (-5)]; ap++ # Return retdata. -ret +[ap] = [fp + (-7)], ap++; // Return syscall_ptr. +[ap] = [fp + (-6)], ap++; // Return range_check_ptr. +[ap] = 1, ap++; // Return retdata_len=1. +[ap] = [fp], ap++; // Return retdata = [fp]. +ret; +// Implementation of __wrappers__.__default__ +[ap] = [[fp + (-5)]], ap++; // Push syscall_ptr. +[ap] = [[fp + (-5)] + 2], ap++; // Push range_check_ptr. +[ap] = [fp + (-6)], ap++; // Push selector. +[ap] = [fp + (-4)], ap++; // Push calldata_size. +[ap] = [fp + (-3)], ap++; // Push calldata. +// Call __default__ +call rel -11; +[ap] = [ap + (-4)], ap++; // Return syscall_ptr. +[ap] = [[fp + (-5)] + 1], ap++; // Return pedersen_ptr. +[ap] = [ap + (-5)], ap++; // Return range_check_ptr. +[ap] = [ap + (-5)], ap++; // Return retdata_size. +[ap] = [ap + (-5)], ap++; // Return retdata. +ret; """ ) assert program.format() == expected_result @@ -292,9 +292,10 @@ def test_valid_l1_default_entry_point(): @l1_handler @raw_input func __l1_default__{syscall_ptr, range_check_ptr}( - selector : felt, calldata_size : felt, calldata : felt*): - return () -end + selector: felt, calldata_size: felt, calldata: felt* +) { + return (); +} """ ) @@ -304,24 +305,24 @@ def test_valid_l1_default_entry_point(): expected_result = "%builtins range_check\n\n" + strip_comments_and_linebreaks( """\ -[ap] = [fp + (-7)]; ap++ # Return syscall_ptr. -[ap] = [fp + (-6)]; ap++ # Return range_check_ptr. -ret -# Implementation of __wrappers__.__default__ -[ap] = [[fp + (-5)]]; ap++ # Push syscall_ptr. -[ap] = [[fp + (-5)] + 1]; ap++ # Push range_check_ptr. -[ap] = [fp + (-6)]; ap++ # Push selector. -[ap] = [fp + (-4)]; ap++ # Push calldata_size. -[ap] = [fp + (-3)]; ap++ # Push calldata. -# Call __default__ -call rel -8 -%{ memory[ap] = segments.add() %} # Allocate memory for return value. -ap += 1 # -[ap] = [ap + (-3)]; ap++ # Return syscall_ptr. -[ap] = [ap + (-3)]; ap++ # Return range_check_ptr. -[ap] = 0; ap++ # Return retdata_size=0. -[ap] = [ap + (-4)]; ap++ # Return retdata_ptr. -ret +[ap] = [fp + (-7)], ap++; // Return syscall_ptr. +[ap] = [fp + (-6)], ap++; // Return range_check_ptr. +ret; +// Implementation of __wrappers__.__default__ +[ap] = [[fp + (-5)]], ap++; // Push syscall_ptr. +[ap] = [[fp + (-5)] + 1], ap++; // Push range_check_ptr. +[ap] = [fp + (-6)], ap++; // Push selector. +[ap] = [fp + (-4)], ap++; // Push calldata_size. +[ap] = [fp + (-3)], ap++; // Push calldata. +// Call __default__ +call rel -8; +%{ memory[ap] = segments.add() %} // Allocate memory for return value. +ap += 1; // +[ap] = [ap + (-3)], ap++; // Return syscall_ptr. +[ap] = [ap + (-3)], ap++; // Return range_check_ptr. +[ap] = 0, ap++; // Return retdata_size=0. +[ap] = [ap + (-4)], ap++; // Return retdata_ptr. +ret; """ ) assert program.format() == expected_result @@ -334,9 +335,9 @@ def test_valid_l1_handler(): %builtins ecdsa @l1_handler -func f(from_address : felt): - return () -end +func f(from_address: felt) { + return (); +} """ ) @@ -344,18 +345,18 @@ def test_valid_l1_handler(): expected_result = "%builtins ecdsa\n\n" + strip_comments_and_linebreaks( """\ -ret -[ap] = [fp + (-3)] + 1; ap++ # Compute effective calldata end. -[fp + (-4)] = [ap + (-1)] - [fp + (-3)] # Verify calldata size (1). -[ap] = [[fp + (-3)]]; ap++ # Pass from_address. -call rel -5 # Call f. -%{ memory[ap] = segments.add() %} # Allocate memory for return value. -ap += 1 -[ap] = [[fp + (-5)]]; ap++ # Return syscall_ptr. -[ap] = [[fp + (-5)] + 1]; ap++ # Return ecdsa. -[ap] = 0; ap++ # Return retdata_size=0. -[ap] = [ap + (-4)]; ap++ # Return retdata_ptr. -ret +ret; +[ap] = [fp + (-3)] + 1, ap++; // Compute effective calldata end. +[fp + (-4)] = [ap + (-1)] - [fp + (-3)]; // Verify calldata size (1). +[ap] = [[fp + (-3)]], ap++; // Pass from_address. +call rel -5; // Call f. +%{ memory[ap] = segments.add() %} // Allocate memory for return value. +ap += 1; +[ap] = [[fp + (-5)]], ap++; // Return syscall_ptr. +[ap] = [[fp + (-5)] + 1], ap++; // Return ecdsa. +[ap] = 0, ap++; // Return retdata_size=0. +[ap] = [ap + (-4)], ap++; // Return retdata_ptr. +ret; """ ) assert program.format() == expected_result @@ -368,14 +369,14 @@ def test_raw_input_failures(): @external @raw_input -func foo(bad_arg): - return () -end +func foo(bad_arg) { + return (); +} """, """ file:?:?: @raw_input requires the following arguments: -(selector : felt, calldata_size : felt, calldata : felt*). -func foo(bad_arg): +(selector: felt, calldata_size: felt, calldata: felt*). +func foo(bad_arg) { ^*****^ """, ) @@ -388,14 +389,14 @@ def test_raw_output_failures(): @external @raw_output -func foo(selector : felt, calldata_size : felt, calldata : felt*): - return () -end +func foo(selector: felt, calldata_size: felt, calldata: felt*) { + return (); +} """, """ file:?:?: @raw_output requires the following return values: -(retdata_size : felt, retdata : felt*). -func foo(selector : felt, calldata_size : felt, calldata : felt*): +(retdata_size: felt, retdata: felt*). +func foo(selector: felt, calldata_size: felt, calldata: felt*) { ^*^ """, ) @@ -406,15 +407,15 @@ def test_raw_output_failures(): @external @raw_output -func foo(selector : felt, calldata_size : felt, calldata : felt*) -> (bad_ret): - return () -end +func foo(selector: felt, calldata_size: felt, calldata: felt*) -> (bad_ret: felt) { + return (); +} """, """ file:?:?: @raw_output requires the following return values: -(retdata_size : felt, retdata : felt*). -func foo(selector : felt, calldata_size : felt, calldata : felt*) -> (bad_ret): - ^*****^ +(retdata_size: felt, retdata: felt*). +func foo(selector: felt, calldata_size: felt, calldata: felt*) -> (bad_ret: felt) { + ^*************^ """, ) @@ -424,9 +425,9 @@ def test_raw_output_failures(): @external @l1_handler -func __default__(): - return () -end +func __default__() { + return (); +} """, """ file:?:?: The __default__ entry point may only be decorated with '@external'. @@ -442,9 +443,9 @@ def test_raw_output_failures(): @external @l1_handler -func __l1_default__(): - return () -end +func __l1_default__() { + return (); +} """, """ file:?:?: The __l1_default__ entry point may only be decorated with '@l1_handler'. @@ -458,13 +459,13 @@ def test_raw_output_failures(): """ %lang starknet -func __default__(): - return () -end +func __default__() { + return (); +} """, """ file:?:?: The __default__ entry point needs to be decorated with '@external'. -func __default__(): +func __default__() { ^*********^ """, @@ -477,13 +478,13 @@ def test_l1_handler_failures(): %lang starknet @l1_handler -func f(): - return () -end +func f() { + return (); +} """, """ file:?:?: The first argument of an L1 handler must be named 'from_address'. -func f(): +func f() { ^ """, ) @@ -493,13 +494,13 @@ def test_l1_handler_failures(): %lang starknet @l1_handler -func f(abc): - return () -end +func f(abc) { + return (); +} """, """ file:?:?: The first argument of an L1 handler must be named 'from_address'. -func f(abc): +func f(abc) { ^*^ """, ) @@ -509,13 +510,13 @@ def test_l1_handler_failures(): %lang starknet @l1_handler -func f(from_address: felt*): - return () -end +func f(from_address: felt*) { + return (); +} """, """ file:?:?: The type of 'from_address' must be felt. -func f(from_address: felt*): +func f(from_address: felt*) { ^***^ """, ) @@ -525,14 +526,14 @@ def test_l1_handler_failures(): %lang starknet @l1_handler -func f(from_address) -> (ret_val): - return (ret_val=0) -end +func f(from_address) -> (ret_val: felt) { + return (ret_val=0); +} """, """ file:?:?: An L1 handler can not have a return value. -func f(from_address) -> (ret_val): - ^*****^ +func f(from_address) -> (ret_val: felt) { + ^*************^ """, ) @@ -543,23 +544,23 @@ def test_constructor_failures(): %lang starknet @constructor -func constructor(): - return () -end +func constructor() { + return (); +} -namespace abc: +namespace abc { @constructor - func constructor(): - return () - end -end + func constructor() { + return (); + } +} """, """ file:?:?: Multiple constructors definitions are not supported. - func constructor(): + func constructor() { ^*********^ file:?:?: The constructor was previously defined here: -func constructor(): +func constructor() { ^*********^ """, ) @@ -569,13 +570,13 @@ def test_constructor_failures(): %lang starknet @constructor -func badly_named_constructor(a : felt): - return () -end +func badly_named_constructor(a: felt) { + return (); +} """, """ file:?:?: The constructor name must be 'constructor'. -func badly_named_constructor(a : felt): +func badly_named_constructor(a: felt) { ^*********************^ """, ) @@ -585,14 +586,14 @@ def test_constructor_failures(): %lang starknet @constructor -func constructor() -> (a : felt): - return (a=5) -end +func constructor() -> (a: felt) { + return (a=5); +} """, """ file:?:?: A constructor can not have a return value. -func constructor() -> (a : felt): - ^******^ +func constructor() -> (a: felt) { + ^*******^ """, ) @@ -602,14 +603,14 @@ def test_unsupported_args(): """ %lang starknet @external -func fc(arg : felt**): - return () -end +func fc(arg: felt**) { + return (); +} """, """ file:?:?: Only pointers to types that consist of felts are supported. -func fc(arg : felt**): - ^****^ +func fc(arg: felt**) { + ^****^ """, ) @@ -619,13 +620,173 @@ def test_unsupported_return_type(): """ %lang starknet @external -func fc() -> (arg : felt**): - return (cast(0, felt**)) -end +func fc() -> (arg: felt**) { + return (cast(0, felt**)); +} """, """ file:?:?: Only pointers to types that consist of felts are supported. -func fc() -> (arg : felt**): - ^****^ +func fc() -> (arg: felt**) { + ^****^ +""", + ) + + +def test_unnamed_return_type_in_external_func(): + verify_exception( + """ +%lang starknet +@external +func fc() -> (felt, felt) { + return (1, 2); +} +""", + """ +file:?:?: A return value in an external function must be named. +func fc() -> (felt, felt) { + ^**^ +""", + ) + + +def test_returned_type_alias_in_external_func(): + program1 = preprocess_str( + """ +%lang starknet + +using A = (a: felt, b: (felt, felt)); +@external +func f() -> A { + return (a=5, b=(4, 3)); +} +""" + ) + + program2 = preprocess_str( + """ +%lang starknet + +@external +func f() -> (a: felt, b: (felt, felt)) { + return (a=5, b=(4, 3)); +} +""" + ) + + assert program1.format() == program2.format() + + +def test_imported_external_func(): + """ + Tests that functions in imported modules are not automatically wrapped as external functions. + """ + + program1 = preprocess_str( + """ +%lang starknet + +from other_file import other_file0, NamespaceInOtherModule + +@external +func main_file0() -> (res: felt) { + return (res=0); +} + +namespace A { + // This function will not be externalized since it is inside a namespace. + @external + func main_file1() -> (res: felt) { + return (res=1); + } +} +""", + additional_modules={ + "other_file": """ +%lang starknet + +from other_file_b import other_file_b0, other_file_b1 + +@external +func other_file0() -> (res: felt) { + other_file1(); + other_file_b0(); + return (res=2); +} + +@external +func other_file1() -> (res: felt) { + return (res=3); +} + +namespace NamespaceInOtherModule { + @external + func other_file2() -> (res: felt) { + return (res=4); + } +} +""", + "other_file_b": """ +%lang starknet + +// This function is used, but not imported directly, so it won't have external wrapper. +@external +func other_file_b0() -> (res: felt) { + return (res=5); +} + +@external +func other_file_b1() -> (res: felt) { + return (res=6); +} +""", + }, + ) + + program2 = preprocess_str( + """ +%lang starknet + +// This function is used, but not imported directly, so it won't have external wrapper. +func other_file_b0() -> (res: felt) { + return (res=5); +} + +@external +func other_file0() -> (res: felt) { + other_file1(); + other_file_b0(); + return (res=2); +} + +// This function is not external, since it wasn't directly imported. +func other_file1() -> (res: felt) { + return (res=3); +} + +@external +func main_file0() -> (res: felt) { + return (res=0); +} +""" + ) + + assert program1.format() == program2.format() + + +def test_non_tuple_return_in_external(): + verify_exception( + """ +%lang starknet + +@external +func fc() -> felt { + return 5; +} + +""", + """ +file:?:?: Only tuple types are supported as the return type of external functions. +func fc() -> felt { + ^**^ """, ) diff --git a/src/starkware/starknet/compiler/starknet_pass_manager.py b/src/starkware/starknet/compiler/starknet_pass_manager.py index 5f0fbf70..255da9a3 100644 --- a/src/starkware/starknet/compiler/starknet_pass_manager.py +++ b/src/starkware/starknet/compiler/starknet_pass_manager.py @@ -12,6 +12,7 @@ from starkware.starknet.compiler.event import EventDeclVisitor, EventImplementationVisitor from starkware.starknet.compiler.external_wrapper import ( WRAPPER_SCOPE, + ExternalWrapperResources, ExternalWrapperVisitor, PreExternalWrapperStage, ) @@ -89,7 +90,10 @@ def starknet_pass_manager( new_stage_name="external_wrapper", new_stage=VisitorStage( lambda context: ExternalWrapperVisitor( - builtins=context.builtins, identifiers=context.identifiers + builtins=context.builtins, + external_wrapper_resources=context.get_resource(ExternalWrapperResources), + main_scope=context.main_scope, + identifiers=context.identifiers, ), modify_ast=True, ), diff --git a/src/starkware/starknet/compiler/starknet_preprocessor.py b/src/starkware/starknet/compiler/starknet_preprocessor.py index c7b2899b..9f276363 100644 --- a/src/starkware/starknet/compiler/starknet_preprocessor.py +++ b/src/starkware/starknet/compiler/starknet_preprocessor.py @@ -116,6 +116,7 @@ def process_abi_arguments( arguments = [] for m_name, cairo_type in members: + assert m_name is not None, f"Missing name for a member of {arg_full_scope}." assert is_type_resolved(cairo_type) abi_type_info = prepare_type_for_abi(cairo_type) arguments.append( @@ -199,7 +200,7 @@ def visit_CodeElementFunction(self, elm: CodeElementFunction): if self.current_scope == WRAPPER_SCOPE: return - external_decorator, _, _ = parse_entry_point_decorators(elm=elm) + external_decorator, _, _, _ = parse_entry_point_decorators(elm=elm) if external_decorator is not None: # Add a function/constructor entry to the ABI. self.add_abi_function_entry( diff --git a/src/starkware/starknet/compiler/starknet_preprocessor_test.py b/src/starkware/starknet/compiler/starknet_preprocessor_test.py index eddd9395..a2873097 100644 --- a/src/starkware/starknet/compiler/starknet_preprocessor_test.py +++ b/src/starkware/starknet/compiler/starknet_preprocessor_test.py @@ -7,9 +7,9 @@ def test_builtin_directive_after_external(): """ %lang starknet @external -func f{}(): - return() -end +func f{}() { + return (); +} %builtins pedersen range_check ecdsa """, """ @@ -50,9 +50,9 @@ def test_missing_lang_directive(): verify_exception( """ @external -func f{}(): - return() -end +func f{}() { + return (); +} """, """ file:?:?: External decorators can only be used in source files that contain the \ @@ -81,10 +81,10 @@ def test_invalid_hint(): """ %lang starknet @external -func fc(): +func fc() { %{ __storage.commitment_update() %} - return () -end + return (); +} """, """ file:?:?: Hint is not whitelisted. @@ -101,49 +101,49 @@ def test_abi_basic(): %lang starknet %builtins range_check -namespace MyNamespace: - struct ExternalStruct: - member y: (x : felt, y : felt) - end -end +namespace MyNamespace { + struct ExternalStruct { + y: (x: felt, y: felt), + } +} -struct ExternalStruct2: - member x: (felt, MyNamespace.ExternalStruct) -end +struct ExternalStruct2 { + x: (felt, MyNamespace.ExternalStruct), +} -struct NonExternalStruct: -end +struct NonExternalStruct { +} -struct ExternalStruct3: - member x: felt -end +struct ExternalStruct3 { + x: felt, +} @constructor -func constructor{syscall_ptr}(): - return () -end +func constructor{syscall_ptr}() { + return (); +} @external -func f(a : (x : felt, y : felt), arr_len : felt, arr : felt*) -> (b : felt, c : felt): - return (0, 1) -end +func f(a: (x: felt, y: felt), arr_len: felt, arr: felt*) -> (b: felt, c: felt) { + return (0, 1); +} @view -func g() -> (a: ExternalStruct3): - return (a=ExternalStruct3(0)) -end +func g() -> (a: ExternalStruct3) { + return (a=ExternalStruct3(0)); +} @l1_handler -func handler(from_address, a: ExternalStruct2): - return () -end +func handler(from_address, a: ExternalStruct2) { + return (); +} -struct ExternalStruct4: -end +struct ExternalStruct4 { +} @event -func status(a: felt, arr_len : felt, arr : felt*, external_struct : ExternalStruct4): -end +func status(a: felt, arr_len: felt, arr: felt*, external_struct: ExternalStruct4) { +} """ ) @@ -163,7 +163,7 @@ def test_abi_basic(): { "type": "struct", "name": "ExternalStruct", - "members": [{"name": "y", "offset": 0, "type": "(x : felt, y : felt)"}], + "members": [{"name": "y", "offset": 0, "type": "(x: felt, y: felt)"}], "size": 2, }, { @@ -180,7 +180,7 @@ def test_abi_basic(): }, { "inputs": [ - {"name": "a", "type": "(x : felt, y : felt)"}, + {"name": "a", "type": "(x: felt, y: felt)"}, {"name": "arr_len", "type": "felt"}, {"name": "arr", "type": "felt*"}, ], @@ -228,33 +228,33 @@ def test_abi_failures(): """ %lang starknet -namespace a: - struct MyStruct: - end -end +namespace a { + struct MyStruct { + } +} -namespace b: - struct MyStruct: - end +namespace b { + struct MyStruct { + } - struct MyStruct2: - member x: ((MyStruct, MyStruct), felt) - end -end + struct MyStruct2 { + x: ((MyStruct, MyStruct), felt), + } +} @external -func f(x : (felt, a.MyStruct)): - return() -end +func f(x: (felt, a.MyStruct)) { + return (); +} @view -func g(y : b.MyStruct2): - return() -end +func g(y: b.MyStruct2) { + return (); +} """, """ file:?:?: Found two external structs named MyStruct: test_scope.a.MyStruct, test_scope.b.MyStruct. - struct MyStruct: + struct MyStruct { ^******^ """, ) diff --git a/src/starkware/starknet/compiler/storage_var.py b/src/starkware/starknet/compiler/storage_var.py index 11e5d73a..fa782c40 100644 --- a/src/starkware/starknet/compiler/storage_var.py +++ b/src/starkware/starknet/compiler/storage_var.py @@ -1,9 +1,10 @@ import dataclasses -from typing import List +from typing import Dict, List, Optional -from starkware.cairo.lang.compiler.ast.cairo_types import CairoType, TypePointer +from starkware.cairo.lang.compiler.ast.cairo_types import CairoType, TypePointer, TypeTuple from starkware.cairo.lang.compiler.ast.code_elements import CodeElementFunction from starkware.cairo.lang.compiler.ast.formatting_utils import get_max_line_length +from starkware.cairo.lang.compiler.error_handling import Location from starkware.cairo.lang.compiler.parser import parse from starkware.cairo.lang.compiler.preprocessor.identifier_aware_visitor import ( IdentifierAwareVisitor, @@ -37,14 +38,23 @@ def get_return_type(elm: CodeElementFunction) -> CairoType: - returns_single_value = elm.returns is not None and len(elm.returns.identifiers) == 1 + returns_single_value = False + if elm.returns is not None: + if not isinstance(elm.returns, TypeTuple): + raise PreprocessorError( + "Only tuple types are currently supported for storage variables.", + location=elm.returns.location, + ) + + returns_single_value = len(elm.returns.members) == 1 + if not returns_single_value: raise PreprocessorError( "Storage variables must return exactly one value.", location=elm.returns.location if elm.returns is not None else elm.identifier.location, ) assert elm.returns is not None - return elm.returns.identifiers[0].get_type() + return elm.returns.members[0].typ def generate_storage_var_functions( @@ -60,28 +70,28 @@ def generate_storage_var_functions( ) code = f"""\ -namespace {var_name}: +namespace {var_name} {{ from starkware.starknet.common.storage import normalize_address from starkware.starknet.common.syscalls import storage_read, storage_write from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.hash import hash2 - func addr{{pedersen_ptr : HashBuiltin*, range_check_ptr}}() -> (res : felt): + func addr{{pedersen_ptr: HashBuiltin*, range_check_ptr}}() -> (res: felt) {{ {addr_func_body} - end + }} func read{{ - syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr - }}(): + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr + }}() {{ {read_func_body} - end + }} func write{{ - syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr - }}(value : felt): + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr + }}(value: felt) {{ {write_func_body} - end -end\ + }} +}}\ """ res = parse(autogen_filename, code, "code_element", CodeElementFunction) @@ -185,42 +195,42 @@ def process_storage_var(visitor: IdentifierAwareVisitor, elm: CodeElementFunctio var_name = elm.identifier.name addr = storage_var_name_to_base_addr(var_name) - addr_func_body = f"let res = {addr}\n" + addr_func_body = f"let res = {addr};\n" for arg, arg_size in safe_zip(elm.arguments.identifiers, arg_sizes): assert arg_size is not None for i in range(arg_size): value_str = f"cast(&{arg.identifier.name}, felt*)[{i}]" - addr_func_body += f"let (res) = hash2{{hash_ptr=pedersen_ptr}}(res, {value_str})\n" + addr_func_body += f"let (res) = hash2{{hash_ptr=pedersen_ptr}}(res, {value_str});\n" if len(elm.arguments.identifiers) > 0: - addr_func_body += "let (res) = normalize_address(addr=res)\n" - addr_func_body += "return (res=res)\n" + addr_func_body += "let (res) = normalize_address(addr=res);\n" + addr_func_body += "return (res=res);\n" args = ", ".join(arg.identifier.name for arg in elm.arguments.identifiers) - read_func_body = f"let (storage_addr) = addr({args})\n" + read_func_body = f"let (storage_addr) = addr({args});\n" for i in range(var_size): read_func_body += ( - f"let (__storage_var_temp{i}) = storage_read(address=storage_addr + {i})\n" + f"let (__storage_var_temp{i}) = storage_read(address=storage_addr + {i});\n" ) # Copy the return implicit args and the return values to a contiguous segment. read_func_body += """ -tempvar syscall_ptr = syscall_ptr -tempvar pedersen_ptr = pedersen_ptr -tempvar range_check_ptr = range_check_ptr +tempvar syscall_ptr = syscall_ptr; +tempvar pedersen_ptr = pedersen_ptr; +tempvar range_check_ptr = range_check_ptr; """ for i in range(var_size): - read_func_body += f"tempvar __storage_var_temp{i} : felt = __storage_var_temp{i}\n" + read_func_body += f"tempvar __storage_var_temp{i}: felt = __storage_var_temp{i};\n" unresolved_return_type_ptr = TypePointer(pointee=unresolved_return_type) read_func_body += ( - f"return ([cast(&__storage_var_temp0, {unresolved_return_type_ptr.format()})],)" + f"return ([cast(&__storage_var_temp0, {unresolved_return_type_ptr.format()})],);" ) - write_func_body = f"let (storage_addr) = addr({args})\n" + write_func_body = f"let (storage_addr) = addr({args});\n" for i in range(var_size): write_func_body += ( - f"storage_write(address=storage_addr + {i}, value=[cast(&value, felt) + {i}])\n" + f"storage_write(address=storage_addr + {i}, value=[cast(&value, felt) + {i}]);\n" ) - write_func_body += "return ()\n" + write_func_body += "return ();\n" return generate_storage_var_functions( elm, addr_func_body=addr_func_body, @@ -245,6 +255,13 @@ class StorageVarDeclVisitor(IdentifierAwareVisitor): functions will full implementation. """ + def __init__(self, *args, **kw): + super().__init__(*args, **kw) + + # A map from storage variable name to its location. + # Used to ensure unique names. + self.storage_var_name_to_location: Dict[str, Optional[Location]] = {} + def _visit_default(self, obj): return obj @@ -252,39 +269,58 @@ def visit_CodeElementFunction(self, elm: CodeElementFunction): is_storage_var, storage_var_location = has_decorator( elm=elm, decorator_name=STORAGE_VAR_DECORATOR ) - if is_storage_var: - verify_starknet_lang( - file_lang=self.file_lang, - location=storage_var_location, - name_in_error_message=f"@{STORAGE_VAR_DECORATOR}", - ) - # Add dummy references and calls that will be visited by the identifier collector - # and the dependency graph. - # Those statements will later be replaced by the real implementation. - addr_func_body = """ -let res = 0 -call hash2 -call normalize_address + if not is_storage_var: + return elm + + self.check_unique_names(elm=elm) + + verify_starknet_lang( + file_lang=self.file_lang, + location=storage_var_location, + name_in_error_message=f"@{STORAGE_VAR_DECORATOR}", + ) + # Add dummy references and calls that will be visited by the identifier collector + # and the dependency graph. + # Those statements will later be replaced by the real implementation. + addr_func_body = """ +let res = 0; +call hash2; +call normalize_address; """ - read_func_body = """ -let storage_addr = 0 -call addr -call storage_read + read_func_body = """ +let storage_addr = 0; +call addr; +call storage_read; """ - write_func_body = """ -let storage_addr = 0 -call addr -call storage_write + write_func_body = """ +let storage_addr = 0; +call addr; +call storage_write; """ - return generate_storage_var_functions( - elm, - addr_func_body=addr_func_body, - read_func_body=read_func_body, - write_func_body=write_func_body, - is_impl=False, - ) + return generate_storage_var_functions( + elm, + addr_func_body=addr_func_body, + read_func_body=read_func_body, + write_func_body=write_func_body, + is_impl=False, + ) - return elm + def check_unique_names(self, elm: CodeElementFunction): + if elm.name not in self.storage_var_name_to_location: + self.storage_var_name_to_location[elm.name] = elm.identifier.location + return + + notes = [] + other_location = self.storage_var_name_to_location[elm.name] + if other_location is not None: + notes.append( + other_location.to_string_with_content("Note: another definition appears here.") + ) + raise PreprocessorError( + f"Found more than one storage variable with the same name ('{elm.name}').", + location=elm.identifier.location, + notes=notes, + ) class StorageVarImplementationVisitor(IdentifierAwareVisitor): diff --git a/src/starkware/starknet/compiler/storage_var_test.py b/src/starkware/starknet/compiler/storage_var_test.py index 3fd78ac1..e05a081b 100644 --- a/src/starkware/starknet/compiler/storage_var_test.py +++ b/src/starkware/starknet/compiler/storage_var_test.py @@ -13,35 +13,34 @@ def test_storage_var_success(): %lang starknet from starkware.cairo.common.cairo_builtins import HashBuiltin -struct A: - member x : felt -end +struct A { + x: felt, +} -struct B: - member a : A - member y : felt -end +struct B { + a: A, + y: felt, +} -func g{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(): - alloc_locals - let (x) = my_var.read() - my_var.write(value=x + 1) - local syscall_ptr : felt* = syscall_ptr - let (my_var2_addr) = my_var2.addr(B(A(0), 1), 2) - my_var2.write(B(A(0), 1), 2, value=B(A(3), 4)) - let a = my_var2.read(B(A(0), 1), 2) - return () -end +func g{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + alloc_locals; + let (x) = my_var.read(); + my_var.write(value=x + 1); + local syscall_ptr: felt* = syscall_ptr; + let (my_var2_addr) = my_var2.addr(B(A(0), 1), 2); + my_var2.write(B(A(0), 1), 2, value=B(A(3), 4)); + let a = my_var2.read(B(A(0), 1), 2); + return (); +} @storage_var -func my_var() -> (res : felt): - # Comment. - -end +func my_var() -> (res: felt) { + // Comment. +} @storage_var -func my_var2(x : B, y) -> (res : B): -end +func my_var2(x: B, y) -> (res: B) { +} """ ) addr = starknet_keccak(b"my_var") @@ -49,131 +48,131 @@ def test_storage_var_success(): expected_result = f"""\ %builtins range_check -# Code for the dummy modules. -ret -ret -ret -ret +// Code for the dummy modules. +ret; +ret; +ret; +ret; -# Implementation of g. -ap += 1 -[ap] = [fp + (-5)]; ap++ # Push syscall_ptr. -[ap] = [fp + (-4)]; ap++ # Push pedersen_ptr. -[ap] = [fp + (-3)]; ap++ # Push range_check_ptr. -call rel ??? # Call my_var.read. -[ap] = [ap + (-4)]; ap++ # Push (updated) syscall_ptr. -[ap] = [ap + (-4)]; ap++ # Push (updated) pedersen_ptr. -[ap] = [ap + (-4)]; ap++ # Push (updated) range_check_ptr. -[ap] = [ap + (-4)] + 1; ap++ # Push value. -call rel ??? # Call my_var.write. -[fp] = [ap + (-3)] # Copy syscall_ptr to a local variable. -[ap] = 0; ap++ # Push 0. -[ap] = 1; ap++ # Push 1. -[ap] = 2; ap++ # Push 2. -call rel ??? # Call my_var2.addr. -[ap] = [fp]; ap++ # Push syscall_ptr. -[ap] = [ap + (-4)]; ap++ # Push pedersen_ptr. -[ap] = [ap + (-4)]; ap++ # Push range_check_ptr. -[ap] = 0; ap++ # Push 0. -[ap] = 1; ap++ # Push 1. -[ap] = 2; ap++ # Push 2. -[ap] = 3; ap++ # Push 3. -[ap] = 4; ap++ # Push 4. -call rel ??? # Call my_var2.write. -[ap] = 0; ap++ # Push 0. -[ap] = 1; ap++ # Push 1. -[ap] = 2; ap++ # Push 2. -call rel ??? # Call my_var2.read. -[ap] = [ap + (-5)]; ap++ # Return (updated) syscall_ptr. -[ap] = [ap + (-5)]; ap++ # Return (updated) pedersen_ptr. -[ap] = [ap + (-5)]; ap++ # Return (updated) range_check_ptr. -ret +// Implementation of g. +ap += 1; +[ap] = [fp + (-5)], ap++; // Push syscall_ptr. +[ap] = [fp + (-4)], ap++; // Push pedersen_ptr. +[ap] = [fp + (-3)], ap++; // Push range_check_ptr. +call rel ???; // Call my_var.read. +[ap] = [ap + (-4)], ap++; // Push (updated) syscall_ptr. +[ap] = [ap + (-4)], ap++; // Push (updated) pedersen_ptr. +[ap] = [ap + (-4)], ap++; // Push (updated) range_check_ptr. +[ap] = [ap + (-4)] + 1, ap++; // Push value. +call rel ???; // Call my_var.write. +[fp] = [ap + (-3)]; // Copy syscall_ptr to a local variable. +[ap] = 0, ap++; // Push 0. +[ap] = 1, ap++; // Push 1. +[ap] = 2, ap++; // Push 2. +call rel ???; // Call my_var2.addr. +[ap] = [fp], ap++; // Push syscall_ptr. +[ap] = [ap + (-4)], ap++; // Push pedersen_ptr. +[ap] = [ap + (-4)], ap++; // Push range_check_ptr. +[ap] = 0, ap++; // Push 0. +[ap] = 1, ap++; // Push 1. +[ap] = 2, ap++; // Push 2. +[ap] = 3, ap++; // Push 3. +[ap] = 4, ap++; // Push 4. +call rel ???; // Call my_var2.write. +[ap] = 0, ap++; // Push 0. +[ap] = 1, ap++; // Push 1. +[ap] = 2, ap++; // Push 2. +call rel ???; // Call my_var2.read. +[ap] = [ap + (-5)], ap++; // Return (updated) syscall_ptr. +[ap] = [ap + (-5)], ap++; // Return (updated) pedersen_ptr. +[ap] = [ap + (-5)], ap++; // Return (updated) range_check_ptr. +ret; -# Implementation of my_var.addr. -[ap] = [fp + (-4)]; ap++ # Return pedersen_ptr. -[ap] = [fp + (-3)]; ap++ # Return range_check_ptr. -[ap] = {addr}; ap++ # Return address. -ret +// Implementation of my_var.addr. +[ap] = [fp + (-4)], ap++; // Return pedersen_ptr. +[ap] = [fp + (-3)], ap++; // Return range_check_ptr. +[ap] = {addr}, ap++; // Return address. +ret; -# Implementation of my_var.read. -[ap] = [fp + (-4)]; ap++ # Push pedersen_ptr. -[ap] = [fp + (-3)]; ap++ # Push range_check_ptr. -call rel ??? # Call my_var.addr(). -[ap] = [fp + (-5)]; ap++ # Push syscall_ptr. -[ap] = [ap + (-2)]; ap++ # Push address. -call rel ??? # Call storage_read(). -[ap] = [ap + (-2)]; ap++ # Return (updated) syscall_ptr. -[ap] = [ap + (-8)]; ap++ # Return (updated) pedersen_ptr. -[ap] = [ap + (-8)]; ap++ # Return (updated) range_check_ptr. -[ap] = [ap + (-4)]; ap++ # Return value. -ret +// Implementation of my_var.read. +[ap] = [fp + (-4)], ap++; // Push pedersen_ptr. +[ap] = [fp + (-3)], ap++; // Push range_check_ptr. +call rel ???; // Call my_var.addr(). +[ap] = [fp + (-5)], ap++; // Push syscall_ptr. +[ap] = [ap + (-2)], ap++; // Push address. +call rel ???; // Call storage_read(). +[ap] = [ap + (-2)], ap++; // Return (updated) syscall_ptr. +[ap] = [ap + (-8)], ap++; // Return (updated) pedersen_ptr. +[ap] = [ap + (-8)], ap++; // Return (updated) range_check_ptr. +[ap] = [ap + (-4)], ap++; // Return value. +ret; -# Implementation of my_var.write. -[ap] = [fp + (-5)]; ap++ # Push range_check_ptr. -[ap] = [fp + (-4)]; ap++ # Push pedersen_ptr. -call rel ??? # Call my_var.addr(). -[ap] = [fp + (-6)]; ap++ # Push syscall_ptr. -[ap] = [ap + (-2)]; ap++ # Push address. -[ap] = [fp + (-3)]; ap++ # Push value. -call rel ??? # Call storage_write(). -[ap] = [ap + (-8)]; ap++ # Return (updated) range_check_ptr. -[ap] = [ap + (-8)]; ap++ # Return (updated) pedersen_ptr. -ret +// Implementation of my_var.write. +[ap] = [fp + (-5)], ap++; // Push range_check_ptr. +[ap] = [fp + (-4)], ap++; // Push pedersen_ptr. +call rel ???; // Call my_var.addr(). +[ap] = [fp + (-6)], ap++; // Push syscall_ptr. +[ap] = [ap + (-2)], ap++; // Push address. +[ap] = [fp + (-3)], ap++; // Push value. +call rel ???; // Call storage_write(). +[ap] = [ap + (-8)], ap++; // Return (updated) range_check_ptr. +[ap] = [ap + (-8)], ap++; // Return (updated) pedersen_ptr. +ret; -# Implementation of my_var2.addr. -[ap] = [fp + (-7)]; ap++ # Push pedersen_ptr. -[ap] = {addr2}; ap++ # Push address. -[ap] = [fp + (-5)]; ap++ # Push x.a.x. -call rel ??? # Call hash2(res, x.a.x). -[ap] = [fp + (-4)]; ap++ # Push x.y. -call rel ??? # Call hash2(res, x.y). -[ap] = [fp + (-3)]; ap++ # Push y. -call rel ??? # Call hash2(res, y). -[ap] = [fp + (-6)]; ap++ # Push range_check_ptr. -[ap] = [ap + (-2)]; ap++ # Push res. -call rel ??? # Call normalize_address(res). -[ap] = [ap + (-6)]; ap++ # Return (updated) pedersen_ptr. -[ap] = [ap + (-3)]; ap++ # Return (updated) range_check_ptr. -[ap] = [ap + (-3)]; ap++ # Return res. -ret +// Implementation of my_var2.addr. +[ap] = [fp + (-7)], ap++; // Push pedersen_ptr. +[ap] = {addr2}, ap++; // Push address. +[ap] = [fp + (-5)], ap++; // Push x.a.x. +call rel ???; // Call hash2(res, x.a.x). +[ap] = [fp + (-4)], ap++; // Push x.y. +call rel ???; // Call hash2(res, x.y). +[ap] = [fp + (-3)], ap++; // Push y. +call rel ???; // Call hash2(res, y). +[ap] = [fp + (-6)], ap++; // Push range_check_ptr. +[ap] = [ap + (-2)], ap++; // Push res. +call rel ???; // Call normalize_address(res). +[ap] = [ap + (-6)], ap++; // Return (updated) pedersen_ptr. +[ap] = [ap + (-3)], ap++; // Return (updated) range_check_ptr. +[ap] = [ap + (-3)], ap++; // Return res. +ret; -# Implementation of my_var2.read. -[ap] = [fp + (-7)]; ap++ # Push pedersen_ptr . -[ap] = [fp + (-6)]; ap++ # Push range_check_ptr. -[ap] = [fp + (-5)]; ap++ # Push x.a.x. -[ap] = [fp + (-4)]; ap++ # Push x.y. -[ap] = [fp + (-3)]; ap++ # Push y. -call rel ??? # Call my_var.addr(). -[ap] = [fp + (-8)]; ap++ # Push syscall_ptr. -[ap] = [ap + (-2)]; ap++ # Push address. -call rel ??? # Call storage_read(). -[ap] = [ap + (-2)]; ap++ # Push (updated) syscall_ptr. -[ap] = [ap + (-6)] + 1; ap++ # Push address + 1. -call rel ??? # Call storage_read(). -[ap] = [ap + (-2)]; ap++ # Return (updated) syscall_ptr. -[ap] = [ap + (-12)]; ap++ # Return (updated) pedersen_ptr. -[ap] = [ap + (-12)]; ap++ # Return (updated) range_check_ptr. -[ap] = [ap + (-8)]; ap++ # Return value (B.a.x). -[ap] = [ap + (-5)]; ap++ # Return value (B.y). -ret +// Implementation of my_var2.read. +[ap] = [fp + (-7)], ap++; // Push pedersen_ptr . +[ap] = [fp + (-6)], ap++; // Push range_check_ptr. +[ap] = [fp + (-5)], ap++; // Push x.a.x. +[ap] = [fp + (-4)], ap++; // Push x.y. +[ap] = [fp + (-3)], ap++; // Push y. +call rel ???; // Call my_var.addr(). +[ap] = [fp + (-8)], ap++; // Push syscall_ptr. +[ap] = [ap + (-2)], ap++; // Push address. +call rel ???; // Call storage_read(). +[ap] = [ap + (-2)], ap++; // Push (updated) syscall_ptr. +[ap] = [ap + (-6)] + 1, ap++; // Push address + 1. +call rel ???; // Call storage_read(). +[ap] = [ap + (-2)], ap++; // Return (updated) syscall_ptr. +[ap] = [ap + (-12)], ap++; // Return (updated) pedersen_ptr. +[ap] = [ap + (-12)], ap++; // Return (updated) range_check_ptr. +[ap] = [ap + (-8)], ap++; // Return value (B.a.x). +[ap] = [ap + (-5)], ap++; // Return value (B.y). +ret; -# Implementation of my_var2.write. -[ap] = [fp + (-9)]; ap++ # Push pedersen_ptr. -[ap] = [fp + (-8)]; ap++ # Push range_check_ptr. -[ap] = [fp + (-7)]; ap++ # Push x.a.x. -[ap] = [fp + (-6)]; ap++ # Push x.y. -[ap] = [fp + (-5)]; ap++ # Push y. -call rel ??? # Call my_var.addr(). -[ap] = [fp + (-10)]; ap++ # Push syscall_ptr. -[ap] = [ap + (-2)]; ap++ # Push address. -[ap] = [fp + (-4)]; ap++ # Push value. -call rel ??? # Call storage_write(). -[ap] = [ap + (-6)] + 1; ap++ # Push address. -[ap] = [fp + (-3)]; ap++ # Push value. -call rel ??? # Call storage_write(). -[ap] = [ap + (-12)]; ap++ # Return (updated) pedersen_ptr. -[ap] = [ap + (-12)]; ap++ # Return (updated) range_check_ptr. -ret +// Implementation of my_var2.write. +[ap] = [fp + (-9)], ap++; // Push pedersen_ptr. +[ap] = [fp + (-8)], ap++; // Push range_check_ptr. +[ap] = [fp + (-7)], ap++; // Push x.a.x. +[ap] = [fp + (-6)], ap++; // Push x.y. +[ap] = [fp + (-5)], ap++; // Push y. +call rel ???; // Call my_var.addr(). +[ap] = [fp + (-10)], ap++; // Push syscall_ptr. +[ap] = [ap + (-2)], ap++; // Push address. +[ap] = [fp + (-4)], ap++; // Push value. +call rel ???; // Call storage_write(). +[ap] = [ap + (-6)] + 1, ap++; // Push address. +[ap] = [fp + (-3)], ap++; // Push value. +call rel ???; // Call storage_write(). +[ap] = [ap + (-12)], ap++; // Return (updated) pedersen_ptr. +[ap] = [ap + (-12)], ap++; // Return (updated) range_check_ptr. +ret; """ assert re.sub( "call rel -?[0-9]+", "call rel ???", strip_comments_and_linebreaks(program.format()) @@ -184,8 +183,8 @@ def test_storage_var_failures(): verify_exception( """ @storage_var -func f() -> (res : felt): -end +func f() -> (res: felt) { +} """, """ file:?:?: @storage_var can only be used in source files that contain the "%lang starknet" directive. @@ -197,40 +196,40 @@ def test_storage_var_failures(): """ %lang starknet @storage_var -func f() -> (res : felt): - return () # Comment. -end +func f() -> (res: felt) { + return (); // Comment. +} """, """ file:?:?: Storage variables must have an empty body. - return () # Comment. - ^*******^ + return (); // Comment. + ^********^ """, ) verify_exception( """ %lang starknet @storage_var -func f() -> (res : felt): - 0 = 1 # Comment. -end +func f() -> (res: felt) { + 0 = 1; // Comment. +} """, """ file:?:?: Storage variables must have an empty body. - 0 = 1 # Comment. - ^***************^ + 0 = 1; // Comment. + ^*****************^ """, ) verify_exception( """ %lang starknet @storage_var -func f{x, y}() -> (res : felt): -end +func f{x, y}() -> (res: felt) { +} """, """ file:?:?: Storage variables must have no implicit arguments. -func f{x, y}() -> (res : felt): +func f{x, y}() -> (res: felt) { ^**^ """, ) @@ -239,8 +238,8 @@ def test_storage_var_failures(): %lang starknet @storage_var @invalid_decorator -func f() -> (res : felt): -end +func f() -> (res: felt) { +} """, """ file:?:?: Unexpected decorator for a storage variable. @@ -252,25 +251,25 @@ def test_storage_var_failures(): """ %lang starknet @storage_var -func f(x, y : felt*) -> (res : felt): -end +func f(x, y: felt*) -> (res: felt) { +} """, """ file:?:?: Arguments of storage variables must be a felts-only type (cannot contain pointers). -func f(x, y : felt*) -> (res : felt): - ^***^ +func f(x, y: felt*) -> (res: felt) { + ^***^ """, ) verify_exception( """ %lang starknet @storage_var -func f(addr : felt) -> (res : felt): -end +func f(addr: felt) -> (res: felt) { +} """, - f""" + """ file:?:?: 'addr' cannot be used as a storage variable argument name. -func f(addr : felt) -> (res : felt): +func f(addr: felt) -> (res: felt) { ^**^ """, ) @@ -278,12 +277,12 @@ def test_storage_var_failures(): """ %lang starknet @storage_var -func f(): -end +func f() { +} """, """ file:?:?: Storage variables must return exactly one value. -func f(): +func f() { ^ """, ) @@ -291,52 +290,86 @@ def test_storage_var_failures(): """ %lang starknet @storage_var -func f() -> (x : felt, y : felt): -end +func f() -> (x: felt, y: felt) { +} """, """ file:?:?: Storage variables must return exactly one value. -func f() -> (x : felt, y : felt): - ^****************^ +func f() -> (x: felt, y: felt) { + ^****************^ """, ) verify_exception( """ %lang starknet @storage_var -func f() -> (x : felt*): -end +func f() -> felt { +} +""", + """ +file:?:?: Only tuple types are currently supported for storage variables. +func f() -> felt { + ^**^ +""", + ) + verify_exception( + """ +%lang starknet +@storage_var +func f() -> (x: felt*) { +} """, """ file:?:?: The return type of storage variables must be a felts-only type (cannot contain pointers). -func f() -> (x : felt*): - ^*******^ +func f() -> (x: felt*) { + ^********^ """, ) verify_exception( """ %lang starknet -# A struct of size 10. -struct A: - member x : (felt, felt, felt, felt, felt, felt, felt, felt, felt, felt) -end +// A struct of size 10. +struct A { + x: (felt, felt, felt, felt, felt, felt, felt, felt, felt, felt), +} -# A struct of size 300. -struct B: - member x : (A, A, A, A, A, A, A, A, A, A) - member y : (A, A, A, A, A, A, A, A, A, A) - member z : (A, A, A, A, A, A, A, A, A, A) -end +// A struct of size 300. +struct B { + x: (A, A, A, A, A, A, A, A, A, A), + y: (A, A, A, A, A, A, A, A, A, A), + z: (A, A, A, A, A, A, A, A, A, A), +} @storage_var -func f() -> (x : B): -end +func f() -> (x: B) { +} """, """ file:?:?: The storage variable size (300) exceeds the maximum value (256). -func f() -> (x : B): - ^***^ +func f() -> (x: B) { + ^****^ +""", + ) + verify_exception( + """ +%lang starknet + +@storage_var +func f() -> (res: felt) { +} + +@storage_var +func f(x: felt) -> (y: felt) { +} +""", + """ +file:?:?: Found more than one storage variable with the same name ('f'). +func f(x: felt) -> (y: felt) { + ^ +file:?:?: Note: another definition appears here. +func f() -> (res: felt) { + ^ """, ) @@ -349,25 +382,25 @@ def test_storage_var_tail_call_failure(): from starkware.cairo.common.cairo_builtins import HashBuiltin @storage_var -func f() -> (x : felt): -end +func f() -> (x: felt) { +} @external -func test{syscall_ptr : felt*, range_check_ptr, pedersen_ptr : HashBuiltin*}() -> (x : felt): - return f.read() -end +func test{syscall_ptr: felt*, range_check_ptr, pedersen_ptr: HashBuiltin*}() -> (x: felt) { + return f.read(); +} """, """ file:?:?: Cannot convert the implicit arguments of f.read to the implicit arguments of test. - return f.read() - ^*************^ + return f.read(); + ^**************^ The implicit arguments of 'f.read' were defined here: file:?:? - func read{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() -> (x : felt): - ^***************************************************************^ + func read{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (x: felt) { + ^*************************************************************^ The implicit arguments of 'test' were defined here: file:?:? -func test{syscall_ptr : felt*, range_check_ptr, pedersen_ptr : HashBuiltin*}() -> (x : felt): - ^***************************************************************^ +func test{syscall_ptr: felt*, range_check_ptr, pedersen_ptr: HashBuiltin*}() -> (x: felt) { + ^*************************************************************^ """, ) diff --git a/src/starkware/starknet/compiler/test_utils.py b/src/starkware/starknet/compiler/test_utils.py index 114114cf..2334d985 100644 --- a/src/starkware/starknet/compiler/test_utils.py +++ b/src/starkware/starknet/compiler/test_utils.py @@ -1,3 +1,5 @@ +from typing import Dict + from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME from starkware.cairo.lang.compiler.preprocessor.preprocessor_error import PreprocessorError from starkware.cairo.lang.compiler.preprocessor.preprocessor_test_utils import ( @@ -14,69 +16,75 @@ STARKNET_TEST_MODULES = { **CAIRO_TEST_MODULES, "starkware.starknet.common.storage": """ -struct Storage: -end +struct Storage { +} -func normalize_address{range_check_ptr}(addr : felt) -> (res : felt): - ret -end +func normalize_address{range_check_ptr}(addr: felt) -> (res: felt) { + ret; +} """, "starkware.starknet.common.syscalls": """ -func call_contract{syscall_ptr : felt*}( - contract_address : felt, function_selector : felt, calldata_size : felt, - calldata : felt*) -> (retdata_size : felt, retdata : felt*): - ret -end +func call_contract{syscall_ptr: felt*}( + contract_address: felt, function_selector: felt, calldata_size: felt, calldata: felt* +) -> (retdata_size: felt, retdata: felt*) { + ret; +} -func library_call{syscall_ptr : felt*}( - class_hash : felt, function_selector : felt, calldata_size : felt, - calldata : felt*) -> (retdata_size : felt, retdata : felt*): - ret -end +func library_call{syscall_ptr: felt*}( + class_hash: felt, function_selector: felt, calldata_size: felt, calldata: felt* +) -> (retdata_size: felt, retdata: felt*) { + ret; +} -func storage_read{syscall_ptr : felt*}(address : felt) -> (value : felt): - ret -end +func storage_read{syscall_ptr: felt*}(address: felt) -> (value: felt) { + ret; +} -func storage_write{syscall_ptr : felt*}(address : felt, value : felt): - ret -end +func storage_write{syscall_ptr: felt*}(address: felt, value: felt) { + ret; +} -func emit_event{syscall_ptr : felt*}(keys_len : felt, keys : felt*, data_len : felt, data : felt*): - ret -end +func emit_event{syscall_ptr: felt*}(keys_len: felt, keys: felt*, data_len: felt, data: felt*) { + ret; +} """, "starkware.cairo.common.cairo_builtins": """ -struct HashBuiltin: -end +struct HashBuiltin { +} """, "starkware.cairo.common.hash": """ from starkware.cairo.common.cairo_builtins import HashBuiltin -func hash2{hash_ptr : HashBuiltin*}(x, y) -> (result : felt): - ret -end +func hash2{hash_ptr: HashBuiltin*}(x, y) -> (result: felt) { + ret; +} """, "starkware.cairo.common.alloc": """ -func alloc() -> (ptr : felt*): - ret -end +func alloc() -> (ptr: felt*) { + ret; +} """, "starkware.cairo.common.memcpy": """ -func memcpy(dst : felt*, src : felt*, len): - # Manually revoke ap tracking to better simulate memcpy(). - ap += [ap] - ret -end +func memcpy(dst: felt*, src: felt*, len) { + // Manually revoke ap tracking to better simulate memcpy(). + ap += [ap]; + ret; +} """, } -def preprocess_str(code: str) -> StarknetPreprocessedProgram: +def preprocess_str( + code: str, additional_modules: Dict[str, str] = None +) -> StarknetPreprocessedProgram: + if additional_modules is None: + additional_modules = {} + preprocessed = preprocess_str_ex( code=code, pass_manager=starknet_pass_manager( - prime=DEFAULT_PRIME, read_module=read_file_from_dict(STARKNET_TEST_MODULES) + prime=DEFAULT_PRIME, + read_module=read_file_from_dict({**STARKNET_TEST_MODULES, **additional_modules}), ), ) assert isinstance(preprocessed, StarknetPreprocessedProgram) diff --git a/src/starkware/starknet/compiler/validation_utils.py b/src/starkware/starknet/compiler/validation_utils.py index b4563160..46647de6 100644 --- a/src/starkware/starknet/compiler/validation_utils.py +++ b/src/starkware/starknet/compiler/validation_utils.py @@ -1,6 +1,7 @@ -from typing import List, Optional, Tuple, Type, TypeVar +from typing import Dict, List, Optional, Tuple, Type, TypeVar from starkware.cairo.lang.compiler.ast.arguments import IdentifierList +from starkware.cairo.lang.compiler.ast.cairo_types import TypeTuple from starkware.cairo.lang.compiler.ast.code_elements import ( CodeElementFunction, CommentedCodeElement, @@ -12,7 +13,14 @@ from starkware.cairo.lang.compiler.preprocessor.preprocessor_error import PreprocessorError from starkware.starknet.compiler.data_encoder import ArgumentInfo, EncodingType, encode_data from starkware.starknet.definitions import constants -from starkware.starknet.public.abi import EXECUTE_ENTRY_POINT_NAME, AbiType +from starkware.starknet.public.abi import ( + ACCOUNT_ENTRY_POINT_NAMES, + EXECUTE_ENTRY_POINT_NAME, + VALIDATE_DECLARE_ENTRY_POINT_NAME, + VALIDATE_ENTRY_POINT_NAME, + AbiEntryType, + AbiType, +) TAttr = TypeVar("TAttr") @@ -65,32 +73,70 @@ def verify_no_return_values(elm: CodeElementFunction, name_in_error_message: str Verifies that the given element has no return values and raises an exception otherwise. """ - if elm.returns is not None and len(elm.returns.identifiers) > 0: + returns = elm.returns + if returns is None: + return + + if not isinstance(returns, TypeTuple) or len(returns.members) > 0: raise PreprocessorError( message=f"{name_in_error_message} must have no return values.", - location=elm.returns.location, + location=returns.location, ) def verify_account_contract(contract_abi: AbiType, is_account_contract: bool): """ - Verifies that the given abi is that of a StarkNet account contract if and only if it - has an entry point named "__execute__" and raises an exception otherwise. + For account contracts (is_account_contract=True), verifies that the given ABI contains + all expected builtin entry points in their correct format. + For non-account contracts, verifies that it contains none of them. """ - contains_execute_entry_point = any( - entry_point["type"] == "function" and entry_point["name"] == EXECUTE_ENTRY_POINT_NAME - for entry_point in contract_abi - ) - if contains_execute_entry_point and (not is_account_contract): - raise PreprocessorError( - message=f"Only account contracts may have a function named " - f'"{EXECUTE_ENTRY_POINT_NAME}". Use --account_contract flag.' - ) + account_entry_points: Dict[str, AbiEntryType] = {} - if (not contains_execute_entry_point) and is_account_contract: - raise PreprocessorError( - message=f'Account contracts must have a function named "{EXECUTE_ENTRY_POINT_NAME}".' - ) + # Collect account contract special entry points. + for entry_point in contract_abi: + if entry_point["type"] == "function" and entry_point["name"] in ACCOUNT_ENTRY_POINT_NAMES: + account_entry_points[entry_point["name"]] = entry_point + + account_entry_point_names = set(account_entry_points.keys()) + + if is_account_contract: + # Handle account contract. + if account_entry_point_names != ACCOUNT_ENTRY_POINT_NAMES: + raise PreprocessorError( + message=( + "Account contracts must have external functions named " + f"{ACCOUNT_ENTRY_POINT_NAMES}, found: {list(account_entry_point_names)}." + ) + ) + + validate_entry_point = account_entry_points[VALIDATE_ENTRY_POINT_NAME] + execute_entry_point = account_entry_points[EXECUTE_ENTRY_POINT_NAME] + validate_declare_entry_point = account_entry_points[VALIDATE_DECLARE_ENTRY_POINT_NAME] + if execute_entry_point["inputs"] != validate_entry_point["inputs"]: + raise PreprocessorError( + message=( + "Account contracts must have the exact same calldata for " + f"'{VALIDATE_ENTRY_POINT_NAME}' and '{EXECUTE_ENTRY_POINT_NAME}' functions." + ) + ) + + if validate_declare_entry_point["inputs"] != [{"name": "class_hash", "type": "felt"}]: + raise PreprocessorError( + message=( + f"'{VALIDATE_DECLARE_ENTRY_POINT_NAME}' function must have one argument " + "`class_hash: felt`." + ) + ) + else: + # Handle non-account contract. + if len(account_entry_point_names) > 0: + # One of the entry points exists in a non-account contract. + raise PreprocessorError( + message=( + f"Only account contracts may have functions named {account_entry_point_names}. " + "Use the --account_contract flag to compile an account contract." + ) + ) # Common utils. diff --git a/src/starkware/starknet/compiler/validation_utils_test.py b/src/starkware/starknet/compiler/validation_utils_test.py new file mode 100644 index 00000000..d8aabed7 --- /dev/null +++ b/src/starkware/starknet/compiler/validation_utils_test.py @@ -0,0 +1,102 @@ +from typing import Dict, Iterable, List, Optional + +import pytest + +from starkware.cairo.lang.compiler.preprocessor.preprocessor_error import PreprocessorError +from starkware.starknet.compiler.validation_utils import verify_account_contract +from starkware.starknet.public import abi as starknet_abi + + +def create_mock_contract_abi( + entry_point_names: Iterable[str], + deform_entry_point_name: Optional[str] = None, + inputs: List[Dict[str, str]] = [], +) -> starknet_abi.AbiType: + mock_abi = [ + { + "type": "function", + "name": entry_point_name, + "inputs": [{"name": "class_hash", "type": "felt"}], + } + for entry_point_name in entry_point_names + if entry_point_name != deform_entry_point_name + ] + if deform_entry_point_name is not None: + mock_abi.append( + { + "type": "function", + "name": deform_entry_point_name, + "inputs": inputs, + } + ) + return mock_abi + + +def test_positive_flow_verify_account_contract(): + # Account contract. + mock_account_contract_abi = create_mock_contract_abi( + entry_point_names=starknet_abi.ACCOUNT_ENTRY_POINT_NAMES + ) + verify_account_contract(contract_abi=mock_account_contract_abi, is_account_contract=True) + + # Non-account contract. + mock_account_contract_abi = create_mock_contract_abi(entry_point_names=["mock_entry_point"]) + verify_account_contract(contract_abi=mock_account_contract_abi, is_account_contract=False) + + +def test_negative_flow_verify_account_contract(): + """ + Test malformed account contracts ABI. + """ + # Contract missing one or more of the account entry points: + # "__execute__", "__validate__", "__validate_declare__". + mock_defected_account_contract_abi = create_mock_contract_abi( + entry_point_names={ + starknet_abi.VALIDATE_ENTRY_POINT_NAME, + starknet_abi.EXECUTE_ENTRY_POINT_NAME, + } + ) + with pytest.raises( + PreprocessorError, match="Account contracts must have external functions named" + ): + verify_account_contract( + contract_abi=mock_defected_account_contract_abi, is_account_contract=True + ) + with pytest.raises(PreprocessorError, match="Only account contracts may have functions named"): + verify_account_contract( + contract_abi=mock_defected_account_contract_abi, is_account_contract=False + ) + + # Contract where "__declare__" and "__execute__" have different calldata. + mock_defected_account_contract_abi = create_mock_contract_abi( + entry_point_names=starknet_abi.ACCOUNT_ENTRY_POINT_NAMES, + deform_entry_point_name=starknet_abi.EXECUTE_ENTRY_POINT_NAME, + inputs=[ + {"name": "class_hash", "type": "felt"}, + {"name": "contract_address", "type": "felt"}, + ], + ) + with pytest.raises( + PreprocessorError, match="Account contracts must have the exact same calldata for" + ): + verify_account_contract( + contract_abi=mock_defected_account_contract_abi, is_account_contract=True + ) + + # Contract where "__validate_declare__" have malformed calldata. + mock_defected_account_contract_abi = create_mock_contract_abi( + entry_point_names=starknet_abi.ACCOUNT_ENTRY_POINT_NAMES, + deform_entry_point_name=starknet_abi.VALIDATE_DECLARE_ENTRY_POINT_NAME, + inputs=[ + {"name": "class_hash", "type": "felt"}, + {"name": "contract_address", "type": "felt"}, + ], + ) + with pytest.raises( + PreprocessorError, + match=f"'{starknet_abi.VALIDATE_DECLARE_ENTRY_POINT_NAME}' function must have one argument " + "`class_hash: felt`.", + ): + verify_account_contract( + contract_abi=mock_defected_account_contract_abi, is_account_contract=True + ) diff --git a/src/starkware/starknet/core/os/CMakeLists.txt b/src/starkware/starknet/core/os/CMakeLists.txt index aef94aad..a2cf98b1 100644 --- a/src/starkware/starknet/core/os/CMakeLists.txt +++ b/src/starkware/starknet/core/os/CMakeLists.txt @@ -47,13 +47,14 @@ python_lib(starknet_os_utils_lib cairo_run_lib cairo_vm_lib starknet_abi_lib + starknet_business_logic_fact_state_lib + starknet_business_logic_patricia_state_lib starknet_business_logic_state_lib starknet_contract_address_lib starknet_contract_class_lib starknet_definitions_lib starknet_execute_entry_point_base_lib starknet_general_config_lib - starknet_internal_transaction_interface_lib starknet_storage_lib starknet_transaction_lib starknet_transaction_execution_objects_lib @@ -71,6 +72,7 @@ full_python_test(starknet_os_program_hash_test FILES program_hash_test.py + program_hash.json LIBS cairo_hash_program_lib diff --git a/src/starkware/starknet/core/os/block_context.cairo b/src/starkware/starknet/core/os/block_context.cairo index faf2e911..7a0ffdf5 100644 --- a/src/starkware/starknet/core/os/block_context.cairo +++ b/src/starkware/starknet/core/os/block_context.cairo @@ -4,39 +4,39 @@ from starkware.starknet.core.os.builtins import BuiltinParams, get_builtin_param from starkware.starknet.core.os.contracts import ContractClassFact, load_contract_class_facts from starkware.starknet.core.os.os_config.os_config import StarknetOsConfig -struct BlockInfo: - # Currently, the block timestamp is not validated. - member block_timestamp : felt - member block_number : felt -end +struct BlockInfo { + // Currently, the block timestamp is not validated. + block_timestamp: felt, + block_number: felt, +} -# Represents information that is the same throughout the block. -struct BlockContext: - # Parameters for select_builtins. - member builtin_params : BuiltinParams* +// Represents information that is the same throughout the block. +struct BlockContext { + // Parameters for select_builtins. + builtin_params: BuiltinParams*, - # A list of (class_hash, contract_class) with the contracts that are executed - # in this block. - member n_contract_class_facts : felt - member contract_class_facts : ContractClassFact* - # The address of the sequencer that is creating this block. - member sequencer_address : felt - # Information about the block. - member block_info : BlockInfo - # StarknetOsConfig instance. - member starknet_os_config : StarknetOsConfig -end + // A list of (class_hash, contract_class) with the contracts that are executed + // in this block. + n_contract_class_facts: felt, + contract_class_facts: ContractClassFact*, + // The address of the sequencer that is creating this block. + sequencer_address: felt, + // Information about the block. + block_info: BlockInfo, + // StarknetOsConfig instance. + starknet_os_config: StarknetOsConfig, +} -# Returns a BlockContext instance. -# -# 'syscall_handler' and 'os_input' should be passed as hint variables. -func get_block_context{pedersen_ptr : HashBuiltin*, range_check_ptr}() -> ( - block_context : BlockContext* -): - alloc_locals - let (n_contract_class_facts, contract_class_facts) = load_contract_class_facts() - let (builtin_params) = get_builtin_params() - local block_context : BlockContext = BlockContext( +// Returns a BlockContext instance. +// +// 'syscall_handler' and 'os_input' should be passed as hint variables. +func get_block_context{pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + block_context: BlockContext* +) { + alloc_locals; + let (n_contract_class_facts, contract_class_facts) = load_contract_class_facts(); + let (builtin_params) = get_builtin_params(); + local block_context: BlockContext = BlockContext( builtin_params=builtin_params, n_contract_class_facts=n_contract_class_facts, contract_class_facts=contract_class_facts, @@ -47,8 +47,8 @@ func get_block_context{pedersen_ptr : HashBuiltin*, range_check_ptr}() -> ( starknet_os_config=StarknetOsConfig( chain_id=nondet %{ os_input.general_config.chain_id.value %}, fee_token_address=nondet %{ os_input.general_config.fee_token_address %} - )) + )); - let (__fp__, _) = get_fp_and_pc() - return (block_context=&block_context) -end + let (__fp__, _) = get_fp_and_pc(); + return (block_context=&block_context); +} diff --git a/src/starkware/starknet/core/os/builtins.cairo b/src/starkware/starknet/core/os/builtins.cairo index 9b1b49fb..c2d95060 100644 --- a/src/starkware/starknet/core/os/builtins.cairo +++ b/src/starkware/starknet/core/os/builtins.cairo @@ -1,52 +1,62 @@ -from starkware.cairo.common.cairo_builtins import BitwiseBuiltin, HashBuiltin, SignatureBuiltin +from starkware.cairo.common.cairo_builtins import ( + BitwiseBuiltin, + EcOpBuiltin, + HashBuiltin, + SignatureBuiltin, +) from starkware.cairo.common.registers import get_fp_and_pc -struct BuiltinPointers: - member pedersen : HashBuiltin* - member range_check : felt - member ecdsa : felt - member bitwise : felt -end - -# A struct containing the ASCII encoding of each builtin. -struct BuiltinEncodings: - member pedersen : felt - member range_check : felt - member ecdsa : felt - member bitwise : felt -end - -# A struct containing the instance size of each builtin. -struct BuiltinInstanceSizes: - member pedersen : felt - member range_check : felt - member ecdsa : felt - member bitwise : felt -end - -struct BuiltinParams: - member builtin_encodings : BuiltinEncodings* - member builtin_instance_sizes : BuiltinInstanceSizes* -end - -func get_builtin_params() -> (builtin_params : BuiltinParams*): - alloc_locals - let (local __fp__, _) = get_fp_and_pc() - - local builtin_encodings : BuiltinEncodings = BuiltinEncodings( +struct BuiltinPointers { + pedersen: HashBuiltin*, + range_check: felt, + ecdsa: felt, + bitwise: felt, + ec_op: felt, +} + +// A struct containing the ASCII encoding of each builtin. +struct BuiltinEncodings { + pedersen: felt, + range_check: felt, + ecdsa: felt, + bitwise: felt, + ec_op: felt, +} + +// A struct containing the instance size of each builtin. +struct BuiltinInstanceSizes { + pedersen: felt, + range_check: felt, + ecdsa: felt, + bitwise: felt, + ec_op: felt, +} + +struct BuiltinParams { + builtin_encodings: BuiltinEncodings*, + builtin_instance_sizes: BuiltinInstanceSizes*, +} + +func get_builtin_params() -> (builtin_params: BuiltinParams*) { + alloc_locals; + let (local __fp__, _) = get_fp_and_pc(); + + local builtin_encodings: BuiltinEncodings = BuiltinEncodings( pedersen='pedersen', range_check='range_check', ecdsa='ecdsa', - bitwise='bitwise') + bitwise='bitwise', + ec_op='ec_op'); - local builtin_instance_sizes : BuiltinInstanceSizes = BuiltinInstanceSizes( + local builtin_instance_sizes: BuiltinInstanceSizes = BuiltinInstanceSizes( pedersen=HashBuiltin.SIZE, range_check=1, ecdsa=SignatureBuiltin.SIZE, - bitwise=BitwiseBuiltin.SIZE) + bitwise=BitwiseBuiltin.SIZE, + ec_op=EcOpBuiltin.SIZE); - local builtin_params : BuiltinParams = BuiltinParams( + local builtin_params: BuiltinParams = BuiltinParams( builtin_encodings=&builtin_encodings, - builtin_instance_sizes=&builtin_instance_sizes) - return (builtin_params=&builtin_params) -end + builtin_instance_sizes=&builtin_instance_sizes); + return (builtin_params=&builtin_params); +} diff --git a/src/starkware/starknet/core/os/class_hash.py b/src/starkware/starknet/core/os/class_hash.py index dfbb3101..132fb214 100644 --- a/src/starkware/starknet/core/os/class_hash.py +++ b/src/starkware/starknet/core/os/class_hash.py @@ -13,6 +13,7 @@ from starkware.cairo.common.structs import CairoStructFactory, CairoStructProxy from starkware.cairo.lang.builtins.hash.hash_builtin_runner import HashBuiltinRunner from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME +from starkware.cairo.lang.compiler.ast.cairo_types import add_backward_compatibility_space from starkware.cairo.lang.compiler.cairo_compile import compile_cairo_files from starkware.cairo.lang.compiler.identifier_definition import ConstDefinition from starkware.cairo.lang.compiler.identifier_manager import IdentifierManager @@ -99,7 +100,13 @@ def compute_hinted_class_hash(contract_class: ContractClass) -> int: """ Computes the hash of the contract class, including hints. """ - dumped_program = dataclasses.replace(contract_class.program, debug_info=None).dump() + program_without_debug_info = dataclasses.replace(contract_class.program, debug_info=None) + + # If compiler_version is not present, this was compiled with a compiler before version 0.10.0. + # Use "(a : felt)" syntax instead of "(a: felt)" so that the class hash will be the same. + with add_backward_compatibility_space(contract_class.program.compiler_version is None): + dumped_program = program_without_debug_info.dump() + if len(dumped_program["attributes"]) == 0: # Remove attributes field from raw dictionary, for hash backward compatibility of # contracts deployed prior to adding this feature. diff --git a/src/starkware/starknet/core/os/contract_address/contract_address.cairo b/src/starkware/starknet/core/os/contract_address/contract_address.cairo index d6df1849..150a793b 100644 --- a/src/starkware/starknet/core/os/contract_address/contract_address.cairo +++ b/src/starkware/starknet/core/os/contract_address/contract_address.cairo @@ -8,29 +8,29 @@ from starkware.cairo.common.hash_state import ( ) from starkware.starknet.common.storage import normalize_address -const CONTRACT_ADDRESS_PREFIX = 'STARKNET_CONTRACT_ADDRESS' +const CONTRACT_ADDRESS_PREFIX = 'STARKNET_CONTRACT_ADDRESS'; -func get_contract_address{hash_ptr : HashBuiltin*, range_check_ptr}( - salt : felt, - class_hash : felt, - constructor_calldata_size : felt, - constructor_calldata : felt*, - deployer_address : felt, -) -> (contract_address : felt): - let (hash_state_ptr) = hash_init() +func get_contract_address{hash_ptr: HashBuiltin*, range_check_ptr}( + salt: felt, + class_hash: felt, + constructor_calldata_size: felt, + constructor_calldata: felt*, + deployer_address: felt, +) -> (contract_address: felt) { + let (hash_state_ptr) = hash_init(); let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=CONTRACT_ADDRESS_PREFIX - ) - let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=deployer_address) - let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=salt) - let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=class_hash) + ); + let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=deployer_address); + let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=salt); + let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=class_hash); let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=constructor_calldata, data_length=constructor_calldata_size, - ) - let (contract_address_before_modulo) = hash_finalize(hash_state_ptr=hash_state_ptr) - let (contract_address) = normalize_address(addr=contract_address_before_modulo) + ); + let (contract_address_before_modulo) = hash_finalize(hash_state_ptr=hash_state_ptr); + let (contract_address) = normalize_address(addr=contract_address_before_modulo); - return (contract_address=contract_address) -end + return (contract_address=contract_address); +} diff --git a/src/starkware/starknet/core/os/contracts.cairo b/src/starkware/starknet/core/os/contracts.cairo index e6909fba..c1e43885 100644 --- a/src/starkware/starknet/core/os/contracts.cairo +++ b/src/starkware/starknet/core/os/contracts.cairo @@ -10,177 +10,177 @@ from starkware.cairo.common.hash_state import ( from starkware.cairo.common.math import assert_lt_felt from starkware.cairo.common.registers import get_fp_and_pc -const API_VERSION = 0 - -struct ContractEntryPoint: - # A field element that encodes the signature of the called function. - member selector : felt - # The offset of the instruction that should be called within the contract bytecode. - member offset : felt -end - -struct ContractClass: - member api_version : felt - - # The length and pointer to the external entry point table of the contract. - member n_external_functions : felt - member external_functions : ContractEntryPoint* - - # The length and pointer to the L1 handler entry point table of the contract. - member n_l1_handlers : felt - member l1_handlers : ContractEntryPoint* - - # The length and pointer to the constructor entry point table of the contract. - member n_constructors : felt - member constructors : ContractEntryPoint* - - member n_builtins : felt - # 'builtin_list' is a continuous memory segment containing the ASCII encoding of the (ordered) - # builtins used by the program. - member builtin_list : felt* - - # The hinted_class_hash field should be set to the starknet_keccak of the - # contract program, including its hints. However the OS does not validate that. - # This field may be used by the operator to differentiate between contract classes that - # differ only in the hints. - # This field is included in the hash of the ContractClass to simplify the implementation. - member hinted_class_hash : felt - - # The length and pointer of the bytecode. - member bytecode_length : felt - member bytecode_ptr : felt* -end - -# Checks that the list of selectors is sorted. +const API_VERSION = 0; + +struct ContractEntryPoint { + // A field element that encodes the signature of the called function. + selector: felt, + // The offset of the instruction that should be called within the contract bytecode. + offset: felt, +} + +struct ContractClass { + api_version: felt, + + // The length and pointer to the external entry point table of the contract. + n_external_functions: felt, + external_functions: ContractEntryPoint*, + + // The length and pointer to the L1 handler entry point table of the contract. + n_l1_handlers: felt, + l1_handlers: ContractEntryPoint*, + + // The length and pointer to the constructor entry point table of the contract. + n_constructors: felt, + constructors: ContractEntryPoint*, + + n_builtins: felt, + // 'builtin_list' is a continuous memory segment containing the ASCII encoding of the (ordered) + // builtins used by the program. + builtin_list: felt*, + + // The hinted_class_hash field should be set to the starknet_keccak of the + // contract program, including its hints. However the OS does not validate that. + // This field may be used by the operator to differentiate between contract classes that + // differ only in the hints. + // This field is included in the hash of the ContractClass to simplify the implementation. + hinted_class_hash: felt, + + // The length and pointer of the bytecode. + bytecode_length: felt, + bytecode_ptr: felt*, +} + +// Checks that the list of selectors is sorted. func validate_entry_points{range_check_ptr}( - n_entry_points : felt, entry_points : ContractEntryPoint* -): - if n_entry_points == 0: - return () - end + n_entry_points: felt, entry_points: ContractEntryPoint* +) { + if (n_entry_points == 0) { + return (); + } return validate_entry_points_inner( n_entry_points=n_entry_points - 1, entry_points=&entry_points[1], prev_selector=entry_points[0].selector, - ) -end + ); +} -# Inner function for validate_entry_points. +// Inner function for validate_entry_points. func validate_entry_points_inner{range_check_ptr}( - n_entry_points : felt, entry_points : ContractEntryPoint*, prev_selector -): - if n_entry_points == 0: - return () - end + n_entry_points: felt, entry_points: ContractEntryPoint*, prev_selector +) { + if (n_entry_points == 0) { + return (); + } - assert_lt_felt(prev_selector, entry_points.selector) + assert_lt_felt(prev_selector, entry_points.selector); return validate_entry_points_inner( n_entry_points=n_entry_points - 1, entry_points=&entry_points[1], prev_selector=entry_points[0].selector, - ) -end + ); +} -func class_hash{hash_ptr : HashBuiltin*}(contract_class : ContractClass*) -> (hash : felt): - let (hash_state_ptr : HashState*) = hash_init() +func class_hash{hash_ptr: HashBuiltin*}(contract_class: ContractClass*) -> (hash: felt) { + let (hash_state_ptr: HashState*) = hash_init(); let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=contract_class.api_version - ) + ); - # Hash external entry points. + // Hash external entry points. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=contract_class.external_functions, data_length=contract_class.n_external_functions * ContractEntryPoint.SIZE, - ) + ); - # Hash L1 handler entry points. + // Hash L1 handler entry points. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=contract_class.l1_handlers, data_length=contract_class.n_l1_handlers * ContractEntryPoint.SIZE, - ) + ); - # Hash constructor entry points. + // Hash constructor entry points. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=contract_class.constructors, data_length=contract_class.n_constructors * ContractEntryPoint.SIZE, - ) + ); - # Hash builtins. + // Hash builtins. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=contract_class.builtin_list, data_length=contract_class.n_builtins, - ) + ); - # Hash hinted_class_hash. + // Hash hinted_class_hash. let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=contract_class.hinted_class_hash - ) + ); - # Hash bytecode. + // Hash bytecode. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=contract_class.bytecode_ptr, data_length=contract_class.bytecode_length, - ) - - let (hash : felt) = hash_finalize(hash_state_ptr=hash_state_ptr) - return (hash=hash) -end - -# A list entry that maps a hash to the corresponding contract classes. -struct ContractClassFact: - # The hash of the contract. This member should be first, so that we can lookup items - # with the hash as key, using find_element(). - member hash : felt - member contract_class : ContractClass* -end - -# Loads the contract classes from the 'os_input' hint variable. -# Returns ContractClassFact list that maps a hash to a ContractClass. -func load_contract_class_facts{pedersen_ptr : HashBuiltin*, range_check_ptr}() -> ( - n_contract_class_facts : felt, contract_class_facts : ContractClassFact* -): - alloc_locals - local n_contract_class_facts - local contract_class_facts : ContractClassFact* + ); + + let (hash: felt) = hash_finalize(hash_state_ptr=hash_state_ptr); + return (hash=hash); +} + +// A list entry that maps a hash to the corresponding contract classes. +struct ContractClassFact { + // The hash of the contract. This member should be first, so that we can lookup items + // with the hash as key, using find_element(). + hash: felt, + contract_class: ContractClass*, +} + +// Loads the contract classes from the 'os_input' hint variable. +// Returns ContractClassFact list that maps a hash to a ContractClass. +func load_contract_class_facts{pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + n_contract_class_facts: felt, contract_class_facts: ContractClassFact* +) { + alloc_locals; + local n_contract_class_facts; + local contract_class_facts: ContractClassFact*; %{ ids.contract_class_facts = segments.add() ids.n_contract_class_facts = len(os_input.contract_definitions) vm_enter_scope({ - 'contract_class_facts' : iter(os_input.contract_definitions.items()), + 'contract_class_facts': iter(os_input.contract_definitions.items()), }) %} load_contract_class_facts_inner( n_contract_class_facts=n_contract_class_facts, contract_class_facts=contract_class_facts - ) + ); %{ vm_exit_scope() %} return ( n_contract_class_facts=n_contract_class_facts, contract_class_facts=contract_class_facts - ) -end - -# Loads 'n_contract_class_facts' from the hint 'contract_class_facts' and appends the -# corresponding ContractClassFact to contract_class_facts. -func load_contract_class_facts_inner{pedersen_ptr : HashBuiltin*, range_check_ptr}( - n_contract_class_facts, contract_class_facts : ContractClassFact* -): - if n_contract_class_facts == 0: - return () - end - alloc_locals - - let contract_class_fact = contract_class_facts - let contract_class = contract_class_fact.contract_class - - # Fetch contract data form hints. + ); +} + +// Loads 'n_contract_class_facts' from the hint 'contract_class_facts' and appends the +// corresponding ContractClassFact to contract_class_facts. +func load_contract_class_facts_inner{pedersen_ptr: HashBuiltin*, range_check_ptr}( + n_contract_class_facts, contract_class_facts: ContractClassFact* +) { + if (n_contract_class_facts == 0) { + return (); + } + alloc_locals; + + let contract_class_fact = contract_class_facts; + let contract_class = contract_class_fact.contract_class; + + // Fetch contract data form hints. %{ from starkware.starknet.core.os.class_hash import get_contract_class_struct @@ -191,19 +191,19 @@ func load_contract_class_facts_inner{pedersen_ptr : HashBuiltin*, range_check_pt ids.contract_class = segments.gen_arg(cairo_contract) %} - assert contract_class.api_version = API_VERSION + assert contract_class.api_version = API_VERSION; validate_entry_points( n_entry_points=contract_class.n_external_functions, entry_points=contract_class.external_functions, - ) + ); validate_entry_points( n_entry_points=contract_class.n_l1_handlers, entry_points=contract_class.l1_handlers - ) + ); - let (hash) = class_hash{hash_ptr=pedersen_ptr}(contract_class) - contract_class_fact.hash = hash + let (hash) = class_hash{hash_ptr=pedersen_ptr}(contract_class); + contract_class_fact.hash = hash; %{ from starkware.python.utils import from_bytes @@ -220,5 +220,5 @@ func load_contract_class_facts_inner{pedersen_ptr : HashBuiltin*, range_check_pt return load_contract_class_facts_inner( n_contract_class_facts=n_contract_class_facts - 1, contract_class_facts=contract_class_facts + ContractClassFact.SIZE, - ) -end + ); +} diff --git a/src/starkware/starknet/core/os/os.cairo b/src/starkware/starknet/core/os/os.cairo index b754a0dd..6ba9712f 100644 --- a/src/starkware/starknet/core/os/os.cairo +++ b/src/starkware/starknet/core/os/os.cairo @@ -1,4 +1,4 @@ -%builtins output pedersen range_check ecdsa bitwise +%builtins output pedersen range_check ecdsa bitwise ec_op from starkware.cairo.common.alloc import alloc from starkware.cairo.common.cairo_builtins import HashBuiltin @@ -9,17 +9,23 @@ from starkware.starknet.core.os.output import OsCarriedOutputs, os_output_serial from starkware.starknet.core.os.state import state_update from starkware.starknet.core.os.transactions import execute_transactions -# Executes transactions on StarkNet. -func main{output_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr, ecdsa_ptr, bitwise_ptr}( - ): - alloc_locals - - # Reserve the initial range check for self validation. - # Note that this must point to the first range check used by the OS. - let initial_range_check_ptr = range_check_ptr - let range_check_ptr = range_check_ptr + 1 - - let (initial_carried_outputs : OsCarriedOutputs*) = alloc() +// Executes transactions on StarkNet. +func main{ + output_ptr: felt*, + pedersen_ptr: HashBuiltin*, + range_check_ptr, + ecdsa_ptr, + bitwise_ptr, + ec_op_ptr, +}() { + alloc_locals; + + // Reserve the initial range check for self validation. + // Note that this must point to the first range check used by the OS. + let initial_range_check_ptr = range_check_ptr; + let range_check_ptr = range_check_ptr + 1; + + let (initial_carried_outputs: OsCarriedOutputs*) = alloc(); %{ from starkware.starknet.core.os.os_input import StarknetOsInput @@ -30,20 +36,20 @@ func main{output_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr, ecds ids.initial_carried_outputs.deployment_info = segments.add_temp_segment() %} - let (block_context : BlockContext*) = get_block_context() + let (block_context: BlockContext*) = get_block_context(); - let outputs = initial_carried_outputs - with outputs: + let outputs = initial_carried_outputs; + with outputs { let (local reserved_range_checks_end, state_changes) = execute_transactions( block_context=block_context - ) - end - let final_carried_outputs = outputs + ); + } + let final_carried_outputs = outputs; - local ecdsa_ptr = ecdsa_ptr - local bitwise_ptr = bitwise_ptr + local ecdsa_ptr = ecdsa_ptr; + local bitwise_ptr = bitwise_ptr; - local initial_storage_updates_ptr : felt* + local initial_storage_updates_ptr: felt*; %{ # This hint shouldn't be whitelisted. vm_enter_scope(dict( @@ -51,26 +57,26 @@ func main{output_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr, ecds os_input=os_input, __merkle_multi_update_skip_validation_runner=pedersen_builtin)) ids.initial_storage_updates_ptr = segments.add_temp_segment() %} - let storage_updates_ptr = initial_storage_updates_ptr + let storage_updates_ptr = initial_storage_updates_ptr; - with storage_updates_ptr: + with storage_updates_ptr { let (commitment_tree_update_output) = state_update{hash_ptr=pedersen_ptr}( state_changes_dict=state_changes.changes_start, state_changes_dict_end=state_changes.changes_end, - ) - end + ); + } %{ vm_exit_scope() %} - # Compute the general config hash. - # This is done here to avoid passing pedersen_ptr to os_output_serialize. - let hash_ptr = pedersen_ptr - with hash_ptr: + // Compute the general config hash. + // This is done here to avoid passing pedersen_ptr to os_output_serialize. + let hash_ptr = pedersen_ptr; + with hash_ptr { let (starknet_os_config_hash) = get_starknet_os_config_hash( starknet_os_config=&block_context.starknet_os_config - ) - end - let pedersen_ptr = hash_ptr + ); + } + let pedersen_ptr = hash_ptr; os_output_serialize( block_context=block_context, @@ -80,14 +86,14 @@ func main{output_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr, ecds storage_updates_ptr_start=initial_storage_updates_ptr, storage_updates_ptr_end=storage_updates_ptr, starknet_os_config_hash=starknet_os_config_hash, - ) + ); - # Make sure that we report using at least 1 range check to guarantee that - # initial_range_check_ptr points to a valid range check instance. - assert_not_equal(initial_range_check_ptr, range_check_ptr) - # Use initial_range_check_ptr to check that range_check_ptr >= reserved_range_checks_end. - # This should guarantee that all the reserved range checks point to valid instances. - assert [initial_range_check_ptr] = range_check_ptr - reserved_range_checks_end + // Make sure that we report using at least 1 range check to guarantee that + // initial_range_check_ptr points to a valid range check instance. + assert_not_equal(initial_range_check_ptr, range_check_ptr); + // Use initial_range_check_ptr to check that range_check_ptr >= reserved_range_checks_end. + // This should guarantee that all the reserved range checks point to valid instances. + assert [initial_range_check_ptr] = range_check_ptr - reserved_range_checks_end; - return () -end + return (); +} diff --git a/src/starkware/starknet/core/os/os_config/CMakeLists.txt b/src/starkware/starknet/core/os/os_config/CMakeLists.txt index 1111dbdf..a733134f 100644 --- a/src/starkware/starknet/core/os/os_config/CMakeLists.txt +++ b/src/starkware/starknet/core/os/os_config/CMakeLists.txt @@ -16,6 +16,7 @@ full_python_test(starknet_os_config_hash_test FILES os_config_hash_test.py + os_config_hash.json LIBS cairo_common_lib @@ -24,6 +25,7 @@ full_python_test(starknet_os_config_hash_test starknet_general_config_lib starknet_os_utils_lib starkware_python_test_utils_lib + starkware_python_utils_lib pip_pytest pip_pytest_asyncio ) diff --git a/src/starkware/starknet/core/os/os_config/os_config.cairo b/src/starkware/starknet/core/os/os_config/os_config.cairo index 391f7100..ca41dcf2 100644 --- a/src/starkware/starknet/core/os/os_config/os_config.cairo +++ b/src/starkware/starknet/core/os/os_config/os_config.cairo @@ -2,40 +2,40 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.hash_state import hash_finalize, hash_init, hash_update_single from starkware.cairo.common.registers import get_fp_and_pc -const STARKNET_OS_CONFIG_VERSION = 'StarknetOsConfig1' +const STARKNET_OS_CONFIG_VERSION = 'StarknetOsConfig1'; -struct StarknetOsConfig: - # The identifier of the chain. - # This field can be used to prevent replay of testnet transactions on mainnet. - member chain_id : felt - # The (L2) address of the fee token contract. - member fee_token_address : felt -end +struct StarknetOsConfig { + // The identifier of the chain. + // This field can be used to prevent replay of testnet transactions on mainnet. + chain_id: felt, + // The (L2) address of the fee token contract. + fee_token_address: felt, +} -# Calculates the hash of StarkNet OS config. -func get_starknet_os_config_hash{hash_ptr : HashBuiltin*}( - starknet_os_config : StarknetOsConfig* -) -> (starknet_os_config_hash : felt): - let (hash_state_ptr) = hash_init() +// Calculates the hash of StarkNet OS config. +func get_starknet_os_config_hash{hash_ptr: HashBuiltin*}(starknet_os_config: StarknetOsConfig*) -> ( + starknet_os_config_hash: felt +) { + let (hash_state_ptr) = hash_init(); let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=STARKNET_OS_CONFIG_VERSION - ) + ); let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=starknet_os_config.chain_id - ) + ); let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=starknet_os_config.fee_token_address - ) + ); - let (starknet_os_config_hash) = hash_finalize(hash_state_ptr=hash_state_ptr) + let (starknet_os_config_hash) = hash_finalize(hash_state_ptr=hash_state_ptr); - return (starknet_os_config_hash=starknet_os_config_hash) -end + return (starknet_os_config_hash=starknet_os_config_hash); +} -func starknet_os_config_new(chain_id : felt, fee_token_address : felt) -> ( - starknet_os_config : StarknetOsConfig* -): - let (fp_val, pc_val) = get_fp_and_pc() - static_assert StarknetOsConfig.SIZE == Args.SIZE - return (starknet_os_config=cast(fp_val - 2 - StarknetOsConfig.SIZE, StarknetOsConfig*)) -end +func starknet_os_config_new(chain_id: felt, fee_token_address: felt) -> ( + starknet_os_config: StarknetOsConfig* +) { + let (fp_val, pc_val) = get_fp_and_pc(); + static_assert StarknetOsConfig.SIZE == Args.SIZE; + return (starknet_os_config=cast(fp_val - 2 - StarknetOsConfig.SIZE, StarknetOsConfig*)); +} diff --git a/src/starkware/starknet/core/os/os_config/os_config_hash_test.py b/src/starkware/starknet/core/os/os_config/os_config_hash_test.py index ba895f8b..9deeff6c 100644 --- a/src/starkware/starknet/core/os/os_config/os_config_hash_test.py +++ b/src/starkware/starknet/core/os/os_config/os_config_hash_test.py @@ -1,4 +1,5 @@ import json +import os from starkware.cairo.common.cairo_function_runner import CairoFunctionRunner from starkware.cairo.common.structs import CairoStructFactory @@ -12,7 +13,10 @@ from starkware.starknet.definitions import fields from starkware.starknet.definitions.general_config import StarknetChainId, StarknetOsConfig -HASH_PATH = get_source_dir_path("src/starkware/starknet/core/os/os_config/os_config_hash.json") +HASH_PATH = get_source_dir_path( + "src/starkware/starknet/core/os/os_config/os_config_hash.json", + default_value=os.path.join(os.path.dirname(__file__), "os_config_hash.json"), +) FEE_TOKEN_ADDRESS = 0x49D36570D4E46F48E99674BD3FCC84644DDD6B96F7C741B1562B82F9E004DC7 FIX_COMMAND = "starknet_os_config_hash_fix" diff --git a/src/starkware/starknet/core/os/output.cairo b/src/starkware/starknet/core/os/output.cairo index af42a467..97765e91 100644 --- a/src/starkware/starknet/core/os/output.cairo +++ b/src/starkware/starknet/core/os/output.cairo @@ -4,103 +4,101 @@ from starkware.cairo.common.serialize import serialize_word from starkware.starknet.core.os.block_context import BlockContext, BlockInfo from starkware.starknet.core.os.state import CommitmentTreeUpdateOutput -# An L2 to L1 message header, the message payload is concatenated to the end of the header. -struct MessageToL1Header: - # The L2 address of the contract sending the message. - member from_address : felt - # The L1 address of the contract receiving the message. - member to_address : felt - member payload_size : felt -end - -# An L1 to L2 message header, the message payload is concatenated to the end of the header. -struct MessageToL2Header: - # The L1 address of the contract sending the message. - member from_address : felt - # The L2 address of the contract receiving the message. - member to_address : felt - member nonce : felt - member selector : felt - member payload_size : felt -end - -# A contract deployment information header. -# Call data of size 'calldata_size' is concatenated to the end of the header. -struct DeploymentInfoHeader: - member contract_address : felt - member class_hash : felt - member calldata_size : felt -end - -# Holds all the information that StarkNet's OS needs to output. -struct OsCarriedOutputs: - member messages_to_l1 : MessageToL1Header* - member messages_to_l2 : MessageToL2Header* - # A concatenated list of deployment infos, each consists of DeploymentInfoHeader and calldata. - member deployment_info : DeploymentInfoHeader* -end +// An L2 to L1 message header, the message payload is concatenated to the end of the header. +struct MessageToL1Header { + // The L2 address of the contract sending the message. + from_address: felt, + // The L1 address of the contract receiving the message. + to_address: felt, + payload_size: felt, +} + +// An L1 to L2 message header, the message payload is concatenated to the end of the header. +struct MessageToL2Header { + // The L1 address of the contract sending the message. + from_address: felt, + // The L2 address of the contract receiving the message. + to_address: felt, + nonce: felt, + selector: felt, + payload_size: felt, +} + +// Contract deployment information. +struct DeploymentInfo { + contract_address: felt, + class_hash: felt, +} + +// Holds all the information that StarkNet's OS needs to output. +struct OsCarriedOutputs { + messages_to_l1: MessageToL1Header*, + messages_to_l2: MessageToL2Header*, + // A concatenated list of deployment infos. + deployment_info: DeploymentInfo*, +} func os_carried_outputs_new( - messages_to_l1 : MessageToL1Header*, - messages_to_l2 : MessageToL2Header*, - deployment_info : DeploymentInfoHeader*, -) -> (os_carried_outputs : OsCarriedOutputs*): - let (fp_val, pc_val) = get_fp_and_pc() - static_assert OsCarriedOutputs.SIZE == Args.SIZE - return (os_carried_outputs=cast(fp_val - 2 - OsCarriedOutputs.SIZE, OsCarriedOutputs*)) -end - -func os_output_serialize{output_ptr : felt*}( - block_context : BlockContext*, - commitment_tree_update_output : CommitmentTreeUpdateOutput*, - initial_carried_outputs : OsCarriedOutputs*, - final_carried_outputs : OsCarriedOutputs*, - storage_updates_ptr_start : felt*, - storage_updates_ptr_end : felt*, - starknet_os_config_hash : felt, -): - # Serialize program output. - - # Serialize roots. - serialize_word(commitment_tree_update_output.initial_storage_root) - serialize_word(commitment_tree_update_output.final_storage_root) - - serialize_word(block_context.block_info.block_number) - serialize_word(starknet_os_config_hash) + messages_to_l1: MessageToL1Header*, + messages_to_l2: MessageToL2Header*, + deployment_info: DeploymentInfo*, +) -> (os_carried_outputs: OsCarriedOutputs*) { + let (fp_val, pc_val) = get_fp_and_pc(); + static_assert OsCarriedOutputs.SIZE == Args.SIZE; + return (os_carried_outputs=cast(fp_val - 2 - OsCarriedOutputs.SIZE, OsCarriedOutputs*)); +} + +func os_output_serialize{output_ptr: felt*}( + block_context: BlockContext*, + commitment_tree_update_output: CommitmentTreeUpdateOutput*, + initial_carried_outputs: OsCarriedOutputs*, + final_carried_outputs: OsCarriedOutputs*, + storage_updates_ptr_start: felt*, + storage_updates_ptr_end: felt*, + starknet_os_config_hash: felt, +) { + // Serialize program output. + + // Serialize roots. + serialize_word(commitment_tree_update_output.initial_storage_root); + serialize_word(commitment_tree_update_output.final_storage_root); + + serialize_word(block_context.block_info.block_number); + serialize_word(starknet_os_config_hash); let messages_to_l1_segment_size = ( final_carried_outputs.messages_to_l1 - - initial_carried_outputs.messages_to_l1) - serialize_word(messages_to_l1_segment_size) + initial_carried_outputs.messages_to_l1); + serialize_word(messages_to_l1_segment_size); - # Relocate 'messages_to_l1_segment' to the correct place in the output segment. - relocate_segment(src_ptr=initial_carried_outputs.messages_to_l1, dest_ptr=output_ptr) - let output_ptr = cast(final_carried_outputs.messages_to_l1, felt*) + // Relocate 'messages_to_l1_segment' to the correct place in the output segment. + relocate_segment(src_ptr=initial_carried_outputs.messages_to_l1, dest_ptr=output_ptr); + let output_ptr = cast(final_carried_outputs.messages_to_l1, felt*); let messages_to_l2_segment_size = ( final_carried_outputs.messages_to_l2 - - initial_carried_outputs.messages_to_l2) - serialize_word(messages_to_l2_segment_size) + initial_carried_outputs.messages_to_l2); + serialize_word(messages_to_l2_segment_size); - # Relocate 'messages_to_l2_segment' to the correct place in the output segment. - relocate_segment(src_ptr=initial_carried_outputs.messages_to_l2, dest_ptr=output_ptr) - let output_ptr = cast(final_carried_outputs.messages_to_l2, felt*) + // Relocate 'messages_to_l2_segment' to the correct place in the output segment. + relocate_segment(src_ptr=initial_carried_outputs.messages_to_l2, dest_ptr=output_ptr); + let output_ptr = cast(final_carried_outputs.messages_to_l2, felt*); - # Serialize data availability. - let da_start = output_ptr + // Serialize data availability. + let da_start = output_ptr; let deployment_info_segment_size = ( final_carried_outputs.deployment_info - - initial_carried_outputs.deployment_info) - serialize_word(deployment_info_segment_size) + initial_carried_outputs.deployment_info); + serialize_word(deployment_info_segment_size); - # Relocate 'deployment_info_segment' to the correct place in the output segment. - relocate_segment(src_ptr=initial_carried_outputs.deployment_info, dest_ptr=output_ptr) - let output_ptr = cast(final_carried_outputs.deployment_info, felt*) + // Relocate 'deployment_info_segment' to the correct place in the output segment. + relocate_segment(src_ptr=initial_carried_outputs.deployment_info, dest_ptr=output_ptr); + let output_ptr = cast(final_carried_outputs.deployment_info, felt*); - # Relocate 'storage_updates_segment' to the correct place in the output segment. - relocate_segment(src_ptr=storage_updates_ptr_start, dest_ptr=output_ptr) - let output_ptr = storage_updates_ptr_end + // Relocate 'storage_updates_segment' to the correct place in the output segment. + relocate_segment(src_ptr=storage_updates_ptr_start, dest_ptr=output_ptr); + let output_ptr = storage_updates_ptr_end; %{ from starkware.python.math_utils import div_ceil @@ -134,5 +132,5 @@ func os_output_serialize{output_ptr : felt*}( ]) %} - return () -end + return (); +} diff --git a/src/starkware/starknet/core/os/program_hash.json b/src/starkware/starknet/core/os/program_hash.json index 8b2658c3..c9f471db 100644 --- a/src/starkware/starknet/core/os/program_hash.json +++ b/src/starkware/starknet/core/os/program_hash.json @@ -1,3 +1,3 @@ { - "program_hash": "0x685cd631b8a3aab798fbada2cf5db713b6080d6fdc7f6cf6218f37ac48e857d" + "program_hash": "0x3695a2473fbe96955d7f2070389e0ea2d57fc0271fb1fc8391c77ef9a9cf55d" } diff --git a/src/starkware/starknet/core/os/program_hash_test.py b/src/starkware/starknet/core/os/program_hash_test.py index fd70ac54..1980f89f 100644 --- a/src/starkware/starknet/core/os/program_hash_test.py +++ b/src/starkware/starknet/core/os/program_hash_test.py @@ -7,7 +7,10 @@ from starkware.python.utils import get_source_dir_path PROGRAM_PATH = os.path.join(os.path.dirname(__file__), "starknet_os_compiled.json") -HASH_PATH = get_source_dir_path("src/starkware/starknet/core/os/program_hash.json") +HASH_PATH = get_source_dir_path( + "src/starkware/starknet/core/os/program_hash.json", + default_value=os.path.join(os.path.dirname(__file__), "program_hash.json"), +) COMMAND = "generate_starknet_os_program_hash" diff --git a/src/starkware/starknet/core/os/state.cairo b/src/starkware/starknet/core/os/state.cairo index c351cdf1..ba59a78a 100644 --- a/src/starkware/starknet/core/os/state.cairo +++ b/src/starkware/starknet/core/os/state.cairo @@ -2,6 +2,7 @@ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.dict import DictAccess, squash_dict from starkware.cairo.common.hash import hash2 +from starkware.cairo.common.math import assert_nn_le from starkware.cairo.common.patricia import ( ParticiaGlobals, PatriciaUpdateConstants, @@ -10,81 +11,105 @@ from starkware.cairo.common.patricia import ( ) from starkware.cairo.common.segments import relocate_segment -const MERKLE_HEIGHT = 251 # PRIME.bit_length() - 1. - -struct CommitmentTreeUpdateOutput: - member initial_storage_root : felt - member final_storage_root : felt -end - -struct StateEntry: - member class_hash : felt - member storage_ptr : DictAccess* -end - -struct StorageUpdateEntry: - member address : felt - member value : felt -end - -func serialize_da_changes{storage_updates : StorageUpdateEntry*}( - update_ptr : DictAccess*, n_updates : felt -): - if n_updates == 0: - return () - end - if update_ptr.prev_value == update_ptr.new_value: - tempvar storage_updates = storage_updates - else: +const MERKLE_HEIGHT = 251; // PRIME.bit_length() - 1. +const UNINITIALIZED_CLASS_HASH = 0; + +// The on-chain data for contract state changes has the following format: +// +// * The number of affected contracts. +// * For each contract: +// * The contract address (1 word). +// * Number of entry updates and the new nonce (1 word): +// +-----------+-------------+ LSB +// | new nonce | n_updates + +// | 64 bits | 64 bits + +// +-----------+-------------+ +// * For each entry update: +// * key (1 word). +// * new value (1 word). + +// A bound on the number of storage entry updates in a contract. +const N_UPDATES_BOUND = 2 ** 64; +// A bound on the nonce of a contract. +const NONCE_BOUND = 2 ** 64; + +struct CommitmentTreeUpdateOutput { + initial_storage_root: felt, + final_storage_root: felt, +} + +struct StateEntry { + class_hash: felt, + storage_ptr: DictAccess*, + nonce: felt, +} + +// Represents an update of a storage entry of a contract. +struct StorageUpdateEntry { + // The entry's key. + key: felt, + // The new value. + value: felt, +} + +func serialize_da_changes{storage_updates: StorageUpdateEntry*}( + update_ptr: DictAccess*, n_updates: felt +) { + if (n_updates == 0) { + return (); + } + if (update_ptr.prev_value == update_ptr.new_value) { + tempvar storage_updates = storage_updates; + } else { assert [storage_updates] = StorageUpdateEntry( - address=update_ptr.key, value=update_ptr.new_value) - tempvar storage_updates = storage_updates + StorageUpdateEntry.SIZE - end - return serialize_da_changes(update_ptr=update_ptr + DictAccess.SIZE, n_updates=n_updates - 1) -end - -# Performs the commitment tree updates required for (validating and) updating the global state. -# Returns a CommitmentTreeUpdateOutput struct. -# Checks that [state_changes_dict, state_changes_dict_end) is a valid according to squash_dict. -func state_update{hash_ptr : HashBuiltin*, range_check_ptr, storage_updates_ptr : felt*}( - state_changes_dict : DictAccess*, state_changes_dict_end : DictAccess* -) -> (commitment_tree_update_output : CommitmentTreeUpdateOutput*): - alloc_locals - let (local squashed_dict : DictAccess*) = alloc() - - # Squash the global dictionary to get a list of triples (addr, dict_begin, dict_end). + key=update_ptr.key, value=update_ptr.new_value); + tempvar storage_updates = storage_updates + StorageUpdateEntry.SIZE; + } + return serialize_da_changes(update_ptr=update_ptr + DictAccess.SIZE, n_updates=n_updates - 1); +} + +// Performs the commitment tree updates required for (validating and) updating the global state. +// Returns a CommitmentTreeUpdateOutput struct. +// Checks that [state_changes_dict, state_changes_dict_end) is a valid according to squash_dict. +// Writes the changed values into storage_updates_ptr, to make this data available on-chain. +func state_update{hash_ptr: HashBuiltin*, range_check_ptr, storage_updates_ptr: felt*}( + state_changes_dict: DictAccess*, state_changes_dict_end: DictAccess* +) -> (commitment_tree_update_output: CommitmentTreeUpdateOutput*) { + alloc_locals; + let (local squashed_dict: DictAccess*) = alloc(); + + // Squash the global dictionary to get a list of triples (addr, dict_begin, dict_end). let (squashed_dict_end) = squash_dict( dict_accesses=state_changes_dict, dict_accesses_end=state_changes_dict_end, squashed_dict=squashed_dict, - ) - - # Hash the entries of state_changes_dict to prepare the input for the commitment tree - # multi-update. - let (local hashed_state_changes : DictAccess*) = alloc() - local n_state_changes = (squashed_dict_end - squashed_dict) / DictAccess.SIZE - # Make room for number of state updates. - let output_n_updates = [storage_updates_ptr] - let storage_updates_ptr = storage_updates_ptr + 1 - let n_actual_state_changes = 0 - # Creates PatriciaUpdateConstants struct for patricia update. - let ( - local patricia_update_constants : PatriciaUpdateConstants* - ) = patricia_update_constants_new() - - with n_actual_state_changes: + ); + + // Hash the entries of state_changes_dict to prepare the input for the commitment tree + // multi-update. + let (local hashed_state_changes: DictAccess*) = alloc(); + local n_state_changes = (squashed_dict_end - squashed_dict) / DictAccess.SIZE; + // Make room for number of state updates. + let output_n_updates = [storage_updates_ptr]; + let storage_updates_ptr = storage_updates_ptr + 1; + let n_actual_state_changes = 0; + // Creates PatriciaUpdateConstants struct for patricia update. + let (local patricia_update_constants: PatriciaUpdateConstants*) = patricia_update_constants_new( + ); + + with n_actual_state_changes { hash_state_changes( n_state_changes=n_state_changes, state_changes=squashed_dict, hashed_state_changes=hashed_state_changes, patricia_update_constants=patricia_update_constants, - ) - end - # Write number of state updates. - assert output_n_updates = n_actual_state_changes + ); + } + // Write number of state updates. + assert output_n_updates = n_actual_state_changes; - # Compute the initial and final roots of the global state. - let (local commitment_tree_update_output : CommitmentTreeUpdateOutput*) = alloc() + // Compute the initial and final roots of the global state. + let (local commitment_tree_update_output: CommitmentTreeUpdateOutput*) = alloc(); %{ from starkware.python.utils import from_bytes @@ -100,8 +125,8 @@ func state_update{hash_ptr : HashBuiltin*, range_check_ptr, storage_updates_ptr assert global_state_storage.commitment_tree.height == ids.MERKLE_HEIGHT %} - # Call patricia_update_using_update_constants() instead of patricia_update() - # in order not to repeat globals_pow2 calculation. + // Call patricia_update_using_update_constants() instead of patricia_update() + // in order not to repeat globals_pow2 calculation. patricia_update_using_update_constants( patricia_update_constants=patricia_update_constants, update_ptr=hashed_state_changes, @@ -109,57 +134,59 @@ func state_update{hash_ptr : HashBuiltin*, range_check_ptr, storage_updates_ptr height=MERKLE_HEIGHT, prev_root=commitment_tree_update_output.initial_storage_root, new_root=commitment_tree_update_output.final_storage_root, - ) - - return (commitment_tree_update_output=commitment_tree_update_output) -end - -func get_contract_state_hash{hash_ptr : HashBuiltin*}(class_hash : felt, storage_root : felt) -> ( - hash : felt -): - const CONTRACT_STATE_HASH_VERSION = 0 - const RESERVED = 0 - if class_hash == 0: - if storage_root == 0: - return (hash=0) - end - end - - # Set res = H(H(class_hash, storage_root), RESERVED). - let (hash_value) = hash2(class_hash, storage_root) - let (hash_value) = hash2(hash_value, RESERVED) - - # Return H(hash_value, CONTRACT_STATE_HASH_VERSION). CONTRACT_STATE_HASH_VERSION must be in the - # outermost hash to guarantee unique "decoding". - let (hash) = hash2(hash_value, CONTRACT_STATE_HASH_VERSION) - return (hash=hash) -end - -# Takes a dict of StateEntry structs and produces a dict of hashes by hashing -# every entry of the input dict. The output is written to 'hashed_state_changes' -# -# Writes all updates to the 'global_state_storage' hint variable. -# -# Writes all storage changes to output (storage_updates_ptr), 'n_actual_state_changes' -# will hold the number of contracts with storage changes. + ); + + return (commitment_tree_update_output=commitment_tree_update_output); +} + +func get_contract_state_hash{hash_ptr: HashBuiltin*}( + class_hash: felt, storage_root: felt, nonce: felt +) -> (hash: felt) { + const CONTRACT_STATE_HASH_VERSION = 0; + if (class_hash == UNINITIALIZED_CLASS_HASH) { + if (storage_root == 0) { + if (nonce == 0) { + return (hash=0); + } + } + } + + // Set res = H(H(class_hash, storage_root), nonce). + let (hash_value) = hash2(class_hash, storage_root); + let (hash_value) = hash2(hash_value, nonce); + + // Return H(hash_value, CONTRACT_STATE_HASH_VERSION). CONTRACT_STATE_HASH_VERSION must be in the + // outermost hash to guarantee unique "decoding". + let (hash) = hash2(hash_value, CONTRACT_STATE_HASH_VERSION); + return (hash=hash); +} + +// Takes a dict of StateEntry structs and produces a dict of hashes by hashing +// every entry of the input dict. The output is written to 'hashed_state_changes' +// +// Writes all updates to the 'global_state_storage' hint variable. +// +// Writes all storage changes to output (storage_updates_ptr), 'n_actual_state_changes' +// will hold the number of contracts with storage changes. func hash_state_changes{ - hash_ptr : HashBuiltin*, range_check_ptr, storage_updates_ptr : felt*, n_actual_state_changes + hash_ptr: HashBuiltin*, range_check_ptr, storage_updates_ptr: felt*, n_actual_state_changes }( n_state_changes, - state_changes : DictAccess*, - hashed_state_changes : DictAccess*, - patricia_update_constants : PatriciaUpdateConstants*, -): - if n_state_changes == 0: - return () - end - alloc_locals - - local prev_state : StateEntry* = cast(state_changes.prev_value, StateEntry*) - local new_state : StateEntry* = cast(state_changes.new_value, StateEntry*) - let (local squashed_storage_dict : DictAccess*) = alloc() - local initial_storage_root - local final_storage_root + state_changes: DictAccess*, + hashed_state_changes: DictAccess*, + patricia_update_constants: PatriciaUpdateConstants*, +) { + if (n_state_changes == 0) { + return (); + } + alloc_locals; + + local prev_state: StateEntry* = cast(state_changes.prev_value, StateEntry*); + local new_state: StateEntry* = cast(state_changes.new_value, StateEntry*); + local new_state_nonce = new_state.nonce; + let (local squashed_storage_dict: DictAccess*) = alloc(); + local initial_storage_root; + local final_storage_root; %{ from starkware.python.utils import from_bytes @@ -178,11 +205,11 @@ func hash_state_changes{ dict_accesses=prev_state.storage_ptr, dict_accesses_end=new_state.storage_ptr, squashed_dict=squashed_storage_dict, - ) + ); - local n_updates = (squashed_storage_dict_end - squashed_storage_dict) / DictAccess.SIZE - # Call patricia_update_using_update_constants() instead of patricia_update() - # in order not to repeat globals_pow2 calculation. + local n_updates = (squashed_storage_dict_end - squashed_storage_dict) / DictAccess.SIZE; + // Call patricia_update_using_update_constants() instead of patricia_update() + // in order not to repeat globals_pow2 calculation. patricia_update_using_update_constants( patricia_update_constants=patricia_update_constants, update_ptr=squashed_storage_dict, @@ -190,64 +217,66 @@ func hash_state_changes{ height=MERKLE_HEIGHT, prev_root=initial_storage_root, new_root=final_storage_root, - ) + ); let (prev_value) = get_contract_state_hash( - class_hash=prev_state.class_hash, storage_root=initial_storage_root - ) - assert hashed_state_changes.prev_value = prev_value + class_hash=prev_state.class_hash, storage_root=initial_storage_root, nonce=prev_state.nonce + ); + assert hashed_state_changes.prev_value = prev_value; let (new_value) = get_contract_state_hash( - class_hash=new_state.class_hash, storage_root=final_storage_root - ) - assert hashed_state_changes.new_value = new_value - assert hashed_state_changes.key = state_changes.key + class_hash=new_state.class_hash, storage_root=final_storage_root, nonce=new_state_nonce + ); + assert hashed_state_changes.new_value = new_value; + assert hashed_state_changes.key = state_changes.key; %{ global_state_storage.write(address=ids.hashed_state_changes.key, value=ids.new_value) %} - let hashed_state_changes = hashed_state_changes + DictAccess.SIZE + let hashed_state_changes = hashed_state_changes + DictAccess.SIZE; - # Write storage updates to output (storage_updates_ptr). + // Write storage updates to output (storage_updates_ptr). - # Prepare updates. - local storage_updates_start : StorageUpdateEntry* + // Prepare updates. + local storage_updates_start: StorageUpdateEntry*; %{ ids.storage_updates_start = segments.add_temp_segment() %} - let storage_updates = storage_updates_start - with storage_updates: - serialize_da_changes(update_ptr=squashed_storage_dict, n_updates=n_updates) - end + let storage_updates = storage_updates_start; + with storage_updates { + serialize_da_changes(update_ptr=squashed_storage_dict, n_updates=n_updates); + } - # Number of actual updates. - local n_updates = (storage_updates - storage_updates_start) / StorageUpdateEntry.SIZE + // Number of actual updates. + local n_updates = (storage_updates - storage_updates_start) / StorageUpdateEntry.SIZE; - if n_updates == 0: - # Relocate the temporary segment even if it's empty (to fix the addresses written in - # the memory). - relocate_segment(src_ptr=storage_updates_start, dest_ptr=storage_updates_ptr) + if (n_updates == 0 and new_state_nonce == prev_state.nonce) { + // Relocate the temporary segment even if it's empty (to fix the addresses written in + // the memory). + relocate_segment(src_ptr=storage_updates_start, dest_ptr=storage_updates_ptr); - # There are no storage updates for this contract. + // There are no storage updates for this contract. return hash_state_changes( n_state_changes=n_state_changes - 1, state_changes=state_changes + DictAccess.SIZE, hashed_state_changes=hashed_state_changes, patricia_update_constants=patricia_update_constants, - ) - end + ); + } - # Write contract address and number of updates. - assert [storage_updates_ptr] = state_changes.key - assert [storage_updates_ptr + 1] = n_updates - let storage_updates_ptr = storage_updates_ptr + 2 + // Write contract address, nonce and number of updates. + assert [storage_updates_ptr] = state_changes.key; + assert_nn_le(n_updates, N_UPDATES_BOUND - 1); + assert_nn_le(new_state_nonce, NONCE_BOUND - 1); + assert [storage_updates_ptr + 1] = new_state_nonce * N_UPDATES_BOUND + n_updates; + let storage_updates_ptr = storage_updates_ptr + 2; - # Write the updates. - relocate_segment(src_ptr=storage_updates_start, dest_ptr=storage_updates_ptr) - let storage_updates_ptr = cast(storage_updates, felt*) + // Write the updates. + relocate_segment(src_ptr=storage_updates_start, dest_ptr=storage_updates_ptr); + let storage_updates_ptr = cast(storage_updates, felt*); - let n_actual_state_changes = n_actual_state_changes + 1 + let n_actual_state_changes = n_actual_state_changes + 1; return hash_state_changes( n_state_changes=n_state_changes - 1, state_changes=state_changes + DictAccess.SIZE, hashed_state_changes=hashed_state_changes, patricia_update_constants=patricia_update_constants, - ) -end + ); +} diff --git a/src/starkware/starknet/core/os/syscall_utils.py b/src/starkware/starknet/core/os/syscall_utils.py index 3583b873..4b6375a0 100644 --- a/src/starkware/starknet/core/os/syscall_utils.py +++ b/src/starkware/starknet/core/os/syscall_utils.py @@ -1,4 +1,3 @@ -import asyncio import contextlib import dataclasses from abc import ABC, abstractmethod @@ -34,24 +33,19 @@ TransactionExecutionContext, TransactionExecutionInfo, ) -from starkware.starknet.business_logic.state.objects import ( - ContractCarriedState, - ContractClassFact, - ContractState, -) -from starkware.starknet.business_logic.state.state import BlockInfo, CarriedState +from starkware.starknet.business_logic.fact_state.state import ExecutionResourcesManager +from starkware.starknet.business_logic.state.state import ContractStorageState +from starkware.starknet.business_logic.state.state_api import SyncState +from starkware.starknet.business_logic.state.state_api_objects import BlockInfo from starkware.starknet.core.os.contract_address.contract_address import ( calculate_contract_address_from_hash, ) from starkware.starknet.core.os.os_program import get_os_program -from starkware.starknet.definitions import fields from starkware.starknet.definitions.error_codes import StarknetErrorCode from starkware.starknet.definitions.general_config import StarknetGeneralConfig -from starkware.starknet.services.api.contract_class import CONSTRUCTOR_SELECTOR, EntryPointType -from starkware.starknet.storage.starknet_storage import ( - BusinessLogicStarknetStorage, - OsSingleStarknetStorage, -) +from starkware.starknet.public.abi import CONSTRUCTOR_ENTRY_POINT_SELECTOR +from starkware.starknet.services.api.contract_class import EntryPointType +from starkware.starknet.storage.starknet_storage import OsSingleStarknetStorage from starkware.starkware_utils.error_handling import StarkException, stark_assert TCallable = TypeVar("TCallable", bound=Callable) @@ -297,7 +291,7 @@ def get_block_number(self, segments: MemorySegmentManager, syscall_ptr: Relocata syscall_name="get_block_number", segments=segments, syscall_ptr=syscall_ptr ) - block_number = self._get_block_number() + block_number = self.block_info.block_number response = self.structs.GetBlockNumberResponse(block_number=block_number) self._write_syscall_response( @@ -354,7 +348,7 @@ def get_block_timestamp(self, segments: MemorySegmentManager, syscall_ptr: Reloc syscall_name="get_block_timestamp", segments=segments, syscall_ptr=syscall_ptr ) - block_timestamp = self._get_block_timestamp() + block_timestamp = self.block_info.block_timestamp response = self.structs.GetBlockTimestampResponse(block_timestamp=block_timestamp) self._write_syscall_response( @@ -516,18 +510,6 @@ def _call_contract_and_write_response( syscall_ptr=syscall_ptr, ) - @abstractmethod - def _get_block_number(self) -> int: - """ - Specific implementation of the get_block_number system call. - """ - - @abstractmethod - def _get_block_timestamp(self) -> int: - """ - Specific implementation of the get_block_timestamp system call. - """ - @abstractmethod def _get_caller_address( self, segments: MemorySegmentManager, syscall_ptr: RelocatableValue @@ -587,10 +569,10 @@ def __init__( self, execute_entry_point_cls: Type[ExecuteEntryPointBase], tx_execution_context: TransactionExecutionContext, - state: CarriedState, + state: SyncState, + resources_manager: ExecutionResourcesManager, caller_address: int, contract_address: int, - starknet_storage: BusinessLogicStarknetStorage, general_config: StarknetGeneralConfig, initial_syscall_ptr: RelocatableValue, ): @@ -599,25 +581,25 @@ def __init__( # Configuration objects. self.general_config = general_config - # Storage-related members. - self.starknet_storage = starknet_storage - self.loop = starknet_storage.loop - # Execution-related objects. self.execute_entry_point_cls = execute_entry_point_cls self.tx_execution_context = tx_execution_context - self.state = state + self.sync_state = state + self.resources_manager = resources_manager self.caller_address = caller_address self.contract_address = contract_address + # Storage-related members. + self.starknet_storage = ContractStorageState( + state=self.sync_state, contract_address=contract_address + ) + # Internal calls executed by the current contract call. self.internal_calls: List[CallInfo] = [] # Events emitted by the current contract call. self.events: List[OrderedEvent] = [] # Messages sent by the current contract call to L1. self.l2_to_l1_messages: List[OrderedL2ToL1Message] = [] - # Addresses of contracts deployed by the current contract call. - self.deployed_contracts: List[int] = [] # Kept for validations during the run. self.expected_syscall_ptr = initial_syscall_ptr @@ -637,8 +619,8 @@ def _allocate_segment( return segment_start def _count_syscall(self, syscall_name: str): - previous_syscall_count = self.state.syscall_counter.get(syscall_name, 0) - self.state.syscall_counter[syscall_name] = previous_syscall_count + 1 + previous_syscall_count = self.resources_manager.syscall_counter.get(syscall_name, 0) + self.resources_manager.syscall_counter[syscall_name] = previous_syscall_count + 1 def _read_and_validate_syscall_request( self, syscall_name: str, segments: MemorySegmentManager, syscall_ptr: RelocatableValue @@ -767,15 +749,9 @@ def _deploy(self, segments: MemorySegmentManager, syscall_ptr: RelocatableValue) # Initialize the contract. class_hash_bytes = to_bytes(class_hash) - future = asyncio.run_coroutine_threadsafe( - coro=initialize_contract_state( - state=self.state, - class_hash=class_hash_bytes, - contract_address=contract_address, - ), - loop=self.loop, + self.sync_state.deploy_contract( + contract_address=contract_address, class_hash=class_hash_bytes ) - future.result() self.execute_constructor_entry_point( contract_address=contract_address, @@ -783,15 +759,12 @@ def _deploy(self, segments: MemorySegmentManager, syscall_ptr: RelocatableValue) constructor_calldata=constructor_calldata, ) - # Update deployed contract addresses. - self.deployed_contracts.append(contract_address) - return contract_address def execute_constructor_entry_point( self, contract_address: int, class_hash_bytes: bytes, constructor_calldata: List[int] ): - contract_class = self.state.get_contract_class(class_hash=class_hash_bytes) + contract_class = self.sync_state.get_contract_class(class_hash=class_hash_bytes) constructor_entry_points = contract_class.entry_points_by_type[EntryPointType.CONSTRUCTOR] if len(constructor_entry_points) == 0: # Contract has no constructor. @@ -813,7 +786,7 @@ def execute_constructor_entry_point( class_hash=None, contract_address=contract_address, code_address=contract_address, - entry_point_selector=CONSTRUCTOR_SELECTOR, + entry_point_selector=CONSTRUCTOR_ENTRY_POINT_SELECTOR, entry_point_type=EntryPointType.CONSTRUCTOR, calldata=constructor_calldata, caller_address=self.contract_address, @@ -823,10 +796,10 @@ def execute_constructor_entry_point( def execute_entry_point(self, call: ExecuteEntryPointBase) -> List[int]: with self.entry_point_execution_context(call=call): # Execute contract call. - call_info = call.sync_execute( - state=self.state, + call_info = call.execute( + state=self.sync_state, + resources_manager=self.resources_manager, general_config=self.general_config, - loop=self.loop, tx_execution_context=self.tx_execution_context, ) @@ -837,15 +810,12 @@ def execute_entry_point(self, call: ExecuteEntryPointBase) -> List[int]: @contextlib.contextmanager def entry_point_execution_context(self, call: ExecuteEntryPointBase): - # Pre-execution preperation and validations. - self._enrich_state(call=call) - try: yield except StarkException as exception: raise HandlerException( called_contract_address=call.contract_address, stark_exception=exception - ) + ) from exception except Exception as exception: # Exceptions caught here that are not StarkException, are necessarily caused due to # security issues, since every exception raised from a Cairo run (in _run) is already @@ -855,39 +825,7 @@ def entry_point_execution_context(self, call: ExecuteEntryPointBase): ) raise HandlerException( called_contract_address=call.contract_address, stark_exception=stark_exception - ) - - # Post-execution updates. - self._update_starknet_storage() - - def _enrich_state(self, call: ExecuteEntryPointBase): - """ - Prepares the state for the execution of the given call. - """ - # Apply current modifications to the origin contract storage, in case there will be - # future nested calls to this contract. - self.state.update_contract_storage( - contract_address=self.contract_address, - modifications=self.starknet_storage.get_modifications(), - ) - - # Fetch required information for the call (that is not already cached in the state). - state_selector = call.get_state_selector() - state_selector -= self.state.state_selector - future_extra_state = asyncio.run_coroutine_threadsafe( - coro=self.state.shared_state.get_filled_carried_state( - ffc=self.state.ffc, state_selector=state_selector - ), - loop=self.loop, - ) - self.state.fill_missing(other=future_extra_state.result()) - - def _update_starknet_storage(self): - """ - Updates the StarkNet storage of the current run after a contract call. - """ - contract_storage_updates = self.state.contract_states[self.contract_address].storage_updates - self.starknet_storage.reset_state(storage_updates=contract_storage_updates) + ) from exception def emit_event(self, segments: MemorySegmentManager, syscall_ptr: RelocatableValue): """ @@ -924,6 +862,7 @@ def _get_tx_info_ptr(self, segments: MemorySegmentManager) -> RelocatableValue: segments=segments, data=self.tx_execution_context.signature ), chain_id=self.general_config.chain_id.value, + nonce=self.tx_execution_context.nonce, ) self.tx_info_ptr = self._allocate_segment(segments=segments, data=tx_info) @@ -950,12 +889,6 @@ def send_message_to_l1(self, segments: MemorySegmentManager, syscall_ptr: Reloca # Update messages count. self.tx_execution_context.n_sent_messages += 1 - def _get_block_number(self) -> int: - return self.state.block_info.block_number - - def _get_block_timestamp(self) -> int: - return self.state.block_info.block_timestamp - def _get_caller_address( self, segments: MemorySegmentManager, syscall_ptr: RelocatableValue ) -> int: @@ -987,8 +920,8 @@ def _storage_write(self, address: int, value: int): # Update modified contracts (for the bouncer). # Note that this is a simplified update - we are considering every write # as a new change in storage (w.r.t. the state of the previous batch), but it could be that - # a write actually cancles a change; e.g., 0 -> 5, 5 -> 0. - self.state.modified_contracts[self.contract_address] = None + # a write actually cancels a change; e.g., 0 -> 5, 5 -> 0. + self.resources_manager.modified_contracts[self.contract_address] = None def get_sequencer_address(self, segments: MemorySegmentManager, syscall_ptr: RelocatableValue): return super().get_sequencer_address(segments=segments, syscall_ptr=syscall_ptr) @@ -1024,62 +957,6 @@ def post_run(self, runner: CairoFunctionRunner, syscall_stop_ptr: MaybeRelocatab self.validate_read_only_segments(runner=runner) -# Shared utilities with InternalDeploy. -async def initialize_contract_state( - state: CarriedState, - class_hash: bytes, - contract_address: int, -): - """ - Initializes a new ContractState object at the given address - (after verifying that it is available). - """ - if contract_address not in state.contract_states: - # The contract address was not known in advance; e.g., when deploying a contract. - # Fetch and cache contract state. - contract_state = await state.shared_state.contract_states.get_leaf( - ffc=state.ffc, index=contract_address, fact_cls=ContractState - ) - state.contract_states[contract_address] = ContractCarriedState.from_state( - state=contract_state - ) - - # Extract ContractState object from carried state and validate. - contract_state = state.contract_states[contract_address].state - stark_assert( - not contract_state.initialized, - code=StarknetErrorCode.CONTRACT_ADDRESS_UNAVAILABLE, - message=f"Requested contract address {contract_address} is unavailable for deployment.", - ) - - if class_hash not in state.contract_definitions: - # Fetch contract class from storage. - contract_class_fact = await ContractClassFact.get( - storage=state.ffc.storage, suffix=class_hash - ) - if contract_class_fact is None: - formatted_class_hash = fields.class_hash_from_bytes(class_hash=class_hash) - raise StarkException( - code=StarknetErrorCode.UNDECLARED_CLASS, - message=f"Class with hash {formatted_class_hash} is not declared.", - ) - # Add contract class to carried state. - state.contract_definitions[class_hash] = contract_class_fact.contract_definition - - contract_class = state.get_contract_class(class_hash=class_hash) - - contract_class.validate() - - # Create updated contract state. - newly_deployed_contract_state = await ContractState.create( - contract_hash=class_hash, - storage_commitment_tree=contract_state.storage_commitment_tree, - ) - state.contract_states[contract_address] = ContractCarriedState.from_state( - state=newly_deployed_contract_state - ) - - class OsSysCallHandler(SysCallHandlerBase): """ The SysCallHandler implementation that is used by the gps ambassador. @@ -1168,12 +1045,6 @@ def _deploy(self, segments: MemorySegmentManager, syscall_ptr: RelocatableValue) assert len(constructor_retdata) == 0, "Unexpected constructor_retdata." return next(self.deployed_contracts_iterator) - def _get_block_number(self) -> int: - return self.block_info.block_number - - def _get_block_timestamp(self) -> int: - return self.block_info.block_timestamp - def _get_caller_address( self, segments: MemorySegmentManager, syscall_ptr: RelocatableValue ) -> int: @@ -1256,3 +1127,10 @@ def exit_call(self): call_state = self.call_stack.pop() assert_exhausted(iterator=call_state.execute_syscall_read_iterator) + + def skip_tx(self): + """ + Called when skipping the execution of a transaction. + It replaces a call to start_tx and end_tx. + """ + next(self.tx_execution_info_iterator) diff --git a/src/starkware/starknet/core/os/transaction_hash/CMakeLists.txt b/src/starkware/starknet/core/os/transaction_hash/CMakeLists.txt index adc2330c..235a2a03 100644 --- a/src/starkware/starknet/core/os/transaction_hash/CMakeLists.txt +++ b/src/starkware/starknet/core/os/transaction_hash/CMakeLists.txt @@ -9,13 +9,12 @@ full_python_test(starknet_transaction_hash_test LIBS cairo_common_lib cairo_function_runner_lib - starknet_contract_class_lib + starknet_abi_lib starknet_definitions_lib starknet_os_abi_lib starknet_os_utils_lib starknet_test_external_contract_test_utils_lib starknet_transaction_hash_lib - starknet_transaction_lib starkware_crypto_lib pip_pytest pip_pytest_asyncio @@ -30,6 +29,7 @@ python_lib(starknet_transaction_hash_lib LIBS cairo_common_lib cairo_vm_crypto_lib + starknet_abi_lib starknet_contract_class_lib starknet_definitions_lib starknet_os_abi_lib diff --git a/src/starkware/starknet/core/os/transaction_hash/transaction_hash.cairo b/src/starkware/starknet/core/os/transaction_hash/transaction_hash.cairo index 8a69eeb2..e7102bd3 100644 --- a/src/starkware/starknet/core/os/transaction_hash/transaction_hash.cairo +++ b/src/starkware/starknet/core/os/transaction_hash/transaction_hash.cairo @@ -7,36 +7,36 @@ from starkware.cairo.common.hash_state import ( hash_update_with_hashchain, ) -func get_transaction_hash{hash_ptr : HashBuiltin*}( - tx_hash_prefix : felt, - version : felt, - contract_address : felt, - entry_point_selector : felt, - calldata_size : felt, - calldata : felt*, - max_fee : felt, - chain_id : felt, - additional_data_size : felt, - additional_data : felt*, -) -> (tx_hash : felt): - let (hash_state_ptr) = hash_init() - let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=tx_hash_prefix) - let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=version) - let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=contract_address) +func get_transaction_hash{hash_ptr: HashBuiltin*}( + tx_hash_prefix: felt, + version: felt, + contract_address: felt, + entry_point_selector: felt, + calldata_size: felt, + calldata: felt*, + max_fee: felt, + chain_id: felt, + additional_data_size: felt, + additional_data: felt*, +) -> (tx_hash: felt) { + let (hash_state_ptr) = hash_init(); + let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=tx_hash_prefix); + let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=version); + let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=contract_address); let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=entry_point_selector - ) + ); let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=calldata, data_length=calldata_size - ) - let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=max_fee) - let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=chain_id) + ); + let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=max_fee); + let (hash_state_ptr) = hash_update_single(hash_state_ptr=hash_state_ptr, item=chain_id); let (hash_state_ptr) = hash_update( hash_state_ptr=hash_state_ptr, data_ptr=additional_data, data_length=additional_data_size - ) + ); - let (tx_hash) = hash_finalize(hash_state_ptr=hash_state_ptr) + let (tx_hash) = hash_finalize(hash_state_ptr=hash_state_ptr); - return (tx_hash=tx_hash) -end + return (tx_hash=tx_hash); +} diff --git a/src/starkware/starknet/core/os/transaction_hash/transaction_hash.py b/src/starkware/starknet/core/os/transaction_hash/transaction_hash.py index 828464cd..c6c1e6cc 100644 --- a/src/starkware/starknet/core/os/transaction_hash/transaction_hash.py +++ b/src/starkware/starknet/core/os/transaction_hash/transaction_hash.py @@ -5,7 +5,9 @@ from starkware.cairo.lang.vm.crypto import pedersen_hash from starkware.python.utils import from_bytes from starkware.starknet.core.os.class_hash import compute_class_hash -from starkware.starknet.services.api.contract_class import CONSTRUCTOR_SELECTOR, ContractClass +from starkware.starknet.definitions import constants +from starkware.starknet.public.abi import CONSTRUCTOR_ENTRY_POINT_SELECTOR +from starkware.starknet.services.api.contract_class import ContractClass class TransactionHashPrefix(Enum): @@ -70,7 +72,7 @@ def calculate_deploy_transaction_hash( tx_hash_prefix=TransactionHashPrefix.DEPLOY, version=version, contract_address=contract_address, - entry_point_selector=CONSTRUCTOR_SELECTOR, + entry_point_selector=CONSTRUCTOR_ENTRY_POINT_SELECTOR, calldata=constructor_calldata, # Field max_fee is considered 0 for Deploy transaction hash calculation purposes. max_fee=0, @@ -86,17 +88,26 @@ def calculate_declare_transaction_hash( sender_address: int, max_fee: int, version: int, + nonce: int, hash_function: Callable[[int, int], int] = pedersen_hash, ) -> int: class_hash = compute_class_hash(contract_class=contract_class, hash_func=hash_function) + + if version in [0, constants.QUERY_VERSION_BASE]: + calldata = [] + additional_data = [class_hash] + else: + calldata = [class_hash] + additional_data = [nonce] + return calculate_transaction_hash_common( tx_hash_prefix=TransactionHashPrefix.DECLARE, version=version, contract_address=sender_address, entry_point_selector=0, - calldata=[], + calldata=calldata, max_fee=max_fee, chain_id=chain_id, - additional_data=[class_hash], + additional_data=additional_data, hash_function=hash_function, ) diff --git a/src/starkware/starknet/core/os/transaction_hash/transaction_hash_test.py b/src/starkware/starknet/core/os/transaction_hash/transaction_hash_test.py index 58046b4b..75d014f7 100644 --- a/src/starkware/starknet/core/os/transaction_hash/transaction_hash_test.py +++ b/src/starkware/starknet/core/os/transaction_hash/transaction_hash_test.py @@ -15,8 +15,7 @@ ) from starkware.starknet.core.test_contract.test_utils import get_contract_class from starkware.starknet.definitions import constants -from starkware.starknet.services.api.contract_class import CONSTRUCTOR_SELECTOR -from starkware.starknet.services.api.gateway.transaction import DECLARE_SENDER_ADDRESS +from starkware.starknet.public.abi import CONSTRUCTOR_ENTRY_POINT_SELECTOR def run_cairo_transaction_hash( @@ -114,7 +113,7 @@ def test_deploy_transaction_hash(constructor_calldata: List[int]): TransactionHashPrefix.DEPLOY.value, version, contract_address, - CONSTRUCTOR_SELECTOR, + CONSTRUCTOR_ENTRY_POINT_SELECTOR, compute_hash_on_elements(data=constructor_calldata, hash_func=pedersen_hash), max_fee, chain_id, @@ -138,8 +137,10 @@ def test_declare_transaction_hash(): # Tested transaction data. version = constants.TRANSACTION_VERSION + sender_address = 19911991 max_fee = 0 chain_id = 1 + nonce = 0 contract_class = get_contract_class(contract_name="dummy_account") class_hash = compute_class_hash(contract_class=contract_class, hash_func=pedersen_hash) @@ -147,12 +148,12 @@ def test_declare_transaction_hash(): data=[ TransactionHashPrefix.DECLARE.value, version, - DECLARE_SENDER_ADDRESS, + sender_address, entry_point_selector, - compute_hash_on_elements(data=[], hash_func=pedersen_hash), + compute_hash_on_elements(data=[class_hash], hash_func=pedersen_hash), max_fee, chain_id, - class_hash, + nonce, ], hash_func=pedersen_hash, ) @@ -160,9 +161,10 @@ def test_declare_transaction_hash(): calculate_declare_transaction_hash( contract_class=contract_class, chain_id=chain_id, - sender_address=DECLARE_SENDER_ADDRESS, + sender_address=sender_address, max_fee=max_fee, version=version, + nonce=nonce, ) == expected_hash ) diff --git a/src/starkware/starknet/core/os/transactions.cairo b/src/starkware/starknet/core/os/transactions.cairo index c2f0b71f..b182d693 100644 --- a/src/starkware/starknet/core/os/transactions.cairo +++ b/src/starkware/starknet/core/os/transactions.cairo @@ -9,6 +9,13 @@ from starkware.cairo.common.memcpy import memcpy from starkware.cairo.common.registers import get_ap, get_fp_and_pc from starkware.cairo.common.segments import relocate_segment from starkware.cairo.common.uint256 import Uint256 +from starkware.starknet.common.constants import ( + DECLARE_HASH_PREFIX, + DEPLOY_HASH_PREFIX, + INVOKE_HASH_PREFIX, + L1_HANDLER_HASH_PREFIX, + ORIGIN_ADDRESS, +) from starkware.starknet.common.syscalls import ( CALL_CONTRACT_SELECTOR, DELEGATE_CALL_SELECTOR, @@ -60,92 +67,94 @@ from starkware.starknet.core.os.contracts import ( ContractClassFact, ContractEntryPoint, ) -from starkware.starknet.core.os.os_config.os_config import StarknetOsConfig from starkware.starknet.core.os.output import ( BlockInfo, - DeploymentInfoHeader, + DeploymentInfo, MessageToL1Header, MessageToL2Header, OsCarriedOutputs, os_carried_outputs_new, ) -from starkware.starknet.core.os.state import StateEntry +from starkware.starknet.core.os.state import UNINITIALIZED_CLASS_HASH, StateEntry from starkware.starknet.core.os.transaction_hash.transaction_hash import get_transaction_hash -const UNINITIALIZED_CLASS_HASH = 0 - -# The dummy caller address of an externally originated transaction. -const ORIGIN_ADDRESS = 0 - -# An entry point offset that indicates that nothing needs to be done. -# Used to implement an empty constructor. -const NOP_ENTRY_POINT_OFFSET = -1 +// An entry point offset that indicates that nothing needs to be done. +// Used to implement an empty constructor. +const NOP_ENTRY_POINT_OFFSET = -1; -const ENTRY_POINT_TYPE_EXTERNAL = 0 -const ENTRY_POINT_TYPE_L1_HANDLER = 1 -const ENTRY_POINT_TYPE_CONSTRUCTOR = 2 +const ENTRY_POINT_TYPE_EXTERNAL = 0; +const ENTRY_POINT_TYPE_L1_HANDLER = 1; +const ENTRY_POINT_TYPE_CONSTRUCTOR = 2; -const TRANSACTION_VERSION = 0 +const TRANSACTION_VERSION = 1; +const L1_HANDLER_VERSION = 0; -# get_selector_from_name('constructor'). -const CONSTRUCTOR_SELECTOR = ( - 0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194) +// get_selector_from_name('constructor'). +const CONSTRUCTOR_ENTRY_POINT_SELECTOR = ( + 0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194); -# get_selector_from_name('__execute__'). +// get_selector_from_name('__execute__'). const EXECUTE_ENTRY_POINT_SELECTOR = ( - 0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad) - -# get_selector_from_name('transfer'). -const TRANSFER_SELECTOR = ( - 0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e) - -const DEFAULT_ENTRY_POINT_SELECTOR = 0 - -# Represents the execution context during the execution of contract code. -struct ExecutionContext: - member entry_point_type : felt - member caller_address : felt - # The execution is done in the context of the contract at 'contract_address'. - # This address controls the storage being used, messages sent to L1, calling contracts, etc. - member contract_address : felt - # The hash of the contract class to execute. - member class_hash : felt - member selector : felt - member calldata_size : felt - member calldata : felt* - # Information about the transaction that triggered the execution. - member original_tx_info : TxInfo* -end - -# A dictionary from address to StateEntry. -struct StateChanges: - member changes_start : DictAccess* - member changes_end : DictAccess* -end - -# Executes the transactions in the hint variable os_input.transactions. -# -# Returns: -# reserved_range_checks_end - end pointer for the reserved range checks. -# state_changes - StateChanges struct corresponding to the changes that were done by -# the transactions. -# -# Assumptions: -# The caller verifies that the memory range [range_check_ptr, reserved_range_checks_end) -# corresponds to valid range check instances. -# Note that if the assumption above does not hold it might be the case that -# the returned range_check_ptr is smaller then reserved_range_checks_end. + 0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad); + +// get_selector_from_name('__validate__'). +const VALIDATE_ENTRY_POINT_SELECTOR = ( + 0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775); + +// get_selector_from_name('__validate_declare__'). +const VALIDATE_DECLARE_ENTRY_POINT_SELECTOR = ( + 0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3); + +// get_selector_from_name('transfer'). +const TRANSFER_ENTRY_POINT_SELECTOR = ( + 0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e); + +const DEFAULT_ENTRY_POINT_SELECTOR = 0; + +// Represents the execution context during the execution of contract code. +struct ExecutionContext { + entry_point_type: felt, + caller_address: felt, + // The execution is done in the context of the contract at 'contract_address'. + // This address controls the storage being used, messages sent to L1, calling contracts, etc. + contract_address: felt, + // The hash of the contract class to execute. + class_hash: felt, + selector: felt, + calldata_size: felt, + calldata: felt*, + // Information about the transaction that triggered the execution. + original_tx_info: TxInfo*, +} + +// A dictionary from address to StateEntry. +struct StateChanges { + changes_start: DictAccess*, + changes_end: DictAccess*, +} + +// Executes the transactions in the hint variable os_input.transactions. +// +// Returns: +// reserved_range_checks_end - end pointer for the reserved range checks. +// state_changes - StateChanges struct corresponding to the changes that were done by +// the transactions. +// +// Assumptions: +// The caller verifies that the memory range [range_check_ptr, reserved_range_checks_end) +// corresponds to valid range check instances. +// Note that if the assumption above does not hold it might be the case that +// the returned range_check_ptr is smaller then reserved_range_checks_end. func execute_transactions{ - pedersen_ptr : HashBuiltin*, + pedersen_ptr: HashBuiltin*, range_check_ptr, ecdsa_ptr, bitwise_ptr, - outputs : OsCarriedOutputs*, -}(block_context : BlockContext*) -> ( - reserved_range_checks_end : felt, state_changes : StateChanges -): - alloc_locals - local n_txs + ec_op_ptr, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*) -> (reserved_range_checks_end: felt, state_changes: StateChanges) { + alloc_locals; + local n_txs; %{ from starkware.python.utils import from_bytes @@ -153,277 +162,414 @@ func execute_transactions{ initial_dict = { address: segments.gen_arg( - (from_bytes(contract.contract_hash), segments.add())) + (from_bytes(contract.contract_hash), segments.add(), contract.nonce)) for address, contract in os_input.contracts.items() } %} - # A dict from contract address to a dict of storage changes. - let (local global_state_changes : DictAccess*) = dict_new() + // A dict from contract address to a dict of storage changes. + let (local global_state_changes: DictAccess*) = dict_new(); - let (__fp__, _) = get_fp_and_pc() - local local_builtin_ptrs : BuiltinPointers = BuiltinPointers( + let (__fp__, _) = get_fp_and_pc(); + local local_builtin_ptrs: BuiltinPointers = BuiltinPointers( pedersen=pedersen_ptr, range_check=nondet %{ segments.add_temp_segment() %}, ecdsa=ecdsa_ptr, - bitwise=bitwise_ptr) + bitwise=bitwise_ptr, + ec_op=ec_op_ptr); - let builtin_ptrs = &local_builtin_ptrs + let builtin_ptrs = &local_builtin_ptrs; %{ vm_enter_scope({ - 'storage_by_address' : storage_by_address, - 'transactions' : iter(os_input.transactions), - 'syscall_handler' : syscall_handler, - '__dict_manager' : __dict_manager, + 'transactions': iter(os_input.transactions), + 'syscall_handler': syscall_handler, + '__dict_manager': __dict_manager, }) %} - # Keep a reference to the start of global_state_changes. - let global_state_changes_start = global_state_changes + // Keep a reference to the start of global_state_changes. + let global_state_changes_start = global_state_changes; execute_transactions_inner{ builtin_ptrs=builtin_ptrs, global_state_changes=global_state_changes - }(block_context=block_context, n_txs=n_txs) + }(block_context=block_context, n_txs=n_txs); %{ vm_exit_scope() %} - let reserved_range_checks_end = range_check_ptr - # Relocate the range checks used by the transactions to reserved_range_checks_end. + let reserved_range_checks_end = range_check_ptr; + // Relocate the range checks used by the transactions to reserved_range_checks_end. relocate_segment( src_ptr=cast(local_builtin_ptrs.range_check, felt*), dest_ptr=cast(reserved_range_checks_end, felt*), - ) + ); - let pedersen_ptr = builtin_ptrs.pedersen - let range_check_ptr = builtin_ptrs.range_check - let ecdsa_ptr = builtin_ptrs.ecdsa - let bitwise_ptr = builtin_ptrs.bitwise + let pedersen_ptr = builtin_ptrs.pedersen; + let range_check_ptr = builtin_ptrs.range_check; + let ecdsa_ptr = builtin_ptrs.ecdsa; + let bitwise_ptr = builtin_ptrs.bitwise; + let ec_op_ptr = builtin_ptrs.ec_op; return ( reserved_range_checks_end=reserved_range_checks_end, state_changes=StateChanges(global_state_changes_start, global_state_changes), - ) -end - -# Inner function for execute_transactions. -# Arguments: -# block_context - a read-only context used for transaction execution. -# n_txs - the number of transactions to execute. -# -# Implicit arguments: -# range_check_ptr - a range check builtin, used and advanced by the OS, not the transactions. -# builtin_ptrs - a struct of builtin pointer that are going to be used by the -# executed transactions. -# The range-checks used internally by the transactions do not affect range_check_ptr. -# They are accounted for in builtin_ptrs. + ); +} + +// Inner function for execute_transactions. +// Arguments: +// block_context - a read-only context used for transaction execution. +// n_txs - the number of transactions to execute. +// +// Implicit arguments: +// range_check_ptr - a range check builtin, used and advanced by the OS, not the transactions. +// builtin_ptrs - a struct of builtin pointer that are going to be used by the +// executed transactions. +// The range-checks used internally by the transactions do not affect range_check_ptr. +// They are accounted for in builtin_ptrs. func execute_transactions_inner{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, -}(block_context : BlockContext*, n_txs): - if n_txs == 0: - return () - end - - alloc_locals - local tx_type - # Guess the current transaction's type. + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*, n_txs) { + if (n_txs == 0) { + return (); + } + + alloc_locals; + local tx_type; + // Guess the current transaction's type. %{ tx = next(transactions) - tx_type_bytes = tx.tx_type.name.encode('ascii') - ids.tx_type = int.from_bytes(tx_type_bytes, 'big') + tx_type_bytes = tx.tx_type.name.encode("ascii") + ids.tx_type = int.from_bytes(tx_type_bytes, "big") %} - if tx_type == 'INVOKE_FUNCTION': - # Handle invoke transaction. - execute_externally_called_invoke_transaction(block_context=block_context) - return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1) - end - - if tx_type == 'DEPLOY': - # Handle deploy transaction. - execute_deploy_transaction(block_context=block_context) - return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1) - end - - assert tx_type = 'DECLARE' - # Handle declare transaction. - execute_declare_transaction(block_context=block_context) - return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1) -end - -# Represents the calldata of an ERC20 transfer. -struct TransferCallData: - member recipient : felt - member amount : Uint256 -end - -# Charges a fee from the user. -# If max_fee is not 0, validates that the selector matches the entry point of an account contract -# and executes an ERC20 transfer on the behalf of that account contract. -# -# Arguments: -# block_context - a global context that is fixed throughout the block. -# tx_execution_context - The execution context of the transaction that pays the fee. + if (tx_type == 'INVOKE_FUNCTION') { + // Handle the invoke-function transaction. + execute_invoke_function_transaction(block_context=block_context); + return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1); + } + + if (tx_type == 'L1_HANDLER') { + // Handle L1 handler transaction. + execute_l1_handler_transaction(block_context=block_context); + return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1); + } + + if (tx_type == 'DEPLOY') { + // Handle the deploy transaction. + execute_deploy_transaction(block_context=block_context); + return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1); + } + + assert tx_type = 'DECLARE'; + // Handle the declare transaction. + execute_declare_transaction(block_context=block_context); + return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1); +} + +// Represents the calldata of an ERC20 transfer. +struct TransferCallData { + recipient: felt, + amount: Uint256, +} + +// Charges a fee from the user. +// If max_fee is not 0, validates that the selector matches the entry point of an account contract +// and executes an ERC20 transfer on the behalf of that account contract. +// +// Arguments: +// block_context - a global context that is fixed throughout the block. +// tx_execution_context - The execution context of the transaction that pays the fee. func charge_fee{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, -}(block_context : BlockContext*, tx_execution_context : ExecutionContext*): - alloc_locals - if tx_execution_context.original_tx_info.max_fee == 0: - return () - end - - # Transactions with fee should go through the EXECUTE_ENTRY_POINT_SELECTOR. - assert tx_execution_context.selector = EXECUTE_ENTRY_POINT_SELECTOR - - local calldata : TransferCallData = TransferCallData( + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*, tx_execution_context: ExecutionContext*) { + alloc_locals; + local original_tx_info: TxInfo* = tx_execution_context.original_tx_info; + local max_fee = original_tx_info.max_fee; + if (max_fee == 0) { + return (); + } + + // Transactions with fee should go through the EXECUTE_ENTRY_POINT_SELECTOR + // or VALIDATE_DECLARE_ENTRY_POINT_SELECTOR. + tempvar selector = tx_execution_context.selector; + assert (selector - EXECUTE_ENTRY_POINT_SELECTOR) * + (selector - VALIDATE_DECLARE_ENTRY_POINT_SELECTOR) = 0; + + local calldata: TransferCallData = TransferCallData( recipient=block_context.sequencer_address, - amount=Uint256(low=nondet %{ syscall_handler.tx_execution_info.actual_fee %}, high=0)) + amount=Uint256(low=nondet %{ syscall_handler.tx_execution_info.actual_fee %}, high=0)); - tempvar original_tx_info = tx_execution_context.original_tx_info + // Verify that the charged amount is not larger than the transaction's max_fee field. + assert_nn_le(calldata.amount.low, max_fee); - # Verify that the charged amount is not larger than the transaction's max_fee field. - assert_nn_le(calldata.amount.low, original_tx_info.max_fee) - - tempvar fee_token_address = block_context.starknet_os_config.fee_token_address - let (fee_state_entry : StateEntry*) = dict_read{dict_ptr=global_state_changes}( + tempvar fee_token_address = block_context.starknet_os_config.fee_token_address; + let (fee_state_entry: StateEntry*) = dict_read{dict_ptr=global_state_changes}( key=fee_token_address - ) - let (__fp__, _) = get_fp_and_pc() - local execution_context : ExecutionContext = ExecutionContext( + ); + let (__fp__, _) = get_fp_and_pc(); + local execution_context: ExecutionContext = ExecutionContext( entry_point_type=ENTRY_POINT_TYPE_EXTERNAL, caller_address=original_tx_info.account_contract_address, contract_address=fee_token_address, class_hash=fee_state_entry.class_hash, - selector=TRANSFER_SELECTOR, + selector=TRANSFER_ENTRY_POINT_SELECTOR, calldata_size=TransferCallData.SIZE, calldata=&calldata, original_tx_info=original_tx_info, - ) + ); + + execute_entry_point(block_context=block_context, execution_context=&execution_context); + + return (); +} + +// Checks that the given transaction version is one of the supported versions. +func validate_transaction_version(tx_version: felt) { + with_attr error_message("Invalid transaction version: {tx_version}.") { + static_assert TRANSACTION_VERSION == 1; + assert (tx_version - 0) * (tx_version - TRANSACTION_VERSION) = 0; + } + return (); +} + +// Executes an invoke-function transaction. +// +// The transaction should be passed in the hint variable 'tx'. +// +// Arguments: +// block_context - a global context that is fixed throughout the block. +func execute_invoke_function_transaction{ + range_check_ptr, + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*) { + alloc_locals; + + let (local tx_execution_context: ExecutionContext*) = get_invoke_tx_execution_context( + entry_point_type=ENTRY_POINT_TYPE_EXTERNAL + ); + + // Guess tx version and make sure it's valid. + local tx_version = nondet %{ tx.version %}; + validate_transaction_version(tx_version=tx_version); + + local nonce = nondet %{ 0 if tx.nonce is None else tx.nonce %}; + local max_fee = nondet %{ tx.max_fee %}; + let (__fp__, _) = get_fp_and_pc(); + + if (tx_version == 0) { + tempvar entry_point_selector_field = tx_execution_context.selector; + tempvar additional_data_size = 0; + tempvar additional_data = cast(0, felt*); + } else { + assert tx_execution_context.selector = EXECUTE_ENTRY_POINT_SELECTOR; + tempvar entry_point_selector_field = 0; + tempvar additional_data_size = 1; + tempvar additional_data = &nonce; + } + + local chain_id = block_context.starknet_os_config.chain_id; + let (transaction_hash) = compute_transaction_hash( + tx_hash_prefix=INVOKE_HASH_PREFIX, + version=tx_version, + execution_context=tx_execution_context, + entry_point_selector_field=entry_point_selector_field, + max_fee=max_fee, + chain_id=chain_id, + additional_data_size=additional_data_size, + additional_data=additional_data, + ); - execute_entry_point(block_context=block_context, execution_context=&execution_context) + assert [tx_execution_context.original_tx_info] = TxInfo( + version=tx_version, + account_contract_address=tx_execution_context.contract_address, + max_fee=max_fee, + signature_len=nondet %{ len(tx.signature) %}, + signature=cast(nondet %{ segments.gen_arg(arg=tx.signature) %}, felt*), + transaction_hash=transaction_hash, + chain_id=chain_id, + nonce=nonce, + ); - return () -end + check_and_increment_nonce(execution_context=tx_execution_context, nonce=nonce); -# Executes an externally called transaction (external invoke or l1 handler). -# -# The transaction should be passed in the hint variable 'tx'. -# If the transaction is an L1 handler, it is appended to the list of consumed L1->L2 messages. -# -# Arguments: -# block_context - a global context that is fixed throughout the block. -func execute_externally_called_invoke_transaction{ - range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, -}(block_context : BlockContext*): - alloc_locals - - # Loads the execution context based on the current transaction. - local contract_address - %{ - from starkware.starknet.business_logic.internal_transaction import InternalInvokeFunction - from starkware.starknet.services.api.contract_class import EntryPointType + %{ syscall_handler.start_tx(tx_info_ptr=ids.tx_execution_context.original_tx_info.address_) %} - if tx.entry_point_type is EntryPointType.L1_HANDLER: - entry_point_type = ids.ENTRY_POINT_TYPE_L1_HANDLER - assert tx.nonce is not None, "L1 handlers must include a nonce." - elif tx.entry_point_type is EntryPointType.EXTERNAL: - entry_point_type = ids.ENTRY_POINT_TYPE_EXTERNAL - else: - raise NotImplementedError(f'Unexpected EntryPointType: {tx.entry_point_type}.') + run_validate(block_context=block_context, tx_execution_context=tx_execution_context); + execute_entry_point(block_context=block_context, execution_context=tx_execution_context); + charge_fee(block_context=block_context, tx_execution_context=tx_execution_context); - assert isinstance(tx, InternalInvokeFunction), \ - f'Expected a transaction of type InternalInvokeFunction, got {tx}.' + %{ syscall_handler.end_tx() %} + return (); +} - ids.contract_address = tx.contract_address - %} +// Executes an L1-handler transaction. +// +// The transaction should be passed in the hint variable 'tx'. +// +// Arguments: +// block_context - a global context that is fixed throughout the block. +func execute_l1_handler_transaction{ + range_check_ptr, + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*) { + alloc_locals; - let (state_entry : StateEntry*) = dict_read{dict_ptr=global_state_changes}(key=contract_address) - local execution_context : ExecutionContext* = new ExecutionContext( - entry_point_type=nondet %{ entry_point_type %}, - caller_address=ORIGIN_ADDRESS, - contract_address=contract_address, - class_hash=state_entry.class_hash, - selector=nondet %{ tx.entry_point_selector %}, - calldata_size=nondet %{ len(tx.calldata) %}, - calldata=cast(nondet %{ segments.gen_arg(tx.calldata) %}, felt*), - original_tx_info=cast(nondet %{ segments.add() %}, TxInfo*), - ) + let (local tx_execution_context: ExecutionContext*) = get_invoke_tx_execution_context( + entry_point_type=ENTRY_POINT_TYPE_L1_HANDLER + ); + + local nonce = nondet %{ tx.nonce %}; + local chain_id = block_context.starknet_os_config.chain_id; - local nonce - local max_fee = nondet %{ tx.max_fee %} - %{ assert tx.version == ids.TRANSACTION_VERSION, 'Wrong transaction version.' %} - if execution_context.entry_point_type == ENTRY_POINT_TYPE_L1_HANDLER: - %{ ids.nonce = tx.nonce %} - let (__fp__, _) = get_fp_and_pc() - tempvar tx_hash_prefix = 'l1_handler' - tempvar additional_data_size = 1 - tempvar additional_data = &nonce - with_attr error_message("An L1 handler transaction must have max_fee==0."): - assert max_fee = 0 - end - else: - # If execution_context.entry_point_type is not ENTRY_POINT_TYPE_L1_HANDLER, - # it must be ENTRY_POINT_TYPE_EXTERNAL. - assert execution_context.entry_point_type = ENTRY_POINT_TYPE_EXTERNAL - tempvar tx_hash_prefix = 'invoke' - tempvar additional_data_size = 0 - tempvar additional_data = cast(0, felt*) - end - - local chain_id = block_context.starknet_os_config.chain_id + let (__fp__, _) = get_fp_and_pc(); let (transaction_hash) = compute_transaction_hash( - tx_hash_prefix=tx_hash_prefix, - execution_context=execution_context, - max_fee=max_fee, + tx_hash_prefix=L1_HANDLER_HASH_PREFIX, + version=L1_HANDLER_VERSION, + execution_context=tx_execution_context, + entry_point_selector_field=tx_execution_context.selector, + max_fee=0, chain_id=chain_id, - additional_data_size=additional_data_size, - additional_data=additional_data, - ) + additional_data_size=1, + additional_data=&nonce, + ); - assert [execution_context.original_tx_info] = TxInfo( - version=TRANSACTION_VERSION, - account_contract_address=execution_context.contract_address, - max_fee=max_fee, - signature_len=nondet %{ len(tx.signature) %}, - signature=cast(nondet %{ segments.gen_arg(arg=tx.signature) %}, felt*), + assert [tx_execution_context.original_tx_info] = TxInfo( + version=L1_HANDLER_VERSION, + account_contract_address=tx_execution_context.contract_address, + max_fee=0, + signature_len=0, + signature=cast(0, felt*), transaction_hash=transaction_hash, chain_id=chain_id, - ) - - if execution_context.entry_point_type == ENTRY_POINT_TYPE_L1_HANDLER: - # Consume L1-to-L2 message. - consume_l1_to_l2_message(execution_context=execution_context, nonce=nonce) - else: - tempvar outputs = outputs - end + nonce=nonce, + ); - %{ syscall_handler.start_tx(tx_info_ptr=ids.execution_context.original_tx_info.address_) %} - execute_entry_point(block_context=block_context, execution_context=execution_context) + // Consume L1-to-L2 message. + consume_l1_to_l2_message(execution_context=tx_execution_context, nonce=nonce); - charge_fee(block_context=block_context, tx_execution_context=execution_context) + %{ syscall_handler.start_tx(tx_info_ptr=ids.tx_execution_context.original_tx_info.address_) %} + execute_entry_point(block_context=block_context, execution_context=tx_execution_context); %{ syscall_handler.end_tx() %} - return () -end + return (); +} -# Calls execute_entry_point and generates the corresponding CallContractResponse. +// Guess the execution context of an invoke transaction (either invoke function or L1 handler). +// Leaves 'original_tx_info' empty - should be filled later on. +func get_invoke_tx_execution_context{global_state_changes: DictAccess*}(entry_point_type: felt) -> ( + tx_execution_context: ExecutionContext* +) { + alloc_locals; + + local contract_address = nondet %{ tx.contract_address %}; + let (state_entry: StateEntry*) = dict_read{dict_ptr=global_state_changes}(key=contract_address); + local tx_execution_context: ExecutionContext* = new ExecutionContext( + entry_point_type=entry_point_type, + caller_address=ORIGIN_ADDRESS, + contract_address=contract_address, + class_hash=state_entry.class_hash, + selector=nondet %{ tx.entry_point_selector %}, + calldata_size=nondet %{ len(tx.calldata) %}, + calldata=cast(nondet %{ segments.gen_arg(tx.calldata) %}, felt*), + original_tx_info=cast(nondet %{ segments.add() %}, TxInfo*), + ); + + return (tx_execution_context=tx_execution_context); +} + +// Verifies that the transaction's nonce matches the contract's nonce and increments the +// latter. +func check_and_increment_nonce{global_state_changes: DictAccess*}( + execution_context: ExecutionContext*, nonce: felt +) -> () { + alloc_locals; + + // Do not handle nonce for version 0. + local tx_version = execution_context.original_tx_info.version; + if (tx_version == 0) { + return (); + } + + tempvar contract_address = execution_context.contract_address; + local state_entry: StateEntry*; + %{ + # Fetch a state_entry in this hint and validate it in the update that comes next. + ids.state_entry = __dict_manager.get_dict(ids.global_state_changes)[ids.contract_address] + %} + + local current_nonce = state_entry.nonce; + with_attr error_message("Unexpected nonce. Expected {current_nonce}, got {nonce}.") { + assert current_nonce = nonce; + } + + // Update global_state_changes. + tempvar new_state_entry = new StateEntry( + class_hash=state_entry.class_hash, + storage_ptr=state_entry.storage_ptr, + nonce=current_nonce + 1); + dict_update{dict_ptr=global_state_changes}( + key=contract_address, + prev_value=cast(state_entry, felt), + new_value=cast(new_state_entry, felt), + ); + return (); +} + +// Runs the account contract's "__validate__" entry point, which is responsible for +// signature verification. +// +// Arguments: +// block_context - a global context that is fixed throughout the block. +// tx_execution_context - The execution context of the underlying invoke transaction. +func run_validate{ + range_check_ptr, + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*, tx_execution_context: ExecutionContext*) { + alloc_locals; + + // Do not run "__validate__" for version 0. + if (tx_execution_context.original_tx_info.version == 0) { + return (); + } + + // "__validate__" is expected to get the same calldata as "__execute__". + local validate_execution_context: ExecutionContext* = new ExecutionContext( + entry_point_type=ENTRY_POINT_TYPE_EXTERNAL, + caller_address=ORIGIN_ADDRESS, + contract_address=tx_execution_context.contract_address, + class_hash=tx_execution_context.class_hash, + selector=VALIDATE_ENTRY_POINT_SELECTOR, + calldata_size=tx_execution_context.calldata_size, + calldata=tx_execution_context.calldata, + original_tx_info=tx_execution_context.original_tx_info, + ); + + execute_entry_point(block_context=block_context, execution_context=validate_execution_context); + return (); +} + +// Calls execute_entry_point and generates the corresponding CallContractResponse. func contract_call_helper{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, }( - block_context : BlockContext*, - execution_context : ExecutionContext*, - call_response : CallContractResponse*, -): + block_context: BlockContext*, + execution_context: ExecutionContext*, + call_response: CallContractResponse*, +) { let (retdata_size, retdata) = execute_entry_point( block_context=block_context, execution_context=execution_context - ) + ); %{ # Check that the actual return value matches the expected one. @@ -432,37 +578,37 @@ func contract_call_helper{ assert expected == actual, f'Return value mismatch expected={expected}, actual={actual}.' %} - relocate_segment(src_ptr=call_response.retdata, dest_ptr=retdata) + relocate_segment(src_ptr=call_response.retdata, dest_ptr=retdata); assert [call_response] = CallContractResponse( retdata_size=retdata_size, - retdata=retdata) - return () -end + retdata=retdata); + return (); +} -# Executes a syscall that calls another contract, invokes a delegate call or a library call. +// Executes a syscall that calls another contract, invokes a delegate call or a library call. func execute_contract_call_syscall{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, }( - block_context : BlockContext*, - contract_address : felt, - caller_address : felt, - entry_point_type : felt, - original_tx_info : TxInfo*, - syscall_ptr : CallContract*, -): - alloc_locals - - let call_req = syscall_ptr.request - - let (state_entry : StateEntry*) = dict_read{dict_ptr=global_state_changes}( + block_context: BlockContext*, + contract_address: felt, + caller_address: felt, + entry_point_type: felt, + original_tx_info: TxInfo*, + syscall_ptr: CallContract*, +) { + alloc_locals; + + let call_req = syscall_ptr.request; + + let (state_entry: StateEntry*) = dict_read{dict_ptr=global_state_changes}( key=call_req.contract_address - ) + ); - local execution_context : ExecutionContext* = new ExecutionContext( + local execution_context: ExecutionContext* = new ExecutionContext( entry_point_type=entry_point_type, caller_address=caller_address, contract_address=contract_address, @@ -471,32 +617,32 @@ func execute_contract_call_syscall{ calldata_size=call_req.calldata_size, calldata=call_req.calldata, original_tx_info=original_tx_info, - ) + ); return contract_call_helper( block_context=block_context, execution_context=execution_context, call_response=&syscall_ptr.response, - ) -end + ); +} -# Implements the library_call and library_call_l1_handler system calls. +// Implements the library_call and library_call_l1_handler system calls. func execute_library_call_syscall{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, }( - block_context : BlockContext*, - caller_execution_context : ExecutionContext*, - entry_point_type : felt, - syscall_ptr : LibraryCall*, -): - alloc_locals + block_context: BlockContext*, + caller_execution_context: ExecutionContext*, + entry_point_type: felt, + syscall_ptr: LibraryCall*, +) { + alloc_locals; - let call_req = syscall_ptr.request + let call_req = syscall_ptr.request; - local execution_context : ExecutionContext* = new ExecutionContext( + local execution_context: ExecutionContext* = new ExecutionContext( entry_point_type=entry_point_type, caller_address=caller_execution_context.caller_address, contract_address=caller_execution_context.contract_address, @@ -505,81 +651,78 @@ func execute_library_call_syscall{ calldata_size=call_req.calldata_size, calldata=call_req.calldata, original_tx_info=caller_execution_context.original_tx_info, - ) + ); return contract_call_helper( block_context=block_context, execution_context=execution_context, call_response=&syscall_ptr.response, - ) -end + ); +} func execute_deploy_syscall{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, -}( - block_context : BlockContext*, - caller_execution_context : ExecutionContext*, - syscall_ptr : Deploy*, -): - let request = syscall_ptr.request - # Verify deploy_from_zero is either 0 (FALSE) or 1 (TRUE). - assert request.deploy_from_zero * (request.deploy_from_zero - 1) = 0 - # Set deployer_address to 0 if request.deploy_from_zero is TRUE. + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*, caller_execution_context: ExecutionContext*, syscall_ptr: Deploy*) { + let request = syscall_ptr.request; + // Verify deploy_from_zero is either 0 (FALSE) or 1 (TRUE). + assert request.deploy_from_zero * (request.deploy_from_zero - 1) = 0; + // Set deployer_address to 0 if request.deploy_from_zero is TRUE. let deployer_address = ( - (1 - request.deploy_from_zero) * caller_execution_context.contract_address) + (1 - request.deploy_from_zero) * caller_execution_context.contract_address); - let hash_ptr = builtin_ptrs.pedersen - with hash_ptr: + let hash_ptr = builtin_ptrs.pedersen; + with hash_ptr { let (contract_address) = get_contract_address( salt=request.contract_address_salt, class_hash=request.class_hash, constructor_calldata_size=request.constructor_calldata_size, constructor_calldata=request.constructor_calldata, deployer_address=deployer_address, - ) - end + ); + } tempvar builtin_ptrs = new BuiltinPointers( pedersen=hash_ptr, range_check=builtin_ptrs.range_check, ecdsa=builtin_ptrs.ecdsa, bitwise=builtin_ptrs.bitwise, - ) + ec_op=builtin_ptrs.ec_op, + ); - # Fill the syscall response, before contract_address is revoked. + // Fill the syscall response, before contract_address is revoked. assert syscall_ptr.response = DeployResponse( contract_address=contract_address, constructor_retdata_size=0, constructor_retdata=cast(0, felt*), - ) + ); tempvar constructor_execution_context = new ExecutionContext( entry_point_type=ENTRY_POINT_TYPE_CONSTRUCTOR, caller_address=caller_execution_context.contract_address, contract_address=contract_address, class_hash=request.class_hash, - selector=CONSTRUCTOR_SELECTOR, + selector=CONSTRUCTOR_ENTRY_POINT_SELECTOR, calldata_size=request.constructor_calldata_size, calldata=request.constructor_calldata, original_tx_info=caller_execution_context.original_tx_info, - ) + ); deploy_contract( block_context=block_context, constructor_execution_context=constructor_execution_context - ) - - return () -end - -# Reads a value from the current contract's storage. -func execute_storage_read{global_state_changes : DictAccess*}( - contract_address, syscall_ptr : StorageRead* -): - alloc_locals - local state_entry : StateEntry* - local new_state_entry : StateEntry* + ); + + return (); +} + +// Reads a value from the current contract's storage. +func execute_storage_read{global_state_changes: DictAccess*}( + contract_address, syscall_ptr: StorageRead* +) { + alloc_locals; + local state_entry: StateEntry*; + local new_state_entry: StateEntry*; %{ syscall_handler.execute_syscall_storage_read() @@ -589,35 +732,36 @@ func execute_storage_read{global_state_changes : DictAccess*}( ids.new_state_entry = segments.add() %} - tempvar value = syscall_ptr.response.value + tempvar value = syscall_ptr.response.value; - # Update the contract's storage. - tempvar storage_ptr = state_entry.storage_ptr + // Update the contract's storage. + tempvar storage_ptr = state_entry.storage_ptr; assert [storage_ptr] = DictAccess( - key=syscall_ptr.request.address, prev_value=value, new_value=value) - let storage_ptr = storage_ptr + DictAccess.SIZE + key=syscall_ptr.request.address, prev_value=value, new_value=value); + let storage_ptr = storage_ptr + DictAccess.SIZE; - # Update global_state_changes. + // Update global_state_changes. assert [new_state_entry] = StateEntry( class_hash=state_entry.class_hash, - storage_ptr=storage_ptr) + storage_ptr=storage_ptr, + nonce=state_entry.nonce); dict_update{dict_ptr=global_state_changes}( key=contract_address, prev_value=cast(state_entry, felt), new_value=cast(new_state_entry, felt), - ) - - return () -end - -# Write a value to the current contract's storage. -func execute_storage_write{global_state_changes : DictAccess*}( - contract_address, syscall_ptr : StorageWrite* -): - alloc_locals - local prev_value : felt - local state_entry : StateEntry* - local new_state_entry : StateEntry* + ); + + return (); +} + +// Write a value to the current contract's storage. +func execute_storage_write{global_state_changes: DictAccess*}( + contract_address, syscall_ptr: StorageWrite* +) { + alloc_locals; + local prev_value: felt; + local state_entry: StateEntry*; + local new_state_entry: StateEntry*; %{ ids.prev_value = syscall_handler.execute_syscall_storage_write() @@ -627,87 +771,88 @@ func execute_storage_write{global_state_changes : DictAccess*}( ids.new_state_entry = segments.add() %} - # Update the contract's storage. - tempvar storage_ptr = state_entry.storage_ptr + // Update the contract's storage. + tempvar storage_ptr = state_entry.storage_ptr; assert [storage_ptr] = DictAccess( - key=syscall_ptr.address, prev_value=prev_value, new_value=syscall_ptr.value) - let storage_ptr = storage_ptr + DictAccess.SIZE + key=syscall_ptr.address, prev_value=prev_value, new_value=syscall_ptr.value); + let storage_ptr = storage_ptr + DictAccess.SIZE; - # Update global_state_changes. + // Update global_state_changes. assert [new_state_entry] = StateEntry( class_hash=state_entry.class_hash, - storage_ptr=storage_ptr) + storage_ptr=storage_ptr, + nonce=state_entry.nonce); dict_update{dict_ptr=global_state_changes}( key=contract_address, prev_value=cast(state_entry, felt), new_value=cast(new_state_entry, felt), - ) - - return () -end - -# Executes the system calls in syscall_ptr. -# -# Arguments: -# block_context - a read-only context used for transaction execution. -# execution_context - The execution context in which the system calls need to be executed. -# syscall_ptr - a pointer to the syscall segment that needs to be executed. -# syscall_size - The size of the system call segment to be executed. + ); + + return (); +} + +// Executes the system calls in syscall_ptr. +// +// Arguments: +// block_context - a read-only context used for transaction execution. +// execution_context - The execution context in which the system calls need to be executed. +// syscall_ptr - a pointer to the syscall segment that needs to be executed. +// syscall_size - The size of the system call segment to be executed. func execute_syscalls{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, }( - block_context : BlockContext*, - execution_context : ExecutionContext*, + block_context: BlockContext*, + execution_context: ExecutionContext*, syscall_size, - syscall_ptr : felt*, -): - if syscall_size == 0: - return () - end + syscall_ptr: felt*, +) { + if (syscall_size == 0) { + return (); + } - tempvar selector = [syscall_ptr] + tempvar selector = [syscall_ptr]; - if selector == STORAGE_READ_SELECTOR: + if (selector == STORAGE_READ_SELECTOR) { execute_storage_read( contract_address=execution_context.contract_address, syscall_ptr=cast(syscall_ptr, StorageRead*), - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - StorageRead.SIZE, syscall_ptr=syscall_ptr + StorageRead.SIZE, - ) - end + ); + } - if selector == STORAGE_WRITE_SELECTOR: + if (selector == STORAGE_WRITE_SELECTOR) { execute_storage_write( contract_address=execution_context.contract_address, syscall_ptr=cast(syscall_ptr, StorageWrite*), - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - StorageWrite.SIZE, syscall_ptr=syscall_ptr + StorageWrite.SIZE, - ) - end + ); + } - if selector == EMIT_EVENT_SELECTOR: - # Skip as long as the block hash is not calculated by the OS. + if (selector == EMIT_EVENT_SELECTOR) { + // Skip as long as the block hash is not calculated by the OS. return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - EmitEvent.SIZE, syscall_ptr=syscall_ptr + EmitEvent.SIZE, - ) - end + ); + } - if selector == CALL_CONTRACT_SELECTOR: - let call_contract_syscall = cast(syscall_ptr, CallContract*) + if (selector == CALL_CONTRACT_SELECTOR) { + let call_contract_syscall = cast(syscall_ptr, CallContract*); execute_contract_call_syscall( block_context=block_context, contract_address=call_contract_syscall.request.contract_address, @@ -715,141 +860,141 @@ func execute_syscalls{ entry_point_type=ENTRY_POINT_TYPE_EXTERNAL, original_tx_info=execution_context.original_tx_info, syscall_ptr=call_contract_syscall, - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - CallContract.SIZE, syscall_ptr=syscall_ptr + CallContract.SIZE, - ) - end + ); + } - if selector == LIBRARY_CALL_SELECTOR: + if (selector == LIBRARY_CALL_SELECTOR) { execute_library_call_syscall( block_context=block_context, caller_execution_context=execution_context, entry_point_type=ENTRY_POINT_TYPE_EXTERNAL, syscall_ptr=cast(syscall_ptr, LibraryCall*), - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - LibraryCall.SIZE, syscall_ptr=syscall_ptr + LibraryCall.SIZE, - ) - end + ); + } - if selector == LIBRARY_CALL_L1_HANDLER_SELECTOR: + if (selector == LIBRARY_CALL_L1_HANDLER_SELECTOR) { execute_library_call_syscall( block_context=block_context, caller_execution_context=execution_context, entry_point_type=ENTRY_POINT_TYPE_L1_HANDLER, syscall_ptr=cast(syscall_ptr, LibraryCall*), - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - LibraryCall.SIZE, syscall_ptr=syscall_ptr + LibraryCall.SIZE, - ) - end + ); + } - if selector == GET_TX_INFO_SELECTOR: + if (selector == GET_TX_INFO_SELECTOR) { assert cast(syscall_ptr, GetTxInfo*).response = GetTxInfoResponse( - tx_info=execution_context.original_tx_info) + tx_info=execution_context.original_tx_info); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - GetTxInfo.SIZE, syscall_ptr=syscall_ptr + GetTxInfo.SIZE, - ) - end + ); + } - if selector == GET_CALLER_ADDRESS_SELECTOR: + if (selector == GET_CALLER_ADDRESS_SELECTOR) { assert [cast(syscall_ptr, GetCallerAddress*)].response = GetCallerAddressResponse( - caller_address=execution_context.caller_address) + caller_address=execution_context.caller_address); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - GetCallerAddress.SIZE, syscall_ptr=syscall_ptr + GetCallerAddress.SIZE, - ) - end + ); + } - if selector == GET_SEQUENCER_ADDRESS_SELECTOR: + if (selector == GET_SEQUENCER_ADDRESS_SELECTOR) { assert [cast(syscall_ptr, GetSequencerAddress*)].response = GetSequencerAddressResponse( - sequencer_address=block_context.sequencer_address) + sequencer_address=block_context.sequencer_address); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - GetSequencerAddress.SIZE, syscall_ptr=syscall_ptr + GetSequencerAddress.SIZE, - ) - end + ); + } - if selector == GET_CONTRACT_ADDRESS_SELECTOR: + if (selector == GET_CONTRACT_ADDRESS_SELECTOR) { assert [cast(syscall_ptr, GetContractAddress*)].response = GetContractAddressResponse( - contract_address=execution_context.contract_address) + contract_address=execution_context.contract_address); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - GetContractAddress.SIZE, syscall_ptr=syscall_ptr + GetContractAddress.SIZE, - ) - end + ); + } - if selector == GET_BLOCK_TIMESTAMP_SELECTOR: + if (selector == GET_BLOCK_TIMESTAMP_SELECTOR) { assert [cast(syscall_ptr, GetBlockTimestamp*)].response = GetBlockTimestampResponse( - block_timestamp=block_context.block_info.block_timestamp) + block_timestamp=block_context.block_info.block_timestamp); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - GetBlockTimestamp.SIZE, syscall_ptr=syscall_ptr + GetBlockTimestamp.SIZE, - ) - end + ); + } - if selector == GET_BLOCK_NUMBER_SELECTOR: + if (selector == GET_BLOCK_NUMBER_SELECTOR) { assert [cast(syscall_ptr, GetBlockNumber*)].response = GetBlockNumberResponse( - block_number=block_context.block_info.block_number) + block_number=block_context.block_info.block_number); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - GetBlockNumber.SIZE, syscall_ptr=syscall_ptr + GetBlockNumber.SIZE, - ) - end + ); + } - if selector == GET_TX_SIGNATURE_SELECTOR: - tempvar original_tx_info : TxInfo* = execution_context.original_tx_info + if (selector == GET_TX_SIGNATURE_SELECTOR) { + tempvar original_tx_info: TxInfo* = execution_context.original_tx_info; assert [cast(syscall_ptr, GetTxSignature*)].response = GetTxSignatureResponse( signature_len=original_tx_info.signature_len, signature=original_tx_info.signature - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - GetTxSignature.SIZE, syscall_ptr=syscall_ptr + GetTxSignature.SIZE, - ) - end + ); + } - if selector == DEPLOY_SELECTOR: + if (selector == DEPLOY_SELECTOR) { execute_deploy_syscall( block_context=block_context, caller_execution_context=execution_context, syscall_ptr=cast(syscall_ptr, Deploy*), - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - Deploy.SIZE, syscall_ptr=syscall_ptr + Deploy.SIZE, - ) - end + ); + } - # DEPRECATED. - if selector == DELEGATE_CALL_SELECTOR: + // DEPRECATED. + if (selector == DELEGATE_CALL_SELECTOR) { execute_contract_call_syscall( block_context=block_context, contract_address=execution_context.contract_address, @@ -857,17 +1002,17 @@ func execute_syscalls{ entry_point_type=ENTRY_POINT_TYPE_EXTERNAL, original_tx_info=execution_context.original_tx_info, syscall_ptr=cast(syscall_ptr, CallContract*), - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - CallContract.SIZE, syscall_ptr=syscall_ptr + CallContract.SIZE, - ) - end + ); + } - # DEPRECATED. - if selector == DELEGATE_L1_HANDLER_SELECTOR: + // DEPRECATED. + if (selector == DELEGATE_L1_HANDLER_SELECTOR) { execute_contract_call_syscall( block_context=block_context, contract_address=execution_context.contract_address, @@ -875,172 +1020,172 @@ func execute_syscalls{ entry_point_type=ENTRY_POINT_TYPE_L1_HANDLER, original_tx_info=execution_context.original_tx_info, syscall_ptr=cast(syscall_ptr, CallContract*), - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - CallContract.SIZE, syscall_ptr=syscall_ptr + CallContract.SIZE, - ) - end + ); + } - # Here the system call must be 'SendMessageToL1'. - assert selector = SEND_MESSAGE_TO_L1_SELECTOR + // Here the system call must be 'SendMessageToL1'. + assert selector = SEND_MESSAGE_TO_L1_SELECTOR; - let syscall = [cast(syscall_ptr, SendMessageToL1SysCall*)] + let syscall = [cast(syscall_ptr, SendMessageToL1SysCall*)]; assert [outputs.messages_to_l1] = MessageToL1Header( from_address=execution_context.contract_address, to_address=syscall.to_address, - payload_size=syscall.payload_size) + payload_size=syscall.payload_size); memcpy( dst=outputs.messages_to_l1 + MessageToL1Header.SIZE, src=syscall.payload_ptr, len=syscall.payload_size, - ) + ); let (outputs) = os_carried_outputs_new( messages_to_l1=outputs.messages_to_l1 + MessageToL1Header.SIZE + outputs.messages_to_l1.payload_size, messages_to_l2=outputs.messages_to_l2, deployment_info=outputs.deployment_info, - ) + ); return execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_size - SendMessageToL1SysCall.SIZE, syscall_ptr=syscall_ptr + SendMessageToL1SysCall.SIZE, - ) -end - -# Adds 'tx' with the given 'nonce' to 'outputs.messages_to_l2'. -func consume_l1_to_l2_message{outputs : OsCarriedOutputs*}( - execution_context : ExecutionContext*, nonce : felt -): - assert_not_zero(execution_context.calldata_size) - # The payload is the calldata without the from_address argument (which is the first). - let payload : felt* = execution_context.calldata + 1 - tempvar payload_size = execution_context.calldata_size - 1 - - # Write the given transaction to the output. + ); +} + +// Adds 'tx' with the given 'nonce' to 'outputs.messages_to_l2'. +func consume_l1_to_l2_message{outputs: OsCarriedOutputs*}( + execution_context: ExecutionContext*, nonce: felt +) { + assert_not_zero(execution_context.calldata_size); + // The payload is the calldata without the from_address argument (which is the first). + let payload: felt* = execution_context.calldata + 1; + tempvar payload_size = execution_context.calldata_size - 1; + + // Write the given transaction to the output. assert [outputs.messages_to_l2] = MessageToL2Header( from_address=[execution_context.calldata], to_address=execution_context.contract_address, nonce=nonce, selector=execution_context.selector, - payload_size=payload_size) + payload_size=payload_size); - let message_payload = cast(outputs.messages_to_l2 + MessageToL2Header.SIZE, felt*) - memcpy(dst=message_payload, src=payload, len=payload_size) + let message_payload = cast(outputs.messages_to_l2 + MessageToL2Header.SIZE, felt*); + memcpy(dst=message_payload, src=payload, len=payload_size); let (outputs) = os_carried_outputs_new( messages_to_l1=outputs.messages_to_l1, messages_to_l2=outputs.messages_to_l2 + MessageToL2Header.SIZE + outputs.messages_to_l2.payload_size, deployment_info=outputs.deployment_info, - ) - return () -end + ); + return (); +} -# Returns the entry point's offset in the program based on 'contract_class' and -# 'execution_context'. +// Returns the entry point's offset in the program based on 'contract_class' and +// 'execution_context'. func get_entry_point_offset{range_check_ptr}( - contract_class : ContractClass*, execution_context : ExecutionContext* -) -> (entry_point_offset : felt): - alloc_locals - # Get the entry points corresponding to the transaction's type. - local entry_points : ContractEntryPoint* - local n_entry_points : felt - - tempvar entry_point_type = execution_context.entry_point_type - if entry_point_type == ENTRY_POINT_TYPE_L1_HANDLER: - entry_points = contract_class.l1_handlers - n_entry_points = contract_class.n_l1_handlers - else: - if entry_point_type == ENTRY_POINT_TYPE_EXTERNAL: - entry_points = contract_class.external_functions - n_entry_points = contract_class.n_external_functions - else: - assert entry_point_type = ENTRY_POINT_TYPE_CONSTRUCTOR - entry_points = contract_class.constructors - n_entry_points = contract_class.n_constructors - - if n_entry_points == 0: - return (entry_point_offset=NOP_ENTRY_POINT_OFFSET) - end - end - end - - # The key must be at offset 0. - static_assert ContractEntryPoint.selector == 0 - let (entry_point_desc : ContractEntryPoint*, success) = search_sorted( + contract_class: ContractClass*, execution_context: ExecutionContext* +) -> (entry_point_offset: felt) { + alloc_locals; + // Get the entry points corresponding to the transaction's type. + local entry_points: ContractEntryPoint*; + local n_entry_points: felt; + + tempvar entry_point_type = execution_context.entry_point_type; + if (entry_point_type == ENTRY_POINT_TYPE_L1_HANDLER) { + entry_points = contract_class.l1_handlers; + n_entry_points = contract_class.n_l1_handlers; + } else { + if (entry_point_type == ENTRY_POINT_TYPE_EXTERNAL) { + entry_points = contract_class.external_functions; + n_entry_points = contract_class.n_external_functions; + } else { + assert entry_point_type = ENTRY_POINT_TYPE_CONSTRUCTOR; + entry_points = contract_class.constructors; + n_entry_points = contract_class.n_constructors; + + if (n_entry_points == 0) { + return (entry_point_offset=NOP_ENTRY_POINT_OFFSET); + } + } + } + + // The key must be at offset 0. + static_assert ContractEntryPoint.selector == 0; + let (entry_point_desc: ContractEntryPoint*, success) = search_sorted( array_ptr=cast(entry_points, felt*), elm_size=ContractEntryPoint.SIZE, n_elms=n_entry_points, key=execution_context.selector, - ) - if success != 0: - return (entry_point_offset=entry_point_desc.offset) - end - - # If the selector was not found, verify that the first entry point is the default entry point, - # and call it. - assert entry_points[0].selector = DEFAULT_ENTRY_POINT_SELECTOR - return (entry_point_offset=entry_points[0].offset) -end - -# Executes an entry point in a contract. -# The contract entry point is selected based on execution_context.entry_point_type -# and execution_context.selector. -# -# Arguments: -# block_context - a global context that is fixed throughout the block. -# execution_context - The context for the current execution. + ); + if (success != 0) { + return (entry_point_offset=entry_point_desc.offset); + } + + // If the selector was not found, verify that the first entry point is the default entry point, + // and call it. + assert entry_points[0].selector = DEFAULT_ENTRY_POINT_SELECTOR; + return (entry_point_offset=entry_points[0].offset); +} + +// Executes an entry point in a contract. +// The contract entry point is selected based on execution_context.entry_point_type +// and execution_context.selector. +// +// Arguments: +// block_context - a global context that is fixed throughout the block. +// execution_context - The context for the current execution. func execute_entry_point{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, -}(block_context : BlockContext*, execution_context : ExecutionContext*) -> ( - retdata_size : felt, retdata : felt* -): - alloc_locals - - # The key must be at offset 0. - static_assert ContractClassFact.hash == 0 - let (contract_class_fact : ContractClassFact*) = find_element( + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*, execution_context: ExecutionContext*) -> ( + retdata_size: felt, retdata: felt* +) { + alloc_locals; + + // The key must be at offset 0. + static_assert ContractClassFact.hash == 0; + let (contract_class_fact: ContractClassFact*) = find_element( array_ptr=block_context.contract_class_facts, elm_size=ContractClassFact.SIZE, n_elms=block_context.n_contract_class_facts, key=execution_context.class_hash, - ) - local contract_class : ContractClass* = contract_class_fact.contract_class + ); + local contract_class: ContractClass* = contract_class_fact.contract_class; let (entry_point_offset) = get_entry_point_offset( contract_class=contract_class, execution_context=execution_context - ) + ); %{ syscall_handler.enter_call() %} - if entry_point_offset == NOP_ENTRY_POINT_OFFSET: - # Assert that there is no call data in the case of NOP entry point. - assert execution_context.calldata_size = 0 + if (entry_point_offset == NOP_ENTRY_POINT_OFFSET) { + // Assert that there is no call data in the case of NOP entry point. + assert execution_context.calldata_size = 0; %{ syscall_handler.exit_call() %} - return (retdata_size=0, retdata=cast(0, felt*)) - end + return (retdata_size=0, retdata=cast(0, felt*)); + } - local range_check_ptr = range_check_ptr - local contract_entry_point : felt* = contract_class.bytecode_ptr + entry_point_offset + local range_check_ptr = range_check_ptr; + local contract_entry_point: felt* = contract_class.bytecode_ptr + entry_point_offset; - local os_context : felt* - local syscall_ptr : felt* + local os_context: felt*; + local syscall_ptr: felt*; %{ ids.os_context = segments.add() ids.syscall_ptr = segments.add() %} - assert [os_context] = cast(syscall_ptr, felt) + assert [os_context] = cast(syscall_ptr, felt); - let n_builtins = BuiltinEncodings.SIZE - local builtin_params : BuiltinParams* = block_context.builtin_params + let n_builtins = BuiltinEncodings.SIZE; + local builtin_params: BuiltinParams* = block_context.builtin_params; select_builtins( n_builtins=n_builtins, all_encodings=builtin_params.builtin_encodings, @@ -1048,31 +1193,30 @@ func execute_entry_point{ n_selected_builtins=contract_class.n_builtins, selected_encodings=contract_class.builtin_list, selected_ptrs=os_context + 1, - ) + ); - # Use tempvar to pass arguments to contract_entry_point(). - tempvar selector = execution_context.selector - tempvar context = os_context - tempvar calldata_size = execution_context.calldata_size - tempvar calldata = execution_context.calldata + // Use tempvar to pass arguments to contract_entry_point(). + tempvar selector = execution_context.selector; + tempvar context = os_context; + tempvar calldata_size = execution_context.calldata_size; + tempvar calldata = execution_context.calldata; %{ vm_enter_scope({ - '__storage' : storage_by_address[ids.execution_context.contract_address], - 'syscall_handler' : syscall_handler, + 'syscall_handler': syscall_handler, }) %} - call abs contract_entry_point + call abs contract_entry_point; %{ vm_exit_scope() %} - # Retrieve returned_builtin_ptrs_subset. - # Note that returned_builtin_ptrs_subset cannot be set in a hint because doing so will allow a - # malicious prover to lie about the storage changes of a valid contract. - let (ap_val) = get_ap() - local returned_builtin_ptrs_subset : felt* = cast( - ap_val - contract_class.n_builtins - 2, felt*) - local retdata_size : felt = [ap_val - 2] - local retdata : felt* = cast([ap_val - 1], felt*) - - local return_builtin_ptrs : BuiltinPointers* + // Retrieve returned_builtin_ptrs_subset. + // Note that returned_builtin_ptrs_subset cannot be set in a hint because doing so will allow a + // malicious prover to lie about the storage changes of a valid contract. + let (ap_val) = get_ap(); + local returned_builtin_ptrs_subset: felt* = cast( + ap_val - contract_class.n_builtins - 2, felt*); + local retdata_size: felt = [ap_val - 2]; + local retdata: felt* = cast([ap_val - 1], felt*); + + local return_builtin_ptrs: BuiltinPointers*; %{ from starkware.starknet.core.os.os_utils import update_builtin_pointers @@ -1096,108 +1240,101 @@ func execute_entry_point{ n_selected_builtins=contract_class.n_builtins, selected_encodings=contract_class.builtin_list, selected_ptrs=returned_builtin_ptrs_subset, - ) + ); - # Call validate_builtins to validate that the builtin pointers have advanced correctly. + // Call validate_builtins to validate that the builtin pointers have advanced correctly. validate_builtins( prev_builtin_ptrs=builtin_ptrs, new_builtin_ptrs=return_builtin_ptrs, builtin_instance_sizes=builtin_params.builtin_instance_sizes, n_builtins=n_builtins, - ) + ); - let syscall_end = cast([returned_builtin_ptrs_subset - 1], felt*) + let syscall_end = cast([returned_builtin_ptrs_subset - 1], felt*); - let builtin_ptrs = return_builtin_ptrs + let builtin_ptrs = return_builtin_ptrs; execute_syscalls( block_context=block_context, execution_context=execution_context, syscall_size=syscall_end - syscall_ptr, syscall_ptr=syscall_ptr, - ) + ); %{ syscall_handler.exit_call() %} - return (retdata_size=retdata_size, retdata=retdata) -end - -# Deploys a contract. -# -# Arguments: -# block_context - A global context that is fixed throughout the block. -# constructor_execution_context - The ExecutionContext of the constructor. + return (retdata_size=retdata_size, retdata=retdata); +} + +// Deploys a contract. +// +// Arguments: +// block_context - A global context that is fixed throughout the block. +// constructor_execution_context - The ExecutionContext of the constructor. func deploy_contract{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, -}(block_context : BlockContext*, constructor_execution_context : ExecutionContext*): - alloc_locals + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*, constructor_execution_context: ExecutionContext*) { + alloc_locals; - local contract_address = constructor_execution_context.contract_address + local contract_address = constructor_execution_context.contract_address; - # Assert that we don't deploy to ORIGIN_ADDRESS. - assert_not_zero(contract_address - ORIGIN_ADDRESS) + // Assert that we don't deploy to ORIGIN_ADDRESS. + assert_not_zero(contract_address - ORIGIN_ADDRESS); - local state_entry : StateEntry* + local state_entry: StateEntry*; %{ # Fetch a state_entry in this hint and validate it in the update at the end # of this function. ids.state_entry = __dict_manager.get_dict(ids.global_state_changes)[ids.contract_address] %} - assert state_entry.class_hash = UNINITIALIZED_CLASS_HASH + assert state_entry.class_hash = UNINITIALIZED_CLASS_HASH; + assert state_entry.nonce = 0; tempvar new_state_entry = new StateEntry( - class_hash=constructor_execution_context.class_hash, storage_ptr=state_entry.storage_ptr) + class_hash=constructor_execution_context.class_hash, + storage_ptr=state_entry.storage_ptr, + nonce=0); dict_update{dict_ptr=global_state_changes}( key=contract_address, prev_value=cast(state_entry, felt), new_value=cast(new_state_entry, felt), - ) + ); - local constructor_calldata_size = constructor_execution_context.calldata_size - assert_nn(constructor_calldata_size) - # Write the contract address and hash to the output. - assert [outputs.deployment_info] = DeploymentInfoHeader( + // Write the contract address and hash to the output. + assert [outputs.deployment_info] = DeploymentInfo( contract_address=contract_address, class_hash=new_state_entry.class_hash, - calldata_size=constructor_calldata_size, - ) - # Copy the constructor calldata to the deployment info. - local deployment_info_calldata_section : felt* = ( - outputs.deployment_info + DeploymentInfoHeader.SIZE) - memcpy( - dst=deployment_info_calldata_section, - src=constructor_execution_context.calldata, - len=constructor_calldata_size, - ) + ); + + // Advance outputs.deployment_info. let (outputs) = os_carried_outputs_new( messages_to_l1=outputs.messages_to_l1, messages_to_l2=outputs.messages_to_l2, - deployment_info=cast( - deployment_info_calldata_section + constructor_calldata_size, DeploymentInfoHeader*), - ) + deployment_info=&outputs.deployment_info[1], + ); - # Invoke the contract constructor. + // Invoke the contract constructor. execute_entry_point( block_context=block_context, execution_context=constructor_execution_context - ) + ); - return () -end + return (); +} func execute_deploy_transaction{ range_check_ptr, - builtin_ptrs : BuiltinPointers*, - global_state_changes : DictAccess*, - outputs : OsCarriedOutputs*, -}(block_context : BlockContext*): - alloc_locals - - local contract_address_salt - local class_hash - local constructor_calldata_size - local constructor_calldata : felt* + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*) { + alloc_locals; + + local contract_address_salt; + local class_hash; + local constructor_calldata_size; + local constructor_calldata: felt*; %{ # Import from_bytes for the class_hash assignment below. from starkware.python.utils import from_bytes @@ -1208,55 +1345,62 @@ func execute_deploy_transaction{ ids.constructor_calldata = segments.gen_arg(arg=tx.constructor_calldata) %} - let hash_ptr = builtin_ptrs.pedersen - with hash_ptr: + let hash_ptr = builtin_ptrs.pedersen; + with hash_ptr { let (contract_address) = get_contract_address( salt=contract_address_salt, class_hash=class_hash, constructor_calldata_size=constructor_calldata_size, constructor_calldata=constructor_calldata, deployer_address=0, - ) - end + ); + } tempvar builtin_ptrs = new BuiltinPointers( pedersen=hash_ptr, range_check=builtin_ptrs.range_check, ecdsa=builtin_ptrs.ecdsa, bitwise=builtin_ptrs.bitwise, - ) + ec_op=builtin_ptrs.ec_op, + ); - local constructor_execution_context : ExecutionContext* = new ExecutionContext( + local constructor_execution_context: ExecutionContext* = new ExecutionContext( entry_point_type=ENTRY_POINT_TYPE_CONSTRUCTOR, caller_address=ORIGIN_ADDRESS, contract_address=contract_address, class_hash=class_hash, - selector=CONSTRUCTOR_SELECTOR, + selector=CONSTRUCTOR_ENTRY_POINT_SELECTOR, calldata_size=constructor_calldata_size, calldata=constructor_calldata, original_tx_info=cast(nondet %{ segments.add() %}, TxInfo*), - ) + ); + + // Guess tx version and make sure it's valid. + local tx_version = nondet %{ tx.version %}; + validate_transaction_version(tx_version=tx_version); - let nullptr = cast(0, felt*) - local chain_id = block_context.starknet_os_config.chain_id + let nullptr = cast(0, felt*); + local chain_id = block_context.starknet_os_config.chain_id; let (transaction_hash) = compute_transaction_hash( - tx_hash_prefix='deploy', + tx_hash_prefix=DEPLOY_HASH_PREFIX, + version=tx_version, execution_context=constructor_execution_context, + entry_point_selector_field=CONSTRUCTOR_ENTRY_POINT_SELECTOR, max_fee=0, chain_id=chain_id, additional_data_size=0, additional_data=nullptr, - ) + ); - %{ assert tx.version == ids.TRANSACTION_VERSION, 'Wrong transaction version.' %} assert [constructor_execution_context.original_tx_info] = TxInfo( - version=TRANSACTION_VERSION, + version=tx_version, account_contract_address=ORIGIN_ADDRESS, max_fee=0, signature_len=0, signature=nullptr, transaction_hash=transaction_hash, chain_id=chain_id, - ) + nonce=0, + ); %{ syscall_handler.start_tx( @@ -1266,61 +1410,126 @@ func execute_deploy_transaction{ deploy_contract( block_context=block_context, constructor_execution_context=constructor_execution_context - ) + ); %{ syscall_handler.end_tx() %} - return () -end - -func execute_declare_transaction{}(block_context : BlockContext*): - alloc_locals - local tx_info : TxInfo* = new TxInfo( - version=TRANSACTION_VERSION, - account_contract_address=nondet %{ tx.sender_address %}, - max_fee=nondet %{ tx.max_fee %}, + return (); +} + +func execute_declare_transaction{ + range_check_ptr, + builtin_ptrs: BuiltinPointers*, + global_state_changes: DictAccess*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*) { + alloc_locals; + + // Guess tx fields. + local tx_version; + local nonce_ptr: felt*; + local max_fee; + local sender_address; + local declared_class_hash_ptr: felt*; + %{ + from starkware.python.utils import from_bytes + + ids.tx_version = tx.version + ids.nonce_ptr = segments.gen_arg([tx.nonce]) + ids.max_fee = tx.max_fee + ids.sender_address = tx.sender_address + ids.declared_class_hash_ptr = segments.gen_arg([from_bytes(tx.class_hash)]) + %} + validate_transaction_version(tx_version=tx_version); + + if (tx_version == 0) { + %{ syscall_handler.skip_tx() %} + return (); + } + + local chain_id = block_context.starknet_os_config.chain_id; + let (state_entry: StateEntry*) = dict_read{dict_ptr=global_state_changes}(key=sender_address); + local validate_declare_execution_context: ExecutionContext* = new ExecutionContext( + entry_point_type=ENTRY_POINT_TYPE_EXTERNAL, + caller_address=ORIGIN_ADDRESS, + contract_address=sender_address, + class_hash=state_entry.class_hash, + selector=VALIDATE_DECLARE_ENTRY_POINT_SELECTOR, + calldata_size=1, + calldata=declared_class_hash_ptr, + original_tx_info=cast(nondet %{ segments.add() %}, TxInfo*), + ); + let (transaction_hash) = compute_transaction_hash( + tx_hash_prefix=DECLARE_HASH_PREFIX, + version=tx_version, + execution_context=validate_declare_execution_context, + entry_point_selector_field=0, + max_fee=max_fee, + chain_id=chain_id, + additional_data_size=1, + additional_data=nonce_ptr, + ); + assert [validate_declare_execution_context.original_tx_info] = TxInfo( + version=tx_version, + account_contract_address=sender_address, + max_fee=max_fee, signature_len=nondet %{ len(tx.signature) %}, signature=cast(nondet %{ segments.gen_arg(arg=tx.signature) %}, felt*), - transaction_hash=0, - chain_id=block_context.starknet_os_config.chain_id, - ) + transaction_hash=transaction_hash, + chain_id=chain_id, + nonce=[nonce_ptr], + ); + + check_and_increment_nonce( + execution_context=validate_declare_execution_context, nonce=[nonce_ptr] + ); - # Skip as long as we don't have class commitment. %{ - syscall_handler.start_tx(tx_info_ptr=ids.tx_info.address_) - syscall_handler.enter_call() - syscall_handler.exit_call() - syscall_handler.end_tx() + syscall_handler.start_tx( + tx_info_ptr=ids.validate_declare_execution_context.original_tx_info.address_ + ) %} - return () -end - -# Computes the hash of the transaction. -# -# Note that execution_context.original_tx_info is uninitialized when this function is called. -# In particular, this field is not used in this function. -func compute_transaction_hash{builtin_ptrs : BuiltinPointers*}( - tx_hash_prefix : felt, - execution_context : ExecutionContext*, - max_fee : felt, - chain_id : felt, - additional_data_size : felt, - additional_data : felt*, -) -> (transaction_hash : felt): - let hash_ptr = builtin_ptrs.pedersen - with hash_ptr: + // Run the account contract's "__validate_declare__" entry point. + execute_entry_point( + block_context=block_context, execution_context=validate_declare_execution_context + ); + charge_fee( + block_context=block_context, tx_execution_context=validate_declare_execution_context + ); + + %{ syscall_handler.end_tx() %} + + return (); +} + +// Computes the hash of the transaction. +// +// Note that execution_context.original_tx_info is uninitialized when this function is called. +// In particular, this field is not used in this function. +func compute_transaction_hash{builtin_ptrs: BuiltinPointers*}( + tx_hash_prefix: felt, + version: felt, + execution_context: ExecutionContext*, + entry_point_selector_field: felt, + max_fee: felt, + chain_id: felt, + additional_data_size: felt, + additional_data: felt*, +) -> (transaction_hash: felt) { + let hash_ptr = builtin_ptrs.pedersen; + with hash_ptr { let (transaction_hash) = get_transaction_hash( tx_hash_prefix=tx_hash_prefix, - version=TRANSACTION_VERSION, + version=version, contract_address=execution_context.contract_address, - entry_point_selector=execution_context.selector, + entry_point_selector=entry_point_selector_field, calldata_size=execution_context.calldata_size, calldata=execution_context.calldata, max_fee=max_fee, chain_id=chain_id, additional_data_size=additional_data_size, additional_data=additional_data, - ) - end + ); + } %{ assert ids.transaction_hash == tx.hash_value, ( @@ -1332,7 +1541,9 @@ func compute_transaction_hash{builtin_ptrs : BuiltinPointers*}( pedersen=hash_ptr, range_check=builtin_ptrs.range_check, ecdsa=builtin_ptrs.ecdsa, - bitwise=builtin_ptrs.bitwise) + bitwise=builtin_ptrs.bitwise, + ec_op=builtin_ptrs.ec_op, + ); - return (transaction_hash=transaction_hash) -end + return (transaction_hash=transaction_hash); +} diff --git a/src/starkware/starknet/core/test_contract/delegate_proxy.cairo b/src/starkware/starknet/core/test_contract/delegate_proxy.cairo index cbe26382..2372f58b 100644 --- a/src/starkware/starknet/core/test_contract/delegate_proxy.cairo +++ b/src/starkware/starknet/core/test_contract/delegate_proxy.cairo @@ -1,4 +1,4 @@ -# Note that this is a dummy contract to be used in tests. +// Note that this is a dummy contract to be used in tests. %lang starknet %builtins pedersen range_check bitwise @@ -6,48 +6,48 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.starknet.common.syscalls import library_call, library_call_l1_handler -# The hash of the implementation contract class. +// The hash of the implementation contract class. @storage_var -func implementation_hash() -> (class_hash : felt): -end +func implementation_hash() -> (class_hash: felt) { +} @external -func set_implementation_hash{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - implementation_hash_ : felt -): - implementation_hash.write(value=implementation_hash_) - return () -end +func set_implementation_hash{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + implementation_hash_: felt +) { + implementation_hash.write(value=implementation_hash_); + return (); +} @external @raw_input @raw_output -func __default__{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - selector : felt, calldata_size : felt, calldata : felt* -) -> (retdata_size : felt, retdata : felt*): - let (class_hash) = implementation_hash.read() +func __default__{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + selector: felt, calldata_size: felt, calldata: felt* +) -> (retdata_size: felt, retdata: felt*) { + let (class_hash) = implementation_hash.read(); - let (retdata_size : felt, retdata : felt*) = library_call( + let (retdata_size: felt, retdata: felt*) = library_call( class_hash=class_hash, function_selector=selector, calldata_size=calldata_size, calldata=calldata, - ) - return (retdata_size=retdata_size, retdata=retdata) -end + ); + return (retdata_size=retdata_size, retdata=retdata); +} @l1_handler @raw_input -func __l1_default__{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - selector : felt, calldata_size : felt, calldata : felt* -): - let (class_hash) = implementation_hash.read() +func __l1_default__{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + selector: felt, calldata_size: felt, calldata: felt* +) { + let (class_hash) = implementation_hash.read(); library_call_l1_handler( class_hash=class_hash, function_selector=selector, calldata_size=calldata_size, calldata=calldata, - ) - return () -end + ); + return (); +} diff --git a/src/starkware/starknet/core/test_contract/dummy_account.cairo b/src/starkware/starknet/core/test_contract/dummy_account.cairo index 25ddfc4e..9e19b13c 100644 --- a/src/starkware/starknet/core/test_contract/dummy_account.cairo +++ b/src/starkware/starknet/core/test_contract/dummy_account.cairo @@ -1,4 +1,4 @@ -# A dummy account contract without any validations. +// A dummy account contract without any validations. %lang starknet @@ -12,41 +12,51 @@ from starkware.starknet.common.syscalls import ( ) @view -func assert_only_self{syscall_ptr : felt*}(): - let (self) = get_contract_address() - let (caller) = get_caller_address() - assert self = caller - return () -end +func assert_only_self{syscall_ptr: felt*}() { + let (self) = get_contract_address(); + let (caller) = get_caller_address(); + assert self = caller; + return (); +} + +@external +func __validate_declare__(class_hash: felt) { + return (); +} + +@external +func __validate__(contract_address, selector: felt, calldata_len: felt, calldata: felt*) { + return (); +} @external @raw_output -func __execute__{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - contract_address, selector : felt, calldata_len : felt, calldata : felt* -) -> (retdata_size : felt, retdata : felt*): - let (retdata_size : felt, retdata : felt*) = call_contract( +func __execute__{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + contract_address, selector: felt, calldata_len: felt, calldata: felt* +) -> (retdata_size: felt, retdata: felt*) { + let (retdata_size: felt, retdata: felt*) = call_contract( contract_address=contract_address, function_selector=selector, calldata_size=calldata_len, calldata=calldata, - ) - return (retdata_size=retdata_size, retdata=retdata) -end + ); + return (retdata_size=retdata_size, retdata=retdata); +} @external -func deploy_contract{syscall_ptr : felt*}( - class_hash : felt, - contract_address_salt : felt, - constructor_calldata_len : felt, - constructor_calldata : felt*, -) -> (contract_address : felt): - assert_only_self() +func deploy_contract{syscall_ptr: felt*}( + class_hash: felt, + contract_address_salt: felt, + constructor_calldata_len: felt, + constructor_calldata: felt*, +) -> (contract_address: felt) { + assert_only_self(); let (contract_address) = deploy( class_hash=class_hash, contract_address_salt=contract_address_salt, constructor_calldata_size=constructor_calldata_len, constructor_calldata=constructor_calldata, deploy_from_zero=FALSE, - ) - return (contract_address=contract_address) -end + ); + return (contract_address=contract_address); +} diff --git a/src/starkware/starknet/core/test_contract/test_utils.py b/src/starkware/starknet/core/test_contract/test_utils.py index e6f7eae4..6e9a5a55 100644 --- a/src/starkware/starknet/core/test_contract/test_utils.py +++ b/src/starkware/starknet/core/test_contract/test_utils.py @@ -4,7 +4,7 @@ from starkware.starknet.services.api.contract_class import ContractClass -@functools.lru_cache(None) +@functools.lru_cache(maxsize=None) def get_contract_class(contract_name: str) -> ContractClass: main_dir_path = os.path.dirname(__file__) file_path = os.path.join(main_dir_path, contract_name + ".json") diff --git a/src/starkware/starknet/definitions/CMakeLists.txt b/src/starkware/starknet/definitions/CMakeLists.txt index 84935b31..873f39f9 100644 --- a/src/starkware/starknet/definitions/CMakeLists.txt +++ b/src/starkware/starknet/definitions/CMakeLists.txt @@ -10,7 +10,9 @@ python_lib(starknet_definitions_lib LIBS cairo_vm_crypto_lib everest_definitions_lib + everest_transaction_type_lib starkware_crypto_lib + starkware_dataclasses_field_utils_lib starkware_dataclasses_utils_lib starkware_error_handling_lib starkware_python_utils_lib @@ -31,6 +33,7 @@ python_lib(starknet_general_config_lib everest_general_config_lib starknet_definitions_lib starkware_config_utils_lib + starkware_dataclasses_field_utils_lib starkware_dataclasses_utils_lib starkware_python_utils_lib pip_marshmallow diff --git a/src/starkware/starknet/definitions/constants.py b/src/starkware/starknet/definitions/constants.py index 7ccfe61f..b4a3fb94 100644 --- a/src/starkware/starknet/definitions/constants.py +++ b/src/starkware/starknet/definitions/constants.py @@ -44,10 +44,13 @@ TRANSACTION_VERSION_UPPER_BOUND = FIELD_SIZE ADDRESS_LOWER_BOUND = 0 ADDRESS_UPPER_BOUND = 2**ADDRESS_BITS +UNINITIALIZED_CLASS_HASH = b"\x00" * HASH_BYTES # In order to identify transactions from unsupported versions. -TRANSACTION_VERSION = 0 +TRANSACTION_VERSION = 1 +# The version is considered 0 for L1-Handler transaction hash calculation purposes. +L1_HANDLER_VERSION = 0 # Indentation for transactions meant to query and not addressed to the OS. QUERY_VERSION_BASE = 2**128 QUERY_VERSION = QUERY_VERSION_BASE + TRANSACTION_VERSION @@ -55,7 +58,7 @@ # OS-related constants. L1_TO_L2_MSG_HEADER_SIZE = 5 L2_TO_L1_MSG_HEADER_SIZE = 3 -DEPLOYMENT_INFO_HEADER_SIZE = 3 +DEPLOYMENT_INFO_SIZE = 2 # StarkNet solidity contract-related constants. N_DEFAULT_TOPICS = 1 # Events have one default topic. diff --git a/src/starkware/starknet/definitions/error_codes.py b/src/starkware/starknet/definitions/error_codes.py index 9c1b3c70..3388c2d6 100644 --- a/src/starkware/starknet/definitions/error_codes.py +++ b/src/starkware/starknet/definitions/error_codes.py @@ -10,6 +10,7 @@ class StarknetErrorCode(ErrorCode): CONTRACT_BYTECODE_SIZE_TOO_LARGE = auto() CONTRACT_CLASS_OBJECT_SIZE_TOO_LARGE = auto() ENTRY_POINT_NOT_FOUND_IN_CONTRACT = auto() + EXTERNAL_TO_INTERNAL_CONVERSION_ERROR = auto() FEE_TRANSFER_FAILURE = auto() INVALID_BLOCK_NUMBER = auto() INVALID_BLOCK_TIMESTAMP = auto() @@ -19,11 +20,14 @@ class StarknetErrorCode(ErrorCode): INVALID_STATUS_MODE = auto() INVALID_TRANSACTION_HASH = auto() INVALID_TRANSACTION_ID = auto() + INVALID_TRANSACTION_NONCE = auto() INVALID_TRANSACTION_QUERYING_VERSION = auto() INVALID_TRANSACTION_VERSION = auto() L1_TO_L2_MESSAGE_CANCELLED = auto() L1_TO_L2_MESSAGE_ZEROED_COUNTER = auto() + MISSING_ENTRY_POINT_FOR_INVOKE = auto() MULTIPLE_ENTRY_POINTS_MATCH_SELECTOR = auto() + NON_EMPTY_SIGNATURE = auto() NON_PERMITTED_CONTRACT = auto() NO_TRACE = auto() OUT_OF_RANGE_ADDRESS = auto() @@ -47,30 +51,37 @@ class StarknetErrorCode(ErrorCode): TRANSACTION_FAILED = auto() TRANSACTION_LIMIT_EXCEEDED = auto() TRANSACTION_NOT_FOUND = auto() + UNAUTHORIZED_ACTION_ON_VALIDATE = auto() + UNAUTHORIZED_ENTRY_POINT_FOR_INVOKE = auto() UNDECLARED_CLASS = auto() UNEXPECTED_FAILURE = auto() UNINITIALIZED_CONTRACT = auto() - UNSUPPORTED_SELECTOR_FOR_FEE = auto() # Errors that are raised by the gateways and caused by wrong usage of the user. common_error_codes: List[ErrorCode] = [ - # Raw builtin exceptions from pre/post_load/dump are wrapped with StarkExcpetion and this code. + # Raw builtin exceptions from pre/post_load/dump are wrapped with StarkException and this code. StarkErrorCode.MALFORMED_REQUEST, StarkErrorCode.OUT_OF_RANGE_FIELD_ELEMENT, StarkErrorCode.SCHEMA_VALIDATION_ERROR, + StarknetErrorCode.INVALID_TRANSACTION_NONCE, + StarknetErrorCode.NON_EMPTY_SIGNATURE, StarknetErrorCode.OUT_OF_RANGE_CONTRACT_ADDRESS, StarknetErrorCode.OUT_OF_RANGE_ENTRY_POINT_OFFSET, StarknetErrorCode.OUT_OF_RANGE_ENTRY_POINT_SELECTOR, StarknetErrorCode.OUT_OF_RANGE_FEE, StarknetErrorCode.OUT_OF_RANGE_TRANSACTION_VERSION, # External-to-internal conversion errors. + StarknetErrorCode.EXTERNAL_TO_INTERNAL_CONVERSION_ERROR, StarknetErrorCode.INVALID_TRANSACTION_QUERYING_VERSION, StarknetErrorCode.INVALID_TRANSACTION_VERSION, - StarknetErrorCode.UNSUPPORTED_SELECTOR_FOR_FEE, + StarknetErrorCode.MISSING_ENTRY_POINT_FOR_INVOKE, + StarknetErrorCode.UNAUTHORIZED_ENTRY_POINT_FOR_INVOKE, # Contract class validation. StarknetErrorCode.INVALID_CONTRACT_CLASS, + # Validate execution. + StarknetErrorCode.UNAUTHORIZED_ACTION_ON_VALIDATE, ] main_gateway_error_code_whitelist: FrozenSet[ErrorCode] = frozenset( diff --git a/src/starkware/starknet/definitions/fields.py b/src/starkware/starknet/definitions/fields.py index 4da13be2..18b20aa5 100644 --- a/src/starkware/starknet/definitions/fields.py +++ b/src/starkware/starknet/definitions/fields.py @@ -16,16 +16,14 @@ ) from starkware.starkware_utils.marshmallow_dataclass_fields import ( BytesAsHex, + FrozenDictField, IntAsHex, IntAsStr, StrictRequiredInteger, VariadicLengthTupleField, ) -from starkware.starkware_utils.validated_fields import ( - OptionalField, - RangeValidatedField, - sequential_id_metadata, -) +from starkware.starkware_utils.marshmallow_fields_metadata import sequential_id_metadata +from starkware.starkware_utils.validated_fields import OptionalField, RangeValidatedField # Fields data: validation data, dataclass metadata. @@ -33,11 +31,7 @@ # Common. felt_as_hex_list_metadata = dict( - marshmallow_field=mfields.List( - everest_fields.FeltField.get_marshmallow_field( - required=True, load_default=marshmallow.utils.missing - ) - ) + marshmallow_field=mfields.List(everest_fields.FeltField.get_marshmallow_field()) ) felt_as_hex_or_str_list_metadata = dict( @@ -124,6 +118,8 @@ def address_metadata(name: str, error_code: StarknetErrorCode) -> Dict[str, Any] OptionalNonceField = OptionalField(field=NonceField, none_probability=0) optional_nonce_metadata = OptionalNonceField.metadata() +non_required_nonce_metadata = NonceField.metadata(required=False, load_default=0) + # Block. @@ -158,6 +154,10 @@ def address_metadata(name: str, error_code: StarknetErrorCode) -> Dict[str, Any] retdata_as_hex_metadata = felt_as_hex_list_metadata +# L1Handler. + +payload_metadata = felt_as_hex_list_metadata + # Contract address. L2AddressField = RangeValidatedField( @@ -299,9 +299,7 @@ def class_hash_from_bytes(class_hash: bytes) -> str: declared_contracts_metadata = dict( marshmallow_field=VariadicLengthTupleField( - ClassHashIntField.get_marshmallow_field( - required=True, load_default=marshmallow.utils.missing - ), + ClassHashIntField.get_marshmallow_field(), required=False, load_default=(), ) @@ -338,6 +336,31 @@ def class_hash_from_bytes(class_hash: bytes) -> str: marshmallow_field=StrictRequiredInteger(validate=validate_non_negative("invoke_tx_n_steps")) ) +validate_n_steps_metadata = dict( + marshmallow_field=StrictRequiredInteger(validate=validate_non_negative("validate_n_steps")) +) + gas_price = dict( marshmallow_field=StrictRequiredInteger(validate=validate_non_negative("gas_price")) ) + + +# Nonces. + +address_to_nonce_metadata = dict( + marshmallow_field=mfields.Dict( + keys=L2AddressField.get_marshmallow_field(), + values=NonceField.get_marshmallow_field(), + load_default=dict, + ) +) + +# ExecutionInfo. + +name_to_resources_metadata = dict( + marshmallow_field=FrozenDictField( + keys=mfields.String(required=True), + values=StrictRequiredInteger(validate=validate_non_negative("Resource value")), + load_default=dict, + ) +) diff --git a/src/starkware/starknet/definitions/general_config.py b/src/starkware/starknet/definitions/general_config.py index 67aea23a..2ac93f46 100644 --- a/src/starkware/starknet/definitions/general_config.py +++ b/src/starkware/starknet/definitions/general_config.py @@ -10,7 +10,7 @@ from services.everest.definitions.general_config import EverestGeneralConfig from starkware.cairo.lang.builtins.all_builtins import ( ALL_BUILTINS, - EC_OP_BUILTIN, + KECCAK_BUILTIN, OUTPUT_BUILTIN, with_suffix, ) @@ -21,6 +21,7 @@ from starkware.starkware_utils.field_validators import validate_dict, validate_non_negative from starkware.starkware_utils.marshmallow_dataclass_fields import ( StrictRequiredInteger, + additional_metadata, load_int_value, ) @@ -50,6 +51,7 @@ class StarknetChainId(Enum): # In order to be able to use Keccak builtin, which uses bitwise, which is sparse. DEFAULT_MAX_STEPS = 10**6 +DEFAULT_VALIDATE_MAX_STEPS = DEFAULT_MAX_STEPS DEFAULT_CHAIN_ID = StarknetChainId.TESTNET DEFAULT_FEE_TOKEN_ADDRESS = load_int_value( field_metadata=fields.fee_token_address_metadata, @@ -62,11 +64,9 @@ class StarknetChainId(Enum): # Given in units of wei. DEFAULT_GAS_PRICE = 100 * 10**9 - - DEFAULT_CAIRO_RESOURCE_FEE_WEIGHTS = { N_STEPS_RESOURCE: 1.0, - **{builtin: 0.0 for builtin in ALL_BUILTINS.except_for(EC_OP_BUILTIN).with_suffix()}, + **{builtin: 0.0 for builtin in ALL_BUILTINS.except_for(KECCAK_BUILTIN).with_suffix()}, } @@ -78,7 +78,7 @@ class StarknetOsConfig(Config): chain_id: StarknetChainId = field(default=DEFAULT_CHAIN_ID) fee_token_address: int = field( - metadata=dict( + metadata=additional_metadata( **fields.fee_token_address_metadata, description="StarkNet fee token L2 address." ), default=DEFAULT_FEE_TOKEN_ADDRESS, @@ -103,17 +103,21 @@ class StarknetGeneralConfig(EverestGeneralConfig): metadata=fields.invoke_tx_n_steps_metadata, default=DEFAULT_MAX_STEPS ) + validate_max_n_steps: int = field( + metadata=fields.validate_n_steps_metadata, default=DEFAULT_VALIDATE_MAX_STEPS + ) + min_gas_price: int = field(metadata=fields.gas_price, default=DEFAULT_GAS_PRICE) sequencer_address: int = field( - metadata=dict( + metadata=additional_metadata( **fields.sequencer_address_metadata, description="StarkNet sequencer address." ), default=DEFAULT_SEQUENCER_ADDRESS, ) tx_commitment_tree_height: int = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=StrictRequiredInteger( validate=validate_non_negative("Transaction commitment tree height"), ), @@ -123,7 +127,7 @@ class StarknetGeneralConfig(EverestGeneralConfig): ) tx_version: int = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=StrictRequiredInteger( validate=validate_non_negative("Transaction version."), ), @@ -136,7 +140,7 @@ class StarknetGeneralConfig(EverestGeneralConfig): ) event_commitment_tree_height: int = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=StrictRequiredInteger( validate=validate_non_negative("Event commitment tree height"), ), @@ -146,7 +150,7 @@ class StarknetGeneralConfig(EverestGeneralConfig): ) cairo_resource_fee_weights: Dict[str, float] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=mfields.Dict( keys=mfields.String, values=mfields.Float, @@ -188,7 +192,7 @@ def build_general_config(raw_general_config: Dict[str, Any]) -> StarknetGeneralC { resource: 0.0 for resource in [N_STEPS_RESOURCE] - + ALL_BUILTINS.except_for(EC_OP_BUILTIN).with_suffix() + + ALL_BUILTINS.except_for(KECCAK_BUILTIN).with_suffix() } ) # Update relevant entries. @@ -198,7 +202,7 @@ def build_general_config(raw_general_config: Dict[str, Any]) -> StarknetGeneralC # All other weights are deduced from n_steps. **{ with_suffix(builtin): n_steps_weight * all_instance.builtins[builtin].ratio - for builtin in ALL_BUILTINS.except_for(OUTPUT_BUILTIN, EC_OP_BUILTIN) + for builtin in ALL_BUILTINS.except_for(OUTPUT_BUILTIN, KECCAK_BUILTIN) }, } ) diff --git a/src/starkware/starknet/definitions/general_config.yml b/src/starkware/starknet/definitions/general_config.yml index ca7cf654..4f282530 100644 --- a/src/starkware/starknet/definitions/general_config.yml +++ b/src/starkware/starknet/definitions/general_config.yml @@ -5,8 +5,10 @@ event_commitment_tree_height: 64 global_state_commitment_tree_height: 251 invoke_tx_max_n_steps: 1000000 min_gas_price: 100000000000 -sequencer_address: '0x4bbfb0d1aab5bf33eec5ada3a1040c41ed902a1eeb38c78a753d6f6359f1666' +sequencer_address: '0x6c4ae5be723ab0402cd675e7f8e1cf5a775e972e6f080ad0b842f40ec202a69' starknet_os_config: - fee_token_address: '0x596b3e5d7f1f6ebe6ce641d6e50ca2830f803c93d82b3906af369bac993ec8d' + chain_id: TESTNET + fee_token_address: '0x5818bca45def7134510ce9874b5061ed3f8048074613817b03cd849907980d' tx_commitment_tree_height: 64 -tx_version: 0 +tx_version: 1 +validate_max_n_steps: 1000000 diff --git a/src/starkware/starknet/definitions/transaction_type.py b/src/starkware/starknet/definitions/transaction_type.py index b1fb68b3..5ba8f256 100644 --- a/src/starkware/starknet/definitions/transaction_type.py +++ b/src/starkware/starknet/definitions/transaction_type.py @@ -1,8 +1,11 @@ -from enum import Enum, auto +from enum import auto +from services.everest.api.gateway.transaction_type import TransactionTypeBase -class TransactionType(Enum): + +class TransactionType(TransactionTypeBase): DECLARE = 0 DEPLOY = auto() INITIALIZE_BLOCK_INFO = auto() INVOKE_FUNCTION = auto() + L1_HANDLER = auto() diff --git a/src/starkware/starknet/public/abi.py b/src/starkware/starknet/public/abi.py index d106f422..4aefb956 100644 --- a/src/starkware/starknet/public/abi.py +++ b/src/starkware/starknet/public/abi.py @@ -15,13 +15,22 @@ # OS context offset. SYSCALL_PTR_OFFSET = 0 +CONSTRUCTOR_ENTRY_POINT_NAME = "constructor" DEFAULT_ENTRY_POINT_NAME = "__default__" DEFAULT_L1_ENTRY_POINT_NAME = "__l1_default__" DEFAULT_ENTRY_POINT_SELECTOR = 0 EXECUTE_ENTRY_POINT_NAME = "__execute__" TRANSFER_ENTRY_POINT_NAME = "transfer" +VALIDATE_ENTRY_POINT_NAME = "__validate__" +VALIDATE_DECLARE_ENTRY_POINT_NAME = "__validate_declare__" +ACCOUNT_ENTRY_POINT_NAMES = { + EXECUTE_ENTRY_POINT_NAME, + VALIDATE_ENTRY_POINT_NAME, + VALIDATE_DECLARE_ENTRY_POINT_NAME, +} -AbiType = List[Dict[str, Any]] +AbiEntryType = Dict[str, Any] +AbiType = List[AbiEntryType] def starknet_keccak(data: bytes) -> int: @@ -39,8 +48,13 @@ def get_selector_from_name(func_name: str) -> int: return starknet_keccak(data=func_name.encode("ascii")) +CONSTRUCTOR_ENTRY_POINT_SELECTOR = get_selector_from_name(func_name=CONSTRUCTOR_ENTRY_POINT_NAME) EXECUTE_ENTRY_POINT_SELECTOR = get_selector_from_name(func_name=EXECUTE_ENTRY_POINT_NAME) TRANSFER_ENTRY_POINT_SELECTOR = get_selector_from_name(func_name=TRANSFER_ENTRY_POINT_NAME) +VALIDATE_ENTRY_POINT_SELECTOR = get_selector_from_name(func_name=VALIDATE_ENTRY_POINT_NAME) +VALIDATE_DECLARE_ENTRY_POINT_SELECTOR = get_selector_from_name( + func_name=VALIDATE_DECLARE_ENTRY_POINT_NAME +) def get_storage_var_address(var_name: str, *args) -> int: diff --git a/src/starkware/starknet/public/abi_structs.py b/src/starkware/starknet/public/abi_structs.py index e0263f8e..1d2ceb04 100644 --- a/src/starkware/starknet/public/abi_structs.py +++ b/src/starkware/starknet/public/abi_structs.py @@ -41,13 +41,13 @@ def prepare_type_for_abi(cairo_type: CairoType) -> AbiTypeInfo: structs=structs, ) elif isinstance(cairo_type, TypeStruct): - struct_name = cairo_type.resolved_scope.path[-1] + struct_name = cairo_type.scope.path[-1] return AbiTypeInfo( modified_type=dataclasses.replace( cairo_type, scope=ScopedName.from_string(struct_name) ), - structs={cairo_type.resolved_scope}, + structs={cairo_type.scope}, ) elif isinstance(cairo_type, TypeFelt): return AbiTypeInfo(modified_type=cairo_type, structs=set()) diff --git a/src/starkware/starknet/security/CMakeLists.txt b/src/starkware/starknet/security/CMakeLists.txt index 126a3e4b..5b13b9ef 100644 --- a/src/starkware/starknet/security/CMakeLists.txt +++ b/src/starkware/starknet/security/CMakeLists.txt @@ -26,7 +26,9 @@ full_python_test(starknet_hints_latest_whitelist_test cairo_common_lib cairo_constants_lib starknet_common_lib + starknet_hints_whitelist_lib starknet_security_lib + starkware_python_utils_lib pip_pytest ) diff --git a/src/starkware/starknet/security/latest_whitelist_test.py b/src/starkware/starknet/security/latest_whitelist_test.py index 2f7da33e..f57a5812 100644 --- a/src/starkware/starknet/security/latest_whitelist_test.py +++ b/src/starkware/starknet/security/latest_whitelist_test.py @@ -12,11 +12,15 @@ CAIRO_FILE = os.path.join(os.path.dirname(__file__), "starknet_common.cairo") +LATEST_WHITELIST_FILE = get_source_dir_path( + "src/starkware/starknet/security/whitelists/latest.json", + default_value=os.path.join(os.path.dirname(__file__), "whitelists/latest.json"), +) def run(fix: bool): program = compile_cairo_files(files=[CAIRO_FILE], prime=DEFAULT_PRIME) - filename = get_source_dir_path("src/starkware/starknet/security/whitelists/latest.json") + filename = LATEST_WHITELIST_FILE whitelist = HintsWhitelist.from_program(program) if fix: data = whitelist.dumps(indent=4, sort_keys=True) diff --git a/src/starkware/starknet/security/secure_hints.py b/src/starkware/starknet/security/secure_hints.py index 9dbf0ead..7d0032cb 100644 --- a/src/starkware/starknet/security/secure_hints.py +++ b/src/starkware/starknet/security/secure_hints.py @@ -11,6 +11,7 @@ from starkware.cairo.lang.compiler.preprocessor.flow import ReferenceManager from starkware.cairo.lang.compiler.program import CairoHint, Program from starkware.starknet.security.simple_references import is_simple_reference +from starkware.starkware_utils.marshmallow_dataclass_fields import additional_metadata from starkware.starkware_utils.validated_dataclass import ( ValidatedDataclass, ValidatedMarshmallowDataclass, @@ -48,7 +49,9 @@ def __lt__(self, other): class HintsWhitelistEntry(ValidatedDataclass): hint_lines: List[str] allowed_expressions: Set[NamedExpression] = field( - metadata=dict(marshmallow_field=SetField(mfields.Nested(NamedExpression.Schema))) + metadata=additional_metadata( + marshmallow_field=SetField(mfields.Nested(NamedExpression.Schema)) + ) ) Schema: ClassVar[Type[marshmallow.Schema]] @@ -83,7 +86,7 @@ class HintsWhitelist(ValidatedMarshmallowDataclass): # Maps a hint string to the set of allowed expressions in its references. allowed_reference_expressions_for_hint: Dict[str, Set[NamedExpression]] = field( - metadata=dict(marshmallow_field=HintsWhitelistDict()) + metadata=additional_metadata(marshmallow_field=HintsWhitelistDict()) ) @classmethod @@ -139,6 +142,21 @@ def union(cls, whitelists: Iterable["HintsWhitelist"]) -> "HintsWhitelist": res.setdefault(code, set()).update(refs) return cls(allowed_reference_expressions_for_hint=res) + def diff(self, other_whitelist: "HintsWhitelist") -> "HintsWhitelist": + """ + Returns the difference between this whitelist and the given other_whitelist. + """ + diff_allowed_reference_expressions_for_hint = { + code: self.allowed_reference_expressions_for_hint[code] + for code in ( + self.allowed_reference_expressions_for_hint.keys() + - other_whitelist.allowed_reference_expressions_for_hint.keys() + ) + } + return HintsWhitelist( + allowed_reference_expressions_for_hint=diff_allowed_reference_expressions_for_hint + ) + # Reading operations. def verify_program_hint_secure(self, program: Program): """ diff --git a/src/starkware/starknet/security/secure_hints_test.py b/src/starkware/starknet/security/secure_hints_test.py index 02ab8a94..50986292 100644 --- a/src/starkware/starknet/security/secure_hints_test.py +++ b/src/starkware/starknet/security/secure_hints_test.py @@ -7,51 +7,43 @@ from starkware.starknet.security.secure_hints import HintsWhitelist, InsecureHintError ALLOWED_CODE = """ -func f(a: felt, b: felt): - %{ - This is a hint. - %} - ap += 5 - ret -end +func f(a: felt, b: felt) { + %{ This is a hint. %} + ap += 5; + ret; +} """ GOOD_CODES = [ """ -func f(b: felt): - %{ - This is a hint. - %} - ap += 5 - ret -end +func f(b: felt) { + %{ This is a hint. %} + ap += 5; + ret; +} """, ] BAD_CODES = [ ( """ -func f(a: felt, b: felt): - let c = a / b - %{ - This is a hint. - %} - ap += 5 - ret -end +func f(a: felt, b: felt) { + let c = a / b; + %{ This is a hint. %} + ap += 5; + ret; +} """, """Forbidden expressions in hint "This is a hint.": [NamedExpression(name='__main__.f.c', expr='cast([fp + (-4)] / [fp + (-3)], felt)')]""", ), ( """ -func f(a: felt, b: felt): - %{ - This is a bad hint. - %} - ap += 5 - ret -end +func f(a: felt, b: felt) { + %{ This is a bad hint. %} + ap += 5; + ret; +} """, "is not whitelisted", ), @@ -84,20 +76,16 @@ def test_collision(): Tests multiple hints with the same code but different reference expressions. """ code = """ -func f(): - let b = [ap] - %{ - ids.b = 1 - %} - ret -end -func g(): - let b = [ap - 10] - %{ - ids.b = 1 - %} - ret -end +func f() { + let b = [ap]; + %{ ids.b = 1 %} + ret; +} +func g() { + let b = [ap - 10]; + %{ ids.b = 1 %} + ret; +} """ program = compile_cairo(code, DEFAULT_PRIME) whitelist = HintsWhitelist.from_program(program) diff --git a/src/starkware/starknet/security/starknet_common.cairo b/src/starkware/starknet/security/starknet_common.cairo index 500c9f69..7d1ac65a 100644 --- a/src/starkware/starknet/security/starknet_common.cairo +++ b/src/starkware/starknet/security/starknet_common.cairo @@ -24,6 +24,7 @@ from starkware.cairo.common.cairo_secp.signature import ( ) from starkware.cairo.common.default_dict import default_dict_finalize, default_dict_new from starkware.cairo.common.dict import dict_read, dict_squash, dict_update, dict_write +from starkware.cairo.common.ec import chained_ec_op, ec_op, recover_y from starkware.cairo.common.find_element import find_element, search_sorted, search_sorted_lower from starkware.cairo.common.keccak import unsafe_keccak from starkware.cairo.common.math import ( @@ -39,6 +40,7 @@ from starkware.cairo.common.math import ( assert_not_equal, assert_not_zero, horner_eval, + is_quad_residue, sign, signed_div_rem, split_felt, diff --git a/src/starkware/starknet/security/whitelists/latest.json b/src/starkware/starknet/security/whitelists/latest.json index b2692ab8..b5bd8bb2 100644 --- a/src/starkware/starknet/security/whitelists/latest.json +++ b/src/starkware/starknet/security/whitelists/latest.json @@ -130,6 +130,12 @@ " raise ValueError(f'Key {key} was not found.')" ] }, + { + "allowed_expressions": [], + "hint_lines": [ + "assert excluded == 2" + ] + }, { "allowed_expressions": [], "hint_lines": [ @@ -475,20 +481,6 @@ "assert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'" ] }, - { - "allowed_expressions": [], - "hint_lines": [ - "from starkware.cairo.common.math_utils import assert_integer", - "assert_integer(ids.a)", - "assert_integer(ids.b)", - "a = ids.a % PRIME", - "b = ids.b % PRIME", - "assert a <= b, f'a = {a} is not less than or equal to b = {b}.'", - "", - "ids.small_inputs = int(", - " a < range_check_builtin.bound and (b - a) < range_check_builtin.bound)" - ] - }, { "allowed_expressions": [], "hint_lines": [ @@ -538,6 +530,75 @@ "assert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'" ] }, + { + "allowed_expressions": [], + "hint_lines": [ + "from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME", + "from starkware.python.math_utils import random_ec_point", + "from starkware.python.utils import to_bytes", + "", + "# Define a seed for random_ec_point that's dependent on all the input, so that:", + "# (1) The added point s is deterministic.", + "# (2) It's hard to choose inputs for which the builtin will fail.", + "seed = b\"\".join(map(to_bytes, [ids.p.x, ids.p.y, ids.m, ids.q.x, ids.q.y]))", + "ids.s.x, ids.s.y = random_ec_point(FIELD_PRIME, ALPHA, BETA, seed)" + ] + }, + { + "allowed_expressions": [], + "hint_lines": [ + "from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME", + "from starkware.python.math_utils import random_ec_point", + "from starkware.python.utils import to_bytes", + "", + "n_elms = ids.len", + "assert isinstance(n_elms, int) and n_elms >= 0, \\", + " f'Invalid value for len. Got: {n_elms}.'", + "if '__chained_ec_op_max_len' in globals():", + " assert n_elms <= __chained_ec_op_max_len, \\", + " f'chained_ec_op() can only be used with len<={__chained_ec_op_max_len}. ' \\", + " f'Got: n_elms={n_elms}.'", + "", + "# Define a seed for random_ec_point that's dependent on all the input, so that:", + "# (1) The added point s is deterministic.", + "# (2) It's hard to choose inputs for which the builtin will fail.", + "seed = b\"\".join(", + " map(", + " to_bytes,", + " [", + " ids.p.x,", + " ids.p.y,", + " *memory.get_range(ids.m, n_elms),", + " *memory.get_range(ids.q.address_, 2 * n_elms),", + " ],", + " )", + ")", + "ids.s.x, ids.s.y = random_ec_point(FIELD_PRIME, ALPHA, BETA, seed)" + ] + }, + { + "allowed_expressions": [], + "hint_lines": [ + "from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME", + "from starkware.python.math_utils import recover_y", + "ids.p.x = ids.x", + "# This raises an exception if `x` is not on the curve.", + "ids.p.y = recover_y(ids.x, ALPHA, BETA, FIELD_PRIME)" + ] + }, + { + "allowed_expressions": [], + "hint_lines": [ + "from starkware.crypto.signature.signature import FIELD_PRIME", + "from starkware.python.math_utils import div_mod, is_quad_residue, sqrt", + "", + "x = ids.x", + "if is_quad_residue(x, FIELD_PRIME):", + " ids.y = sqrt(x, FIELD_PRIME)", + "else:", + " ids.y = sqrt(div_mod(x, 3, FIELD_PRIME), FIELD_PRIME)" + ] + }, { "allowed_expressions": [], "hint_lines": [ @@ -617,6 +678,30 @@ "del initial_dict" ] }, + { + "allowed_expressions": [], + "hint_lines": [ + "import itertools", + "", + "from starkware.cairo.common.math_utils import assert_integer", + "assert_integer(ids.a)", + "assert_integer(ids.b)", + "a = ids.a % PRIME", + "b = ids.b % PRIME", + "assert a <= b, f'a = {a} is not less than or equal to b = {b}.'", + "", + "# Find an arc less than PRIME / 3, and another less than PRIME / 2.", + "lengths_and_indices = [(a, 0), (b - a, 1), (PRIME - 1 - b, 2)]", + "lengths_and_indices.sort()", + "assert lengths_and_indices[0][0] <= PRIME // 3 and lengths_and_indices[1][0] <= PRIME // 2", + "excluded = lengths_and_indices[2][1]", + "", + "memory[ids.range_check_ptr + 1], memory[ids.range_check_ptr + 0] = (", + " divmod(lengths_and_indices[0][0], ids.PRIME_OVER_3_HIGH))", + "memory[ids.range_check_ptr + 3], memory[ids.range_check_ptr + 2] = (", + " divmod(lengths_and_indices[1][0], ids.PRIME_OVER_2_HIGH))" + ] + }, { "allowed_expressions": [], "hint_lines": [ @@ -654,6 +739,18 @@ "memory[ap] = 1 if 0 <= (ids.a.high % PRIME) < 2 ** 127 else 0" ] }, + { + "allowed_expressions": [], + "hint_lines": [ + "memory[ap] = 1 if excluded != 0 else 0" + ] + }, + { + "allowed_expressions": [], + "hint_lines": [ + "memory[ap] = 1 if excluded != 1 else 0" + ] + }, { "allowed_expressions": [], "hint_lines": [ diff --git a/src/starkware/starknet/services/CMakeLists.txt b/src/starkware/starknet/services/CMakeLists.txt index 53d257b0..9b599545 100644 --- a/src/starkware/starknet/services/CMakeLists.txt +++ b/src/starkware/starknet/services/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(api) +add_subdirectory(utils) diff --git a/src/starkware/starknet/services/api/CMakeLists.txt b/src/starkware/starknet/services/api/CMakeLists.txt index 2ad7b578..07e60710 100644 --- a/src/starkware/starknet/services/api/CMakeLists.txt +++ b/src/starkware/starknet/services/api/CMakeLists.txt @@ -10,9 +10,8 @@ python_lib(starknet_messages_lib LIBS cairo_bootloader_generate_fact_lib everest_definitions_lib - starknet_contract_class_lib starknet_definitions_lib - starknet_internal_transaction_lib + starknet_transaction_objects_lib starkware_dataclasses_utils_lib starkware_error_handling_lib ) diff --git a/src/starkware/starknet/services/api/contract_class.py b/src/starkware/starknet/services/api/contract_class.py index a13b68ee..e234b6be 100644 --- a/src/starkware/starknet/services/api/contract_class.py +++ b/src/starkware/starknet/services/api/contract_class.py @@ -9,7 +9,7 @@ from starkware.cairo.lang.compiler.program import Program from starkware.starknet.definitions import fields from starkware.starknet.definitions.error_codes import StarknetErrorCode -from starkware.starknet.public.abi import AbiType, get_selector_from_name +from starkware.starknet.public.abi import AbiType from starkware.starkware_utils.error_handling import stark_assert from starkware.starkware_utils.subsequence import is_subsequence from starkware.starkware_utils.validated_dataclass import ( @@ -18,8 +18,7 @@ ) # An ordered list of the supported builtins. -SUPPORTED_BUILTINS = ["pedersen", "range_check", "ecdsa", "bitwise"] -CONSTRUCTOR_SELECTOR = get_selector_from_name("constructor") +SUPPORTED_BUILTINS = ["pedersen", "range_check", "ecdsa", "bitwise", "ec_op"] class EntryPointType(Enum): diff --git a/src/starkware/starknet/services/api/feeder_gateway/CMakeLists.txt b/src/starkware/starknet/services/api/feeder_gateway/CMakeLists.txt index b7023359..c3425764 100644 --- a/src/starkware/starknet/services/api/feeder_gateway/CMakeLists.txt +++ b/src/starkware/starknet/services/api/feeder_gateway/CMakeLists.txt @@ -8,6 +8,7 @@ python_lib(starknet_feeder_gateway_client_lib everest_feeder_gateway_client_lib services_external_api_lib starknet_definitions_lib + starknet_feeder_gateway_request_objects_lib starknet_feeder_gateway_response_objects_lib starknet_transaction_lib starkware_dataclasses_utils_lib @@ -27,8 +28,9 @@ python_lib(starknet_feeder_gateway_response_objects_lib everest_transaction_execution_objects_lib starknet_contract_class_lib starknet_definitions_lib - starknet_internal_transaction_lib + starknet_transaction_objects_lib starknet_transaction_execution_objects_lib + starkware_dataclasses_field_utils_lib starkware_dataclasses_utils_lib starkware_python_utils_lib pip_marshmallow @@ -38,3 +40,18 @@ python_lib(starknet_feeder_gateway_response_objects_lib pip_typing_extensions pip_web3 ) + +python_lib(starknet_feeder_gateway_request_objects_lib + PREFIX starkware/starknet/services/api/feeder_gateway + + FILES + request_objects.py + + LIBS + everest_definitions_lib + starknet_definitions_lib + starknet_execute_entry_point_lib + starknet_transaction_objects_lib + starkware_dataclasses_utils_lib + pip_marshmallow_dataclass +) diff --git a/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py b/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py index d40b0b9b..7c6ba67a 100644 --- a/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py +++ b/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py @@ -4,15 +4,21 @@ from services.everest.api.feeder_gateway.feeder_gateway_client import EverestFeederGatewayClient from services.external_api.client import JsonObject from starkware.starknet.definitions import fields +from starkware.starknet.services.api.feeder_gateway.request_objects import ( + CallFunction, + CallL1Handler, +) from starkware.starknet.services.api.feeder_gateway.response_objects import ( BlockIdentifier, BlockTransactionTraces, + FeeEstimationInfo, StarknetBlock, TransactionInfo, TransactionReceipt, + TransactionSimulationInfo, TransactionTrace, ) -from starkware.starknet.services.api.gateway.transaction import InvokeFunction +from starkware.starknet.services.api.gateway.transaction import AccountTransaction from starkware.starkware_utils.validated_fields import RangeValidatedField CastableToHash = Union[int, str] @@ -29,7 +35,7 @@ async def get_contract_addresses(self) -> Dict[str, str]: async def call_contract( self, - invoke_tx: InvokeFunction, + call_function: CallFunction, block_hash: Optional[CastableToHash] = None, block_number: Optional[BlockIdentifier] = None, ) -> Dict[str, List[str]]: @@ -39,25 +45,57 @@ async def call_contract( raw_response = await self._send_request( send_method="POST", uri=f"/call_contract?{formatted_block_named_argument}", - data=invoke_tx.dumps(), + data=call_function.dumps(), ) return json.loads(raw_response) async def estimate_fee( self, - invoke_tx: InvokeFunction, + tx: AccountTransaction, block_hash: Optional[CastableToHash] = None, block_number: Optional[BlockIdentifier] = None, - ) -> JsonObject: + ) -> FeeEstimationInfo: formatted_block_named_argument = get_formatted_block_named_argument( block_hash=block_hash, block_number=block_number ) raw_response = await self._send_request( send_method="POST", uri=f"/estimate_fee?{formatted_block_named_argument}", - data=invoke_tx.dumps(), + data=AccountTransaction.Schema().dumps(obj=tx), ) - return json.loads(raw_response) + return FeeEstimationInfo.loads(data=raw_response) + + async def estimate_message_fee( + self, + call_l1_handler: CallL1Handler, + block_hash: Optional[CastableToHash] = None, + block_number: Optional[BlockIdentifier] = None, + ) -> FeeEstimationInfo: + formatted_block_named_argument = get_formatted_block_named_argument( + block_hash=block_hash, block_number=block_number + ) + raw_response = await self._send_request( + send_method="POST", + uri=f"/estimate_message_fee?{formatted_block_named_argument}", + data=call_l1_handler.dumps(), + ) + return FeeEstimationInfo.loads(data=raw_response) + + async def simulate_transaction( + self, + tx: AccountTransaction, + block_hash: Optional[CastableToHash] = None, + block_number: Optional[BlockIdentifier] = None, + ) -> TransactionSimulationInfo: + formatted_block_named_argument = get_formatted_block_named_argument( + block_hash=block_hash, block_number=block_number + ) + raw_response = await self._send_request( + send_method="POST", + uri=f"/simulate_transaction?{formatted_block_named_argument}", + data=AccountTransaction.Schema().dumps(obj=tx), + ) + return TransactionSimulationInfo.loads(data=raw_response) async def get_block( self, @@ -110,9 +148,10 @@ async def get_code( formatted_block_named_argument = get_formatted_block_named_argument( block_hash=block_hash, block_number=block_number ) + contract_address_str = fields.L2AddressField.format(contract_address) raw_response = await self._send_request( send_method="GET", - uri=f"/get_code?contractAddress={fields.L2AddressField.format(contract_address)}&" + uri=f"/get_code?contractAddress={contract_address_str}&" f"{formatted_block_named_argument}", ) return json.loads(raw_response) @@ -130,8 +169,9 @@ async def get_full_contract( formatted_block_named_argument = get_formatted_block_named_argument( block_hash=block_hash, block_number=block_number ) + contract_address_str = fields.L2AddressField.format(contract_address) uri = ( - f"/get_full_contract?contractAddress={fields.L2AddressField.format(contract_address)}&" + f"/get_full_contract?contractAddress={contract_address_str}&" f"{formatted_block_named_argument}" ) raw_response = await self._send_request(send_method="GET", uri=uri) @@ -175,13 +215,28 @@ async def get_storage_at( formatted_block_named_argument = get_formatted_block_named_argument( block_hash=block_hash, block_number=block_number ) + contract_address_str = fields.L2AddressField.format(contract_address) uri = ( - f"/get_storage_at?contractAddress={fields.L2AddressField.format(contract_address)}&" + f"/get_storage_at?contractAddress={contract_address_str}&" f"key={key}&{formatted_block_named_argument}" ) raw_response = await self._send_request(send_method="GET", uri=uri) return json.loads(raw_response) + async def get_nonce( + self, + contract_address: int, + block_hash: Optional[CastableToHash] = None, + block_number: Optional[BlockIdentifier] = None, + ) -> int: + formatted_block_identifier = get_formatted_block_named_argument( + block_hash=block_hash, block_number=block_number + ) + contract_address_str = fields.L2AddressField.format(contract_address) + uri = f"/get_nonce?contractAddress={contract_address_str}&{formatted_block_identifier}" + raw_response = await self._send_request(send_method="GET", uri=uri) + return int(json.loads(raw_response), 16) + async def get_transaction_status(self, tx_hash: CastableToHash) -> JsonObject: raw_response = await self._send_request( send_method="GET", diff --git a/src/starkware/starknet/services/api/feeder_gateway/request_objects.py b/src/starkware/starknet/services/api/feeder_gateway/request_objects.py new file mode 100644 index 00000000..84e5103b --- /dev/null +++ b/src/starkware/starknet/services/api/feeder_gateway/request_objects.py @@ -0,0 +1,55 @@ +from dataclasses import field +from typing import List + +import marshmallow_dataclass + +from services.everest.definitions import fields as everest_fields +from starkware.starknet.business_logic.execution.execute_entry_point import ExecuteEntryPoint +from starkware.starknet.business_logic.transaction.objects import InternalL1Handler +from starkware.starknet.definitions import fields +from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass + + +@marshmallow_dataclass.dataclass(frozen=True) +class CallFunction(ValidatedMarshmallowDataclass): + """ + Represents a contract function call in the StarkNet network. + """ + + contract_address: int = field(metadata=fields.contract_address_metadata) + # A field element that encodes the invoked method. + entry_point_selector: int = field(metadata=fields.entry_point_selector_metadata) + calldata: List[int] = field(metadata=fields.call_data_metadata) + + def to_entry_point(self) -> ExecuteEntryPoint: + return ExecuteEntryPoint.create_for_testing( + contract_address=self.contract_address, + calldata=self.calldata, + entry_point_selector=self.entry_point_selector, + ) + + +@marshmallow_dataclass.dataclass(frozen=True) +class CallL1Handler(ValidatedMarshmallowDataclass): + """ + Represents an L1 handler call in the StarkNet network. + """ + + from_address: int = field( + metadata=everest_fields.EthAddressIntField.metadata(field_name="from_address") + ) + to_address: int = field(metadata=fields.contract_address_metadata) + entry_point_selector: int = field(metadata=fields.entry_point_selector_metadata) + payload: List[int] = field(metadata=fields.payload_metadata) + + def to_internal(self, chain_id: int) -> InternalL1Handler: + """ + Creates an internal L1 handler with nonce 0. + """ + return InternalL1Handler.create( + contract_address=self.to_address, + entry_point_selector=self.entry_point_selector, + calldata=[self.from_address, *self.payload], + nonce=0, + chain_id=chain_id, + ) diff --git a/src/starkware/starknet/services/api/feeder_gateway/response_objects.py b/src/starkware/starknet/services/api/feeder_gateway/response_objects.py index c021ef48..ddf4b67c 100644 --- a/src/starkware/starknet/services/api/feeder_gateway/response_objects.py +++ b/src/starkware/starknet/services/api/feeder_gateway/response_objects.py @@ -8,7 +8,6 @@ import marshmallow.fields as mfields import marshmallow.utils import marshmallow_dataclass -from marshmallow.decorators import pre_load from marshmallow_oneofschema import OneOfSchema from typing_extensions import Literal from web3 import Web3 @@ -20,7 +19,7 @@ from services.everest.business_logic.transaction_execution_objects import TransactionFailureReason from services.everest.definitions import fields as everest_fields from starkware.cairo.lang.vm.cairo_pie import ExecutionResources -from starkware.python.utils import from_bytes, to_bytes +from starkware.python.utils import as_non_optional, from_bytes, to_bytes from starkware.starknet.business_logic.execution.objects import ( CallInfo, CallType, @@ -28,22 +27,24 @@ OrderedEvent, OrderedL2ToL1Message, ) -from starkware.starknet.business_logic.internal_transaction import ( +from starkware.starknet.business_logic.transaction.objects import ( InternalDeclare, InternalDeploy, InternalInvokeFunction, + InternalL1Handler, InternalTransaction, ) -from starkware.starknet.definitions import fields +from starkware.starknet.definitions import constants, fields from starkware.starknet.definitions.transaction_type import TransactionType from starkware.starknet.services.api.contract_class import EntryPointType from starkware.starkware_utils.marshmallow_dataclass_fields import ( VariadicLengthTupleField, + additional_metadata, nonrequired_optional_metadata, ) +from starkware.starkware_utils.marshmallow_fields_metadata import sequential_id_metadata from starkware.starkware_utils.serializable_dataclass import SerializableMarshmallowDataclass from starkware.starkware_utils.validated_dataclass import ValidatedDataclass -from starkware.starkware_utils.validated_fields import sequential_id_metadata BlockNumber = int LatestBlock = Literal["latest"] @@ -224,6 +225,7 @@ def __post_init__(self): @marshmallow_dataclass.dataclass(frozen=True) class TransactionSpecificInfo(ValidatedResponseObject): tx_type: ClassVar[TransactionType] + version: int = field(metadata=fields.tx_version_metadata) @classmethod def from_internal(cls, internal_tx: InternalTransaction) -> "TransactionSpecificInfo": @@ -232,7 +234,11 @@ def from_internal(cls, internal_tx: InternalTransaction) -> "TransactionSpecific elif isinstance(internal_tx, InternalDeploy): return DeploySpecificInfo.from_internal_deploy(internal_tx=internal_tx) elif isinstance(internal_tx, InternalInvokeFunction): + if internal_tx.entry_point_type is EntryPointType.L1_HANDLER: + return L1HandlerSpecificInfo.from_internal_invoke(internal_tx=internal_tx) return InvokeSpecificInfo.from_internal_invoke(internal_tx=internal_tx) + elif isinstance(internal_tx, InternalL1Handler): + return L1HandlerSpecificInfo.from_internal_l1_handler(internal_tx=internal_tx) else: raise NotImplementedError(f"No response object for {internal_tx}.") @@ -243,9 +249,8 @@ class DeclareSpecificInfo(TransactionSpecificInfo): sender_address: int = field(metadata=fields.contract_address_metadata) nonce: int = field(metadata=fields.nonce_metadata) max_fee: int = field(metadata=fields.fee_metadata) - version: int = field(metadata=fields.tx_version_metadata) transaction_hash: int = field(metadata=fields.transaction_hash_metadata) - signature: List[int] = field(metadata=fields.signature_metadata) + signature: List[int] = field(metadata=fields.signature_as_hex_metadata) tx_type: ClassVar[TransactionType] = TransactionType.DECLARE @@ -254,7 +259,7 @@ def from_internal_declare(cls, internal_tx: InternalDeclare) -> "DeclareSpecific return cls( class_hash=from_bytes(internal_tx.class_hash), sender_address=internal_tx.sender_address, - nonce=internal_tx.nonce, + nonce=as_non_optional(internal_tx.nonce), max_fee=internal_tx.max_fee, version=internal_tx.version, transaction_hash=internal_tx.hash_value, @@ -279,6 +284,7 @@ def from_internal_deploy(cls, internal_tx: InternalDeploy) -> "DeploySpecificInf contract_address_salt=internal_tx.contract_address_salt, class_hash=from_bytes(internal_tx.contract_hash), constructor_calldata=internal_tx.constructor_calldata, + version=internal_tx.version, transaction_hash=internal_tx.hash_value, ) @@ -288,6 +294,7 @@ class InvokeSpecificInfo(TransactionSpecificInfo): contract_address: int = field(metadata=fields.contract_address_metadata) entry_point_selector: int = field(metadata=fields.entry_point_selector_metadata) entry_point_type: EntryPointType + nonce: Optional[int] = field(metadata=fields.optional_nonce_metadata) calldata: List[int] = field(metadata=fields.call_data_as_hex_metadata) signature: List[int] = field(metadata=fields.signature_as_hex_metadata) transaction_hash: int = field(metadata=fields.transaction_hash_metadata) @@ -301,18 +308,57 @@ def from_internal_invoke(cls, internal_tx: InternalInvokeFunction) -> "InvokeSpe contract_address=internal_tx.contract_address, entry_point_selector=internal_tx.entry_point_selector, entry_point_type=internal_tx.entry_point_type, + nonce=internal_tx.nonce, calldata=internal_tx.calldata, + version=internal_tx.version, signature=internal_tx.signature, transaction_hash=internal_tx.hash_value, max_fee=internal_tx.max_fee, ) +@marshmallow_dataclass.dataclass(frozen=True) +class L1HandlerSpecificInfo(TransactionSpecificInfo): + contract_address: int = field(metadata=fields.contract_address_metadata) + entry_point_selector: int = field(metadata=fields.entry_point_selector_metadata) + nonce: int = field(metadata=fields.nonce_metadata) + calldata: List[int] = field(metadata=fields.call_data_as_hex_metadata) + transaction_hash: int = field(metadata=fields.transaction_hash_metadata) + + tx_type: ClassVar[TransactionType] = TransactionType.L1_HANDLER + + @classmethod + def from_internal_l1_handler(cls, internal_tx: InternalL1Handler) -> "L1HandlerSpecificInfo": + return cls( + contract_address=internal_tx.contract_address, + entry_point_selector=internal_tx.entry_point_selector, + nonce=internal_tx.nonce, + calldata=internal_tx.calldata, + version=constants.L1_HANDLER_VERSION, + transaction_hash=internal_tx.hash_value, + ) + + @classmethod + def from_internal_invoke(cls, internal_tx: InternalInvokeFunction) -> "L1HandlerSpecificInfo": + assert ( + internal_tx.entry_point_type is EntryPointType.L1_HANDLER + ), "This method only accepts InternalInvokeFunction objects that represent L1 Handlers" + return cls( + contract_address=internal_tx.contract_address, + entry_point_selector=internal_tx.entry_point_selector, + nonce=internal_tx.nonce if internal_tx.nonce is not None else 0, + calldata=internal_tx.calldata, + version=constants.L1_HANDLER_VERSION, + transaction_hash=internal_tx.hash_value, + ) + + class TransactionSpecificInfoSchema(OneOfSchema): type_schemas: Dict[str, Type[marshmallow.Schema]] = { TransactionType.DECLARE.name: DeclareSpecificInfo.Schema, TransactionType.DEPLOY.name: DeploySpecificInfo.Schema, TransactionType.INVOKE_FUNCTION.name: InvokeSpecificInfo.Schema, + TransactionType.L1_HANDLER.name: L1HandlerSpecificInfo.Schema, } def get_obj_type(self, obj: TransactionSpecificInfo) -> str: @@ -408,7 +454,7 @@ class TransactionExecution(ValidatedResponseObject): events: List[Event] # The resources needed by the transaction. execution_resources: Optional[ExecutionResources] - # The actual fee that was charged. + # The actual fee that was charged in Wei. actual_fee: Optional[int] = field(metadata=fields.optional_fee_metadata) @@ -482,7 +528,7 @@ class DeployedContract(ValidatedResponseObject): address: int = field(metadata=fields.L2AddressField.metadata(field_name="address")) class_hash: int = field(metadata=fields.ClassHashIntField.metadata()) - @pre_load + @marshmallow.decorators.pre_load def replace_contract_hash_with_class_hash( self, data: Dict[str, Any], many: bool, **kwargs ) -> Dict[str, Any]: @@ -508,17 +554,15 @@ class StateDiff(ValidatedResponseObject): """ storage_diffs: Dict[int, List[StorageEntry]] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=mfields.Dict( - keys=fields.L2AddressField.get_marshmallow_field( - required=True, - load_default=marshmallow.utils.missing, - ), + keys=fields.L2AddressField.get_marshmallow_field(), values=mfields.List(mfields.Nested(StorageEntry.Schema)), ) ) ) + nonces: Dict[int, int] = field(metadata=fields.address_to_nonce_metadata) deployed_contracts: List[DeployedContract] declared_contracts: Tuple[int, ...] = field(metadata=fields.declared_contracts_metadata) @@ -596,7 +640,7 @@ class FunctionInvocation(BaseResponseObject, SerializableMarshmallowDataclass): result: List[int] = field(metadata=fields.retdata_as_hex_metadata) execution_resources: ExecutionResources internal_calls: List["FunctionInvocation"] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=mfields.List(mfields.Nested(lambda: FunctionInvocation.Schema())) ) ) @@ -604,7 +648,7 @@ class FunctionInvocation(BaseResponseObject, SerializableMarshmallowDataclass): messages: List[OrderedL2ToL1MessageResponse] @classmethod - def from_internal_version(cls, call_info: CallInfo) -> "FunctionInvocation": + def from_internal(cls, call_info: CallInfo) -> "FunctionInvocation": return cls( caller_address=call_info.caller_address, call_type=call_info.call_type, @@ -616,7 +660,7 @@ def from_internal_version(cls, call_info: CallInfo) -> "FunctionInvocation": result=call_info.retdata, execution_resources=call_info.execution_resources, internal_calls=[ - cls.from_internal_version(call_info=internal_call) + cls.from_internal(call_info=internal_call) for internal_call in call_info.internal_calls ], events=OrderedEventResponse.from_internal(events=call_info.events), @@ -625,6 +669,12 @@ def from_internal_version(cls, call_info: CallInfo) -> "FunctionInvocation": ), ) + @classmethod + def from_optional_internal( + cls, call_info: Optional[CallInfo] + ) -> Optional["FunctionInvocation"]: + return None if call_info is None else cls.from_internal(call_info=call_info) + @marshmallow_dataclass.dataclass(frozen=True) class TransactionTrace(ValidatedResponseObject): @@ -633,8 +683,10 @@ class TransactionTrace(ValidatedResponseObject): including internal calls. """ - # An object describing the invocation of a specific function. - function_invocation: FunctionInvocation + # Objects describe invocation of validation, fee transfer, and a specific function. + validate_invocation: Optional[FunctionInvocation] + function_invocation: Optional[FunctionInvocation] + fee_transfer_invocation: Optional[FunctionInvocation] signature: List[int] = field(metadata=fields.signature_as_hex_metadata) @@ -654,7 +706,7 @@ class BlockTransactionTraces(ValidatedResponseObject): """ traces: Tuple[BlockSingleTransactionTrace, ...] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=VariadicLengthTupleField( mfields.Nested(BlockSingleTransactionTrace.Schema) ) @@ -675,7 +727,7 @@ class StarknetBlock(ValidatedResponseObject): status: Optional[BlockStatus] gas_price: int = field(metadata=fields.gas_price_metadata) transactions: Tuple[TransactionSpecificInfo, ...] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=VariadicLengthTupleField( mfields.Nested(TransactionSpecificInfo.Schema) ) @@ -684,7 +736,7 @@ class StarknetBlock(ValidatedResponseObject): timestamp: int = field(metadata=fields.timestamp_metadata) sequencer_address: Optional[int] = field(metadata=fields.optional_sequencer_address_metadata) transaction_receipts: Optional[Tuple[TransactionExecution, ...]] = field( - metadata=dict( + metadata=additional_metadata( marshmallow_field=VariadicLengthTupleField( mfields.Nested(TransactionExecution.Schema), allow_none=True ) @@ -743,3 +795,25 @@ def __post_init__(self): assert all( field is not None for field in created_block_fields ), "Block hash, block number, state_root must appear in a created block." + + +@marshmallow_dataclass.dataclass(frozen=True) +class FeeEstimationInfo(ValidatedResponseObject): + """ + Represents the fee estimation information. + """ + + overall_fee: int + gas_price: int + gas_usage: int + unit: str = "wei" + + +@marshmallow_dataclass.dataclass(frozen=True) +class TransactionSimulationInfo(ValidatedResponseObject): + """ + Represents the information regarding a StarkNet transaction's simulation. + """ + + trace: TransactionTrace + fee_estimation: FeeEstimationInfo diff --git a/src/starkware/starknet/services/api/gateway/CMakeLists.txt b/src/starkware/starknet/services/api/gateway/CMakeLists.txt index 2d784c9b..87ef0bd7 100644 --- a/src/starkware/starknet/services/api/gateway/CMakeLists.txt +++ b/src/starkware/starknet/services/api/gateway/CMakeLists.txt @@ -6,6 +6,7 @@ python_lib(starknet_transaction_lib LIBS everest_transaction_lib + starknet_abi_lib starknet_contract_address_lib starknet_contract_class_lib starknet_definitions_lib diff --git a/src/starkware/starknet/services/api/gateway/transaction.py b/src/starkware/starknet/services/api/gateway/transaction.py index 3e763bb9..de0be724 100644 --- a/src/starkware/starknet/services/api/gateway/transaction.py +++ b/src/starkware/starknet/services/api/gateway/transaction.py @@ -1,6 +1,7 @@ +import dataclasses from abc import abstractmethod from dataclasses import field -from typing import Any, ClassVar, Dict, List, Type +from typing import Any, ClassVar, Dict, List, Optional, Type import marshmallow import marshmallow.decorators @@ -15,7 +16,7 @@ calculate_deploy_transaction_hash, calculate_transaction_hash_common, ) -from starkware.starknet.definitions import fields +from starkware.starknet.definitions import constants, fields from starkware.starknet.definitions.general_config import StarknetGeneralConfig from starkware.starknet.definitions.transaction_type import TransactionType from starkware.starknet.services.api.contract_class import ContractClass @@ -25,18 +26,19 @@ decompress_program, ) -DECLARE_SENDER_ADDRESS = 1 +# The sender address used by default in declare transactions of version 0. +DEFAULT_DECLARE_SENDER_ADDRESS = 1 # Mypy has a problem with dataclasses that contain unimplemented abstract methods. # See https://github.com/python/mypy/issues/5374 for details on this problem. -@marshmallow_dataclass.dataclass(frozen=True) # type: ignore[misc] +@dataclasses.dataclass(frozen=True) # type: ignore[misc] class Transaction(EverestTransaction): """ StarkNet transaction base class. """ - # The version of the transaction. It is fixed (currently, 0) in the OS, and should be + # The version of the transaction. It is fixed (currently, 1) in the OS, and should be # signed by the account contract. # This field allows invalidating old transactions, whenever the meaning of the other # transaction fields is changed (in the OS). @@ -59,8 +61,29 @@ def calculate_hash(self, general_config: StarknetGeneralConfig) -> int: """ +# Mypy has a problem with dataclasses that contain unimplemented abstract methods. +# See https://github.com/python/mypy/issues/5374 for details on this problem. +@dataclasses.dataclass(frozen=True) # type: ignore[misc] +class AccountTransaction(Transaction): + """ + Represents a transaction in the StarkNet network that is originated from an action of an + account. + """ + + # The maximal fee to be paid in Wei for executing the transaction. + max_fee: int = field(metadata=fields.fee_metadata) + # The signature of the transaction. + # The exact way this field is handled is defined by the called contract's function, + # similar to calldata. + signature: List[int] = field(metadata=fields.signature_metadata) + # The nonce of the transaction. + # A sequential number attached to the account contract, that prevents transaction replay + # and guarantees the order of execution and uniqueness of the transaction hash. + nonce: Optional[int] = field(metadata=fields.optional_nonce_metadata) + + @marshmallow_dataclass.dataclass(frozen=True) -class Declare(Transaction): +class Declare(AccountTransaction): """ Represents a transaction in the StarkNet network that is a declaration of a StarkNet contract class. @@ -69,11 +92,6 @@ class Declare(Transaction): contract_class: ContractClass # The address of the account contract sending the declaration transaction. sender_address: int = field(metadata=fields.contract_address_metadata) - # The maximal fee to be paid in Wei for declaring a contract class. - max_fee: int = field(metadata=fields.fee_metadata) - # Additional information given by the caller that represents the signature of the transaction. - signature: List[int] = field(metadata=fields.signature_metadata) - # A sequential integer used to distinguish between transactions and order them. nonce: int = field(metadata=fields.nonce_metadata) # Class variables. @@ -103,6 +121,7 @@ def calculate_hash(self, general_config: StarknetGeneralConfig) -> int: sender_address=self.sender_address, max_fee=self.max_fee, version=self.version, + nonce=self.nonce, ) @@ -152,42 +171,91 @@ def calculate_hash(self, general_config: StarknetGeneralConfig) -> int: @marshmallow_dataclass.dataclass(frozen=True) -class InvokeFunction(Transaction): +class InvokeFunction(AccountTransaction): """ Represents a transaction in the StarkNet network that is an invocation of a Cairo contract function. """ contract_address: int = field(metadata=fields.contract_address_metadata) - # A field element that encodes the signature of the invoked function. - entry_point_selector: int = field(metadata=fields.entry_point_selector_metadata) calldata: List[int] = field(metadata=fields.call_data_metadata) - # The maximal fee to be paid in Wei for executing invoked function. - max_fee: int = field(metadata=fields.fee_metadata) - # Additional information given by the caller that represents the signature of the transaction. - # The exact way this field is handled is defined by the called contract's function, like - # calldata. - signature: List[int] = field(metadata=fields.signature_metadata) # Class variables. tx_type: ClassVar[TransactionType] = TransactionType.INVOKE_FUNCTION + # A field element that encodes the signature of the invoked function. + # The entry_point_selector is deprecated for version 1 and above (transactions + # should go through the '__execute__' entry point). + entry_point_selector: Optional[int] = field( + default=None, metadata=fields.optional_entry_point_selector_metadata + ) + + @marshmallow.decorators.post_dump + def remove_entry_point_selector( + self, data: Dict[str, Any], many: bool, **kwargs + ) -> Dict[str, Any]: + version = fields.TransactionVersionField.load_value(data["version"]) + if version in (0, constants.QUERY_VERSION_BASE): + return data + + assert ( + data["entry_point_selector"] is None + ), f"entry_point_selector should be None in version {version}." + del data["entry_point_selector"] + + return data + def calculate_hash(self, general_config: StarknetGeneralConfig) -> int: """ Calculates the transaction hash in the StarkNet network. """ + if self.version in [0, constants.QUERY_VERSION_BASE]: + assert ( + self.nonce is None + ), f"nonce is not None ({self.nonce}) for version={self.version}." + additional_data = [] + assert ( + self.entry_point_selector is not None + ), f"entry_point_selector is None for version={self.version}." + entry_point_selector_field = self.entry_point_selector + else: + assert self.nonce is not None, f"nonce is None for version={self.version}." + additional_data = [self.nonce] + assert ( + self.entry_point_selector is None + ), f"entry_point_selector is deprecated in version={self.version}." + entry_point_selector_field = 0 + return calculate_transaction_hash_common( tx_hash_prefix=TransactionHashPrefix.INVOKE, version=self.version, contract_address=self.contract_address, - entry_point_selector=self.entry_point_selector, + entry_point_selector=entry_point_selector_field, calldata=self.calldata, max_fee=self.max_fee, chain_id=general_config.chain_id.value, - additional_data=[], + additional_data=additional_data, ) +class AccountTransactionSchema(OneOfSchema): + """ + Schema for account transaction. + OneOfSchema adds a "type" field. + """ + + type_schemas: Dict[str, Type[marshmallow.Schema]] = { + TransactionType.DECLARE.name: Declare.Schema, + TransactionType.INVOKE_FUNCTION.name: InvokeFunction.Schema, + } + + def get_obj_type(self, obj: AccountTransaction) -> str: + return obj.tx_type.name + + +AccountTransaction.Schema = AccountTransactionSchema + + class TransactionSchema(OneOfSchema): """ Schema for transaction. @@ -199,9 +267,8 @@ class TransactionSchema(OneOfSchema): """ type_schemas: Dict[str, Type[marshmallow.Schema]] = { - TransactionType.DECLARE.name: Declare.Schema, + **AccountTransactionSchema.type_schemas, TransactionType.DEPLOY.name: Deploy.Schema, - TransactionType.INVOKE_FUNCTION.name: InvokeFunction.Schema, } def get_obj_type(self, obj: Transaction) -> str: diff --git a/src/starkware/starknet/services/api/messages.py b/src/starkware/starknet/services/api/messages.py index a3b1f40a..fa39ee28 100644 --- a/src/starkware/starknet/services/api/messages.py +++ b/src/starkware/starknet/services/api/messages.py @@ -5,9 +5,8 @@ from services.everest.definitions import fields as everest_fields from starkware.cairo.bootloaders.compute_fact import keccak_ints -from starkware.starknet.business_logic.internal_transaction import InternalInvokeFunction +from starkware.starknet.business_logic.transaction.objects import InternalL1Handler from starkware.starknet.definitions import fields -from starkware.starknet.services.api.contract_class import EntryPointType from starkware.starkware_utils.validated_dataclass import ValidatedDataclass @@ -70,13 +69,7 @@ def get_hash(self) -> str: return keccak_ints(values=self.encode()) @staticmethod - def get_message_hash_from_tx(tx: InternalInvokeFunction) -> str: - assert ( - tx.entry_point_type is EntryPointType.L1_HANDLER - ), f"Transaction must be of type L1_HANDLER. Got: {tx.entry_point_type.name}." - - assert tx.nonce is not None, "L1 handlers must include a nonce." - + def get_message_hash_from_tx(tx: InternalL1Handler) -> str: return StarknetMessageToL2( from_address=tx.calldata[0], to_address=tx.contract_address, diff --git a/src/starkware/starknet/services/utils/CMakeLists.txt b/src/starkware/starknet/services/utils/CMakeLists.txt new file mode 100644 index 00000000..91990c64 --- /dev/null +++ b/src/starkware/starknet/services/utils/CMakeLists.txt @@ -0,0 +1,19 @@ +python_lib(starknet_sequencer_api_utils_lib + PREFIX starkware/starknet/services/utils + + FILES + sequencer_api_utils.py + + LIBS + everest_transaction_lib + starknet_business_logic_fact_state_lib + starknet_business_logic_state_lib + starknet_business_logic_utils_lib + starknet_feeder_gateway_response_objects_lib + starknet_general_config_lib + starknet_transaction_execution_objects_lib + starknet_transaction_fee_lib + starknet_transaction_lib + starknet_transaction_objects_lib + starkware_config_utils_lib +) diff --git a/src/starkware/starknet/services/utils/sequencer_api_utils.py b/src/starkware/starknet/services/utils/sequencer_api_utils.py new file mode 100644 index 00000000..546ebaba --- /dev/null +++ b/src/starkware/starknet/services/utils/sequencer_api_utils.py @@ -0,0 +1,85 @@ +from typing import Optional, Tuple, Type + +from services.everest.api.gateway.transaction import EverestTransaction +from starkware.starknet.business_logic.execution.objects import CallInfo, ResourcesMapping +from starkware.starknet.business_logic.state.state_api import SyncState +from starkware.starknet.business_logic.transaction.fee import calculate_tx_fee +from starkware.starknet.business_logic.transaction.objects import ( + InternalAccountTransaction, + InternalDeclare, + InternalInvokeFunction, + InternalTransaction, +) +from starkware.starknet.business_logic.utils import verify_version +from starkware.starknet.definitions.general_config import StarknetGeneralConfig +from starkware.starknet.services.api.feeder_gateway.response_objects import FeeEstimationInfo +from starkware.starknet.services.api.gateway.transaction import ( + AccountTransaction, + Declare, + InvokeFunction, +) +from starkware.starkware_utils.config_base import Config + + +def format_fee_info(gas_price: int, overall_fee: int) -> FeeEstimationInfo: + return FeeEstimationInfo( + overall_fee=overall_fee, gas_price=gas_price, gas_usage=overall_fee // gas_price + ) + + +class InternalAccountTransactionForSimulate(InternalAccountTransaction): + """ + Represents an internal transaction in the StarkNet network for the simulate transaction API. + """ + + @classmethod + def from_external( + cls, external_tx: EverestTransaction, general_config: Config + ) -> InternalTransaction: + """ + Returns an internal transaction for simulation, generated based on an external one. + """ + # Downcast arguments to application-specific types. + assert isinstance(external_tx, AccountTransaction) + assert isinstance(general_config, StarknetGeneralConfig) + + internal_cls: Type[InternalAccountTransactionForSimulate] + if isinstance(external_tx, InvokeFunction): + internal_cls = InternalInvokeFunctionForSimulate + elif isinstance(external_tx, Declare): + internal_cls = InternalDeclareForSimulate + else: + raise NotImplementedError(f"Unexpected type {type(external_tx).__name__}.") + + return internal_cls._specific_from_external( + external_tx=external_tx, general_config=general_config + ) + + def verify_version(self): + verify_version(version=self.version, only_query=True) + + def charge_fee( + self, state: SyncState, resources: ResourcesMapping, general_config: StarknetGeneralConfig + ) -> Tuple[Optional[CallInfo], int]: + """ + Overrides the charge fee method. Only calculates the actual fee and does not charge any fee. + """ + actual_fee = calculate_tx_fee( + gas_price=state.block_info.gas_price, resources=resources, general_config=general_config + ) + + return None, actual_fee + + +class InternalInvokeFunctionForSimulate( + InternalAccountTransactionForSimulate, InternalInvokeFunction +): + """ + Represents an internal invoke function in the StarkNet network for the simulate transaction API. + """ + + +class InternalDeclareForSimulate(InternalAccountTransactionForSimulate, InternalDeclare): + """ + Represents an internal declare in the StarkNet network for the simulate transaction API. + """ diff --git a/src/starkware/starknet/solidity/CMakeLists.txt b/src/starkware/starknet/solidity/CMakeLists.txt index 4cb61dd6..6fd2818b 100644 --- a/src/starkware/starknet/solidity/CMakeLists.txt +++ b/src/starkware/starknet/solidity/CMakeLists.txt @@ -1,10 +1,27 @@ -python_lib(starknet_messaging_sol +include(solidity.cmake) + +python_lib(starknet_core_sol PREFIX starkware/starknet/solidity FILES - IStarknetMessaging.sol - IStarknetMessagingEvents.sol - StarknetMessaging.sol + Output.sol + Starknet.sol + StarknetOperator.sol + StarknetState.sol LIBS + governance_contract_sol named_storage_sol + solidity_contract_initializer_sol + solidity_contracts_interfaces_sol + solidity_contracts_components_sol + starknet_governance_sol + starknet_messaging_sol +) + +solidity_env(starknet_core_contract + CONTRACTS + Starknet + + LIBS + starknet_core_sol ) diff --git a/src/starkware/starknet/solidity/IStarknetMessaging.sol b/src/starkware/starknet/solidity/IStarknetMessaging.sol index 883e586a..5388ac66 100644 --- a/src/starkware/starknet/solidity/IStarknetMessaging.sol +++ b/src/starkware/starknet/solidity/IStarknetMessaging.sol @@ -6,14 +6,15 @@ import "./IStarknetMessagingEvents.sol"; interface IStarknetMessaging is IStarknetMessagingEvents { /** Sends a message to an L2 contract. + This function is payable, the payed amount is the message fee. - Returns the hash of the message. + Returns the hash of the message and the nonce of the message. */ function sendMessageToL2( uint256 toAddress, uint256 selector, uint256[] calldata payload - ) external returns (bytes32, uint256); + ) external payable returns (bytes32, uint256); /** Consumes a message that was sent from an L2 contract. @@ -41,6 +42,8 @@ interface IStarknetMessaging is IStarknetMessagingEvents { /** Cancels an L1 to L2 message, this function should be called messageCancellationDelay() seconds after the call to startL1ToL2MessageCancellation(). + + Note that the message fee is not refunded. */ function cancelL1ToL2Message( uint256 toAddress, diff --git a/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol b/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol index 2648460c..9e7c841e 100644 --- a/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol +++ b/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol @@ -11,7 +11,8 @@ interface IStarknetMessagingEvents { uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, - uint256 nonce + uint256 nonce, + uint256 fee ); // An event that is raised when a message from L2 to L1 is consumed. diff --git a/src/starkware/starknet/solidity/Output.sol b/src/starkware/starknet/solidity/Output.sol new file mode 100644 index 00000000..d51a9138 --- /dev/null +++ b/src/starkware/starknet/solidity/Output.sol @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +library CommitmentTreeUpdateOutput { + /** + Returns the previous commitment tree root. + */ + function getPrevRoot(uint256[] calldata commitmentTreeUpdateData) + internal + pure + returns (uint256) + { + return commitmentTreeUpdateData[0]; + } + + /** + Returns the new commitment tree root. + */ + function getNewRoot(uint256[] calldata commitmentTreeUpdateData) + internal + pure + returns (uint256) + { + return commitmentTreeUpdateData[1]; + } +} + +library StarknetOutput { + uint256 internal constant MERKLE_UPDATE_OFFSET = 0; + uint256 internal constant BLOCK_NUMBER_OFFSET = 2; + uint256 internal constant CONFIG_HASH_OFFSET = 3; + uint256 internal constant HEADER_SIZE = 4; + + uint256 constant MESSAGE_TO_L1_FROM_ADDRESS_OFFSET = 0; + uint256 constant MESSAGE_TO_L1_TO_ADDRESS_OFFSET = 1; + uint256 constant MESSAGE_TO_L1_PAYLOAD_SIZE_OFFSET = 2; + uint256 constant MESSAGE_TO_L1_PREFIX_SIZE = 3; + + uint256 constant MESSAGE_TO_L2_FROM_ADDRESS_OFFSET = 0; + uint256 constant MESSAGE_TO_L2_TO_ADDRESS_OFFSET = 1; + uint256 constant MESSAGE_TO_L2_NONCE_OFFSET = 2; + uint256 constant MESSAGE_TO_L2_SELECTOR_OFFSET = 3; + uint256 constant MESSAGE_TO_L2_PAYLOAD_SIZE_OFFSET = 4; + uint256 constant MESSAGE_TO_L2_PREFIX_SIZE = 5; + + // An event that is raised when a message is sent from L2 to L1. + event LogMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload); + + // An event that is raised when a message from L1 to L2 is consumed. + event ConsumedMessageToL2( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce + ); + + /** + Does a sanity check of the output_data length. + */ + function validate(uint256[] calldata output_data) internal pure { + require(output_data.length > HEADER_SIZE, "STARKNET_OUTPUT_TOO_SHORT"); + } + + /** + Returns a slice of the 'output_data' with the commitment tree update information. + */ + function getMerkleUpdate(uint256[] calldata output_data) + internal + pure + returns (uint256[] calldata) + { + return output_data[MERKLE_UPDATE_OFFSET:MERKLE_UPDATE_OFFSET + 2]; + } + + /** + Processes a message segment from the program output. + The format of a message segment is the length of the messages in words followed + by the concatenation of all the messages. + + The 'messages' mapping is updated according to the messages and the direction ('isL2ToL1'). + */ + function processMessages( + bool isL2ToL1, + uint256[] calldata programOutputSlice, + mapping(bytes32 => uint256) storage messages + ) internal returns (uint256) { + uint256 messageSegmentSize = programOutputSlice[0]; + require(messageSegmentSize < 2**30, "INVALID_MESSAGE_SEGMENT_SIZE"); + + uint256 offset = 1; + uint256 messageSegmentEnd = offset + messageSegmentSize; + + uint256 payloadSizeOffset = ( + isL2ToL1 ? MESSAGE_TO_L1_PAYLOAD_SIZE_OFFSET : MESSAGE_TO_L2_PAYLOAD_SIZE_OFFSET + ); + + uint256 totalMsgFees = 0; + while (offset < messageSegmentEnd) { + uint256 payloadLengthOffset = offset + payloadSizeOffset; + require(payloadLengthOffset < programOutputSlice.length, "MESSAGE_TOO_SHORT"); + + uint256 payloadLength = programOutputSlice[payloadLengthOffset]; + require(payloadLength < 2**30, "INVALID_PAYLOAD_LENGTH"); + + uint256 endOffset = payloadLengthOffset + 1 + payloadLength; + require(endOffset <= programOutputSlice.length, "TRUNCATED_MESSAGE_PAYLOAD"); + + if (isL2ToL1) { + bytes32 messageHash = keccak256( + abi.encodePacked(programOutputSlice[offset:endOffset]) + ); + + emit LogMessageToL1( + // from= + programOutputSlice[offset + MESSAGE_TO_L1_FROM_ADDRESS_OFFSET], + // to= + address(programOutputSlice[offset + MESSAGE_TO_L1_TO_ADDRESS_OFFSET]), + // payload= + (uint256[])(programOutputSlice[offset + MESSAGE_TO_L1_PREFIX_SIZE:endOffset]) + ); + messages[messageHash] += 1; + } else { + { + bytes32 messageHash = keccak256( + abi.encodePacked(programOutputSlice[offset:endOffset]) + ); + + uint256 msgFeePlusOne = messages[messageHash]; + require(msgFeePlusOne > 0, "INVALID_MESSAGE_TO_CONSUME"); + totalMsgFees += msgFeePlusOne - 1; + messages[messageHash] = 0; + } + + uint256 nonce = programOutputSlice[offset + MESSAGE_TO_L2_NONCE_OFFSET]; + uint256[] memory messageSlice = (uint256[])( + programOutputSlice[offset + MESSAGE_TO_L2_PREFIX_SIZE:endOffset] + ); + emit ConsumedMessageToL2( + // from= + address(programOutputSlice[offset + MESSAGE_TO_L2_FROM_ADDRESS_OFFSET]), + // to= + programOutputSlice[offset + MESSAGE_TO_L2_TO_ADDRESS_OFFSET], + // selector= + programOutputSlice[offset + MESSAGE_TO_L2_SELECTOR_OFFSET], + // payload= + messageSlice, + // nonce = + nonce + ); + } + + offset = endOffset; + } + require(offset == messageSegmentEnd, "INVALID_MESSAGE_SEGMENT_SIZE"); + + if (totalMsgFees > 0) { + // NOLINTNEXTLINE: low-level-calls. + (bool success, ) = msg.sender.call{value: totalMsgFees}(""); + require(success, "ETH_TRANSFER_FAILED"); + } + + return offset; + } +} diff --git a/src/starkware/starknet/solidity/Starknet.sol b/src/starkware/starknet/solidity/Starknet.sol new file mode 100644 index 00000000..15641dee --- /dev/null +++ b/src/starkware/starknet/solidity/Starknet.sol @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; +pragma experimental ABIEncoderV2; + +import "./Output.sol"; +import "./StarknetGovernance.sol"; +import "./StarknetMessaging.sol"; +import "./StarknetOperator.sol"; +import "./StarknetState.sol"; +import "starkware/solidity/components/GovernedFinalizable.sol"; +import "starkware/solidity/components/OnchainDataFactTreeEncoder.sol"; +import "starkware/solidity/interfaces/ContractInitializer.sol"; +import "starkware/solidity/interfaces/Identity.sol"; +import "starkware/solidity/interfaces/IFactRegistry.sol"; +import "starkware/solidity/interfaces/ProxySupport.sol"; +import "starkware/solidity/libraries/NamedStorage.sol"; + +contract Starknet is + Identity, + StarknetMessaging, + StarknetGovernance, + GovernedFinalizable, + StarknetOperator, + ContractInitializer, + ProxySupport +{ + using StarknetState for StarknetState.State; + + // Logs the new state following a state update. + event LogStateUpdate(uint256 globalRoot, int256 blockNumber); + + // Logs a stateTransitionFact that was used to update the state. + event LogStateTransitionFact(bytes32 stateTransitionFact); + + // Random storage slot tags. + string internal constant PROGRAM_HASH_TAG = "STARKNET_1.0_INIT_PROGRAM_HASH_UINT"; + string internal constant VERIFIER_ADDRESS_TAG = "STARKNET_1.0_INIT_VERIFIER_ADDRESS"; + string internal constant STATE_STRUCT_TAG = "STARKNET_1.0_INIT_STARKNET_STATE_STRUCT"; + + // The hash of the StarkNet config. + string internal constant CONFIG_HASH_TAG = "STARKNET_1.0_STARKNET_CONFIG_HASH"; + + function setProgramHash(uint256 newProgramHash) external notFinalized onlyGovernance { + programHash(newProgramHash); + } + + function setConfigHash(uint256 newConfigHash) external notFinalized onlyGovernance { + configHash(newConfigHash); + } + + function setMessageCancellationDelay(uint256 delayInSeconds) + external + notFinalized + onlyGovernance + { + messageCancellationDelay(delayInSeconds); + } + + // State variable "programHash" read-access function. + function programHash() public view returns (uint256) { + return NamedStorage.getUintValue(PROGRAM_HASH_TAG); + } + + // State variable "programHash" write-access function. + function programHash(uint256 value) internal { + NamedStorage.setUintValue(PROGRAM_HASH_TAG, value); + } + + // State variable "verifier" access function. + function verifier() internal view returns (address) { + return NamedStorage.getAddressValue(VERIFIER_ADDRESS_TAG); + } + + // State variable "configHash" write-access function. + function configHash(uint256 value) internal { + NamedStorage.setUintValue(CONFIG_HASH_TAG, value); + } + + // State variable "configHash" read-access function. + function configHash() public view returns (uint256) { + return NamedStorage.getUintValue(CONFIG_HASH_TAG); + } + + function setVerifierAddress(address value) internal { + NamedStorage.setAddressValueOnce(VERIFIER_ADDRESS_TAG, value); + } + + // State variable "state" access function. + function state() internal pure returns (StarknetState.State storage stateStruct) { + bytes32 location = keccak256(abi.encodePacked(STATE_STRUCT_TAG)); + assembly { + stateStruct_slot := location + } + } + + function isInitialized() internal view override returns (bool) { + return programHash() != 0; + } + + function numOfSubContracts() internal pure override returns (uint256) { + return 0; + } + + function validateInitData(bytes calldata data) internal view override { + require(data.length == 5 * 32, "ILLEGAL_INIT_DATA_SIZE"); + uint256 programHash_ = abi.decode(data[:32], (uint256)); + require(programHash_ != 0, "BAD_INITIALIZATION"); + } + + function processSubContractAddresses(bytes calldata subContractAddresses) internal override {} + + function initializeContractState(bytes calldata data) internal override { + ( + uint256 programHash_, + address verifier_, + uint256 configHash_, + StarknetState.State memory initialState + ) = abi.decode(data, (uint256, address, uint256, StarknetState.State)); + + programHash(programHash_); + setVerifierAddress(verifier_); + state().copy(initialState); + configHash(configHash_); + messageCancellationDelay(5 days); + } + + /** + Returns a string that identifies the contract. + */ + function identify() external pure override returns (string memory) { + return "StarkWare_Starknet_2022_4"; + } + + /** + Returns the current state root. + */ + function stateRoot() external view returns (uint256) { + return state().globalRoot; + } + + /** + Returns the current block number. + */ + function stateBlockNumber() external view returns (int256) { + return state().blockNumber; + } + + /** + Updates the state of the StarkNet, based on a proof of the + StarkNet OS that the state transition is valid. + + Arguments: + programOutput - The main part of the StarkNet OS program output. + data_availability_fact - An encoding of the on-chain data associated + with the 'programOutput'. + */ + function updateState( + uint256[] calldata programOutput, + uint256 onchainDataHash, + uint256 onchainDataSize + ) external onlyOperator { + // Validate program output. + StarknetOutput.validate(programOutput); + + // Validate config hash. + require( + configHash() == programOutput[StarknetOutput.CONFIG_HASH_OFFSET], + "INVALID_CONFIG_HASH" + ); + + bytes32 stateTransitionFact = OnchainDataFactTreeEncoder.encodeFactWithOnchainData( + programOutput, + OnchainDataFactTreeEncoder.DataAvailabilityFact(onchainDataHash, onchainDataSize) + ); + bytes32 sharpFact = keccak256(abi.encode(programHash(), stateTransitionFact)); + require(IFactRegistry(verifier()).isValid(sharpFact), "NO_STATE_TRANSITION_PROOF"); + emit LogStateTransitionFact(stateTransitionFact); + + // Process L2 -> L1 messages. + uint256 outputOffset = StarknetOutput.HEADER_SIZE; + outputOffset += StarknetOutput.processMessages( + // isL2ToL1= + true, + programOutput[outputOffset:], + l2ToL1Messages() + ); + + // Process L1 -> L2 messages. + outputOffset += StarknetOutput.processMessages( + // isL2ToL1= + false, + programOutput[outputOffset:], + l1ToL2Messages() + ); + + require(outputOffset == programOutput.length, "STARKNET_OUTPUT_TOO_LONG"); + + // Perform state update. + state().update(programOutput); + StarknetState.State storage state_ = state(); + emit LogStateUpdate(state_.globalRoot, state_.blockNumber); + } +} diff --git a/src/starkware/starknet/solidity/StarknetGovernance.sol b/src/starkware/starknet/solidity/StarknetGovernance.sol new file mode 100644 index 00000000..8d4749d9 --- /dev/null +++ b/src/starkware/starknet/solidity/StarknetGovernance.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "starkware/solidity/components/Governance.sol"; + +contract StarknetGovernance is Governance { + string constant STARKNET_GOVERNANCE_INFO_TAG = "STARKNET_1.0_GOVERNANCE_INFO"; + + /* + Returns the GovernanceInfoStruct associated with the governance tag. + */ + function getGovernanceInfo() internal view override returns (GovernanceInfoStruct storage gub) { + bytes32 location = keccak256(abi.encodePacked(STARKNET_GOVERNANCE_INFO_TAG)); + assembly { + gub_slot := location + } + } + + function starknetIsGovernor(address user) external view returns (bool) { + return _isGovernor(user); + } + + function starknetNominateNewGovernor(address newGovernor) external { + _nominateNewGovernor(newGovernor); + } + + function starknetRemoveGovernor(address governorForRemoval) external { + _removeGovernor(governorForRemoval); + } + + function starknetAcceptGovernance() external { + _acceptGovernance(); + } + + function starknetCancelNomination() external { + _cancelNomination(); + } +} diff --git a/src/starkware/starknet/solidity/StarknetMessaging.sol b/src/starkware/starknet/solidity/StarknetMessaging.sol index c02ed9b9..2d2b5e77 100644 --- a/src/starkware/starknet/solidity/StarknetMessaging.sol +++ b/src/starkware/starknet/solidity/StarknetMessaging.sol @@ -2,7 +2,7 @@ pragma solidity ^0.6.12; import "./IStarknetMessaging.sol"; -import "contracts/starkware/solidity/libraries/NamedStorage.sol"; +import "starkware/solidity/libraries/NamedStorage.sol"; /** Implements sending messages to L2 by adding them to a pipe and consuming messages from L2 by @@ -26,6 +26,12 @@ contract StarknetMessaging is IStarknetMessaging { "STARKNET_1.0_MSGING_L1TOL2_CANCELLATION_DELAY" ); + uint256 public constant MAX_L1_MSG_FEE = 1 ether; + + /** + Returns the msg_fee + 1 for the message with the given 'msgHash', + or 0 if no message with such a hash is pending. + */ function l1ToL2Messages(bytes32 msgHash) external view returns (uint256) { return l1ToL2Messages()[msgHash]; } @@ -101,12 +107,15 @@ contract StarknetMessaging is IStarknetMessaging { uint256 toAddress, uint256 selector, uint256[] calldata payload - ) external override returns (bytes32, uint256) { + ) external payable override returns (bytes32, uint256) { + require(msg.value <= MAX_L1_MSG_FEE, "MAX_L1_MSG_FEE_EXCEEDED"); uint256 nonce = l1ToL2MessageNonce(); NamedStorage.setUintValue(L1L2_MESSAGE_NONCE_TAG, nonce + 1); - emit LogMessageToL2(msg.sender, toAddress, selector, payload, nonce); + emit LogMessageToL2(msg.sender, toAddress, selector, payload, nonce, msg.value); bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); - l1ToL2Messages()[msgHash] += 1; + // Note that the inclusion of the unique nonce in the message hash implies that + // l1ToL2Messages()[msgHash] was not accessed before. + l1ToL2Messages()[msgHash] = msg.value + 1; return (msgHash, nonce); } @@ -138,8 +147,8 @@ contract StarknetMessaging is IStarknetMessaging { ) external override returns (bytes32) { emit MessageToL2CancellationStarted(msg.sender, toAddress, selector, payload, nonce); bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); - uint256 msgCount = l1ToL2Messages()[msgHash]; - require(msgCount > 0, "NO_MESSAGE_TO_CANCEL"); + uint256 msgFeePlusOne = l1ToL2Messages()[msgHash]; + require(msgFeePlusOne > 0, "NO_MESSAGE_TO_CANCEL"); l1ToL2MessageCancellations()[msgHash] = block.timestamp; return msgHash; } @@ -152,8 +161,8 @@ contract StarknetMessaging is IStarknetMessaging { ) external override returns (bytes32) { emit MessageToL2Canceled(msg.sender, toAddress, selector, payload, nonce); bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); - uint256 msgCount = l1ToL2Messages()[msgHash]; - require(msgCount > 0, "NO_MESSAGE_TO_CANCEL"); + uint256 msgFeePlusOne = l1ToL2Messages()[msgHash]; + require(msgFeePlusOne != 0, "NO_MESSAGE_TO_CANCEL"); uint256 requestTime = l1ToL2MessageCancellations()[msgHash]; require(requestTime != 0, "MESSAGE_CANCELLATION_NOT_REQUESTED"); @@ -162,7 +171,7 @@ contract StarknetMessaging is IStarknetMessaging { require(cancelAllowedTime >= requestTime, "CANCEL_ALLOWED_TIME_OVERFLOW"); require(block.timestamp >= cancelAllowedTime, "MESSAGE_CANCELLATION_NOT_ALLOWED_YET"); - l1ToL2Messages()[msgHash] = msgCount - 1; - return msgHash; + l1ToL2Messages()[msgHash] = 0; + return (msgHash); } } diff --git a/src/starkware/starknet/solidity/StarknetOperator.sol b/src/starkware/starknet/solidity/StarknetOperator.sol new file mode 100644 index 00000000..169ebba0 --- /dev/null +++ b/src/starkware/starknet/solidity/StarknetOperator.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "starkware/solidity/components/Operator.sol"; +import "starkware/solidity/libraries/NamedStorage.sol"; + +abstract contract StarknetOperator is Operator { + string constant OPERATORS_MAPPING_TAG = "STARKNET_1.0_ROLES_OPERATORS_MAPPING_TAG"; + + function getOperators() internal view override returns (mapping(address => bool) storage) { + return NamedStorage.addressToBoolMapping(OPERATORS_MAPPING_TAG); + } +} diff --git a/src/starkware/starknet/solidity/StarknetState.sol b/src/starkware/starknet/solidity/StarknetState.sol new file mode 100644 index 00000000..3fd648ef --- /dev/null +++ b/src/starkware/starknet/solidity/StarknetState.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "./Output.sol"; + +library StarknetState { + struct State { + uint256 globalRoot; + int256 blockNumber; + } + + function copy(State storage state, State memory stateFrom) internal { + state.globalRoot = stateFrom.globalRoot; + state.blockNumber = stateFrom.blockNumber; + } + + /** + Validates that the 'blockNumber' and the previous root are consistent with the + current state and updates the state. + */ + function update(State storage state, uint256[] calldata starknetOutput) internal { + // Check the blockNumber first as the error is less ambiguous then INVALID_PREVIOUS_ROOT. + state.blockNumber += 1; + require( + uint256(state.blockNumber) == starknetOutput[StarknetOutput.BLOCK_NUMBER_OFFSET], + "INVALID_BLOCK_NUMBER" + ); + + uint256[] calldata commitment_tree_update = StarknetOutput.getMerkleUpdate(starknetOutput); + require( + state.globalRoot == CommitmentTreeUpdateOutput.getPrevRoot(commitment_tree_update), + "INVALID_PREVIOUS_ROOT" + ); + state.globalRoot = CommitmentTreeUpdateOutput.getNewRoot(commitment_tree_update); + } +} diff --git a/src/starkware/starknet/solidity/solidity.cmake b/src/starkware/starknet/solidity/solidity.cmake new file mode 100644 index 00000000..d2cc6508 --- /dev/null +++ b/src/starkware/starknet/solidity/solidity.cmake @@ -0,0 +1,19 @@ +python_lib(starknet_governance_sol + PREFIX starkware/starknet/solidity + FILES + StarknetGovernance.sol + + LIBS + governance_contract_sol +) + +python_lib(starknet_messaging_sol + PREFIX starkware/starknet/solidity + FILES + IStarknetMessaging.sol + IStarknetMessagingEvents.sol + StarknetMessaging.sol + + LIBS + named_storage_sol +) diff --git a/src/starkware/starknet/storage/starknet_storage.py b/src/starkware/starknet/storage/starknet_storage.py index c400d216..ae2fd16f 100644 --- a/src/starkware/starknet/storage/starknet_storage.py +++ b/src/starkware/starknet/storage/starknet_storage.py @@ -16,6 +16,7 @@ TStorageLeaf = TypeVar("TStorageLeaf", bound="StorageLeaf") +ContractStorageMapping = Dict[int, "StorageLeaf"] @dataclasses.dataclass(frozen=True) @@ -107,7 +108,7 @@ def __init__( self, commitment_tree: PatriciaTree, ffc: FactFetchingContext, - pending_modifications: Optional[Dict[int, StorageLeaf]] = None, + pending_modifications: Optional[ContractStorageMapping] = None, loop: Optional[asyncio.AbstractEventLoop] = None, ): """ @@ -197,7 +198,7 @@ def write(self, address: int, value: int): self.modifications[address] = value - def get_modifications(self) -> Dict[int, StorageLeaf]: + def get_modifications(self) -> ContractStorageMapping: """ Returns a dict of modifications that need to be applied to self.commitment_tree. """ @@ -290,7 +291,7 @@ def __init__( self, commitment_tree: PatriciaTree, ffc: FactFetchingContext, - pending_modifications: Optional[Dict[int, StorageLeaf]] = None, + pending_modifications: Optional[ContractStorageMapping] = None, loop: Optional[asyncio.AbstractEventLoop] = None, ): super().__init__( diff --git a/src/starkware/starknet/testing/CMakeLists.txt b/src/starkware/starknet/testing/CMakeLists.txt index a41ade53..ef5493f2 100644 --- a/src/starkware/starknet/testing/CMakeLists.txt +++ b/src/starkware/starknet/testing/CMakeLists.txt @@ -26,7 +26,7 @@ python_lib(starknet_mock_messaging_contracts_lib ARTIFACTS "${CMAKE_CURRENT_BINARY_DIR}/MockStarknetMessaging.json MockStarknetMessaging.json" ) -add_dependencies(starknet_mock_messaging_contracts_lib starknet_mock_messaging_sol) +add_dependencies(starknet_mock_messaging_contracts_lib mock_starknet_messaging_sol_env) python_lib(starknet_testing_lib PREFIX starkware/starknet/testing @@ -45,16 +45,19 @@ python_lib(starknet_testing_lib cairo_vm_lib starknet_abi_lib starknet_api_utils_lib + starknet_business_logic_fact_state_lib + starknet_business_logic_patricia_state_lib starknet_business_logic_state_lib starknet_compile_lib starknet_contract_class_lib starknet_definitions_lib + starknet_execute_entry_point_lib starknet_feeder_gateway_response_objects_lib starknet_general_config_lib - starknet_internal_transaction_interface_lib - starknet_internal_transaction_lib + starknet_transaction_objects_lib starknet_messages_lib starknet_mock_messaging_contracts_lib + starknet_os_abi_lib starknet_transaction_execution_objects_lib starknet_transaction_lib starkware_dataclasses_utils_lib diff --git a/src/starkware/starknet/testing/MockStarknetMessaging.sol b/src/starkware/starknet/testing/MockStarknetMessaging.sol index 06826e09..fa4b0baf 100644 --- a/src/starkware/starknet/testing/MockStarknetMessaging.sol +++ b/src/starkware/starknet/testing/MockStarknetMessaging.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0. pragma solidity ^0.6.12; -import "contracts/starkware/starknet/solidity/StarknetMessaging.sol"; +import "starkware/starknet/solidity/StarknetMessaging.sol"; contract MockStarknetMessaging is StarknetMessaging { constructor(uint256 MessageCancellationDelay) public { diff --git a/src/starkware/starknet/testing/contract.py b/src/starkware/starknet/testing/contract.py index 402b4816..dd2cd1fa 100644 --- a/src/starkware/starknet/testing/contract.py +++ b/src/starkware/starknet/testing/contract.py @@ -25,7 +25,7 @@ flatten, parse_arguments, ) -from starkware.starknet.testing.objects import Dataclass, StarknetTransactionExecutionInfo +from starkware.starknet.testing.objects import Dataclass, StarknetCallInfo from starkware.starknet.testing.state import CastableToAddress, StarknetState from starkware.starknet.utils.api_utils import cast_to_felts @@ -44,7 +44,7 @@ class StarknetContract: contract = StarknetContract( state=state, abi=contract_class.abi, contract_address=contract_address) - await contract.foo(a=1, b=[2, 3]).invoke() + await contract.foo(a=1, b=[2, 3]).execute() """ def __init__( @@ -52,11 +52,11 @@ def __init__( state: StarknetState, abi: AbiType, contract_address: CastableToAddress, - deploy_execution_info: StarknetTransactionExecutionInfo, + deploy_call_info: StarknetCallInfo, ): self.state = state self.abi = abi - self.deploy_execution_info = deploy_execution_info + self.deploy_call_info = deploy_call_info self.struct_manager = StructManager(abi=abi) self.event_manager = EventManager(abi=abi) @@ -246,7 +246,7 @@ def replace_abi( state=self.state, abi=impl_contract_abi, contract_address=self.contract_address, - deploy_execution_info=self.deploy_execution_info, + deploy_call_info=self.deploy_call_info, ) @@ -270,59 +270,57 @@ class StarknetContractFunctionInvocation: retdata_tuple: type has_raw_output: bool - async def call( - self, caller_address: int = 0, signature: List[int] = None - ) -> StarknetTransactionExecutionInfo: + async def call(self, caller_address: int = 0) -> StarknetCallInfo: """ Executes the function call without changing the state. """ - return await self._invoke_on_given_state( - state=self.state.copy(), caller_address=caller_address, signature=signature + return await self._execute_on_given_state( + state=self.state.copy(), caller_address=caller_address ) async def invoke( self, caller_address: int = 0, max_fee: int = 0, signature: List[int] = None - ) -> StarknetTransactionExecutionInfo: + ) -> StarknetCallInfo: + raise NotImplementedError( + "Invoking through an account contract is not supported yet, please use " + "execute() instead." + ) + + async def execute(self, caller_address: int = 0) -> StarknetCallInfo: """ Executes the function call and apply changes on the state. """ - return await self._invoke_on_given_state( - state=self.state, caller_address=caller_address, max_fee=max_fee, signature=signature - ) + return await self._execute_on_given_state(state=self.state, caller_address=caller_address) - async def _invoke_on_given_state( + async def _execute_on_given_state( self, state: StarknetState, caller_address: int = 0, - max_fee: int = 0, - signature: List[int] = None, - ) -> StarknetTransactionExecutionInfo: + ) -> StarknetCallInfo: """ Executes the function call and apply changes on the given state. """ - execution_info = await state.invoke_raw( + call_info = await state.execute_entry_point_raw( contract_address=self.contract_address, selector=self.name, calldata=self.calldata, caller_address=caller_address, - max_fee=max_fee, - signature=None if signature is None else cast_to_felts(values=signature), ) # Check if function has @raw_output. if self.has_raw_output: # Return the result as a raw tuple. - result = tuple(execution_info.call_info.retdata) + result = tuple(call_info.retdata) else: args = self._build_arguments( - arg_values=execution_info.call_info.retdata, + arg_values=call_info.retdata, arg_types=self.retdata_arg_types, ) result = self.retdata_tuple(*args) - main_call_raw_events = execution_info.call_info.events + main_call_raw_events = call_info.events - return StarknetTransactionExecutionInfo.from_internal( - tx_execution_info=execution_info, + return StarknetCallInfo.from_internal( + call_info=call_info, result=result, main_call_events=self._build_events(raw_events=main_call_raw_events), ) @@ -401,14 +399,14 @@ def build_arg( build_arg(arg_type=arg_type, arg_value_iterator=arg_value_iterator) for arg_type in arg_types ] - except StopIteration: - raise ArgumentParsingFailed("Too few argument values.") + except StopIteration as exception: + raise ArgumentParsingFailed("Too few argument values.") from exception # Make sure the iterator is empty. try: assert_exhausted(iterator=arg_value_iterator) - except AssertionError: - raise ArgumentParsingFailed("Too many argument values.") + except AssertionError as exception: + raise ArgumentParsingFailed("Too many argument values.") from exception return res diff --git a/src/starkware/starknet/testing/contract_test.py b/src/starkware/starknet/testing/contract_test.py index a3d9d68f..6a8df610 100644 --- a/src/starkware/starknet/testing/contract_test.py +++ b/src/starkware/starknet/testing/contract_test.py @@ -3,6 +3,7 @@ from typing import Tuple import pytest +import pytest_asyncio from starkware.starknet.business_logic.execution.objects import Event from starkware.starknet.core.test_contract.test_utils import get_contract_class @@ -17,12 +18,12 @@ # Fixtures. -@pytest.fixture +@pytest_asyncio.fixture async def starknet() -> Starknet: return await Starknet.empty() -@pytest.fixture +@pytest_asyncio.fixture async def test_contract(starknet: Starknet) -> StarknetContract: return await starknet.deploy( source=CONTRACT_FILE, @@ -30,12 +31,12 @@ async def test_contract(starknet: Starknet) -> StarknetContract: ) -@pytest.fixture +@pytest_asyncio.fixture async def test_class(starknet: Starknet) -> DeclaredClass: return await starknet.declare(source=CONTRACT_FILE) -@pytest.fixture +@pytest_asyncio.fixture async def proxy_contract(starknet: Starknet) -> StarknetContract: contract_class = get_contract_class("delegate_proxy") return await starknet.deploy( @@ -44,7 +45,7 @@ async def proxy_contract(starknet: Starknet) -> StarknetContract: ) -@pytest.fixture +@pytest_asyncio.fixture async def account_contract(starknet: Starknet) -> StarknetContract: contract_class = get_contract_class("dummy_account") return await starknet.deploy( @@ -58,32 +59,28 @@ async def account_contract(starknet: Starknet) -> StarknetContract: @pytest.mark.asyncio async def test_function_call(test_contract: StarknetContract): - await test_contract.increase_value(address=132, value=3).invoke() - await test_contract.increase_value(132, 5).invoke() + await test_contract.increase_value(address=132, value=3).execute() + await test_contract.increase_value(132, 5).execute() await test_contract.increase_value(132, 10).call() # Since the return type is a named tuple, the result can be checked in multiple ways. - execution_info = await test_contract.get_value(address=132).invoke() + execution_info = await test_contract.get_value(address=132).execute() assert execution_info.result == (8,) execution_info = await test_contract.get_value(address=132).call() assert execution_info.result.res == 8 # Access by the name of the return value, `res`. - execution_info = await test_contract.takes_array(a=[1, 2, 4]).invoke() + execution_info = await test_contract.takes_array(a=[1, 2, 4]).execute() assert execution_info.result[0] == 6 # Access by location. - # Pass signature values using invoke's signature argument. - execution_info = await test_contract.get_signature().invoke(signature=[1, 2, 4, 10]) - assert execution_info.result == ([1, 2, 4, 10],) - # Check structs. point_1 = test_contract.Point(x=1, y=2) point_2 = test_contract.Point(x=3, y=4) - execution_info = await test_contract.sum_points(points=(point_1, point_2)).invoke() + execution_info = await test_contract.sum_points(points=(point_1, point_2)).execute() assert execution_info.result == ((4, 6),) - execution_info = await test_contract.sum_points(((-1, 2), (-3, 4))).invoke() + execution_info = await test_contract.sum_points(((-1, 2), (-3, 4))).execute() assert execution_info.result.res == tuple(cast_to_felts(values=[-4, 6])) # Check multiple return values. - execution_info = await test_contract.sum_and_mult_points(points=(point_1, point_2)).invoke() + execution_info = await test_contract.sum_and_mult_points(points=(point_1, point_2)).execute() assert execution_info.result == (test_contract.Point(x=4, y=6), 11) # Check struct type consistency. @@ -122,9 +119,9 @@ async def test_proxy_call(proxy_contract: StarknetContract, test_class: Declared impl_class_abi=test_class.abi, ) - await wrapped_contract.increase_value(address=132, value=7).invoke() + await wrapped_contract.increase_value(address=132, value=7).execute() - execution_info = await wrapped_contract.get_value(address=132).invoke() + execution_info = await wrapped_contract.get_value(address=132).execute() assert execution_info.result == (7,) @@ -137,12 +134,12 @@ async def test_raw_decorators( selector = get_selector_from_name("increase_value") await account_contract.__execute__( contract_address=test_contract.contract_address, selector=selector, calldata=[132, 41] - ).invoke() + ).execute() selector = get_selector_from_name("get_value") execution_info = await account_contract.__execute__( contract_address=test_contract.contract_address, selector=selector, calldata=[132] - ).invoke() + ).execute() assert execution_info.result == (41,) with pytest.raises(AssertionError, match="Direct raw_input function calls are not supported."): @@ -160,7 +157,7 @@ async def test_event(test_contract: StarknetContract): ) expected_event = log_sum_points_tuple(points=[p1, p2], sum=point_sum) - execution_info = await test_contract.sum_points(points=(p1, p2)).invoke() + execution_info = await test_contract.sum_points(points=(p1, p2)).execute() (actual_event,) = execution_info.main_call_events # Check high-level form. @@ -191,5 +188,5 @@ async def wrap_with_proxy( """ Wraps an implementation contract's ABI with a proxy contract. """ - await proxy_contract.set_implementation_hash(implementation_hash_=impl_class_hash).invoke() + await proxy_contract.set_implementation_hash(implementation_hash_=impl_class_hash).execute() return proxy_contract.replace_abi(impl_contract_abi=impl_class_abi) diff --git a/src/starkware/starknet/testing/objects.py b/src/starkware/starknet/testing/objects.py index 5e96f311..55640c2a 100644 --- a/src/starkware/starknet/testing/objects.py +++ b/src/starkware/starknet/testing/objects.py @@ -1,11 +1,7 @@ import dataclasses from typing import Any, List -from starkware.starknet.business_logic.execution.objects import ( - Event, - L2ToL1MessageInfo, - TransactionExecutionInfo, -) +from starkware.starknet.business_logic.execution.objects import CallInfo, Event, L2ToL1MessageInfo from starkware.starknet.services.api.feeder_gateway.response_objects import FunctionInvocation from starkware.starkware_utils.validated_dataclass import ValidatedDataclass @@ -13,9 +9,9 @@ @dataclasses.dataclass(frozen=True) -class StarknetTransactionExecutionInfo(ValidatedDataclass): +class StarknetCallInfo(ValidatedDataclass): """ - A lean version of TransactionExecutionInfo class, containing merely the information relevant + A lean version of CallInfo class, containing merely the information relevant for the user. """ @@ -31,16 +27,14 @@ class StarknetTransactionExecutionInfo(ValidatedDataclass): @classmethod def from_internal( cls, - tx_execution_info: TransactionExecutionInfo, + call_info: CallInfo, result: tuple, main_call_events: List[Dataclass], - ) -> "StarknetTransactionExecutionInfo": + ) -> "StarknetCallInfo": return cls( result=result, main_call_events=main_call_events, - raw_events=tx_execution_info.get_sorted_events(), - l2_to_l1_messages=tx_execution_info.get_sorted_l2_to_l1_messages(), - call_info=FunctionInvocation.from_internal_version( - call_info=tx_execution_info.call_info - ), + raw_events=call_info.get_sorted_events(), + l2_to_l1_messages=call_info.get_sorted_l2_to_l1_messages(), + call_info=FunctionInvocation.from_internal(call_info=call_info), ) diff --git a/src/starkware/starknet/testing/postman.py b/src/starkware/starknet/testing/postman.py index f14d074e..5f12035a 100644 --- a/src/starkware/starknet/testing/postman.py +++ b/src/starkware/starknet/testing/postman.py @@ -1,8 +1,12 @@ +from typing import Type, TypeVar + from starkware.eth.eth_test_utils import EthContract, EthTestUtils from starkware.starknet.services.api.feeder_gateway.response_objects import LATEST_BLOCK_ID from starkware.starknet.testing.contracts import MockStarknetMessaging from starkware.starknet.testing.starknet import Starknet +TPostman = TypeVar("TPostman", bound="Postman") + class Postman: def __init__( @@ -21,7 +25,7 @@ def __init__( ) @classmethod - async def create(cls, eth_test_utils: EthTestUtils): + async def create(cls: Type[TPostman], eth_test_utils: EthTestUtils) -> TPostman: mock_starknet_messaging_contract = eth_test_utils.accounts[0].deploy( MockStarknetMessaging, 0 ) diff --git a/src/starkware/starknet/testing/postman_test.py b/src/starkware/starknet/testing/postman_test.py index c3eddf45..c4f8cb5b 100644 --- a/src/starkware/starknet/testing/postman_test.py +++ b/src/starkware/starknet/testing/postman_test.py @@ -1,6 +1,7 @@ import os import pytest +import pytest_asyncio from starkware.eth.eth_test_utils import EthTestUtils, eth_reverts from starkware.starknet.public.abi import get_selector_from_name @@ -12,12 +13,12 @@ CONTRACT_FILE = os.path.join(os.path.dirname(__file__), "test.cairo") -@pytest.fixture +@pytest_asyncio.fixture async def postman(eth_test_utils: EthTestUtils) -> Postman: return await Postman.create(eth_test_utils) -@pytest.fixture +@pytest_asyncio.fixture async def test_contract(postman: Postman) -> StarknetContract: return await postman.starknet.deploy(source=CONTRACT_FILE) @@ -59,7 +60,7 @@ async def test_postman_l1_to_l2_positive_flow( for msg_hash in msg_hashes: assert postman.mock_starknet_messaging_contract.l1ToL2Messages.call(msg_hash) == 0 - execution_info = await test_contract.get_value(user1).invoke() + execution_info = await test_contract.get_value(user1).execute() assert execution_info.result == (2 * amount1,) user2 = 47 @@ -84,7 +85,7 @@ async def test_postman_l1_to_l2_positive_flow( await postman.flush() assert postman.mock_starknet_messaging_contract.l1ToL2Messages.call(msg_hash2) == 0 - execution_info = await test_contract.get_value(user2).invoke() + execution_info = await test_contract.get_value(user2).execute() assert execution_info.result == (amount2,) @@ -109,8 +110,8 @@ async def test_postman_l2_to_l1_positive_flow( l1_address = int(eth_test_utils.accounts[0].address, 16) payload1 = [1, 2, 3] - await test_contract.send_message(to_address=l1_address, payload=payload1).invoke() - await test_contract.send_message(to_address=l1_address, payload=payload1).invoke() + await test_contract.send_message(to_address=l1_address, payload=payload1).execute() + await test_contract.send_message(to_address=l1_address, payload=payload1).execute() msg_hash1 = StarknetMessageToL1( from_address=test_contract.contract_address, @@ -136,7 +137,7 @@ async def test_postman_l2_to_l1_positive_flow( ) payload2 = [4, 5] - await test_contract.send_message(to_address=l1_address, payload=payload2).invoke() + await test_contract.send_message(to_address=l1_address, payload=payload2).execute() msg_hash2 = StarknetMessageToL1( from_address=test_contract.contract_address, diff --git a/src/starkware/starknet/testing/starknet.py b/src/starkware/starknet/testing/starknet.py index 0ac062f2..806e4a0b 100644 --- a/src/starkware/starknet/testing/starknet.py +++ b/src/starkware/starknet/testing/starknet.py @@ -1,13 +1,16 @@ +import copy from typing import List, Optional, Union -from starkware.python.utils import from_bytes +from starkware.python.utils import as_non_optional, from_bytes from starkware.starknet.business_logic.execution.objects import TransactionExecutionInfo +from starkware.starknet.business_logic.transaction.objects import InternalL1Handler from starkware.starknet.definitions.general_config import StarknetGeneralConfig -from starkware.starknet.services.api.contract_class import ContractClass, EntryPointType +from starkware.starknet.public.abi import get_selector_from_name +from starkware.starknet.services.api.contract_class import ContractClass from starkware.starknet.services.api.messages import StarknetMessageToL1 from starkware.starknet.testing.contract import DeclaredClass, StarknetContract from starkware.starknet.testing.contract_utils import get_abi, get_contract_class -from starkware.starknet.testing.objects import StarknetTransactionExecutionInfo +from starkware.starknet.testing.objects import StarknetCallInfo from starkware.starknet.testing.state import CastableToAddress, CastableToAddressSalt, StarknetState @@ -17,7 +20,7 @@ class Starknet: Example: starknet = await Starknet.empty() contract = await starknet.deploy('contract.cairo') - await contract.foo(a=1, b=[2, 3]).invoke() + await contract.foo(a=1, b=[2, 3]).execute() """ def __init__(self, state: StarknetState): @@ -31,6 +34,9 @@ def __init__(self, state: StarknetState): async def empty(cls, general_config: Optional[StarknetGeneralConfig] = None) -> "Starknet": return Starknet(state=await StarknetState.empty(general_config=general_config)) + def copy(self) -> "Starknet": + return copy.deepcopy(self) + async def declare( self, source: Optional[str] = None, @@ -44,8 +50,7 @@ async def declare( contract_class = get_contract_class( source=source, contract_class=contract_class, cairo_path=cairo_path ) - execution_info = await self.state.declare(contract_class=contract_class) - class_hash = execution_info.call_info.class_hash + class_hash, _ = await self.state.declare(contract_class=contract_class) assert class_hash is not None return DeclaredClass( class_hash=from_bytes(class_hash), abi=get_abi(contract_class=contract_class) @@ -72,14 +77,14 @@ async def deploy( constructor_calldata=[] if constructor_calldata is None else constructor_calldata, ) - deploy_execution_info = StarknetTransactionExecutionInfo.from_internal( - tx_execution_info=execution_info, result=(), main_call_events=[] + deploy_call_info = StarknetCallInfo.from_internal( + call_info=as_non_optional(execution_info.call_info), result=(), main_call_events=[] ) return StarknetContract( state=self.state, abi=get_abi(contract_class=contract_class), contract_address=address, - deploy_execution_info=deploy_execution_info, + deploy_call_info=deploy_call_info, ) def consume_message_from_l2(self, from_address: int, to_address: int, payload: List[int]): @@ -108,16 +113,24 @@ async def send_message_to_l2( Takes an optional nonce paramater to force a specific nonce, this should only be used by the Postman class. """ + if isinstance(to_address, str): + to_address = int(to_address, 16) + assert isinstance(to_address, int) + + if isinstance(selector, str): + selector = get_selector_from_name(selector) + assert isinstance(selector, int) + if nonce is None: nonce = self.l1_to_l2_nonce self.l1_to_l2_nonce += 1 - return await self.state.invoke_raw( + tx = InternalL1Handler.create( contract_address=to_address, - selector=selector, + entry_point_selector=selector, calldata=[from_address, *payload], - caller_address=0, - max_fee=max_fee, - entry_point_type=EntryPointType.L1_HANDLER, nonce=nonce, + chain_id=self.state.general_config.chain_id.value, ) + + return await self.state.execute_tx(tx=tx) diff --git a/src/starkware/starknet/testing/starknet_test.py b/src/starkware/starknet/testing/starknet_test.py index 37e1f545..5ed4f4d4 100644 --- a/src/starkware/starknet/testing/starknet_test.py +++ b/src/starkware/starknet/testing/starknet_test.py @@ -2,6 +2,7 @@ import re import pytest +import pytest_asyncio from starkware.starknet.compiler.compile import compile_starknet_files from starkware.starknet.testing.contract import StarknetContract @@ -11,31 +12,31 @@ HINT_CONTRACT_FILE = os.path.join(os.path.dirname(__file__), "test_unwhitelisted_hint.cairo") -@pytest.fixture +@pytest_asyncio.fixture async def starknet() -> Starknet: return await Starknet.empty() -@pytest.fixture +@pytest_asyncio.fixture async def contract(starknet: Starknet) -> StarknetContract: return await starknet.deploy(source=CONTRACT_FILE) @pytest.mark.asyncio async def test_basic(starknet: Starknet, contract: StarknetContract): - execution_info = contract.deploy_execution_info - assert execution_info.result == () + call_info = contract.deploy_call_info + assert call_info.result == () - execution_info = await contract.increase_value(address=100, value=5).invoke() - assert execution_info.result == () - execution_info = await contract.get_value(address=100).call() - assert execution_info.result == (5,) + call_info = await contract.increase_value(address=100, value=5).execute() + assert call_info.result == () + call_info = await contract.get_value(address=100).call() + assert call_info.result == (5,) # Check caller address. - execution_info = await contract.get_caller().invoke() - assert execution_info.result == (0,) - execution_info = await contract.get_caller().invoke(caller_address=1234) - assert execution_info.result == (1234,) + call_info = await contract.get_caller().execute() + assert call_info.result == (0,) + call_info = await contract.get_caller().execute(caller_address=1234) + assert call_info.result == (1234,) # Check deploy without compilation. contract_class = compile_starknet_files(files=[CONTRACT_FILE]) @@ -46,7 +47,7 @@ async def test_basic(starknet: Starknet, contract: StarknetContract): async def test_l2_to_l1_message(starknet: Starknet, contract: StarknetContract): l1_address = int("0xce08635cc6477f3634551db7613cc4f36b4e49dc", 16) payload = [6, 28] - await contract.send_message(to_address=l1_address, payload=payload).invoke() + await contract.send_message(to_address=l1_address, payload=payload).execute() # Consume the message. starknet.consume_message_from_l2( @@ -73,7 +74,7 @@ async def test_l1_to_l2_message(starknet: Starknet, contract: StarknetContract): selector="deposit", payload=[user, amount], ) - execution_info = await contract.get_value(address=user).invoke() + execution_info = await contract.get_value(address=user).execute() assert execution_info.result == (28,) @@ -83,16 +84,16 @@ async def test_contract_interaction(starknet: Starknet): contract = await starknet.deploy(contract_class=contract_class) proxy_contract = await starknet.deploy(contract_class=contract_class) - await proxy_contract.call_increase_value(contract.contract_address, 123, 234).invoke() - assert (await proxy_contract.get_value(123).invoke()).result == (0,) - assert (await contract.get_value(123).invoke()).result == (234,) + await proxy_contract.call_increase_value(contract.contract_address, 123, 234).execute() + assert (await proxy_contract.get_value(123).execute()).result == (0,) + assert (await contract.get_value(123).execute()).result == (234,) @pytest.mark.asyncio async def test_struct_arrays(starknet: Starknet): contract_class = compile_starknet_files([CONTRACT_FILE], debug_info=True) contract = await starknet.deploy(contract_class=contract_class) - assert (await contract.transpose([(123, 234), (4, 5)]).invoke()).result == ( + assert (await contract.transpose([(123, 234), (4, 5)]).execute()).result == ( [ contract.Point(x=123, y=4), contract.Point(x=234, y=5), @@ -103,7 +104,7 @@ async def test_struct_arrays(starknet: Starknet): TypeError, match=re.escape("argument inp[1] has wrong number of elements (expected 2, got 3 instead)"), ): - await contract.transpose([(123, 234), (4, 5, 6)]).invoke() + await contract.transpose([(123, 234), (4, 5, 6)]).execute() @pytest.mark.asyncio diff --git a/src/starkware/starknet/testing/state.py b/src/starkware/starknet/testing/state.py index 5e33e65b..c35d6f2b 100644 --- a/src/starkware/starknet/testing/state.py +++ b/src/starkware/starknet/testing/state.py @@ -1,22 +1,29 @@ import copy -from typing import Dict, List, Optional, Tuple, Union +from typing import List, MutableMapping, Optional, Tuple, Union from starkware.cairo.lang.vm.crypto import pedersen_hash_func +from starkware.starknet.business_logic.execution.execute_entry_point import ExecuteEntryPoint from starkware.starknet.business_logic.execution.objects import ( CallInfo, Event, TransactionExecutionInfo, ) -from starkware.starknet.business_logic.internal_transaction import ( +from starkware.starknet.business_logic.fact_state.patricia_state import PatriciaStateReader +from starkware.starknet.business_logic.fact_state.state import SharedState +from starkware.starknet.business_logic.state.state import CachedState +from starkware.starknet.business_logic.state.state_api import State +from starkware.starknet.business_logic.state.state_api_objects import BlockInfo +from starkware.starknet.business_logic.transaction.objects import ( InternalDeclare, InternalDeploy, InternalInvokeFunction, + InternalTransaction, ) -from starkware.starknet.business_logic.state.state import CarriedState from starkware.starknet.definitions import constants, fields from starkware.starknet.definitions.general_config import StarknetGeneralConfig from starkware.starknet.public.abi import get_selector_from_name from starkware.starknet.services.api.contract_class import ContractClass, EntryPointType +from starkware.starknet.services.api.gateway.transaction import DEFAULT_DECLARE_SENDER_ADDRESS from starkware.starknet.services.api.messages import StarknetMessageToL1 from starkware.storage.dict_storage import DictStorage from starkware.storage.storage import FactFetchingContext @@ -37,14 +44,14 @@ class StarknetState: contract_address=contract_address, selector="func", calldata=[1, 2]) """ - def __init__(self, state: CarriedState, general_config: StarknetGeneralConfig): + def __init__(self, state: CachedState, general_config: StarknetGeneralConfig): """ Constructor. Should not be used directly. Use empty() instead. """ self.state = state self.general_config = general_config # A mapping from L2-to-L1 message hash to its counter. - self._l2_to_l1_messages: Dict[str, int] = {} + self._l2_to_l1_messages: MutableMapping[str, int] = {} # A list of all L2-to-L1 messages sent, in chronological order. self.l2_to_l1_messages_log: List[StarknetMessageToL1] = [] # A list of all events emitted, in chronological order. @@ -66,32 +73,44 @@ async def empty(cls, general_config: Optional[StarknetGeneralConfig] = None) -> general_config = StarknetGeneralConfig() ffc = FactFetchingContext(storage=DictStorage(), hash_func=pedersen_hash_func) - state = await CarriedState.empty_for_testing( - shared_state=None, ffc=ffc, general_config=general_config + empty_shared_state = await SharedState.empty(ffc=ffc, general_config=general_config) + state_reader = PatriciaStateReader( + global_state_root=empty_shared_state.contract_states, ffc=ffc + ) + state = CachedState( + block_info=BlockInfo.empty(sequencer_address=general_config.sequencer_address), + state_reader=state_reader, ) return cls(state=state, general_config=general_config) - async def declare(self, contract_class: ContractClass) -> TransactionExecutionInfo: + async def declare( + self, contract_class: ContractClass + ) -> Tuple[bytes, TransactionExecutionInfo]: """ Declares a contract class. - Returns the execution info (which includes the class hash). + Returns the class hash and the execution info. Args: contract_class - a compiled StarkNet contract returned by compile_starknet_files(). """ - tx = await InternalDeclare.create_for_testing( - ffc=self.state.ffc, + tx = InternalDeclare.create( contract_class=contract_class, chain_id=self.general_config.chain_id.value, + sender_address=DEFAULT_DECLARE_SENDER_ADDRESS, + max_fee=0, + version=0, + signature=[], + nonce=0, ) + await self.state.set_contract_class(class_hash=tx.class_hash, contract_class=contract_class) with self.state.copy_and_apply() as state_copy: tx_execution_info = await tx.apply_state_updates( state=state_copy, general_config=self.general_config ) - return tx_execution_info + return tx.class_hash, tx_execution_info async def deploy( self, @@ -113,97 +132,102 @@ async def deploy( contract_address_salt = int(contract_address_salt, 16) assert isinstance(contract_address_salt, int) - tx = await InternalDeploy.create_for_testing( - ffc=self.state.ffc, - contract_class=contract_class, + tx = InternalDeploy.create( contract_address_salt=contract_address_salt, constructor_calldata=constructor_calldata, + contract_class=contract_class, chain_id=self.general_config.chain_id.value, + version=constants.TRANSACTION_VERSION, + ) + await self.state.set_contract_class( + class_hash=tx.contract_hash, contract_class=contract_class ) - with self.state.copy_and_apply() as state_copy: - tx_execution_info = await tx.apply_state_updates( - state=state_copy, general_config=self.general_config - ) + tx_execution_info = await self.execute_tx(tx=tx) return tx.contract_address, tx_execution_info - async def call_raw( + async def invoke_raw( self, contract_address: CastableToAddress, selector: Union[int, str], calldata: List[int], - caller_address: int, max_fee: int, signature: Optional[List[int]] = None, - entry_point_type: EntryPointType = EntryPointType.EXTERNAL, nonce: Optional[int] = None, - version: int = constants.QUERY_VERSION, - ) -> Tuple[CallInfo, CarriedState]: + ) -> TransactionExecutionInfo: """ - Calls a function on a contract and returns its CallInfo without modifying the state. + Invokes a contract function. Returns the execution info. + + Args: + contract_address - a hexadecimal string or an integer representing the contract address. + selector - either a function name or an integer selector for the entrypoint to invoke. + calldata - a list of integers to pass as calldata to the invoked function. + signature - a list of integers to pass as signature to the invoked function. """ - tx = create_invoke_function( + tx = await create_invoke_function( + state=self.state, contract_address=contract_address, selector=selector, calldata=calldata, - caller_address=caller_address, max_fee=max_fee, - version=version, + version=constants.TRANSACTION_VERSION, signature=signature, - entry_point_type=entry_point_type, nonce=nonce, chain_id=self.general_config.chain_id.value, - only_query=True, - ) - child_state = self.state.create_child_state_for_querying() - - call_info = await tx.execute( - state=child_state, general_config=self.general_config, only_query=True ) - return call_info, child_state + return await self.execute_tx(tx=tx) - async def invoke_raw( + async def execute_entry_point_raw( self, contract_address: CastableToAddress, selector: Union[int, str], calldata: List[int], caller_address: int, - max_fee: int, - signature: Optional[List[int]] = None, - entry_point_type: EntryPointType = EntryPointType.EXTERNAL, - nonce: Optional[int] = None, - ) -> TransactionExecutionInfo: + ) -> CallInfo: """ - Invokes a contract function. Returns the execution info. - - Args: - contract_address - a hexadecimal string or an integer representing the contract address. - selector - either a function name or an integer selector for the entrypoint to invoke. - calldata - a list of integers to pass as calldata to the invoked function. - signature - a list of integers to pass as signature to the invoked function. + Builds the transaction execution context and executes the entry point. + Returns the CallInfo. """ + if isinstance(contract_address, str): + contract_address = int(contract_address, 16) + assert isinstance(contract_address, int) + + if isinstance(selector, str): + selector = get_selector_from_name(selector) + assert isinstance(selector, int) - tx = create_invoke_function( + call = ExecuteEntryPoint.create( contract_address=contract_address, - selector=selector, + entry_point_selector=selector, + entry_point_type=EntryPointType.EXTERNAL, calldata=calldata, caller_address=caller_address, - max_fee=max_fee, - version=constants.TRANSACTION_VERSION, - signature=signature, - entry_point_type=entry_point_type, - nonce=nonce, - chain_id=self.general_config.chain_id.value, ) + with self.state.copy_and_apply() as state_copy: + call_info = await call.execute_for_testing( + state=state_copy, + general_config=self.general_config, + ) + + self.add_messages_and_events(execution_info=call_info) + + return call_info + + async def execute_tx(self, tx: InternalTransaction) -> TransactionExecutionInfo: with self.state.copy_and_apply() as state_copy: tx_execution_info = await tx.apply_state_updates( state=state_copy, general_config=self.general_config ) + self.add_messages_and_events(execution_info=tx_execution_info) + + return tx_execution_info + + def add_messages_and_events(self, execution_info: Union[CallInfo, TransactionExecutionInfo]): # Add messages. - for message in tx_execution_info.get_sorted_l2_to_l1_messages(): + for message in execution_info.get_sorted_l2_to_l1_messages(): starknet_message = StarknetMessageToL1( from_address=message.from_address, to_address=message.to_address, @@ -214,9 +238,7 @@ async def invoke_raw( self._l2_to_l1_messages[message_hash] = self._l2_to_l1_messages.get(message_hash, 0) + 1 # Add events. - self.events += tx_execution_info.get_sorted_events() - - return tx_execution_info + self.events += execution_info.get_sorted_events() def consume_message_hash(self, message_hash: str): """ @@ -229,20 +251,18 @@ def consume_message_hash(self, message_hash: str): self._l2_to_l1_messages[message_hash] -= 1 -def create_invoke_function( +async def create_invoke_function( + state: State, contract_address: CastableToAddress, selector: Union[int, str], calldata: List[int], - caller_address: int, max_fee: int, version: int, signature: Optional[List[int]], - entry_point_type: EntryPointType, nonce: Optional[int], chain_id: int, only_query: bool = False, ) -> InternalInvokeFunction: - if isinstance(contract_address, str): contract_address = int(contract_address, 16) assert isinstance(contract_address, int) @@ -251,18 +271,20 @@ def create_invoke_function( selector = get_selector_from_name(selector) assert isinstance(selector, int) - signature = [] if signature is None else signature + if signature is None: + signature = [] + + # We allow not specifying nonce. In this case, the current nonce of the contract will be used. + if nonce is None: + nonce = await state.get_nonce_at(contract_address=contract_address) return InternalInvokeFunction.create( contract_address=contract_address, entry_point_selector=selector, - entry_point_type=entry_point_type, calldata=calldata, max_fee=max_fee, signature=signature, - caller_address=caller_address, nonce=nonce, chain_id=chain_id, version=version, - only_query=only_query, ) diff --git a/src/starkware/starknet/testing/test.cairo b/src/starkware/starknet/testing/test.cairo index 9371fe9f..f6dfbac9 100644 --- a/src/starkware/starknet/testing/test.cairo +++ b/src/starkware/starknet/testing/test.cairo @@ -12,98 +12,98 @@ from starkware.starknet.common.syscalls import ( ) @contract_interface -namespace MyContract: - func increase_value(address : felt, value : felt): - end -end +namespace MyContract { + func increase_value(address: felt, value: felt) { + } +} @external -func increase_value{syscall_ptr : felt*}(address : felt, value : felt): - let (res) = storage_read(address=address) - return storage_write(address=address, value=res + value) -end +func increase_value{syscall_ptr: felt*}(address: felt, value: felt) { + let (res) = storage_read(address=address); + return storage_write(address=address, value=res + value); +} @external -func call_increase_value{syscall_ptr : felt*, range_check_ptr}( - contract_address : felt, address : felt, value : felt -): - MyContract.increase_value(contract_address=contract_address, address=address, value=value) - return () -end +func call_increase_value{syscall_ptr: felt*, range_check_ptr}( + contract_address: felt, address: felt, value: felt +) { + MyContract.increase_value(contract_address=contract_address, address=address, value=value); + return (); +} @external -func get_value{syscall_ptr : felt*}(address : felt) -> (res : felt): - let (res) = storage_read(address=address) - return (res=res) -end +func get_value{syscall_ptr: felt*}(address: felt) -> (res: felt) { + let (res) = storage_read(address=address); + return (res=res); +} @external -func get_caller{syscall_ptr : felt*}() -> (res : felt): - let (caller_address) = get_caller_address() - return (res=caller_address) -end +func get_caller{syscall_ptr: felt*}() -> (res: felt) { + let (caller_address) = get_caller_address(); + return (res=caller_address); +} @external -func takes_array{syscall_ptr : felt*}(a_len : felt, a : felt*) -> (res : felt): - let res = a_len + a[0] + a[1] - return (res=res) -end +func takes_array{syscall_ptr: felt*}(a_len: felt, a: felt*) -> (res: felt) { + let res = a_len + a[0] + a[1]; + return (res=res); +} @external -func get_signature{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*}() -> ( - res_len : felt, res : felt* -): - let (tx_info) = get_tx_info() - return (res_len=tx_info.signature_len, res=tx_info.signature) -end +func get_signature{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*}() -> ( + res_len: felt, res: felt* +) { + let (tx_info) = get_tx_info(); + return (res_len=tx_info.signature_len, res=tx_info.signature); +} @external -func send_message{syscall_ptr : felt*}(to_address : felt, payload_len : felt, payload : felt*): - send_message_to_l1(to_address=to_address, payload_size=payload_len, payload=payload) - return () -end +func send_message{syscall_ptr: felt*}(to_address: felt, payload_len: felt, payload: felt*) { + send_message_to_l1(to_address=to_address, payload_size=payload_len, payload=payload); + return (); +} @l1_handler -func deposit{syscall_ptr : felt*}(from_address : felt, user : felt, amount : felt): - increase_value(address=user, value=amount) - return () -end +func deposit{syscall_ptr: felt*}(from_address: felt, user: felt, amount: felt) { + increase_value(address=user, value=amount); + return (); +} -struct Point: - member x : felt - member y : felt -end +struct Point { + x: felt, + y: felt, +} @event -func log_sum_points(points_len : felt, points : Point*, sum : Point): -end +func log_sum_points(points_len: felt, points: Point*, sum: Point) { +} @view -func sum_points{syscall_ptr : felt*, range_check_ptr}(points : (Point, Point)) -> (res : Point): - # Calculate sum. - let res : Point = Point(x=points[0].x + points[1].x, y=points[0].y + points[1].y) +func sum_points{syscall_ptr: felt*, range_check_ptr}(points: (Point, Point)) -> (res: Point) { + // Calculate sum. + let res: Point = Point(x=points[0].x + points[1].x, y=points[0].y + points[1].y); - # Log points and their sum. - let (__fp__, _) = get_fp_and_pc() - log_sum_points.emit(points_len=2, points=&points[0], sum=res) + // Log points and their sum. + let (__fp__, _) = get_fp_and_pc(); + log_sum_points.emit(points_len=2, points=&points[0], sum=res); - return (res=res) -end + return (res=res); +} @view -func sum_and_mult_points{syscall_ptr : felt*, range_check_ptr}(points : (Point, Point)) -> ( - sum_res : Point, mult_res : felt -): - let sum_res : Point = sum_points(points=points) - let mult_res : felt = (points[0].x * points[1].x) + (points[0].y * points[1].y) - return (sum_res=sum_res, mult_res=mult_res) -end +func sum_and_mult_points{syscall_ptr: felt*, range_check_ptr}(points: (Point, Point)) -> ( + sum_res: Point, mult_res: felt +) { + let sum_res: Point = sum_points(points=points); + let mult_res: felt = (points[0].x * points[1].x) + (points[0].y * points[1].y); + return (sum_res=sum_res, mult_res=mult_res); +} @external -func transpose(inp_len : felt, inp : Point*) -> (res_len : felt, res : Point*): - assert inp_len = 2 - let (res : Point*) = alloc() - assert res[0] = Point(x=inp[0].x, y=inp[1].x) - assert res[1] = Point(x=inp[0].y, y=inp[1].y) - return (res_len=2, res=res) -end +func transpose(inp_len: felt, inp: Point*) -> (res_len: felt, res: Point*) { + assert inp_len = 2; + let (res: Point*) = alloc(); + assert res[0] = Point(x=inp[0].x, y=inp[1].x); + assert res[1] = Point(x=inp[0].y, y=inp[1].y); + return (res_len=2, res=res); +} diff --git a/src/starkware/starknet/testing/test_unwhitelisted_hint.cairo b/src/starkware/starknet/testing/test_unwhitelisted_hint.cairo index 3a399d9c..f02f51ff 100644 --- a/src/starkware/starknet/testing/test_unwhitelisted_hint.cairo +++ b/src/starkware/starknet/testing/test_unwhitelisted_hint.cairo @@ -2,7 +2,7 @@ from starkware.cairo.common.cairo_builtins import HashBuiltin @constructor -func constructor{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(): +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { %{ print("Deploying contract...") %} - return () -end + return (); +} diff --git a/src/starkware/starknet/third_party/open_zeppelin/Account.cairo b/src/starkware/starknet/third_party/open_zeppelin/Account.cairo index 4b971334..f044fbe8 100644 --- a/src/starkware/starknet/third_party/open_zeppelin/Account.cairo +++ b/src/starkware/starknet/third_party/open_zeppelin/Account.cairo @@ -1,5 +1,5 @@ -# SPDX-License-Identifier: MIT -# OpenZeppelin Cairo Contracts v0.1.0 (account/Account.cairo) +// SPDX-License-Identifier: MIT +// OpenZeppelin Cairo Contracts v0.1.0 (account/Account.cairo) %lang starknet @@ -11,6 +11,7 @@ from starkware.cairo.common.hash_state import ( hash_update, hash_update_single, ) +from starkware.cairo.common.math import assert_not_equal from starkware.cairo.common.memcpy import memcpy from starkware.cairo.common.registers import get_fp_and_pc from starkware.cairo.common.signature import verify_ecdsa_signature @@ -21,248 +22,250 @@ from starkware.starknet.common.syscalls import ( get_contract_address, get_tx_info, ) -from starkware.starknet.core.os.transactions import ORIGIN_ADDRESS +from starkware.starknet.common.constants import ORIGIN_ADDRESS from starkware.starknet.third_party.open_zeppelin.utils.constants import PREFIX_TRANSACTION -# -# Structs -# - -struct MultiCall: - member account : felt - member calls_len : felt - member calls : Call* - member nonce : felt - member max_fee : felt - member version : felt -end - -struct Call: - member to : felt - member selector : felt - member calldata_len : felt - member calldata : felt* -end - -# Tmp struct introduced while we wait for Cairo -# to support passing `[Call]` to __execute__ -struct CallArray: - member to : felt - member selector : felt - member data_offset : felt - member data_len : felt -end - -# -# Storage -# +// +// Structs +// + +struct MultiCall { + account: felt, + calls_len: felt, + calls: Call*, + max_fee: felt, + version: felt, +} + +struct Call { + to: felt, + selector: felt, + calldata_len: felt, + calldata: felt*, +} + +// Tmp struct introduced while we wait for Cairo +// to support passing `[Call]` to __execute__ +struct CallArray { + to: felt, + selector: felt, + data_offset: felt, + data_len: felt, +} + +// +// Storage +// @storage_var -func current_nonce() -> (res : felt): -end +func public_key() -> (res: felt) { +} -@storage_var -func public_key() -> (res : felt): -end - -# -# Guards -# +// +// Guards +// @view -func assert_only_self{syscall_ptr : felt*}(): - let (self) = get_contract_address() - let (caller) = get_caller_address() - assert self = caller - return () -end +func assert_only_self{syscall_ptr: felt*}() { + let (self) = get_contract_address(); + let (caller) = get_caller_address(); + assert self = caller; + return (); +} -# -# Getters -# +// +// Getters +// @view -func get_public_key{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() -> ( - res : felt -): - let (res) = public_key.read() - return (res=res) -end +func get_public_key{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + res: felt +) { + let (res) = public_key.read(); + return (res=res); +} -@view -func get_nonce{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() -> (res : felt): - let (res) = current_nonce.read() - return (res=res) -end - -# -# Setters -# +// +// Setters +// @external -func set_public_key{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - new_public_key : felt -): - assert_only_self() - public_key.write(new_public_key) - return () -end - -# -# Constructor -# +func set_public_key{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + new_public_key: felt +) { + assert_only_self(); + public_key.write(new_public_key); + return (); +} + +// +// Constructor +// @constructor -func constructor{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( - _public_key : felt -): - public_key.write(_public_key) - return () -end +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + _public_key: felt +) { + public_key.write(_public_key); + return (); +} -# -# Business logic -# +// +// Business logic +// @view func is_valid_signature{ - syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr, ecdsa_ptr : SignatureBuiltin* -}(hash : felt, signature_len : felt, signature : felt*) -> (): - let (_public_key) = public_key.read() + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, ecdsa_ptr: SignatureBuiltin* +}(hash: felt, signature_len: felt, signature: felt*) -> () { + let (_public_key) = public_key.read(); + + // This interface expects a signature pointer and length to make + // no assumption about signature validation schemes. + // But this implementation does, and it expects a (sig_r, sig_s) pair. + with_attr error_message("INVALID_SIGNATURE_LENGTH") { + assert signature_len = 2; + } - # This interface expects a signature pointer and length to make - # no assumption about signature validation schemes. - # But this implementation does, and it expects a (sig_r, sig_s) pair. - let sig_r = signature[0] - let sig_s = signature[1] + let sig_r = signature[0]; + let sig_s = signature[1]; verify_ecdsa_signature( message=hash, public_key=_public_key, signature_r=sig_r, signature_s=sig_s - ) + ); - return () -end + return (); +} + +@external +func __validate_declare__{ + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, ecdsa_ptr: SignatureBuiltin* +}(class_hash: felt) { + let (tx_info) = get_tx_info(); + is_valid_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature); + return (); +} + +@external +func __validate__{ + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, ecdsa_ptr: SignatureBuiltin* +}(call_array_len: felt, call_array: CallArray*, calldata_len: felt, calldata: felt*) { + let (tx_info) = get_tx_info(); + is_valid_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature); + return (); +} @external @raw_output func __execute__{ - syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr, ecdsa_ptr : SignatureBuiltin* -}( - call_array_len : felt, - call_array : CallArray*, - calldata_len : felt, - calldata : felt*, - nonce : felt, -) -> (retdata_size : felt, retdata : felt*): - alloc_locals - - let (__fp__, _) = get_fp_and_pc() - let (tx_info) = get_tx_info() - - # validate caller - let (caller) = get_caller_address() + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, ecdsa_ptr: SignatureBuiltin* +}(call_array_len: felt, call_array: CallArray*, calldata_len: felt, calldata: felt*) -> ( + retdata_size: felt, retdata: felt* +) { + alloc_locals; + + let (__fp__, _) = get_fp_and_pc(); + let (tx_info) = get_tx_info(); + + // validate caller. + let (caller) = get_caller_address(); with_attr error_message( - "Invalid caller. This function cannot be called from another contract."): - assert caller = ORIGIN_ADDRESS - end - - # validate nonce - let (_current_nonce) = current_nonce.read() - with_attr error_message("Invalid nonce."): - assert nonce = _current_nonce - end - - # TMP: Convert `CallArray` to 'Call'. - let (calls : Call*) = alloc() - from_call_array_to_call(call_array_len, call_array, calldata, calls) - let calls_len = call_array_len - - local multicall : MultiCall = MultiCall( + "Invalid caller. This function cannot be called from another contract.") { + assert caller = ORIGIN_ADDRESS; + } + + // validate version + with_attr error_message( + "Invalid transaction version. This account contract does not support " + "transaction version 0.") { + assert_not_equal(tx_info.version, 0); + } + + // TMP: Convert `CallArray` to 'Call'. + let (calls: Call*) = alloc(); + from_call_array_to_call(call_array_len, call_array, calldata, calls); + let calls_len = call_array_len; + + local multicall: MultiCall = MultiCall( tx_info.account_contract_address, calls_len, calls, - _current_nonce, tx_info.max_fee, tx_info.version - ) - - # validate transaction - - is_valid_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature) - - # bump nonce - current_nonce.write(_current_nonce + 1) + ); - # execute call - let (response : felt*) = alloc() - let (response_len) = execute_list(multicall.calls_len, multicall.calls, response) + // execute call. + let (response: felt*) = alloc(); + let (response_len) = execute_list(multicall.calls_len, multicall.calls, response); - return (retdata_size=response_len, retdata=response) -end + return (retdata_size=response_len, retdata=response); +} @external -func deploy_contract{syscall_ptr : felt*}( - class_hash : felt, - contract_address_salt : felt, - constructor_calldata_len : felt, - constructor_calldata : felt*, - deploy_from_zero : felt, -) -> (contract_address : felt): - assert_only_self() +func deploy_contract{syscall_ptr: felt*}( + class_hash: felt, + contract_address_salt: felt, + constructor_calldata_len: felt, + constructor_calldata: felt*, + deploy_from_zero: felt, +) -> (contract_address: felt) { + assert_only_self(); let (contract_address) = deploy( class_hash=class_hash, contract_address_salt=contract_address_salt, constructor_calldata_size=constructor_calldata_len, constructor_calldata=constructor_calldata, deploy_from_zero=deploy_from_zero, - ) - return (contract_address=contract_address) -end - -func execute_list{syscall_ptr : felt*}(calls_len : felt, calls : Call*, response : felt*) -> ( - response_len : felt -): - alloc_locals - - # if no more calls - if calls_len == 0: - return (response_len=0) - end - - # do the current call - let this_call : Call = [calls] + ); + return (contract_address=contract_address); +} + +func execute_list{syscall_ptr: felt*}(calls_len: felt, calls: Call*, response: felt*) -> ( + response_len: felt +) { + alloc_locals; + + // if no more calls + if (calls_len == 0) { + return (response_len=0); + } + + // do the current call + let this_call: Call = [calls]; let res = call_contract( contract_address=this_call.to, function_selector=this_call.selector, calldata_size=this_call.calldata_len, calldata=this_call.calldata, - ) - # copy the result in response - memcpy(response, res.retdata, res.retdata_size) - # do the next calls recursively - let (response_len) = execute_list(calls_len - 1, calls + Call.SIZE, response + res.retdata_size) - return (response_len=response_len + res.retdata_size) -end - -func from_call_array_to_call{syscall_ptr : felt*}( - call_array_len : felt, call_array : CallArray*, calldata : felt*, calls : Call* -): - # if no more calls - if call_array_len == 0: - return () - end - - # parse the current call + ); + // copy the result in response + memcpy(response, res.retdata, res.retdata_size); + // do the next calls recursively + let (response_len) = execute_list( + calls_len - 1, calls + Call.SIZE, response + res.retdata_size + ); + return (response_len=response_len + res.retdata_size); +} + +func from_call_array_to_call{syscall_ptr: felt*}( + call_array_len: felt, call_array: CallArray*, calldata: felt*, calls: Call* +) { + // if no more calls + if (call_array_len == 0) { + return (); + } + + // parse the current call assert [calls] = Call( to=[call_array].to, selector=[call_array].selector, calldata_len=[call_array].data_len, calldata=calldata + [call_array].data_offset - ) + ); - # parse the remaining calls recursively + // parse the remaining calls recursively from_call_array_to_call( call_array_len - 1, call_array + CallArray.SIZE, calldata, calls + Call.SIZE - ) - return () -end + ); + return (); +} diff --git a/src/starkware/starknet/third_party/open_zeppelin/utils/constants.cairo b/src/starkware/starknet/third_party/open_zeppelin/utils/constants.cairo index a49ea4e5..6bd8a197 100644 --- a/src/starkware/starknet/third_party/open_zeppelin/utils/constants.cairo +++ b/src/starkware/starknet/third_party/open_zeppelin/utils/constants.cairo @@ -1,23 +1,23 @@ -# SPDX-License-Identifier: MIT -# OpenZeppelin Cairo Contracts v0.1.0 (utils/constants.cairo) +// SPDX-License-Identifier: MIT +// OpenZeppelin Cairo Contracts v0.1.0 (utils/constants.cairo) %lang starknet -# -# Booleans -# +// +// Booleans +// -const TRUE = 1 -const FALSE = 0 +const TRUE = 1; +const FALSE = 0; -# -# Hashing Transactions -# +// +// Hashing Transactions +// -const PREFIX_TRANSACTION = 'StarkNet Transaction' +const PREFIX_TRANSACTION = 'StarkNet Transaction'; -# -# Numbers -# +// +// Numbers +// -const UINT8_MAX = 256 +const UINT8_MAX = 256; diff --git a/src/starkware/starknet/utils/api_utils.py b/src/starkware/starknet/utils/api_utils.py index c249e304..2eedd13d 100644 --- a/src/starkware/starknet/utils/api_utils.py +++ b/src/starkware/starknet/utils/api_utils.py @@ -16,7 +16,7 @@ def cast_to_felts(values: Sequence[Union[str, int]]) -> List[int]: except ValueError: raise ValueError( f"Invalid input value: '{value}'. Expected a decimal or hexadecimal integer." - ) + ) from None if not lower_bound <= value_int < upper_bound: raise ValueError( diff --git a/src/starkware/starknet/wallets/CMakeLists.txt b/src/starkware/starknet/wallets/CMakeLists.txt index 82d595e6..36ba86c0 100644 --- a/src/starkware/starknet/wallets/CMakeLists.txt +++ b/src/starkware/starknet/wallets/CMakeLists.txt @@ -6,6 +6,7 @@ python_lib(starknet_wallets_lib starknet_context.py LIBS + starknet_contract_class_lib starknet_definitions_lib starknet_feeder_gateway_client_lib starknet_gateway_client_lib @@ -25,6 +26,7 @@ python_lib(starknet_standard_wallets_lib starknet_abi_lib starknet_api_utils_lib starknet_contract_address_lib + starknet_contract_class_lib starknet_definitions_lib starknet_feeder_gateway_response_objects_lib starknet_transaction_hash_lib diff --git a/src/starkware/starknet/wallets/account.py b/src/starkware/starknet/wallets/account.py index c8e1b729..0479ce0f 100644 --- a/src/starkware/starknet/wallets/account.py +++ b/src/starkware/starknet/wallets/account.py @@ -1,7 +1,8 @@ import dataclasses from abc import ABC, abstractmethod -from typing import List, Optional, Tuple +from typing import Awaitable, Callable, List, Tuple +from starkware.starknet.services.api.contract_class import ContractClass from starkware.starknet.wallets.starknet_context import StarknetContext DEFAULT_ACCOUNT_DIR = "~/.starknet_accounts" @@ -14,6 +15,7 @@ class WrappedMethod: calldata: List[int] max_fee: int signature: List[int] + nonce: int class Account(ABC): @@ -40,7 +42,7 @@ async def sign_invoke_transaction( chain_id: int, max_fee: int, version: int, - nonce: Optional[int], + nonce_callback: Callable[[int], Awaitable[int]], dry_run: bool = False, ) -> WrappedMethod: """ @@ -60,10 +62,25 @@ async def deploy_contract( chain_id: int, max_fee: int, version: int, - nonce: Optional[int], + nonce_callback: Callable[[int], Awaitable[int]], ) -> Tuple[WrappedMethod, int]: """ Prepares the required information for invoking a contract deployment function through the account contract. Returns the wrapped method and the deployed contract address. """ + + @abstractmethod + async def declare( + self, + contract_class: ContractClass, + chain_id: int, + max_fee: int, + version: int, + nonce_callback: Callable[[int], Awaitable[int]], + dry_run: bool = False, + ) -> WrappedMethod: + """ + Prepares the required information for declaring a contract class through the account + contract. + """ diff --git a/src/starkware/starknet/wallets/open_zeppelin.py b/src/starkware/starknet/wallets/open_zeppelin.py index 505fe4fe..e9a278e2 100644 --- a/src/starkware/starknet/wallets/open_zeppelin.py +++ b/src/starkware/starknet/wallets/open_zeppelin.py @@ -1,7 +1,7 @@ import json import os import shutil -from typing import List, Optional, Tuple +from typing import Awaitable, Callable, List, Optional, Tuple from services.external_api.client import JsonObject from starkware.crypto.signature.signature import get_random_private_key, private_to_stark_key, sign @@ -10,12 +10,13 @@ ) from starkware.starknet.core.os.transaction_hash.transaction_hash import ( TransactionHashPrefix, + calculate_declare_transaction_hash, calculate_transaction_hash_common, ) from starkware.starknet.definitions import constants, fields from starkware.starknet.public.abi import EXECUTE_ENTRY_POINT_SELECTOR, get_selector_from_name -from starkware.starknet.services.api.feeder_gateway.response_objects import PENDING_BLOCK_ID -from starkware.starknet.services.api.gateway.transaction import Deploy, InvokeFunction +from starkware.starknet.services.api.contract_class import ContractClass +from starkware.starknet.services.api.gateway.transaction import Deploy from starkware.starknet.third_party.open_zeppelin.starknet_contracts import account_contract from starkware.starknet.wallets.account import Account, WrappedMethod from starkware.starknet.wallets.starknet_context import StarknetContext @@ -47,6 +48,35 @@ def account_file(self): os.path.expanduser(self.starknet_context.account_dir), ACCOUNT_FILE_NAME ) + async def declare( + self, + contract_class: ContractClass, + chain_id: int, + max_fee: int, + version: int, + nonce_callback: Callable[[int], Awaitable[int]], + dry_run: bool = False, + ) -> WrappedMethod: + account = self.get_account_information() + account_address = int(account["address"], 16) + + private_key: Optional[int] + if "private_key" in account: + private_key = int(account["private_key"], 16) + else: + assert dry_run, f"Missing private key for {hex(account_address)}" + private_key = None + + return sign_declare_transaction( + contract_class=contract_class, + private_key=private_key, + sender_address=account_address, + chain_id=chain_id, + max_fee=max_fee, + version=version, + nonce=await nonce_callback(account_address), + ) + async def deploy(self): # Read the account file. if os.path.exists(self.account_file): @@ -129,7 +159,7 @@ async def sign_invoke_transaction( chain_id: int, max_fee: Optional[int], version: int, - nonce: Optional[int], + nonce_callback: Callable[[int], Awaitable[int]], dry_run: bool = False, ) -> WrappedMethod: account = self.get_account_information() @@ -142,11 +172,6 @@ async def sign_invoke_transaction( assert dry_run, f"Missing private_key for {hex(account_address)}." private_key = None - if nonce is None: - # Obtain the current nonce. Note that you can't invoke a function again before the - # previous transaction was accepted. - nonce = await self.get_current_nonce(account_address=account_address) - return sign_invoke_transaction( signer_address=account_address, private_key=private_key, @@ -156,7 +181,7 @@ async def sign_invoke_transaction( chain_id=chain_id, max_fee=max_fee, version=version, - nonce=nonce, + nonce=await nonce_callback(account_address), ) async def deploy_contract( @@ -168,7 +193,7 @@ async def deploy_contract( chain_id: int, max_fee: Optional[int], version: int, - nonce: Optional[int], + nonce_callback: Callable[[int], Awaitable[int]], ) -> Tuple[WrappedMethod, int]: account = self.get_account_information() account_address = int(account["address"], 16) @@ -188,30 +213,48 @@ async def deploy_contract( chain_id=chain_id, max_fee=max_fee, version=version, - nonce=nonce, + nonce_callback=nonce_callback, ) + contract_address = calculate_contract_address_from_hash( salt=salt, class_hash=class_hash, constructor_calldata=constructor_calldata, deployer_address=0 if deploy_from_zero else account_address, ) + return wrapped_invocation, contract_address - async def get_current_nonce(self, account_address: int) -> int: - get_nonce_tx = InvokeFunction( - contract_address=account_address, - entry_point_selector=GET_NONCE_SELECTOR, - calldata=[], - max_fee=0, - version=constants.QUERY_VERSION, - signature=[], - ) - res = await self.starknet_context.feeder_gateway_client.call_contract( - invoke_tx=get_nonce_tx, block_hash=None, block_number=PENDING_BLOCK_ID - ) - (nonce_hex,) = res["result"] - return int(nonce_hex, 16) + +def sign_declare_transaction( + contract_class: ContractClass, + private_key: Optional[int], + sender_address: int, + chain_id: int, + max_fee: int, + version: int, + nonce: int, +) -> WrappedMethod: + hash_value = calculate_declare_transaction_hash( + contract_class=contract_class, + chain_id=chain_id, + sender_address=sender_address, + max_fee=max_fee, + version=version, + nonce=nonce, + ) + if private_key is None: + signature = [] + else: + signature = list(sign(msg_hash=hash_value, priv_key=private_key)) + return WrappedMethod( + address=sender_address, + selector=0, + calldata=[], + max_fee=max_fee, + signature=signature, + nonce=nonce, + ) def sign_invoke_transaction( @@ -233,17 +276,17 @@ def sign_invoke_transaction( data_len = len(calldata) call_entry = [contract_address, selector, data_offset, data_len] call_array_len = 1 - wrapped_method_calldata = [call_array_len, *call_entry, len(calldata), *calldata, nonce] + wrapped_method_calldata = [call_array_len, *call_entry, len(calldata), *calldata] max_fee = 0 if max_fee is None else max_fee hash_value = calculate_transaction_hash_common( tx_hash_prefix=TransactionHashPrefix.INVOKE, version=version, contract_address=signer_address, - entry_point_selector=EXECUTE_ENTRY_POINT_SELECTOR, + entry_point_selector=0, calldata=wrapped_method_calldata, max_fee=max_fee, chain_id=chain_id, - additional_data=[], + additional_data=[nonce], ) if private_key is None: signature = [] @@ -254,5 +297,6 @@ def sign_invoke_transaction( selector=EXECUTE_ENTRY_POINT_SELECTOR, calldata=wrapped_method_calldata, max_fee=max_fee, + nonce=nonce, signature=signature, ) diff --git a/src/starkware/starkware_utils/CMakeLists.txt b/src/starkware/starkware_utils/CMakeLists.txt index 11bd7ec4..41e0777b 100644 --- a/src/starkware/starkware_utils/CMakeLists.txt +++ b/src/starkware/starkware_utils/CMakeLists.txt @@ -22,7 +22,7 @@ python_lib(starkware_utils_lib starkware_commitment_tree_facts_lib starkware_config_utils_lib starkware_custom_dict_utils_lib - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib starkware_error_handling_lib starkware_python_utils_lib starkware_serializability_utils_lib diff --git a/src/starkware/starkware_utils/CMakeLists_common.txt b/src/starkware/starkware_utils/CMakeLists_common.txt index ae1cb1f7..528249f7 100644 --- a/src/starkware/starkware_utils/CMakeLists_common.txt +++ b/src/starkware/starkware_utils/CMakeLists_common.txt @@ -15,6 +15,9 @@ python_lib(starkware_error_handling_lib FILES error_handling.py + + LIBS + pip_marshmallow ) python_lib(starkware_custom_dict_utils_lib @@ -31,9 +34,7 @@ python_lib(starkware_dataclasses_utils_lib PREFIX starkware/starkware_utils FILES - field_validators.py marshmallow_dataclass_fields.py - one_of_schema_tracker.py serializable_dataclass.py validated_dataclass.py validated_fields.py @@ -48,7 +49,32 @@ python_lib(starkware_dataclasses_utils_lib pip_marshmallow_dataclass pip_mypy_extensions pip_typeguard - pip_web3 +) + +python_lib(starkware_one_of_schema_utils_lib + PREFIX starkware/starkware_utils + + FILES + one_of_schema_tracker.py + + LIBS + starkware_dataclasses_utils_lib + pip_marshmallow + pip_marshmallow_oneofschema +) + +python_lib(starkware_dataclasses_field_utils_lib + PREFIX starkware/starkware_utils + + FILES + field_validators.py + marshmallow_fields_metadata.py + + LIBS + starkware_dataclasses_utils_lib + pip_eth_utils + pip_marshmallow + pip_setuptools ) python_lib(starkware_config_utils_lib @@ -58,7 +84,7 @@ python_lib(starkware_config_utils_lib config_base.py LIBS - starkware_dataclasses_utils_lib + starkware_dataclasses_field_utils_lib pip_marshmallow pip_pyyaml ) diff --git a/src/starkware/starkware_utils/commitment_tree/binary_fact_tree.py b/src/starkware/starkware_utils/commitment_tree/binary_fact_tree.py index 4e87ae17..d2ed6039 100644 --- a/src/starkware/starkware_utils/commitment_tree/binary_fact_tree.py +++ b/src/starkware/starkware_utils/commitment_tree/binary_fact_tree.py @@ -2,17 +2,18 @@ from dataclasses import field from importlib import import_module from logging import Logger -from typing import Collection, Dict, Optional, Tuple, Type +from typing import Collection, Dict, Optional, Tuple, Type, TypeVar import marshmallow_dataclass from starkware.starkware_utils.commitment_tree.inner_node_fact import InnerNodeFact from starkware.starkware_utils.commitment_tree.leaf_fact import LeafFact, TLeafFact +from starkware.starkware_utils.marshmallow_fields_metadata import bytes_as_hex_metadata from starkware.starkware_utils.validated_dataclass import ValidatedMarshmallowDataclass -from starkware.starkware_utils.validated_fields import bytes_as_hex_metadata from starkware.storage.storage import FactFetchingContext BinaryFactDict = Dict[int, Tuple[int, ...]] +TBinaryFactTree = TypeVar("TBinaryFactTree", bound="BinaryFactTree") # Mypy has a problem with dataclasses that contain unimplemented abstract methods. diff --git a/src/starkware/starkware_utils/commitment_tree/binary_fact_tree_da_utils.py b/src/starkware/starkware_utils/commitment_tree/binary_fact_tree_da_utils.py index ae28bee1..89337669 100644 --- a/src/starkware/starkware_utils/commitment_tree/binary_fact_tree_da_utils.py +++ b/src/starkware/starkware_utils/commitment_tree/binary_fact_tree_da_utils.py @@ -4,8 +4,8 @@ from starkware.python.utils import from_bytes from starkware.starkware_utils.commitment_tree.binary_fact_tree import BinaryFactTree +from starkware.starkware_utils.marshmallow_fields_metadata import int_as_hex_metadata from starkware.starkware_utils.validated_dataclass import ValidatedDataclass -from starkware.starkware_utils.validated_fields import int_as_hex_metadata TBinaryFactTreeDiff = TypeVar("TBinaryFactTreeDiff", bound="BinaryFactTreeDiffBase") diff --git a/src/starkware/starkware_utils/commitment_tree/calculation.py b/src/starkware/starkware_utils/commitment_tree/calculation.py index dda69644..ef008278 100644 --- a/src/starkware/starkware_utils/commitment_tree/calculation.py +++ b/src/starkware/starkware_utils/commitment_tree/calculation.py @@ -1,21 +1,39 @@ import asyncio import dataclasses +import itertools from abc import ABC, abstractmethod from concurrent.futures import Executor -from typing import Any, Dict, Generic, List, Optional, Tuple, Type, TypeVar +from typing import Any, Dict, Generic, Iterable, List, Optional, Tuple, Type, TypeVar from starkware.starkware_utils.commitment_tree.binary_fact_tree import BinaryFactDict from starkware.starkware_utils.commitment_tree.binary_fact_tree_node import ( BinaryFactDict, TBinaryFactTreeNode, - TInnerNodeFact, ) +from starkware.starkware_utils.commitment_tree.inner_node_fact import InnerNodeFact from starkware.starkware_utils.commitment_tree.leaf_fact import LeafFact -from starkware.storage.storage import FactFetchingContext, HashFunctionType +from starkware.storage.storage import Fact, FactFetchingContext, HashFunctionType T = TypeVar("T") TCalculationNode = TypeVar("TCalculationNode", bound="CalculationNode") -NodeFactDict = Dict[bytes, TInnerNodeFact] + + +@dataclasses.dataclass +class NodeFactDict: + """ + A mapping between a hash and its corresponding fact. Split into two maps, one for leaves and + one for inner nodes. + """ + + inner_nodes: Dict[bytes, InnerNodeFact] = dataclasses.field(default_factory=dict) + leaves: Dict[bytes, LeafFact] = dataclasses.field(default_factory=dict) + + def update(self, other: "NodeFactDict"): + self.inner_nodes.update(other.inner_nodes) + self.leaves.update(other.leaves) + + def items(self) -> Iterable[Tuple[bytes, Fact]]: + return itertools.chain(self.inner_nodes.items(), self.leaves.items()) class Calculation(Generic[T], ABC): @@ -59,7 +77,7 @@ def calculate_new_fact_nodes( """ Same as calculate(), but return the facts. """ - fact_nodes: NodeFactDict = {} + fact_nodes = NodeFactDict() result = self.calculate( dependency_results=dependency_results, hash_func=hash_func, fact_nodes=fact_nodes ) @@ -97,7 +115,7 @@ def full_calculate_new_fact_nodes( Recursively calcuates the result of the dependency calculations. """ - fact_nodes: NodeFactDict = {} + fact_nodes = NodeFactDict() result = self.full_calculate(hash_func=hash_func, fact_nodes=fact_nodes) return result, fact_nodes @@ -186,7 +204,7 @@ def calculate( ) -> bytes: assert len(dependency_results) == 0, "LeafFactCalculation has no dependencies." hash_result = self.fact._hash(hash_func=hash_func) - fact_nodes[hash_result] = self.fact + fact_nodes.leaves[hash_result] = self.fact return hash_result def get_dependency_calculations(self) -> List[Calculation[bytes]]: diff --git a/src/starkware/starkware_utils/commitment_tree/patricia_tree/virtual_calculation_node.py b/src/starkware/starkware_utils/commitment_tree/patricia_tree/virtual_calculation_node.py index 70fd06db..96412149 100644 --- a/src/starkware/starkware_utils/commitment_tree/patricia_tree/virtual_calculation_node.py +++ b/src/starkware/starkware_utils/commitment_tree/patricia_tree/virtual_calculation_node.py @@ -42,7 +42,7 @@ def calculate( left_hash, right_hash = dependency_results fact = BinaryNodeFact(left_hash, right_hash) fact_hash = fact._hash(hash_func=hash_func) - fact_nodes[fact_hash] = fact + fact_nodes.inner_nodes[fact_hash] = fact return fact_hash @@ -64,7 +64,7 @@ def calculate( (bottom_hash,) = dependency_results fact = EdgeNodeFact(bottom_node=bottom_hash, edge_path=self.path, edge_length=self.length) fact_hash = fact._hash(hash_func=hash_func) - fact_nodes[fact_hash] = fact + fact_nodes.inner_nodes[fact_hash] = fact return fact_hash diff --git a/src/starkware/starkware_utils/commitment_tree/patricia_tree/virtual_calculation_node_test.py b/src/starkware/starkware_utils/commitment_tree/patricia_tree/virtual_calculation_node_test.py index 53bdaf7e..b9427641 100644 --- a/src/starkware/starkware_utils/commitment_tree/patricia_tree/virtual_calculation_node_test.py +++ b/src/starkware/starkware_utils/commitment_tree/patricia_tree/virtual_calculation_node_test.py @@ -1,6 +1,7 @@ import random import pytest +import pytest_asyncio from starkware.starkware_utils.commitment_tree.calculation import ConstantCalculation from starkware.starkware_utils.commitment_tree.patricia_tree.virtual_calculation_node import ( @@ -18,13 +19,13 @@ def ffc() -> FactFetchingContext: return FactFetchingContext(storage=MockStorage(), hash_func=hash_func) -@pytest.fixture +@pytest_asyncio.fixture async def leaf_calculation(ffc: FactFetchingContext) -> ConstantCalculation: leaf_hash = await SimpleLeafFact(value=random.randrange(1, 100)).set_fact(ffc=ffc) return ConstantCalculation(leaf_hash) -@pytest.fixture +@pytest_asyncio.fixture async def leaf_calculation2(ffc: FactFetchingContext) -> ConstantCalculation: leaf_hash = await SimpleLeafFact(value=random.randrange(100, 200)).set_fact(ffc=ffc) return ConstantCalculation(leaf_hash) diff --git a/src/starkware/starkware_utils/commitment_tree/update_tree.py b/src/starkware/starkware_utils/commitment_tree/update_tree.py index 1d807b66..c0903bd3 100644 --- a/src/starkware/starkware_utils/commitment_tree/update_tree.py +++ b/src/starkware/starkware_utils/commitment_tree/update_tree.py @@ -7,7 +7,6 @@ TBinaryFactTreeNode, ) from starkware.starkware_utils.commitment_tree.calculation import CalculationNode, NodeFactDict -from starkware.starkware_utils.commitment_tree.inner_node_fact import InnerNodeFact from starkware.starkware_utils.commitment_tree.leaf_fact import LeafFact from starkware.starkware_utils.commitment_tree.merkle_tree.traverse_tree import traverse_tree from starkware.starkware_utils.executor import executor_ctx_var @@ -51,7 +50,7 @@ async def update_tree( # 2. Node is a leaf update, and we just updated the leaf value. # 3. When its two children are already updated (happens in update_necessary()). updated_nodes: Dict[int, CalculationNode] = {} - new_facts: NodeFactDict = {} + new_facts = NodeFactDict() async def update_necessary(node_index: int): """ @@ -134,10 +133,9 @@ async def build_updated_calculation() -> CalculationNode: await write_fact_nodes(ffc=ffc, fact_nodes=new_facts) if facts is not None: - for fact_hash, node_fact in new_facts.items(): - # The leaves aren't stored in `facts`. Only nodes are stored there. - if isinstance(node_fact, InnerNodeFact): - facts[from_bytes(fact_hash)] = node_fact.to_tuple() + # The leaves aren't stored in `facts`. Only nodes are stored there. + for fact_hash, node_fact in new_facts.inner_nodes.items(): + facts[from_bytes(fact_hash)] = node_fact.to_tuple() return root_node diff --git a/src/starkware/starkware_utils/config_base.py b/src/starkware/starkware_utils/config_base.py index d31798b2..f956a9f9 100644 --- a/src/starkware/starkware_utils/config_base.py +++ b/src/starkware/starkware_utils/config_base.py @@ -53,7 +53,7 @@ def get_object_by_path(path: str) -> Any: class Config(ValidatedMarshmallowDataclass): @classmethod def load(cls: Type[TConfig], data: dict) -> TConfig: - config_instance = super().load(data) + config_instance = super().load(data=data) log_fields(config=config_instance) return config_instance diff --git a/src/starkware/starkware_utils/error_handling.py b/src/starkware/starkware_utils/error_handling.py index b8edddfe..cdf7da8f 100644 --- a/src/starkware/starkware_utils/error_handling.py +++ b/src/starkware/starkware_utils/error_handling.py @@ -1,8 +1,12 @@ import contextlib +import dataclasses import logging import operator from enum import Enum, auto -from typing import Any, Dict, List, Optional, Type +from types import TracebackType +from typing import Any, Callable, Dict, List, Optional, Type + +import marshmallow symbol_to_function = {"!=": operator.ne, "==": operator.eq, ">": operator.gt, ">=": operator.ge} @@ -54,6 +58,8 @@ class StarkErrorCode(ErrorCode): INVALID_FACT = auto() #: Fee taken is too high. INVALID_FEE_TAKEN = auto() + #: Invalid multi transaction. + INVALID_MULTI_TRANSACTION = auto() #: Invalid order ID. INVALID_ORDER_ID = auto() #: Invalid order type. @@ -102,6 +108,8 @@ class StarkErrorCode(ErrorCode): OUT_OF_RANGE_EXPIRATION_TIMESTAMP = auto() #: Field element value is out of range. OUT_OF_RANGE_FIELD_ELEMENT = auto() + #: Forced trade nonce value is out of range. + OUT_OF_RANGE_FORCED_TRADE_NONCE = auto() #: Nonce value is out of range. OUT_OF_RANGE_NONCE = auto() #: Oracle price quorum value is out of range. @@ -250,3 +258,64 @@ def wrap_with_stark_exception( logger.error(message, exc_info=True) raise StarkException(code=code, message=message) + + +@dataclasses.dataclass(frozen=True) +class ErrorByKey: + key_error: str + error: BaseException + + def __repr__(self) -> str: + return f"{{{self.key_error}: {repr(self.error)}}}" + + +class ErrorCollector: + """ + Context manager for collecting errors. + + For example: + for tx in txs: + with error_collector(key_error=tx.tx_id): + # Do something that might raise an exception. + assert len(error_collector.errors) == 0, str(error_collector.errors) + """ + + def __init__(self): + self.errors: List[ErrorByKey] = [] + + def __call__(self, key_error: str) -> "ErrorCollector": + self._element = key_error + return self + + def __enter__(self): + pass + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> bool: + if exc_type is not None: + assert exc_value is not None + self.errors.append(ErrorByKey(key_error=self._element, error=exc_value)) + return True + + +def stark_exception_dominant_in_validation_error( + stark_error_code: StarkErrorCode, +) -> Callable: + """ + A custom error-handling function for a marshmallow schema. Raises StarkException with the given + error code when either serialization or deserialization fails with any StarkException. + """ + + def handle_error(self, exc: marshmallow.ValidationError, data, **kwargs) -> None: + if "StarkException" in str(exc.messages): + raise StarkException( + code=stark_error_code, + message=f"Either serialization or deserialization error: {exc.messages}", + ) + raise exc + + return handle_error diff --git a/src/starkware/starkware_utils/field_validators.py b/src/starkware/starkware_utils/field_validators.py index 1e0ad715..2cc18544 100644 --- a/src/starkware/starkware_utils/field_validators.py +++ b/src/starkware/starkware_utils/field_validators.py @@ -4,7 +4,7 @@ import marshmallow import marshmallow.exceptions import marshmallow.validate -from web3 import Web3 +from eth_utils import is_checksum_address DNS_REGEX = r"^((\*)|(\*\.))?([a-z0-9-]){1,62}(\.[a-z0-9-]{1,62})*\.?$" @@ -81,6 +81,10 @@ def validate_url( url_name="Node endpoint", schemes={"http", "https"}, require_full_url=False ) +validate_alternative_endpoint = validate_url( + url_name="Alternative transactions endpoint", schemes={"http", "https"}, require_full_url=True +) + def validate_one_of( field_name: str, *, choices: Iterable, allow_none: bool = False @@ -219,7 +223,7 @@ def validator(addresses: Union[str, List[str]]): for address in addresses: validate_address_regex(address) - if not Web3.isChecksumAddress(address): + if not is_checksum_address(value=address): raise marshmallow.ValidationError(error_message.format(input=address)) return True @@ -236,6 +240,15 @@ def validate_private_key(field_name: str) -> ValidatorType: return marshmallow.validate.Regexp(regex=private_key_regex, error=error_message) +def validate_block_hash(field_name: str) -> ValidatorType: + error_message = "Invalid {field_name}: {{input}}; must be a legal Ethereum block hash".format( + field_name=field_name + ) + + private_key_regex = r"^0x[a-fA-F0-9]{64}$" + return marshmallow.validate.Regexp(regex=private_key_regex, error=error_message) + + def validate_customer_id(field_name: str) -> ValidatorType: error_message = "Invalid {field_name}: {{input}}; must be an alphanumeric string".format( field_name=field_name diff --git a/src/starkware/starkware_utils/marshmallow_dataclass_fields.py b/src/starkware/starkware_utils/marshmallow_dataclass_fields.py index def29aac..ae41c38d 100644 --- a/src/starkware/starkware_utils/marshmallow_dataclass_fields.py +++ b/src/starkware/starkware_utils/marshmallow_dataclass_fields.py @@ -12,6 +12,8 @@ from starkware.starkware_utils.custom_raising_dict import CustomRaisingDict, CustomRaisingFrozenDict +FieldMetadata = Dict[str, Any] + OptionalFloat: Callable[[VarArg(), KwArg()], mfields.Float] = functools.partial( mfields.Float, allow_none=True ) @@ -189,25 +191,60 @@ class CustomRaisingFrozenDictField(CustomField, mfields.Mapping): _type = CustomRaisingFrozenDict +# Utilities. + + +def load_int_value(field_metadata: FieldMetadata, value: str) -> int: + return field_metadata["marshmallow_field"]._deserialize(value=value, attr=None, data=None) + + +allowed_marshmallow_dataclass_keywords = {"marshmallow_field"} +allowed_marshmallow_keywords = { + "load_default", + "dump_default", + "data_key", + "attribute", + "validate", + "required", + "allow_none", + "load_only", + "dump_only", + "error_messages", + "metadata", + *allowed_marshmallow_dataclass_keywords, +} + + +def additional_metadata(**kwargs) -> FieldMetadata: + """ + Returns additional metadata for marshmallow field constructor. + All keywords that do not appear in allowed_marshmallow_keywords are moved to "metadata" + dictionary. + """ + disallowed_keywords = kwargs.keys() - allowed_marshmallow_keywords + disallowed_kwargs = {keyword: kwargs.pop(keyword) for keyword in disallowed_keywords} + + metadata: FieldMetadata = kwargs.setdefault("metadata", {}) + metadata.update(disallowed_kwargs) + + return kwargs + + # Field metadata for general use in marshmallow dataclasses. def enum_field_metadata( *, enum_class: type, require: bool = True, allow_none: bool = False -) -> dict: - return dict( +) -> FieldMetadata: + return additional_metadata( marshmallow_field=EnumField(enum_cls=enum_class, required=require, allow_none=allow_none) ) -boolean_field_metadata: Dict[str, Any] = dict(marshmallow_field=RequiredBoolean()) -optional_field_metadata: Dict[str, Any] = dict(allow_none=True, load_default=None) +boolean_field_metadata: FieldMetadata = additional_metadata(marshmallow_field=RequiredBoolean()) +optional_field_metadata: FieldMetadata = additional_metadata(allow_none=True, load_default=None) -nonrequired_optional_metadata: Dict[str, Any] = dict(load_default=None, required=False) -nonrequired_list_metadata: Dict[str, Any] = dict(load_default=list, required=False) - -# Utilities. - - -def load_int_value(field_metadata: Dict[str, Any], value: str) -> int: - return field_metadata["marshmallow_field"]._deserialize(value=value, attr=None, data=None) +nonrequired_optional_metadata: FieldMetadata = additional_metadata( + load_default=None, required=False +) +nonrequired_list_metadata: FieldMetadata = additional_metadata(load_default=list, required=False) diff --git a/src/starkware/starkware_utils/marshmallow_fields_metadata.py b/src/starkware/starkware_utils/marshmallow_fields_metadata.py new file mode 100644 index 00000000..8c854467 --- /dev/null +++ b/src/starkware/starkware_utils/marshmallow_fields_metadata.py @@ -0,0 +1,87 @@ +from typing import Any, Dict, Optional, Type + +import marshmallow.fields as mfields +import marshmallow.utils + +from starkware.starkware_utils.field_validators import validate_in_range +from starkware.starkware_utils.marshmallow_dataclass_fields import ( + BytesAsBase64Str, + BytesAsHex, + IntAsHex, + IntAsStr, +) +from starkware.starkware_utils.validated_fields import Field + + +def _generate_metadata( + marshmallow_field_cls: Type[mfields.Field], + validated_field: Optional[Field], + required: Optional[bool] = None, +) -> Dict[str, Any]: + if required is None: + required = True + + metadata: Dict[str, Any] = dict(marshmallow_field=marshmallow_field_cls(required=required)) + if validated_field is not None: + metadata.update(validated_field=validated_field) + + return metadata + + +def int_metadata( + validated_field: Optional[Field], required: Optional[bool] = None +) -> Dict[str, Any]: + return _generate_metadata( + marshmallow_field_cls=mfields.Integer, validated_field=validated_field, required=required + ) + + +def int_as_hex_metadata( + validated_field: Optional[Field], required: Optional[bool] = None +) -> Dict[str, Any]: + return _generate_metadata( + marshmallow_field_cls=IntAsHex, validated_field=validated_field, required=required + ) + + +def int_as_str_metadata( + validated_field: Optional[Field], required: Optional[bool] = None +) -> Dict[str, Any]: + return _generate_metadata( + marshmallow_field_cls=IntAsStr, validated_field=validated_field, required=required + ) + + +def bytes_as_hex_metadata( + validated_field: Optional[Field], required: Optional[bool] = None +) -> Dict[str, Any]: + return _generate_metadata( + marshmallow_field_cls=BytesAsHex, validated_field=validated_field, required=required + ) + + +def bytes_as_base64_str_metadata( + validated_field: Optional[Field], required: Optional[bool] = None +) -> Dict[str, Any]: + return _generate_metadata( + marshmallow_field_cls=BytesAsBase64Str, validated_field=validated_field, required=required + ) + + +def sequential_id_metadata( + field_name: str, + required: bool = True, + allow_previous_id: bool = False, + load_default: Any = marshmallow.utils.missing, +) -> Dict[str, Any]: + load_default_value = load_default() if callable(load_default) else load_default + validator = validate_in_range( + field_name=field_name, + min_value=-1 if allow_previous_id else 0, + allow_none=load_default_value is None, + ) + return dict( + marshmallow_field=mfields.Integer( + strict=True, required=required, validate=validator, load_default=load_default + ) + ) diff --git a/src/starkware/starkware_utils/time/synchronous_executor.py b/src/starkware/starkware_utils/time/synchronous_executor.py index be7fb252..44f8db20 100644 --- a/src/starkware/starkware_utils/time/synchronous_executor.py +++ b/src/starkware/starkware_utils/time/synchronous_executor.py @@ -16,7 +16,7 @@ def submit(self, fn, *args, **kwargs): if self._shutdown: raise RuntimeError("cannot schedule new futures after shutdown") - f = Future() + f: Future = Future() try: result = fn(*args, **kwargs) except BaseException as e: diff --git a/src/starkware/starkware_utils/validated_dataclass.py b/src/starkware/starkware_utils/validated_dataclass.py index 8ae4a877..a8be3b33 100644 --- a/src/starkware/starkware_utils/validated_dataclass.py +++ b/src/starkware/starkware_utils/validated_dataclass.py @@ -55,6 +55,9 @@ class Outer(ValidatedMarshmallowDataclass): """ new_object_data = {} for field in dataclasses.fields(cls): + if not field.init: + continue + # Fields with a value from the arguments. if field.name in data.keys(): new_object_data[field.name] = data[field.name] @@ -79,8 +82,8 @@ class Outer(ValidatedMarshmallowDataclass): continue # If the field was not supplied but there is a default value, use the default value. - if field.default is not dataclasses.MISSING: - new_object_data[field.name] = field.default + if has_default_value(attr_value=field): + new_object_data[field.name] = get_default_value(field=field) continue raise Exception( @@ -91,6 +94,10 @@ class Outer(ValidatedMarshmallowDataclass): def validate_values(self): for field in dataclasses.fields(self): + # init=False fields are ignored as they are not yet defined. + if non_init_with_default(field=field): + continue + metadata = getattr(field, "metadata", None) if metadata is None: continue @@ -109,6 +116,10 @@ def validate_values(self): def validate_types(self): for field in dataclasses.fields(self): + # init=False fields are ignored as they are not yet defined. + if non_init_with_default(field=field): + continue + typeguard.check_type( argname=field.name, value=getattr(self, field.name), expected_type=field.type ) @@ -224,7 +235,7 @@ def set_class_annotations_and_attribute_values( for name, attr_value in attr_values.items(): setattr(cls, name, attr_value) - if has_default_value(cls=cls, attr_value=attr_value): + if has_default_value(attr_value=attr_value): default_value_annotations[name] = annotations[name] # Locate members with default values in the end of the annotations dictionary. @@ -236,7 +247,7 @@ def set_class_annotations_and_attribute_values( cls.__annotations__.update(default_value_annotations) -def has_default_value(cls, attr_value: Any) -> bool: +def has_default_value(attr_value: Any) -> bool: """ Returns whether the class member has a default value or not. """ @@ -248,19 +259,37 @@ class A: """ return True - # If member does not appear in __init__'s signature, having a default value is irrelevant. return ( - attr_value.init - and attr_value.default is not dataclasses.MISSING - or + attr_value.default is not dataclasses.MISSING # Mypy has a problem with object members that are callables (it sees access to them as # passing self). This is actually originated in dataclasses' annotations in typeshed, since # the source code has no annotations. # See https://github.com/python/mypy/issues/6910 for details on this problem. - attr_value.default_factory is not dataclasses.MISSING # type: ignore + or attr_value.default_factory is not dataclasses.MISSING # type: ignore ) +def non_init_with_default(field: dataclasses.Field) -> bool: + # A field that that does not appear in the c-tor's signature but does have a default value is + # initialized with this value in the dataclass' c-tor. + return not field.init and not has_default_value(attr_value=field) + + +def get_default_value(field: dataclasses.Field) -> Any: + """ + Returns the default value for the given field if exists or dataclasses.MISSING otherwise. + In case of a default_factory function, returns the output of its call. + """ + if field.default is not dataclasses.MISSING: + return field.default + + # See https://github.com/python/mypy/issues/6910 for the mypy type-ignore cause. + if field.default_factory is not dataclasses.MISSING: # type: ignore + return field.default_factory() # type: ignore + + return dataclasses.MISSING + + # Validators for private use in this file. diff --git a/src/starkware/starkware_utils/validated_fields.py b/src/starkware/starkware_utils/validated_fields.py index 10ef23b4..de3eeba2 100644 --- a/src/starkware/starkware_utils/validated_fields.py +++ b/src/starkware/starkware_utils/validated_fields.py @@ -2,17 +2,16 @@ import random from abc import ABC, abstractmethod from dataclasses import field -from typing import Any, Callable, ClassVar, Dict, Generic, List, Optional, Type, TypeVar +from typing import Any, Callable, ClassVar, Dict, Generic, List, Optional, TypeVar import marshmallow.fields as mfields import marshmallow.utils from starkware.python.utils import get_random_bytes, initialize_random from starkware.starkware_utils.error_handling import ErrorCode, stark_assert -from starkware.starkware_utils.field_validators import validate_in_range from starkware.starkware_utils.marshmallow_dataclass_fields import ( - BytesAsBase64Str, BytesAsHex, + FieldMetadata, IntAsHex, IntAsStr, ) @@ -114,7 +113,7 @@ def metadata( field_name: Optional[str] = None, required: bool = True, load_default: Any = marshmallow.utils.missing, - ) -> Dict[str, Any]: + ) -> FieldMetadata: """ Creates the metadata associated with this field. If provided, then use the given field_name for messages, and otherwise (if it is None) use the default name. @@ -174,9 +173,28 @@ def format_invalid_value_error_message( return f"{name} is valid (None)." return self.field.format_invalid_value_error_message(value=value, name=name) - def get_marshmallow_field(self, required: bool, load_default: Any) -> mfields.Field: + # Metadata. + + def metadata( + self, + field_name: Optional[str] = None, + required: bool = False, + load_default: Any = None, + ) -> Dict[str, Any]: + """ + Creates the metadata associated with this optional field. + """ + assert not required, "Optional field must not be required." + assert load_default is None, "Optional field must have default value None." + return super().metadata(field_name=field_name, required=required, load_default=load_default) + + def get_marshmallow_field( + self, required: bool = False, load_default: Any = None + ) -> mfields.Field: + assert not required, "Optional field must not be required." + assert load_default is None, "Optional field must have default value None." # Field is created with allow_none=True if load_default is None. - return self.field.get_marshmallow_field(required=False, load_default=None) + return self.field.get_marshmallow_field(required=required, load_default=load_default) # Mypy has a problem with dataclasses that contain unimplemented abstract methods. @@ -206,7 +224,9 @@ def _format_value(self, value: int) -> str: return str(value) return self.formatter(value) - def get_marshmallow_field(self, required: bool, load_default: Any) -> mfields.Field: + def get_marshmallow_field( + self, required: bool = True, load_default: Any = marshmallow.utils.missing + ) -> mfields.Field: if self.formatter == hex: return IntAsHex(required=required, load_default=load_default) if self.formatter == str: @@ -296,86 +316,10 @@ def format_invalid_value_error_message(self, value: bytes, name: Optional[str] = return f"{name} {value_repr} length is not {self.length} bytes, instead it is {len(value)}" # Serialization. - def get_marshmallow_field(self, required: bool, load_default: Any) -> mfields.Field: + def get_marshmallow_field( + self, required: bool = True, load_default: Any = marshmallow.utils.missing + ) -> mfields.Field: return BytesAsHex(required=required, load_default=load_default) def format(self, value: bytes) -> str: return value.hex() - - -# Field metadata utilities. - - -def _generate_metadata( - marshmallow_field_cls: Type[mfields.Field], - validated_field: Optional[Field], - required: Optional[bool] = None, -) -> Dict[str, Any]: - if required is None: - required = True - - metadata: Dict[str, Any] = dict(marshmallow_field=marshmallow_field_cls(required=required)) - if validated_field is not None: - metadata.update(validated_field=validated_field) - - return metadata - - -def int_metadata( - validated_field: Optional[Field], required: Optional[bool] = None -) -> Dict[str, Any]: - return _generate_metadata( - marshmallow_field_cls=mfields.Integer, validated_field=validated_field, required=required - ) - - -def int_as_hex_metadata( - validated_field: Optional[Field], required: Optional[bool] = None -) -> Dict[str, Any]: - return _generate_metadata( - marshmallow_field_cls=IntAsHex, validated_field=validated_field, required=required - ) - - -def int_as_str_metadata( - validated_field: Optional[Field], required: Optional[bool] = None -) -> Dict[str, Any]: - return _generate_metadata( - marshmallow_field_cls=IntAsStr, validated_field=validated_field, required=required - ) - - -def bytes_as_hex_metadata( - validated_field: Optional[Field], required: Optional[bool] = None -) -> Dict[str, Any]: - return _generate_metadata( - marshmallow_field_cls=BytesAsHex, validated_field=validated_field, required=required - ) - - -def bytes_as_base64_str_metadata( - validated_field: Optional[Field], required: Optional[bool] = None -) -> Dict[str, Any]: - return _generate_metadata( - marshmallow_field_cls=BytesAsBase64Str, validated_field=validated_field, required=required - ) - - - -def sequential_id_metadata( - field_name: str, - required: bool = True, - allow_previous_id: bool = False, - load_default: Any = marshmallow.utils.missing, -) -> Dict[str, Any]: - load_default_value = load_default() if callable(load_default) else load_default - validator = validate_in_range( - field_name=field_name, - min_value=-1 if allow_previous_id else 0, - allow_none=load_default_value is None, - ) - return dict( - marshmallow_field=mfields.Integer( - strict=True, required=required, validate=validator, load_default=load_default - ) - ) diff --git a/src/starkware/storage/storage.py b/src/starkware/storage/storage.py index c5b25795..d705957b 100644 --- a/src/starkware/storage/storage.py +++ b/src/starkware/storage/storage.py @@ -434,11 +434,23 @@ async def from_config_context(config, logger=None): @abstractmethod async def lock(self, name: str) -> LockObject: - pass + """ + Creates a lock object. + """ + + @abstractmethod + async def lock_exists(self, name: str) -> bool: + """ + Returns True iff lock object is exists. + """ @abstractmethod async def try_lock(self, name: str, ttl: int = None) -> LockObject: - pass + """ + Tries to create a lock object. + """ async def destroy(self): - pass + """ + Closes the LockManager. + """ diff --git a/src/starkware/storage/storage_test.py b/src/starkware/storage/storage_test.py index 936966d3..3c425124 100644 --- a/src/starkware/storage/storage_test.py +++ b/src/starkware/storage/storage_test.py @@ -23,6 +23,9 @@ async def try_lock1(): async with await lock_manager.lock("lock1") as lock: # Try to lock. t = asyncio.create_task(try_lock1()) + + # Check that lock exists. + assert await lock_manager.lock_exists("lock0") await asyncio.sleep(0.01) assert locked[0] is False await asyncio.sleep(0.01) diff --git a/src/starkware/storage/test_utils.py b/src/starkware/storage/test_utils.py index 7acf0931..9fa5f694 100644 --- a/src/starkware/storage/test_utils.py +++ b/src/starkware/storage/test_utils.py @@ -36,6 +36,9 @@ async def try_lock(self, name: str, ttl: int = None) -> DummyLockObject: raise LockError() return await self.lock(name) + async def lock_exists(self, name: str) -> bool: + return name in self.locked.keys() + async def lock(self, name: str) -> DummyLockObject: while name in self.locked: await self.locked[name]