@aztec/stdlib 3.0.0-nightly.20251113 → 3.0.0-nightly.20251115

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 (80) hide show
  1. package/dest/avm/avm.d.ts +102 -8
  2. package/dest/avm/avm.d.ts.map +1 -1
  3. package/dest/avm/avm.js +43 -4
  4. package/dest/avm/public_data_write.d.ts +1 -1
  5. package/dest/avm/public_data_write.d.ts.map +1 -1
  6. package/dest/avm/revert_code.d.ts +2 -1
  7. package/dest/avm/revert_code.d.ts.map +1 -1
  8. package/dest/avm/revert_code.js +8 -8
  9. package/dest/block/body.d.ts +3 -6
  10. package/dest/block/body.d.ts.map +1 -1
  11. package/dest/block/body.js +6 -25
  12. package/dest/block/index.d.ts +1 -0
  13. package/dest/block/index.d.ts.map +1 -1
  14. package/dest/block/index.js +1 -0
  15. package/dest/block/l2_block.d.ts +5 -0
  16. package/dest/block/l2_block.d.ts.map +1 -1
  17. package/dest/block/l2_block.js +34 -4
  18. package/dest/block/l2_block_new.d.ts +97 -0
  19. package/dest/block/l2_block_new.d.ts.map +1 -0
  20. package/dest/block/l2_block_new.js +113 -0
  21. package/dest/checkpoint/checkpoint.d.ts +108 -0
  22. package/dest/checkpoint/checkpoint.d.ts.map +1 -0
  23. package/dest/checkpoint/checkpoint.js +39 -0
  24. package/dest/checkpoint/index.d.ts +1 -1
  25. package/dest/checkpoint/index.d.ts.map +1 -1
  26. package/dest/checkpoint/index.js +1 -1
  27. package/dest/logs/private_log.d.ts +1 -1
  28. package/dest/logs/private_log.d.ts.map +1 -1
  29. package/dest/logs/private_log.js +2 -5
  30. package/dest/messaging/in_hash.d.ts +4 -0
  31. package/dest/messaging/in_hash.d.ts.map +1 -0
  32. package/dest/messaging/in_hash.js +15 -0
  33. package/dest/messaging/index.d.ts +2 -0
  34. package/dest/messaging/index.d.ts.map +1 -1
  35. package/dest/messaging/index.js +2 -0
  36. package/dest/messaging/out_hash.d.ts +5 -0
  37. package/dest/messaging/out_hash.d.ts.map +1 -0
  38. package/dest/messaging/out_hash.js +28 -0
  39. package/dest/rollup/checkpoint_constant_data.d.ts +16 -0
  40. package/dest/rollup/checkpoint_constant_data.d.ts.map +1 -1
  41. package/dest/rollup/checkpoint_constant_data.js +17 -0
  42. package/dest/tests/factories.d.ts +17 -21
  43. package/dest/tests/factories.d.ts.map +1 -1
  44. package/dest/tests/factories.js +14 -111
  45. package/dest/tests/mocks.d.ts +17 -1
  46. package/dest/tests/mocks.d.ts.map +1 -1
  47. package/dest/tests/mocks.js +108 -4
  48. package/dest/tx/partial_state_reference.d.ts +3 -0
  49. package/dest/tx/partial_state_reference.d.ts.map +1 -1
  50. package/dest/tx/partial_state_reference.js +10 -0
  51. package/dest/tx/state_reference.d.ts +3 -0
  52. package/dest/tx/state_reference.d.ts.map +1 -1
  53. package/dest/tx/state_reference.js +9 -0
  54. package/dest/tx/tx_effect.d.ts +9 -6
  55. package/dest/tx/tx_effect.d.ts.map +1 -1
  56. package/dest/tx/tx_effect.js +53 -57
  57. package/package.json +8 -8
  58. package/src/avm/avm.ts +48 -10
  59. package/src/avm/public_data_write.ts +1 -1
  60. package/src/avm/revert_code.ts +9 -8
  61. package/src/block/body.ts +7 -32
  62. package/src/block/index.ts +1 -0
  63. package/src/block/l2_block.ts +33 -2
  64. package/src/block/l2_block_new.ts +143 -0
  65. package/src/checkpoint/checkpoint.ts +46 -0
  66. package/src/checkpoint/index.ts +1 -1
  67. package/src/logs/private_log.ts +2 -3
  68. package/src/messaging/in_hash.ts +15 -0
  69. package/src/messaging/index.ts +2 -0
  70. package/src/messaging/out_hash.ts +36 -0
  71. package/src/rollup/checkpoint_constant_data.ts +20 -0
  72. package/src/tests/factories.ts +91 -193
  73. package/src/tests/mocks.ts +196 -4
  74. package/src/tx/partial_state_reference.ts +9 -0
  75. package/src/tx/state_reference.ts +9 -0
  76. package/src/tx/tx_effect.ts +61 -67
  77. package/dest/checkpoint/checkpoint_body.d.ts +0 -4
  78. package/dest/checkpoint/checkpoint_body.d.ts.map +0 -1
  79. package/dest/checkpoint/checkpoint_body.js +0 -9
  80. package/src/checkpoint/checkpoint_body.ts +0 -10
