@aztec/simulator 0.74.0 → 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2
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/dest/acvm/acvm.js +18 -21
- package/dest/acvm/acvm_types.js +3 -2
- package/dest/acvm/deserialize.js +9 -13
- package/dest/acvm/index.js +0 -1
- package/dest/acvm/oracle/index.js +0 -1
- package/dest/acvm/oracle/oracle.js +42 -23
- package/dest/acvm/oracle/typed_oracle.js +36 -38
- package/dest/acvm/serialize.js +7 -14
- package/dest/avm/avm_context.js +24 -27
- package/dest/avm/avm_contract_call_result.js +12 -7
- package/dest/avm/avm_execution_environment.js +10 -7
- package/dest/avm/avm_gas.js +93 -56
- package/dest/avm/avm_machine_state.js +60 -61
- package/dest/avm/avm_memory_types.js +166 -255
- package/dest/avm/avm_simulator.js +68 -47
- package/dest/avm/avm_tree.js +282 -276
- package/dest/avm/bytecode_utils.js +8 -6
- package/dest/avm/errors.js +46 -63
- package/dest/avm/fixtures/avm_simulation_tester.js +18 -17
- package/dest/avm/fixtures/base_avm_simulation_tester.js +21 -16
- package/dest/avm/fixtures/index.js +27 -26
- package/dest/avm/fixtures/simple_contract_data_source.js +9 -13
- package/dest/avm/index.js +0 -1
- package/dest/avm/journal/index.js +0 -1
- package/dest/avm/journal/journal.js +147 -200
- package/dest/avm/journal/nullifiers.js +43 -46
- package/dest/avm/journal/public_storage.js +73 -87
- package/dest/avm/opcodes/accrued_substate.js +140 -110
- package/dest/avm/opcodes/addressing_mode.js +29 -31
- package/dest/avm/opcodes/arithmetic.js +17 -15
- package/dest/avm/opcodes/bitwise.js +40 -26
- package/dest/avm/opcodes/comparators.js +12 -10
- package/dest/avm/opcodes/contract.js +31 -29
- package/dest/avm/opcodes/control_flow.js +47 -43
- package/dest/avm/opcodes/conversion.js +30 -26
- package/dest/avm/opcodes/ec_add.js +35 -34
- package/dest/avm/opcodes/environment_getters.js +33 -33
- package/dest/avm/opcodes/external_calls.js +83 -74
- package/dest/avm/opcodes/hashing.js +69 -61
- package/dest/avm/opcodes/index.js +0 -1
- package/dest/avm/opcodes/instruction.js +31 -40
- package/dest/avm/opcodes/instruction_impl.js +12 -15
- package/dest/avm/opcodes/memory.js +177 -156
- package/dest/avm/opcodes/misc.js +27 -25
- package/dest/avm/opcodes/multi_scalar_mul.js +43 -41
- package/dest/avm/opcodes/storage.js +28 -25
- package/dest/avm/serialization/buffer_cursor.js +4 -4
- package/dest/avm/serialization/bytecode_serialization.js +292 -89
- package/dest/avm/serialization/instruction_serialization.js +67 -28
- package/dest/avm/test_utils.js +6 -9
- package/dest/client/client_execution_context.js +197 -219
- package/dest/client/db_oracle.js +4 -7
- package/dest/client/execution_note_cache.js +80 -81
- package/dest/client/index.js +0 -1
- package/dest/client/pick_notes.js +27 -30
- package/dest/client/private_execution.js +13 -14
- package/dest/client/simulator.js +44 -48
- package/dest/client/unconstrained_execution.js +8 -11
- package/dest/client/view_data_oracle.js +130 -139
- package/dest/common/debug_fn_name.js +1 -4
- package/dest/common/errors.js +30 -39
- package/dest/common/hashed_values_cache.js +16 -20
- package/dest/common/index.js +0 -1
- package/dest/common/message_load_oracle_inputs.js +7 -7
- package/dest/common/simulation_provider.js +3 -6
- package/dest/common.js +0 -1
- package/dest/providers/acvm_native.js +46 -32
- package/dest/providers/acvm_wasm.js +18 -10
- package/dest/providers/acvm_wasm_with_blobs.js +2 -5
- package/dest/providers/factory.js +5 -5
- package/dest/providers/index.js +0 -1
- package/dest/public/bytecode_errors.js +1 -2
- package/dest/public/db_interfaces.js +1 -2
- package/dest/public/execution.js +2 -4
- package/dest/public/executor_metrics.js +16 -12
- package/dest/public/fee_payment.js +2 -5
- package/dest/public/fixtures/index.js +0 -1
- package/dest/public/fixtures/public_tx_simulation_tester.js +13 -17
- package/dest/public/fixtures/utils.js +11 -14
- package/dest/public/index.js +0 -1
- package/dest/public/public_db_sources.js +79 -87
- package/dest/public/public_processor.js +310 -306
- package/dest/public/public_processor_metrics.js +46 -27
- package/dest/public/public_tx_context.js +97 -118
- package/dest/public/public_tx_simulator.js +299 -314
- package/dest/public/side_effect_errors.js +1 -2
- package/dest/public/side_effect_trace.js +44 -71
- package/dest/public/side_effect_trace_interface.js +1 -2
- package/dest/public/unique_class_ids.js +22 -27
- package/dest/public/utils.js +16 -11
- package/dest/server.js +0 -1
- package/dest/stats/index.js +0 -1
- package/dest/stats/stats.js +1 -2
- package/dest/test/utils.js +5 -4
- package/package.json +11 -11
- package/src/acvm/oracle/typed_oracle.ts +34 -34
- package/src/avm/avm_machine_state.ts +18 -14
- package/src/avm/avm_memory_types.ts +43 -183
- package/src/avm/avm_simulator.ts +37 -11
- package/src/avm/opcodes/accrued_substate.ts +7 -21
- package/src/avm/opcodes/addressing_mode.ts +9 -2
- package/src/avm/opcodes/arithmetic.ts +1 -3
- package/src/avm/opcodes/bitwise.ts +2 -6
- package/src/avm/opcodes/comparators.ts +1 -3
- package/src/avm/opcodes/contract.ts +1 -3
- package/src/avm/opcodes/control_flow.ts +1 -9
- package/src/avm/opcodes/conversion.ts +1 -3
- package/src/avm/opcodes/ec_add.ts +1 -3
- package/src/avm/opcodes/environment_getters.ts +1 -3
- package/src/avm/opcodes/external_calls.ts +3 -6
- package/src/avm/opcodes/hashing.ts +3 -9
- package/src/avm/opcodes/memory.ts +6 -20
- package/src/avm/opcodes/misc.ts +1 -3
- package/src/avm/opcodes/multi_scalar_mul.ts +1 -7
- package/src/avm/opcodes/storage.ts +2 -6
- package/src/client/index.ts +2 -2
- package/dest/acvm/acvm.d.ts +0 -35
- package/dest/acvm/acvm.d.ts.map +0 -1
- package/dest/acvm/acvm_types.d.ts +0 -10
- package/dest/acvm/acvm_types.d.ts.map +0 -1
- package/dest/acvm/deserialize.d.ts +0 -36
- package/dest/acvm/deserialize.d.ts.map +0 -1
- package/dest/acvm/index.d.ts +0 -6
- package/dest/acvm/index.d.ts.map +0 -1
- package/dest/acvm/oracle/index.d.ts +0 -14
- package/dest/acvm/oracle/index.d.ts.map +0 -1
- package/dest/acvm/oracle/oracle.d.ts +0 -49
- package/dest/acvm/oracle/oracle.d.ts.map +0 -1
- package/dest/acvm/oracle/typed_oracle.d.ts +0 -75
- package/dest/acvm/oracle/typed_oracle.d.ts.map +0 -1
- package/dest/acvm/serialize.d.ts +0 -20
- package/dest/acvm/serialize.d.ts.map +0 -1
- package/dest/avm/avm_context.d.ts +0 -39
- package/dest/avm/avm_context.d.ts.map +0 -1
- package/dest/avm/avm_contract_call_result.d.ts +0 -30
- package/dest/avm/avm_contract_call_result.d.ts.map +0 -1
- package/dest/avm/avm_execution_environment.d.ts +0 -21
- package/dest/avm/avm_execution_environment.d.ts.map +0 -1
- package/dest/avm/avm_gas.d.ts +0 -60
- package/dest/avm/avm_gas.d.ts.map +0 -1
- package/dest/avm/avm_machine_state.d.ts +0 -93
- package/dest/avm/avm_machine_state.d.ts.map +0 -1
- package/dest/avm/avm_memory_types.d.ts +0 -310
- package/dest/avm/avm_memory_types.d.ts.map +0 -1
- package/dest/avm/avm_simulator.d.ts +0 -37
- package/dest/avm/avm_simulator.d.ts.map +0 -1
- package/dest/avm/avm_tree.d.ts +0 -281
- package/dest/avm/avm_tree.d.ts.map +0 -1
- package/dest/avm/bytecode_utils.d.ts +0 -5
- package/dest/avm/bytecode_utils.d.ts.map +0 -1
- package/dest/avm/errors.d.ts +0 -121
- package/dest/avm/errors.d.ts.map +0 -1
- package/dest/avm/fixtures/avm_simulation_tester.d.ts +0 -21
- package/dest/avm/fixtures/avm_simulation_tester.d.ts.map +0 -1
- package/dest/avm/fixtures/base_avm_simulation_tester.d.ts +0 -35
- package/dest/avm/fixtures/base_avm_simulation_tester.d.ts.map +0 -1
- package/dest/avm/fixtures/index.d.ts +0 -67
- package/dest/avm/fixtures/index.d.ts.map +0 -1
- package/dest/avm/fixtures/simple_contract_data_source.d.ts +0 -31
- package/dest/avm/fixtures/simple_contract_data_source.d.ts.map +0 -1
- package/dest/avm/index.d.ts +0 -4
- package/dest/avm/index.d.ts.map +0 -1
- package/dest/avm/journal/index.d.ts +0 -2
- package/dest/avm/journal/index.d.ts.map +0 -1
- package/dest/avm/journal/journal.d.ts +0 -176
- package/dest/avm/journal/journal.d.ts.map +0 -1
- package/dest/avm/journal/nullifiers.d.ts +0 -62
- package/dest/avm/journal/nullifiers.d.ts.map +0 -1
- package/dest/avm/journal/public_storage.d.ts +0 -66
- package/dest/avm/journal/public_storage.d.ts.map +0 -1
- package/dest/avm/opcodes/accrued_substate.d.ts +0 -75
- package/dest/avm/opcodes/accrued_substate.d.ts.map +0 -1
- package/dest/avm/opcodes/addressing_mode.d.ts +0 -27
- package/dest/avm/opcodes/addressing_mode.d.ts.map +0 -1
- package/dest/avm/opcodes/arithmetic.d.ts +0 -37
- package/dest/avm/opcodes/arithmetic.d.ts.map +0 -1
- package/dest/avm/opcodes/bitwise.d.ts +0 -50
- package/dest/avm/opcodes/bitwise.d.ts.map +0 -1
- package/dest/avm/opcodes/comparators.d.ts +0 -25
- package/dest/avm/opcodes/comparators.d.ts.map +0 -1
- package/dest/avm/opcodes/contract.d.ts +0 -21
- package/dest/avm/opcodes/contract.d.ts.map +0 -1
- package/dest/avm/opcodes/control_flow.d.ts +0 -41
- package/dest/avm/opcodes/control_flow.d.ts.map +0 -1
- package/dest/avm/opcodes/conversion.d.ts +0 -17
- package/dest/avm/opcodes/conversion.d.ts.map +0 -1
- package/dest/avm/opcodes/ec_add.d.ts +0 -19
- package/dest/avm/opcodes/ec_add.d.ts.map +0 -1
- package/dest/avm/opcodes/environment_getters.d.ts +0 -28
- package/dest/avm/opcodes/environment_getters.d.ts.map +0 -1
- package/dest/avm/opcodes/external_calls.d.ts +0 -50
- package/dest/avm/opcodes/external_calls.d.ts.map +0 -1
- package/dest/avm/opcodes/hashing.d.ts +0 -36
- package/dest/avm/opcodes/hashing.d.ts.map +0 -1
- package/dest/avm/opcodes/index.d.ts +0 -16
- package/dest/avm/opcodes/index.d.ts.map +0 -1
- package/dest/avm/opcodes/instruction.d.ts +0 -70
- package/dest/avm/opcodes/instruction.d.ts.map +0 -1
- package/dest/avm/opcodes/instruction_impl.d.ts +0 -19
- package/dest/avm/opcodes/instruction_impl.d.ts.map +0 -1
- package/dest/avm/opcodes/memory.d.ts +0 -74
- package/dest/avm/opcodes/memory.d.ts.map +0 -1
- package/dest/avm/opcodes/misc.d.ts +0 -17
- package/dest/avm/opcodes/misc.d.ts.map +0 -1
- package/dest/avm/opcodes/multi_scalar_mul.d.ts +0 -16
- package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +0 -1
- package/dest/avm/opcodes/storage.d.ts +0 -24
- package/dest/avm/opcodes/storage.d.ts.map +0 -1
- package/dest/avm/serialization/buffer_cursor.d.ts +0 -28
- package/dest/avm/serialization/buffer_cursor.d.ts.map +0 -1
- package/dest/avm/serialization/bytecode_serialization.d.ts +0 -21
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +0 -1
- package/dest/avm/serialization/instruction_serialization.d.ts +0 -105
- package/dest/avm/serialization/instruction_serialization.d.ts.map +0 -1
- package/dest/avm/test_utils.d.ts +0 -16
- package/dest/avm/test_utils.d.ts.map +0 -1
- package/dest/client/client_execution_context.d.ts +0 -214
- package/dest/client/client_execution_context.d.ts.map +0 -1
- package/dest/client/db_oracle.d.ts +0 -229
- package/dest/client/db_oracle.d.ts.map +0 -1
- package/dest/client/execution_note_cache.d.ts +0 -93
- package/dest/client/execution_note_cache.d.ts.map +0 -1
- package/dest/client/index.d.ts +0 -15
- package/dest/client/index.d.ts.map +0 -1
- package/dest/client/pick_notes.d.ts +0 -85
- package/dest/client/pick_notes.d.ts.map +0 -1
- package/dest/client/private_execution.d.ts +0 -19
- package/dest/client/private_execution.d.ts.map +0 -1
- package/dest/client/simulator.d.ts +0 -60
- package/dest/client/simulator.d.ts.map +0 -1
- package/dest/client/unconstrained_execution.d.ts +0 -10
- package/dest/client/unconstrained_execution.d.ts.map +0 -1
- package/dest/client/view_data_oracle.d.ts +0 -159
- package/dest/client/view_data_oracle.d.ts.map +0 -1
- package/dest/common/debug_fn_name.d.ts +0 -4
- package/dest/common/debug_fn_name.d.ts.map +0 -1
- package/dest/common/errors.d.ts +0 -54
- package/dest/common/errors.d.ts.map +0 -1
- package/dest/common/hashed_values_cache.d.ts +0 -28
- package/dest/common/hashed_values_cache.d.ts.map +0 -1
- package/dest/common/index.d.ts +0 -3
- package/dest/common/index.d.ts.map +0 -1
- package/dest/common/message_load_oracle_inputs.d.ts +0 -15
- package/dest/common/message_load_oracle_inputs.d.ts.map +0 -1
- package/dest/common/simulation_provider.d.ts +0 -19
- package/dest/common/simulation_provider.d.ts.map +0 -1
- package/dest/common.d.ts +0 -2
- package/dest/common.d.ts.map +0 -1
- package/dest/providers/acvm_native.d.ts +0 -40
- package/dest/providers/acvm_native.d.ts.map +0 -1
- package/dest/providers/acvm_wasm.d.ts +0 -15
- package/dest/providers/acvm_wasm.d.ts.map +0 -1
- package/dest/providers/acvm_wasm_with_blobs.d.ts +0 -19
- package/dest/providers/acvm_wasm_with_blobs.d.ts.map +0 -1
- package/dest/providers/factory.d.ts +0 -12
- package/dest/providers/factory.d.ts.map +0 -1
- package/dest/providers/index.d.ts +0 -5
- package/dest/providers/index.d.ts.map +0 -1
- package/dest/public/bytecode_errors.d.ts +0 -4
- package/dest/public/bytecode_errors.d.ts.map +0 -1
- package/dest/public/db_interfaces.d.ts +0 -105
- package/dest/public/db_interfaces.d.ts.map +0 -1
- package/dest/public/execution.d.ts +0 -102
- package/dest/public/execution.d.ts.map +0 -1
- package/dest/public/executor_metrics.d.ts +0 -13
- package/dest/public/executor_metrics.d.ts.map +0 -1
- package/dest/public/fee_payment.d.ts +0 -11
- package/dest/public/fee_payment.d.ts.map +0 -1
- package/dest/public/fixtures/index.d.ts +0 -3
- package/dest/public/fixtures/index.d.ts.map +0 -1
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +0 -21
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +0 -1
- package/dest/public/fixtures/utils.d.ts +0 -17
- package/dest/public/fixtures/utils.d.ts.map +0 -1
- package/dest/public/index.d.ts +0 -9
- package/dest/public/index.d.ts.map +0 -1
- package/dest/public/public_db_sources.d.ts +0 -81
- package/dest/public/public_db_sources.d.ts.map +0 -1
- package/dest/public/public_processor.d.ts +0 -72
- package/dest/public/public_processor.d.ts.map +0 -1
- package/dest/public/public_processor_metrics.d.ts +0 -27
- package/dest/public/public_processor_metrics.d.ts.map +0 -1
- package/dest/public/public_tx_context.d.ts +0 -131
- package/dest/public/public_tx_context.d.ts.map +0 -1
- package/dest/public/public_tx_simulator.d.ts +0 -99
- package/dest/public/public_tx_simulator.d.ts.map +0 -1
- package/dest/public/side_effect_errors.d.ts +0 -4
- package/dest/public/side_effect_errors.d.ts.map +0 -1
- package/dest/public/side_effect_trace.d.ts +0 -126
- package/dest/public/side_effect_trace.d.ts.map +0 -1
- package/dest/public/side_effect_trace_interface.d.ts +0 -32
- package/dest/public/side_effect_trace_interface.d.ts.map +0 -1
- package/dest/public/unique_class_ids.d.ts +0 -37
- package/dest/public/unique_class_ids.d.ts.map +0 -1
- package/dest/public/utils.d.ts +0 -5
- package/dest/public/utils.d.ts.map +0 -1
- package/dest/server.d.ts +0 -6
- package/dest/server.d.ts.map +0 -1
- package/dest/stats/index.d.ts +0 -2
- package/dest/stats/index.d.ts.map +0 -1
- package/dest/stats/stats.d.ts +0 -4
- package/dest/stats/stats.d.ts.map +0 -1
- package/dest/test/utils.d.ts +0 -12
- package/dest/test/utils.d.ts.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MerkleTreeId } from '@aztec/circuit-types';
|
|
2
|
-
import { AztecAddress, CANONICAL_AUTH_REGISTRY_ADDRESS, DEPLOYER_CONTRACT_ADDRESS, FEE_JUICE_ADDRESS, MULTI_CALL_ENTRYPOINT_ADDRESS, NullifierLeafPreimage, REGISTERER_CONTRACT_ADDRESS, ROUTER_ADDRESS, SerializableContractInstance
|
|
3
|
-
import { computeNoteHashNonce, computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash, siloNullifier
|
|
2
|
+
import { AztecAddress, CANONICAL_AUTH_REGISTRY_ADDRESS, DEPLOYER_CONTRACT_ADDRESS, FEE_JUICE_ADDRESS, MULTI_CALL_ENTRYPOINT_ADDRESS, NullifierLeafPreimage, REGISTERER_CONTRACT_ADDRESS, ROUTER_ADDRESS, SerializableContractInstance } from '@aztec/circuits.js';
|
|
3
|
+
import { computeNoteHashNonce, computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/circuits.js/hash';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
5
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
6
6
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -17,20 +17,18 @@ import { PublicStorage } from './public_storage.js';
|
|
|
17
17
|
* The simulator should make any world state / tree queries through this object.
|
|
18
18
|
*
|
|
19
19
|
* Manages merging of successful/reverted child state into current state.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
nullifiers = new NullifierManager(worldStateDB), doMerkleOperations = false,
|
|
32
|
-
/** Ephmeral forest for merkle tree operations */
|
|
33
|
-
merkleTrees, firstNullifier) {
|
|
20
|
+
*/ export class AvmPersistableStateManager {
|
|
21
|
+
worldStateDB;
|
|
22
|
+
trace;
|
|
23
|
+
publicStorage;
|
|
24
|
+
nullifiers;
|
|
25
|
+
doMerkleOperations;
|
|
26
|
+
merkleTrees;
|
|
27
|
+
firstNullifier;
|
|
28
|
+
log;
|
|
29
|
+
/** Make sure a forked state is never merged twice. */ alreadyMergedIntoParent;
|
|
30
|
+
constructor(/** Reference to node storage */ worldStateDB, /** Side effect trace */ // TODO(5818): make private once no longer accessed in executor
|
|
31
|
+
trace, /** Public storage, including cached writes */ publicStorage = new PublicStorage(worldStateDB), /** Nullifier set, including cached/recently-emitted nullifiers */ nullifiers = new NullifierManager(worldStateDB), doMerkleOperations = false, /** Ephmeral forest for merkle tree operations */ merkleTrees, firstNullifier){
|
|
34
32
|
this.worldStateDB = worldStateDB;
|
|
35
33
|
this.trace = trace;
|
|
36
34
|
this.publicStorage = publicStorage;
|
|
@@ -39,35 +37,27 @@ export class AvmPersistableStateManager {
|
|
|
39
37
|
this.merkleTrees = merkleTrees;
|
|
40
38
|
this.firstNullifier = firstNullifier;
|
|
41
39
|
this.log = createLogger('simulator:avm:state_manager');
|
|
42
|
-
/** Make sure a forked state is never merged twice. */
|
|
43
40
|
this.alreadyMergedIntoParent = false;
|
|
44
41
|
}
|
|
45
42
|
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
static async create(worldStateDB, trace, doMerkleOperations = false, firstNullifier) {
|
|
43
|
+
* Create a new state manager
|
|
44
|
+
*/ static async create(worldStateDB, trace, doMerkleOperations = false, firstNullifier) {
|
|
49
45
|
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
50
|
-
return new AvmPersistableStateManager(worldStateDB, trace,
|
|
51
|
-
/*publicStorage=*/ new PublicStorage(worldStateDB),
|
|
52
|
-
/*nullifiers=*/ new NullifierManager(worldStateDB),
|
|
53
|
-
/*doMerkleOperations=*/ doMerkleOperations, ephemeralForest, firstNullifier);
|
|
46
|
+
return new AvmPersistableStateManager(worldStateDB, trace, /*publicStorage=*/ new PublicStorage(worldStateDB), /*nullifiers=*/ new NullifierManager(worldStateDB), /*doMerkleOperations=*/ doMerkleOperations, ephemeralForest, firstNullifier);
|
|
54
47
|
}
|
|
55
48
|
/**
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
fork() {
|
|
49
|
+
* Create a new state manager forked from this one
|
|
50
|
+
*/ fork() {
|
|
59
51
|
return new AvmPersistableStateManager(this.worldStateDB, this.trace.fork(), this.publicStorage.fork(), this.nullifiers.fork(), this.doMerkleOperations, this.merkleTrees.fork(), this.firstNullifier);
|
|
60
52
|
}
|
|
61
53
|
/**
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
merge(forkedState) {
|
|
54
|
+
* Accept forked world state modifications & traced side effects / hints
|
|
55
|
+
*/ merge(forkedState) {
|
|
65
56
|
this._merge(forkedState, /*reverted=*/ false);
|
|
66
57
|
}
|
|
67
58
|
/**
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
reject(forkedState) {
|
|
59
|
+
* Reject forked world state modifications & traced side effects, keep traced hints
|
|
60
|
+
*/ reject(forkedState) {
|
|
71
61
|
this._merge(forkedState, /*reverted=*/ true);
|
|
72
62
|
}
|
|
73
63
|
_merge(forkedState, reverted) {
|
|
@@ -81,20 +71,18 @@ export class AvmPersistableStateManager {
|
|
|
81
71
|
if (this.doMerkleOperations) {
|
|
82
72
|
this.log.trace(`Rolled back nullifier tree to root ${this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE).getRoot()}`);
|
|
83
73
|
}
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
74
|
+
} else {
|
|
86
75
|
this.log.trace('Merging forked state into parent...');
|
|
87
76
|
this.merkleTrees = forkedState.merkleTrees;
|
|
88
77
|
}
|
|
89
78
|
}
|
|
90
79
|
/**
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
async writeStorage(contractAddress, slot, value, protocolWrite = false) {
|
|
80
|
+
* Write to public storage, journal/trace the write.
|
|
81
|
+
*
|
|
82
|
+
* @param contractAddress - the address of the contract whose storage is being written to
|
|
83
|
+
* @param slot - the slot in the contract's storage being written to
|
|
84
|
+
* @param value - the value being written to the slot
|
|
85
|
+
*/ async writeStorage(contractAddress, slot, value, protocolWrite = false) {
|
|
98
86
|
this.log.debug(`Storage write (address=${contractAddress}, slot=${slot}): value=${value}`);
|
|
99
87
|
const leafSlot = await computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
100
88
|
this.log.debug(`leafSlot=${leafSlot}`);
|
|
@@ -115,19 +103,17 @@ export class AvmPersistableStateManager {
|
|
|
115
103
|
assert(newLeafPreimage.value.equals(value), `Value mismatch when performing public data write (got value: ${value}, value in ephemeral tree: ${newLeafPreimage.value})`);
|
|
116
104
|
}
|
|
117
105
|
await this.trace.tracePublicStorageWrite(contractAddress, slot, value, protocolWrite, lowLeafPreimage, new Fr(lowLeafIndex), lowLeafPath, newLeafPreimage, insertionPath);
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
106
|
+
} else {
|
|
120
107
|
await this.trace.tracePublicStorageWrite(contractAddress, slot, value, protocolWrite);
|
|
121
108
|
}
|
|
122
109
|
}
|
|
123
110
|
/**
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
async readStorage(contractAddress, slot) {
|
|
111
|
+
* Read from public storage, trace the read.
|
|
112
|
+
*
|
|
113
|
+
* @param contractAddress - the address of the contract whose storage is being read from
|
|
114
|
+
* @param slot - the slot in the contract's storage being read from
|
|
115
|
+
* @returns the latest value written to slot, or 0 if never written to before
|
|
116
|
+
*/ async readStorage(contractAddress, slot) {
|
|
131
117
|
const { value, cached } = await this.publicStorage.read(contractAddress, slot);
|
|
132
118
|
this.log.debug(`Storage read (address=${contractAddress}, slot=${slot}): value=${value}, cached=${cached}`);
|
|
133
119
|
const leafSlot = await computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
@@ -135,7 +121,7 @@ export class AvmPersistableStateManager {
|
|
|
135
121
|
if (this.doMerkleOperations) {
|
|
136
122
|
// Get leaf if present, low leaf if absent
|
|
137
123
|
// If leaf is present, hint/trace it. Otherwise, hint/trace the low leaf.
|
|
138
|
-
const { preimage, index: leafIndex, alreadyPresent
|
|
124
|
+
const { preimage, index: leafIndex, alreadyPresent } = await this.merkleTrees.getLeafOrLowLeafInfo(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot);
|
|
139
125
|
// The index and preimage here is either the low leaf or the leaf itself (depending on the value of update flag)
|
|
140
126
|
// In either case, we just want the sibling path to this leaf - it's up to the avm to distinguish if it's a low leaf or not
|
|
141
127
|
const leafPath = await this.merkleTrees.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, leafIndex);
|
|
@@ -144,45 +130,40 @@ export class AvmPersistableStateManager {
|
|
|
144
130
|
this.log.debug(`leafPreimage.nextSlot: ${leafPreimage.nextSlot}, leafPreimage.nextIndex: ${Number(leafPreimage.nextIndex)}`);
|
|
145
131
|
if (alreadyPresent) {
|
|
146
132
|
assert(leafPreimage.value.equals(value), `Value mismatch when performing public data read (got value: ${value}, value in ephemeral tree: ${leafPreimage.value})`);
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
133
|
+
} else {
|
|
149
134
|
this.log.debug(`Slot has never been written before!`);
|
|
150
135
|
// Sanity check that the leaf slot is skipped by low leaf when it doesn't exist
|
|
151
|
-
assert(leafPreimage.slot.toBigInt() < leafSlot.toBigInt() &&
|
|
152
|
-
(leafPreimage.nextIndex === 0n || leafPreimage.nextSlot.toBigInt() > leafSlot.toBigInt()), 'Public data tree low leaf should skip the target leaf slot when the target leaf does not exist or is the max value.');
|
|
136
|
+
assert(leafPreimage.slot.toBigInt() < leafSlot.toBigInt() && (leafPreimage.nextIndex === 0n || leafPreimage.nextSlot.toBigInt() > leafSlot.toBigInt()), 'Public data tree low leaf should skip the target leaf slot when the target leaf does not exist or is the max value.');
|
|
153
137
|
}
|
|
154
138
|
// On non-existence, AVM circuit will need to recognize that leafPreimage.slot != leafSlot,
|
|
155
139
|
// prove that this is a low leaf that skips leafSlot, and then prove membership of the leaf.
|
|
156
140
|
this.trace.tracePublicStorageRead(contractAddress, slot, value, leafPreimage, new Fr(leafIndex), leafPath);
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
141
|
+
} else {
|
|
159
142
|
this.trace.tracePublicStorageRead(contractAddress, slot, value);
|
|
160
143
|
}
|
|
161
144
|
return Promise.resolve(value);
|
|
162
145
|
}
|
|
163
146
|
/**
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
async peekStorage(contractAddress, slot) {
|
|
147
|
+
* Read from public storage, don't trace the read.
|
|
148
|
+
*
|
|
149
|
+
* @param contractAddress - the address of the contract whose storage is being read from
|
|
150
|
+
* @param slot - the slot in the contract's storage being read from
|
|
151
|
+
* @returns the latest value written to slot, or 0 if never written to before
|
|
152
|
+
*/ async peekStorage(contractAddress, slot) {
|
|
171
153
|
const { value, cached } = await this.publicStorage.read(contractAddress, slot);
|
|
172
154
|
this.log.debug(`Storage peek (address=${contractAddress}, slot=${slot}): value=${value}, cached=${cached}`);
|
|
173
155
|
return Promise.resolve(value);
|
|
174
156
|
}
|
|
175
157
|
// TODO(4886): We currently don't silo note hashes.
|
|
176
158
|
/**
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const gotLeafValue = (await this.worldStateDB.getCommitmentValue(leafIndex.toBigInt())) ?? Fr.ZERO;
|
|
159
|
+
* Check if a note hash exists at the given leaf index, trace the check.
|
|
160
|
+
*
|
|
161
|
+
* @param contractAddress - the address of the contract whose storage is being read from
|
|
162
|
+
* @param noteHash - the unsiloed note hash being checked
|
|
163
|
+
* @param leafIndex - the leaf index being checked
|
|
164
|
+
* @returns true if the note hash exists at the given leaf index, false otherwise
|
|
165
|
+
*/ async checkNoteHashExists(contractAddress, noteHash, leafIndex) {
|
|
166
|
+
const gotLeafValue = await this.worldStateDB.getCommitmentValue(leafIndex.toBigInt()) ?? Fr.ZERO;
|
|
186
167
|
const exists = gotLeafValue.equals(noteHash);
|
|
187
168
|
this.log.debug(`noteHashes(${contractAddress})@${noteHash} ?? leafIndex: ${leafIndex} | gotLeafValue: ${gotLeafValue}, exists: ${exists}.`);
|
|
188
169
|
if (this.doMerkleOperations) {
|
|
@@ -190,113 +171,110 @@ export class AvmPersistableStateManager {
|
|
|
190
171
|
// such that the VM can constrain the equality and decide on exists based on that.
|
|
191
172
|
const path = await this.merkleTrees.getSiblingPath(MerkleTreeId.NOTE_HASH_TREE, leafIndex.toBigInt());
|
|
192
173
|
this.trace.traceNoteHashCheck(contractAddress, gotLeafValue, leafIndex, exists, path);
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
174
|
+
} else {
|
|
195
175
|
this.trace.traceNoteHashCheck(contractAddress, gotLeafValue, leafIndex, exists);
|
|
196
176
|
}
|
|
197
177
|
return Promise.resolve(exists);
|
|
198
178
|
}
|
|
199
179
|
/**
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
async writeNoteHash(contractAddress, noteHash) {
|
|
180
|
+
* Write a raw note hash, silo it and make it unique, then trace the write.
|
|
181
|
+
* @param noteHash - the unsiloed note hash to write
|
|
182
|
+
*/ async writeNoteHash(contractAddress, noteHash) {
|
|
204
183
|
const siloedNoteHash = await siloNoteHash(contractAddress, noteHash);
|
|
205
184
|
await this.writeSiloedNoteHash(siloedNoteHash);
|
|
206
185
|
}
|
|
207
186
|
/**
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
async writeSiloedNoteHash(noteHash) {
|
|
187
|
+
* Write a note hash, make it unique, trace the write.
|
|
188
|
+
* @param noteHash - the non unique note hash to write
|
|
189
|
+
*/ async writeSiloedNoteHash(noteHash) {
|
|
212
190
|
const nonce = await computeNoteHashNonce(this.firstNullifier, this.trace.getNoteHashCount());
|
|
213
191
|
const uniqueNoteHash = await computeUniqueNoteHash(nonce, noteHash);
|
|
214
192
|
await this.writeUniqueNoteHash(uniqueNoteHash);
|
|
215
193
|
}
|
|
216
194
|
/**
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
async writeUniqueNoteHash(noteHash) {
|
|
195
|
+
* Write a note hash, trace the write.
|
|
196
|
+
* @param noteHash - the siloed unique hash to write
|
|
197
|
+
*/ async writeUniqueNoteHash(noteHash) {
|
|
221
198
|
this.log.debug(`noteHashes += @${noteHash}.`);
|
|
222
199
|
if (this.doMerkleOperations) {
|
|
223
200
|
// Should write a helper for this
|
|
224
201
|
const leafIndex = new Fr(this.merkleTrees.treeMap.get(MerkleTreeId.NOTE_HASH_TREE).leafCount);
|
|
225
202
|
const insertionPath = await this.merkleTrees.appendNoteHash(noteHash);
|
|
226
203
|
this.trace.traceNewNoteHash(noteHash, leafIndex, insertionPath);
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
204
|
+
} else {
|
|
229
205
|
this.trace.traceNewNoteHash(noteHash);
|
|
230
206
|
}
|
|
231
207
|
}
|
|
232
208
|
/**
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
async checkNullifierExists(contractAddress, nullifier) {
|
|
209
|
+
* Check if a nullifier exists, trace the check.
|
|
210
|
+
* @param contractAddress - address of the contract that the nullifier is associated with
|
|
211
|
+
* @param nullifier - the unsiloed nullifier to check
|
|
212
|
+
* @returns exists - whether the nullifier exists in the nullifier set
|
|
213
|
+
*/ async checkNullifierExists(contractAddress, nullifier) {
|
|
239
214
|
this.log.debug(`Checking existence of nullifier (address=${contractAddress}, nullifier=${nullifier})`);
|
|
240
215
|
const siloedNullifier = await siloNullifier(contractAddress, nullifier);
|
|
241
216
|
const [exists, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(siloedNullifier);
|
|
242
217
|
if (this.doMerkleOperations) {
|
|
243
218
|
this.trace.traceNullifierCheck(siloedNullifier, exists, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath);
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
219
|
+
} else {
|
|
246
220
|
this.trace.traceNullifierCheck(siloedNullifier, exists);
|
|
247
221
|
}
|
|
248
222
|
return Promise.resolve(exists);
|
|
249
223
|
}
|
|
250
224
|
/**
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
async getNullifierMembership(siloedNullifier) {
|
|
225
|
+
* Helper to get membership information for a siloed nullifier when checking its existence.
|
|
226
|
+
* Optionally trace the nullifier check.
|
|
227
|
+
*
|
|
228
|
+
* @param siloedNullifier - the siloed nullifier to get membership information for
|
|
229
|
+
* @returns
|
|
230
|
+
* - exists - whether the nullifier exists in the nullifier set
|
|
231
|
+
* - leafOrLowLeafPreimage - the preimage of the nullifier leaf or its low-leaf if it doesn't exist
|
|
232
|
+
* - leafOrLowLeafIndex - the leaf index of the nullifier leaf or its low-leaf if it doesn't exist
|
|
233
|
+
* - leafOrLowLeafPath - the sibling path of the nullifier leaf or its low-leaf if it doesn't exist
|
|
234
|
+
*/ async getNullifierMembership(siloedNullifier) {
|
|
262
235
|
const [exists, isPending, _] = await this.nullifiers.checkExists(siloedNullifier);
|
|
263
236
|
this.log.debug(`Checked siloed nullifier ${siloedNullifier} (exists=${exists}), pending=${isPending}`);
|
|
264
237
|
if (this.doMerkleOperations) {
|
|
265
238
|
// Get leaf if present, low leaf if absent
|
|
266
239
|
// If leaf is present, hint/trace it. Otherwise, hint/trace the low leaf.
|
|
267
|
-
const { preimage, index: leafIndex, alreadyPresent
|
|
240
|
+
const { preimage, index: leafIndex, alreadyPresent } = await this.merkleTrees.getLeafOrLowLeafInfo(MerkleTreeId.NULLIFIER_TREE, siloedNullifier);
|
|
268
241
|
const leafPreimage = preimage;
|
|
269
242
|
const leafPath = await this.merkleTrees.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, leafIndex);
|
|
270
243
|
assert(alreadyPresent == exists, 'WorldStateDB contains nullifier leaf, but merkle tree does not (or vice versa).... This is a bug!');
|
|
271
244
|
if (exists) {
|
|
272
245
|
this.log.debug(`Siloed nullifier ${siloedNullifier} exists at leafIndex=${leafIndex}`);
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
246
|
+
} else {
|
|
275
247
|
// Sanity check that the leaf value is skipped by low leaf when it doesn't exist
|
|
276
|
-
assert(leafPreimage.nullifier.toBigInt() < siloedNullifier.toBigInt() &&
|
|
277
|
-
(leafPreimage.nextIndex === 0n || leafPreimage.nextNullifier.toBigInt() > siloedNullifier.toBigInt()), 'Nullifier tree low leaf should skip the target leaf nullifier when the target leaf does not exist.');
|
|
248
|
+
assert(leafPreimage.nullifier.toBigInt() < siloedNullifier.toBigInt() && (leafPreimage.nextIndex === 0n || leafPreimage.nextNullifier.toBigInt() > siloedNullifier.toBigInt()), 'Nullifier tree low leaf should skip the target leaf nullifier when the target leaf does not exist.');
|
|
278
249
|
}
|
|
279
|
-
return [
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
250
|
+
return [
|
|
251
|
+
exists,
|
|
252
|
+
leafPreimage,
|
|
253
|
+
new Fr(leafIndex),
|
|
254
|
+
leafPath
|
|
255
|
+
];
|
|
256
|
+
} else {
|
|
257
|
+
return [
|
|
258
|
+
exists,
|
|
259
|
+
NullifierLeafPreimage.empty(),
|
|
260
|
+
Fr.ZERO,
|
|
261
|
+
[]
|
|
262
|
+
];
|
|
283
263
|
}
|
|
284
264
|
}
|
|
285
265
|
/**
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
async writeNullifier(contractAddress, nullifier) {
|
|
266
|
+
* Write a nullifier to the nullifier set, trace the write.
|
|
267
|
+
* @param contractAddress - address of the contract that the nullifier is associated with
|
|
268
|
+
* @param nullifier - the unsiloed nullifier to write
|
|
269
|
+
*/ async writeNullifier(contractAddress, nullifier) {
|
|
291
270
|
this.log.debug(`Inserting new nullifier (address=${nullifier}, nullifier=${contractAddress})`);
|
|
292
271
|
const siloedNullifier = await siloNullifier(contractAddress, nullifier);
|
|
293
272
|
await this.writeSiloedNullifier(siloedNullifier);
|
|
294
273
|
}
|
|
295
274
|
/**
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
async writeSiloedNullifier(siloedNullifier) {
|
|
275
|
+
* Write a nullifier to the nullifier set, trace the write.
|
|
276
|
+
* @param siloedNullifier - the siloed nullifier to write
|
|
277
|
+
*/ async writeSiloedNullifier(siloedNullifier) {
|
|
300
278
|
this.log.debug(`Inserting siloed nullifier=${siloedNullifier}`);
|
|
301
279
|
if (this.doMerkleOperations) {
|
|
302
280
|
// Maybe overkill, but we should check if the nullifier is already present in the tree before attempting to insert
|
|
@@ -309,47 +287,39 @@ export class AvmPersistableStateManager {
|
|
|
309
287
|
// instead we provide the direct membership path
|
|
310
288
|
const path = await this.merkleTrees.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, index);
|
|
311
289
|
// This just becomes a nullifier read hint
|
|
312
|
-
this.trace.traceNullifierCheck(siloedNullifier,
|
|
313
|
-
/*exists=*/ alreadyPresent, preimage, new Fr(index), path);
|
|
290
|
+
this.trace.traceNullifierCheck(siloedNullifier, /*exists=*/ alreadyPresent, preimage, new Fr(index), path);
|
|
314
291
|
throw new NullifierCollisionError(`Siloed nullifier ${siloedNullifier} already exists in parent cache or host.`);
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
292
|
+
} else {
|
|
317
293
|
// Cache pending nullifiers for later access
|
|
318
294
|
await this.nullifiers.append(siloedNullifier);
|
|
319
295
|
// We append the new nullifier
|
|
320
|
-
this.log.debug(`Nullifier tree root before insertion ${await this.merkleTrees.treeMap
|
|
321
|
-
.get(MerkleTreeId.NULLIFIER_TREE)
|
|
322
|
-
.getRoot()}`);
|
|
296
|
+
this.log.debug(`Nullifier tree root before insertion ${await this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE).getRoot()}`);
|
|
323
297
|
const appendResult = await this.merkleTrees.appendNullifier(siloedNullifier);
|
|
324
|
-
this.log.debug(`Nullifier tree root after insertion ${await this.merkleTrees.treeMap
|
|
325
|
-
.get(MerkleTreeId.NULLIFIER_TREE)
|
|
326
|
-
.getRoot()}`);
|
|
298
|
+
this.log.debug(`Nullifier tree root after insertion ${await this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE).getRoot()}`);
|
|
327
299
|
const lowLeafPreimage = appendResult.lowWitness.preimage;
|
|
328
300
|
const lowLeafIndex = appendResult.lowWitness.index;
|
|
329
301
|
const lowLeafPath = appendResult.lowWitness.siblingPath;
|
|
330
302
|
const insertionPath = appendResult.insertionPath;
|
|
331
303
|
this.trace.traceNewNullifier(siloedNullifier, lowLeafPreimage, new Fr(lowLeafIndex), lowLeafPath, insertionPath);
|
|
332
304
|
}
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
305
|
+
} else {
|
|
335
306
|
// Cache pending nullifiers for later access
|
|
336
307
|
await this.nullifiers.append(siloedNullifier);
|
|
337
308
|
this.trace.traceNewNullifier(siloedNullifier);
|
|
338
309
|
}
|
|
339
310
|
}
|
|
340
311
|
async writeSiloedNullifiersFromPrivate(siloedNullifiers) {
|
|
341
|
-
for (const siloedNullifier of siloedNullifiers.filter(n
|
|
312
|
+
for (const siloedNullifier of siloedNullifiers.filter((n)=>!n.isEmpty())){
|
|
342
313
|
await this.writeSiloedNullifier(siloedNullifier);
|
|
343
314
|
}
|
|
344
315
|
}
|
|
345
316
|
/**
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const valueAtIndex = (await this.worldStateDB.getL1ToL2LeafValue(msgLeafIndex.toBigInt())) ?? Fr.ZERO;
|
|
317
|
+
* Check if an L1 to L2 message exists, trace the check.
|
|
318
|
+
* @param msgHash - the message hash to check existence of
|
|
319
|
+
* @param msgLeafIndex - the message leaf index to use in the check
|
|
320
|
+
* @returns exists - whether the message exists in the L1 to L2 Messages tree
|
|
321
|
+
*/ async checkL1ToL2MessageExists(contractAddress, msgHash, msgLeafIndex) {
|
|
322
|
+
const valueAtIndex = await this.worldStateDB.getL1ToL2LeafValue(msgLeafIndex.toBigInt()) ?? Fr.ZERO;
|
|
353
323
|
const exists = valueAtIndex.equals(msgHash);
|
|
354
324
|
this.log.debug(`l1ToL2Messages(@${msgLeafIndex}) ?? exists: ${exists}, expected: ${msgHash}, found: ${valueAtIndex}.`);
|
|
355
325
|
if (this.doMerkleOperations) {
|
|
@@ -358,37 +328,33 @@ export class AvmPersistableStateManager {
|
|
|
358
328
|
// We should defintely add a helper here
|
|
359
329
|
const path = await this.merkleTrees.treeDb.getSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, msgLeafIndex.toBigInt());
|
|
360
330
|
this.trace.traceL1ToL2MessageCheck(contractAddress, valueAtIndex, msgLeafIndex, exists, path.toFields());
|
|
361
|
-
}
|
|
362
|
-
else {
|
|
331
|
+
} else {
|
|
363
332
|
this.trace.traceL1ToL2MessageCheck(contractAddress, valueAtIndex, msgLeafIndex, exists);
|
|
364
333
|
}
|
|
365
334
|
return Promise.resolve(exists);
|
|
366
335
|
}
|
|
367
336
|
/**
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
writeL2ToL1Message(contractAddress, recipient, content) {
|
|
337
|
+
* Write an L2 to L1 message.
|
|
338
|
+
* @param contractAddress - L2 contract address that created this message
|
|
339
|
+
* @param recipient - L1 contract address to send the message to.
|
|
340
|
+
* @param content - Message content.
|
|
341
|
+
*/ writeL2ToL1Message(contractAddress, recipient, content) {
|
|
374
342
|
this.log.debug(`L2ToL1Messages(${contractAddress}) += (recipient: ${recipient}, content: ${content}).`);
|
|
375
343
|
this.trace.traceNewL2ToL1Message(contractAddress, recipient, content);
|
|
376
344
|
}
|
|
377
345
|
/**
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
writePublicLog(contractAddress, log) {
|
|
346
|
+
* Write a public log
|
|
347
|
+
* @param contractAddress - address of the contract that emitted the log
|
|
348
|
+
* @param log - log contents
|
|
349
|
+
*/ writePublicLog(contractAddress, log) {
|
|
383
350
|
this.log.debug(`PublicLog(${contractAddress}) += event with ${log.length} fields.`);
|
|
384
351
|
this.trace.tracePublicLog(contractAddress, log);
|
|
385
352
|
}
|
|
386
353
|
/**
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
async getContractInstance(contractAddress) {
|
|
354
|
+
* Get a contract instance.
|
|
355
|
+
* @param contractAddress - address of the contract instance to retrieve.
|
|
356
|
+
* @returns the contract instance or undefined if it does not exist.
|
|
357
|
+
*/ async getContractInstance(contractAddress) {
|
|
392
358
|
this.log.debug(`Getting contract instance for address ${contractAddress}`);
|
|
393
359
|
const instanceWithAddress = await this.worldStateDB.getContractInstance(contractAddress);
|
|
394
360
|
const exists = instanceWithAddress !== undefined;
|
|
@@ -396,12 +362,11 @@ export class AvmPersistableStateManager {
|
|
|
396
362
|
exists,
|
|
397
363
|
NullifierLeafPreimage.empty(),
|
|
398
364
|
Fr.ZERO,
|
|
399
|
-
new Array()
|
|
365
|
+
new Array()
|
|
400
366
|
];
|
|
401
367
|
if (!contractAddressIsCanonical(contractAddress)) {
|
|
402
368
|
const contractAddressNullifier = await siloNullifier(AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS), contractAddress.toField());
|
|
403
|
-
[existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
|
|
404
|
-
/*siloedNullifier=*/ contractAddressNullifier);
|
|
369
|
+
[existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(/*siloedNullifier=*/ contractAddressNullifier);
|
|
405
370
|
assert(exists == existsInTree, 'WorldStateDB contains contract instance, but nullifier tree does not contain contract address (or vice versa).... This is a bug!');
|
|
406
371
|
}
|
|
407
372
|
if (exists) {
|
|
@@ -409,28 +374,23 @@ export class AvmPersistableStateManager {
|
|
|
409
374
|
this.log.debug(`Got contract instance (address=${contractAddress}): exists=${exists}, instance=${jsonStringify(instance)}`);
|
|
410
375
|
if (this.doMerkleOperations) {
|
|
411
376
|
this.trace.traceGetContractInstance(contractAddress, exists, instance, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath);
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
377
|
+
} else {
|
|
414
378
|
this.trace.traceGetContractInstance(contractAddress, exists, instance);
|
|
415
379
|
}
|
|
416
380
|
return Promise.resolve(instance);
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
381
|
+
} else {
|
|
419
382
|
this.log.debug(`Contract instance NOT FOUND (address=${contractAddress})`);
|
|
420
383
|
if (this.doMerkleOperations) {
|
|
421
|
-
this.trace.traceGetContractInstance(contractAddress, exists,
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
else {
|
|
384
|
+
this.trace.traceGetContractInstance(contractAddress, exists, /*instance=*/ undefined, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath);
|
|
385
|
+
} else {
|
|
425
386
|
this.trace.traceGetContractInstance(contractAddress, exists);
|
|
426
387
|
}
|
|
427
388
|
return Promise.resolve(undefined);
|
|
428
389
|
}
|
|
429
390
|
}
|
|
430
391
|
/**
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
async getBytecode(contractAddress) {
|
|
392
|
+
* Get a contract's bytecode from the contracts DB, also trace the contract class and instance
|
|
393
|
+
*/ async getBytecode(contractAddress) {
|
|
434
394
|
this.log.debug(`Getting bytecode for contract address ${contractAddress}`);
|
|
435
395
|
const instanceWithAddress = await this.worldStateDB.getContractInstance(contractAddress);
|
|
436
396
|
const exists = instanceWithAddress !== undefined;
|
|
@@ -438,12 +398,11 @@ export class AvmPersistableStateManager {
|
|
|
438
398
|
exists,
|
|
439
399
|
NullifierLeafPreimage.empty(),
|
|
440
400
|
Fr.ZERO,
|
|
441
|
-
new Array()
|
|
401
|
+
new Array()
|
|
442
402
|
];
|
|
443
403
|
if (!contractAddressIsCanonical(contractAddress)) {
|
|
444
404
|
const contractAddressNullifier = await siloNullifier(AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS), contractAddress.toField());
|
|
445
|
-
[existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
|
|
446
|
-
/*siloedNullifier=*/ contractAddressNullifier);
|
|
405
|
+
[existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(/*siloedNullifier=*/ contractAddressNullifier);
|
|
447
406
|
assert(exists == existsInTree, 'WorldStateDB contains contract instance, but nullifier tree does not contain contract address (or vice versa).... This is a bug!');
|
|
448
407
|
}
|
|
449
408
|
if (exists) {
|
|
@@ -455,27 +414,21 @@ export class AvmPersistableStateManager {
|
|
|
455
414
|
const contractClassPreimage = {
|
|
456
415
|
artifactHash: contractClass.artifactHash,
|
|
457
416
|
privateFunctionsRoot: contractClass.privateFunctionsRoot,
|
|
458
|
-
publicBytecodeCommitment: bytecodeCommitment
|
|
417
|
+
publicBytecodeCommitment: bytecodeCommitment
|
|
459
418
|
};
|
|
460
419
|
if (this.doMerkleOperations) {
|
|
461
420
|
this.trace.traceGetBytecode(contractAddress, exists, contractClass.packedBytecode, instance, contractClassPreimage, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath);
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
421
|
+
} else {
|
|
464
422
|
this.trace.traceGetBytecode(contractAddress, exists, contractClass.packedBytecode, instance, contractClassPreimage);
|
|
465
423
|
}
|
|
466
424
|
return contractClass.packedBytecode;
|
|
467
|
-
}
|
|
468
|
-
else {
|
|
425
|
+
} else {
|
|
469
426
|
// If the contract instance is not found, we assume it has not been deployed.
|
|
470
427
|
// It doesnt matter what the values of the contract instance are in this case, as long as we tag it with exists=false.
|
|
471
428
|
// This will hint to the avm circuit to just perform the non-membership check on the address and disregard the bytecode hash
|
|
472
429
|
if (this.doMerkleOperations) {
|
|
473
|
-
this.trace.traceGetBytecode(contractAddress, exists,
|
|
474
|
-
|
|
475
|
-
/*contractClass=*/ undefined,
|
|
476
|
-
/*bytecode=*/ undefined, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath);
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
430
|
+
this.trace.traceGetBytecode(contractAddress, exists, /*instance=*/ undefined, /*contractClass=*/ undefined, /*bytecode=*/ undefined, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath);
|
|
431
|
+
} else {
|
|
479
432
|
this.trace.traceGetBytecode(contractAddress, exists); // bytecode, instance, class undefined
|
|
480
433
|
}
|
|
481
434
|
return undefined;
|
|
@@ -489,11 +442,5 @@ export class AvmPersistableStateManager {
|
|
|
489
442
|
}
|
|
490
443
|
}
|
|
491
444
|
function contractAddressIsCanonical(contractAddress) {
|
|
492
|
-
return
|
|
493
|
-
contractAddress.equals(AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS)) ||
|
|
494
|
-
contractAddress.equals(AztecAddress.fromNumber(REGISTERER_CONTRACT_ADDRESS)) ||
|
|
495
|
-
contractAddress.equals(AztecAddress.fromNumber(MULTI_CALL_ENTRYPOINT_ADDRESS)) ||
|
|
496
|
-
contractAddress.equals(AztecAddress.fromNumber(FEE_JUICE_ADDRESS)) ||
|
|
497
|
-
contractAddress.equals(AztecAddress.fromNumber(ROUTER_ADDRESS)));
|
|
445
|
+
return contractAddress.equals(AztecAddress.fromNumber(CANONICAL_AUTH_REGISTRY_ADDRESS)) || contractAddress.equals(AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS)) || contractAddress.equals(AztecAddress.fromNumber(REGISTERER_CONTRACT_ADDRESS)) || contractAddress.equals(AztecAddress.fromNumber(MULTI_CALL_ENTRYPOINT_ADDRESS)) || contractAddress.equals(AztecAddress.fromNumber(FEE_JUICE_ADDRESS)) || contractAddress.equals(AztecAddress.fromNumber(ROUTER_ADDRESS));
|
|
498
446
|
}
|
|
499
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam91cm5hbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hdm0vam91cm5hbC9qb3VybmFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRCxPQUFPLEVBQ0wsWUFBWSxFQUNaLCtCQUErQixFQUMvQix5QkFBeUIsRUFDekIsaUJBQWlCLEVBQ2pCLDZCQUE2QixFQUM3QixxQkFBcUIsRUFHckIsMkJBQTJCLEVBQzNCLGNBQWMsRUFDZCw0QkFBNEIsR0FDN0IsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLDZCQUE2QixFQUM3QixxQkFBcUIsRUFDckIsWUFBWSxFQUNaLGFBQWEsR0FDZCxNQUFNLHlCQUF5QixDQUFDO0FBQ2pDLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXJELE9BQU8sRUFBRSxNQUFNLElBQUksTUFBTSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRTFDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBSTNFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVwRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sT0FBTywwQkFBMEI7SUFNckM7SUFDRSxnQ0FBZ0M7SUFDZixZQUEwQjtJQUMzQyx3QkFBd0I7SUFDeEIsK0RBQStEO0lBQy9DLEtBQXFDO0lBQ3JELDhDQUE4QztJQUM3QixnQkFB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
|