@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.
Files changed (304) hide show
  1. package/dest/acvm/acvm.js +18 -21
  2. package/dest/acvm/acvm_types.js +3 -2
  3. package/dest/acvm/deserialize.js +9 -13
  4. package/dest/acvm/index.js +0 -1
  5. package/dest/acvm/oracle/index.js +0 -1
  6. package/dest/acvm/oracle/oracle.js +42 -23
  7. package/dest/acvm/oracle/typed_oracle.js +36 -38
  8. package/dest/acvm/serialize.js +7 -14
  9. package/dest/avm/avm_context.js +24 -27
  10. package/dest/avm/avm_contract_call_result.js +12 -7
  11. package/dest/avm/avm_execution_environment.js +10 -7
  12. package/dest/avm/avm_gas.js +93 -56
  13. package/dest/avm/avm_machine_state.js +60 -61
  14. package/dest/avm/avm_memory_types.js +166 -255
  15. package/dest/avm/avm_simulator.js +68 -47
  16. package/dest/avm/avm_tree.js +282 -276
  17. package/dest/avm/bytecode_utils.js +8 -6
  18. package/dest/avm/errors.js +46 -63
  19. package/dest/avm/fixtures/avm_simulation_tester.js +18 -17
  20. package/dest/avm/fixtures/base_avm_simulation_tester.js +21 -16
  21. package/dest/avm/fixtures/index.js +27 -26
  22. package/dest/avm/fixtures/simple_contract_data_source.js +9 -13
  23. package/dest/avm/index.js +0 -1
  24. package/dest/avm/journal/index.js +0 -1
  25. package/dest/avm/journal/journal.js +147 -200
  26. package/dest/avm/journal/nullifiers.js +43 -46
  27. package/dest/avm/journal/public_storage.js +73 -87
  28. package/dest/avm/opcodes/accrued_substate.js +140 -110
  29. package/dest/avm/opcodes/addressing_mode.js +29 -31
  30. package/dest/avm/opcodes/arithmetic.js +17 -15
  31. package/dest/avm/opcodes/bitwise.js +40 -26
  32. package/dest/avm/opcodes/comparators.js +12 -10
  33. package/dest/avm/opcodes/contract.js +31 -29
  34. package/dest/avm/opcodes/control_flow.js +47 -43
  35. package/dest/avm/opcodes/conversion.js +30 -26
  36. package/dest/avm/opcodes/ec_add.js +35 -34
  37. package/dest/avm/opcodes/environment_getters.js +33 -33
  38. package/dest/avm/opcodes/external_calls.js +83 -74
  39. package/dest/avm/opcodes/hashing.js +69 -61
  40. package/dest/avm/opcodes/index.js +0 -1
  41. package/dest/avm/opcodes/instruction.js +31 -40
  42. package/dest/avm/opcodes/instruction_impl.js +12 -15
  43. package/dest/avm/opcodes/memory.js +177 -156
  44. package/dest/avm/opcodes/misc.js +27 -25
  45. package/dest/avm/opcodes/multi_scalar_mul.js +43 -41
  46. package/dest/avm/opcodes/storage.js +28 -25
  47. package/dest/avm/serialization/buffer_cursor.js +4 -4
  48. package/dest/avm/serialization/bytecode_serialization.js +292 -89
  49. package/dest/avm/serialization/instruction_serialization.js +67 -28
  50. package/dest/avm/test_utils.js +6 -9
  51. package/dest/client/client_execution_context.js +197 -219
  52. package/dest/client/db_oracle.js +4 -7
  53. package/dest/client/execution_note_cache.js +80 -81
  54. package/dest/client/index.js +0 -1
  55. package/dest/client/pick_notes.js +27 -30
  56. package/dest/client/private_execution.js +13 -14
  57. package/dest/client/simulator.js +44 -48
  58. package/dest/client/unconstrained_execution.js +8 -11
  59. package/dest/client/view_data_oracle.js +130 -139
  60. package/dest/common/debug_fn_name.js +1 -4
  61. package/dest/common/errors.js +30 -39
  62. package/dest/common/hashed_values_cache.js +16 -20
  63. package/dest/common/index.js +0 -1
  64. package/dest/common/message_load_oracle_inputs.js +7 -7
  65. package/dest/common/simulation_provider.js +3 -6
  66. package/dest/common.js +0 -1
  67. package/dest/providers/acvm_native.js +46 -32
  68. package/dest/providers/acvm_wasm.js +18 -10
  69. package/dest/providers/acvm_wasm_with_blobs.js +2 -5
  70. package/dest/providers/factory.js +5 -5
  71. package/dest/providers/index.js +0 -1
  72. package/dest/public/bytecode_errors.js +1 -2
  73. package/dest/public/db_interfaces.js +1 -2
  74. package/dest/public/execution.js +2 -4
  75. package/dest/public/executor_metrics.js +16 -12
  76. package/dest/public/fee_payment.js +2 -5
  77. package/dest/public/fixtures/index.js +0 -1
  78. package/dest/public/fixtures/public_tx_simulation_tester.js +13 -17
  79. package/dest/public/fixtures/utils.js +11 -14
  80. package/dest/public/index.js +0 -1
  81. package/dest/public/public_db_sources.js +79 -87
  82. package/dest/public/public_processor.js +310 -306
  83. package/dest/public/public_processor_metrics.js +46 -27
  84. package/dest/public/public_tx_context.js +97 -118
  85. package/dest/public/public_tx_simulator.js +299 -314
  86. package/dest/public/side_effect_errors.js +1 -2
  87. package/dest/public/side_effect_trace.js +44 -71
  88. package/dest/public/side_effect_trace_interface.js +1 -2
  89. package/dest/public/unique_class_ids.js +22 -27
  90. package/dest/public/utils.js +16 -11
  91. package/dest/server.js +0 -1
  92. package/dest/stats/index.js +0 -1
  93. package/dest/stats/stats.js +1 -2
  94. package/dest/test/utils.js +5 -4
  95. package/package.json +11 -11
  96. package/src/acvm/oracle/typed_oracle.ts +34 -34
  97. package/src/avm/avm_machine_state.ts +18 -14
  98. package/src/avm/avm_memory_types.ts +43 -183
  99. package/src/avm/avm_simulator.ts +37 -11
  100. package/src/avm/opcodes/accrued_substate.ts +7 -21
  101. package/src/avm/opcodes/addressing_mode.ts +9 -2
  102. package/src/avm/opcodes/arithmetic.ts +1 -3
  103. package/src/avm/opcodes/bitwise.ts +2 -6
  104. package/src/avm/opcodes/comparators.ts +1 -3
  105. package/src/avm/opcodes/contract.ts +1 -3
  106. package/src/avm/opcodes/control_flow.ts +1 -9
  107. package/src/avm/opcodes/conversion.ts +1 -3
  108. package/src/avm/opcodes/ec_add.ts +1 -3
  109. package/src/avm/opcodes/environment_getters.ts +1 -3
  110. package/src/avm/opcodes/external_calls.ts +3 -6
  111. package/src/avm/opcodes/hashing.ts +3 -9
  112. package/src/avm/opcodes/memory.ts +6 -20
  113. package/src/avm/opcodes/misc.ts +1 -3
  114. package/src/avm/opcodes/multi_scalar_mul.ts +1 -7
  115. package/src/avm/opcodes/storage.ts +2 -6
  116. package/src/client/index.ts +2 -2
  117. package/dest/acvm/acvm.d.ts +0 -35
  118. package/dest/acvm/acvm.d.ts.map +0 -1
  119. package/dest/acvm/acvm_types.d.ts +0 -10
  120. package/dest/acvm/acvm_types.d.ts.map +0 -1
  121. package/dest/acvm/deserialize.d.ts +0 -36
  122. package/dest/acvm/deserialize.d.ts.map +0 -1
  123. package/dest/acvm/index.d.ts +0 -6
  124. package/dest/acvm/index.d.ts.map +0 -1
  125. package/dest/acvm/oracle/index.d.ts +0 -14
  126. package/dest/acvm/oracle/index.d.ts.map +0 -1
  127. package/dest/acvm/oracle/oracle.d.ts +0 -49
  128. package/dest/acvm/oracle/oracle.d.ts.map +0 -1
  129. package/dest/acvm/oracle/typed_oracle.d.ts +0 -75
  130. package/dest/acvm/oracle/typed_oracle.d.ts.map +0 -1
  131. package/dest/acvm/serialize.d.ts +0 -20
  132. package/dest/acvm/serialize.d.ts.map +0 -1
  133. package/dest/avm/avm_context.d.ts +0 -39
  134. package/dest/avm/avm_context.d.ts.map +0 -1
  135. package/dest/avm/avm_contract_call_result.d.ts +0 -30
  136. package/dest/avm/avm_contract_call_result.d.ts.map +0 -1
  137. package/dest/avm/avm_execution_environment.d.ts +0 -21
  138. package/dest/avm/avm_execution_environment.d.ts.map +0 -1
  139. package/dest/avm/avm_gas.d.ts +0 -60
  140. package/dest/avm/avm_gas.d.ts.map +0 -1
  141. package/dest/avm/avm_machine_state.d.ts +0 -93
  142. package/dest/avm/avm_machine_state.d.ts.map +0 -1
  143. package/dest/avm/avm_memory_types.d.ts +0 -310
  144. package/dest/avm/avm_memory_types.d.ts.map +0 -1
  145. package/dest/avm/avm_simulator.d.ts +0 -37
  146. package/dest/avm/avm_simulator.d.ts.map +0 -1
  147. package/dest/avm/avm_tree.d.ts +0 -281
  148. package/dest/avm/avm_tree.d.ts.map +0 -1
  149. package/dest/avm/bytecode_utils.d.ts +0 -5
  150. package/dest/avm/bytecode_utils.d.ts.map +0 -1
  151. package/dest/avm/errors.d.ts +0 -121
  152. package/dest/avm/errors.d.ts.map +0 -1
  153. package/dest/avm/fixtures/avm_simulation_tester.d.ts +0 -21
  154. package/dest/avm/fixtures/avm_simulation_tester.d.ts.map +0 -1
  155. package/dest/avm/fixtures/base_avm_simulation_tester.d.ts +0 -35
  156. package/dest/avm/fixtures/base_avm_simulation_tester.d.ts.map +0 -1
  157. package/dest/avm/fixtures/index.d.ts +0 -67
  158. package/dest/avm/fixtures/index.d.ts.map +0 -1
  159. package/dest/avm/fixtures/simple_contract_data_source.d.ts +0 -31
  160. package/dest/avm/fixtures/simple_contract_data_source.d.ts.map +0 -1
  161. package/dest/avm/index.d.ts +0 -4
  162. package/dest/avm/index.d.ts.map +0 -1
  163. package/dest/avm/journal/index.d.ts +0 -2
  164. package/dest/avm/journal/index.d.ts.map +0 -1
  165. package/dest/avm/journal/journal.d.ts +0 -176
  166. package/dest/avm/journal/journal.d.ts.map +0 -1
  167. package/dest/avm/journal/nullifiers.d.ts +0 -62
  168. package/dest/avm/journal/nullifiers.d.ts.map +0 -1
  169. package/dest/avm/journal/public_storage.d.ts +0 -66
  170. package/dest/avm/journal/public_storage.d.ts.map +0 -1
  171. package/dest/avm/opcodes/accrued_substate.d.ts +0 -75
  172. package/dest/avm/opcodes/accrued_substate.d.ts.map +0 -1
  173. package/dest/avm/opcodes/addressing_mode.d.ts +0 -27
  174. package/dest/avm/opcodes/addressing_mode.d.ts.map +0 -1
  175. package/dest/avm/opcodes/arithmetic.d.ts +0 -37
  176. package/dest/avm/opcodes/arithmetic.d.ts.map +0 -1
  177. package/dest/avm/opcodes/bitwise.d.ts +0 -50
  178. package/dest/avm/opcodes/bitwise.d.ts.map +0 -1
  179. package/dest/avm/opcodes/comparators.d.ts +0 -25
  180. package/dest/avm/opcodes/comparators.d.ts.map +0 -1
  181. package/dest/avm/opcodes/contract.d.ts +0 -21
  182. package/dest/avm/opcodes/contract.d.ts.map +0 -1
  183. package/dest/avm/opcodes/control_flow.d.ts +0 -41
  184. package/dest/avm/opcodes/control_flow.d.ts.map +0 -1
  185. package/dest/avm/opcodes/conversion.d.ts +0 -17
  186. package/dest/avm/opcodes/conversion.d.ts.map +0 -1
  187. package/dest/avm/opcodes/ec_add.d.ts +0 -19
  188. package/dest/avm/opcodes/ec_add.d.ts.map +0 -1
  189. package/dest/avm/opcodes/environment_getters.d.ts +0 -28
  190. package/dest/avm/opcodes/environment_getters.d.ts.map +0 -1
  191. package/dest/avm/opcodes/external_calls.d.ts +0 -50
  192. package/dest/avm/opcodes/external_calls.d.ts.map +0 -1
  193. package/dest/avm/opcodes/hashing.d.ts +0 -36
  194. package/dest/avm/opcodes/hashing.d.ts.map +0 -1
  195. package/dest/avm/opcodes/index.d.ts +0 -16
  196. package/dest/avm/opcodes/index.d.ts.map +0 -1
  197. package/dest/avm/opcodes/instruction.d.ts +0 -70
  198. package/dest/avm/opcodes/instruction.d.ts.map +0 -1
  199. package/dest/avm/opcodes/instruction_impl.d.ts +0 -19
  200. package/dest/avm/opcodes/instruction_impl.d.ts.map +0 -1
  201. package/dest/avm/opcodes/memory.d.ts +0 -74
  202. package/dest/avm/opcodes/memory.d.ts.map +0 -1
  203. package/dest/avm/opcodes/misc.d.ts +0 -17
  204. package/dest/avm/opcodes/misc.d.ts.map +0 -1
  205. package/dest/avm/opcodes/multi_scalar_mul.d.ts +0 -16
  206. package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +0 -1
  207. package/dest/avm/opcodes/storage.d.ts +0 -24
  208. package/dest/avm/opcodes/storage.d.ts.map +0 -1
  209. package/dest/avm/serialization/buffer_cursor.d.ts +0 -28
  210. package/dest/avm/serialization/buffer_cursor.d.ts.map +0 -1
  211. package/dest/avm/serialization/bytecode_serialization.d.ts +0 -21
  212. package/dest/avm/serialization/bytecode_serialization.d.ts.map +0 -1
  213. package/dest/avm/serialization/instruction_serialization.d.ts +0 -105
  214. package/dest/avm/serialization/instruction_serialization.d.ts.map +0 -1
  215. package/dest/avm/test_utils.d.ts +0 -16
  216. package/dest/avm/test_utils.d.ts.map +0 -1
  217. package/dest/client/client_execution_context.d.ts +0 -214
  218. package/dest/client/client_execution_context.d.ts.map +0 -1
  219. package/dest/client/db_oracle.d.ts +0 -229
  220. package/dest/client/db_oracle.d.ts.map +0 -1
  221. package/dest/client/execution_note_cache.d.ts +0 -93
  222. package/dest/client/execution_note_cache.d.ts.map +0 -1
  223. package/dest/client/index.d.ts +0 -15
  224. package/dest/client/index.d.ts.map +0 -1
  225. package/dest/client/pick_notes.d.ts +0 -85
  226. package/dest/client/pick_notes.d.ts.map +0 -1
  227. package/dest/client/private_execution.d.ts +0 -19
  228. package/dest/client/private_execution.d.ts.map +0 -1
  229. package/dest/client/simulator.d.ts +0 -60
  230. package/dest/client/simulator.d.ts.map +0 -1
  231. package/dest/client/unconstrained_execution.d.ts +0 -10
  232. package/dest/client/unconstrained_execution.d.ts.map +0 -1
  233. package/dest/client/view_data_oracle.d.ts +0 -159
  234. package/dest/client/view_data_oracle.d.ts.map +0 -1
  235. package/dest/common/debug_fn_name.d.ts +0 -4
  236. package/dest/common/debug_fn_name.d.ts.map +0 -1
  237. package/dest/common/errors.d.ts +0 -54
  238. package/dest/common/errors.d.ts.map +0 -1
  239. package/dest/common/hashed_values_cache.d.ts +0 -28
  240. package/dest/common/hashed_values_cache.d.ts.map +0 -1
  241. package/dest/common/index.d.ts +0 -3
  242. package/dest/common/index.d.ts.map +0 -1
  243. package/dest/common/message_load_oracle_inputs.d.ts +0 -15
  244. package/dest/common/message_load_oracle_inputs.d.ts.map +0 -1
  245. package/dest/common/simulation_provider.d.ts +0 -19
  246. package/dest/common/simulation_provider.d.ts.map +0 -1
  247. package/dest/common.d.ts +0 -2
  248. package/dest/common.d.ts.map +0 -1
  249. package/dest/providers/acvm_native.d.ts +0 -40
  250. package/dest/providers/acvm_native.d.ts.map +0 -1
  251. package/dest/providers/acvm_wasm.d.ts +0 -15
  252. package/dest/providers/acvm_wasm.d.ts.map +0 -1
  253. package/dest/providers/acvm_wasm_with_blobs.d.ts +0 -19
  254. package/dest/providers/acvm_wasm_with_blobs.d.ts.map +0 -1
  255. package/dest/providers/factory.d.ts +0 -12
  256. package/dest/providers/factory.d.ts.map +0 -1
  257. package/dest/providers/index.d.ts +0 -5
  258. package/dest/providers/index.d.ts.map +0 -1
  259. package/dest/public/bytecode_errors.d.ts +0 -4
  260. package/dest/public/bytecode_errors.d.ts.map +0 -1
  261. package/dest/public/db_interfaces.d.ts +0 -105
  262. package/dest/public/db_interfaces.d.ts.map +0 -1
  263. package/dest/public/execution.d.ts +0 -102
  264. package/dest/public/execution.d.ts.map +0 -1
  265. package/dest/public/executor_metrics.d.ts +0 -13
  266. package/dest/public/executor_metrics.d.ts.map +0 -1
  267. package/dest/public/fee_payment.d.ts +0 -11
  268. package/dest/public/fee_payment.d.ts.map +0 -1
  269. package/dest/public/fixtures/index.d.ts +0 -3
  270. package/dest/public/fixtures/index.d.ts.map +0 -1
  271. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +0 -21
  272. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +0 -1
  273. package/dest/public/fixtures/utils.d.ts +0 -17
  274. package/dest/public/fixtures/utils.d.ts.map +0 -1
  275. package/dest/public/index.d.ts +0 -9
  276. package/dest/public/index.d.ts.map +0 -1
  277. package/dest/public/public_db_sources.d.ts +0 -81
  278. package/dest/public/public_db_sources.d.ts.map +0 -1
  279. package/dest/public/public_processor.d.ts +0 -72
  280. package/dest/public/public_processor.d.ts.map +0 -1
  281. package/dest/public/public_processor_metrics.d.ts +0 -27
  282. package/dest/public/public_processor_metrics.d.ts.map +0 -1
  283. package/dest/public/public_tx_context.d.ts +0 -131
  284. package/dest/public/public_tx_context.d.ts.map +0 -1
  285. package/dest/public/public_tx_simulator.d.ts +0 -99
  286. package/dest/public/public_tx_simulator.d.ts.map +0 -1
  287. package/dest/public/side_effect_errors.d.ts +0 -4
  288. package/dest/public/side_effect_errors.d.ts.map +0 -1
  289. package/dest/public/side_effect_trace.d.ts +0 -126
  290. package/dest/public/side_effect_trace.d.ts.map +0 -1
  291. package/dest/public/side_effect_trace_interface.d.ts +0 -32
  292. package/dest/public/side_effect_trace_interface.d.ts.map +0 -1
  293. package/dest/public/unique_class_ids.d.ts +0 -37
  294. package/dest/public/unique_class_ids.d.ts.map +0 -1
  295. package/dest/public/utils.d.ts +0 -5
  296. package/dest/public/utils.d.ts.map +0 -1
  297. package/dest/server.d.ts +0 -6
  298. package/dest/server.d.ts.map +0 -1
  299. package/dest/stats/index.d.ts +0 -2
  300. package/dest/stats/index.d.ts.map +0 -1
  301. package/dest/stats/stats.d.ts +0 -4
  302. package/dest/stats/stats.d.ts.map +0 -1
  303. package/dest/test/utils.d.ts +0 -12
  304. package/dest/test/utils.d.ts.map +0 -1