@@ -1,10 +1,21 @@
1
- import { MAX_ENQUEUED_CALLS_PER_TX, MAX_INCLUDE_BY_TIMESTAMP_DURATION } from '@aztec/constants';
1
+ import {
2
+ FIXED_DA_GAS,
3
+ FIXED_L2_GAS,
4
+ MAX_ENQUEUED_CALLS_PER_TX,
5
+ MAX_INCLUDE_BY_TIMESTAMP_DURATION,
6
+ MAX_NULLIFIERS_PER_TX,
7
+ MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
8
+ } from '@aztec/constants';
9
+ import { makeTuple } from '@aztec/foundation/array';
2
10
  import { Buffer32 } from '@aztec/foundation/buffer';
3
- import { times } from '@aztec/foundation/collection';
11
+ import { padArrayEnd, times } from '@aztec/foundation/collection';
4
12
  import { Secp256k1Signer, randomBytes } from '@aztec/foundation/crypto';
5
13
  import { Fr } from '@aztec/foundation/fields';
6
14
 
7
15
  import type { ContractArtifact } from '../abi/abi.js';
16
+ import { AvmCircuitPublicInputs } from '../avm/avm_circuit_public_inputs.js';
17
+ import { PublicDataWrite } from '../avm/public_data_write.js';
18
+ import { RevertCode } from '../avm/revert_code.js';
8
19
  import { AztecAddress } from '../aztec-address/index.js';
9
20
  import { CommitteeAttestation, L1PublishedData, L2BlockHeader } from '../block/index.js';
10
21
  import { L2Block } from '../block/l2_block.js';
@@ -14,16 +25,21 @@ import { computeContractAddressFromInstance } from '../contract/contract_address
14
25
  import { getContractClassFromArtifact } from '../contract/contract_class.js';
15
26
  import { SerializableContractInstance } from '../contract/contract_instance.js';
16
27
  import type { ContractInstanceWithAddress } from '../contract/index.js';
28
+ import { computeEffectiveGasFees } from '../fees/transaction_fee.js';
17
29
  import { Gas } from '../gas/gas.js';
18
30
  import { GasFees } from '../gas/gas_fees.js';
19
31
  import { GasSettings } from '../gas/gas_settings.js';
32
+ import type { GasUsed } from '../gas/gas_used.js';
33
+ import type { MerkleTreeReadOperations } from '../interfaces/merkle_tree_operations.js';
20
34
  import { Nullifier } from '../kernel/nullifier.js';
21
35
  import { PrivateCircuitPublicInputs } from '../kernel/private_circuit_public_inputs.js';
22
36
  import {
23
37
  PartialPrivateTailPublicInputsForPublic,
24
38
  PrivateKernelTailCircuitPublicInputs,
25
39
  } from '../kernel/private_kernel_tail_circuit_public_inputs.js';
40
+ import { PrivateToAvmAccumulatedData } from '../kernel/private_to_avm_accumulated_data.js';
26
41
  import { PrivateToPublicAccumulatedDataBuilder } from '../kernel/private_to_public_accumulated_data_builder.js';
42
+ import { PublicCallRequestArrayLengths } from '../kernel/public_call_request.js';
27
43
  import { Note } from '../note/note.js';
28
44
  import { UniqueNote } from '../note/unique_note.js';
29
45
  import { BlockAttestation } from '../p2p/block_attestation.js';
@@ -31,12 +47,38 @@ import { BlockProposal } from '../p2p/block_proposal.js';
31
47
  import { ConsensusPayload } from '../p2p/consensus_payload.js';
