@aztec/sequencer-client 0.26.6 → 0.27.1

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 (33) hide show
  1. package/dest/block_builder/solo_block_builder.d.ts.map +1 -1
  2. package/dest/block_builder/solo_block_builder.js +6 -25
  3. package/dest/config.d.ts.map +1 -1
  4. package/dest/config.js +2 -5
  5. package/dest/publisher/l1-publisher.d.ts +1 -21
  6. package/dest/publisher/l1-publisher.d.ts.map +1 -1
  7. package/dest/publisher/l1-publisher.js +1 -55
  8. package/dest/publisher/viem-tx-sender.d.ts +1 -10
  9. package/dest/publisher/viem-tx-sender.d.ts.map +1 -1
  10. package/dest/publisher/viem-tx-sender.js +2 -41
  11. package/dest/sequencer/abstract_phase_manager.d.ts.map +1 -1
  12. package/dest/sequencer/abstract_phase_manager.js +6 -4
  13. package/dest/sequencer/hints_builder.d.ts +9 -3
  14. package/dest/sequencer/hints_builder.d.ts.map +1 -1
  15. package/dest/sequencer/hints_builder.js +26 -5
  16. package/dest/sequencer/processed_tx.d.ts +1 -1
  17. package/dest/sequencer/processed_tx.d.ts.map +1 -1
  18. package/dest/sequencer/processed_tx.js +3 -5
  19. package/dest/sequencer/sequencer.d.ts +0 -6
  20. package/dest/sequencer/sequencer.d.ts.map +1 -1
  21. package/dest/sequencer/sequencer.js +1 -26
  22. package/dest/simulator/public_executor.d.ts.map +1 -1
  23. package/dest/simulator/public_executor.js +1 -15
  24. package/package.json +13 -13
  25. package/src/block_builder/solo_block_builder.ts +11 -45
  26. package/src/config.ts +0 -4
  27. package/src/publisher/l1-publisher.ts +1 -85
  28. package/src/publisher/viem-tx-sender.ts +2 -52
  29. package/src/sequencer/abstract_phase_manager.ts +17 -2
  30. package/src/sequencer/hints_builder.ts +42 -6
  31. package/src/sequencer/processed_tx.ts +2 -18
  32. package/src/sequencer/sequencer.ts +0 -35
  33. package/src/simulator/public_executor.ts +0 -20