@@ -4,19 +4,18 @@ import { poseidon2Hash } from '@aztec/foundation/crypto';
4
4
  import { Fr } from '@aztec/foundation/fields';
5
5
  import { strict as assert } from 'assert';
6
6
  import cloneDeep from 'lodash.clonedeep';
7
- /****************************************************/
8
- /****** The AvmEphemeralForest Class ****************/
9
- /****************************************************/
10
- /**
7
+ /****************************************************/ /****** The AvmEphemeralForest Class ****************/ /****************************************************/ /**
11
8
  * This provides a forkable abstraction over the EphemeralAvmTree class
12
9
  * It contains the logic to look up into a read-only MerkleTreeDb to discover
13
10
  * the sibling paths and low witnesses that weren't inserted as part of this tx
14
- */
15
- export class AvmEphemeralForest {
16
- constructor(treeDb, treeMap,
17
- // This contains the [leaf index,indexed leaf preimages] tuple that were updated or inserted in the ephemeral tree
11
+ */ export class AvmEphemeralForest {
12
+ treeDb;
13
+ treeMap;
14
+ indexedUpdates;
15
+ indexedSortedKeys;
16
+ constructor(treeDb, treeMap, // This contains the [leaf index,indexed leaf preimages] tuple that were updated or inserted in the ephemeral tree
18
17
  // This is needed since we have a sparse collection of keys sorted leaves in the ephemeral tree
19
- indexedUpdates, indexedSortedKeys) {
18
+ indexedUpdates, indexedSortedKeys){
20
19
  this.treeDb = treeDb;
21
20
  this.treeMap = treeMap;
22
21
  this.indexedUpdates = indexedUpdates;
@@ -24,7 +23,11 @@ export class AvmEphemeralForest {
24
23
  }
25
24
  static async create(treeDb) {
26
25
  const treeMap = new Map();
27
- for (const treeType of [MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.PUBLIC_DATA_TREE]) {
26
+ for (const treeType of [
27
+ MerkleTreeId.NULLIFIER_TREE,
28
+ MerkleTreeId.NOTE_HASH_TREE,
29
+ MerkleTreeId.PUBLIC_DATA_TREE
30
+ ]){
28
31
  const treeInfo = await treeDb.getTreeInfo(treeType);
29
32
  const tree = await EphemeralAvmTree.create(treeInfo.size, treeInfo.depth, treeDb, treeType);
30
33
  treeMap.set(treeType, tree);
@@ -38,12 +41,11 @@ export class AvmEphemeralForest {
38
41
  return new AvmEphemeralForest(this.treeDb, cloneDeep(this.treeMap), cloneDeep(this.indexedUpdates), cloneDeep(this.indexedSortedKeys));
39
42
  }
40
43
  /**
41
- * Gets sibling path for a leaf - if the sibling path is not found in the tree, it is fetched from the DB
42
- * @param treeId - The tree to be queried for a sibling path.
43
- * @param index - The index of the leaf for which a sibling path should be returned.
44
- * @returns The sibling path of the leaf.
45
- */
46
- async getSiblingPath(treeId, index) {
44
+ * Gets sibling path for a leaf - if the sibling path is not found in the tree, it is fetched from the DB
45
+ * @param treeId - The tree to be queried for a sibling path.
46
+ * @param index - The index of the leaf for which a sibling path should be returned.
47
+ * @returns The sibling path of the leaf.
48
+ */ async getSiblingPath(treeId, index) {
47
49
  const tree = this.treeMap.get(treeId);
48
50
  let path = await tree.getSiblingPath(index);
49
51
  if (path === undefined) {
@@ -51,7 +53,7 @@ export class AvmEphemeralForest {
51
53
  path = (await this.treeDb.getSiblingPath(treeId, index)).toFields();
52
54
  // Since the sibling path could be outdated, we compare it with nodes in our tree
53
55
  // if we encounter a mismatch, we replace it with the node we found in our tree.
54
- for (let i = 0; i < path.length; i++) {
56
+ for(let i = 0; i < path.length; i++){
55
57
  const siblingIndex = index ^ 1n;
56
58
  const node = tree.getNode(siblingIndex, tree.depth - i);
57
59
  if (node !== undefined) {
@@ -66,14 +68,13 @@ export class AvmEphemeralForest {
66
68
  return path;
67
69
  }
68
70
  /**
69
- * This does the work of appending the new leaf and updating the low witness
70
- * @param treeId - The tree to be queried for a sibling path.
71
- * @param lowWitnessIndex - The index of the low leaf in the tree.
72
- * @param lowWitness - The preimage of the low leaf.
73
- * @param newLeafPreimage - The preimage of the new leaf to be inserted.
74
- * @returns The sibling path of the new leaf (i.e. the insertion path)
75
- */
76
- async appendIndexedTree(treeId, lowLeafIndex, lowLeafPreimage, newLeafPreimage) {
71
+ * This does the work of appending the new leaf and updating the low witness
72
+ * @param treeId - The tree to be queried for a sibling path.
73
+ * @param lowWitnessIndex - The index of the low leaf in the tree.
74
+ * @param lowWitness - The preimage of the low leaf.
75
+ * @param newLeafPreimage - The preimage of the new leaf to be inserted.
76
+ * @returns The sibling path of the new leaf (i.e. the insertion path)
77
+ */ async appendIndexedTree(treeId, lowLeafIndex, lowLeafPreimage, newLeafPreimage) {
77
78
  const tree = this.treeMap.get(treeId);
78
79
  const newLeaf = await this.hashPreimage(newLeafPreimage);
79
80
  const insertIndex = tree.leafCount;
@@ -84,15 +85,14 @@ export class AvmEphemeralForest {
84
85
  // Append the new leaf
85
86
  tree.appendLeaf(newLeaf);
86
87
  this.setIndexedUpdates(treeId, insertIndex, newLeafPreimage);
87
- return (await tree.getSiblingPath(insertIndex));
88
+ return await tree.getSiblingPath(insertIndex);
88
89
  }
89
90
  /**
90
- * This writes or updates a slot in the public data tree with a value
91
- * @param slot - The slot to be written to.
92
- * @param newValue - The value to be written or updated to
93
- * @returns The insertion result which contains the insertion path, low leaf and the new leaf index
94
- */
95
- async writePublicStorage(slot, newValue) {
91
+ * This writes or updates a slot in the public data tree with a value
92
+ * @param slot - The slot to be written to.
93
+ * @param newValue - The value to be written or updated to
94
+ * @returns The insertion result which contains the insertion path, low leaf and the new leaf index
95
+ */ async writePublicStorage(slot, newValue) {
96
96
  // This only works for the public data tree
97
97
  const treeId = MerkleTreeId.PUBLIC_DATA_TREE;
98
98
  const tree = this.treeMap.get(treeId);
@@ -109,15 +109,19 @@ export class AvmEphemeralForest {
109
109
  updatedPreimage.value = newValue;
110
110
  tree.updateLeaf(await this.hashPreimage(updatedPreimage), lowLeafIndex);
111
111
  this.setIndexedUpdates(treeId, lowLeafIndex, updatedPreimage);
112
- this._updateSortedKeys(treeId, [updatedPreimage.slot], [lowLeafIndex]);
112
+ this._updateSortedKeys(treeId, [
113
+ updatedPreimage.slot
114
+ ], [
115
+ lowLeafIndex
116
+ ]);
113
117
  return {
114
118
  element: updatedPreimage,
115
119
  lowWitness: {
116
120
  preimage: preimage,
117
121
  index: lowLeafIndex,
118
- siblingPath: existingPublicDataSiblingPath,
122
+ siblingPath: existingPublicDataSiblingPath
119
123
  },
120
- update: true,
124
+ update: true
121
125
  };
122
126
  }
123
127
  // We are writing to a new slot, so our preimage is a lowNullifier
@@ -129,42 +133,49 @@ export class AvmEphemeralForest {
129
133
  const insertionPath = await this.appendIndexedTree(treeId, lowLeafIndex, updatedLowLeaf, newPublicDataLeaf);
130
134
  // Even though the low leaf key is not updated, we still need to update the sorted keys in case we have
131
135
  // not seen the low leaf before
132
- this._updateSortedKeys(treeId, [newPublicDataLeaf.slot, updatedLowLeaf.slot], [insertionIndex, lowLeafIndex]);
136
+ this._updateSortedKeys(treeId, [
137
+ newPublicDataLeaf.slot,
138
+ updatedLowLeaf.slot
139
+ ], [
140
+ insertionIndex,
141
+ lowLeafIndex
142
+ ]);
133
143
  return {
134
144
  element: newPublicDataLeaf,
135
145
  lowWitness: {
136
146
  preimage,
137
147
  index: lowLeafIndex,
138
- siblingPath,
148
+ siblingPath
139
149
  },
140
150
  update: false,
141
151
  leafIndex: insertionIndex,
142
- insertionPath: insertionPath,
152
+ insertionPath: insertionPath
143
153
  };
144
154
  }
145
155
  _updateSortedKeys(treeId, keys, index) {
146
156
  // This is a reference
147
157
  const existingKeyVector = this.indexedSortedKeys.get(treeId);
148
158
  // Should already be sorted so not need to re-sort if we just update or splice
149
- for (let i = 0; i < keys.length; i++) {
150
- const foundIndex = existingKeyVector.findIndex(x => x[1] === index[i]);
159
+ for(let i = 0; i < keys.length; i++){
160
+ const foundIndex = existingKeyVector.findIndex((x)=>x[1] === index[i]);
151
161
  if (foundIndex === -1) {
152
162
  // New element, we splice it into the correct location
153
- const spliceIndex = indexOrNextLowestInArray(keys[i], existingKeyVector.map(x => x[0])) + 1;
154
- existingKeyVector.splice(spliceIndex, 0, [keys[i], index[i]]);
155
- }
156
- else {
163
+ const spliceIndex = indexOrNextLowestInArray(keys[i], existingKeyVector.map((x)=>x[0])) + 1;
164
+ existingKeyVector.splice(spliceIndex, 0, [
165
+ keys[i],
166
+ index[i]
167
+ ]);
168
+ } else {
157
169
  // Update the existing element
158
170
  existingKeyVector[foundIndex][0] = keys[i];
159
171
  }
160
172
  }
161
173
  }
162
174
  /**
163
- * This appends a nullifier to the nullifier tree, and throws if the nullifier already exists
164
- * @param value - The nullifier to be appended
165
- * @returns The insertion result which contains the insertion path, low leaf and the new leaf index
166
- */
167
- async appendNullifier(nullifier) {
175
+ * This appends a nullifier to the nullifier tree, and throws if the nullifier already exists
176
+ * @param value - The nullifier to be appended
177
+ * @returns The insertion result which contains the insertion path, low leaf and the new leaf index
178
+ */ async appendNullifier(nullifier) {
168
179
  const treeId = MerkleTreeId.NULLIFIER_TREE;
169
180
  const tree = this.treeMap.get(treeId);
170
181
  const [leafOrLowLeafInfo, pathAbsentInEphemeralTree] = await this._getLeafOrLowLeafInfo(treeId, nullifier);
@@ -184,24 +195,29 @@ export class AvmEphemeralForest {
184
195
  const insertionPath = await this.appendIndexedTree(treeId, index, updatedLowNullifier, newNullifierLeaf);
185
196
  // Even though the low nullifier key is not updated, we still need to update the sorted keys in case we have
186
197
  // not seen the low nullifier before
187
- this._updateSortedKeys(treeId, [newNullifierLeaf.nullifier, updatedLowNullifier.nullifier], [insertionIndex, index]);
198
+ this._updateSortedKeys(treeId, [
199
+ newNullifierLeaf.nullifier,
200
+ updatedLowNullifier.nullifier
201
+ ], [
202
+ insertionIndex,
203
+ index
204
+ ]);
188
205
  return {
189
206
  element: newNullifierLeaf,
190
207
  lowWitness: {
191
208
  preimage,
192
209
  index,
193
- siblingPath,
210
+ siblingPath
194
211
  },
195
212
  leafIndex: insertionIndex,
196
- insertionPath: insertionPath,
213
+ insertionPath: insertionPath
197
214
  };
198
215
  }
199
216
  /**
200
- * This appends a note hash to the note hash tree
201
- * @param value - The note hash to be appended
202
- * @returns The insertion result which contains the insertion path
203
- */
204
- async appendNoteHash(noteHash) {
217
+ * This appends a note hash to the note hash tree
218
+ * @param value - The note hash to be appended
219
+ * @returns The insertion result which contains the insertion path
220
+ */ async appendNoteHash(noteHash) {
205
221
  const tree = this.treeMap.get(MerkleTreeId.NOTE_HASH_TREE);
206
222
  tree.appendLeaf(noteHash);
207
223
  // We use leafCount - 1 here because we would have just appended a leaf
@@ -209,9 +225,8 @@ export class AvmEphemeralForest {
209
225
  return insertionPath;
210
226
  }
211
227
  /**
212
- * This is wrapper around treeId to set values in the indexedUpdates map
213
- */
214
- setIndexedUpdates(treeId, index, preimage) {
228
+ * This is wrapper around treeId to set values in the indexedUpdates map
229
+ */ setIndexedUpdates(treeId, index, preimage) {
215
230
  let updates = this.indexedUpdates.get(treeId);
216
231
  if (updates === undefined) {
217
232
  updates = new Map();
@@ -220,10 +235,9 @@ export class AvmEphemeralForest {
220
235
  updates.set(index, preimage);
221
236
  }
222
237
  /**
223
- * This is wrapper around treeId to get values in the indexedUpdates map.
224
- * Should only be called if we know the value exists.
225
- */
226
- getIndexedUpdate(treeId, index) {
238
+ * This is wrapper around treeId to get values in the indexedUpdates map.
239
+ * Should only be called if we know the value exists.
240
+ */ getIndexedUpdate(treeId, index) {
227
241
  const updates = this.indexedUpdates.get(treeId);
228
242
  assert(updates !== undefined, `No updates exist in the ephemeral ${MerkleTreeId[treeId]} tree.`);
229
243
  const preimage = updates.get(index);
@@ -231,9 +245,8 @@ export class AvmEphemeralForest {
231
245
  return preimage;
232
246
  }
233
247
  /**
234
- * This is wrapper around treeId to check membership (i.e. has()) of index in the indexedUpdates map
235
- */
236
- hasLocalUpdates(treeId, index) {
248
+ * This is wrapper around treeId to check membership (i.e. has()) of index in the indexedUpdates map
249
+ */ hasLocalUpdates(treeId, index) {
237
250
  const updates = this.indexedUpdates.get(treeId);
238
251
  if (updates === undefined) {
239
252
  return false;
@@ -241,30 +254,28 @@ export class AvmEphemeralForest {
241
254
  return updates.has(index);
242
255
  }
243
256
  /**
244
- * Get the leaf or low leaf preimage and its index in the indexed tree given a key (slot or nullifier value).
245
- * If the key is not found in the tree, it does an external lookup to the underlying merkle DB.
246
- * @param treeId - The tree we are looking up in
247
- * @param key - The key for which we are look up the leaf or low leaf for.
248
- * @param T - The type of the preimage (PublicData or Nullifier)
249
- * @returns The leaf or low leaf info (preimage & leaf index).
250
- */
251
- async getLeafOrLowLeafInfo(treeId, key) {
257
+ * Get the leaf or low leaf preimage and its index in the indexed tree given a key (slot or nullifier value).
258
+ * If the key is not found in the tree, it does an external lookup to the underlying merkle DB.
259
+ * @param treeId - The tree we are looking up in
260
+ * @param key - The key for which we are look up the leaf or low leaf for.
261
+ * @param T - The type of the preimage (PublicData or Nullifier)
262
+ * @returns The leaf or low leaf info (preimage & leaf index).
263
+ */ async getLeafOrLowLeafInfo(treeId, key) {
252
264
  const [leafOrLowLeafInfo, _] = await this._getLeafOrLowLeafInfo(treeId, key);
253
265
  return leafOrLowLeafInfo;
254
266
  }
255
267
  /**
256
- * Internal helper to get the leaf or low leaf preimage and its index in the indexed tree given a key (slot or nullifier value).
257
- * If the key is not found in the tree, it does an external lookup to the underlying merkle DB.
258
- * Indicates whethe the sibling path is absent in the ephemeral tree.
259
- * @param treeId - The tree we are looking up in
260
- * @param key - The key for which we are look up the leaf or low leaf for.
261
- * @param T - The type of the preimage (PublicData or Nullifier)
262
- * @returns [
263
- * getLeafResult - The leaf or low leaf info (preimage & leaf index),
264
- * pathAbsentInEphemeralTree - whether its sibling path is absent in the ephemeral tree (useful during insertions)
265
- * ]
266
- */
267
- async _getLeafOrLowLeafInfo(treeId, key) {
268
+ * Internal helper to get the leaf or low leaf preimage and its index in the indexed tree given a key (slot or nullifier value).
269
+ * If the key is not found in the tree, it does an external lookup to the underlying merkle DB.
270
+ * Indicates whethe the sibling path is absent in the ephemeral tree.
271
+ * @param treeId - The tree we are looking up in
272
+ * @param key - The key for which we are look up the leaf or low leaf for.
273
+ * @param T - The type of the preimage (PublicData or Nullifier)
274
+ * @returns [
275
+ * getLeafResult - The leaf or low leaf info (preimage & leaf index),
276
+ * pathAbsentInEphemeralTree - whether its sibling path is absent in the ephemeral tree (useful during insertions)
277
+ * ]
278
+ */ async _getLeafOrLowLeafInfo(treeId, key) {
268
279
  const bigIntKey = key.toBigInt();
269
280
  // In this function, "min" refers to the leaf with the
270
281
  // largest key <= the specified key in the indexedUpdates.
@@ -276,7 +287,10 @@ export class AvmEphemeralForest {
276
287
  const leafOrLowLeafWitnessFromExternalDb = await this._getLeafOrLowLeafWitnessInExternalDb(treeId, bigIntKey);
277
288
  // If the indexed updates are empty, we can return the leaf from the DB
278
289
  if (minIndexedLeafIndex === -1n) {
279
- return [leafOrLowLeafWitnessFromExternalDb, /*pathAbsentInEphemeralTree=*/ true];
290
+ return [
291
+ leafOrLowLeafWitnessFromExternalDb,
292
+ /*pathAbsentInEphemeralTree=*/ true
293
+ ];
280
294
  }
281
295
  // Otherwise, we return the closest one. First fetch the leaf from the indexed updates.
282
296
  const minIndexedUpdate = this.getIndexedUpdate(treeId, minIndexedLeafIndex);
@@ -285,56 +299,61 @@ export class AvmEphemeralForest {
285
299
  const keyFromExternal = leafOrLowLeafWitnessFromExternalDb.preimage.getKey();
286
300
  if (keyFromExternal > keyFromIndexed) {
287
301
  // this.log.debug(`Using leaf from external DB for ${MerkleTreeId[treeId]}`);
288
- return [leafOrLowLeafWitnessFromExternalDb, /*pathAbsentInEphemeralTree=*/ true];
289
- }
290
- else {
302
+ return [
303
+ leafOrLowLeafWitnessFromExternalDb,
304
+ /*pathAbsentInEphemeralTree=*/ true
305
+ ];
306
+ } else {
291
307
  // this.log.debug(`Using leaf from indexed DB for ${MerkleTreeId[treeId]}`);
292
308
  const leafInfo = {
293
309
  preimage: minIndexedUpdate,
294
310
  index: minIndexedLeafIndex,
295
- alreadyPresent: keyFromIndexed === bigIntKey,
311
+ alreadyPresent: keyFromIndexed === bigIntKey
296
312
  };
297
- return [leafInfo, /*pathAbsentInEphemeralTree=*/ false];
313
+ return [
314
+ leafInfo,
315
+ /*pathAbsentInEphemeralTree=*/ false
316
+ ];
298
317
  }
299
318
  }
300
319
  /**
301
- * Helper to search for the leaf with the specified key in the indexedUpdates
302
- * and return its leafIndex.
303
- * If not present, return the leafIndex of the largest leaf <= the specified key
304
- * (the leafIndex of the next lowest key).
305
- *
306
- * If no entry exists in indexedUpdates <= the specified key, return -1.
307
- * @returns - The leafIndex of the leaf with the largest key <= the specified key.
308
- */
309
- _getLeafIndexOrNextLowestInIndexedUpdates(treeId, key) {
320
+ * Helper to search for the leaf with the specified key in the indexedUpdates
321
+ * and return its leafIndex.
322
+ * If not present, return the leafIndex of the largest leaf <= the specified key
323
+ * (the leafIndex of the next lowest key).
324
+ *
325
+ * If no entry exists in indexedUpdates <= the specified key, return -1.
326
+ * @returns - The leafIndex of the leaf with the largest key <= the specified key.
327
+ */ _getLeafIndexOrNextLowestInIndexedUpdates(treeId, key) {
310
328
  const keyOrderedVector = this.indexedSortedKeys.get(treeId);
311
- const indexInVector = indexOrNextLowestInArray(key, keyOrderedVector.map(x => x[0]));
329
+ const indexInVector = indexOrNextLowestInArray(key, keyOrderedVector.map((x)=>x[0]));
312
330
  if (indexInVector !== -1) {
313
331
  const [_, leafIndex] = keyOrderedVector[indexInVector];
314
332
  return leafIndex;
315
- }
316
- else {
333
+ } else {
317
334
  // no leaf <= the specified key was found
318
335
  return -1n;
319
336
  }
320
337
  }
321
338
  /**
322
- * Query the external DB to get leaf if present, low leaf if absent
323
- */
324
- async _getLeafOrLowLeafWitnessInExternalDb(treeId, key) {
339
+ * Query the external DB to get leaf if present, low leaf if absent
340
+ */ async _getLeafOrLowLeafWitnessInExternalDb(treeId, key) {
325
341
  // "key" is siloed slot (leafSlot) or siloed nullifier
326
342
  const previousValueIndex = await this.treeDb.getPreviousValueIndex(treeId, key);
327
343
  assert(previousValueIndex !== undefined, `${MerkleTreeId[treeId]} low leaf index should always be found (even if target leaf does not exist)`);
328
344
  const { index: leafIndex, alreadyPresent } = previousValueIndex;
329
345
  const leafPreimage = await this.treeDb.getLeafPreimage(treeId, leafIndex);
330
346
  assert(leafPreimage !== undefined, `${MerkleTreeId[treeId]} low leaf preimage should never be undefined (even if target leaf does not exist)`);
331
- return { preimage: leafPreimage, index: leafIndex, alreadyPresent };
347
+ return {
348
+ preimage: leafPreimage,
349
+ index: leafIndex,
350
+ alreadyPresent
351
+ };
332
352
  }
333
353
  /**
334
- * This hashes the preimage to a field element
335
- */
336
- hashPreimage(preimage) {
337
- const input = preimage.toHashInputs().map(x => Fr.fromBuffer(x));
354
+ * This hashes the preimage to a field element
355
+ */ hashPreimage(preimage) {
356
+ const input = preimage.toHashInputs().map((x)=>Fr.fromBuffer(x));
338
357
  return poseidon2Hash(input);
339
358
  }
340
359
  async getTreeSnapshot(id) {
@@ -343,42 +362,38 @@ export class AvmEphemeralForest {
343
362
  return new AppendOnlyTreeSnapshot(root, Number(tree.leafCount));
344
363
  }
345
364
  }
346
- /****************************************************/
347
- /****** Some useful Structs and Enums **************/
348
- /****************************************************/
349
- var TreeType;
350
- (function (TreeType) {
365
+ /****************************************************/ /****** Some useful Structs and Enums **************/ /****************************************************/ var TreeType = /*#__PURE__*/ function(TreeType) {
351
366
  TreeType[TreeType["LEAF"] = 0] = "LEAF";
352
367
  TreeType[TreeType["NODE"] = 1] = "NODE";
353
- })(TreeType || (TreeType = {}));
354
- var SiblingStatus;
355
- (function (SiblingStatus) {
368
+ return TreeType;
369
+ }(TreeType || {});
370
+ var SiblingStatus = /*#__PURE__*/ function(SiblingStatus) {
356
371
  SiblingStatus[SiblingStatus["MEMBER"] = 0] = "MEMBER";
357
372
  SiblingStatus[SiblingStatus["NONMEMBER"] = 1] = "NONMEMBER";
358
373
  SiblingStatus[SiblingStatus["ERROR"] = 2] = "ERROR";
359
- })(SiblingStatus || (SiblingStatus = {}));
360
- /****************************************************/
361
- /****** Some Helpful Constructors for Trees ********/
362
- /****************************************************/
363
- const Node = (left, right) => ({
364
- tag: TreeType.NODE,
365
- leftTree: left,
366
- rightTree: right,
367
- });
368
- const Leaf = (value) => ({
369
- tag: TreeType.LEAF,
370
- value,
371
- });
372
- /****************************************************/
373
- /****** The EphemeralAvmTree Class *****************/
374
- /****************************************************/
375
- /**
374
+ return SiblingStatus;
375
+ }(SiblingStatus || {});
376
+ /****************************************************/ /****** Some Helpful Constructors for Trees ********/ /****************************************************/ const Node = (left, right)=>({
377
+ tag: 1,
378
+ leftTree: left,
379
+ rightTree: right
380
+ });
381
+ const Leaf = (value)=>({
382
+ tag: 0,
383
+ value
384
+ });
385
+ /****************************************************/ /****** The EphemeralAvmTree Class *****************/ /****************************************************/ /**
376
386
  * This class contains a recursively defined tree that has leaves at different heights
377
387
  * It is seeded by an existing merkle treeDb for which it derives a frontier
378
388
  * It is intended to be a lightweight tree that contains only the necessary information to suppport appends or updates
379
- */
380
- export class EphemeralAvmTree {
381
- constructor(root, leafCount, depth, zeroHashes) {
389
+ */ export class EphemeralAvmTree {
390
+ root;
391
+ leafCount;
392
+ depth;
393
+ zeroHashes;
394
+ tree;
395
+ frontier;
396
+ constructor(root, leafCount, depth, zeroHashes){
382
397
  this.root = root;
383
398
  this.leafCount = leafCount;
384
399
  this.depth = depth;
@@ -390,82 +405,78 @@ export class EphemeralAvmTree {
390
405
  let zeroHash = Fr.zero();
391
406
  // Can probably cache this elsewhere
392
407
  const zeroHashes = [];
393
- for (let i = 0; i < depth; i++) {
408
+ for(let i = 0; i < depth; i++){
394
409
  zeroHashes.push(zeroHash);
395
- zeroHash = await poseidon2Hash([zeroHash, zeroHash]);
410
+ zeroHash = await poseidon2Hash([
411
+ zeroHash,
412
+ zeroHash
413
+ ]);
396
414
  }
397
415
  const tree = new EphemeralAvmTree(Leaf(zeroHash), forkedLeafCount, depth, zeroHashes);
398
416
  await tree.initializeFrontier(treeDb, merkleId);
399
417
  return tree;
400
418
  }
401
419
  /**
402
- * This is a recursive function that inserts a leaf into the tree
403
- * @param value - The value of the leaf to be inserted
404
- */
405
- appendLeaf(value) {
420
+ * This is a recursive function that inserts a leaf into the tree
421
+ * @param value - The value of the leaf to be inserted
422
+ */ appendLeaf(value) {
406
423
  const insertPath = this._derivePathLE(this.leafCount);
407
424
  this.tree = this._insertLeaf(value, insertPath, this.depth, this.tree);
408
425
  this.leafCount++;
409
426
  }
410
427
  /**
411
- * This is a recursive function that upserts a leaf into the tree at a index and depth
412
- * @param value - The value of the leaf to be inserted
413
- * @param index - The index of the leaf to be inserted
414
- * @param depth - The depth of the leaf to be inserted (defaults to the bottom of the tree)
415
- */
416
- updateLeaf(value, index, depth = this.depth) {
428
+ * This is a recursive function that upserts a leaf into the tree at a index and depth
429
+ * @param value - The value of the leaf to be inserted
430
+ * @param index - The index of the leaf to be inserted
431
+ * @param depth - The depth of the leaf to be inserted (defaults to the bottom of the tree)
432
+ */ updateLeaf(value, index, depth = this.depth) {
417
433
  const insertPath = this._derivePathLE(index, depth);
418
434
  this.tree = this._insertLeaf(value, insertPath, depth, this.tree);
419
435
  }
420
436
  /**
421
- * Get the sibling path of a leaf in the tree
422
- * @param index - The index of the leaf for which a sibling path should be returned.
423
- * @returns The sibling path of the leaf, can fail if the path is not found
424
- */
425
- async getSiblingPath(index) {
437
+ * Get the sibling path of a leaf in the tree
438
+ * @param index - The index of the leaf for which a sibling path should be returned.
439
+ * @returns The sibling path of the leaf, can fail if the path is not found
440
+ */ async getSiblingPath(index) {
426
441
  const searchPath = this._derivePathLE(index);
427
442
  // Handle cases where we error out
428
443
  const { path, status } = await this._getSiblingPath(searchPath, this.tree, []);
429
- if (status === SiblingStatus.ERROR) {
444
+ if (status === 2) {
430
445
  return undefined;
431
446
  }
432
447
  return path;
433
448
  }
434
449
  /**
435
- * This upserts the nodes of the sibling path into the tree
436
- * @param index - The index of the leaf that the sibling path is derived from
437
- * @param siblingPath - The sibling path of the index
438
- */
439
- insertSiblingPath(index, siblingPath) {
440
- for (let i = 0; i < siblingPath.length; i++) {
450
+ * This upserts the nodes of the sibling path into the tree
451
+ * @param index - The index of the leaf that the sibling path is derived from
452
+ * @param siblingPath - The sibling path of the index
453
+ */ insertSiblingPath(index, siblingPath) {
454
+ for(let i = 0; i < siblingPath.length; i++){
441
455
  // Flip(XOR) the last bit because we are inserting siblings of the leaf
442
456
  const sibIndex = index ^ 1n;
443
457
  const node = this.getNode(sibIndex, this.depth - i);
444
458
  // If we are inserting a sibling path and we already have a branch at that index in our
445
459
  // ephemeral tree, we should not overwrite it
446
- if (node === undefined || node.tag === TreeType.LEAF) {
460
+ if (node === undefined || node.tag === 0) {
447
461
  this.updateLeaf(siblingPath[i], sibIndex, this.depth - i);
448
462
  }
449
463
  index >>= 1n;
450
464
  }
451
465
  }
452
466
  /**
453
- * This is a helper function that computes the index of the frontier nodes at each depth
454
- * @param leafCount - The number of leaves in the tree
455
- * @returns An array of frontier indices at each depth, sorted from leaf to root
456
- */
457
- // Do we really need LeafCount to be a bigint - log2 is on numbers only
467
+ * This is a helper function that computes the index of the frontier nodes at each depth
468
+ * @param leafCount - The number of leaves in the tree
469
+ * @returns An array of frontier indices at each depth, sorted from leaf to root
470
+ */ // Do we really need LeafCount to be a bigint - log2 is on numbers only
458
471
  static computeFrontierLeafIndices(leafCount) {
459
472
  const numFrontierEntries = Math.floor(Math.log2(leafCount)) + 1;
460
473
  const frontierIndices = [];
461
- for (let i = 0; i < numFrontierEntries; i++) {
474
+ for(let i = 0; i < numFrontierEntries; i++){
462
475
  if (leafCount === 0) {
463
476
  frontierIndices.push(0);
464
- }
465
- else if (leafCount % 2 === 0) {
477
+ } else if (leafCount % 2 === 0) {
466
478
  frontierIndices.push(leafCount - 2);
467
- }
468
- else {
479
+ } else {
469
480
  frontierIndices.push(leafCount - 1);
470
481
  }
471
482
  leafCount >>= 1;
@@ -473,11 +484,10 @@ export class EphemeralAvmTree {
473
484
  return frontierIndices;
474
485
  }
475
486
  /**
476
- * This derives the frontier and inserts them into the tree
477
- * @param treeDb - The treeDb to be queried for sibling paths
478
- * @param merkleId - The treeId of the tree to be queried for sibling paths
479
- */
480
- async initializeFrontier(treeDb, merkleId) {
487
+ * This derives the frontier and inserts them into the tree
488
+ * @param treeDb - The treeDb to be queried for sibling paths
489
+ * @param merkleId - The treeId of the tree to be queried for sibling paths
490
+ */ async initializeFrontier(treeDb, merkleId) {
481
491
  // The frontier indices are sorted from the leaf to root
482
492
  const frontierIndices = EphemeralAvmTree.computeFrontierLeafIndices(Number(this.leafCount));
483
493
  // The frontier indices are level-based - i.e. index N at level L.
@@ -488,7 +498,7 @@ export class EphemeralAvmTree {
488
498
  // NOTE: This is terribly inefficient and we should probably change the DB API to allow for getting paths to a node
489
499
  const frontierValues = [];
490
500
  // These are leaf indexes that pass through the frontier nodes
491
- for (let i = 0; i < frontierIndices.length; i++) {
501
+ for(let i = 0; i < frontierIndices.length; i++){
492
502
  // Given the index to a frontier, we first xor it so we can get its sibling index at depth L
493
503
  // We then extend the path to that sibling index by shifting left the requisite number of times (for simplicity we just go left down the tree - it doesnt matter)
494
504
  // This provides us the leaf index such that if we ask for this leafIndex's sibling path, it will pass through the frontier node
@@ -507,159 +517,156 @@ export class EphemeralAvmTree {
507
517
  this.frontier = frontierValues;
508
518
  }
509
519
  /**
510
- * Computes the root of the tree
511
- */
512
- getRoot() {
520
+ * Computes the root of the tree
521
+ */ getRoot() {
513
522
  return this.hashTree(this.tree, this.depth);
514
523
  }
515
524
  /**
516
- * Recursively hashes the subtree
517
- * @param tree - The tree to be hashed
518
- * @param depth - The depth of the tree
519
- */
520
- async hashTree(tree, depth) {
521
- switch (tree.tag) {
522
- case TreeType.NODE: {
523
- return poseidon2Hash([
524
- await this.hashTree(tree.leftTree, depth - 1),
525
- await this.hashTree(tree.rightTree, depth - 1),
526
- ]);
527
- }
528
- case TreeType.LEAF: {
529
- return tree.value;
530
- }
525
+ * Recursively hashes the subtree
526
+ * @param tree - The tree to be hashed
527
+ * @param depth - The depth of the tree
528
+ */ async hashTree(tree, depth) {
529
+ switch(tree.tag){
530
+ case 1:
531
+ {
532
+ return poseidon2Hash([
533
+ await this.hashTree(tree.leftTree, depth - 1),
534
+ await this.hashTree(tree.rightTree, depth - 1)
535
+ ]);
536
+ }
537
+ case 0:
538
+ {
539
+ return tree.value;
540
+ }
531
541
  }
532
542
  }
533
543
  /**
534
- * Extracts the subtree from a given index and depth
535
- * @param index - The index of the node to be extracted
536
- * @param depth - The depth of the node to be extracted
537
- * @returns The subtree rooted at the index and depth
538
- */
539
- getNode(index, depth) {
544
+ * Extracts the subtree from a given index and depth
545
+ * @param index - The index of the node to be extracted
546
+ * @param depth - The depth of the node to be extracted
547
+ * @returns The subtree rooted at the index and depth
548
+ */ getNode(index, depth) {
540
549
  const path = this._derivePathBE(index, depth);
541
550
  const truncatedPath = path.slice(0, depth);
542
551
  truncatedPath.reverse();
543
552
  try {
544
553
  return this._getNode(truncatedPath, this.tree);
545
- }
546
- catch (e) {
554
+ } catch (e) {
547
555
  return undefined;
548
556
  }
549
557
  }
550
558
  /**
551
- * This is the recursive helper for getNode
552
- */
553
- _getNode(nodePath, tree) {
559
+ * This is the recursive helper for getNode
560
+ */ _getNode(nodePath, tree) {
554
561
  if (nodePath.length === 0) {
555
562
  return tree;
556
563
  }
557
- switch (tree.tag) {
558
- case TreeType.NODE:
564
+ switch(tree.tag){
565
+ case 1:
559
566
  return nodePath.pop() === 0 ? this._getNode(nodePath, tree.leftTree) : this._getNode(nodePath, tree.rightTree);
560
- case TreeType.LEAF:
567
+ case 0:
561
568
  throw new Error('Node not found');
562
569
  }
563
570
  }
564
571
  /** Our tree traversal uses an array of 1s and 0s to represent the path to a leaf and expects them to be in LE order
565
- * This helps with deriving it given an index and (optionally a depth)
566
- * @param index - The index to derive a path to within the tree, does not have to terminate at a leaf
567
- * @param depth - The depth to traverse, if not provided it will traverse to the bottom of the tree
568
- * @returns The path to the leaf in LE order
569
- */
570
- _derivePathLE(index, depth = this.depth) {
572
+ * This helps with deriving it given an index and (optionally a depth)
573
+ * @param index - The index to derive a path to within the tree, does not have to terminate at a leaf
574
+ * @param depth - The depth to traverse, if not provided it will traverse to the bottom of the tree
575
+ * @returns The path to the leaf in LE order
576
+ */ _derivePathLE(index, depth = this.depth) {
571
577
  return this._derivePathBE(index, depth).reverse();
572
578
  }
573
579
  /** Sometimes we want it in BE order, to make truncating easier
574
- * @param index - The index to derive a path to within the tree, does not have to terminate at a leaf
575
- * @param depth - The depth to traverse, if not provided it will traverse to the bottom of the tree
576
- * @returns The path to the leaf in LE order
577
- */
578
- _derivePathBE(index, depth = this.depth) {
579
- return index
580
- .toString(2)
581
- .padStart(depth, '0')
582
- .split('')
583
- .map(x => parseInt(x));
580
+ * @param index - The index to derive a path to within the tree, does not have to terminate at a leaf
581
+ * @param depth - The depth to traverse, if not provided it will traverse to the bottom of the tree
582
+ * @returns The path to the leaf in LE order
583
+ */ _derivePathBE(index, depth = this.depth) {
584
+ return index.toString(2).padStart(depth, '0').split('').map((x)=>parseInt(x));
584
585
  }
585
586
  /**
586
- * This is a recursive function that upserts a leaf into the tree given a path
587
- * @param value - The value of the leaf to be upserted
588
- * @param insertPath - The path to the leaf, this should be ordered from leaf to root (i.e. LE encoded)
589
- * @param depth - The depth of the tree
590
- * @param tree - The current tree
591
- * @param appendMode - If true we append the relevant zeroHashes to the tree as we traverse
592
- */
593
- _insertLeaf(value, insertPath, depth, tree) {
587
+ * This is a recursive function that upserts a leaf into the tree given a path
588
+ * @param value - The value of the leaf to be upserted
589
+ * @param insertPath - The path to the leaf, this should be ordered from leaf to root (i.e. LE encoded)
590
+ * @param depth - The depth of the tree
591
+ * @param tree - The current tree
592
+ * @param appendMode - If true we append the relevant zeroHashes to the tree as we traverse
593
+ */ _insertLeaf(value, insertPath, depth, tree) {
594
594
  if (insertPath.length > this.depth || depth > this.depth) {
595
595
  throw new Error('PATH EXCEEDS DEPTH');
596
596
  }
597
597
  if (depth === 0 || insertPath.length === 0) {
598
598
  return Leaf(value);
599
599
  }
600
- switch (tree.tag) {
601
- case TreeType.NODE: {
602
- return insertPath.pop() === 0
603
- ? Node(this._insertLeaf(value, insertPath, depth - 1, tree.leftTree), tree.rightTree)
604
- : Node(tree.leftTree, this._insertLeaf(value, insertPath, depth - 1, tree.rightTree));
605
- }
606
- case TreeType.LEAF: {
607
- const zeroLeaf = Leaf(this.zeroHashes[depth - 1]);
608
- return insertPath.pop() === 0
609
- ? Node(this._insertLeaf(value, insertPath, depth - 1, zeroLeaf), zeroLeaf)
610
- : Node(zeroLeaf, this._insertLeaf(value, insertPath, depth - 1, zeroLeaf));
611
- }
600
+ switch(tree.tag){
601
+ case 1:
602
+ {
603
+ return insertPath.pop() === 0 ? Node(this._insertLeaf(value, insertPath, depth - 1, tree.leftTree), tree.rightTree) : Node(tree.leftTree, this._insertLeaf(value, insertPath, depth - 1, tree.rightTree));
604
+ }
605
+ case 0:
606
+ {
607
+ const zeroLeaf = Leaf(this.zeroHashes[depth - 1]);
608
+ return insertPath.pop() === 0 ? Node(this._insertLeaf(value, insertPath, depth - 1, zeroLeaf), zeroLeaf) : Node(zeroLeaf, this._insertLeaf(value, insertPath, depth - 1, zeroLeaf));
609
+ }
612
610
  }
613
611
  }
614
612
  /* Recursive helper for getSiblingPath, this only looks inside the tree and does not resolve using
615
- * a DB. If a path is not found, it returns an error status that is expected to be handled by the caller
616
- * @param searchPath - The path to the leaf for which we would like the sibling pathin LE order
617
- * @param tree - The current tree
618
- * @param acc - The accumulated sibling path
619
- */
620
- async _getSiblingPath(searchPath, tree, acc) {
613
+ * a DB. If a path is not found, it returns an error status that is expected to be handled by the caller
614
+ * @param searchPath - The path to the leaf for which we would like the sibling pathin LE order
615
+ * @param tree - The current tree
616
+ * @param acc - The accumulated sibling path
617
+ */ async _getSiblingPath(searchPath, tree, acc) {
621
618
  // If we have reached the end of the path, we should be at a leaf or empty node
622
619
  // If it is a leaf, we check if the value is equal to the leaf value
623
620
  // If it is empty we check if the value is equal to zero
624
621
  if (searchPath.length === 0) {
625
- switch (tree.tag) {
626
- case TreeType.LEAF:
627
- return { path: acc, status: SiblingStatus.MEMBER };
628
- case TreeType.NODE:
629
- return { path: [], status: SiblingStatus.ERROR };
622
+ switch(tree.tag){
623
+ case 0:
624
+ return {
625
+ path: acc,
626
+ status: 0
627
+ };
628
+ case 1:
629
+ return {
630
+ path: [],
631
+ status: 2
632
+ };
630
633
  }
631
634
  }
632
635
  // Keep exploring here
633
- switch (tree.tag) {
634
- case TreeType.NODE: {
635
- // Look at the next element of the path to decided if we go left or right, note this mutates!
636
- return searchPath.pop() === 0
637
- ? await this._getSiblingPath(searchPath, tree.leftTree, [await this.hashTree(tree.rightTree, searchPath.length)].concat(acc))
638
- : await this._getSiblingPath(searchPath, tree.rightTree, [await this.hashTree(tree.leftTree, searchPath.length)].concat(acc));
639
- }
636
+ switch(tree.tag){
637
+ case 1:
638
+ {
639
+ // Look at the next element of the path to decided if we go left or right, note this mutates!
640
+ return searchPath.pop() === 0 ? await this._getSiblingPath(searchPath, tree.leftTree, [
641
+ await this.hashTree(tree.rightTree, searchPath.length)
642
+ ].concat(acc)) : await this._getSiblingPath(searchPath, tree.rightTree, [
643
+ await this.hashTree(tree.leftTree, searchPath.length)
644
+ ].concat(acc));
645
+ }
640
646
  // In these two situations we are exploring a subtree we dont have information about
641
647
  // We should return an error and look inside the DB
642
- case TreeType.LEAF:
643
- return { path: [], status: SiblingStatus.ERROR };
648
+ case 0:
649
+ return {
650
+ path: [],
651
+ status: 2
652
+ };
644
653
  }
645
654
  }
646
655
  }
647
656
  /**
648
657
  * Return the index of the key in the array, or index-1 if they key is not found.
649
- */
650
- function indexOrNextLowestInArray(key, arr) {
658
+ */ function indexOrNextLowestInArray(key, arr) {
651
659
  // We are looking for the index of the largest element in the array that is less than the key
652
660
  let start = 0;
653
661
  let end = arr.length;
654
662
  // Note that the easiest way is to increment the search key by 1 and then do a binary search
655
663
  const keyPlus1 = key.add(Fr.ONE);
656
- while (start < end) {
664
+ while(start < end){
657
665
  const mid = Math.floor((start + end) / 2);
658
666
  if (arr[mid].cmp(keyPlus1) < 0) {
659
667
  // The key + 1 is greater than the midpoint, so we can continue searching the top half
660
668
  start = mid + 1;
661
- }
662
- else {
669
+ } else {
663
670
  // The key + 1 is LT or EQ the arr element, so we can continue searching the bottom half
664
671
  end = mid;
665
672
  }
@@ -669,4 +676,3 @@ function indexOrNextLowestInArray(key, arr) {
669
676
  // greater than the key
670
677
  return start - 1;
671
678
  }
672
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXZtX3RyZWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXZtL2F2bV90cmVlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBc0IsWUFBWSxFQUFpQyxNQUFNLHNCQUFzQixDQUFDO0FBQ3ZHLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxxQkFBcUIsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQy9HLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFHOUMsT0FBTyxFQUFFLE1BQU0sSUFBSSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDMUMsT0FBTyxTQUFTLE1BQU0sa0JBQWtCLENBQUM7QUF1RHpDLHNEQUFzRDtBQUN0RCxzREFBc0Q7QUFDdEQsc0RBQXNEO0FBRXREOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBQzdCLFlBQ1MsTUFBZ0MsRUFDaEMsT0FBNEM7SUFDbkQsa0hBQWtIO0lBQ2xILCtGQUErRjtJQUN4RixjQUF3RSxFQUN4RSxpQkFBcUQ7UUFMckQsV0FBTSxHQUFOLE1BQU0sQ0FBMEI7UUFDaEMsWUFBTyxHQUFQLE9BQU8sQ0FBcUM7UUFHNUMsbUJBQWMsR0FBZCxjQUFjLENBQTBEO1FBQ3hFLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBb0M7SUFDM0QsQ0FBQztJQUVKLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQWdDO1FBQ2xELE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFrQyxDQUFDO1FBQzFELEtBQUssTUFBTSxRQUFRLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztZQUNqSCxNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxX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