@aztec/pxe 0.0.1-commit.e6bd8901 → 0.0.1-commit.ec5f612

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 (205) hide show
  1. package/dest/access_scopes.d.ts +9 -0
  2. package/dest/access_scopes.d.ts.map +1 -0
  3. package/dest/access_scopes.js +6 -0
  4. package/dest/block_synchronizer/block_synchronizer.d.ts +5 -3
  5. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  6. package/dest/block_synchronizer/block_synchronizer.js +11 -5
  7. package/dest/config/package_info.js +1 -1
  8. package/dest/contract_function_simulator/contract_function_simulator.d.ts +54 -30
  9. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  10. package/dest/contract_function_simulator/contract_function_simulator.js +174 -70
  11. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts +5 -5
  12. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts.map +1 -1
  13. package/dest/contract_function_simulator/execution_tagging_index_cache.js +3 -3
  14. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +1 -1
  15. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +2 -2
  16. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
  18. package/dest/contract_function_simulator/oracle/interfaces.d.ts +10 -10
  19. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  20. package/dest/contract_function_simulator/oracle/oracle.d.ts +5 -5
  21. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  22. package/dest/contract_function_simulator/oracle/oracle.js +38 -26
  23. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +36 -36
  24. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  25. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +74 -31
  26. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +53 -29
  27. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  28. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +84 -63
  29. package/dest/contract_logging.d.ts +22 -0
  30. package/dest/contract_logging.d.ts.map +1 -0
  31. package/dest/contract_logging.js +23 -0
  32. package/dest/contract_sync/contract_sync_service.d.ts +43 -0
  33. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -0
  34. package/dest/contract_sync/contract_sync_service.js +97 -0
  35. package/dest/contract_sync/helpers.d.ts +29 -0
  36. package/dest/contract_sync/helpers.d.ts.map +1 -0
  37. package/dest/contract_sync/{index.js → helpers.js} +14 -15
  38. package/dest/debug/pxe_debug_utils.d.ts +24 -10
  39. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  40. package/dest/debug/pxe_debug_utils.js +28 -18
  41. package/dest/entrypoints/client/bundle/index.d.ts +4 -1
  42. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  43. package/dest/entrypoints/client/bundle/index.js +3 -0
  44. package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
  45. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  46. package/dest/entrypoints/client/bundle/utils.js +21 -7
  47. package/dest/entrypoints/client/lazy/index.d.ts +4 -1
  48. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  49. package/dest/entrypoints/client/lazy/index.js +3 -0
  50. package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
  51. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  52. package/dest/entrypoints/client/lazy/utils.js +22 -8
  53. package/dest/entrypoints/pxe_creation_options.d.ts +3 -2
  54. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  55. package/dest/entrypoints/server/index.d.ts +4 -2
  56. package/dest/entrypoints/server/index.d.ts.map +1 -1
  57. package/dest/entrypoints/server/index.js +3 -1
  58. package/dest/entrypoints/server/utils.d.ts +1 -1
  59. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  60. package/dest/entrypoints/server/utils.js +28 -9
  61. package/dest/events/event_service.d.ts +4 -5
  62. package/dest/events/event_service.d.ts.map +1 -1
  63. package/dest/events/event_service.js +5 -6
  64. package/dest/job_coordinator/job_coordinator.d.ts +3 -2
  65. package/dest/job_coordinator/job_coordinator.d.ts.map +1 -1
  66. package/dest/job_coordinator/job_coordinator.js +3 -2
  67. package/dest/logs/log_service.d.ts +7 -5
  68. package/dest/logs/log_service.d.ts.map +1 -1
  69. package/dest/logs/log_service.js +19 -30
  70. package/dest/notes/note_service.d.ts +7 -7
  71. package/dest/notes/note_service.d.ts.map +1 -1
  72. package/dest/notes/note_service.js +9 -10
  73. package/dest/notes_filter.d.ts +25 -0
  74. package/dest/notes_filter.d.ts.map +1 -0
  75. package/dest/notes_filter.js +4 -0
  76. package/dest/oracle_version.d.ts +3 -3
  77. package/dest/oracle_version.d.ts.map +1 -1
  78. package/dest/oracle_version.js +2 -2
  79. package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts +4 -0
  80. package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts.map +1 -0
  81. package/dest/private_kernel/hints/{compute_tx_include_by_timestamp.js → compute_tx_expiration_timestamp.js} +12 -12
  82. package/dest/private_kernel/hints/index.d.ts +1 -1
  83. package/dest/private_kernel/hints/index.js +1 -1
  84. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +4 -3
  85. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -1
  86. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.js +129 -68
  87. package/dest/private_kernel/hints/test_utils.d.ts +122 -0
  88. package/dest/private_kernel/hints/test_utils.d.ts.map +1 -0
  89. package/dest/private_kernel/hints/test_utils.js +203 -0
  90. package/dest/private_kernel/private_kernel_execution_prover.d.ts +3 -2
  91. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  92. package/dest/private_kernel/private_kernel_execution_prover.js +21 -13
  93. package/dest/private_kernel/private_kernel_oracle.d.ts +8 -4
  94. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  95. package/dest/private_kernel/private_kernel_oracle.js +7 -3
  96. package/dest/pxe.d.ts +69 -23
  97. package/dest/pxe.d.ts.map +1 -1
  98. package/dest/pxe.js +99 -65
  99. package/dest/storage/address_store/address_store.d.ts +1 -1
  100. package/dest/storage/address_store/address_store.d.ts.map +1 -1
  101. package/dest/storage/address_store/address_store.js +12 -11
  102. package/dest/storage/anchor_block_store/anchor_block_store.d.ts +9 -1
  103. package/dest/storage/anchor_block_store/anchor_block_store.d.ts.map +1 -1
  104. package/dest/storage/anchor_block_store/anchor_block_store.js +8 -1
  105. package/dest/storage/capsule_store/capsule_store.js +6 -8
  106. package/dest/storage/contract_store/contract_store.d.ts +42 -15
  107. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  108. package/dest/storage/contract_store/contract_store.js +157 -72
  109. package/dest/storage/metadata.d.ts +1 -1
  110. package/dest/storage/metadata.js +1 -1
  111. package/dest/storage/note_store/note_store.d.ts +13 -3
  112. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  113. package/dest/storage/note_store/note_store.js +147 -107
  114. package/dest/storage/private_event_store/private_event_store.d.ts +1 -1
  115. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  116. package/dest/storage/private_event_store/private_event_store.js +84 -61
  117. package/dest/storage/private_event_store/stored_private_event.d.ts +4 -4
  118. package/dest/storage/private_event_store/stored_private_event.d.ts.map +1 -1
  119. package/dest/storage/private_event_store/stored_private_event.js +2 -2
  120. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +6 -6
  121. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  122. package/dest/storage/tagging_store/recipient_tagging_store.js +31 -19
  123. package/dest/storage/tagging_store/sender_address_book_store.d.ts +1 -1
  124. package/dest/storage/tagging_store/sender_address_book_store.d.ts.map +1 -1
  125. package/dest/storage/tagging_store/sender_address_book_store.js +20 -14
  126. package/dest/storage/tagging_store/sender_tagging_store.d.ts +5 -5
  127. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  128. package/dest/storage/tagging_store/sender_tagging_store.js +184 -114
  129. package/dest/tagging/get_all_logs_by_tags.d.ts +4 -4
  130. package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -1
  131. package/dest/tagging/get_all_logs_by_tags.js +17 -3
  132. package/dest/tagging/index.d.ts +2 -2
  133. package/dest/tagging/index.d.ts.map +1 -1
  134. package/dest/tagging/index.js +1 -1
  135. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +5 -6
  136. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  137. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +7 -7
  138. package/dest/tagging/recipient_sync/utils/find_highest_indexes.js +2 -2
  139. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +7 -8
  140. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +1 -1
  141. package/dest/tagging/recipient_sync/utils/load_logs_for_range.js +12 -11
  142. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +5 -9
  143. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
  144. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +3 -6
  145. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +5 -8
  146. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  147. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +14 -15
  148. package/package.json +25 -16
  149. package/src/access_scopes.ts +9 -0
  150. package/src/block_synchronizer/block_synchronizer.ts +23 -19
  151. package/src/config/package_info.ts +1 -1
  152. package/src/contract_function_simulator/contract_function_simulator.ts +323 -128
  153. package/src/contract_function_simulator/execution_tagging_index_cache.ts +5 -5
  154. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -1
  155. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -1
  156. package/src/contract_function_simulator/oracle/interfaces.ts +12 -12
  157. package/src/contract_function_simulator/oracle/oracle.ts +41 -24
  158. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +101 -113
  159. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +139 -70
  160. package/src/contract_logging.ts +39 -0
  161. package/src/contract_sync/contract_sync_service.ts +152 -0
  162. package/src/contract_sync/{index.ts → helpers.ts} +22 -24
  163. package/src/debug/pxe_debug_utils.ts +63 -19
  164. package/src/entrypoints/client/bundle/index.ts +3 -0
  165. package/src/entrypoints/client/bundle/utils.ts +16 -15
  166. package/src/entrypoints/client/lazy/index.ts +3 -0
  167. package/src/entrypoints/client/lazy/utils.ts +17 -15
  168. package/src/entrypoints/pxe_creation_options.ts +2 -1
  169. package/src/entrypoints/server/index.ts +3 -1
  170. package/src/entrypoints/server/utils.ts +22 -26
  171. package/src/events/event_service.ts +4 -6
  172. package/src/job_coordinator/job_coordinator.ts +4 -3
  173. package/src/logs/log_service.ts +31 -39
  174. package/src/notes/note_service.ts +9 -11
  175. package/src/notes_filter.ts +26 -0
  176. package/src/oracle_version.ts +2 -2
  177. package/src/private_kernel/hints/{compute_tx_include_by_timestamp.ts → compute_tx_expiration_timestamp.ts} +13 -13
  178. package/src/private_kernel/hints/index.ts +1 -1
  179. package/src/private_kernel/hints/private_kernel_reset_private_inputs_builder.ts +164 -117
  180. package/src/private_kernel/hints/test_utils.ts +325 -0
  181. package/src/private_kernel/private_kernel_execution_prover.ts +25 -15
  182. package/src/private_kernel/private_kernel_oracle.ts +9 -9
  183. package/src/pxe.ts +192 -117
  184. package/src/storage/address_store/address_store.ts +15 -15
  185. package/src/storage/anchor_block_store/anchor_block_store.ts +8 -0
  186. package/src/storage/capsule_store/capsule_store.ts +8 -8
  187. package/src/storage/contract_store/contract_store.ts +186 -76
  188. package/src/storage/metadata.ts +1 -1
  189. package/src/storage/note_store/note_store.ts +169 -132
  190. package/src/storage/private_event_store/private_event_store.ts +102 -81
  191. package/src/storage/private_event_store/stored_private_event.ts +3 -3
  192. package/src/storage/tagging_store/recipient_tagging_store.ts +38 -24
  193. package/src/storage/tagging_store/sender_address_book_store.ts +20 -14
  194. package/src/storage/tagging_store/sender_tagging_store.ts +214 -130
  195. package/src/tagging/get_all_logs_by_tags.ts +31 -7
  196. package/src/tagging/index.ts +1 -1
  197. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +9 -12
  198. package/src/tagging/recipient_sync/utils/find_highest_indexes.ts +2 -2
  199. package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +12 -17
  200. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +6 -11
  201. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +14 -23
  202. package/dest/contract_sync/index.d.ts +0 -23
  203. package/dest/contract_sync/index.d.ts.map +0 -1
  204. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts +0 -4
  205. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts.map +0 -1
