@aztec/stdlib 0.0.1-commit.e0f15ab9b → 0.0.1-commit.e304674f1

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 (182) hide show
  1. package/dest/abi/decoder.d.ts +5 -44
  2. package/dest/abi/decoder.d.ts.map +1 -1
  3. package/dest/abi/decoder.js +12 -67
  4. package/dest/abi/function_selector.js +1 -1
  5. package/dest/abi/function_signature_decoder.d.ts +43 -0
  6. package/dest/abi/function_signature_decoder.d.ts.map +1 -0
  7. package/dest/abi/function_signature_decoder.js +66 -0
  8. package/dest/abi/index.d.ts +2 -1
  9. package/dest/abi/index.d.ts.map +1 -1
  10. package/dest/abi/index.js +1 -0
  11. package/dest/abi/selector.d.ts +2 -2
  12. package/dest/abi/selector.d.ts.map +1 -1
  13. package/dest/abi/selector.js +1 -1
  14. package/dest/avm/revert_code.d.ts +8 -18
  15. package/dest/avm/revert_code.d.ts.map +1 -1
  16. package/dest/avm/revert_code.js +15 -30
  17. package/dest/block/l2_block_source.d.ts +80 -3
  18. package/dest/block/l2_block_source.d.ts.map +1 -1
  19. package/dest/block/l2_block_source.js +1 -0
  20. package/dest/block/l2_block_stream/l2_tips_store_base.d.ts +1 -1
  21. package/dest/block/l2_block_stream/l2_tips_store_base.d.ts.map +1 -1
  22. package/dest/block/l2_block_stream/l2_tips_store_base.js +17 -4
  23. package/dest/block/test/l2_tips_store_test_suite.d.ts +1 -1
  24. package/dest/block/test/l2_tips_store_test_suite.d.ts.map +1 -1
  25. package/dest/block/test/l2_tips_store_test_suite.js +3 -2
  26. package/dest/checkpoint/checkpoint.d.ts +7 -1
  27. package/dest/checkpoint/checkpoint.d.ts.map +1 -1
  28. package/dest/checkpoint/checkpoint.js +9 -1
  29. package/dest/checkpoint/checkpoint_data.d.ts +71 -5
  30. package/dest/checkpoint/checkpoint_data.d.ts.map +1 -1
  31. package/dest/checkpoint/checkpoint_data.js +10 -0
  32. package/dest/epoch-helpers/index.d.ts +5 -1
  33. package/dest/epoch-helpers/index.d.ts.map +1 -1
  34. package/dest/epoch-helpers/index.js +6 -0
  35. package/dest/file-store/factory.d.ts +4 -3
  36. package/dest/file-store/factory.d.ts.map +1 -1
  37. package/dest/file-store/factory.js +2 -2
  38. package/dest/file-store/http.d.ts +9 -2
  39. package/dest/file-store/http.d.ts.map +1 -1
  40. package/dest/file-store/http.js +20 -9
  41. package/dest/file-store/index.d.ts +2 -1
  42. package/dest/file-store/index.d.ts.map +1 -1
  43. package/dest/gas/gas_settings.d.ts +40 -3
  44. package/dest/gas/gas_settings.d.ts.map +1 -1
  45. package/dest/gas/gas_settings.js +50 -6
  46. package/dest/hash/hash.d.ts +4 -1
  47. package/dest/hash/hash.d.ts.map +1 -1
  48. package/dest/hash/hash.js +5 -0
  49. package/dest/interfaces/archiver.d.ts +1 -1
  50. package/dest/interfaces/archiver.d.ts.map +1 -1
  51. package/dest/interfaces/archiver.js +3 -1
  52. package/dest/interfaces/aztec-node-admin.d.ts +4 -14
  53. package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
  54. package/dest/interfaces/aztec-node-admin.js +3 -3
  55. package/dest/interfaces/proving-job.d.ts +166 -166
  56. package/dest/interfaces/slasher.d.ts +1 -10
  57. package/dest/interfaces/slasher.d.ts.map +1 -1
  58. package/dest/interfaces/slasher.js +0 -2
  59. package/dest/interfaces/validator.d.ts +4 -15
  60. package/dest/interfaces/validator.d.ts.map +1 -1
  61. package/dest/interfaces/validator.js +0 -1
  62. package/dest/l1-contracts/index.d.ts +2 -2
  63. package/dest/l1-contracts/index.d.ts.map +1 -1
  64. package/dest/l1-contracts/index.js +1 -1
  65. package/dest/logs/extended_directional_app_tagging_secret.d.ts +4 -4
  66. package/dest/logs/extended_directional_app_tagging_secret.d.ts.map +1 -1
  67. package/dest/logs/extended_directional_app_tagging_secret.js +12 -5
  68. package/dest/logs/message_context.d.ts +4 -7
  69. package/dest/logs/message_context.d.ts.map +1 -1
  70. package/dest/logs/message_context.js +23 -9
  71. package/dest/logs/pending_tagged_log.d.ts +2 -3
  72. package/dest/logs/pending_tagged_log.d.ts.map +1 -1
  73. package/dest/logs/pending_tagged_log.js +2 -2
  74. package/dest/logs/shared_secret_derivation.d.ts +11 -10
  75. package/dest/logs/shared_secret_derivation.d.ts.map +1 -1
  76. package/dest/logs/shared_secret_derivation.js +15 -9
  77. package/dest/logs/siloed_tag.d.ts +4 -1
  78. package/dest/logs/siloed_tag.d.ts.map +1 -1
  79. package/dest/logs/siloed_tag.js +7 -3
  80. package/dest/messaging/l1_to_l2_message.d.ts +3 -2
  81. package/dest/messaging/l1_to_l2_message.d.ts.map +1 -1
  82. package/dest/messaging/l1_to_l2_message.js +11 -13
  83. package/dest/note/note_dao.d.ts +1 -1
  84. package/dest/note/note_dao.d.ts.map +1 -1
  85. package/dest/note/note_dao.js +1 -4
  86. package/dest/p2p/checkpoint_proposal.d.ts +2 -2
  87. package/dest/p2p/checkpoint_proposal.d.ts.map +1 -1
  88. package/dest/p2p/checkpoint_proposal.js +3 -15
  89. package/dest/proofs/chonk_proof.d.ts +46 -2
  90. package/dest/proofs/chonk_proof.d.ts.map +1 -1
  91. package/dest/proofs/chonk_proof.js +85 -10
  92. package/dest/slashing/index.d.ts +2 -3
  93. package/dest/slashing/index.d.ts.map +1 -1
  94. package/dest/slashing/index.js +1 -2
  95. package/dest/slashing/serialization.d.ts +2 -6
  96. package/dest/slashing/serialization.d.ts.map +1 -1
  97. package/dest/slashing/serialization.js +0 -60
  98. package/dest/slashing/types.d.ts +4 -90
  99. package/dest/slashing/types.d.ts.map +1 -1
  100. package/dest/slashing/types.js +0 -14
  101. package/dest/slashing/{tally.d.ts → votes.d.ts} +1 -1
  102. package/dest/slashing/{tally.d.ts.map → votes.d.ts.map} +1 -1
  103. package/dest/slashing/{tally.js → votes.js} +1 -1
  104. package/dest/tests/factories.d.ts +1 -1
  105. package/dest/tests/factories.d.ts.map +1 -1
  106. package/dest/tests/factories.js +11 -1
  107. package/dest/tests/mocks.d.ts +1 -1
  108. package/dest/tests/mocks.d.ts.map +1 -1
  109. package/dest/tests/mocks.js +13 -18
  110. package/dest/timetable/index.d.ts +2 -1
  111. package/dest/timetable/index.d.ts.map +1 -1
  112. package/dest/timetable/index.js +6 -2
  113. package/dest/tx/capsule.d.ts +6 -2
  114. package/dest/tx/capsule.d.ts.map +1 -1
  115. package/dest/tx/capsule.js +9 -3
  116. package/dest/tx/global_variable_builder.d.ts +14 -2
  117. package/dest/tx/global_variable_builder.d.ts.map +1 -1
  118. package/dest/tx/simulated_tx.d.ts +3 -3
  119. package/dest/tx/simulated_tx.d.ts.map +1 -1
  120. package/dest/tx/simulated_tx.js +2 -2
  121. package/dest/tx/tx_receipt.d.ts +8 -4
  122. package/dest/tx/tx_receipt.d.ts.map +1 -1
  123. package/dest/tx/tx_receipt.js +8 -15
  124. package/dest/world-state/genesis_data.d.ts +11 -0
  125. package/dest/world-state/genesis_data.d.ts.map +1 -0
  126. package/dest/world-state/genesis_data.js +4 -0
  127. package/dest/world-state/index.d.ts +2 -1
  128. package/dest/world-state/index.d.ts.map +1 -1
  129. package/dest/world-state/index.js +1 -0
  130. package/package.json +8 -8
  131. package/src/abi/decoder.ts +23 -78
  132. package/src/abi/function_selector.ts +1 -1
  133. package/src/abi/function_signature_decoder.ts +77 -0
  134. package/src/abi/index.ts +1 -0
  135. package/src/abi/selector.ts +1 -1
  136. package/src/avm/revert_code.ts +25 -39
  137. package/src/block/l2_block_source.ts +10 -2
  138. package/src/block/l2_block_stream/l2_tips_store_base.ts +24 -12
  139. package/src/block/test/l2_tips_store_test_suite.ts +8 -1
  140. package/src/checkpoint/checkpoint.ts +11 -1
  141. package/src/checkpoint/checkpoint_data.ts +40 -4
  142. package/src/epoch-helpers/index.ts +13 -0
  143. package/src/file-store/factory.ts +13 -4
  144. package/src/file-store/http.ts +29 -10
  145. package/src/file-store/index.ts +1 -0
  146. package/src/gas/gas_settings.ts +65 -12
  147. package/src/hash/hash.ts +5 -0
  148. package/src/interfaces/archiver.ts +3 -1
  149. package/src/interfaces/aztec-node-admin.ts +5 -7
  150. package/src/interfaces/slasher.ts +0 -6
  151. package/src/interfaces/validator.ts +2 -9
  152. package/src/l1-contracts/index.ts +1 -1
  153. package/src/logs/extended_directional_app_tagging_secret.ts +19 -8
  154. package/src/logs/message_context.ts +17 -7
  155. package/src/logs/pending_tagged_log.ts +1 -3
  156. package/src/logs/shared_secret_derivation.ts +21 -10
  157. package/src/logs/siloed_tag.ts +7 -2
  158. package/src/messaging/l1_to_l2_message.ts +12 -9
  159. package/src/note/note_dao.ts +1 -4
  160. package/src/p2p/checkpoint_proposal.ts +10 -26
  161. package/src/proofs/chonk_proof.ts +91 -5
  162. package/src/slashing/index.ts +1 -2
  163. package/src/slashing/serialization.ts +1 -81
  164. package/src/slashing/types.ts +3 -35
  165. package/src/slashing/{tally.ts → votes.ts} +1 -1
  166. package/src/tests/factories.ts +5 -1
  167. package/src/tests/mocks.ts +14 -12
  168. package/src/timetable/index.ts +7 -2
  169. package/src/tx/capsule.ts +10 -2
  170. package/src/tx/global_variable_builder.ts +15 -0
  171. package/src/tx/simulated_tx.ts +5 -1
  172. package/src/tx/tx_receipt.ts +11 -14
  173. package/src/world-state/genesis_data.ts +15 -0
  174. package/src/world-state/index.ts +1 -0
  175. package/dest/l1-contracts/slash_factory.d.ts +0 -45
  176. package/dest/l1-contracts/slash_factory.d.ts.map +0 -1
  177. package/dest/l1-contracts/slash_factory.js +0 -158
  178. package/dest/slashing/empire.d.ts +0 -31
  179. package/dest/slashing/empire.d.ts.map +0 -1
  180. package/dest/slashing/empire.js +0 -87
  181. package/src/l1-contracts/slash_factory.ts +0 -180
  182. package/src/slashing/empire.ts +0 -104
