@aztec/stdlib 3.0.0-nightly.20251005 → 3.0.0-nightly.20251008

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 (110) hide show
  1. package/dest/avm/avm.d.ts +62 -78
  2. package/dest/avm/avm.d.ts.map +1 -1
  3. package/dest/avm/avm.js +8 -22
  4. package/dest/avm/avm_circuit_public_inputs.d.ts +19 -6
  5. package/dest/avm/avm_circuit_public_inputs.d.ts.map +1 -1
  6. package/dest/avm/avm_circuit_public_inputs.js +12 -11
  7. package/dest/avm/avm_proving_request.d.ts +49 -40
  8. package/dest/avm/avm_proving_request.d.ts.map +1 -1
  9. package/dest/file-store/interface.d.ts +8 -2
  10. package/dest/file-store/interface.d.ts.map +1 -1
  11. package/dest/file-store/s3.d.ts +1 -0
  12. package/dest/file-store/s3.d.ts.map +1 -1
  13. package/dest/file-store/s3.js +81 -16
  14. package/dest/interfaces/aztec-node-admin.d.ts +3 -0
  15. package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
  16. package/dest/interfaces/configs.d.ts +5 -0
  17. package/dest/interfaces/configs.d.ts.map +1 -1
  18. package/dest/interfaces/configs.js +2 -1
  19. package/dest/interfaces/proving-job.d.ts +49 -40
  20. package/dest/interfaces/proving-job.d.ts.map +1 -1
  21. package/dest/interfaces/validator.d.ts +1 -1
  22. package/dest/interfaces/validator.d.ts.map +1 -1
  23. package/dest/kernel/hints/build_nullifier_read_request_hints.d.ts +3 -2
  24. package/dest/kernel/hints/build_nullifier_read_request_hints.d.ts.map +1 -1
  25. package/dest/kernel/hints/nullifier_read_request_hints.d.ts +4 -3
  26. package/dest/kernel/hints/nullifier_read_request_hints.d.ts.map +1 -1
  27. package/dest/kernel/private_call_data.d.ts +4 -24
  28. package/dest/kernel/private_call_data.d.ts.map +1 -1
  29. package/dest/kernel/private_call_data.js +4 -16
  30. package/dest/kernel/private_kernel_circuit_public_inputs.d.ts +3 -3
  31. package/dest/kernel/private_kernel_circuit_public_inputs.d.ts.map +1 -1
  32. package/dest/kernel/private_kernel_circuit_public_inputs.js +3 -3
  33. package/dest/kernel/private_kernel_init_circuit_private_inputs.d.ts +5 -4
  34. package/dest/kernel/private_kernel_init_circuit_private_inputs.d.ts.map +1 -1
  35. package/dest/kernel/private_kernel_init_circuit_private_inputs.js +7 -6
  36. package/dest/kernel/private_kernel_tail_circuit_public_inputs.js +1 -1
  37. package/dest/p2p/block_proposal.d.ts +2 -0
  38. package/dest/p2p/block_proposal.d.ts.map +1 -1
  39. package/dest/rollup/block_constant_data.d.ts +4 -4
  40. package/dest/rollup/block_constant_data.d.ts.map +1 -1
  41. package/dest/rollup/block_constant_data.js +4 -4
  42. package/dest/rollup/checkpoint_constant_data.d.ts +4 -4
  43. package/dest/rollup/checkpoint_constant_data.d.ts.map +1 -1
  44. package/dest/rollup/checkpoint_constant_data.js +4 -4
  45. package/dest/rollup/epoch_constant_data.d.ts +4 -4
  46. package/dest/rollup/epoch_constant_data.d.ts.map +1 -1
  47. package/dest/rollup/epoch_constant_data.js +5 -5
  48. package/dest/snapshots/download.d.ts.map +1 -1
  49. package/dest/snapshots/download.js +58 -2
  50. package/dest/snapshots/upload.d.ts.map +1 -1
  51. package/dest/snapshots/upload.js +1 -0
  52. package/dest/tests/factories.d.ts +5 -4
  53. package/dest/tests/factories.d.ts.map +1 -1
  54. package/dest/tests/factories.js +11 -10
  55. package/dest/tests/mocks.d.ts +2 -2
  56. package/dest/tests/mocks.d.ts.map +1 -1
  57. package/dest/tests/mocks.js +2 -2
  58. package/dest/trees/index.d.ts +0 -1
  59. package/dest/trees/index.d.ts.map +1 -1
  60. package/dest/trees/index.js +0 -1
  61. package/dest/tx/index.d.ts +2 -0
  62. package/dest/tx/index.d.ts.map +1 -1
  63. package/dest/tx/index.js +2 -0
  64. package/dest/tx/private_tx_constant_data.d.ts +60 -0
  65. package/dest/tx/private_tx_constant_data.d.ts.map +1 -0
  66. package/dest/tx/private_tx_constant_data.js +69 -0
  67. package/dest/tx/protocol_contracts.d.ts +29 -0
  68. package/dest/tx/protocol_contracts.d.ts.map +1 -0
  69. package/dest/tx/protocol_contracts.js +49 -0
  70. package/dest/tx/tx_constant_data.d.ts +5 -37
  71. package/dest/tx/tx_constant_data.d.ts.map +1 -1
  72. package/dest/tx/tx_constant_data.js +8 -17
  73. package/dest/tx/validator/error_texts.d.ts +1 -1
  74. package/dest/tx/validator/error_texts.d.ts.map +1 -1
  75. package/dest/tx/validator/error_texts.js +1 -1
  76. package/dest/versioning/versioning.d.ts +2 -2
  77. package/dest/versioning/versioning.d.ts.map +1 -1
  78. package/dest/versioning/versioning.js +8 -8
  79. package/package.json +8 -8
  80. package/src/avm/avm.ts +13 -24
  81. package/src/avm/avm_circuit_public_inputs.ts +11 -10
  82. package/src/file-store/interface.ts +8 -2
  83. package/src/file-store/s3.ts +83 -15
  84. package/src/interfaces/configs.ts +3 -0
  85. package/src/interfaces/validator.ts +1 -1
  86. package/src/kernel/hints/build_nullifier_read_request_hints.ts +3 -2
  87. package/src/kernel/hints/nullifier_read_request_hints.ts +3 -3
  88. package/src/kernel/private_call_data.ts +2 -21
  89. package/src/kernel/private_kernel_circuit_public_inputs.ts +4 -4
  90. package/src/kernel/private_kernel_init_circuit_private_inputs.ts +5 -4
  91. package/src/kernel/private_kernel_tail_circuit_public_inputs.ts +1 -1
  92. package/src/p2p/block_proposal.ts +2 -0
  93. package/src/rollup/block_constant_data.ts +3 -3
  94. package/src/rollup/checkpoint_constant_data.ts +3 -3
  95. package/src/rollup/epoch_constant_data.ts +3 -9
  96. package/src/snapshots/download.ts +66 -2
  97. package/src/snapshots/upload.ts +1 -0
  98. package/src/tests/factories.ts +12 -19
  99. package/src/tests/mocks.ts +3 -3
  100. package/src/trees/index.ts +0 -1
  101. package/src/tx/index.ts +2 -0
  102. package/src/tx/private_tx_constant_data.ts +94 -0
  103. package/src/tx/protocol_contracts.ts +70 -0
  104. package/src/tx/tx_constant_data.ts +6 -19
  105. package/src/tx/validator/error_texts.ts +1 -1
  106. package/src/versioning/versioning.ts +10 -10
  107. package/dest/trees/protocol_contract_leaf.d.ts +0 -84
  108. package/dest/trees/protocol_contract_leaf.d.ts.map +0 -1
  109. package/dest/trees/protocol_contract_leaf.js +0 -100
  110. package/src/trees/protocol_contract_leaf.ts +0 -128