@@ -0,0 +1,26 @@
1
+ import type { Fr } from '@aztec/foundation/curves/bn254';
2
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+ import type { NoteStatus } from '@aztec/stdlib/note';
4
+
5
+ import type { AccessScopes } from './access_scopes.js';
6
+
7
+ /**
8
+ * A filter used to fetch notes.
9
+ * @remarks This filter is applied as an intersection of all its params.
10
+ */
11
+ export type NotesFilter = {
12
+ /**
13
+ * The contract address the note belongs to.
14
+ * @remarks Providing a contract address is required as we need that information to trigger private state sync.
15
+ */
16
+ contractAddress: AztecAddress;
17
+ /** The owner of the note. */
18
+ owner?: AztecAddress;
19
+ /** The specific storage location of the note on the contract. */
20
+ storageSlot?: Fr;
21
+ /** The status of the note. Defaults to 'ACTIVE'. */
22
+ status?: NoteStatus;
23
+ /** The siloed nullifier for the note. */
24
+ siloedNullifier?: Fr;
25
+ scopes: AccessScopes;
26
+ };
@@ -4,9 +4,9 @@
4
4
  ///
5
5
  /// @dev Whenever a contract function or Noir test is run, the `utilityAssertCompatibleOracleVersion` oracle is called
6
6
  /// and if the oracle version is incompatible an error is thrown.