@@ -5,8 +5,6 @@ import {
5
5
  AppendOnlyTreeSnapshot,
6
6
  BaseOrMergeRollupPublicInputs,
7
7
  BaseRollupInputs,
8
- CONTRACT_SUBTREE_HEIGHT,
9
- CONTRACT_SUBTREE_SIBLING_PATH_LENGTH,
10
8
  ConstantRollupData,
11
9
  GlobalVariables,
12
10
  L1_TO_L2_MSG_SUBTREE_HEIGHT,
@@ -137,9 +135,6 @@ export class SoloBlockBuilder implements BlockBuilder {
137
135
  if (txHeader.state.partial.nullifierTree.isZero()) {
138
136
  throw new Error(`Empty nullifier tree in tx: ${toFriendlyJSON(tx)}`);
139
137
  }
140
- if (txHeader.state.partial.contractTree.isZero()) {
141
- throw new Error(`Empty contract tree in tx: ${toFriendlyJSON(tx)}`);
142
- }
143
138
  if (txHeader.state.partial.publicDataTree.isZero()) {
144
139
  throw new Error(`Empty public data tree in tx: ${toFriendlyJSON(tx)}`);
145
140
  }
@@ -171,14 +166,11 @@ export class SoloBlockBuilder implements BlockBuilder {
171
166
  for (const tx of txs) {
172
167
  const input = await this.buildBaseRollupInput(tx, globalVariables);
173
168
  baseRollupInputs.push(input);
174
- const promises = [
175
- MerkleTreeId.NOTE_HASH_TREE,
176
- MerkleTreeId.CONTRACT_TREE,
177
- MerkleTreeId.NULLIFIER_TREE,
178
- MerkleTreeId.PUBLIC_DATA_TREE,
179
- ].map(async (id: MerkleTreeId) => {
180
- return { key: id, value: await this.getTreeSnapshot(id) };
181
- });
169
+ const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(
170
+ async (id: MerkleTreeId) => {
171
+ return { key: id, value: await this.getTreeSnapshot(id) };
172
+ },
173
+ );
182
174
  const snapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot> = new Map(
183
175
  (await Promise.all(promises)).map(obj => [obj.key, obj.value]),
184
176
  );
@@ -316,11 +308,6 @@ export class SoloBlockBuilder implements BlockBuilder {
316
308
  partialState.nullifierTree,
317
309
  'NullifierTree',
318
310
  );
319
- this.validateSimulatedTree(
320
- treeSnapshots.get(MerkleTreeId.CONTRACT_TREE)!,
321
- partialState.contractTree,
322
- 'ContractTree',
323
- );
324
311
  this.validateSimulatedTree(
325
312
  treeSnapshots.get(MerkleTreeId.PUBLIC_DATA_TREE)!,
326
313
  partialState.publicDataTree,
@@ -329,14 +316,11 @@ export class SoloBlockBuilder implements BlockBuilder {
329
316
  }
330
317
 
331
318
  protected async validateState(state: StateReference) {
332
- const promises = [
333
- MerkleTreeId.NOTE_HASH_TREE,
334
- MerkleTreeId.CONTRACT_TREE,
335
- MerkleTreeId.NULLIFIER_TREE,
336
- MerkleTreeId.PUBLIC_DATA_TREE,
337
- ].map(async (id: MerkleTreeId) => {
338
- return { key: id, value: await this.getTreeSnapshot(id) };
339
- });
319
+ const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(
320
+ async (id: MerkleTreeId) => {
321
+ return { key: id, value: await this.getTreeSnapshot(id) };
322
+ },
323
+ );
340
324
  const snapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot> = new Map(
341
325
  (await Promise.all(promises)).map(obj => [obj.key, obj.value]),
342
326
  );
@@ -636,7 +620,6 @@ export class SoloBlockBuilder implements BlockBuilder {
636
620
  const start = new PartialStateReference(
637
621
  await this.getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE),
638
622
  await this.getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE),
639
- await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE),
640
623
  await this.getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE),
641
624
  );
642
625
 
@@ -650,25 +633,9 @@ export class SoloBlockBuilder implements BlockBuilder {
650
633
  i < noteHashSubtreeSiblingPathArray.length ? noteHashSubtreeSiblingPathArray[i] : Fr.ZERO,
651
634
  );
652
635
 
653
- const contractSubtreeSiblingPathArray = await this.getSubtreeSiblingPath(
654
- MerkleTreeId.CONTRACT_TREE,
655
- CONTRACT_SUBTREE_HEIGHT,
656
- );
657
-
658
- const contractSubtreeSiblingPath = makeTuple(CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, i =>
659
- i < contractSubtreeSiblingPathArray.length ? contractSubtreeSiblingPathArray[i] : Fr.ZERO,
660
- );
661
-
662
- // Update the contract and note hash trees with the new items being inserted to get the new roots
636
+ // Update the note hash trees with the new items being inserted to get the new roots
663
637
  // that will be used by the next iteration of the base rollup circuit, skipping the empty ones
664
- const newContracts = tx.data.combinedData.newContracts.map(cd => cd.hash());
665
638
  const newNoteHashes = tx.data.combinedData.newNoteHashes.map(x => x.value.toBuffer());
666
-
667
- await this.db.appendLeaves(
668
- MerkleTreeId.CONTRACT_TREE,
669
- newContracts.map(x => x.toBuffer()),
670
- );
671
-
672
639
  await this.db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, newNoteHashes);
673
640
 
674
641
  // The read witnesses for a given TX should be generated before the writes of the same TX are applied.
@@ -720,7 +687,6 @@ export class SoloBlockBuilder implements BlockBuilder {
720
687
  sortedNullifierIndexes: makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
721
688
  noteHashSubtreeSiblingPath,
722
689
  nullifierSubtreeSiblingPath,
723
- contractSubtreeSiblingPath,
724
690
  publicDataSiblingPath,
725
691
  });
726
692
 
package/src/config.ts CHANGED
@@ -44,7 +44,6 @@ export function getConfigEnvVars(): SequencerClientConfig {
44
44
  ROLLUP_CONTRACT_ADDRESS,
45
45
  REGISTRY_CONTRACT_ADDRESS,
46
46
  INBOX_CONTRACT_ADDRESS,
47
- CONTRACT_DEPLOYMENT_EMITTER_ADDRESS,
48
47
  OUTBOX_CONTRACT_ADDRESS,
49
48
  COINBASE,
50
49
  FEE_RECIPIENT,
@@ -64,9 +63,6 @@ export function getConfigEnvVars(): SequencerClientConfig {
64
63
  registryAddress: REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO,
65
64
  inboxAddress: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
66
65
  outboxAddress: OUTBOX_CONTRACT_ADDRESS ? EthAddress.fromString(OUTBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
67
- contractDeploymentEmitterAddress: CONTRACT_DEPLOYMENT_EMITTER_ADDRESS
68
- ? EthAddress.fromString(CONTRACT_DEPLOYMENT_EMITTER_ADDRESS)
69
- : EthAddress.ZERO,
70
66
  };
71
67
 
72
68
  return {
@@ -1,4 +1,4 @@
1
- import { ExtendedContractData, L2Block } from '@aztec/circuit-types';
1
+ import { L2Block } from '@aztec/circuit-types';
2
2
  import { L1PublishStats } from '@aztec/circuit-types/stats';
3
3
  import { createDebugLogger } from '@aztec/foundation/log';
4
4
  import { InterruptibleSleep } from '@aztec/foundation/sleep';
@@ -54,22 +54,6 @@ export interface L1PublisherTxSender {
54
54
  */
55
55
  sendProcessTx(encodedData: L1ProcessArgs): Promise<string | undefined>;
56
56
 
57
- /**
58
- * Sends a tx to the contract deployment emitter contract with contract deployment data such as bytecode. Returns once the tx has been mined.
59
- * @param l2BlockNum - Number of the L2 block that owns this encrypted logs.
60
- * @param l2BlockHash - The hash of the block corresponding to this data.
61
- * @param partialAddresses - The partial addresses of the deployed contract
62
- * @param publicKeys - The public keys of the deployed contract
63
- * @param newExtendedContractData - Data to publish.
64
- * @returns The hash of the mined tx.
65
- * @remarks Partial addresses, public keys and contract data has to be in the same order. Read more {@link https://docs.aztec.network/concepts/foundation/accounts/keys#addresses-partial-addresses-and-public-keys | here}.
66
- */
67
- sendEmitContractDeploymentTx(
68
- l2BlockNum: number,
69
- l2BlockHash: Buffer,
70
- newExtendedContractData: ExtendedContractData[],
71
- ): Promise<(string | undefined)[]>;
72
-
73
57
  /**
74
58
  * Returns a tx receipt if the tx has been mined.
75
59
  * @param txHash - Hash of the tx to look for.
@@ -111,16 +95,6 @@ export type L1ProcessArgs = {
111
95
  proof: Buffer;
112
96
  };
113
97
 
114
- /**
115
- * Helper function to filter out undefined items from an array.
116
- * Also asserts the resulting array is of type <T>.
117
- * @param item - An item from an array to check if undefined or not.
118
- * @returns True if the item is not undefined.
119
- */
120
- function isNotUndefined<T>(item: T | undefined): item is T {
121
- return item !== undefined;
122
- }
123
-
124
98
  /**
125
99
  * Publishes L2 blocks to L1. This implementation does *not* retry a transaction in
126
100
  * the event of network congestion, but should work for local development.
@@ -234,49 +208,6 @@ export class L1Publisher implements L2BlockReceiver {
234
208
  return false;
235
209
  }
236
210
 
237
- /**
238
- * Publishes new contract data to L1.
239
- * @param l2BlockNum - The L2 block number that the new contracts were deployed on.
240
- * @param l2BlockHash - The hash of the block corresponding to this data.
241
- * @param contractData - The new contract data to publish.
242
- * @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise.
243
- */
244
- public async processNewContractData(l2BlockNum: number, l2BlockHash: Buffer, contractData: ExtendedContractData[]) {
245
- let _contractData: ExtendedContractData[] = [];
246
- while (!this.interrupted) {
247
- const arr = _contractData.length ? _contractData : contractData;
248
- const txHashes = await this.sendEmitNewContractDataTx(l2BlockNum, l2BlockHash, arr);
249
- if (!txHashes) {
250
- break;
251
- }
252
- // filter successful txs
253
- _contractData = arr.filter((_, i) => !!txHashes[i]);
254
-
255
- const receipts = await Promise.all(
256
- txHashes.filter(isNotUndefined).map(txHash => this.getTransactionReceipt(txHash)),
257
- );
258
- if (!receipts?.length) {
259
- break;
260
- }
261
-
262
- // ALL Txs were mined successfully
263
- if (receipts.length === contractData.length && receipts.every(r => r?.status)) {
264
- return true;
265
- }
266
-
267
- this.log(
268
- `Transaction status failed: ${receipts
269
- .filter(r => !r?.status)
270
- .map(r => r?.transactionHash)
271
- .join(',')}`,
272
- );
273
- await this.sleepOrInterrupted();
274
- }
275
-
276
- this.log('L2 block data syncing interrupted while processing contract data.');
277
- return false;
278
- }
279
-
280
211
  /**
281
212
  * Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
282
213
  * Be warned, the call may return false even if the tx subsequently gets successfully mined.
@@ -330,21 +261,6 @@ export class L1Publisher implements L2BlockReceiver {
330
261
  }
331
262
  }
332
263
 
333
- private async sendEmitNewContractDataTx(
334
- l2BlockNum: number,
335
- l2BlockHash: Buffer,
336
- newExtendedContractData: ExtendedContractData[],
337
- ) {
338
- while (!this.interrupted) {
339
- try {
340
- return await this.txSender.sendEmitContractDeploymentTx(l2BlockNum, l2BlockHash, newExtendedContractData);
341
- } catch (err) {
342
- this.log.error(`Error sending contract data to L1`, err);
343
- await this.sleepOrInterrupted();
344
- }
345
- }
346
- }
347
-
348
264
  private async getTransactionReceipt(txHash: string): Promise<MinimalTransactionReceipt | undefined> {
349
265
  while (!this.interrupted) {
350
266
  try {
@@ -1,8 +1,7 @@
1
- import { ExtendedContractData, L2Block } from '@aztec/circuit-types';
2
- import { BLOB_SIZE_IN_BYTES } from '@aztec/circuits.js/constants';
1
+ import { L2Block } from '@aztec/circuit-types';
3
2
  import { createEthereumChain } from '@aztec/ethereum';
4
3
  import { createDebugLogger } from '@aztec/foundation/log';
5
- import { AvailabilityOracleAbi, ContractDeploymentEmitterAbi, RollupAbi } from '@aztec/l1-artifacts';
4
+ import { AvailabilityOracleAbi, RollupAbi } from '@aztec/l1-artifacts';
6
5
 
7
6
  import {
8
7
  GetContractReturnType,
@@ -40,10 +39,6 @@ export class ViemTxSender implements L1PublisherTxSender {
40
39
  typeof RollupAbi,
41
40
  WalletClient<HttpTransport, chains.Chain, PrivateKeyAccount>
42
41
  >;
43
- private contractDeploymentEmitterContract: GetContractReturnType<
44
- typeof ContractDeploymentEmitterAbi,
45
- WalletClient<HttpTransport, chains.Chain, PrivateKeyAccount>
46
- >;
47
42
 
48
43
  private log = createDebugLogger('aztec:sequencer:viem-tx-sender');
49
44
  private publicClient: PublicClient<HttpTransport, chains.Chain>;
@@ -74,11 +69,6 @@ export class ViemTxSender implements L1PublisherTxSender {
74
69
  abi: RollupAbi,
75
70
  client: walletClient,
76
71
  });
77
- this.contractDeploymentEmitterContract = getContract({
78
- address: getAddress(l1Contracts.contractDeploymentEmitterAddress.toString()),
79
- abi: ContractDeploymentEmitterAbi,
80
- client: walletClient,
81
- });
82
72
  }
83
73
 
84
74
  async getCurrentArchive(): Promise<Buffer> {
@@ -169,46 +159,6 @@ export class ViemTxSender implements L1PublisherTxSender {
169
159
  return hash;
170
160
  }
171
161
 
172
- /**
173
- * Sends a tx to the contract deployment emitter contract with contract deployment data such as bytecode. Returns once the tx has been mined.
174
- * @param l2BlockNum - Number of the L2 block that owns this encrypted logs.
175
- * @param l2BlockHash - The hash of the block corresponding to this data.
176
- * @param newExtendedContractData - Data to publish.
177
- * @returns The hash of the mined tx.
178
- */
179
- async sendEmitContractDeploymentTx(
180
- l2BlockNum: number,
181
- l2BlockHash: Buffer,
182
- newExtendedContractData: ExtendedContractData[],
183
- ): Promise<(string | undefined)[]> {
184
- const hashes: string[] = [];
185
- for (const extendedContractData of newExtendedContractData) {
186
- const args = [
187
- BigInt(l2BlockNum),
188
- extendedContractData.contractData.contractAddress.toString() as Hex,
189
- extendedContractData.contractData.portalContractAddress.toString() as Hex,
190
- `0x${l2BlockHash.toString('hex')}`,
191
- extendedContractData.contractClassId.toString(),
192
- extendedContractData.saltedInitializationHash.toString(),
193
- extendedContractData.publicKeyHash.toString(),
194
- `0x${extendedContractData.bytecode.toString('hex')}`,
195
- ] as const;
196
-
197
- const codeSize = extendedContractData.bytecode.length;
198
- this.log(`Bytecode is ${codeSize} bytes and require ${codeSize / BLOB_SIZE_IN_BYTES} blobs`);
199
-
200
- const gas = await this.contractDeploymentEmitterContract.estimateGas.emitContractDeployment(args, {
201
- account: this.account,
202
- });
203
- const hash = await this.contractDeploymentEmitterContract.write.emitContractDeployment(args, {
204
- gas,
205
- account: this.account,
206
- });
207
- hashes.push(hash);
208
- }
209
- return hashes;
210
- }
211
-
212
162
  /**
213
163
  * Gets the chain object for the given chain id.
214
164
  * @param chainId - Chain id of the target EVM chain.
@@ -13,6 +13,7 @@ import {
13
13
  MAX_NEW_NULLIFIERS_PER_CALL,
14
14
  MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX,
15
15
  MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
16
+ MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,
16
17
  MAX_NULLIFIER_READ_REQUESTS_PER_CALL,
17
18
  MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
18
19
  MAX_PUBLIC_DATA_READS_PER_CALL,
@@ -264,13 +265,22 @@ export abstract class AbstractPhaseManager {
264
265
 
265
266
  if (this.phase === PublicKernelPhase.TAIL) {
266
267
  const { endNonRevertibleData, end } = previousOutput;
267
- const nullifierReadRequestResetHints = await this.hintsBuilder.getNullifierReadRequestResetHints(
268
+ const nullifierReadRequestHints = await this.hintsBuilder.getNullifierReadRequestHints(
268
269
  endNonRevertibleData.nullifierReadRequests,
269
270
  end.nullifierReadRequests,
270
271
  endNonRevertibleData.newNullifiers,
271
272
  end.newNullifiers,
272
273
  );
273
- const inputs = new PublicKernelTailCircuitPrivateInputs(previousKernel, nullifierReadRequestResetHints);
274
+ const nullifierNonExistentReadRequestHints = await this.hintsBuilder.getNullifierNonExistentReadRequestHints(
275
+ endNonRevertibleData.nullifierNonExistentReadRequests,
276
+ endNonRevertibleData.newNullifiers,
277
+ end.newNullifiers,
278
+ );
279
+ const inputs = new PublicKernelTailCircuitPrivateInputs(
280
+ previousKernel,
281
+ nullifierReadRequestHints,
282
+ nullifierNonExistentReadRequestHints,
283
+ );
274
284
  return this.publicKernel.publicKernelCircuitTail(inputs);
275
285
  }
276
286
 
@@ -329,6 +339,11 @@ export abstract class AbstractPhaseManager {
329
339
  ReadRequest.empty(),
330
340
  MAX_NULLIFIER_READ_REQUESTS_PER_CALL,
331
341
  ),
342
+ nullifierNonExistentReadRequests: padArrayEnd(
343
+ result.nullifierNonExistentReadRequests,
344
+ ReadRequest.empty(),
345
+ MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,
346
+ ),
332
347
  contractStorageReads: padArrayEnd(
333
348
  result.contractStorageReads,
334
349
  ContractStorageRead.empty(),
@@ -3,14 +3,15 @@ import {
3
3
  Fr,
4
4
  MAX_NEW_NULLIFIERS_PER_TX,
5
5
  MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX,
6
+ MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX,
6
7
  MAX_NULLIFIER_READ_REQUESTS_PER_TX,
7
8
  MAX_REVERTIBLE_NULLIFIERS_PER_TX,
8
9
  MembershipWitness,
9
10
  NULLIFIER_TREE_HEIGHT,
10
- NullifierLeafPreimage,
11
11
  ReadRequestContext,
12
12
  SideEffectLinkedToNoteHash,
13
- buildNullifierReadRequestResetHints,
13
+ buildNullifierNonExistentReadRequestHints,
14
+ buildNullifierReadRequestHints,
14
15
  concatAccumulatedData,
15
16
  mergeAccumulatedData,
16
17
  } from '@aztec/circuits.js';
@@ -20,13 +21,13 @@ import { MerkleTreeOperations } from '@aztec/world-state';
20
21
  export class HintsBuilder {
21
22
  constructor(private db: MerkleTreeOperations) {}
22
23
 
23
- getNullifierReadRequestResetHints(
24
+ getNullifierReadRequestHints(
24
25
  nullifierReadRequestsNonRevertible: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
25
26
  nullifierReadRequestsRevertible: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
26
27
  nullifiersNonRevertible: Tuple<SideEffectLinkedToNoteHash, typeof MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX>,
27
28
  nullifiersRevertible: Tuple<SideEffectLinkedToNoteHash, typeof MAX_REVERTIBLE_NULLIFIERS_PER_TX>,
28
29
  ) {
29
- return buildNullifierReadRequestResetHints(
30
+ return buildNullifierReadRequestHints(
30
31
  this,
31
32
  mergeAccumulatedData(
32
33
  MAX_NULLIFIER_READ_REQUESTS_PER_TX,
@@ -37,19 +38,54 @@ export class HintsBuilder {
37
38
  );
38
39
  }
39
40
 
41
+ getNullifierNonExistentReadRequestHints(
42
+ nullifierNonExistentReadRequests: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX>,
43
+ nullifiersNonRevertible: Tuple<SideEffectLinkedToNoteHash, typeof MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX>,
44
+ nullifiersRevertible: Tuple<SideEffectLinkedToNoteHash, typeof MAX_REVERTIBLE_NULLIFIERS_PER_TX>,
45
+ ) {
46
+ const pendingNullifiers = concatAccumulatedData(
47
+ MAX_NEW_NULLIFIERS_PER_TX,
48
+ nullifiersNonRevertible,
49
+ nullifiersRevertible,
50
+ );
51
+ return buildNullifierNonExistentReadRequestHints(this, nullifierNonExistentReadRequests, pendingNullifiers);
52
+ }
53
+
40
54
  async getNullifierMembershipWitness(nullifier: Fr) {
41
55
  const index = await this.db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
42
56
  if (index === undefined) {
43
57
  return;
44
58
  }
45
59
 
46
- const siblingPath = await this.db.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, index);
60
+ return this.getNullifierMembershipWitnessWithPreimage(index);
61
+ }
62
+
63
+ async getLowNullifierMembershipWitness(nullifier: Fr) {
64
+ const res = await this.db.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
65
+ if (res === undefined) {
66
+ throw new Error(`Cannot find the low leaf for nullifier ${nullifier.toBigInt()}.`);
67
+ }
68
+
69
+ const { index, alreadyPresent } = res;
70
+ if (alreadyPresent) {
71
+ throw new Error(`Nullifier ${nullifier.toBigInt()} already exists in the tree.`);
72
+ }
73
+
74
+ return this.getNullifierMembershipWitnessWithPreimage(index);
75
+ }
76
+
77
+ private async getNullifierMembershipWitnessWithPreimage(index: bigint) {
78
+ const siblingPath = await this.db.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(MerkleTreeId.NULLIFIER_TREE, index);
47
79
  const membershipWitness = new MembershipWitness(
48
80
  NULLIFIER_TREE_HEIGHT,
49
81
  index,
50
82
  siblingPath.toTuple<typeof NULLIFIER_TREE_HEIGHT>(),
51
83
  );
52
- const leafPreimage = (await this.db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))! as NullifierLeafPreimage;
84
+
85
+ const leafPreimage = await this.db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
86
+ if (!leafPreimage) {
87
+ throw new Error(`Cannot find the leaf preimage at index ${index}.`);
88
+ }
53
89
 
54
90
  return { membershipWitness, leafPreimage };
55
91
  }
@@ -1,17 +1,7 @@
1
- import {
2
- ContractData,
3
- ExtendedContractData,
4
- PublicDataWrite,
5
- SimulationError,
6
- Tx,
7
- TxEffect,
8
- TxHash,
9
- TxL2Logs,
10
- } from '@aztec/circuit-types';
1
+ import { PublicDataWrite, SimulationError, Tx, TxEffect, TxHash, TxL2Logs } from '@aztec/circuit-types';
11
2
  import {
12
3
  Fr,
13
4
  Header,
14
- MAX_NEW_CONTRACTS_PER_TX,
15
5
  MAX_NEW_NOTE_HASHES_PER_TX,
16
6
  MAX_NEW_NULLIFIERS_PER_TX,
17
7
  MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
@@ -29,7 +19,7 @@ import { Tuple, fromFieldsTuple } from '@aztec/foundation/serialize';
29
19
  * Represents a tx that has been processed by the sequencer public processor,
30
20
  * so its kernel circuit public inputs are filled in.
31
21
  */
32
- export type ProcessedTx = Pick<Tx, 'proof' | 'encryptedLogs' | 'unencryptedLogs' | 'newContracts'> & {
22
+ export type ProcessedTx = Pick<Tx, 'proof' | 'encryptedLogs' | 'unencryptedLogs'> & {
33
23
  /**
34
24
  * Output of the public kernel circuit for this tx.
35
25
  */
@@ -153,7 +143,6 @@ export function makeProcessedTx(
153
143
  proof: previousProof,
154
144
  encryptedLogs: revertReason ? new TxL2Logs([]) : tx.encryptedLogs,
155
145
  unencryptedLogs: revertReason ? new TxL2Logs([]) : tx.unencryptedLogs,
156
- newContracts: revertReason ? [ExtendedContractData.empty()] : tx.newContracts,
157
146
  isEmpty: false,
158
147
  revertReason,
159
148
  };
@@ -177,7 +166,6 @@ export function makeEmptyProcessedTx(header: Header, chainId: Fr, version: Fr):
177
166
  unencryptedLogs: new TxL2Logs([]),
178
167
  data: emptyKernelOutput,
179
168
  proof: emptyProof,
180
- newContracts: [ExtendedContractData.empty()],
181
169
  isEmpty: true,
182
170
  revertReason: undefined,
183
171
  };
@@ -195,10 +183,6 @@ export function toTxEffect(tx: ProcessedTx): TxEffect {
195
183
  PublicDataWrite,
196
184
  typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
197
185
  >,
198
- tx.data.combinedData.newContracts.map(cd => cd.hash()) as Tuple<Fr, typeof MAX_NEW_CONTRACTS_PER_TX>,
199
- tx.data.combinedData.newContracts.map(
200
- cd => new ContractData(cd.contractAddress, cd.portalContractAddress),
201
- ) as Tuple<ContractData, typeof MAX_NEW_CONTRACTS_PER_TX>,
202
186
  tx.encryptedLogs || new TxL2Logs([]),
203
187
  tx.unencryptedLogs || new TxL2Logs([]),
204
188
  );
@@ -227,10 +227,6 @@ export class Sequencer {
227
227
 
228
228
  await assertBlockHeight();
229
229
 
230
- await this.publishExtendedContractData(processedValidTxs, block);
231
-
232
- await assertBlockHeight();
233
-
234
230
  await this.publishL2Block(block);
235
231
  this.log.info(`Submitted rollup block ${block.number} with ${processedValidTxs.length} transactions`);
236
232
  } catch (err) {
@@ -239,37 +235,6 @@ export class Sequencer {
239
235
  }
240
236
  }
241
237
 
242
- /**
243
- * Gets new extended contract data from the txs and publishes it on chain.
244
- * @param validTxs - The set of real transactions being published as part of the block.
245
- * @param block - The L2Block to be published.
246
- */
247
- protected async publishExtendedContractData(validTxs: ProcessedTx[], block: L2Block) {
248
- // Publishes contract data for txs to the network and awaits the tx to be mined
249
- this.state = SequencerState.PUBLISHING_CONTRACT_DATA;
250
- const newContracts = validTxs.flatMap(tx => tx.newContracts).filter(cd => !cd.isEmpty());
251
-
252
- if (newContracts.length === 0) {
253
- this.log.debug(`No new contracts to publish in block ${block.number}`);
254
- return;
255
- }
256
-
257
- const txsEffectsHash = block.body.getTxsEffectsHash();
258
- this.log.info(`Publishing ${newContracts.length} contracts in block ${block.number}`);
259
-
260
- const publishedContractData = await this.publisher.processNewContractData(
261
- block.number,
262
- txsEffectsHash,
263
- newContracts,
264
- );
265
-
266
- if (publishedContractData) {
267
- this.log(`Successfully published new contract data for block ${block.number}`);
268
- } else if (!publishedContractData && newContracts.length) {
269
- this.log(`Failed to publish new contract data for block ${block.number}`);
270
- }
271
- }
272
-
273
238
  /**
274
239
  * Publishes the L2Block to the rollup contract.
275
240
  * @param block - The L2Block to be published.
@@ -45,16 +45,6 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB {
45
45
  * @param tx - The transaction to add contracts from.
46
46
  */
47
47
  public addNewContracts(tx: Tx): Promise<void> {
48
- for (const contract of tx.newContracts) {
49
- const contractAddress = contract.contractData.contractAddress;
50
-
51
- if (contractAddress.isZero()) {
52
- continue;
53
- }
54
-
55
- this.cache.set(contractAddress.toString(), contract);
56
- }
57
-
58
48
  // Extract contract class and instance data from logs and add to cache for this block
59
49
  const logs = tx.unencryptedLogs.unrollLogs().map(UnencryptedL2Log.fromBuffer);
60
50
  ContractClassRegisteredEvent.fromLogs(logs, ClassRegistererAddress).forEach(e => {
@@ -76,16 +66,6 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB {
76
66
  * @param tx - The tx's contracts to be removed
77
67
  */
78
68
  public removeNewContracts(tx: Tx): Promise<void> {
79
- for (const contract of tx.newContracts) {
80
- const contractAddress = contract.contractData.contractAddress;
81
-
82
- if (contractAddress.isZero()) {
83
- continue;
84
- }
85
-
86
- this.cache.delete(contractAddress.toString());
87
- }
88
-
89
69
  // TODO(@spalladino): Can this inadvertently delete a valid contract added by another tx?
90
70
  // Let's say we have two txs adding the same contract on the same block. If the 2nd one reverts,
91
71
  // wouldn't that accidentally remove the contract added on the first one?