@aztec/simulator 0.0.0-test.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -0
- package/dest/client.d.ts +5 -0
- package/dest/client.d.ts.map +1 -0
- package/dest/client.js +3 -0
- package/dest/common/db_interfaces.d.ts +80 -0
- package/dest/common/db_interfaces.d.ts.map +1 -0
- package/dest/common/db_interfaces.js +1 -0
- package/dest/common/debug_fn_name.d.ts +5 -0
- package/dest/common/debug_fn_name.d.ts.map +1 -0
- package/dest/common/debug_fn_name.js +6 -0
- package/dest/common/errors.d.ts +54 -0
- package/dest/common/errors.d.ts.map +1 -0
- package/dest/common/errors.js +135 -0
- package/dest/common/index.d.ts +4 -0
- package/dest/common/index.d.ts.map +1 -0
- package/dest/common/index.js +3 -0
- package/dest/common/message_load_oracle_inputs.d.ts +15 -0
- package/dest/common/message_load_oracle_inputs.d.ts.map +1 -0
- package/dest/common/message_load_oracle_inputs.js +15 -0
- package/dest/common/stats/index.d.ts +2 -0
- package/dest/common/stats/index.d.ts.map +1 -0
- package/dest/common/stats/index.js +1 -0
- package/dest/common/stats/stats.d.ts +4 -0
- package/dest/common/stats/stats.d.ts.map +1 -0
- package/dest/common/stats/stats.js +10 -0
- package/dest/private/acvm/acvm.d.ts +35 -0
- package/dest/private/acvm/acvm.d.ts.map +1 -0
- package/dest/private/acvm/acvm.js +70 -0
- package/dest/private/acvm/acvm_types.d.ts +10 -0
- package/dest/private/acvm/acvm_types.d.ts.map +1 -0
- package/dest/private/acvm/acvm_types.js +3 -0
- package/dest/private/acvm/deserialize.d.ts +36 -0
- package/dest/private/acvm/deserialize.d.ts.map +1 -0
- package/dest/private/acvm/deserialize.js +42 -0
- package/dest/private/acvm/index.d.ts +6 -0
- package/dest/private/acvm/index.d.ts.map +1 -0
- package/dest/private/acvm/index.js +5 -0
- package/dest/private/acvm/oracle/index.d.ts +14 -0
- package/dest/private/acvm/oracle/index.d.ts.map +1 -0
- package/dest/private/acvm/oracle/index.js +2 -0
- package/dest/private/acvm/oracle/oracle.d.ts +49 -0
- package/dest/private/acvm/oracle/oracle.d.ts.map +1 -0
- package/dest/private/acvm/oracle/oracle.js +263 -0
- package/dest/private/acvm/oracle/typed_oracle.d.ts +83 -0
- package/dest/private/acvm/oracle/typed_oracle.d.ts.map +1 -0
- package/dest/private/acvm/oracle/typed_oracle.js +132 -0
- package/dest/private/acvm/serialize.d.ts +24 -0
- package/dest/private/acvm/serialize.d.ts.map +1 -0
- package/dest/private/acvm/serialize.js +46 -0
- package/dest/private/execution_data_provider.d.ts +261 -0
- package/dest/private/execution_data_provider.d.ts.map +1 -0
- package/dest/private/execution_data_provider.js +14 -0
- package/dest/private/execution_note_cache.d.ts +93 -0
- package/dest/private/execution_note_cache.d.ts.map +1 -0
- package/dest/private/execution_note_cache.js +180 -0
- package/dest/private/hashed_values_cache.d.ts +28 -0
- package/dest/private/hashed_values_cache.d.ts.map +1 -0
- package/dest/private/hashed_values_cache.js +46 -0
- package/dest/private/index.d.ts +13 -0
- package/dest/private/index.d.ts.map +1 -0
- package/dest/private/index.js +12 -0
- package/dest/private/pick_notes.d.ts +85 -0
- package/dest/private/pick_notes.d.ts.map +1 -0
- package/dest/private/pick_notes.js +51 -0
- package/dest/private/private_execution.d.ts +25 -0
- package/dest/private/private_execution.d.ts.map +1 -0
- package/dest/private/private_execution.js +92 -0
- package/dest/private/private_execution_oracle.d.ts +215 -0
- package/dest/private/private_execution_oracle.d.ts.map +1 -0
- package/dest/private/private_execution_oracle.js +382 -0
- package/dest/private/providers/acvm_native.d.ts +40 -0
- package/dest/private/providers/acvm_native.d.ts.map +1 -0
- package/dest/private/providers/acvm_native.js +139 -0
- package/dest/private/providers/acvm_wasm.d.ts +15 -0
- package/dest/private/providers/acvm_wasm.d.ts.map +1 -0
- package/dest/private/providers/acvm_wasm.js +62 -0
- package/dest/private/providers/acvm_wasm_with_blobs.d.ts +19 -0
- package/dest/private/providers/acvm_wasm_with_blobs.d.ts.map +1 -0
- package/dest/private/providers/acvm_wasm_with_blobs.js +32 -0
- package/dest/private/providers/factory.d.ts +12 -0
- package/dest/private/providers/factory.d.ts.map +1 -0
- package/dest/private/providers/factory.js +27 -0
- package/dest/private/providers/simulation_provider.d.ts +19 -0
- package/dest/private/providers/simulation_provider.d.ts.map +1 -0
- package/dest/private/providers/simulation_provider.js +24 -0
- package/dest/private/simulator.d.ts +34 -0
- package/dest/private/simulator.d.ts.map +1 -0
- package/dest/private/simulator.js +76 -0
- package/dest/private/unconstrained_execution.d.ts +10 -0
- package/dest/private/unconstrained_execution.d.ts.map +1 -0
- package/dest/private/unconstrained_execution.js +27 -0
- package/dest/private/unconstrained_execution_oracle.d.ts +161 -0
- package/dest/private/unconstrained_execution_oracle.d.ts.map +1 -0
- package/dest/private/unconstrained_execution_oracle.js +258 -0
- package/dest/public/avm/avm_context.d.ts +41 -0
- package/dest/public/avm/avm_context.d.ts.map +1 -0
- package/dest/public/avm/avm_context.js +44 -0
- package/dest/public/avm/avm_contract_call_result.d.ts +30 -0
- package/dest/public/avm/avm_contract_call_result.d.ts.map +1 -0
- package/dest/public/avm/avm_contract_call_result.js +50 -0
- package/dest/public/avm/avm_execution_environment.d.ts +21 -0
- package/dest/public/avm/avm_execution_environment.d.ts.map +1 -0
- package/dest/public/avm/avm_execution_environment.js +31 -0
- package/dest/public/avm/avm_gas.d.ts +60 -0
- package/dest/public/avm/avm_gas.d.ts.map +1 -0
- package/dest/public/avm/avm_gas.js +203 -0
- package/dest/public/avm/avm_machine_state.d.ts +95 -0
- package/dest/public/avm/avm_machine_state.d.ts.map +1 -0
- package/dest/public/avm/avm_machine_state.js +107 -0
- package/dest/public/avm/avm_memory_types.d.ts +264 -0
- package/dest/public/avm/avm_memory_types.d.ts.map +1 -0
- package/dest/public/avm/avm_memory_types.js +340 -0
- package/dest/public/avm/avm_simulator.d.ts +40 -0
- package/dest/public/avm/avm_simulator.d.ts.map +1 -0
- package/dest/public/avm/avm_simulator.js +202 -0
- package/dest/public/avm/bytecode_utils.d.ts +5 -0
- package/dest/public/avm/bytecode_utils.d.ts.map +1 -0
- package/dest/public/avm/bytecode_utils.js +17 -0
- package/dest/public/avm/errors.d.ts +122 -0
- package/dest/public/avm/errors.d.ts.map +1 -0
- package/dest/public/avm/errors.js +179 -0
- package/dest/public/avm/fixtures/avm_simulation_tester.d.ts +21 -0
- package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -0
- package/dest/public/avm/fixtures/avm_simulation_tester.js +76 -0
- package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts +36 -0
- package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -0
- package/dest/public/avm/fixtures/base_avm_simulation_tester.js +83 -0
- package/dest/public/avm/fixtures/index.d.ts +84 -0
- package/dest/public/avm/fixtures/index.d.ts.map +1 -0
- package/dest/public/avm/fixtures/index.js +175 -0
- package/dest/public/avm/fixtures/simple_contract_data_source.d.ts +35 -0
- package/dest/public/avm/fixtures/simple_contract_data_source.d.ts.map +1 -0
- package/dest/public/avm/fixtures/simple_contract_data_source.js +74 -0
- package/dest/public/avm/index.d.ts +4 -0
- package/dest/public/avm/index.d.ts.map +1 -0
- package/dest/public/avm/index.js +3 -0
- package/dest/public/avm/journal/index.d.ts +2 -0
- package/dest/public/avm/journal/index.d.ts.map +1 -0
- package/dest/public/avm/journal/index.js +1 -0
- package/dest/public/avm/journal/journal.d.ts +209 -0
- package/dest/public/avm/journal/journal.d.ts.map +1 -0
- package/dest/public/avm/journal/journal.js +486 -0
- package/dest/public/avm/journal/nullifiers.d.ts +64 -0
- package/dest/public/avm/journal/nullifiers.d.ts.map +1 -0
- package/dest/public/avm/journal/nullifiers.js +97 -0
- package/dest/public/avm/journal/public_storage.d.ts +66 -0
- package/dest/public/avm/journal/public_storage.d.ts.map +1 -0
- package/dest/public/avm/journal/public_storage.js +145 -0
- package/dest/public/avm/opcodes/accrued_substate.d.ts +75 -0
- package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -0
- package/dest/public/avm/opcodes/accrued_substate.js +252 -0
- package/dest/public/avm/opcodes/addressing_mode.d.ts +27 -0
- package/dest/public/avm/opcodes/addressing_mode.d.ts.map +1 -0
- package/dest/public/avm/opcodes/addressing_mode.js +74 -0
- package/dest/public/avm/opcodes/arithmetic.d.ts +37 -0
- package/dest/public/avm/opcodes/arithmetic.d.ts.map +1 -0
- package/dest/public/avm/opcodes/arithmetic.js +73 -0
- package/dest/public/avm/opcodes/bitwise.d.ts +50 -0
- package/dest/public/avm/opcodes/bitwise.d.ts.map +1 -0
- package/dest/public/avm/opcodes/bitwise.js +106 -0
- package/dest/public/avm/opcodes/comparators.d.ts +25 -0
- package/dest/public/avm/opcodes/comparators.d.ts.map +1 -0
- package/dest/public/avm/opcodes/comparators.js +43 -0
- package/dest/public/avm/opcodes/contract.d.ts +21 -0
- package/dest/public/avm/opcodes/contract.d.ts.map +1 -0
- package/dest/public/avm/opcodes/contract.js +66 -0
- package/dest/public/avm/opcodes/control_flow.d.ts +41 -0
- package/dest/public/avm/opcodes/control_flow.d.ts.map +1 -0
- package/dest/public/avm/opcodes/control_flow.js +105 -0
- package/dest/public/avm/opcodes/conversion.d.ts +17 -0
- package/dest/public/avm/opcodes/conversion.d.ts.map +1 -0
- package/dest/public/avm/opcodes/conversion.js +69 -0
- package/dest/public/avm/opcodes/ec_add.d.ts +19 -0
- package/dest/public/avm/opcodes/ec_add.d.ts.map +1 -0
- package/dest/public/avm/opcodes/ec_add.js +84 -0
- package/dest/public/avm/opcodes/environment_getters.d.ts +28 -0
- package/dest/public/avm/opcodes/environment_getters.d.ts.map +1 -0
- package/dest/public/avm/opcodes/environment_getters.js +79 -0
- package/dest/public/avm/opcodes/external_calls.d.ts +58 -0
- package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -0
- package/dest/public/avm/opcodes/external_calls.js +204 -0
- package/dest/public/avm/opcodes/hashing.d.ts +36 -0
- package/dest/public/avm/opcodes/hashing.d.ts.map +1 -0
- package/dest/public/avm/opcodes/hashing.js +114 -0
- package/dest/public/avm/opcodes/index.d.ts +16 -0
- package/dest/public/avm/opcodes/index.d.ts.map +1 -0
- package/dest/public/avm/opcodes/index.js +15 -0
- package/dest/public/avm/opcodes/instruction.d.ts +70 -0
- package/dest/public/avm/opcodes/instruction.d.ts.map +1 -0
- package/dest/public/avm/opcodes/instruction.js +91 -0
- package/dest/public/avm/opcodes/instruction_impl.d.ts +19 -0
- package/dest/public/avm/opcodes/instruction_impl.d.ts.map +1 -0
- package/dest/public/avm/opcodes/instruction_impl.js +30 -0
- package/dest/public/avm/opcodes/memory.d.ts +74 -0
- package/dest/public/avm/opcodes/memory.d.ts.map +1 -0
- package/dest/public/avm/opcodes/memory.js +253 -0
- package/dest/public/avm/opcodes/misc.d.ts +17 -0
- package/dest/public/avm/opcodes/misc.d.ts.map +1 -0
- package/dest/public/avm/opcodes/misc.js +48 -0
- package/dest/public/avm/opcodes/storage.d.ts +24 -0
- package/dest/public/avm/opcodes/storage.d.ts.map +1 -0
- package/dest/public/avm/opcodes/storage.js +66 -0
- package/dest/public/avm/serialization/buffer_cursor.d.ts +28 -0
- package/dest/public/avm/serialization/buffer_cursor.d.ts.map +1 -0
- package/dest/public/avm/serialization/buffer_cursor.js +99 -0
- package/dest/public/avm/serialization/bytecode_serialization.d.ts +21 -0
- package/dest/public/avm/serialization/bytecode_serialization.d.ts.map +1 -0
- package/dest/public/avm/serialization/bytecode_serialization.js +332 -0
- package/dest/public/avm/serialization/instruction_serialization.d.ts +105 -0
- package/dest/public/avm/serialization/instruction_serialization.d.ts.map +1 -0
- package/dest/public/avm/serialization/instruction_serialization.js +226 -0
- package/dest/public/avm/test_utils.d.ts +18 -0
- package/dest/public/avm/test_utils.d.ts.map +1 -0
- package/dest/public/avm/test_utils.js +52 -0
- package/dest/public/bytecode_errors.d.ts +4 -0
- package/dest/public/bytecode_errors.d.ts.map +1 -0
- package/dest/public/bytecode_errors.js +6 -0
- package/dest/public/execution.d.ts +108 -0
- package/dest/public/execution.d.ts.map +1 -0
- package/dest/public/execution.js +9 -0
- package/dest/public/executor_metrics.d.ts +13 -0
- package/dest/public/executor_metrics.d.ts.map +1 -0
- package/dest/public/executor_metrics.js +54 -0
- package/dest/public/fixtures/index.d.ts +3 -0
- package/dest/public/fixtures/index.d.ts.map +1 -0
- package/dest/public/fixtures/index.js +2 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +32 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -0
- package/dest/public/fixtures/public_tx_simulation_tester.js +93 -0
- package/dest/public/fixtures/utils.d.ts +13 -0
- package/dest/public/fixtures/utils.d.ts.map +1 -0
- package/dest/public/fixtures/utils.js +126 -0
- package/dest/public/index.d.ts +10 -0
- package/dest/public/index.d.ts.map +1 -0
- package/dest/public/index.js +8 -0
- package/dest/public/public_db_sources.d.ts +129 -0
- package/dest/public/public_db_sources.d.ts.map +1 -0
- package/dest/public/public_db_sources.js +264 -0
- package/dest/public/public_processor/public_processor.d.ts +74 -0
- package/dest/public/public_processor/public_processor.d.ts.map +1 -0
- package/dest/public/public_processor/public_processor.js +379 -0
- package/dest/public/public_processor/public_processor_metrics.d.ts +27 -0
- package/dest/public/public_processor/public_processor_metrics.d.ts.map +1 -0
- package/dest/public/public_processor/public_processor_metrics.js +125 -0
- package/dest/public/public_tx_simulator/public_tx_context.d.ts +137 -0
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/public_tx_context.js +320 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +102 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.js +334 -0
- package/dest/public/side_effect_errors.d.ts +4 -0
- package/dest/public/side_effect_errors.d.ts.map +1 -0
- package/dest/public/side_effect_errors.js +6 -0
- package/dest/public/side_effect_trace.d.ts +132 -0
- package/dest/public/side_effect_trace.d.ts.map +1 -0
- package/dest/public/side_effect_trace.js +249 -0
- package/dest/public/side_effect_trace_interface.d.ts +34 -0
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -0
- package/dest/public/side_effect_trace_interface.js +1 -0
- package/dest/public/tx_contract_cache.d.ts +41 -0
- package/dest/public/tx_contract_cache.d.ts.map +1 -0
- package/dest/public/tx_contract_cache.js +49 -0
- package/dest/public/unique_class_ids.d.ts +37 -0
- package/dest/public/unique_class_ids.d.ts.map +1 -0
- package/dest/public/unique_class_ids.js +61 -0
- package/dest/public/utils.d.ts +5 -0
- package/dest/public/utils.d.ts.map +1 -0
- package/dest/public/utils.js +35 -0
- package/dest/server.d.ts +6 -0
- package/dest/server.d.ts.map +1 -0
- package/dest/server.js +4 -0
- package/dest/test/utils.d.ts +13 -0
- package/dest/test/utils.d.ts.map +1 -0
- package/dest/test/utils.js +22 -0
- package/package.json +104 -0
- package/src/client.ts +4 -0
- package/src/common/db_interfaces.ts +94 -0
- package/src/common/debug_fn_name.ts +18 -0
- package/src/common/errors.ts +183 -0
- package/src/common/index.ts +3 -0
- package/src/common/message_load_oracle_inputs.ts +15 -0
- package/src/common/stats/index.ts +1 -0
- package/src/common/stats/stats.ts +20 -0
- package/src/private/acvm/acvm.ts +127 -0
- package/src/private/acvm/acvm_types.ts +11 -0
- package/src/private/acvm/deserialize.ts +52 -0
- package/src/private/acvm/index.ts +5 -0
- package/src/private/acvm/oracle/index.ts +16 -0
- package/src/private/acvm/oracle/oracle.ts +455 -0
- package/src/private/acvm/oracle/typed_oracle.ts +259 -0
- package/src/private/acvm/serialize.ts +60 -0
- package/src/private/execution_data_provider.ts +323 -0
- package/src/private/execution_note_cache.ts +217 -0
- package/src/private/hashed_values_cache.ts +55 -0
- package/src/private/index.ts +16 -0
- package/src/private/pick_notes.ts +141 -0
- package/src/private/private_execution.ts +151 -0
- package/src/private/private_execution_oracle.ts +614 -0
- package/src/private/providers/acvm_native.ts +171 -0
- package/src/private/providers/acvm_wasm.ts +63 -0
- package/src/private/providers/acvm_wasm_with_blobs.ts +50 -0
- package/src/private/providers/factory.ts +38 -0
- package/src/private/providers/simulation_provider.ts +45 -0
- package/src/private/simulator.ts +147 -0
- package/src/private/unconstrained_execution.ts +50 -0
- package/src/private/unconstrained_execution_oracle.ts +373 -0
- package/src/public/avm/avm_context.ts +61 -0
- package/src/public/avm/avm_contract_call_result.ts +55 -0
- package/src/public/avm/avm_execution_environment.ts +39 -0
- package/src/public/avm/avm_gas.ts +195 -0
- package/src/public/avm/avm_machine_state.ts +164 -0
- package/src/public/avm/avm_memory_types.ts +423 -0
- package/src/public/avm/avm_simulator.ts +284 -0
- package/src/public/avm/bytecode_utils.ts +17 -0
- package/src/public/avm/errors.ts +232 -0
- package/src/public/avm/fixtures/avm_simulation_tester.ts +105 -0
- package/src/public/avm/fixtures/base_avm_simulation_tester.ts +109 -0
- package/src/public/avm/fixtures/index.ts +296 -0
- package/src/public/avm/fixtures/simple_contract_data_source.ts +105 -0
- package/src/public/avm/index.ts +3 -0
- package/src/public/avm/journal/index.ts +1 -0
- package/src/public/avm/journal/journal.ts +742 -0
- package/src/public/avm/journal/nullifiers.ts +109 -0
- package/src/public/avm/journal/public_storage.ts +174 -0
- package/src/public/avm/opcodes/.eslintrc.cjs +8 -0
- package/src/public/avm/opcodes/accrued_substate.ts +253 -0
- package/src/public/avm/opcodes/addressing_mode.ts +87 -0
- package/src/public/avm/opcodes/arithmetic.ts +95 -0
- package/src/public/avm/opcodes/bitwise.ts +109 -0
- package/src/public/avm/opcodes/comparators.ts +52 -0
- package/src/public/avm/opcodes/contract.ts +72 -0
- package/src/public/avm/opcodes/control_flow.ts +114 -0
- package/src/public/avm/opcodes/conversion.ts +80 -0
- package/src/public/avm/opcodes/ec_add.ts +93 -0
- package/src/public/avm/opcodes/environment_getters.ts +82 -0
- package/src/public/avm/opcodes/external_calls.ts +228 -0
- package/src/public/avm/opcodes/hashing.ts +125 -0
- package/src/public/avm/opcodes/index.ts +15 -0
- package/src/public/avm/opcodes/instruction.ts +126 -0
- package/src/public/avm/opcodes/instruction_impl.ts +36 -0
- package/src/public/avm/opcodes/memory.ts +254 -0
- package/src/public/avm/opcodes/misc.ts +60 -0
- package/src/public/avm/opcodes/storage.ts +71 -0
- package/src/public/avm/serialization/buffer_cursor.ts +115 -0
- package/src/public/avm/serialization/bytecode_serialization.ts +206 -0
- package/src/public/avm/serialization/instruction_serialization.ts +208 -0
- package/src/public/avm/test_utils.ts +81 -0
- package/src/public/bytecode_errors.ts +6 -0
- package/src/public/execution.ts +140 -0
- package/src/public/executor_metrics.ts +71 -0
- package/src/public/fixtures/index.ts +2 -0
- package/src/public/fixtures/public_tx_simulation_tester.ts +179 -0
- package/src/public/fixtures/utils.ts +199 -0
- package/src/public/index.ts +9 -0
- package/src/public/public_db_sources.ts +369 -0
- package/src/public/public_processor/public_processor.ts +521 -0
- package/src/public/public_processor/public_processor_metrics.ts +154 -0
- package/src/public/public_tx_simulator/public_tx_context.ts +504 -0
- package/src/public/public_tx_simulator/public_tx_simulator.ts +474 -0
- package/src/public/side_effect_errors.ts +6 -0
- package/src/public/side_effect_trace.ts +516 -0
- package/src/public/side_effect_trace_interface.ts +76 -0
- package/src/public/tx_contract_cache.ts +69 -0
- package/src/public/unique_class_ids.ts +80 -0
- package/src/public/utils.ts +32 -0
- package/src/server.ts +5 -0
- package/src/test/utils.ts +36 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MEM_TAG_FF,
|
|
3
|
+
MEM_TAG_U1,
|
|
4
|
+
MEM_TAG_U8,
|
|
5
|
+
MEM_TAG_U16,
|
|
6
|
+
MEM_TAG_U32,
|
|
7
|
+
MEM_TAG_U64,
|
|
8
|
+
MEM_TAG_U128,
|
|
9
|
+
} from '@aztec/constants';
|
|
10
|
+
import { toBufferBE } from '@aztec/foundation/bigint-buffer';
|
|
11
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
12
|
+
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
13
|
+
import type { FunctionsOf } from '@aztec/foundation/types';
|
|
14
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
15
|
+
|
|
16
|
+
import { strict as assert } from 'assert';
|
|
17
|
+
|
|
18
|
+
import { InvalidTagValueError, MemorySliceOutOfRangeError, TagCheckError } from './errors.js';
|
|
19
|
+
|
|
20
|
+
/** MemoryValue gathers the common operations for all memory types. */
|
|
21
|
+
export abstract class MemoryValue {
|
|
22
|
+
public abstract add(rhs: MemoryValue): MemoryValue;
|
|
23
|
+
public abstract sub(rhs: MemoryValue): MemoryValue;
|
|
24
|
+
public abstract mul(rhs: MemoryValue): MemoryValue;
|
|
25
|
+
public abstract div(rhs: MemoryValue): MemoryValue;
|
|
26
|
+
|
|
27
|
+
public abstract equals(rhs: MemoryValue): boolean;
|
|
28
|
+
public abstract lt(rhs: MemoryValue): boolean;
|
|
29
|
+
|
|
30
|
+
// We need this to be able to build an instance of the subclasses.
|
|
31
|
+
public abstract build(n: bigint): MemoryValue;
|
|
32
|
+
|
|
33
|
+
// Use sparingly.
|
|
34
|
+
public abstract toBigInt(): bigint;
|
|
35
|
+
|
|
36
|
+
// To Buffer
|
|
37
|
+
public abstract toBuffer(): Buffer;
|
|
38
|
+
|
|
39
|
+
// To field
|
|
40
|
+
public toFr(): Fr {
|
|
41
|
+
return new Fr(this.toBigInt());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public toAztecAddress(): AztecAddress {
|
|
45
|
+
return new AztecAddress(this.toFr());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// To number. Throws if exceeds max safe int.
|
|
49
|
+
public toNumber(): number {
|
|
50
|
+
return this.toFr().toNumber();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public toString(): string {
|
|
54
|
+
return `${this.constructor.name}(0x${this.toBigInt().toString(16)})`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** IntegralValue gathers the common operations for all integral memory types. */
|
|
59
|
+
export abstract class IntegralValue extends MemoryValue {
|
|
60
|
+
public abstract shl(rhs: IntegralValue): IntegralValue;
|
|
61
|
+
public abstract shr(rhs: IntegralValue): IntegralValue;
|
|
62
|
+
public abstract and(rhs: IntegralValue): IntegralValue;
|
|
63
|
+
public abstract or(rhs: IntegralValue): IntegralValue;
|
|
64
|
+
public abstract xor(rhs: IntegralValue): IntegralValue;
|
|
65
|
+
public abstract not(): IntegralValue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* This function creates a class for unsigned integers of a given number of bits.
|
|
70
|
+
* In TypeScript terms, it's a class mixin.
|
|
71
|
+
**/
|
|
72
|
+
function UnsignedIntegerClassFactory(bits: number) {
|
|
73
|
+
return class NewUintClass extends IntegralValue {
|
|
74
|
+
static readonly mod: bigint = 1n << BigInt(bits);
|
|
75
|
+
static readonly bitmask: bigint = this.mod - 1n;
|
|
76
|
+
public readonly n: bigint; // Cannot be private due to TS limitations.
|
|
77
|
+
|
|
78
|
+
public constructor(n: bigint | number) {
|
|
79
|
+
super();
|
|
80
|
+
this.n = BigInt(n);
|
|
81
|
+
assert(n < NewUintClass.mod, `Value ${n} is too large for ${this.constructor.name}.`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public build(n: bigint): NewUintClass {
|
|
85
|
+
return new this.constructor.prototype.constructor(n);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public add(rhs: NewUintClass): NewUintClass {
|
|
89
|
+
return this.build((this.n + rhs.n) & NewUintClass.bitmask);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public sub(rhs: NewUintClass): NewUintClass {
|
|
93
|
+
const res: bigint = this.n - rhs.n;
|
|
94
|
+
return this.build(res >= 0 ? res : res + NewUintClass.mod);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public mul(rhs: NewUintClass): NewUintClass {
|
|
98
|
+
return this.build((this.n * rhs.n) & NewUintClass.bitmask);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public div(rhs: NewUintClass): NewUintClass {
|
|
102
|
+
return this.build(this.n / rhs.n);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// No sign extension.
|
|
106
|
+
public shr(rhs: NewUintClass): NewUintClass {
|
|
107
|
+
// Note that this.n is > 0 by class invariant.
|
|
108
|
+
return this.build(this.n >> rhs.n);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public shl(rhs: NewUintClass): NewUintClass {
|
|
112
|
+
return this.build((this.n << rhs.n) & NewUintClass.bitmask);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public and(rhs: NewUintClass): NewUintClass {
|
|
116
|
+
return this.build(this.n & rhs.n);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public or(rhs: NewUintClass): NewUintClass {
|
|
120
|
+
return this.build(this.n | rhs.n);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public xor(rhs: NewUintClass): NewUintClass {
|
|
124
|
+
return this.build(this.n ^ rhs.n);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public not(): NewUintClass {
|
|
128
|
+
return this.build(~this.n & NewUintClass.bitmask);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public equals(rhs: NewUintClass): boolean {
|
|
132
|
+
return this.n === rhs.n;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public lt(rhs: NewUintClass): boolean {
|
|
136
|
+
return this.n < rhs.n;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public toBigInt(): bigint {
|
|
140
|
+
return this.n;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public toBuffer(): Buffer {
|
|
144
|
+
if (bits < 8) {
|
|
145
|
+
return toBufferBE(this.n, 1);
|
|
146
|
+
}
|
|
147
|
+
return toBufferBE(this.n, bits / 8);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Now we can create the classes for each unsigned integer type.
|
|
153
|
+
// We extend instead of just assigning so that the class has the right name.
|
|
154
|
+
// Otherwise they are all called "NewUintClass".
|
|
155
|
+
export class Uint1 extends UnsignedIntegerClassFactory(1) {}
|
|
156
|
+
export class Uint8 extends UnsignedIntegerClassFactory(8) {}
|
|
157
|
+
export class Uint16 extends UnsignedIntegerClassFactory(16) {}
|
|
158
|
+
export class Uint32 extends UnsignedIntegerClassFactory(32) {}
|
|
159
|
+
export class Uint64 extends UnsignedIntegerClassFactory(64) {}
|
|
160
|
+
export class Uint128 extends UnsignedIntegerClassFactory(128) {}
|
|
161
|
+
|
|
162
|
+
export class Field extends MemoryValue {
|
|
163
|
+
public static readonly MODULUS: bigint = Fr.MODULUS;
|
|
164
|
+
private readonly rep: Fr;
|
|
165
|
+
|
|
166
|
+
constructor(v: number | bigint | Fr | Buffer) {
|
|
167
|
+
super();
|
|
168
|
+
this.rep = new Fr(v);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public build(n: bigint): Field {
|
|
172
|
+
return new Field(n);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public add(rhs: Field): Field {
|
|
176
|
+
return new Field(this.rep.add(rhs.rep));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public sub(rhs: Field): Field {
|
|
180
|
+
return new Field(this.rep.sub(rhs.rep));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public mul(rhs: Field): Field {
|
|
184
|
+
return new Field(this.rep.mul(rhs.rep));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Euclidean division.
|
|
188
|
+
public div(rhs: Field): Field {
|
|
189
|
+
return new Field(this.rep.ediv(rhs.rep));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Field division.
|
|
193
|
+
public fdiv(rhs: Field): Field {
|
|
194
|
+
return new Field(this.rep.div(rhs.rep));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public equals(rhs: Field): boolean {
|
|
198
|
+
return this.rep.equals(rhs.rep);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
public lt(rhs: Field): boolean {
|
|
202
|
+
return this.rep.lt(rhs.rep);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
public toBigInt(): bigint {
|
|
206
|
+
return this.rep.toBigInt();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public toBuffer(): Buffer {
|
|
210
|
+
return this.rep.toBuffer();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export enum TypeTag {
|
|
215
|
+
FIELD = MEM_TAG_FF,
|
|
216
|
+
UINT1 = MEM_TAG_U1,
|
|
217
|
+
UINT8 = MEM_TAG_U8,
|
|
218
|
+
UINT16 = MEM_TAG_U16,
|
|
219
|
+
UINT32 = MEM_TAG_U32,
|
|
220
|
+
UINT64 = MEM_TAG_U64,
|
|
221
|
+
UINT128 = MEM_TAG_U128,
|
|
222
|
+
INVALID = MEM_TAG_U128 + 1,
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Lazy interface definition for tagged memory
|
|
226
|
+
export type TaggedMemoryInterface = FunctionsOf<TaggedMemory>;
|
|
227
|
+
|
|
228
|
+
export class TaggedMemory implements TaggedMemoryInterface {
|
|
229
|
+
static readonly log: Logger = createLogger('simulator:avm:memory');
|
|
230
|
+
|
|
231
|
+
// Whether to track and validate memory accesses for each instruction.
|
|
232
|
+
static readonly TRACK_MEMORY_ACCESSES = process.env.NODE_ENV === 'test';
|
|
233
|
+
|
|
234
|
+
// Memory is modelled by a map with key type being number.
|
|
235
|
+
// We however restrict the keys to be non-negative integers smaller than
|
|
236
|
+
// MAX_MEMORY_SIZE.
|
|
237
|
+
static readonly MAX_MEMORY_SIZE = Number(1n << 32n);
|
|
238
|
+
private _mem: Map<number, MemoryValue>;
|
|
239
|
+
|
|
240
|
+
constructor() {
|
|
241
|
+
this._mem = new Map<number, MemoryValue>();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
public getMaxMemorySize(): number {
|
|
245
|
+
return TaggedMemory.MAX_MEMORY_SIZE;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
public get(offset: number): MemoryValue {
|
|
249
|
+
return this.getAs<MemoryValue>(offset);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
public getAs<T>(offset: number): T {
|
|
253
|
+
assert(Number.isInteger(offset) && offset < TaggedMemory.MAX_MEMORY_SIZE);
|
|
254
|
+
const word = this._mem.get(offset);
|
|
255
|
+
//TaggedMemory.log.trace(`get(${offset}) = ${word}`);
|
|
256
|
+
if (word === undefined) {
|
|
257
|
+
TaggedMemory.log.debug(`WARNING: Memory at offset ${offset} is undefined!`);
|
|
258
|
+
return new Field(0) as T;
|
|
259
|
+
}
|
|
260
|
+
return word as T;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
public getSlice(offset: number, size: number): MemoryValue[] {
|
|
264
|
+
assert(Number.isInteger(offset) && Number.isInteger(size));
|
|
265
|
+
|
|
266
|
+
if (offset + size > TaggedMemory.MAX_MEMORY_SIZE) {
|
|
267
|
+
throw new MemorySliceOutOfRangeError(offset, size);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const slice = new Array<MemoryValue>(size);
|
|
271
|
+
|
|
272
|
+
for (let i = 0; i < size; i++) {
|
|
273
|
+
slice[i] = this._mem.get(offset + i) ?? new Field(0);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
TaggedMemory.log.trace(`getSlice(${offset}, ${size}) = ${slice}`);
|
|
277
|
+
return slice;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public getSliceAs<T>(offset: number, size: number): T[] {
|
|
281
|
+
return this.getSlice(offset, size) as T[];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
public getSliceTags(offset: number, size: number): TypeTag[] {
|
|
285
|
+
return this.getSlice(offset, size).map(TaggedMemory.getTag);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
public set(offset: number, v: MemoryValue) {
|
|
289
|
+
assert(Number.isInteger(offset) && offset < TaggedMemory.MAX_MEMORY_SIZE);
|
|
290
|
+
this._mem.set(offset, v);
|
|
291
|
+
//TaggedMemory.log.trace(`set(${offset}, ${v})`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
public setSlice(offset: number, slice: MemoryValue[]) {
|
|
295
|
+
assert(Number.isInteger(offset));
|
|
296
|
+
|
|
297
|
+
if (offset + slice.length > TaggedMemory.MAX_MEMORY_SIZE) {
|
|
298
|
+
throw new MemorySliceOutOfRangeError(offset, slice.length);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
slice.forEach((element, idx) => {
|
|
302
|
+
this._mem.set(offset + idx, element);
|
|
303
|
+
});
|
|
304
|
+
TaggedMemory.log.trace(`setSlice(${offset}, ${slice})`);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
public getTag(offset: number): TypeTag {
|
|
308
|
+
assert(Number.isInteger(offset) && offset < TaggedMemory.MAX_MEMORY_SIZE);
|
|
309
|
+
return TaggedMemory.getTag(this._mem.get(offset));
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Check that the memory at the given offset matches the specified tag.
|
|
314
|
+
*/
|
|
315
|
+
public checkTag(tag: TypeTag, offset: number) {
|
|
316
|
+
const gotTag = this.getTag(offset);
|
|
317
|
+
if (gotTag !== tag) {
|
|
318
|
+
throw TagCheckError.forOffset(offset, TypeTag[gotTag], TypeTag[tag]);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
public checkIsValidMemoryOffsetTag(offset: number) {
|
|
323
|
+
this.checkTag(TypeTag.UINT32, offset);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
public static checkIsIntegralTag(tag: TypeTag) {
|
|
327
|
+
if (!INTEGRAL_TAGS.has(tag)) {
|
|
328
|
+
throw TagCheckError.forTag(TypeTag[tag], 'integral');
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
public static checkIsValidTag(tagNumber: number) {
|
|
333
|
+
if (!VALID_TAGS.has(tagNumber)) {
|
|
334
|
+
throw new InvalidTagValueError(tagNumber);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Check tags for memory at all of the specified offsets.
|
|
340
|
+
*/
|
|
341
|
+
public checkTags(tag: TypeTag, ...offsets: number[]) {
|
|
342
|
+
for (const offset of offsets) {
|
|
343
|
+
this.checkTag(tag, offset);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Check that all tags at the given offsets are the same.
|
|
349
|
+
*/
|
|
350
|
+
public checkTagsAreSame(offset0: number, offset1: number) {
|
|
351
|
+
const tag0 = this.getTag(offset0);
|
|
352
|
+
this.checkTag(tag0, offset1);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Check tags for all memory in the specified range.
|
|
357
|
+
*/
|
|
358
|
+
public checkTagsRange(tag: TypeTag, startOffset: number, size: number) {
|
|
359
|
+
for (let offset = startOffset; offset < startOffset + size; offset++) {
|
|
360
|
+
this.checkTag(tag, offset);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
public static getTag(v: MemoryValue | undefined): TypeTag {
|
|
365
|
+
if (v === undefined) {
|
|
366
|
+
return TypeTag.FIELD; // uninitialized memory is Field(0)
|
|
367
|
+
} else {
|
|
368
|
+
return TAG_FOR_MEM_VAL.get(v.constructor.name) ?? TypeTag.INVALID;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Truncates the value to fit the type.
|
|
373
|
+
public static buildFromTagTruncating(v: bigint | number, tag: TypeTag): MemoryValue {
|
|
374
|
+
v = BigInt(v);
|
|
375
|
+
switch (tag) {
|
|
376
|
+
case TypeTag.FIELD:
|
|
377
|
+
return new Field(v);
|
|
378
|
+
case TypeTag.UINT1:
|
|
379
|
+
return new Uint1(v & 1n);
|
|
380
|
+
case TypeTag.UINT8:
|
|
381
|
+
return new Uint8(v & ((1n << 8n) - 1n));
|
|
382
|
+
case TypeTag.UINT16:
|
|
383
|
+
return new Uint16(v & ((1n << 16n) - 1n));
|
|
384
|
+
case TypeTag.UINT32:
|
|
385
|
+
return new Uint32(v & ((1n << 32n) - 1n));
|
|
386
|
+
case TypeTag.UINT64:
|
|
387
|
+
return new Uint64(v & ((1n << 64n) - 1n));
|
|
388
|
+
case TypeTag.UINT128:
|
|
389
|
+
return new Uint128(v & ((1n << 128n) - 1n));
|
|
390
|
+
default:
|
|
391
|
+
throw new InvalidTagValueError(tag);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const TAG_FOR_MEM_VAL = new Map<string, TypeTag>([
|
|
397
|
+
['Field', TypeTag.FIELD],
|
|
398
|
+
['Uint1', TypeTag.UINT1],
|
|
399
|
+
['Uint8', TypeTag.UINT8],
|
|
400
|
+
['Uint16', TypeTag.UINT16],
|
|
401
|
+
['Uint32', TypeTag.UINT32],
|
|
402
|
+
['Uint64', TypeTag.UINT64],
|
|
403
|
+
['Uint128', TypeTag.UINT128],
|
|
404
|
+
]);
|
|
405
|
+
|
|
406
|
+
const VALID_TAGS = new Set([
|
|
407
|
+
TypeTag.FIELD,
|
|
408
|
+
TypeTag.UINT1,
|
|
409
|
+
TypeTag.UINT8,
|
|
410
|
+
TypeTag.UINT16,
|
|
411
|
+
TypeTag.UINT32,
|
|
412
|
+
TypeTag.UINT64,
|
|
413
|
+
TypeTag.UINT128,
|
|
414
|
+
]);
|
|
415
|
+
|
|
416
|
+
const INTEGRAL_TAGS = new Set([
|
|
417
|
+
TypeTag.UINT1,
|
|
418
|
+
TypeTag.UINT8,
|
|
419
|
+
TypeTag.UINT16,
|
|
420
|
+
TypeTag.UINT32,
|
|
421
|
+
TypeTag.UINT64,
|
|
422
|
+
TypeTag.UINT128,
|
|
423
|
+
]);
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { MAX_L2_GAS_PER_TX_PUBLIC_PORTION } from '@aztec/constants';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
|
+
import type { GlobalVariables } from '@aztec/stdlib/tx';
|
|
6
|
+
|
|
7
|
+
import { strict as assert } from 'assert';
|
|
8
|
+
|
|
9
|
+
import { SideEffectLimitReachedError } from '../side_effect_errors.js';
|
|
10
|
+
import { AvmContext } from './avm_context.js';
|
|
11
|
+
import { AvmContractCallResult } from './avm_contract_call_result.js';
|
|
12
|
+
import { AvmExecutionEnvironment } from './avm_execution_environment.js';
|
|
13
|
+
import type { Gas } from './avm_gas.js';
|
|
14
|
+
import { AvmMachineState } from './avm_machine_state.js';
|
|
15
|
+
import { isAvmBytecode } from './bytecode_utils.js';
|
|
16
|
+
import {
|
|
17
|
+
AvmExecutionError,
|
|
18
|
+
AvmRevertReason,
|
|
19
|
+
InvalidProgramCounterError,
|
|
20
|
+
revertReasonFromExceptionalHalt,
|
|
21
|
+
revertReasonFromExplicitRevert,
|
|
22
|
+
} from './errors.js';
|
|
23
|
+
import type { AvmPersistableStateManager } from './journal/journal.js';
|
|
24
|
+
import type { Instruction } from './opcodes/instruction.js';
|
|
25
|
+
import {
|
|
26
|
+
INSTRUCTION_SET,
|
|
27
|
+
type InstructionSet,
|
|
28
|
+
decodeInstructionFromBytecode,
|
|
29
|
+
} from './serialization/bytecode_serialization.js';
|
|
30
|
+
|
|
31
|
+
type OpcodeTally = {
|
|
32
|
+
count: number;
|
|
33
|
+
gas: Gas;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export class AvmSimulator {
|
|
37
|
+
private log: Logger;
|
|
38
|
+
private bytecode: Buffer | undefined;
|
|
39
|
+
private opcodeTallies: Map<string, OpcodeTally> = new Map();
|
|
40
|
+
// maps pc to [instr, bytesRead]
|
|
41
|
+
private deserializedInstructionsCache: Map<number, [Instruction, number]> = new Map();
|
|
42
|
+
|
|
43
|
+
private tallyPrintFunction = () => {};
|
|
44
|
+
private tallyInstructionFunction = (_b: string, _c: Gas) => {};
|
|
45
|
+
|
|
46
|
+
// Test Purposes only: Logger will not have the proper function name. Use this constructor for testing purposes
|
|
47
|
+
// only. Otherwise, use build() below.
|
|
48
|
+
constructor(
|
|
49
|
+
private context: AvmContext,
|
|
50
|
+
private instructionSet: InstructionSet = INSTRUCTION_SET,
|
|
51
|
+
enableTallying = false,
|
|
52
|
+
) {
|
|
53
|
+
// This will be used by the CALL opcode to create a new simulator. It is required to
|
|
54
|
+
// avoid a dependency cycle.
|
|
55
|
+
context.provideSimulator = AvmSimulator.build;
|
|
56
|
+
assert(
|
|
57
|
+
context.machineState.gasLeft.l2Gas <= MAX_L2_GAS_PER_TX_PUBLIC_PORTION,
|
|
58
|
+
`Cannot allocate more than ${MAX_L2_GAS_PER_TX_PUBLIC_PORTION} to the AVM for execution.`,
|
|
59
|
+
);
|
|
60
|
+
this.log = createLogger(`simulator:avm(calldata[0]: ${context.environment.calldata[0]})`);
|
|
61
|
+
// Turn on tallying if explicitly enabled or if trace logging
|
|
62
|
+
if (enableTallying || this.log.isLevelEnabled('trace')) {
|
|
63
|
+
this.tallyPrintFunction = this.printOpcodeTallies;
|
|
64
|
+
this.tallyInstructionFunction = this.tallyInstruction;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Factory to have a proper function name in the logger. Retrieving the name is asynchronous and
|
|
69
|
+
// cannot be done as part of the constructor.
|
|
70
|
+
public static async build(context: AvmContext): Promise<AvmSimulator> {
|
|
71
|
+
const simulator = new AvmSimulator(context);
|
|
72
|
+
const fnName = await context.persistableState.getPublicFunctionDebugName(context.environment);
|
|
73
|
+
simulator.log = createLogger(`simulator:avm(f:${fnName})`);
|
|
74
|
+
|
|
75
|
+
return simulator;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public static async create(
|
|
79
|
+
stateManager: AvmPersistableStateManager,
|
|
80
|
+
address: AztecAddress,
|
|
81
|
+
sender: AztecAddress,
|
|
82
|
+
transactionFee: Fr,
|
|
83
|
+
globals: GlobalVariables,
|
|
84
|
+
isStaticCall: boolean,
|
|
85
|
+
calldata: Fr[],
|
|
86
|
+
allocatedGas: Gas,
|
|
87
|
+
) {
|
|
88
|
+
const avmExecutionEnv = new AvmExecutionEnvironment(
|
|
89
|
+
address,
|
|
90
|
+
sender,
|
|
91
|
+
/*contractCallDepth=*/ Fr.zero(),
|
|
92
|
+
transactionFee,
|
|
93
|
+
globals,
|
|
94
|
+
isStaticCall,
|
|
95
|
+
calldata,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const avmMachineState = new AvmMachineState(allocatedGas);
|
|
99
|
+
const avmContext = new AvmContext(stateManager, avmExecutionEnv, avmMachineState);
|
|
100
|
+
return await AvmSimulator.build(avmContext);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Fetch the bytecode and execute it in the current context.
|
|
105
|
+
*/
|
|
106
|
+
public async execute(): Promise<AvmContractCallResult> {
|
|
107
|
+
let bytecode: Buffer | undefined;
|
|
108
|
+
try {
|
|
109
|
+
bytecode = await this.context.persistableState.getBytecode(this.context.environment.address);
|
|
110
|
+
} catch (err: any) {
|
|
111
|
+
if (!(err instanceof AvmExecutionError || err instanceof SideEffectLimitReachedError)) {
|
|
112
|
+
this.log.error(`Unknown error thrown by AVM during bytecode retrieval: ${err}`);
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
return await this.handleFailureToRetrieveBytecode(
|
|
116
|
+
`Bytecode retrieval for contract '${this.context.environment.address}' failed with ${err}. Reverting...`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!bytecode) {
|
|
121
|
+
return await this.handleFailureToRetrieveBytecode(
|
|
122
|
+
`No bytecode found at: ${this.context.environment.address}. Reverting...`,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return await this.executeBytecode(bytecode);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Return the bytecode used for execution, if any.
|
|
131
|
+
*/
|
|
132
|
+
public getBytecode(): Buffer | undefined {
|
|
133
|
+
return this.bytecode;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Executes the provided bytecode in the current context.
|
|
138
|
+
* This method is useful for testing and debugging.
|
|
139
|
+
*/
|
|
140
|
+
public async executeBytecode(bytecode: Buffer): Promise<AvmContractCallResult> {
|
|
141
|
+
const startTotalTime = performance.now();
|
|
142
|
+
assert(isAvmBytecode(bytecode), "AVM simulator can't execute non-AVM bytecode");
|
|
143
|
+
assert(bytecode.length > 0, "AVM simulator can't execute empty bytecode");
|
|
144
|
+
|
|
145
|
+
this.bytecode = bytecode;
|
|
146
|
+
|
|
147
|
+
const { machineState } = this.context;
|
|
148
|
+
const callStartGas = machineState.gasLeft; // Save gas before executing instruction (for profiling)
|
|
149
|
+
try {
|
|
150
|
+
// Execute instruction pointed to by the current program counter
|
|
151
|
+
// continuing until the machine state signifies a halt
|
|
152
|
+
let instrCounter = 0;
|
|
153
|
+
while (!machineState.getHalted()) {
|
|
154
|
+
// Get the instruction from cache, or deserialize for the first time
|
|
155
|
+
let cachedInstruction = this.deserializedInstructionsCache.get(machineState.pc);
|
|
156
|
+
|
|
157
|
+
if (cachedInstruction === undefined) {
|
|
158
|
+
cachedInstruction = decodeInstructionFromBytecode(bytecode, machineState.pc, this.instructionSet);
|
|
159
|
+
this.deserializedInstructionsCache.set(machineState.pc, cachedInstruction);
|
|
160
|
+
}
|
|
161
|
+
const [instruction, bytesRead] = cachedInstruction;
|
|
162
|
+
|
|
163
|
+
const instrStartGas = machineState.gasLeft; // Save gas before executing instruction (for profiling)
|
|
164
|
+
|
|
165
|
+
if (this.log.isLevelEnabled('trace')) {
|
|
166
|
+
// Skip this entirely to avoid toStringing etc if trace is not enabled
|
|
167
|
+
this.log.trace(
|
|
168
|
+
`[PC:${machineState.pc}] [IC:${instrCounter}] ${instruction.toString()} (gasLeft l2=${
|
|
169
|
+
machineState.l2GasLeft
|
|
170
|
+
} da=${machineState.daGasLeft})`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
instrCounter++;
|
|
174
|
+
|
|
175
|
+
machineState.nextPc = machineState.pc + bytesRead;
|
|
176
|
+
|
|
177
|
+
// Execute the instruction.
|
|
178
|
+
// Normal returns and reverts will return normally here.
|
|
179
|
+
// "Exceptional halts" will throw.
|
|
180
|
+
await instruction.execute(this.context);
|
|
181
|
+
if (!instruction.handlesPC()) {
|
|
182
|
+
// Increment PC if the instruction doesn't handle it itself
|
|
183
|
+
machineState.pc += bytesRead;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// gas used by this instruction - used for profiling/tallying
|
|
187
|
+
const gasUsed: Gas = {
|
|
188
|
+
l2Gas: instrStartGas.l2Gas - machineState.l2GasLeft,
|
|
189
|
+
daGas: instrStartGas.daGas - machineState.daGasLeft,
|
|
190
|
+
};
|
|
191
|
+
this.tallyInstructionFunction(instruction.constructor.name, gasUsed);
|
|
192
|
+
|
|
193
|
+
if (machineState.pc >= bytecode.length) {
|
|
194
|
+
this.log.warn('Passed end of program');
|
|
195
|
+
throw new InvalidProgramCounterError(machineState.pc, /*max=*/ bytecode.length);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const output = machineState.getOutput();
|
|
200
|
+
const reverted = machineState.getReverted();
|
|
201
|
+
const revertReason = reverted ? await revertReasonFromExplicitRevert(output, this.context) : undefined;
|
|
202
|
+
const results = new AvmContractCallResult(reverted, output, machineState.gasLeft, revertReason);
|
|
203
|
+
this.log.debug(`Context execution results: ${results.toString()}`);
|
|
204
|
+
const totalGasUsed: Gas = {
|
|
205
|
+
l2Gas: callStartGas.l2Gas - machineState.l2GasLeft,
|
|
206
|
+
daGas: callStartGas.daGas - machineState.daGasLeft,
|
|
207
|
+
};
|
|
208
|
+
this.log.debug(`Executed ${instrCounter} instructions and consumed ${totalGasUsed.l2Gas} L2 Gas`);
|
|
209
|
+
|
|
210
|
+
this.tallyPrintFunction();
|
|
211
|
+
|
|
212
|
+
const endTotalTime = performance.now();
|
|
213
|
+
const totalTime = endTotalTime - startTotalTime;
|
|
214
|
+
this.log.debug(`Core AVM simulation took ${totalTime}ms`);
|
|
215
|
+
|
|
216
|
+
// Return results for processing by calling context
|
|
217
|
+
return results;
|
|
218
|
+
} catch (err: any) {
|
|
219
|
+
this.log.verbose('Exceptional halt (revert by something other than REVERT opcode)');
|
|
220
|
+
// FIXME: weird that we have to do this OutOfGasError check because:
|
|
221
|
+
// 1. OutOfGasError is an AvmExecutionError, so that check should cover both
|
|
222
|
+
// 2. We should at least be able to do instanceof OutOfGasError instead of checking the constructor name
|
|
223
|
+
if (
|
|
224
|
+
!(
|
|
225
|
+
err.constructor.name == 'OutOfGasError' ||
|
|
226
|
+
err instanceof AvmExecutionError ||
|
|
227
|
+
err instanceof SideEffectLimitReachedError
|
|
228
|
+
)
|
|
229
|
+
) {
|
|
230
|
+
this.log.error(`Unknown error thrown by AVM: ${err}`);
|
|
231
|
+
throw err;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const revertReason = await revertReasonFromExceptionalHalt(err, this.context);
|
|
235
|
+
// Exceptional halts consume all allocated gas
|
|
236
|
+
const noGasLeft = { l2Gas: 0, daGas: 0 };
|
|
237
|
+
// Note: "exceptional halts" cannot return data, hence [].
|
|
238
|
+
const results = new AvmContractCallResult(/*reverted=*/ true, /*output=*/ [], noGasLeft, revertReason);
|
|
239
|
+
this.log.debug(`Context execution results: ${results.toString()}`);
|
|
240
|
+
|
|
241
|
+
this.tallyPrintFunction();
|
|
242
|
+
// Return results for processing by calling context
|
|
243
|
+
return results;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private async handleFailureToRetrieveBytecode(message: string): Promise<AvmContractCallResult> {
|
|
248
|
+
// revert, consuming all gas
|
|
249
|
+
const fnName = await this.context.persistableState.getPublicFunctionDebugName(this.context.environment);
|
|
250
|
+
const revertReason = new AvmRevertReason(
|
|
251
|
+
message,
|
|
252
|
+
/*failingFunction=*/ {
|
|
253
|
+
contractAddress: this.context.environment.address,
|
|
254
|
+
functionName: fnName,
|
|
255
|
+
},
|
|
256
|
+
/*noirCallStack=*/ [],
|
|
257
|
+
);
|
|
258
|
+
this.log.warn(message);
|
|
259
|
+
return new AvmContractCallResult(
|
|
260
|
+
/*reverted=*/ true,
|
|
261
|
+
/*output=*/ [],
|
|
262
|
+
/*gasLeft=*/ { l2Gas: 0, daGas: 0 }, // consumes all allocated gas
|
|
263
|
+
revertReason,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private tallyInstruction(opcode: string, gasUsed: Gas) {
|
|
268
|
+
const opcodeTally = this.opcodeTallies.get(opcode) || ({ count: 0, gas: { l2Gas: 0, daGas: 0 } } as OpcodeTally);
|
|
269
|
+
opcodeTally.count++;
|
|
270
|
+
opcodeTally.gas.l2Gas += gasUsed.l2Gas;
|
|
271
|
+
opcodeTally.gas.daGas += gasUsed.daGas;
|
|
272
|
+
this.opcodeTallies.set(opcode, opcodeTally);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private printOpcodeTallies() {
|
|
276
|
+
this.log.debug(`Printing tallies per opcode sorted by gas...`);
|
|
277
|
+
// sort descending by L2 gas consumed
|
|
278
|
+
const sortedOpcodes = Array.from(this.opcodeTallies.entries()).sort((a, b) => b[1].gas.l2Gas - a[1].gas.l2Gas);
|
|
279
|
+
for (const [opcode, tally] of sortedOpcodes) {
|
|
280
|
+
// NOTE: don't care to clutter the logs with DA gas for now
|
|
281
|
+
this.log.debug(`${opcode} executed ${tally.count} times consuming a total of ${tally.gas.l2Gas} L2 gas`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|