@@ -14,18 +14,54 @@ import { CheckpointHeader } from '../rollup/checkpoint_header.js';
14
14
  import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js';
15
15
  import { L1PublishedData } from './published_checkpoint.js';
16
16
 
17
- /** Lightweight checkpoint metadata without full block data. */
18
- export type CheckpointData = {
17
+ /** Base type for checkpoint data */
18
+ export type CommonCheckpointData = {
19
19
  checkpointNumber: CheckpointNumber;
20
20
  header: CheckpointHeader;
21
- archive: AppendOnlyTreeSnapshot;
22
- checkpointOutHash: Fr;
23
21
  startBlock: BlockNumber;
24
22
  blockCount: number;
23
+ };
24
+
25
+ /** Data stored with checkpoint data after publishing on l1 */
26
+ export type L1EnrichedCheckpointData = {
25
27
  attestations: CommitteeAttestation[];
26
28
  l1: L1PublishedData;
27
29
  };
28
30
 
31
+ /** Data stored alongside checkpoint data in storage */
32
+ export type StorageEnrichedCheckpointData = {
33
+ archive: AppendOnlyTreeSnapshot;
34
+ checkpointOutHash: Fr;
35
+ };
36
+
37
+ /** Data stored only with proposed checkpoint data */
38
+ export type ProposedOnlyCheckpointData = {
39
+ totalManaUsed: bigint;
40
+ feeAssetPriceModifier: bigint;
41
+ };
42
+
43
+ /** Lightweight checkpoint metadata without full block data. */
44
+ export type CheckpointData = CommonCheckpointData & StorageEnrichedCheckpointData & L1EnrichedCheckpointData;
45
+
46
+ /** Input for setting a proposed checkpoint. The archive and checkpointOutHash are computed
47
+ * internally by the block store from the stored blocks. */
48
+ export type ProposedCheckpointInput = CommonCheckpointData & ProposedOnlyCheckpointData;
49
+
50
+ /** Full data for a proposed checkpoint (proposed but not yet L1-confirmed).
51
+ * Includes fee-relevant fields used during pipelining to compute the fee header override. */
52
+ export type ProposedCheckpointData = ProposedCheckpointInput & StorageEnrichedCheckpointData;
53
+
54
+ export const ProposedCheckpointDataSchema = z.object({
55
+ checkpointNumber: CheckpointNumberSchema,
56
+ header: CheckpointHeader.schema,
57
+ archive: AppendOnlyTreeSnapshot.schema,
58
+ checkpointOutHash: schemas.Fr,
59
+ startBlock: BlockNumberSchema,
60
+ blockCount: z.number(),
61
+ totalManaUsed: schemas.BigInt,
62
+ feeAssetPriceModifier: schemas.BigInt,
63
+ });
64
+
29
65
  export const CheckpointDataSchema = z
30
66
  .object({
31
67
  checkpointNumber: CheckpointNumberSchema,
@@ -68,6 +68,14 @@ export function getNextL1SlotTimestamp(
68
68
  return constants.l1GenesisTime + (currentL1Slot + 1n) * BigInt(constants.ethereumSlotDuration);
69
69
  }
70
70
 
71
+ /** Returns the timestamp of the last L1 slot within a given L2 slot. */
72
+ export function getLastL1SlotTimestampForL2Slot(
73
+ slot: SlotNumber,
74
+ constants: Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration' | 'ethereumSlotDuration'>,
75
+ ): bigint {
76
+ return getTimestampForSlot(slot, constants) + BigInt(constants.slotDuration - constants.ethereumSlotDuration);
77
+ }
78
+
71
79
  /** Returns the L2 slot number at the next L1 block based on the current timestamp. */
72
80
  export function getSlotAtNextL1Block(
73
81
  currentL1Timestamp: bigint,
@@ -154,6 +162,11 @@ export function getProofSubmissionDeadlineTimestamp(
154
162
  return getTimestampForSlot(deadlineSlot, constants);
155
163
  }
156
164
 
165
+ /** Computes the quorum size required for a committee (⌊2n/3⌋ + 1). */
166
+ export function computeQuorum(committeeSize: number): number {
167
+ return Math.floor((committeeSize * 2) / 3) + 1;
168
+ }
169
+
157
170
  /** Returns the timestamp to start building a block for a given L2 slot. Computed as the start timestamp of the slot minus one L1 slot duration. */
158
171
  export function getSlotStartBuildTimestamp(
159
172
  slotNumber: SlotNumber,
@@ -1,7 +1,7 @@
1
1
  import { type Logger, createLogger } from '@aztec/foundation/log';
2
2
 
3
3
  import { GoogleCloudFileStore } from './gcs.js';
4
- import { HttpFileStore } from './http.js';
4
+ import { HttpFileStore, type HttpFileStoreOptions } from './http.js';
5
5
  import type { FileStore, ReadOnlyFileStore } from './interface.js';
6
6
  import { LocalFileStore } from './local.js';
7
7
  import { S3FileStore } from './s3.js';
@@ -59,17 +59,26 @@ export async function createFileStore(
59
59
  }
60
60
  }
61
61
 
62
- export async function createReadOnlyFileStore(config: string, logger?: Logger): Promise<ReadOnlyFileStore>;
63
- export async function createReadOnlyFileStore(config: undefined, logger?: Logger): Promise<undefined>;
62
+ export async function createReadOnlyFileStore(
63
+ config: string,
64
+ logger?: Logger,
65
+ options?: HttpFileStoreOptions,
66
+ ): Promise<ReadOnlyFileStore>;
67
+ export async function createReadOnlyFileStore(
68
+ config: undefined,
69
+ logger?: Logger,
70
+ options?: HttpFileStoreOptions,
71
+ ): Promise<undefined>;
64
72
  export async function createReadOnlyFileStore(
65
73
  config: string | undefined,
66
74
  logger = createLogger('stdlib:file-store'),
75
+ options?: HttpFileStoreOptions,
67
76
  ): Promise<ReadOnlyFileStore | undefined> {
68
77
  if (config === undefined) {
69
78
  return undefined;
70
79
  } else if (config.startsWith('http://') || config.startsWith('https://')) {
71
80
  logger.info(`Creating read-only HTTP file store at ${config}`);
72
- return new HttpFileStore(config, logger);
81
+ return new HttpFileStore(config, logger, options);
73
82
  } else {
74
83
  return await createFileStore(config, logger);
75
84
  }
@@ -10,6 +10,14 @@ import { pipeline } from 'stream/promises';
10
10
 
11
11
  import type { ReadOnlyFileStore } from './interface.js';
12
12
 
13
+ /** Options for configuring HttpFileStore behavior. */
14
+ export interface HttpFileStoreOptions {
15
+ /** Retry backoff intervals in seconds. Empty array disables retries. Default: [1, 1, 3]. */
16
+ retryBackoff?: number[];
17
+ /** Request timeout in milliseconds. Default: no timeout (axios default). */
18
+ timeoutMs?: number;
19
+ }
20
+
13
21
  export class HttpFileStore implements ReadOnlyFileStore {
14
22
  private readonly axiosInstance: AxiosInstance;
15
23
  private readonly fetch: <T>(config: AxiosRequestConfig) => Promise<AxiosResponse<T>>;
@@ -17,17 +25,28 @@ export class HttpFileStore implements ReadOnlyFileStore {
17
25
  constructor(
18
26
  private readonly baseUrl: string,
19
27
  private readonly log: Logger = createLogger('stdlib:http-file-store'),
28
+ options?: HttpFileStoreOptions,
20
29
  ) {
21
- this.axiosInstance = axios.create();
22
- this.fetch = async <T>(config: AxiosRequestConfig) => {
23
- return await retry(
24
- () => this.axiosInstance.request<T>(config),
25
- `Fetching ${config.url}`,
26
- makeBackoff([1, 1, 3]),
27
- this.log,
28
- /*failSilently=*/ true,
29
- );
30
- };
30
+ this.axiosInstance = axios.create({
31
+ ...(options?.timeoutMs !== undefined && { timeout: options.timeoutMs }),
32
+ });
33
+
34
+ const retryBackoff = options?.retryBackoff ?? [1, 1, 3];
35
+ if (retryBackoff.length > 0) {
36
+ this.fetch = async <T>(config: AxiosRequestConfig) => {
37
+ return await retry(
38
+ () => this.axiosInstance.request<T>(config),
39
+ `Fetching ${config.url}`,
40
+ makeBackoff(retryBackoff),
41
+ this.log,
42
+ /*failSilently=*/ true,
43
+ );
44
+ };
45
+ } else {
46
+ this.fetch = async <T>(config: AxiosRequestConfig) => {
47
+ return await this.axiosInstance.request<T>(config);
48
+ };
49
+ }
31
50
  }
32
51
 
33
52
  public async read(pathOrUrl: string): Promise<Buffer> {
@@ -1,2 +1,3 @@
1
1
  export * from './interface.js';
2
2
  export * from './factory.js';
3
+ export { type HttpFileStoreOptions } from './http.js';
@@ -1,10 +1,4 @@
1
- import {
2
- DEFAULT_DA_GAS_LIMIT,
3
- DEFAULT_L2_GAS_LIMIT,
4
- DEFAULT_TEARDOWN_DA_GAS_LIMIT,
5
- DEFAULT_TEARDOWN_L2_GAS_LIMIT,
6
- GAS_SETTINGS_LENGTH,
7
- } from '@aztec/constants';
1
+ import { GAS_SETTINGS_LENGTH, MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS } from '@aztec/constants';
8
2
  import { Fr } from '@aztec/foundation/curves/bn254';
9
3
  import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize';
10
4
  import type { FieldsOf } from '@aztec/foundation/types';
@@ -14,6 +8,21 @@ import { z } from 'zod';
14
8
  import { Gas, GasDimensions } from './gas.js';
15
9
  import { GasFees } from './gas_fees.js';
16
10
 
11
+ /** Approximate max DA gas limit. Arbitrary, assuming 4 blocks per checkpoint — users should use gas estimation. */
12
+ export const APPROXIMATE_MAX_DA_GAS_PER_BLOCK = Math.floor(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT / 4);
13
+ /** Fallback teardown L2 gas limit. Arbitrary — users should use gas estimation. */
14
+ export const FALLBACK_TEARDOWN_L2_GAS_LIMIT = Math.floor(MAX_PROCESSABLE_L2_GAS / 8);
15
+ /** Fallback teardown DA gas limit. Arbitrary — users should use gas estimation. */
16
+ export const FALLBACK_TEARDOWN_DA_GAS_LIMIT = Math.floor(APPROXIMATE_MAX_DA_GAS_PER_BLOCK / 2);
17
+
18
+ // For gas estimation, we use intentionally high limits above what the network can process,
19
+ // so the simulation runs without hitting gas caps. Since teardown gas is counted towards total,
20
+ // the total estimation limit is teardown + max processable.
21
+ export const GAS_ESTIMATION_TEARDOWN_L2_GAS_LIMIT = MAX_PROCESSABLE_L2_GAS;
22
+ export const GAS_ESTIMATION_L2_GAS_LIMIT = GAS_ESTIMATION_TEARDOWN_L2_GAS_LIMIT + MAX_PROCESSABLE_L2_GAS;
23
+ export const GAS_ESTIMATION_TEARDOWN_DA_GAS_LIMIT = MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT;
24
+ export const GAS_ESTIMATION_DA_GAS_LIMIT = GAS_ESTIMATION_TEARDOWN_DA_GAS_LIMIT + MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT;
25
+
17
26
  // docs:start:gas_settings_vars
18
27
  /** Gas usage and fees limits set by the transaction sender for different dimensions and phases. */
19
28
  export class GasSettings {
@@ -95,18 +104,62 @@ export class GasSettings {
95
104
  return new GasSettings(Gas.empty(), Gas.empty(), GasFees.empty(), GasFees.empty());
96
105
  }
97
106
 
98
- /** Default gas settings to use when user has not provided them. Requires explicit max fees per gas. */
99
- static default(overrides: {
107
+ /**
108
+ * Fills in gas limits high enough for transactions to be included in most cases.
109
+ * gasLimits is set to the maximum the protocol allows; since teardown gas is reserved
110
+ * from gasLimits during private execution (see gas_meter.nr), the effective gas available
111
+ * for app logic will be gasLimits - teardownGasLimits - privateOverhead.
112
+ * The DA gas limit is set to an approximate max per block assuming 4 blocks per checkpoint,
113
+ * since using the maximum per checkpoint would cause nodes to reject transactions.
114
+ * These values won't work if:
115
+ * - Teardown consumes more than the arbitrarily assigned fallback limits
116
+ * - The rest of the transaction consumes more than the remaining gas after teardown
117
+ * - The DA gas limit is too low for the transaction, while still within the checkpoint limit
118
+ */
119
+ static fallback(overrides: {
120
+ gasLimits?: Gas;
121
+ teardownGasLimits?: Gas;
122
+ maxFeesPerGas: GasFees;
123
+ maxPriorityFeesPerGas?: GasFees;
124
+ }) {
125
+ return GasSettings.from({
126
+ gasLimits: overrides.gasLimits ?? {
127
+ l2Gas: MAX_PROCESSABLE_L2_GAS,
128
+ daGas: APPROXIMATE_MAX_DA_GAS_PER_BLOCK,
129
+ },
130
+ teardownGasLimits: overrides.teardownGasLimits ?? {
131
+ l2Gas: FALLBACK_TEARDOWN_L2_GAS_LIMIT,
132
+ daGas: FALLBACK_TEARDOWN_DA_GAS_LIMIT,
133
+ },
134
+ maxFeesPerGas: overrides.maxFeesPerGas,
135
+ maxPriorityFeesPerGas: overrides.maxPriorityFeesPerGas ?? GasFees.empty(),
136
+ });
137
+ }
138
+
139
+ /**
140
+ * Gas settings for simulation/estimation only.
141
+ * Since teardown gas is reserved upfront from gasLimits during private execution (see gas_meter.nr),
142
+ * the effective gas available for app logic is gasLimits - teardownGasLimits - privateOverhead.
143
+ * To ensure estimation never hits gas caps, we set both limits above what the protocol allows:
144
+ * teardown gets MAX_PROCESSABLE and gasLimits gets teardown + MAX_PROCESSABLE, so the full
145
+ * processable amount remains available for each phase independently. To be used in conjunction
146
+ * with skipTxValidation: true during public simulation, or the node would reject the transaction
147
+ * outright due to gas limits being above protocol max.
148
+ */
149
+ static forEstimation(overrides: {
100
150
  gasLimits?: Gas;
101
151
  teardownGasLimits?: Gas;
102
152
  maxFeesPerGas: GasFees;
103
153
  maxPriorityFeesPerGas?: GasFees;
104
154
  }) {
105
155
  return GasSettings.from({
106
- gasLimits: overrides.gasLimits ?? { l2Gas: DEFAULT_L2_GAS_LIMIT, daGas: DEFAULT_DA_GAS_LIMIT },
156
+ gasLimits: overrides.gasLimits ?? {
157
+ l2Gas: GAS_ESTIMATION_L2_GAS_LIMIT,
158
+ daGas: GAS_ESTIMATION_DA_GAS_LIMIT,
159
+ },
107
160
  teardownGasLimits: overrides.teardownGasLimits ?? {
108
- l2Gas: DEFAULT_TEARDOWN_L2_GAS_LIMIT,
109
- daGas: DEFAULT_TEARDOWN_DA_GAS_LIMIT,
161
+ l2Gas: GAS_ESTIMATION_TEARDOWN_L2_GAS_LIMIT,
162
+ daGas: GAS_ESTIMATION_TEARDOWN_DA_GAS_LIMIT,
110
163
  },
111
164
  maxFeesPerGas: overrides.maxFeesPerGas,
112
165
  maxPriorityFeesPerGas: overrides.maxPriorityFeesPerGas ?? GasFees.empty(),
package/src/hash/hash.ts CHANGED
@@ -98,6 +98,11 @@ export function computeProtocolNullifier(txRequestHash: Fr): Promise<Fr> {
98
98
  return siloNullifier(AztecAddress.fromBigInt(NULL_MSG_SENDER_CONTRACT_ADDRESS), txRequestHash);
99
99
  }
100
100
 
101
+ /** Domain-separates a raw log tag with the given domain separator. */
102
+ export function computeLogTag(rawTag: number | bigint | boolean | Fr | Buffer, domSep: DomainSeparator): Promise<Fr> {
103
+ return poseidon2HashWithSeparator([new Fr(rawTag)], domSep);
104
+ }
105
+
101
106
  export function computeSiloedPrivateLogFirstField(contract: AztecAddress, field: Fr): Promise<Fr> {
102
107
  return poseidon2HashWithSeparator([contract, field], DomainSeparator.PRIVATE_LOG_FIRST_FIELD);
103
108
  }
@@ -11,7 +11,7 @@ import { L2Block } from '../block/l2_block.js';
11
11
  import { type L2BlockSource, L2TipsSchema } from '../block/l2_block_source.js';
12
12
  import { ValidateCheckpointResultSchema } from '../block/validate_block_result.js';
13
13
  import { Checkpoint } from '../checkpoint/checkpoint.js';
14
- import { CheckpointDataSchema } from '../checkpoint/checkpoint_data.js';
14
+ import { CheckpointDataSchema, ProposedCheckpointDataSchema } from '../checkpoint/checkpoint_data.js';
15
15
  import { PublishedCheckpoint } from '../checkpoint/published_checkpoint.js';
16
16
  import {
17
17
  ContractClassPublicSchema,
@@ -150,6 +150,8 @@ export const ArchiverApiSchema: ApiSchemaFor<ArchiverApi> = {
150
150
  .args()
151
151
  .returns(z.object({ genesisArchiveRoot: schemas.Fr })),
152
152
  getL1Timestamp: z.function().args().returns(schemas.BigInt.optional()),
153
+ getProposedCheckpoint: z.function().args().returns(ProposedCheckpointDataSchema.optional()),
154
+ getProposedCheckpointOnly: z.function().args().returns(ProposedCheckpointDataSchema.optional()),
153
155
  syncImmediate: z.function().args().returns(z.void()),
154
156
  isPendingChainInvalid: z.function().args().returns(z.boolean()),
155
157
  getPendingChainValidationStatus: z.function().args().returns(ValidateCheckpointResultSchema),
@@ -3,7 +3,8 @@ import { createSafeJsonRpcClient, defaultFetch } from '@aztec/foundation/json-rp
3
3
  import { z } from 'zod';
4
4
 
5
5
  import type { ApiSchemaFor } from '../schemas/schemas.js';
6
- import { type Offense, OffenseSchema, type SlashPayloadRound, SlashPayloadRoundSchema } from '../slashing/index.js';
6
+ import { optional } from '../schemas/schemas.js';
7
+ import { type Offense, OffenseSchema } from '../slashing/index.js';
7
8
  import { type ComponentsVersions, getVersioningResponseHandler } from '../versioning/index.js';
8
9
  import { type ArchiverSpecificConfig, ArchiverSpecificConfigSchema } from './archiver.js';
9
10
  import { type SequencerConfig, SequencerConfigSchema } from './configs.js';
@@ -36,8 +37,9 @@ export interface AztecNodeAdmin {
36
37
  * Pauses syncing and rolls back the database to the target L2 block number.
37
38
  * @param targetBlockNumber - The block number to roll back to.
38
39
  * @param force - If true, clears the world state db and p2p dbs if rolling back to behind the finalized block.
40
+ * @param resumeSync - If true (default), resumes archiver and world state sync after rollback.
39
41
  */
40
- rollbackTo(targetBlockNumber: number, force?: boolean): Promise<void>;
42
+ rollbackTo(targetBlockNumber: number, force?: boolean, resumeSync?: boolean): Promise<void>;
41
43
 
42
44
  /** Pauses archiver and world state syncing. */
43
45
  pauseSync(): Promise<void>;
@@ -45,9 +47,6 @@ export interface AztecNodeAdmin {
45
47
  /** Resumes archiver and world state syncing. */
46
48
  resumeSync(): Promise<void>;
47
49
 
48
- /** Returns all monitored payloads by the slasher for the current round. */
49
- getSlashPayloads(): Promise<SlashPayloadRound[]>;
50
-
51
50
  /** Returns all offenses applicable for the given round. */
52
51
  getSlashOffenses(round: bigint | 'all' | 'current'): Promise<Offense[]>;
53
52
 
@@ -100,10 +99,9 @@ export const AztecNodeAdminApiSchema: ApiSchemaFor<AztecNodeAdmin> = {
100
99
  getConfig: z.function().returns(AztecNodeAdminConfigSchema),
101
100
  setConfig: z.function().args(AztecNodeAdminConfigSchema.partial()).returns(z.void()),
102
101
  startSnapshotUpload: z.function().args(z.string()).returns(z.void()),
103
- rollbackTo: z.function().args(z.number()).returns(z.void()),
102
+ rollbackTo: z.function().args(z.number(), optional(z.boolean()), optional(z.boolean())).returns(z.void()),
104
103
  pauseSync: z.function().returns(z.void()),
105
104
  resumeSync: z.function().returns(z.void()),
106
- getSlashPayloads: z.function().returns(z.array(SlashPayloadRoundSchema)),
107
105
  getSlashOffenses: z
108
106
  .function()
109
107
  .args(z.union([z.bigint(), z.literal('all'), z.literal('current')]))
@@ -3,12 +3,8 @@ import { schemas, zodFor } from '@aztec/foundation/schemas';
3
3
 
4
4
  import { z } from 'zod';
5
5
 
6
- export type SlasherClientType = 'empire' | 'tally';
7
-
8
6
  export interface SlasherConfig {
9
7
  slashOverridePayload?: EthAddress;
10
- slashMinPenaltyPercentage: number;
11
- slashMaxPenaltyPercentage: number;
12
8
  slashSelfAllowed?: boolean; // Whether to allow slashes to own validators
13
9
  slashValidatorsAlways: EthAddress[]; // Array of validator addresses
14
10
  slashValidatorsNever: EthAddress[]; // Array of validator addresses
@@ -32,8 +28,6 @@ export interface SlasherConfig {
32
28
  export const SlasherConfigSchema = zodFor<SlasherConfig>()(
33
29
  z.object({
34
30
  slashOverridePayload: schemas.EthAddress.optional(),
35
- slashMinPenaltyPercentage: z.number(),
36
- slashMaxPenaltyPercentage: z.number(),
37
31
  slashValidatorsAlways: z.array(schemas.EthAddress),
38
32
  slashValidatorsNever: z.array(schemas.EthAddress),
39
33
  slashPrunePenalty: schemas.BigInt,
@@ -9,7 +9,6 @@ import type {
9
9
  BlockProposal,
10
10
  BlockProposalOptions,
11
11
  CheckpointAttestation,
12
- CheckpointLastBlockData,
13
12
  CheckpointProposal,
14
13
  CheckpointProposalOptions,
15
14
  } from '@aztec/stdlib/p2p';
@@ -48,10 +47,7 @@ export type ValidatorClientConfig = ValidatorHASignerConfig &
48
47
  /** Interval between polling for new attestations from peers */
49
48
  attestationPollingIntervalMs: number;
50
49
 
51
- /** Whether to re-execute transactions in a block proposal before attesting */
52
- validatorReexecute: boolean;
53
-
54
- /** Whether to always reexecute block proposals, even for non-validator nodes or when out of the currnet committee */
50
+ /** Whether to always reexecute block proposals, even for non-validator nodes or when out of the current committee */
55
51
  alwaysReexecuteBlockProposals?: boolean;
56
52
 
57
53
  /** Whether to run in fisherman mode: validates all proposals and attestations but does not broadcast attestations or participate in consensus */
@@ -98,7 +94,6 @@ export const ValidatorClientConfigSchema = zodFor<Omit<ValidatorClientConfig, 'v
98
94
  disableValidator: z.boolean(),
99
95
  disabledValidators: z.array(schemas.EthAddress),
100
96
  attestationPollingIntervalMs: z.number().min(0),
101
- validatorReexecute: z.boolean(),
102
97
  alwaysReexecuteBlockProposals: z.boolean().optional(),
103
98
  fishermanMode: z.boolean().optional(),
104
99
  skipCheckpointProposalValidation: z.boolean().optional(),
@@ -122,8 +117,6 @@ export const ValidatorClientFullConfigSchema = zodFor<Omit<ValidatorClientFullCo
122
117
  }),
123
118
  );
124
119
 
125
- export type CreateCheckpointProposalLastBlockData = Omit<CheckpointLastBlockData, 'txHashes'> & { txs: Tx[] };
126
-
127
120
  export interface Validator {
128
121
  start(): Promise<void>;
129
122
  updateConfig(config: Partial<ValidatorClientFullConfig>): void;
@@ -144,7 +137,7 @@ export interface Validator {
144
137
  checkpointHeader: CheckpointHeader,
145
138
  archive: Fr,
146
139
  feeAssetPriceModifier: bigint,
147
- lastBlockInfo: CreateCheckpointProposalLastBlockData | undefined,
140
+ lastBlockProposal: BlockProposal | undefined,
148
141
  proposerAddress: EthAddress | undefined,
149
142
  options: CheckpointProposalOptions,
150
143
  ): Promise<CheckpointProposal>;
@@ -1 +1 @@
1
- export * from './slash_factory.js';
1
+ // No exports.
@@ -23,14 +23,14 @@ import { computeAddressSecret, computePreaddress } from '../keys/derivation.js';
23
23
  * doesn't seem to be a good way around this.
24
24
  */
25
25
  export class ExtendedDirectionalAppTaggingSecret {
26
- private constructor(
26
+ constructor(
27
27
  public readonly secret: Fr,
28
28
  public readonly app: AztecAddress,
29
29
  ) {}
30
30
 
31
31
  /**
32
32
  * Derives shared tagging secret and from that, the app address and recipient derives the directional app tagging
33
- * secret.
33
+ * secret. Returns undefined if `externalAddress` is an invalid address.
34
34
  *
35
35
  * @param localAddress - The complete address of entity A in the shared tagging secret derivation scheme
36
36
  * @param localIvsk - The incoming viewing secret key of entity A
@@ -45,8 +45,12 @@ export class ExtendedDirectionalAppTaggingSecret {
45
45
  externalAddress: AztecAddress,
46
46
  app: AztecAddress,
47
47
  recipient: AztecAddress,
48
- ): Promise<ExtendedDirectionalAppTaggingSecret> {
48
+ ): Promise<ExtendedDirectionalAppTaggingSecret | undefined> {
49
49
  const taggingSecretPoint = await computeSharedTaggingSecret(localAddress, localIvsk, externalAddress);
50
+ if (!taggingSecretPoint) {
51
+ return undefined;
52
+ }
53
+
50
54
  const appTaggingSecret = await poseidon2Hash([taggingSecretPoint.x, taggingSecretPoint.y, app]);
51
55
  const directionalAppTaggingSecret = await poseidon2Hash([appTaggingSecret, recipient]);
52
56
 
@@ -63,18 +67,25 @@ export class ExtendedDirectionalAppTaggingSecret {
63
67
  }
64
68
  }
65
69
 
66
- // Returns shared tagging secret computed with Diffie-Hellman key exchange.
70
+ // Returns shared tagging secret computed with Diffie-Hellman key exchange, or undefined if `externalAddress` is an
71
+ // invalid address.
67
72
  async function computeSharedTaggingSecret(
68
73
  localAddress: CompleteAddress,
69
74
  localIvsk: Fq,
70
75
  externalAddress: AztecAddress,
71
- ): Promise<Point> {
72
- const knownPreaddress = await computePreaddress(await localAddress.publicKeys.hash(), localAddress.partialAddress);
73
- // TODO: #8970 - Computation of address point from x coordinate might fail
74
- const externalAddressPoint = await externalAddress.toAddressPoint();
76
+ ): Promise<Point | undefined> {
75
77
  // Given A (local complete address) -> B (external address) and h == preaddress
76
78
  // Compute shared secret as S = (h_A + local_ivsk_A) * Addr_Point_B
77
79
 
80
+ const knownPreaddress = await computePreaddress(await localAddress.publicKeys.hash(), localAddress.partialAddress);
81
+
82
+ // An invalid address has no corresponding address point
83
+ if (!(await externalAddress.isValid())) {
84
+ return undefined;
85
+ }
86
+
87
+ const externalAddressPoint = await externalAddress.toAddressPoint();
88
+
78
89
  // Beware! h_a + local_ivsk_a (also known as the address secret) can lead to an address point with a negative
79
90
  // y-coordinate, since there's two possible candidates computeAddressSecret takes care of selecting the one that
80
91
  // leads to a positive y-coordinate, which is the only valid address point
@@ -1,8 +1,7 @@
1
1
  import { MAX_NOTE_HASHES_PER_TX } from '@aztec/constants';
2
+ import { range } from '@aztec/foundation/array';
2
3
  import { Fr } from '@aztec/foundation/curves/bn254';
3
4
 
4
- import type { AztecAddress } from '../aztec-address/index.js';
5
- import type { TxEffect } from '../tx/tx_effect.js';
6
5
  import type { TxHash } from '../tx/tx_hash.js';
7
6
 
8
7
  /**
@@ -19,7 +18,6 @@ export class MessageContext {
19
18
  public txHash: TxHash,
20
19
  public uniqueNoteHashesInTx: Fr[],
21
20
  public firstNullifierInTx: Fr,
22
- public recipient: AztecAddress,
23
21
  ) {}
24
22
 
25
23
  toFields(): Fr[] {
@@ -27,7 +25,6 @@ export class MessageContext {
27
25
  this.txHash.hash,
28
26
  ...serializeBoundedVec(this.uniqueNoteHashesInTx, MAX_NOTE_HASHES_PER_TX),
29
27
  this.firstNullifierInTx,
30
- this.recipient.toField(),
31
28
  ];
32
29
  }
33
30
 
@@ -37,13 +34,22 @@ export class MessageContext {
37
34
  tx_hash: this.txHash.hash,
38
35
  unique_note_hashes_in_tx: this.uniqueNoteHashesInTx,
39
36
  first_nullifier_in_tx: this.firstNullifierInTx,
40
- recipient: this.recipient,
41
37
  };
42
38
  /* eslint-enable camelcase */
43
39
  }
44
40
 
45
- static fromTxEffectAndRecipient(txEffect: TxEffect, recipient: AztecAddress): MessageContext {
46
- return new MessageContext(txEffect.txHash, txEffect.noteHashes, txEffect.nullifiers[0], recipient);
41
+ static toEmptyFields(): Fr[] {
42
+ const serializationLen =
43
+ 1 /* txHash */ + MAX_NOTE_HASHES_PER_TX + 1 /* uniqueNoteHashesInTx BVec */ + 1; /* firstNullifierInTx */
44
+ return range(serializationLen).map(_ => Fr.zero());
45
+ }
46
+
47
+ static toSerializedOption(response: MessageContext | null): Fr[] {
48
+ if (response) {
49
+ return [new Fr(1), ...response.toFields()];
50
+ } else {
51
+ return [new Fr(0), ...MessageContext.toEmptyFields()];
52
+ }
47
53
  }
48
54
  }
49
55
 
@@ -55,6 +61,10 @@ export class MessageContext {
55
61
  * @dev Copied over from pending_tagged_log.ts.
56
62
  */
57
63
  function serializeBoundedVec(values: Fr[], maxLength: number): Fr[] {
64
+ if (values.length > maxLength) {
65
+ throw new Error(`Attempted to serialize ${values} values into a BoundedVec with max length ${maxLength}`);
66
+ }
67
+
58
68
  const lengthDiff = maxLength - values.length;
59
69
  const zeroPaddingArray = Array(lengthDiff).fill(Fr.ZERO);
60
70
  const storage = values.concat(zeroPaddingArray);
@@ -1,7 +1,6 @@
1
1
  import { PRIVATE_LOG_SIZE_IN_FIELDS } from '@aztec/constants';
2
2
  import { Fr } from '@aztec/foundation/curves/bn254';
3
3
 
4
- import type { AztecAddress } from '../aztec-address/index.js';
5
4
  import type { TxHash } from '../tx/tx_hash.js';
6
5
  import { MessageContext } from './message_context.js';
7
6
 
@@ -17,9 +16,8 @@ export class PendingTaggedLog {
17
16
  txHash: TxHash,
18
17
  uniqueNoteHashesInTx: Fr[],
19
18
  firstNullifierInTx: Fr,
20
- recipient: AztecAddress,
21
19
  ) {
22
- this.context = new MessageContext(txHash, uniqueNoteHashesInTx, firstNullifierInTx, recipient);
20
+ this.context = new MessageContext(txHash, uniqueNoteHashesInTx, firstNullifierInTx);
23
21
  }
24
22
 
25
23
  toFields(): Fr[] {
@@ -1,26 +1,37 @@
1
+ import { DomainSeparator } from '@aztec/constants';
1
2
  import { Grumpkin } from '@aztec/foundation/crypto/grumpkin';
2
- import type { GrumpkinScalar, Point } from '@aztec/foundation/curves/grumpkin';
3
+ import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto/poseidon';
4
+ import type { Fr } from '@aztec/foundation/curves/bn254';
5
+ import type { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
3
6
 
7
+ import type { AztecAddress } from '../aztec-address/index.js';
4
8
  import type { PublicKey } from '../keys/public_key.js';
5
9
 
6
10
  /**
7
- * Derive an Elliptic Curve Diffie-Hellman (ECDH) Shared Secret.
8
- * The function takes in an ECDH public key, a private key, and a Grumpkin instance to compute
9
- * the shared secret.
11
+ * Derives an app-siloed ECDH shared secret.
12
+ *
13
+ * Computes the raw ECDH shared secret `S = secretKey * publicKey`, then app-silos it:
14
+ * `s_app = h(DOM_SEP__APP_SILOED_ECDH_SHARED_SECRET, S.x, S.y, contractAddress)`
10
15
  *
11
16
  * @param secretKey - The secret key used to derive shared secret.
12
17
  * @param publicKey - The public key used to derive shared secret.
13
- * @returns A derived shared secret.
18
+ * @param contractAddress - The address of the calling contract, used for app-siloing.
19
+ * @returns The app-siloed shared secret as a Field.
14
20
  * @throws If the publicKey is zero.
15
- *
16
- * TODO(#12656): This function is kept around because of the utilityGetSharedSecret oracle. Nuke this once returning
17
- * the app-siloed secret.
18
21
  */
19
- export function deriveEcdhSharedSecret(secretKey: GrumpkinScalar, publicKey: PublicKey): Promise<Point> {
22
+ export async function deriveAppSiloedSharedSecret(
23
+ secretKey: GrumpkinScalar,
24
+ publicKey: PublicKey,
25
+ contractAddress: AztecAddress,
26
+ ): Promise<Fr> {
20
27
  if (publicKey.isZero()) {
21
28
  throw new Error(
22
29
  `Attempting to derive a shared secret with a zero public key. You have probably passed a zero public key in your Noir code somewhere thinking that the note won't be broadcast... but it was.`,
23
30
  );
24
31
  }
25
- return Grumpkin.mul(publicKey, secretKey);
32
+ const rawSharedSecret = await Grumpkin.mul(publicKey, secretKey);
33
+ return poseidon2HashWithSeparator(
34
+ [rawSharedSecret.x, rawSharedSecret.y, contractAddress],
35
+ DomainSeparator.APP_SILOED_ECDH_SHARED_SECRET,
36
+ );
26
37
  }
@@ -1,8 +1,9 @@
1
+ import { DomainSeparator } from '@aztec/constants';
1
2
  import type { Fr } from '@aztec/foundation/curves/bn254';
2
3
  import type { ZodFor } from '@aztec/foundation/schemas';
3
4
 
4
5
  import type { AztecAddress } from '../aztec-address/index.js';
5
- import { computeSiloedPrivateLogFirstField } from '../hash/hash.js';
6
+ import { computeLogTag, computeSiloedPrivateLogFirstField } from '../hash/hash.js';
6
7
  import { schemas } from '../schemas/schemas.js';
7
8
  import type { PreTag } from './pre_tag.js';
8
9
  import { Tag } from './tag.js';
@@ -24,9 +25,13 @@ export class SiloedTag {
24
25
 
25
26
  static async compute(preTag: PreTag): Promise<SiloedTag> {
26
27
  const tag = await Tag.compute(preTag);
27
- return SiloedTag.computeFromTagAndApp(tag, preTag.extendedSecret.app);
28
+ const logTag = await computeLogTag(tag.value, DomainSeparator.UNCONSTRAINED_MSG_LOG_TAG);
29
+ return SiloedTag.computeFromTagAndApp(new Tag(logTag), preTag.extendedSecret.app);
28
30
  }
29
31
 
32
+ /**
33
+ * Unlike `compute`, this expects a tag whose value is already domain-separated.
34
+ */
30
35
  static async computeFromTagAndApp(tag: Tag, app: AztecAddress): Promise<SiloedTag> {
31
36
  const siloedTag = await computeSiloedPrivateLogFirstField(app, tag.value);
32
37
  return new SiloedTag(siloedTag);