@@ -16,6 +16,7 @@ import {
16
16
  } from '../kernel/private_to_avm_accumulated_data.js';
17
17
  import { PublicCallRequest, PublicCallRequestArrayLengths } from '../kernel/public_call_request.js';
18
18
  import { GlobalVariables } from '../tx/global_variables.js';
19
+ import { ProtocolContracts } from '../tx/protocol_contracts.js';
19
20
  import { TreeSnapshots } from '../tx/tree_snapshots.js';
20
21
  import { AvmAccumulatedData, AvmAccumulatedDataArrayLengths } from './avm_accumulated_data.js';
21
22
  import { serializeWithMessagePack } from './message_pack.js';
@@ -27,7 +28,7 @@ export class AvmCircuitPublicInputs {
27
28
  ///////////////////////////////////
28
29
  // Inputs.
29
30
  public globalVariables: GlobalVariables,
30
- public protocolContractTreeRoot: Fr,
31
+ public protocolContracts: ProtocolContracts,
31
32
  public startTreeSnapshots: TreeSnapshots,
32
33
  public startGasUsed: Gas,
33
34
  public gasSettings: GasSettings,
@@ -56,7 +57,7 @@ export class AvmCircuitPublicInputs {
56
57
  return z
57
58
  .object({
58
59
  globalVariables: GlobalVariables.schema,
59
- protocolContractTreeRoot: schemas.Fr,
60
+ protocolContracts: ProtocolContracts.schema,
60
61
  startTreeSnapshots: TreeSnapshots.schema,
61
62
  startGasUsed: Gas.schema,
62
63
  gasSettings: GasSettings.schema,
@@ -81,7 +82,7 @@ export class AvmCircuitPublicInputs {
81
82
  .transform(
82
83
  ({
83
84
  globalVariables,
84
- protocolContractTreeRoot,
85
+ protocolContracts,
85
86
  startTreeSnapshots,
86
87
  startGasUsed,
87
88
  gasSettings,
@@ -105,7 +106,7 @@ export class AvmCircuitPublicInputs {
105
106
  }) =>
106
107
  new AvmCircuitPublicInputs(
107
108
  globalVariables,
108
- protocolContractTreeRoot,
109
+ protocolContracts,
109
110
  startTreeSnapshots,
110
111
  startGasUsed,
111
112
  gasSettings,
@@ -134,7 +135,7 @@ export class AvmCircuitPublicInputs {
134
135
  const reader = BufferReader.asReader(buffer);
135
136
  return new AvmCircuitPublicInputs(
136
137
  reader.readObject(GlobalVariables),
137
- reader.readObject(Fr),
138
+ reader.readObject(ProtocolContracts),
138
139
  reader.readObject(TreeSnapshots),
139
140
  reader.readObject(Gas),
140
141
  reader.readObject(GasSettings),
@@ -161,7 +162,7 @@ export class AvmCircuitPublicInputs {
161
162
  toBuffer() {
162
163
  return serializeToBuffer(
163
164
  this.globalVariables,
164
- this.protocolContractTreeRoot,
165
+ this.protocolContracts,
165
166
  this.startTreeSnapshots,
166
167
  this.startGasUsed,
167
168
  this.gasSettings,
@@ -197,7 +198,7 @@ export class AvmCircuitPublicInputs {
197
198
  const reader = FieldReader.asReader(fields);
198
199
  return new AvmCircuitPublicInputs(
199
200
  GlobalVariables.fromFields(reader),
200
- reader.readField(),
201
+ ProtocolContracts.fromFields(reader),
201
202
  TreeSnapshots.fromFields(reader),
202
203
  Gas.fromFields(reader),
203
204
  GasSettings.fromFields(reader),
@@ -224,7 +225,7 @@ export class AvmCircuitPublicInputs {
224
225
  toFields() {
225
226
  return [
226
227
  ...this.globalVariables.toFields(),
227
- this.protocolContractTreeRoot,
228
+ ...this.protocolContracts.toFields(),
228
229
  ...this.startTreeSnapshots.toFields(),
229
230
  ...this.startGasUsed.toFields(),
230
231
  ...this.gasSettings.toFields(),
@@ -251,7 +252,7 @@ export class AvmCircuitPublicInputs {
251
252
  static empty() {
252
253
  return new AvmCircuitPublicInputs(
253
254
  GlobalVariables.empty(),
254
- Fr.zero(),
255
+ ProtocolContracts.empty(),
255
256
  TreeSnapshots.empty(),
256
257
  Gas.empty(),
257
258
  GasSettings.empty(),
@@ -282,7 +283,7 @@ export class AvmCircuitPublicInputs {
282
283
  [inspect.custom]() {
283
284
  return `AvmCircuitPublicInputs {
284
285
  globalVariables: ${inspect(this.globalVariables)},
285
- protocolContractTreeRoot: ${inspect(this.protocolContractTreeRoot)},
286
+ protocolContracts: ${inspect(this.protocolContracts)},
286
287
  startTreeSnapshots: ${inspect(this.startTreeSnapshots)},
287
288
  startGasUsed: ${inspect(this.startGasUsed)},
288
289
  gasSettings: ${inspect(this.gasSettings)},
@@ -12,8 +12,14 @@ export type FileStoreSaveOptions = { public?: boolean; metadata?: Record<string,
12
12
 
13
13
  /** Simple file store. */
14
14
  export interface FileStore extends ReadOnlyFileStore {
15
- /** Saves contents to the given path. Returns an URI that can be used later to `read` the file. */
15
+ /**
16
+ * Saves contents to the given path. Returns an URI that can be used later to `read` the file.
17
+ * Default: `compress` is false unless explicitly set.
18
+ */
16
19
  save(path: string, data: Buffer, opts?: FileStoreSaveOptions): Promise<string>;
17
- /** Uploads contents from a local file. Returns an URI that can be used later to `read` the file. */
20
+ /**
21
+ * Uploads contents from a local file. Returns an URI that can be used later to `read` the file.
22
+ * Default: `compress` is true unless explicitly set to false.
23
+ */
18
24
  upload(destPath: string, srcPath: string, opts?: FileStoreSaveOptions): Promise<string>;
19
25
  }
@@ -8,8 +8,9 @@ import {
8
8
  S3Client,
9
9
  } from '@aws-sdk/client-s3';
10
10
  import { createReadStream, createWriteStream } from 'fs';
11
- import { mkdir } from 'fs/promises';
12
- import { dirname, join } from 'path';
11
+ import { mkdir, mkdtemp, stat, unlink } from 'fs/promises';
12
+ import { tmpdir } from 'os';
13
+ import { basename, dirname, join } from 'path';
13
14
  import { Readable } from 'stream';
14
15
  import { finished } from 'stream/promises';
15
16
  import { createGzip } from 'zlib';
@@ -49,15 +50,19 @@ export class S3FileStore implements FileStore {
49
50
 
50
51
  public async save(path: string, data: Buffer, opts: FileStoreSaveOptions = {}): Promise<string> {
51
52
  const key = this.getFullPath(path);
52
- const shouldCompress = !opts.compress;
53
+ const shouldCompress = !!opts.compress;
54
+
53
55
  const body = shouldCompress ? (await import('zlib')).gzipSync(data) : data;
56
+ const contentLength = body.length;
57
+ const contentType = this.detectContentType(key, shouldCompress);
54
58
  const put = new PutObjectCommand({
55
59
  Bucket: this.bucketName,
56
60
  Key: key,
57
61
  Body: body,
58
- ContentEncoding: shouldCompress ? 'gzip' : undefined,
62
+ ContentType: contentType,
59
63
  CacheControl: opts.metadata?.['Cache-control'],
60
64
  Metadata: this.extractUserMetadata(opts.metadata),
65
+ ContentLength: contentLength,
61
66
  });
62
67
  await this.s3.send(put);
63
68
  return this.buildReturnedUrl(key, !!opts.public);
@@ -68,18 +73,59 @@ export class S3FileStore implements FileStore {
68
73
  const shouldCompress = opts.compress !== false; // default true like GCS impl
69
74
 
70
75
  await mkdir(dirname(srcPath), { recursive: true }).catch(() => undefined);
76
+ let contentLength: number | undefined;
77
+ let bodyPath = srcPath;
78
+
79
+ // We don't set Content-Encoding and we avoid SigV4 streaming (aws-chunked).
80
+ // With AWS SigV4 streaming uploads (Content-Encoding: aws-chunked[,gzip]), servers require
81
+ // x-amz-decoded-content-length (the size of the decoded payload) and an exact Content-Length
82
+ // that includes chunk metadata. For on-the-fly compression, providing
83
+ // those values without buffering or a pre-pass is impractical. Instead, we pre-gzip to a temp file
84
+ // to know ContentLength up-front and upload the gzipped bytes as-is, omitting Content-Encoding.
85
+ // Reference: AWS SigV4 streaming (chunked upload) requirements —
86
+ // https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html
87
+ if (shouldCompress) {
88
+ // Pre-gzip to a temp file so we know the exact length for R2/S3 headers
89
+ const tmpDir = await mkdtemp(join(tmpdir(), 's3-upload-'));
90
+ const gzPath = join(tmpDir, `${basename(srcPath)}.gz`);
91
+ const source = createReadStream(srcPath);
92
+ const gz = createGzip();
93
+ const out = createWriteStream(gzPath);
94
+ try {
95
+ await finished(source.pipe(gz).pipe(out));
96
+ const st = await stat(gzPath);
97
+ contentLength = st.size;
98
+ bodyPath = gzPath;
99
+ } catch (err) {
100
+ // Ensure temp file is removed on failure
101
+ await unlink(gzPath).catch(() => undefined);
102
+ throw err;
103
+ }
104
+ } else {
105
+ const st = await stat(srcPath);
106
+ contentLength = st.size;
107
+ bodyPath = srcPath;
108
+ }
71
109
 
72
- const source = createReadStream(srcPath);
73
- const bodyStream = shouldCompress ? source.pipe(createGzip()) : source;
74
- const put = new PutObjectCommand({
75
- Bucket: this.bucketName,
76
- Key: key,
77
- Body: bodyStream as any,
78
- ContentEncoding: shouldCompress ? 'gzip' : undefined,
79
- CacheControl: opts.metadata?.['Cache-control'],
80
- Metadata: this.extractUserMetadata(opts.metadata),
81
- });
82
- await this.s3.send(put);
110
+ const bodyStream = createReadStream(bodyPath);
111
+ const contentType = this.detectContentType(key, shouldCompress);
112
+ try {
113
+ const put = new PutObjectCommand({
114
+ Bucket: this.bucketName,
115
+ Key: key,
116
+ Body: bodyStream as any,
117
+ ContentType: contentType,
118
+ CacheControl: opts.metadata?.['Cache-control'],
119
+ Metadata: this.extractUserMetadata(opts.metadata),
120
+ // Explicitly set ContentLength so R2 can compute x-amz-decoded-content-length correctly
121
+ ContentLength: contentLength,
122
+ } as any);
123
+ await this.s3.send(put);
124
+ } finally {
125
+ if (shouldCompress && bodyPath !== srcPath) {
126
+ await unlink(bodyPath).catch(() => undefined);
127
+ }
128
+ }
83
129
  return this.buildReturnedUrl(key, !!opts.public);
84
130
  }
85
131
 
@@ -125,6 +171,28 @@ export class S3FileStore implements FileStore {
125
171
  return Object.keys(rest).length ? rest : undefined;
126
172
  }
127
173
 
174
+ private detectContentType(key: string, isCompressed: boolean | undefined): string | undefined {
175
+ // Basic content type inference
176
+ const lower = key.toLowerCase();
177
+ if (lower.endsWith('.json') || lower.endsWith('.json.gz')) {
178
+ return 'application/json';
179
+ }
180
+ if (lower.endsWith('.txt') || lower.endsWith('.log') || lower.endsWith('.csv') || lower.endsWith('.md')) {
181
+ return 'text/plain; charset=utf-8';
182
+ }
183
+ if (lower.endsWith('.db') || lower.endsWith('.sqlite') || lower.endsWith('.bin')) {
184
+ return 'application/octet-stream';
185
+ }
186
+ if (lower.endsWith('.wasm') || lower.endsWith('.wasm.gz')) {
187
+ return 'application/wasm';
188
+ }
189
+ // If compressed, prefer octet-stream unless known
190
+ if (isCompressed) {
191
+ return 'application/octet-stream';
192
+ }
193
+ return undefined;
194
+ }
195
+
128
196
  private buildReturnedUrl(key: string, makePublic: boolean): string {
129
197
  if (!makePublic) {
130
198
  return `s3://${this.bucketName}/${key}`;
@@ -52,6 +52,8 @@ export interface SequencerConfig {
52
52
  skipCollectingAttestations?: boolean;
53
53
  /** Do not invalidate the previous block if invalid when we are the proposer (for testing only) */
54
54
  skipInvalidateBlockAsProposer?: boolean;
55
+ /** Broadcast invalid block proposals with corrupted state (for testing only) */
56
+ broadcastInvalidBlockProposal?: boolean;
55
57
  }
56
58
 
57
59
  export const SequencerConfigSchema = z.object({
@@ -75,4 +77,5 @@ export const SequencerConfigSchema = z.object({
75
77
  skipCollectingAttestations: z.boolean().optional(),
76
78
  secondsBeforeInvalidatingBlockAsCommitteeMember: z.number(),
77
79
  secondsBeforeInvalidatingBlockAsNonCommitteeMember: z.number(),
80
+ broadcastInvalidBlockProposal: z.boolean().optional(),
78
81
  }) satisfies ZodFor<SequencerConfig>;
@@ -43,7 +43,7 @@ export interface ValidatorClientConfig {
43
43
  }
44
44
 
45
45
  export type ValidatorClientFullConfig = ValidatorClientConfig &
46
- Pick<SequencerConfig, 'txPublicSetupAllowList'> &
46
+ Pick<SequencerConfig, 'txPublicSetupAllowList' | 'broadcastInvalidBlockProposal'> &
47
47
  Pick<SlasherConfig, 'slashBroadcastedInvalidBlockPenalty'>;
48
48
 
49
49
  export const ValidatorClientConfigSchema = z.object({
@@ -4,9 +4,10 @@ import {
4
4
  type NULLIFIER_TREE_HEIGHT,
5
5
  } from '@aztec/constants';
6
6
  import type { Fr } from '@aztec/foundation/fields';
7
- import { type IndexedTreeLeafPreimage, MembershipWitness } from '@aztec/foundation/trees';
7
+ import { MembershipWitness } from '@aztec/foundation/trees';
8
8
 
9
9
  import { siloNullifier } from '../../hash/hash.js';
10
+ import type { NullifierLeafPreimage } from '../../trees/nullifier_leaf.js';
10
11
  import type { ClaimedLengthArray } from '../claimed_length_array.js';
11
12
  import type { ScopedNullifier } from '../nullifier.js';
12
13
  import { NullifierReadRequestHintsBuilder } from './nullifier_read_request_hints.js';
@@ -24,7 +25,7 @@ export function isValidNullifierReadRequest(readRequest: ScopedReadRequest, null
24
25
 
25
26
  interface NullifierMembershipWitnessWithPreimage {
26
27
  membershipWitness: MembershipWitness<typeof NULLIFIER_TREE_HEIGHT>;
27
- leafPreimage: IndexedTreeLeafPreimage;
28
+ leafPreimage: NullifierLeafPreimage;
28
29
  }
29
30
 
30
31
  export function getNullifierReadRequestResetActions(
@@ -1,7 +1,7 @@
1
1
  import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT } from '@aztec/constants';
2
2
  import { makeTuple } from '@aztec/foundation/array';
3
3
  import type { BufferReader } from '@aztec/foundation/serialize';
4
- import type { MembershipWitness, TreeLeafPreimage } from '@aztec/foundation/trees';
4
+ import type { MembershipWitness } from '@aztec/foundation/trees';
5
5
 
6
6
  import { NullifierLeafPreimage } from '../../trees/index.js';
7
7
  import { PendingReadHint, ReadRequestAction, ReadRequestResetHints, SettledReadHint } from './read_request_hints.js';
@@ -11,7 +11,7 @@ export type NullifierReadRequestHints<PENDING extends number, SETTLED extends nu
11
11
  PENDING,
12
12
  SETTLED,
13
13
  typeof NULLIFIER_TREE_HEIGHT,
14
- TreeLeafPreimage
14
+ NullifierLeafPreimage
15
15
  >;
16
16
 
17
17
  export function nullifierReadRequestHintsFromBuffer<PENDING extends number, SETTLED extends number>(
@@ -64,7 +64,7 @@ export class NullifierReadRequestHintsBuilder<PENDING extends number, SETTLED ex
64
64
  addSettledReadRequest(
65
65
  readRequestIndex: number,
66
66
  membershipWitness: MembershipWitness<typeof NULLIFIER_TREE_HEIGHT>,
67
- leafPreimage: TreeLeafPreimage,
67
+ leafPreimage: NullifierLeafPreimage,
68
68
  ) {
69
69
  if (this.numSettledReadHints === this.maxSettled) {
70
70
  throw new Error('Cannot add more settled read request.');
@@ -1,9 +1,4 @@
1
- import {
2
- FUNCTION_TREE_HEIGHT,
3
- PROTOCOL_CONTRACT_TREE_HEIGHT,
4
- PUBLIC_DATA_TREE_HEIGHT,
5
- UPDATES_VALUE_SIZE,
6
- } from '@aztec/constants';
1
+ import { FUNCTION_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, UPDATES_VALUE_SIZE } from '@aztec/constants';
7
2
  import { Fr } from '@aztec/foundation/fields';
8
3
  import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
9
4
  import { MembershipWitness } from '@aztec/foundation/trees';
@@ -11,7 +6,7 @@ import type { FieldsOf } from '@aztec/foundation/types';
11
6
 
12
7
  import { DelayedPublicMutableValues } from '../delayed_public_mutable/delayed_public_mutable_values.js';
13
8
  import { PublicKeys } from '../keys/public_keys.js';
14
- import { ProtocolContractLeafPreimage, PublicDataTreeLeafPreimage } from '../trees/index.js';
9
+ import { PublicDataTreeLeafPreimage } from '../trees/index.js';
15
10
  import { VerificationKeyAsFields } from '../vks/verification_key.js';
16
11
  import { PrivateCircuitPublicInputs } from './private_circuit_public_inputs.js';
17
12
 
@@ -94,16 +89,6 @@ export class PrivateVerificationKeyHints {
94
89
  * The membership witness for the function leaf corresponding to the function being invoked.
95
90
  */
96
91
  public functionLeafMembershipWitness: MembershipWitness<typeof FUNCTION_TREE_HEIGHT>,
97
- /**
98
- * The membership witness for the protocolContractLeaf.
99
- */
100
- public protocolContractMembershipWitness: MembershipWitness<typeof PROTOCOL_CONTRACT_TREE_HEIGHT>,
101
- /**
102
- * The leaf of the protocol contract tree, of either:
103
- * The protocol contract being called.
104
- * The low leaf showing that the address of the contract being called is not in the tree.
105
- */
106
- public protocolContractLeaf: ProtocolContractLeafPreimage,
107
92
 
108
93
  public updatedClassIdHints: UpdatedClassIdHints,
109
94
  ) {}
@@ -120,8 +105,6 @@ export class PrivateVerificationKeyHints {
120
105
  fields.publicKeys,
121
106
  fields.saltedInitializationHash,
122
107
  fields.functionLeafMembershipWitness,
123
- fields.protocolContractMembershipWitness,
124
- fields.protocolContractLeaf,
125
108
  fields.updatedClassIdHints,
126
109
  ] as const;
127
110
  }
@@ -151,8 +134,6 @@ export class PrivateVerificationKeyHints {
151
134
  reader.readObject(PublicKeys),
152
135
  reader.readObject(Fr),
153
136
  reader.readObject(MembershipWitness.deserializer(FUNCTION_TREE_HEIGHT)),
154
- reader.readObject(MembershipWitness.deserializer(PROTOCOL_CONTRACT_TREE_HEIGHT)),
155
- reader.readObject(ProtocolContractLeafPreimage),
156
137
  reader.readObject(UpdatedClassIdHints),
157
138
  );
158
139
  }
@@ -3,7 +3,7 @@ import { bufferSchemaFor } from '@aztec/foundation/schemas';
3
3
  import { BufferReader, bigintToUInt64BE, serializeToBuffer } from '@aztec/foundation/serialize';
4
4
 
5
5
  import { AztecAddress } from '../aztec-address/index.js';
6
- import { TxConstantData } from '../tx/tx_constant_data.js';
6
+ import { PrivateTxConstantData } from '../tx/private_tx_constant_data.js';
7
7
  import type { UInt64 } from '../types/shared.js';
8
8
  import { PrivateAccumulatedData } from './private_accumulated_data.js';
9
9
  import { PrivateValidationRequests } from './private_validation_requests.js';
@@ -17,7 +17,7 @@ export class PrivateKernelCircuitPublicInputs {
17
17
  /**
18
18
  * Data which is not modified by the circuits.
19
19
  */
20
- public constants: TxConstantData,
20
+ public constants: PrivateTxConstantData,
21
21
  /**
22
22
  * The side effect counter that non-revertible side effects are all beneath.
23
23
  */
@@ -82,7 +82,7 @@ export class PrivateKernelCircuitPublicInputs {
82
82
  static fromBuffer(buffer: Buffer | BufferReader): PrivateKernelCircuitPublicInputs {
83
83
  const reader = BufferReader.asReader(buffer);
84
84
  return new PrivateKernelCircuitPublicInputs(
85
- reader.readObject(TxConstantData),
85
+ reader.readObject(PrivateTxConstantData),
86
86
  reader.readObject(Fr),
87
87
  reader.readObject(PrivateValidationRequests),
88
88
  reader.readObject(PrivateAccumulatedData),
@@ -96,7 +96,7 @@ export class PrivateKernelCircuitPublicInputs {
96
96
 
97
97
  static empty() {
98
98
  return new PrivateKernelCircuitPublicInputs(
99
- TxConstantData.empty(),
99
+ PrivateTxConstantData.empty(),
100
100
  Fr.zero(),
101
101
  PrivateValidationRequests.empty(),
102
102
  PrivateAccumulatedData.empty(),
@@ -1,6 +1,7 @@
1
1
  import { Fr } from '@aztec/foundation/fields';
2
2
  import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
3
3
 
4
+ import { ProtocolContracts } from '../tx/protocol_contracts.js';
4
5
  import { TxRequest } from '../tx/tx_request.js';
5
6
  import { PrivateCallData } from './private_call_data.js';
6
7
 
@@ -18,9 +19,9 @@ export class PrivateKernelInitCircuitPrivateInputs {
18
19
  */
19
20
  public vkTreeRoot: Fr,
20
21
  /**
21
- * The root of the protocol contract tree.
22
+ * The protocol contracts.
22
23
  */
23
- public protocolContractTreeRoot: Fr,
24
+ public protocolContracts: ProtocolContracts,
24
25
  /**
25
26
  * Private calldata corresponding to this iteration of the kernel.
26
27
  */
@@ -43,7 +44,7 @@ export class PrivateKernelInitCircuitPrivateInputs {
43
44
  return serializeToBuffer(
44
45
  this.txRequest,
45
46
  this.vkTreeRoot,
46
- this.protocolContractTreeRoot,
47
+ this.protocolContracts,
47
48
  this.privateCall,
48
49
  this.firstNullifierHint,
49
50
  );
@@ -59,7 +60,7 @@ export class PrivateKernelInitCircuitPrivateInputs {
59
60
  return new PrivateKernelInitCircuitPrivateInputs(
60
61
  reader.readObject(TxRequest),
61
62
  Fr.fromBuffer(reader),
62
- Fr.fromBuffer(reader),
63
+ reader.readObject(ProtocolContracts),
63
64
  reader.readObject(PrivateCallData),
64
65
  reader.readBoolean(),
65
66
  Fr.fromBuffer(reader),
@@ -173,7 +173,7 @@ export class PrivateKernelTailCircuitPublicInputs {
173
173
  this.constants.anchorBlockHeader,
174
174
  this.constants.txContext,
175
175
  this.constants.vkTreeRoot,
176
- this.constants.protocolContractTreeRoot,
176
+ this.constants.protocolContractsHash,
177
177
  );
178
178
  return new PrivateToRollupKernelCircuitPublicInputs(
179
179
  constants,
@@ -26,6 +26,8 @@ export class BlockProposalHash extends Buffer32 {
26
26
 
27
27
  export type BlockProposalOptions = {
28
28
  publishFullTxs: boolean;
29
+ /** Whether to generate an invalid block proposal for broadcasting. Use only for testing. */
30
+ broadcastInvalidBlockProposal?: boolean;
29
31
  };
30
32
 
31
33
  /**
@@ -21,8 +21,8 @@ export class BlockConstantData {
21
21
  public l1ToL2TreeSnapshot: AppendOnlyTreeSnapshot,
22
22
  /** Root of the verification key tree. */
23
23
  public vkTreeRoot: Fr,
24
- /** Root of the protocol contract tree. */
25
- public protocolContractTreeRoot: Fr,
24
+ /** Hash of the protocol contracts list. */
25
+ public protocolContractsHash: Fr,
26
26
  /** Global variables for the block. */
27
27
  public globalVariables: GlobalVariables,
28
28
  /** Identifier of the prover. */
@@ -50,7 +50,7 @@ export class BlockConstantData {
50
50
  fields.lastArchive,
51
51
  fields.l1ToL2TreeSnapshot,
52
52
  fields.vkTreeRoot,
53
- fields.protocolContractTreeRoot,
53
+ fields.protocolContractsHash,
54
54
  fields.globalVariables,
55
55
  fields.proverId,
56
56
  ] as const;
@@ -17,8 +17,8 @@ export class CheckpointConstantData {
17
17
  public version: Fr,
18
18
  /** Root of the verification key tree. */
19
19
  public vkTreeRoot: Fr,
20
- /** Root of the protocol contract tree. */
21
- public protocolContractTreeRoot: Fr,
20
+ /** Hash of the protocol contracts list. */
21
+ public protocolContractsHash: Fr,
22
22
  /** Identifier of the prover. */
23
23
  public proverId: Fr,
24
24
  /** Slot number of the checkpoint. */
@@ -40,7 +40,7 @@ export class CheckpointConstantData {
40
40
  fields.chainId,
41
41
  fields.version,
42
42
  fields.vkTreeRoot,
43
- fields.protocolContractTreeRoot,
43
+ fields.protocolContractsHash,
44
44
  fields.proverId,
45
45
  fields.slotNumber,
46
46
  fields.coinbase,
@@ -20,9 +20,9 @@ export class EpochConstantData {
20
20
  */
21
21
  public vkTreeRoot: Fr,
22
22
  /**
23
- * Root of the protocol contract tree.
23
+ * Hash of the protocol contracts list.
24
24
  */
25
- public protocolContractTreeRoot: Fr,
25
+ public protocolContractsHash: Fr,
26
26
  /**
27
27
  * Identifier of the prover of the epoch.
28
28
  */
@@ -34,13 +34,7 @@ export class EpochConstantData {
34
34
  }
35
35
 
36
36
  static getFields(fields: FieldsOf<EpochConstantData>) {
37
- return [
38
- fields.chainId,
39
- fields.version,
40
- fields.vkTreeRoot,
41
- fields.protocolContractTreeRoot,
42
- fields.proverId,
43
- ] as const;
37
+ return [fields.chainId, fields.version, fields.vkTreeRoot, fields.protocolContractsHash, fields.proverId] as const;
44
38
  }
45
39
 
46
40
  toFields(): Fr[] {
@@ -2,6 +2,12 @@ import { fromEntries, getEntries, maxBy } from '@aztec/foundation/collection';
2
2
  import { jsonParseWithSchema } from '@aztec/foundation/json-rpc';
3
3
  import type { ReadOnlyFileStore } from '@aztec/stdlib/file-store';
4
4
 
5
+ import { createReadStream, createWriteStream } from 'fs';
6
+ import fs from 'fs/promises';
7
+ import pathMod from 'path';
8
+ import { pipeline } from 'stream/promises';
9
+ import { createGunzip, gunzipSync } from 'zlib';
10
+
5
11
  import {
6
12
  SnapshotDataKeys,
7
13
  type SnapshotDataUrls,
@@ -20,7 +26,8 @@ export async function getSnapshotIndex(
20
26
  try {
21
27
  if (await store.exists(snapshotIndexPath)) {
22
28
  const snapshotIndexData = await store.read(snapshotIndexPath);
23
- return jsonParseWithSchema(snapshotIndexData.toString(), SnapshotsIndexSchema);
29
+ const buf = maybeGunzip(snapshotIndexData);
30
+ return jsonParseWithSchema(buf.toString('utf-8'), SnapshotsIndexSchema);
24
31
  } else {
25
32
  return undefined;
26
33
  }
@@ -50,10 +57,67 @@ export function makeSnapshotPaths(baseDir: string): SnapshotDataUrls {
50
57
  return fromEntries(SnapshotDataKeys.map(key => [key, `${baseDir}/${key}.db`]));
51
58
  }
52
59
 
60
+ function isGzipMagic(data: Buffer): boolean {
61
+ return data.length >= 2 && data[0] === 0x1f && data[1] === 0x8b;
62
+ }
63
+
64
+ function maybeGunzip(data: Buffer): Buffer {
65
+ const magicNumberIndicatesGzip = isGzipMagic(data);
66
+
67
+ if (magicNumberIndicatesGzip) {
68
+ try {
69
+ const out = gunzipSync(data);
70
+ return out;
71
+ } catch (err) {
72
+ throw new Error(`Decompression of gzipped data failed: ${(err as Error).message}`);
73
+ }
74
+ }
75
+ return data;
76
+ }
77
+
78
+ async function detectGzip(localFilePathToPeek: string): Promise<boolean> {
79
+ // Peek the actual bytes we downloaded.
80
+ try {
81
+ const fd = await fs.open(localFilePathToPeek, 'r');
82
+ try {
83
+ const header = Buffer.alloc(2);
84
+ const { bytesRead } = await fd.read(header, 0, 2, 0);
85
+ return bytesRead >= 2 && isGzipMagic(header);
86
+ } finally {
87
+ await fd.close();
88
+ }
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+
53
94
  export async function downloadSnapshot(
54
95
  snapshot: Pick<SnapshotMetadata, 'dataUrls'>,
55
96
  localPaths: Record<SnapshotDataKeys, string>,
56
97
  store: ReadOnlyFileStore,
57
98
  ): Promise<void> {
58
- await Promise.all(getEntries(localPaths).map(([key, path]) => store.download(snapshot.dataUrls[key], path)));
99
+ await Promise.all(
100
+ getEntries(localPaths).map(async ([key, path]) => {
101
+ await fs.mkdir(pathMod.dirname(path), { recursive: true });
102
+
103
+ const tmpPath = `${path}.download`;
104
+ try {
105
+ const url = snapshot.dataUrls[key];
106
+ await store.download(url, tmpPath);
107
+
108
+ const isGzip = await detectGzip(tmpPath);
109
+
110
+ const read = createReadStream(tmpPath);
111
+ const write = createWriteStream(path);
112
+ if (isGzip) {
113
+ const gunzip = createGunzip();
114
+ await pipeline(read, gunzip, write);
115
+ } else {
116
+ await pipeline(read, write);
117
+ }
118
+ } finally {
119
+ await fs.unlink(tmpPath).catch(() => undefined);
120
+ }
121
+ }),
122
+ );
59
123
  }
@@ -48,6 +48,7 @@ export async function uploadSnapshotToIndex(
48
48
 
49
49
  await store.save(getSnapshotIndexPath(metadata), Buffer.from(jsonStringify(snapshotsIndex, true)), {
50
50
  public: true, // Make the index publicly accessible
51
+ compress: false, // Ensure index.json is not gzipped
51
52
  metadata: { ['Cache-control']: 'no-store' }, // Do not cache object versions
52
53
  });
53
54
  return newSnapshotMetadata;