7
- export const ORACLE_VERSION = 9;
7
+ export const ORACLE_VERSION = 12;
8
8
 
9
9
  /// This hash is computed as by hashing the Oracle interface and it is used to detect when the Oracle interface changes,
10
10
  /// which in turn implies that you need to update the ORACLE_VERSION constant in this file and in
11
11
  /// `noir-projects/aztec-nr/aztec/src/oracle/version.nr`.
12
- export const ORACLE_INTERFACE_HASH = '9866cc52510acaef75a3d47a0ed501fd9ff92b9d53b2c8a88c8a3ffd04ced81f';
12
+ export const ORACLE_INTERFACE_HASH = '666a8a7fc697f72b29dbf0ae7464db269cf5afa019acac8861f814543147dbb4';
@@ -1,4 +1,4 @@
1
- import { MAX_INCLUDE_BY_TIMESTAMP_DURATION } from '@aztec/constants';
1
+ import { MAX_TX_LIFETIME } from '@aztec/constants';
2
2
  import type { PrivateKernelCircuitPublicInputs } from '@aztec/stdlib/kernel';
3
3
  import type { UInt64 } from '@aztec/stdlib/types';
4
4
 
@@ -8,12 +8,12 @@ const ROUNDED_DURATIONS = [
8
8
  1, // 1 second
9
9
  ];
10
10
 