32
48
  import { SignatureDomainSeparator, getHashedSignaturePayloadEthSignedMessage } from '../p2p/signature_utils.js';
33
49
  import { ChonkProof } from '../proofs/chonk_proof.js';
34
- import { HashedValues, PrivateCallExecutionResult, PrivateExecutionResult, StateReference, Tx } from '../tx/index.js';
50
+ import { ProvingRequestType } from '../proofs/proving_request_type.js';
51
+ import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js';
52
+ import {
53
+ BlockHeader,
54
+ GlobalVariables,
55
+ HashedValues,
56
+ PrivateCallExecutionResult,
57
+ PrivateExecutionResult,
58
+ ProtocolContracts,
59
+ StateReference,
60
+ Tx,
61
+ TxConstantData,
62
+ makeProcessedTxFromPrivateOnlyTx,
63
+ makeProcessedTxFromTxWithPublicCalls,
64
+ } from '../tx/index.js';
35
65
  import { NestedProcessReturnValues, PublicSimulationOutput } from '../tx/public_simulation_output.js';
36
66
  import { TxSimulationResult } from '../tx/simulated_tx.js';
37
67
  import { TxEffect } from '../tx/tx_effect.js';
38
68
  import { TxHash } from '../tx/tx_hash.js';
39
- import { makeGas, makeGlobalVariables, makeL2BlockHeader, makePublicCallRequest } from './factories.js';
69
+ import {
70
+ makeAvmCircuitInputs,
71
+ makeAztecAddress,
72
+ makeGas,
73
+ makeGlobalVariables,
74
+ makeHeader,
75
+ makeL2BlockHeader,
76
+ makePrivateToPublicAccumulatedData,
77
+ makePrivateToRollupAccumulatedData,
78
+ makeProtocolContracts,
79
+ makePublicCallRequest,
80
+ makePublicDataWrite,
81
+ } from './factories.js';
40
82
 
41
83
  export const randomTxHash = (): TxHash => TxHash.random();
42
84
 
@@ -159,6 +201,156 @@ export const mockTx = async (
159
201
  export const mockTxForRollup = (seed = 1, opts: Parameters<typeof mockTx>[1] = {}) =>
160
202
  mockTx(seed, { ...opts, numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0 });
161
203
 
204
+ /** Mock a processed tx for testing purposes. */
205
+ export async function mockProcessedTx({
206
+ seed = 1,
207
+ anchorBlockHeader,
208
+ db,
209
+ chainId = Fr.ZERO,
210
+ version = Fr.ZERO,
211
+ gasSettings = GasSettings.default({ maxFeesPerGas: new GasFees(10, 10) }),
212
+ vkTreeRoot = Fr.ZERO,
213
+ protocolContracts = makeProtocolContracts(seed + 0x100),
214
+ globalVariables = GlobalVariables.empty(),
215
+ newL1ToL2Snapshot = AppendOnlyTreeSnapshot.empty(),
216
+ feePayer,
217
+ feePaymentPublicDataWrite,
218
+ // The default gasUsed is the tx overhead.
219
+ gasUsed = Gas.from({ daGas: FIXED_DA_GAS, l2Gas: FIXED_L2_GAS }),
220
+ privateOnly = false,
221
+ ...mockTxOpts
222
+ }: {
223
+ seed?: number;
224
+ anchorBlockHeader?: BlockHeader;
225
+ db?: MerkleTreeReadOperations;
226
+ gasSettings?: GasSettings;
227
+ globalVariables?: GlobalVariables;
228
+ newL1ToL2Snapshot?: AppendOnlyTreeSnapshot;
229
+ protocolContracts?: ProtocolContracts;
230
+ feePaymentPublicDataWrite?: PublicDataWrite;
231
+ privateOnly?: boolean;
232
+ } & Parameters<typeof mockTx>[1] = {}) {
233
+ seed *= 0x1000; // Avoid clashing with the previous mock values if seed only increases by 1.
234
+ anchorBlockHeader ??= db?.getInitialHeader() ?? makeHeader(seed);
235
+ feePayer ??= makeAztecAddress(seed + 0x100);
236
+ feePaymentPublicDataWrite ??= makePublicDataWrite(seed + 0x200);
237
+
238
+ const txConstantData = TxConstantData.empty();
239
+ txConstantData.anchorBlockHeader = anchorBlockHeader;
240
+ txConstantData.txContext.chainId = chainId;
241
+ txConstantData.txContext.version = version;
242
+ txConstantData.txContext.gasSettings = gasSettings;
243
+ txConstantData.vkTreeRoot = vkTreeRoot;
244
+ txConstantData.protocolContractsHash = await protocolContracts.hash();
245
+
246
+ const tx = !privateOnly
247
+ ? await mockTx(seed, { feePayer, gasUsed, ...mockTxOpts })
248
+ : await mockTx(seed, {
249
+ numberOfNonRevertiblePublicCallRequests: 0,
250
+ numberOfRevertiblePublicCallRequests: 0,
251
+ feePayer,
252
+ gasUsed,
253
+ ...mockTxOpts,
254
+ });
255
+ tx.data.constants = txConstantData;
256
+
257
+ const transactionFee = tx.data.gasUsed.computeFee(globalVariables.gasFees);
258
+
259
+ if (privateOnly) {
260
+ const data = makePrivateToRollupAccumulatedData(seed + 0x1000, { numContractClassLogs: 0 });
261
+
262
+ tx.data.forRollup!.end = data;
263
+
264
+ await tx.recomputeHash();
265
+ return makeProcessedTxFromPrivateOnlyTx(tx, transactionFee, feePaymentPublicDataWrite, globalVariables);
266
+ } else {
267
+ const dataFromPrivate = tx.data.forPublic!;
268
+
269
+ const nonRevertibleData = dataFromPrivate.nonRevertibleAccumulatedData;
270
+
271
+ // Create revertible data.
272
+ const revertibleData = makePrivateToPublicAccumulatedData(seed + 0x1000, { numContractClassLogs: 0 });
273
+ revertibleData.nullifiers[MAX_NULLIFIERS_PER_TX - 1] = Fr.ZERO; // Leave one space for the tx hash nullifier in nonRevertibleAccumulatedData.
274
+ dataFromPrivate.revertibleAccumulatedData = revertibleData;
275
+
276
+ // Create avm output.
277
+ const avmOutput = AvmCircuitPublicInputs.empty();
278
+ // Assign data from hints.
279
+ avmOutput.protocolContracts = protocolContracts;
280
+ avmOutput.startTreeSnapshots.l1ToL2MessageTree = newL1ToL2Snapshot;
281
+ avmOutput.endTreeSnapshots.l1ToL2MessageTree = newL1ToL2Snapshot;
282
+ avmOutput.effectiveGasFees = computeEffectiveGasFees(globalVariables.gasFees, gasSettings);
283
+ // Assign data from private.
284
+ avmOutput.globalVariables = globalVariables;
285
+ avmOutput.startGasUsed = tx.data.gasUsed;
286
+ avmOutput.gasSettings = gasSettings;
287
+ avmOutput.feePayer = feePayer;
288
+ avmOutput.publicCallRequestArrayLengths = new PublicCallRequestArrayLengths(
289
+ tx.data.numberOfNonRevertiblePublicCallRequests(),
290
+ tx.data.numberOfRevertiblePublicCallRequests(),
291
+ tx.data.hasTeardownPublicCallRequest(),
292
+ );
293
+ avmOutput.publicSetupCallRequests = dataFromPrivate.nonRevertibleAccumulatedData.publicCallRequests;
294
+ avmOutput.publicAppLogicCallRequests = dataFromPrivate.revertibleAccumulatedData.publicCallRequests;
295
+ avmOutput.publicTeardownCallRequest = dataFromPrivate.publicTeardownCallRequest;
296
+ avmOutput.previousNonRevertibleAccumulatedData = new PrivateToAvmAccumulatedData(
297
+ dataFromPrivate.nonRevertibleAccumulatedData.noteHashes,
298
+ dataFromPrivate.nonRevertibleAccumulatedData.nullifiers,
299
+ dataFromPrivate.nonRevertibleAccumulatedData.l2ToL1Msgs,
300
+ );
301
+ avmOutput.previousNonRevertibleAccumulatedDataArrayLengths =
302
+ avmOutput.previousNonRevertibleAccumulatedData.getArrayLengths();
303
+ avmOutput.previousRevertibleAccumulatedData = new PrivateToAvmAccumulatedData(
304
+ dataFromPrivate.revertibleAccumulatedData.noteHashes,
305
+ dataFromPrivate.revertibleAccumulatedData.nullifiers,
306
+ dataFromPrivate.revertibleAccumulatedData.l2ToL1Msgs,
307
+ );
308
+ avmOutput.previousRevertibleAccumulatedDataArrayLengths =
309
+ avmOutput.previousRevertibleAccumulatedData.getArrayLengths();
310
+ // Assign final data emitted from avm.
311
+ avmOutput.accumulatedData.noteHashes = revertibleData.noteHashes;
312
+ avmOutput.accumulatedData.nullifiers = padArrayEnd(
313
+ nonRevertibleData.nullifiers.concat(revertibleData.nullifiers).filter(n => !n.isEmpty()),
314
+ Fr.ZERO,
315
+ MAX_NULLIFIERS_PER_TX,
316
+ );
317
+ avmOutput.accumulatedData.l2ToL1Msgs = revertibleData.l2ToL1Msgs;
318
+ avmOutput.accumulatedData.publicDataWrites = makeTuple(
319
+ MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
320
+ i => new PublicDataWrite(new Fr(i), new Fr(i + 10)),
321
+ seed + 0x2000,
322
+ );
323
+ avmOutput.accumulatedData.publicDataWrites[0] = feePaymentPublicDataWrite;
324
+ avmOutput.accumulatedDataArrayLengths = avmOutput.accumulatedData.getArrayLengths();
325
+ avmOutput.gasSettings = gasSettings;
326
+ // Note: The fee is computed from the tx's gas used, which only includes the gas used in private. But this shouldn't
327
+ // be a problem for the tests.
328
+ avmOutput.transactionFee = transactionFee;
329
+
330
+ const avmCircuitInputs = await makeAvmCircuitInputs(seed + 0x3000, { publicInputs: avmOutput });
331
+ avmCircuitInputs.hints.startingTreeRoots.l1ToL2MessageTree = newL1ToL2Snapshot;
332
+
333
+ const gasUsed = {
334
+ totalGas: Gas.empty(),
335
+ teardownGas: Gas.empty(),
336
+ publicGas: Gas.empty(),
337
+ billedGas: Gas.empty(),
338
+ } satisfies GasUsed;
339
+
340
+ await tx.recomputeHash();
341
+ return makeProcessedTxFromTxWithPublicCalls(
342
+ tx,
343
+ {
344
+ type: ProvingRequestType.PUBLIC_VM,
345
+ inputs: avmCircuitInputs,
346
+ },
347
+ gasUsed,
348
+ RevertCode.OK,
349
+ undefined /* revertReason */,
350
+ );
351
+ }
352
+ }
353
+
162
354
  const emptyPrivateCallExecutionResult = () =>
163
355
  new PrivateCallExecutionResult(
164
356
  Buffer.from(''),
@@ -2,6 +2,7 @@ import { PARTIAL_STATE_REFERENCE_LENGTH } from '@aztec/constants';
2
2
  import type { ViemPartialStateReference } from '@aztec/ethereum';
3
3
  import type { Fr } from '@aztec/foundation/fields';
4
4
  import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize';
5
+ import type { FieldsOf } from '@aztec/foundation/types';
5
6
 
6
7
  import { z } from 'zod';
7
8
 
@@ -37,6 +38,14 @@ export class PartialStateReference {
37
38
  return this.noteHashTree.getSize() + this.nullifierTree.getSize() + this.publicDataTree.getSize();
38
39
  }
39
40
 
41
+ static getFields(fields: FieldsOf<PartialStateReference>) {
42
+ return [fields.noteHashTree, fields.nullifierTree, fields.publicDataTree] as const;
43
+ }
44
+
45
+ static from(fields: FieldsOf<PartialStateReference>) {
46
+ return new PartialStateReference(...PartialStateReference.getFields(fields));
47
+ }
48
+
40
49
  static fromBuffer(buffer: Buffer | BufferReader): PartialStateReference {
41
50
  const reader = BufferReader.asReader(buffer);
42
51
  return new PartialStateReference(
@@ -7,6 +7,7 @@ import {
7
7
  import type { ViemStateReference } from '@aztec/ethereum';
8
8
  import type { Fr } from '@aztec/foundation/fields';
9
9
  import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize';
10
+ import type { FieldsOf } from '@aztec/foundation/types';
10
11
 
11
12
  import { inspect } from 'util';
12
13
  import { z } from 'zod';
@@ -38,6 +39,14 @@ export class StateReference {
38
39
  return this.l1ToL2MessageTree.getSize() + this.partial.getSize();
39
40
  }
40
41
 
42
+ static getFields(fields: FieldsOf<StateReference>) {
43
+ return [fields.l1ToL2MessageTree, fields.partial] as const;
44
+ }
45
+
46
+ static from(fields: FieldsOf<StateReference>) {
47
+ return new StateReference(...StateReference.getFields(fields));
48
+ }
49
+
41
50
  toBuffer() {
42
51
  // Note: The order here must match the order in the ProposedHeaderLib solidity library.
43
52
  return serializeToBuffer(this.l1ToL2MessageTree, this.partial);
@@ -1,4 +1,10 @@
1
- import { decodeTxStartMarker, encodeTxStartMarker, isValidTxStartMarker } from '@aztec/blob-lib/encoding';
1
+ import {
2
+ type TxBlobData,
3
+ type TxStartMarker,
4
+ decodeTxBlobData,
5
+ encodeTxBlobData,
6
+ getNumTxBlobFields,
7
+ } from '@aztec/blob-lib/encoding';
2
8
  import {
3
9
  MAX_CONTRACT_CLASS_LOGS_PER_TX,
4
10
  MAX_L2_TO_L1_MSGS_PER_TX,
@@ -10,14 +16,8 @@ import {
10
16
  import { type FieldsOf, makeTuple, makeTupleAsync } from '@aztec/foundation/array';
11
17
  import { Fr } from '@aztec/foundation/fields';
12
18
  import { type ZodFor, schemas } from '@aztec/foundation/schemas';
13
- import {
14
- BufferReader,
15
- FieldReader,
16
- serializeArrayOfBufferableToVector,
17
- serializeToBuffer,
18
- } from '@aztec/foundation/serialize';
19
+ import { BufferReader, serializeArrayOfBufferableToVector, serializeToBuffer } from '@aztec/foundation/serialize';
19
20
  import { bufferToHex, hexToBuffer } from '@aztec/foundation/string';
20
- import { computeUnbalancedMerkleTreeRoot } from '@aztec/foundation/trees';
21
21
 
22
22
  import { inspect } from 'util';
23
23
  import { z } from 'zod';
@@ -27,6 +27,7 @@ import { RevertCode } from '../avm/revert_code.js';
27
27
  import { ContractClassLog } from '../logs/contract_class_log.js';
28
28
  import { PrivateLog } from '../logs/private_log.js';
29
29
  import { FlatPublicLogs, PublicLog } from '../logs/public_log.js';
30
+ import { computeTxOutHash } from '../messaging/out_hash.js';
30
31
  import { TxHash } from './tx_hash.js';
31
32
 
32
33
  export class TxEffect {
@@ -160,11 +161,6 @@ export class TxEffect {
160
161
  );
161
162
  }
162
163
 
163
- /** Returns the size of this tx effect in bytes as serialized onto DA. */
164
- getDASize() {
165
- return this.toBlobFields().length * Fr.SIZE_IN_BYTES;
166
- }
167
-
168
164
  /**
169
165
  * Deserializes the TxEffect object from a Buffer.
170
166
  * @param buffer - Buffer or BufferReader object to deserialize.
@@ -191,13 +187,8 @@ export class TxEffect {
191
187
  * Computes txOutHash of this tx effect.
192
188
  * @dev Follows new_sha in unbalanced_merkle_tree.nr
193
189
  */
194
- txOutHash(): Buffer {
195
- const { l2ToL1Msgs } = this;
196
- if (l2ToL1Msgs.length == 0) {
197
- return Buffer.alloc(32);
198
- }
199
-
200
- return computeUnbalancedMerkleTreeRoot(l2ToL1Msgs.map(msg => msg.toBuffer()));
190
+ txOutHash(): Fr {
191
+ return computeTxOutHash(this.l2ToL1Msgs);
201
192
  }
202
193
 
203
194
  static async random(
@@ -242,71 +233,74 @@ export class TxEffect {
242
233
  return bufferToHex(this.toBuffer());
243
234
  }
244
235
 
245
- /**
246
- * Returns a flat packed array of fields of all tx effects, to be appended to blobs.
247
- * Must match the implementation in noir-protocol-circuits/crates/rollup-lib/src/tx_base/components/tx_blob_data.nr
248
- */
249
- toBlobFields(): Fr[] {
250
- const flattened: Fr[] = [];
236
+ getNumBlobFields(): number {
237
+ return this.getTxStartMarker().numBlobFields;
238
+ }
251
239
 
252
- // We reassign the first field at the end when we know the length of all effects to create the tx start marker.
253
- flattened.push(Fr.ZERO);
240
+ toBlobFields(): Fr[] {
241
+ return encodeTxBlobData(this.toTxBlobData());
242
+ }
254
243
 
255
- flattened.push(this.txHash.hash);
256
- flattened.push(this.transactionFee);
257
- flattened.push(...this.noteHashes);
258
- flattened.push(...this.nullifiers);
259
- flattened.push(...this.l2ToL1Msgs);
260
- flattened.push(...this.publicDataWrites.flatMap(w => w.toBlobFields()));
261
- flattened.push(...this.privateLogs.flatMap(l => l.toBlobFields()));
262
- const flattenedPublicLogs = FlatPublicLogs.fromLogs(this.publicLogs);
263
- flattened.push(...flattenedPublicLogs.toBlobFields());
264
- flattened.push(...this.contractClassLogs.flatMap(l => l.toBlobFields()));
244
+ static fromBlobFields(fields: Fr[]) {
245
+ return TxEffect.fromTxBlobData(decodeTxBlobData(fields));
246
+ }
265
247
 
266
- flattened[0] = encodeTxStartMarker({
248
+ getTxStartMarker(): TxStartMarker {
249
+ const flatPublicLogs = FlatPublicLogs.fromLogs(this.publicLogs);
250
+ const partialTxStartMarker = {
267
251
  revertCode: this.revertCode.getCode(),
268
- numBlobFields: flattened.length,
269
252
  numNoteHashes: this.noteHashes.length,
270
253
  numNullifiers: this.nullifiers.length,
271
254
  numL2ToL1Msgs: this.l2ToL1Msgs.length,
272
255
  numPublicDataWrites: this.publicDataWrites.length,
273
256
  numPrivateLogs: this.privateLogs.length,
274
- publicLogsLength: flattenedPublicLogs.length,
257
+ privateLogsLength: this.privateLogs.reduce((acc, log) => acc + log.emittedLength, 0),
258
+ publicLogsLength: flatPublicLogs.length,
275
259
  contractClassLogLength: this.contractClassLogs[0]?.emittedLength ?? 0,
276
- });
260
+ };
261
+ const numBlobFields = getNumTxBlobFields(partialTxStartMarker);
262
+ return {
263
+ ...partialTxStartMarker,
264
+ numBlobFields,
265
+ };
266
+ }
277
267
 
278
- return flattened;
268
+ /**
269
+ * Returns a flat packed array of fields of all tx effects, to be appended to blobs.
270
+ * Must match the implementation in noir-protocol-circuits/crates/rollup-lib/src/tx_base/components/tx_blob_data.nr
271
+ */
272
+ toTxBlobData(): TxBlobData {
273
+ return {
274
+ txStartMarker: this.getTxStartMarker(),
275
+ txHash: this.txHash.hash,
276
+ transactionFee: this.transactionFee,
277
+ noteHashes: this.noteHashes,
278
+ nullifiers: this.nullifiers,
279
+ l2ToL1Msgs: this.l2ToL1Msgs,
280
+ publicDataWrites: this.publicDataWrites.map(w => w.toBlobFields()),
281
+ privateLogs: this.privateLogs.map(l => l.toBlobFields()),
282
+ publicLogs: FlatPublicLogs.fromLogs(this.publicLogs).toBlobFields(),
283
+ contractClassLog: this.contractClassLogs.map(l => l.toBlobFields()).flat(),
284
+ };
279
285
  }
280
286
 
281
287
  /**
282
288
  * Decodes a flat packed array of fields to TxEffect.
283
289
  */
284
- static fromBlobFields(fields: Fr[] | FieldReader) {
285
- const reader = FieldReader.asReader(fields);
286
- const totalFields = reader.remainingFields();
287
- if (!totalFields) {
288
- throw new Error('Cannot process empty blob fields.');
289
- }
290
-
291
- const txStartMarker = decodeTxStartMarker(reader.readField());
292
- if (!isValidTxStartMarker(txStartMarker)) {
293
- throw new Error('Invalid fields given to TxEffect.fromBlobFields(): invalid TxStartMarker');
294
- }
295
-
296
- const revertCode = RevertCode.fromField(new Fr(txStartMarker.revertCode));
297
- const txHash = new TxHash(reader.readField());
298
- const transactionFee = reader.readField();
299
- const noteHashes = reader.readFieldArray(txStartMarker.numNoteHashes);
300
- const nullifiers = reader.readFieldArray(txStartMarker.numNullifiers);
301
- const l2ToL1Msgs = reader.readFieldArray(txStartMarker.numL2ToL1Msgs);
302
- const publicDataWrites = Array.from({ length: txStartMarker.numPublicDataWrites }, () =>
303
- PublicDataWrite.fromBlobFields(reader),
304
- );
305
- const privateLogs = Array.from({ length: txStartMarker.numPrivateLogs }, () => PrivateLog.fromBlobFields(reader));
306
- const publicLogs = FlatPublicLogs.fromBlobFields(txStartMarker.publicLogsLength, reader).toLogs();
290
+ static fromTxBlobData(txBlobData: TxBlobData) {
291
+ const txStartMarker = txBlobData.txStartMarker;
292
+ const revertCode = RevertCode.fromNumber(txStartMarker.revertCode);
293
+ const txHash = new TxHash(txBlobData.txHash);
294
+ const transactionFee = txBlobData.transactionFee;
295
+ const noteHashes = txBlobData.noteHashes;
296
+ const nullifiers = txBlobData.nullifiers;
297
+ const l2ToL1Msgs = txBlobData.l2ToL1Msgs;
298
+ const publicDataWrites = txBlobData.publicDataWrites.map(w => PublicDataWrite.fromBlobFields(w));
299
+ const privateLogs = txBlobData.privateLogs.map(l => PrivateLog.fromBlobFields(l.length, l));
300
+ const publicLogs = FlatPublicLogs.fromBlobFields(txStartMarker.publicLogsLength, txBlobData.publicLogs).toLogs();
307
301
  const contractClassLogs =
308
302
  txStartMarker.contractClassLogLength > 0
309
- ? [ContractClassLog.fromBlobFields(txStartMarker.contractClassLogLength, reader)]
303
+ ? [ContractClassLog.fromBlobFields(txStartMarker.contractClassLogLength, txBlobData.contractClassLog)]
310
304
  : [];
311
305
 
312
306
  return TxEffect.from({
@@ -1,4 +0,0 @@
1
- import { Fr } from '@aztec/foundation/fields';
2
- import type { TxEffect } from '../tx/tx_effect.js';
3
- export declare function getCheckpointBlobFields(txEffectsInBlocks: TxEffect[][]): Fr[];
4
- //# sourceMappingURL=checkpoint_body.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"checkpoint_body.d.ts","sourceRoot":"","sources":["../../src/checkpoint/checkpoint_body.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAG9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,wBAAgB,uBAAuB,CAAC,iBAAiB,EAAE,QAAQ,EAAE,EAAE,QAItE"}
@@ -1,9 +0,0 @@
1
- import { Fr } from '@aztec/foundation/fields';
2
- import { getBlockBlobFields } from '../block/body.js';
3
- export function getCheckpointBlobFields(txEffectsInBlocks) {
4
- const blockBlobFields = txEffectsInBlocks.map((blockTxEffects)=>getBlockBlobFields(blockTxEffects)).flat();
5
- const totalNumBlobFields = blockBlobFields.length + 1; // +1 for the prefix indicating the number of total blob fields in a checkpoint.
6
- return [
7
- new Fr(totalNumBlobFields)
8
- ].concat(blockBlobFields);
9
- }
@@ -1,10 +0,0 @@
1
- import { Fr } from '@aztec/foundation/fields';
2
-
3
- import { getBlockBlobFields } from '../block/body.js';
4
- import type { TxEffect } from '../tx/tx_effect.js';
5
-
6
- export function getCheckpointBlobFields(txEffectsInBlocks: TxEffect[][]) {
7
- const blockBlobFields = txEffectsInBlocks.map(blockTxEffects => getBlockBlobFields(blockTxEffects)).flat();
8
- const totalNumBlobFields = blockBlobFields.length + 1; // +1 for the prefix indicating the number of total blob fields in a checkpoint.
9
- return [new Fr(totalNumBlobFields)].concat(blockBlobFields);
10
- }