11
- function roundTimestamp(blockTimestamp: bigint, includeByTimestamp: bigint): UInt64 {
11
+ function roundTimestamp(blockTimestamp: bigint, expirationTimestamp: bigint): UInt64 {
12
12
  return ROUNDED_DURATIONS.reduce((timestamp, duration) => {
13
13
  if (timestamp <= blockTimestamp) {
14
14
  // The timestamp must be greater than the block timestamp.
15
15
  // If it is too small, round it down again using a smaller duration.
16
- const totalDuration = includeByTimestamp - blockTimestamp;
16
+ const totalDuration = expirationTimestamp - blockTimestamp;
17
17
  const roundedDuration = totalDuration - (totalDuration % BigInt(duration));
18
18
  return blockTimestamp + roundedDuration;
19
19
  }
@@ -21,36 +21,36 @@ function roundTimestamp(blockTimestamp: bigint, includeByTimestamp: bigint): UIn
21
21
  }, 0n);
22
22
  }
23
23
 
24
- export function computeTxIncludeByTimestamp(
24
+ export function computeTxExpirationTimestamp(
25
25
  previousKernel: PrivateKernelCircuitPublicInputs,
26
- maxDuration = MAX_INCLUDE_BY_TIMESTAMP_DURATION,
26
+ txLifetime = MAX_TX_LIFETIME,
27
27
  ): UInt64 {
28
- if (maxDuration > MAX_INCLUDE_BY_TIMESTAMP_DURATION) {
28
+ if (txLifetime > MAX_TX_LIFETIME) {
29
29
  throw new Error(
30
- `Custom max duration cannot be greater than the max allowed. Max allowed: ${MAX_INCLUDE_BY_TIMESTAMP_DURATION}. Custom value: ${maxDuration}.`,
30
+ `Custom tx lifetime cannot be greater than the max allowed. Max allowed: ${MAX_TX_LIFETIME}. Custom value: ${txLifetime}.`,
31
31
  );
32
32
  }
33
33
 
34
34
  const anchorBlockTimestamp = previousKernel.constants.anchorBlockHeader.globalVariables.timestamp;
35
- const maxTimestamp = anchorBlockTimestamp + BigInt(maxDuration);
36
- const includeByTimestamp = previousKernel.includeByTimestamp;
35
+ const maxTimestamp = anchorBlockTimestamp + BigInt(txLifetime);
36
+ const expirationTimestamp = previousKernel.expirationTimestamp;
37
37
 
38
- // If the includeByTimestamp set during the tx execution is greater than or equal to the max allowed duration,
38
+ // If the expirationTimestamp set during the tx execution is greater than or equal to the max allowed duration,
39
39
  // use the maximum allowed timestamp.
40
40
  // Note: It shouldn't be larger than the max allowed duration, but we check for it anyway.
41
- if (includeByTimestamp >= maxTimestamp) {
41
+ if (expirationTimestamp >= maxTimestamp) {
42
42
  return maxTimestamp;
43
43
  }
44
44
 
45
45
  // Round it down to the nearest hour/min/second to reduce precision and avoid revealing the exact value.
46
46
  // This makes it harder for others to infer what function calls may have been used to produce a specific timestamp.
47
- const roundedTimestamp = roundTimestamp(anchorBlockTimestamp, includeByTimestamp);
47
+ const roundedTimestamp = roundTimestamp(anchorBlockTimestamp, expirationTimestamp);
48
48
 
49
49
  // The tx can't be published if the timestamp is the same or less than the anchor block's timestamp.
50
50
  // Future blocks will have a greater timestamp, so the tx would never be included.
51
51
  if (roundedTimestamp <= anchorBlockTimestamp) {
52
52
  throw new Error(
53
- `Include-by timestamp must be greater than the anchor block timestamp. Anchor block timestamp: ${anchorBlockTimestamp}. Include-by timestamp: ${includeByTimestamp}.`,
53
+ `Include-by timestamp must be greater than the anchor block timestamp. Anchor block timestamp: ${anchorBlockTimestamp}. Include-by timestamp: ${expirationTimestamp}.`,
54
54
  );
55
55
  }
56
56
 
@@ -1,2 +1,2 @@
1
1
  export * from './private_kernel_reset_private_inputs_builder.js';
2
- export * from './compute_tx_include_by_timestamp.js';
2
+ export * from './compute_tx_expiration_timestamp.js';
@@ -10,7 +10,7 @@ import {
10
10
  import { makeTuple } from '@aztec/foundation/array';
11
11
  import { padArrayEnd } from '@aztec/foundation/collection';
12
12
  import type { Fr } from '@aztec/foundation/curves/bn254';
13
- import { type Tuple, assertLength } from '@aztec/foundation/serialize';
13
+ import { assertLength } from '@aztec/foundation/serialize';
14
14
  import { MembershipWitness } from '@aztec/foundation/trees';
15
15
  import { privateKernelResetDimensionsConfig } from '@aztec/noir-protocol-circuits-types/client';
16
16
  import {
@@ -26,14 +26,12 @@ import {
26
26
  type PrivateKernelSimulateOutput,
27
27
  ReadRequestActionEnum,
28
28
  ReadRequestResetActions,
29
- type ScopedKeyValidationRequestAndGenerator,
30
- ScopedNoteHash,
31
- ScopedNullifier,
32
- ScopedReadRequest,
29
+ type ScopedKeyValidationRequestAndSeparator,
33
30
  TransientDataSquashingHint,
34
31
  buildNoteHashReadRequestHintsFromResetActions,
35
32
  buildNullifierReadRequestHintsFromResetActions,
36
33
  buildTransientDataHints,
34
+ countSquashedLogs,
37
35
  findPrivateKernelResetDimensions,
38
36
  getNoteHashReadRequestResetActions,
39
37
  getNullifierReadRequestResetActions,
@@ -44,15 +42,6 @@ import { VkData } from '@aztec/stdlib/vks';
44
42
 
45
43
  import type { PrivateKernelOracle } from '../private_kernel_oracle.js';
46
44
 
47
- function collectNestedReadRequests<N extends number>(
48
- executionStack: PrivateCallExecutionResult[],
49
- extractReadRequests: (execution: PrivateCallExecutionResult) => ClaimedLengthArray<ScopedReadRequest, N>,
50
- ): ScopedReadRequest[] {
51
- return collectNested(executionStack, executionResult => {
52
- return extractReadRequests(executionResult).getActiveItems();
53
- });
54
- }
55
-
56
45
  function getNullifierMembershipWitnessResolver(oracle: PrivateKernelOracle) {
57
46
  return async (nullifier: Fr) => {
58
47
  const res = await oracle.getNullifierMembershipWitness(nullifier);
@@ -68,9 +57,9 @@ function getNullifierMembershipWitnessResolver(oracle: PrivateKernelOracle) {
68
57
  };
69
58
  }
70
59
 
71
- async function getMasterSecretKeysAndAppKeyGenerators(
60
+ async function getMasterSecretKeysAndKeyTypeDomainSeparators(
72
61
  keyValidationRequests: ClaimedLengthArray<
73
- ScopedKeyValidationRequestAndGenerator,
62
+ ScopedKeyValidationRequestAndSeparator,
74
63
  typeof MAX_KEY_VALIDATION_REQUESTS_PER_TX
75
64
  >,
76
65
  numRequestsToVerify: number,
@@ -91,11 +80,14 @@ export class PrivateKernelResetPrivateInputsBuilder {
91
80
  // If there's no next iteration, it's the final reset.
92
81
  private nextIteration?: PrivateCircuitPublicInputs;
93
82
 
94
- private noteHashResetActions: ReadRequestResetActions<typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX>;
95
- private nullifierResetActions: ReadRequestResetActions<typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>;
83
+ private noteHashResetActions = ReadRequestResetActions.empty(MAX_NOTE_HASH_READ_REQUESTS_PER_TX);
84
+ private nullifierResetActions = ReadRequestResetActions.empty(MAX_NULLIFIER_READ_REQUESTS_PER_TX);
96
85
  private numTransientData?: number;
97
- private transientDataSquashingHints: Tuple<TransientDataSquashingHint, typeof MAX_NULLIFIERS_PER_TX>;
98
- private requestedDimensions: PrivateKernelResetDimensions;
86
+ private transientDataSquashingHints = makeTuple(
87
+ MAX_NULLIFIERS_PER_TX,
88
+ () => new TransientDataSquashingHint(MAX_NULLIFIERS_PER_TX, MAX_NOTE_HASHES_PER_TX),
89
+ );
90
+ private requestedDimensions = PrivateKernelResetDimensions.empty();
99
91
 
100
92
  constructor(
101
93
  private previousKernelOutput: PrivateKernelSimulateOutput<PrivateKernelCircuitPublicInputs>,
@@ -104,21 +96,18 @@ export class PrivateKernelResetPrivateInputsBuilder {
104
96
  private splitCounter: number,
105
97
  ) {
106
98
  this.previousKernel = previousKernelOutput.publicInputs;
107
- this.requestedDimensions = PrivateKernelResetDimensions.empty();
108
- this.noteHashResetActions = ReadRequestResetActions.empty(MAX_NOTE_HASH_READ_REQUESTS_PER_TX);
109
- this.nullifierResetActions = ReadRequestResetActions.empty(MAX_NULLIFIER_READ_REQUESTS_PER_TX);
110
- this.transientDataSquashingHints = makeTuple(
111
- MAX_NULLIFIERS_PER_TX,
112
- () => new TransientDataSquashingHint(MAX_NULLIFIERS_PER_TX, MAX_NOTE_HASHES_PER_TX),
113
- );
114
99
  this.nextIteration = executionStack[this.executionStack.length - 1]?.publicInputs;
115
100
  }
116
101
 
102
+ getRequestedDimensions(): PrivateKernelResetDimensions {
103
+ return this.requestedDimensions;
104
+ }
105
+
117
106
  needsReset(): boolean {
118
107
  const fns: (() => boolean)[] = [
119
108
  () => this.needsResetNoteHashReadRequests(),
120
109
  () => this.needsResetNullifierReadRequests(),
121
- () => this.needsResetNullifierKeys(),
110
+ () => this.needsResetKeyValidationRequests(),
122
111
  () => this.needsResetTransientData(),
123
112
  ];
124
113
 
@@ -145,8 +134,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
145
134
 
146
135
  const isInner = !!this.nextIteration;
147
136
 
148
- // "final" reset must be done at most once.
149
- // Because the code that silo note hashes can't be run repeatedly.
137
+ // "final" reset must be done exactly once, because siloing can't be run repeatedly.
150
138
  // The dimensions found must be big enough to reset all values, i.e. empty remainder.
151
139
  const allowRemainder = isInner;
152
140
 
@@ -189,8 +177,8 @@ export class PrivateKernelResetPrivateInputsBuilder {
189
177
  this.previousKernel.validationRequests.nullifierReadRequests,
190
178
  this.nullifierResetActions,
191
179
  ),
192
- getMasterSecretKeysAndAppKeyGenerators(
193
- this.previousKernel.validationRequests.scopedKeyValidationRequestsAndGenerators,
180
+ getMasterSecretKeysAndKeyTypeDomainSeparators(
181
+ this.previousKernel.validationRequests.scopedKeyValidationRequestsAndSeparators,
194
182
  dimensions.KEY_VALIDATION,
195
183
  oracle,
196
184
  ),
@@ -246,24 +234,17 @@ export class PrivateKernelResetPrivateInputsBuilder {
246
234
  resetActions.pendingReadHints = resetActions.pendingReadHints.slice(0, maxPending);
247
235
  }
248
236
 
249
- private needsResetNoteHashReadRequests(forceResetAll = false) {
237
+ private needsResetNoteHashReadRequests(forceReset = false) {
250
238
  const numCurr = this.previousKernel.validationRequests.noteHashReadRequests.claimedLength;
251
239
  const numNext = this.nextIteration ? this.nextIteration.noteHashReadRequests.claimedLength : 0;
252
- const maxAmountToKeep = !this.nextIteration || forceResetAll ? 0 : MAX_NOTE_HASH_READ_REQUESTS_PER_TX;
240
+ const maxAmountToKeep = !this.nextIteration || forceReset ? 0 : MAX_NOTE_HASH_READ_REQUESTS_PER_TX;
253
241
  if (numCurr + numNext <= maxAmountToKeep) {
254
242
  return false;
255
243
  }
256
244
 
257
- const futureNoteHashes = collectNested(this.executionStack, executionResult => {
258
- return executionResult.publicInputs.noteHashes
259
- .getActiveItems()
260
- .map(noteHash => new ScopedNoteHash(noteHash, executionResult.publicInputs.callContext.contractAddress));
261
- });
262
-
263
245
  const resetActions = getNoteHashReadRequestResetActions(
264
246
  this.previousKernel.validationRequests.noteHashReadRequests,
265
247
  this.previousKernel.end.noteHashes,
266
- futureNoteHashes,
267
248
  );
268
249
 
269
250
  const numPendingReads = resetActions.pendingReadHints.length;
@@ -272,53 +253,72 @@ export class PrivateKernelResetPrivateInputsBuilder {
272
253
  0,
273
254
  );
274
255
 
256
+ const totalReadsToReset = numPendingReads + numSettledReads;
257
+ const minResetNeeded = numCurr + numNext - maxAmountToKeep;
258
+ if (totalReadsToReset < minResetNeeded) {
259
+ if (!this.nextIteration) {
260
+ // In the final reset, all note hashes have been emitted. So if we can't reset all requests, at least one
261
+ // pending read request doesn't match any of them.
262
+ throw new Error('No matching note hash found for note hash read request.');
263
+ } else if (!forceReset) {
264
+ // A pending read request can only be reset if its note hash has already been included (e.g. a parent call might
265
+ // be reading a note hash emitted by a child call. The read request of the parent call is included before the note
266
+ // hash of the child call).
267
+ // If we can't clear enough read requests to make room for the next iteration's reads, we're stuck.
268
+ throw new Error('Number of note hash read requests exceeds the limit.');
269
+ } else if (totalReadsToReset == 0) {
270
+ // It's transient data squashing asking for the read requests to be reset first (forceReset == true), and
271
+ // there's nothing to reset, returns false and let needsResetTransientData throw a more descriptive error.
272
+ return false;
273
+ }
274
+ // Otherwise, forceReset is true, we should proceed to reset as many as we can.
275
+ }
276
+
275
277
  if (!this.nextIteration) {
278
+ // If there's no next iteration, we need to reset all the read requests.
276
279
  this.noteHashResetActions = resetActions;
277
280
  this.requestedDimensions.NOTE_HASH_PENDING_READ = numPendingReads;
278
281
  this.requestedDimensions.NOTE_HASH_SETTLED_READ = numSettledReads;
279
282
  } else {
280
- // Pick only one dimension to reset if next iteration is not empty.
283
+ // If there's a next iteration, only one dimension can be reset at a time.
284
+ // So we pick the dimension that has more read requests to reset.
281
285
  if (numPendingReads > numSettledReads) {
282
- this.requestedDimensions.NOTE_HASH_PENDING_READ = numPendingReads;
283
- this.noteHashResetActions.actions = assertLength(
286
+ // Reset the pending read requests.
287
+ const pendingOnlyActions = assertLength(
284
288
  resetActions.actions.map(action =>
285
289
  action === ReadRequestActionEnum.READ_AS_PENDING ? action : ReadRequestActionEnum.SKIP,
286
290
  ),
287
291
  MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
288
292
  );
289
- this.noteHashResetActions.pendingReadHints = resetActions.pendingReadHints;
293
+ this.noteHashResetActions = new ReadRequestResetActions(pendingOnlyActions, resetActions.pendingReadHints);
294
+ this.requestedDimensions.NOTE_HASH_PENDING_READ = numPendingReads;
290
295
  } else {
291
- this.requestedDimensions.NOTE_HASH_SETTLED_READ = numSettledReads;
292
- this.noteHashResetActions.actions = assertLength(
296
+ // Reset the settled read requests.
297
+ const settledOnlyActions = assertLength(
293
298
  resetActions.actions.map(action =>
294
299
  action === ReadRequestActionEnum.READ_AS_SETTLED ? action : ReadRequestActionEnum.SKIP,
295
300
  ),
296
301
  MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
297
302
  );
303
+ this.noteHashResetActions = new ReadRequestResetActions(settledOnlyActions, []);
304
+ this.requestedDimensions.NOTE_HASH_SETTLED_READ = numSettledReads;
298
305
  }
299
306
  }
300
307
 
301
308
  return true;
302
309
  }
303
310
 
304
- private needsResetNullifierReadRequests(forceResetAll = false) {
311
+ private needsResetNullifierReadRequests(forceReset = false) {
305
312
  const numCurr = this.previousKernel.validationRequests.nullifierReadRequests.claimedLength;
306
313
  const numNext = this.nextIteration ? this.nextIteration.nullifierReadRequests.claimedLength : 0;
307
- const maxAmountToKeep = !this.nextIteration || forceResetAll ? 0 : MAX_NULLIFIER_READ_REQUESTS_PER_TX;
314
+ const maxAmountToKeep = !this.nextIteration || forceReset ? 0 : MAX_NULLIFIER_READ_REQUESTS_PER_TX;
308
315
  if (numCurr + numNext <= maxAmountToKeep) {
309
316
  return false;
310
317
  }
311
318
 
312
- const futureNullifiers = collectNested(this.executionStack, executionResult => {
313
- return executionResult.publicInputs.nullifiers
314
- .getActiveItems()
315
- .map(nullifier => new ScopedNullifier(nullifier, executionResult.publicInputs.callContext.contractAddress));
316
- });
317
-
318
319
  const resetActions = getNullifierReadRequestResetActions(
319
320
  this.previousKernel.validationRequests.nullifierReadRequests,
320
321
  this.previousKernel.end.nullifiers,
321
- futureNullifiers,
322
322
  );
323
323
 
324
324
  const numPendingReads = resetActions.pendingReadHints.length;
@@ -327,38 +327,63 @@ export class PrivateKernelResetPrivateInputsBuilder {
327
327
  0,
328
328
  );
329
329
 
330
+ const totalReadsToReset = numPendingReads + numSettledReads;
331
+ const minResetNeeded = numCurr + numNext - maxAmountToKeep;
332
+ if (totalReadsToReset < minResetNeeded) {
333
+ if (!this.nextIteration) {
334
+ // In the final reset, all nullifiers have been emitted. So if we can't reset all requests, at least one pending
335
+ // read request doesn't match any of them.
336
+ throw new Error('No matching nullifier found for nullifier read request.');
337
+ } else if (!forceReset) {
338
+ // A pending read request can only be reset if its nullifier has already been included (e.g. a parent call might
339
+ // be reading a nullifier emitted by a child call. The read request of the parent call is included before the
340
+ // nullifier of the child call).
341
+ // If we can't clear enough read requests to make room for the next iteration's reads, we're stuck.
342
+ throw new Error('Number of nullifier read requests exceeds the limit.');
343
+ } else if (totalReadsToReset == 0) {
344
+ // It's transient data squashing asking for the read requests to be reset first (forceReset == true), and
345
+ // there's nothing to reset, returns false and let needsResetTransientData throw a more descriptive error.
346
+ return false;
347
+ }
348
+ // Otherwise, forceReset is true, we should proceed to reset as many as we can.
349
+ }
350
+
330
351
  if (!this.nextIteration) {
352
+ // If there's no next iteration, we need to reset all the read requests.
331
353
  this.nullifierResetActions = resetActions;
332
354
  this.requestedDimensions.NULLIFIER_PENDING_READ = numPendingReads;
333
355
  this.requestedDimensions.NULLIFIER_SETTLED_READ = numSettledReads;
334
356
  } else {
335
- // Pick only one dimension to reset if next iteration is not empty.
357
+ // If there's a next iteration, we can only reset one dimension at a time.
336
358
  if (numPendingReads > numSettledReads) {
337
- this.requestedDimensions.NULLIFIER_PENDING_READ = numPendingReads;
338
- this.nullifierResetActions.actions = assertLength(
359
+ // Reset the pending read requests.
360
+ const pendingOnlyActions = assertLength(
339
361
  resetActions.actions.map(action =>
340
362
  action === ReadRequestActionEnum.READ_AS_PENDING ? action : ReadRequestActionEnum.SKIP,
341
363
  ),
342
364
  MAX_NULLIFIER_READ_REQUESTS_PER_TX,
343
365
  );
344
- this.nullifierResetActions.pendingReadHints = resetActions.pendingReadHints;
366
+ this.nullifierResetActions = new ReadRequestResetActions(pendingOnlyActions, resetActions.pendingReadHints);
367
+ this.requestedDimensions.NULLIFIER_PENDING_READ = numPendingReads;
345
368
  } else {
346
- this.requestedDimensions.NULLIFIER_SETTLED_READ = numSettledReads;
347
- this.nullifierResetActions.actions = assertLength(
369
+ // Reset the settled read requests.
370
+ const settledOnlyActions = assertLength(
348
371
  resetActions.actions.map(action =>
349
372
  action === ReadRequestActionEnum.READ_AS_SETTLED ? action : ReadRequestActionEnum.SKIP,
350
373
  ),
351
374
  MAX_NULLIFIER_READ_REQUESTS_PER_TX,
352
375
  );
376
+ this.nullifierResetActions = new ReadRequestResetActions(settledOnlyActions, []);
377
+ this.requestedDimensions.NULLIFIER_SETTLED_READ = numSettledReads;
353
378
  }
354
379
  }
355
380
 
356
381
  return true;
357
382
  }
358
383
 
359
- private needsResetNullifierKeys() {
360
- const numCurr = this.previousKernel.validationRequests.scopedKeyValidationRequestsAndGenerators.claimedLength;
361
- const numNext = this.nextIteration ? this.nextIteration.keyValidationRequestsAndGenerators.claimedLength : 0;
384
+ private needsResetKeyValidationRequests() {
385
+ const numCurr = this.previousKernel.validationRequests.scopedKeyValidationRequestsAndSeparators.claimedLength;
386
+ const numNext = this.nextIteration ? this.nextIteration.keyValidationRequestsAndSeparators.claimedLength : 0;
362
387
  const maxAmountToKeep = !this.nextIteration ? 0 : MAX_KEY_VALIDATION_REQUESTS_PER_TX;
363
388
  if (numCurr + numNext <= maxAmountToKeep) {
364
389
  return false;
@@ -370,9 +395,6 @@ export class PrivateKernelResetPrivateInputsBuilder {
370
395
  }
371
396
 
372
397
  private needsResetTransientData() {
373
- // Initialize this to 0 so that needsSilo can be run.
374
- this.numTransientData = 0;
375
-
376
398
  const nextAccumNoteHashes =
377
399
  this.previousKernel.end.noteHashes.claimedLength + (this.nextIteration?.noteHashes.claimedLength ?? 0);
378
400
  const noteHashWillOverflow = nextAccumNoteHashes > MAX_NOTE_HASHES_PER_TX;
@@ -387,19 +409,19 @@ export class PrivateKernelResetPrivateInputsBuilder {
387
409
  return false;
388
410
  }
389
411
 
390
- const futureNoteHashReads = collectNestedReadRequests(
391
- this.executionStack,
392
- executionResult => executionResult.publicInputs.noteHashReadRequests,
412
+ const futureNoteHashReads = collectNested(this.executionStack, executionResult =>
413
+ executionResult.publicInputs.noteHashReadRequests.getActiveItems(),
414
+ );
415
+ const futureNullifierReads = collectNested(this.executionStack, executionResult =>
416
+ executionResult.publicInputs.nullifierReadRequests.getActiveItems(),
393
417
  );
394
- const futureNullifierReads = collectNestedReadRequests(
395
- this.executionStack,
396
- executionResult => executionResult.publicInputs.nullifierReadRequests,
418
+ const futureLogs = collectNested(this.executionStack, executionResult =>
419
+ executionResult.publicInputs.privateLogs.getActiveItems(),
397
420
  );
398
- // TODO(#15902): Collect future logs and only allow squashing a note hash when all its logs have been emitted
399
- // (i.e. none of the future logs are linked to the to-be-squashed note hashes).
400
421
  if (this.nextIteration) {
401
- // If it's not the final reset, only one dimension will be reset at a time.
402
- // The note hashes and nullifiers for the remaining read requests can't be squashed.
422
+ // If it's not the final reset, only one dimension will be reset at a time. Since we are resetting the transient
423
+ // data, the note hash and nullifier read requests in the previous kernel won't be squashed and need to be
424
+ // included in the future read requests.
403
425
  futureNoteHashReads.push(...this.previousKernel.validationRequests.noteHashReadRequests.getActiveItems());
404
426
  futureNullifierReads.push(...this.previousKernel.validationRequests.nullifierReadRequests.getActiveItems());
405
427
  }
@@ -409,27 +431,50 @@ export class PrivateKernelResetPrivateInputsBuilder {
409
431
  this.previousKernel.end.nullifiers,
410
432
  futureNoteHashReads,
411
433
  futureNullifierReads,
434
+ futureLogs,
412
435
  this.noteHashNullifierCounterMap,
413
436
  this.splitCounter,
414
437
  );
415
438
 
416
- if (this.nextIteration && !numTransientData) {
417
- const forceResetAll = true;
418
- const canClearReadRequests =
419
- (noteHashWillOverflow && this.needsResetNoteHashReadRequests(forceResetAll)) ||
420
- (nullifierWillOverflow && this.needsResetNullifierReadRequests(forceResetAll)) ||
421
- (logsWillOverflow && this.needsResetNoteHashReadRequests(forceResetAll));
422
- if (!canClearReadRequests) {
423
- const overflownData = noteHashWillOverflow
424
- ? 'note hashes'
425
- : nullifierWillOverflow
426
- ? 'nullifiers'
427
- : 'private logs';
428
- throw new Error(`Number of ${overflownData} exceeds the limit.`);
439
+ if (this.nextIteration) {
440
+ const noteHashOverflowBy = noteHashWillOverflow
441
+ ? nextAccumNoteHashes - MAX_NOTE_HASHES_PER_TX - numTransientData
442
+ : 0;
443
+ const nullifierOverflowBy = nullifierWillOverflow
444
+ ? nextAccumNullifiers - MAX_NULLIFIERS_PER_TX - numTransientData
445
+ : 0;
446
+ const numSquashedLogs = logsWillOverflow
447
+ ? countSquashedLogs(
448
+ this.previousKernel.end.noteHashes,
449
+ this.previousKernel.end.privateLogs,
450
+ transientDataSquashingHints.slice(0, numTransientData),
451
+ )
452
+ : 0;
453
+ const logsOverflowBy = logsWillOverflow ? nextAccumLogs - MAX_PRIVATE_LOGS_PER_TX - numSquashedLogs : 0;
454
+
455
+ if (noteHashOverflowBy > 0 || nullifierOverflowBy > 0 || logsOverflowBy > 0) {
456
+ // There's not enough transient data to squash to clear space for the overflow. It may be because some data is
457
+ // still required for read requests. Force a reset of the read requests first, and return to transient data
458
+ // squashing in the next round of reset.
459
+ // Note that clearing the read requests might not be enough to clear more space for the overflow. In this case,
460
+ // running the next reset will fail at the following check.
461
+ // Only one dimension can be reset at a time for an inner reset, so we try the note hash read requests first
462
+ // (which also helps with log overflow), then fall back to nullifier read requests.
463
+ const forceReset = true;
464
+ if ((noteHashOverflowBy > 0 || logsOverflowBy > 0) && this.needsResetNoteHashReadRequests(forceReset)) {
465
+ return true;
466
+ }
467
+ if (nullifierOverflowBy > 0 && this.needsResetNullifierReadRequests(forceReset)) {
468
+ return true;
469
+ }
470
+ if (noteHashWillOverflow) {
471
+ throw new Error('Number of note hashes exceeds the limit.');
472
+ }
473
+ if (nullifierWillOverflow) {
474
+ throw new Error('Number of nullifiers exceeds the limit.');
475
+ }
476
+ throw new Error('Number of private logs exceeds the limit.');
429
477
  }
430
- // Clearing the read requests might not be enough to squash the overflown data.
431
- // In this case, the next iteration will fail at the above check.
432
- return true;
433
478
  }
434
479
 
435
480
  this.numTransientData = numTransientData;
@@ -444,10 +489,13 @@ export class PrivateKernelResetPrivateInputsBuilder {
444
489
  throw new Error('`needsResetTransientData` must be run before `needsSiloNoteHashes`.');
445
490
  }
446
491
 
447
- const numNoteHashes = this.previousKernel.end.noteHashes
448
- .getActiveItems()
449
- .filter(n => !n.contractAddress.isZero()).length;
450
- const numToSilo = Math.max(0, numNoteHashes - this.numTransientData);
492
+ const noteHashes = this.previousKernel.end.noteHashes;
493
+ if (noteHashes.claimedLength > 0 && noteHashes.array[0].contractAddress.isZero()) {
494
+ // Already siloed.
495
+ return false;
496
+ }
497
+
498
+ const numToSilo = noteHashes.claimedLength - this.numTransientData;
451
499
  this.requestedDimensions.NOTE_HASH_SILOING = numToSilo;
452
500
 
453
501
  return numToSilo > 0;
@@ -458,15 +506,14 @@ export class PrivateKernelResetPrivateInputsBuilder {
458
506
  throw new Error('`needsResetTransientData` must be run before `needsSiloNullifiers`.');
459
507
  }
460
508
 
461
- const numNullifiers = this.previousKernel.end.nullifiers
462
- .getActiveItems()
463
- .filter(n => !n.contractAddress.isZero()).length;
464
- const numToSilo = Math.max(0, numNullifiers - this.numTransientData);
465
- // Include the first nullifier if there's something to silo.
466
- // The reset circuit checks that capped_size must be greater than or equal to all non-empty nullifiers.
467
- // Which includes the first nullifier, even though its contract address is always zero and doesn't need siloing.
468
- const cappedSize = numToSilo ? numToSilo + 1 : 0;
469
- this.requestedDimensions.NULLIFIER_SILOING = cappedSize;
509
+ const nullifiers = this.previousKernel.end.nullifiers;
510
+ if (nullifiers.claimedLength > 0 && nullifiers.array[0].contractAddress.isZero()) {
511
+ // Already siloed.
512
+ return false;
513
+ }
514
+
515
+ const numToSilo = nullifiers.claimedLength - this.numTransientData;
516
+ this.requestedDimensions.NULLIFIER_SILOING = numToSilo;
470
517
 
471
518
  return numToSilo > 0;
472
519
  }
@@ -477,17 +524,17 @@ export class PrivateKernelResetPrivateInputsBuilder {
477
524
  }
478
525
 
479
526
  const privateLogs = this.previousKernel.end.privateLogs;
480
- const numLogs = privateLogs.getActiveItems().filter(l => !l.contractAddress.isZero()).length;
527
+ if (privateLogs.claimedLength > 0 && privateLogs.array[0].contractAddress.isZero()) {
528
+ // Already siloed.
529
+ return false;
530
+ }
481
531
 
482
- const noteHashes = this.previousKernel.end.noteHashes;
483
- const squashedNoteHashCounters = this.transientDataSquashingHints
484
- .filter(h => h.noteHashIndex < noteHashes.claimedLength)
485
- .map(h => noteHashes.array[h.noteHashIndex].counter);
486
- const numSquashedLogs = privateLogs
487
- .getActiveItems()
488
- .filter(l => squashedNoteHashCounters.includes(l.inner.noteHashCounter)).length;
489
-
490
- const numToSilo = numLogs - numSquashedLogs;
532
+ const numSquashedLogs = countSquashedLogs(
533
+ this.previousKernel.end.noteHashes,
534
+ privateLogs,
535
+ this.transientDataSquashingHints.slice(0, this.numTransientData),
536
+ );
537
+ const numToSilo = privateLogs.claimedLength - numSquashedLogs;
491
538
  this.requestedDimensions.PRIVATE_LOG_SILOING = numToSilo;
492
539
 
493
540
  return numToSilo > 0;