@aztec/txe 0.0.1-commit.7d4e6cd → 0.0.1-commit.9372f48

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 (48) hide show
  1. package/dest/constants.d.ts +1 -2
  2. package/dest/constants.d.ts.map +1 -1
  3. package/dest/constants.js +0 -1
  4. package/dest/oracle/interfaces.d.ts +3 -3
  5. package/dest/oracle/interfaces.d.ts.map +1 -1
  6. package/dest/oracle/txe_oracle_public_context.d.ts +3 -3
  7. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  8. package/dest/oracle/txe_oracle_public_context.js +6 -6
  9. package/dest/oracle/txe_oracle_top_level_context.d.ts +3 -2
  10. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  11. package/dest/oracle/txe_oracle_top_level_context.js +30 -22
  12. package/dest/rpc_translator.d.ts +16 -10
  13. package/dest/rpc_translator.d.ts.map +1 -1
  14. package/dest/rpc_translator.js +53 -40
  15. package/dest/state_machine/archiver.d.ts +20 -69
  16. package/dest/state_machine/archiver.d.ts.map +1 -1
  17. package/dest/state_machine/archiver.js +34 -178
  18. package/dest/state_machine/index.d.ts +1 -1
  19. package/dest/state_machine/index.d.ts.map +1 -1
  20. package/dest/state_machine/index.js +22 -4
  21. package/dest/state_machine/mock_epoch_cache.d.ts +6 -6
  22. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  23. package/dest/state_machine/mock_epoch_cache.js +7 -7
  24. package/dest/state_machine/synchronizer.d.ts +3 -3
  25. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  26. package/dest/txe_session.d.ts +5 -3
  27. package/dest/txe_session.d.ts.map +1 -1
  28. package/dest/txe_session.js +31 -15
  29. package/dest/util/encoding.d.ts +17 -17
  30. package/dest/utils/block_creation.d.ts +4 -4
  31. package/dest/utils/block_creation.d.ts.map +1 -1
  32. package/dest/utils/block_creation.js +16 -4
  33. package/dest/utils/tx_effect_creation.d.ts +2 -3
  34. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  35. package/dest/utils/tx_effect_creation.js +3 -6
  36. package/package.json +16 -16
  37. package/src/constants.ts +0 -1
  38. package/src/oracle/interfaces.ts +2 -2
  39. package/src/oracle/txe_oracle_public_context.ts +6 -8
  40. package/src/oracle/txe_oracle_top_level_context.ts +50 -24
  41. package/src/rpc_translator.ts +62 -47
  42. package/src/state_machine/archiver.ts +35 -234
  43. package/src/state_machine/index.ts +26 -4
  44. package/src/state_machine/mock_epoch_cache.ts +6 -11
  45. package/src/state_machine/synchronizer.ts +2 -2
  46. package/src/txe_session.ts +38 -24
  47. package/src/utils/block_creation.ts +17 -16
  48. package/src/utils/tx_effect_creation.ts +3 -11
@@ -1,216 +1,48 @@
1
- import { ArchiverStoreHelper, KVArchiverDataStore } from '@aztec/archiver';
1
+ import { ArchiverDataSourceBase, ArchiverDataStoreUpdater, KVArchiverDataStore } from '@aztec/archiver';
2
2
  import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
3
- import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { CheckpointNumber, type EpochNumber, type SlotNumber } from '@aztec/foundation/branded-types';
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import type { EthAddress } from '@aztec/foundation/eth-address';
6
- import { isDefined } from '@aztec/foundation/types';
7
6
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
8
- import type { AztecAddress } from '@aztec/stdlib/aztec-address';
9
- import {
10
- type CheckpointId,
11
- CommitteeAttestation,
12
- L2Block,
13
- type L2BlockId,
14
- type L2BlockNew,
15
- type L2BlockSource,
16
- type L2TipId,
17
- type L2Tips,
18
- PublishedL2Block,
19
- type ValidateCheckpointResult,
20
- } from '@aztec/stdlib/block';
21
- import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
22
- import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
7
+ import type { CheckpointId, L2BlockId, L2TipId, L2Tips, ValidateCheckpointResult } from '@aztec/stdlib/block';
8
+ import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
23
9
  import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
24
- import type { BlockHeader } from '@aztec/stdlib/tx';
25
- import type { UInt64 } from '@aztec/stdlib/types';
26
10
 
27
- // We are extending the ArchiverDataStoreHelper here because it provides most of the endpoints needed by the
28
- // node for reading from and writing to state, without needing any of the extra overhead that the Archiver itself
29
- // requires (i.e. an L1 client)
30
- export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
31
- constructor(db: AztecAsyncKVStore) {
32
- super(new KVArchiverDataStore(db, 9999));
33
- }
34
-
35
- public async getBlock(number: BlockNumber): Promise<L2Block | undefined> {
36
- if (number === 0) {
37
- return undefined;
38
- }
39
- const publishedBlocks = await this.getPublishedBlocks(number, 1);
40
- if (publishedBlocks.length === 0) {
41
- return undefined;
42
- }
43
- return publishedBlocks[0].block;
44
- }
45
-
46
- public async getBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<L2Block[]> {
47
- const publishedBlocks = await this.getPublishedBlocks(from, limit, proven);
48
- return publishedBlocks.map(x => x.block);
49
- }
50
-
51
- public override async addCheckpoints(
52
- checkpoints: PublishedCheckpoint[],
53
- _result?: ValidateCheckpointResult,
54
- ): Promise<boolean> {
55
- const allBlocks = checkpoints.flatMap(ch => ch.checkpoint.blocks);
56
- const opResults = await Promise.all([this.store.addLogs(allBlocks), this.store.addCheckpoints(checkpoints)]);
57
-
58
- return opResults.every(Boolean);
59
- }
60
-
61
- /**
62
- * Gets the number of the latest L2 block processed by the block source implementation.
63
- * @returns The number of the latest L2 block processed by the block source implementation.
64
- */
65
- public getBlockNumber(): Promise<BlockNumber> {
66
- return this.store.getLatestBlockNumber();
67
- }
68
-
69
- /**
70
- * Gets the number of the latest L2 block proven seen by the block source implementation.
71
- * @returns The number of the latest L2 block proven seen by the block source implementation.
72
- */
73
- public override getProvenBlockNumber(): Promise<BlockNumber> {
74
- return this.store.getProvenBlockNumber();
75
- }
76
-
77
- /**
78
- * Gets a published l2 block. If a negative number is passed, the block returned is the most recent.
79
- * @param number - The block number to return (inclusive).
80
- * @returns The requested L2 block.
81
- */
82
- public async getPublishedBlock(number: number): Promise<PublishedL2Block | undefined> {
83
- // If the number provided is -ve, then return the latest block.
84
- if (number < 0) {
85
- number = await this.store.getLatestBlockNumber();
86
- }
87
- if (number == 0) {
88
- return undefined;
89
- }
90
- const publishedBlocks = await this.retrievePublishedBlocks(BlockNumber(number), 1);
91
- return publishedBlocks.length === 0 ? undefined : publishedBlocks[0];
92
- }
93
-
94
- getPublishedBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
95
- return this.retrievePublishedBlocks(from, limit, proven);
96
- }
97
-
98
- async getL2BlocksNew(from: BlockNumber, limit: number, proven?: boolean): Promise<L2BlockNew[]> {
99
- const blocks = await this.store.getBlocks(from, limit);
11
+ /**
12
+ * TXE Archiver implementation.
13
+ * Provides most of the endpoints needed by the node for reading from and writing to state,
14
+ * without needing any of the extra overhead that the Archiver itself requires (i.e. an L1 client).
15
+ */
16
+ export class TXEArchiver extends ArchiverDataSourceBase {
17
+ private readonly updater = new ArchiverDataStoreUpdater(this.store);
100
18
 
101
- if (proven === true) {
102
- const provenBlockNumber = await this.store.getProvenBlockNumber();
103
- return blocks.filter(b => b.number <= provenBlockNumber);
104
- }
105
- return blocks;
106
- }
107
-
108
- private async retrievePublishedBlocks(
109
- from: BlockNumber,
110
- limit: number,
111
- proven?: boolean,
112
- ): Promise<PublishedL2Block[]> {
113
- const checkpoints = await this.store.getRangeOfCheckpoints(CheckpointNumber(from), limit);
114
- const provenCheckpointNumber = await this.store.getProvenCheckpointNumber();
115
- const blocks = (
116
- await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
117
- ).filter(isDefined);
118
-
119
- const olbBlocks: PublishedL2Block[] = [];
120
- for (let i = 0; i < checkpoints.length; i++) {
121
- const blockForCheckpoint = blocks[i][0];
122
- const checkpoint = checkpoints[i];
123
- if (proven === true && checkpoint.checkpointNumber > provenCheckpointNumber) {
124
- continue;
125
- }
126
- const oldCheckpoint = new Checkpoint(
127
- blockForCheckpoint.archive,
128
- checkpoint.header,
129
- [blockForCheckpoint],
130
- checkpoint.checkpointNumber,
131
- );
132
- const oldBlock = L2Block.fromCheckpoint(oldCheckpoint);
133
- const publishedBlock = new PublishedL2Block(
134
- oldBlock,
135
- checkpoint.l1,
136
- checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
137
- );
138
- olbBlocks.push(publishedBlock);
139
- }
140
- return olbBlocks;
141
- }
142
-
143
- /**
144
- * Gets an l2 block. If a negative number is passed, the block returned is the most recent.
145
- * @param number - The block number to return (inclusive).
146
- * @returns The requested L2 block.
147
- */
148
- public getL2Block(number: BlockNumber | 'latest'): Promise<L2Block | undefined> {
149
- return this.getPublishedBlock(number != 'latest' ? number : -1).then(b => b?.block);
150
- }
151
-
152
- /**
153
- * Gets an L2 block (new format).
154
- * @param number - The block number to return.
155
- * @returns The requested L2 block.
156
- */
157
- public getL2BlockNew(number: BlockNumber): Promise<L2BlockNew | undefined> {
158
- if (number === 0) {
159
- return Promise.resolve(undefined);
160
- }
161
- return this.store.getBlock(number);
162
- }
163
-
164
- /**
165
- * Gets an l2 block header.
166
- * @param number - The block number to return or 'latest' for the most recent one.
167
- * @returns The requested L2 block header.
168
- */
169
- public async getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
170
- if (number === 'latest') {
171
- number = await this.store.getLatestBlockNumber();
172
- }
173
- if (number === 0) {
174
- return undefined;
175
- }
176
- const headers = await this.store.getBlockHeaders(BlockNumber(number), 1);
177
- return headers.length === 0 ? undefined : headers[0];
178
- }
179
-
180
- public getBlockRange(from: number, limit: number, _proven?: boolean): Promise<L2Block[]> {
181
- return this.getPublishedBlocks(BlockNumber(from), limit).then(blocks => blocks.map(b => b.block));
182
- }
183
-
184
- public getPublishedCheckpoints(_from: CheckpointNumber, _limit: number): Promise<PublishedCheckpoint[]> {
185
- throw new Error('TXE Archiver does not implement "getPublishedCheckpoints"');
186
- }
187
-
188
- public getCheckpointByArchive(_archive: Fr): Promise<Checkpoint | undefined> {
189
- throw new Error('TXE Archiver does not implement "getCheckpointByArchive"');
19
+ constructor(db: AztecAsyncKVStore) {
20
+ const store = new KVArchiverDataStore(db, 9999, { epochDuration: 32 });
21
+ super(store);
190
22
  }
191
23
 
192
- public getL2SlotNumber(): Promise<SlotNumber | undefined> {
193
- throw new Error('TXE Archiver does not implement "getL2SlotNumber"');
24
+ public async addCheckpoints(checkpoints: PublishedCheckpoint[], result?: ValidateCheckpointResult): Promise<void> {
25
+ await this.updater.addCheckpoints(checkpoints, result);
194
26
  }
195
27
 
196
- public getL2EpochNumber(): Promise<EpochNumber> {
197
- throw new Error('TXE Archiver does not implement "getL2EpochNumber"');
28
+ public getRollupAddress(): Promise<EthAddress> {
29
+ throw new Error('TXE Archiver does not implement "getRollupAddress"');
198
30
  }
199
31
 
200
- public getCheckpointsForEpoch(_epochNumber: EpochNumber): Promise<Checkpoint[]> {
201
- throw new Error('TXE Archiver does not implement "getCheckpointsForEpoch"');
32
+ public getRegistryAddress(): Promise<EthAddress> {
33
+ throw new Error('TXE Archiver does not implement "getRegistryAddress"');
202
34
  }
203
35
 
204
- public getBlocksForEpoch(_epochNumber: EpochNumber): Promise<L2Block[]> {
205
- throw new Error('TXE Archiver does not implement "getBlocksForEpoch"');
36
+ public getL1Constants(): Promise<L1RollupConstants> {
37
+ throw new Error('TXE Archiver does not implement "getL1Constants"');
206
38
  }
207
39
 
208
- public getBlockHeadersForEpoch(_epochNumber: EpochNumber): Promise<BlockHeader[]> {
209
- throw new Error('TXE Archiver does not implement "getBlockHeadersForEpoch"');
40
+ public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
41
+ return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
210
42
  }
211
43
 
212
- public isEpochComplete(_epochNumber: EpochNumber): Promise<boolean> {
213
- throw new Error('TXE Archiver does not implement "isEpochComplete"');
44
+ public getL1Timestamp(): Promise<bigint | undefined> {
45
+ throw new Error('TXE Archiver does not implement "getL1Timestamp"');
214
46
  }
215
47
 
216
48
  public async getL2Tips(): Promise<L2Tips> {
@@ -227,7 +59,7 @@ export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
227
59
  if (!checkpointedBlock) {
228
60
  throw new Error(`L2Tips requested from TXE Archiver but no checkpointed block found for block number ${number}`);
229
61
  }
230
- const checkpoint = await this.store.getRangeOfCheckpoints(CheckpointNumber(number), 1);
62
+ const checkpoint = await this.store.getRangeOfCheckpoints(CheckpointNumber.fromBlockNumber(number), 1);
231
63
  if (checkpoint.length === 0) {
232
64
  throw new Error(`L2Tips requested from TXE Archiver but no checkpoint found for block number ${number}`);
233
65
  }
@@ -245,50 +77,19 @@ export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
245
77
  };
246
78
  }
247
79
 
248
- public getL1Constants(): Promise<L1RollupConstants> {
249
- throw new Error('TXE Archiver does not implement "getL2Constants"');
250
- }
251
-
252
- public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
253
- return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
254
- }
255
-
256
- public syncImmediate(): Promise<void> {
257
- throw new Error('TXE Archiver does not implement "syncImmediate"');
258
- }
259
-
260
- public getContract(_address: AztecAddress, _timestamp?: UInt64): Promise<ContractInstanceWithAddress | undefined> {
261
- throw new Error('TXE Archiver does not implement "getContract"');
262
- }
263
-
264
- public getRollupAddress(): Promise<EthAddress> {
265
- throw new Error('TXE Archiver does not implement "getRollupAddress"');
266
- }
267
-
268
- public getRegistryAddress(): Promise<EthAddress> {
269
- throw new Error('TXE Archiver does not implement "getRegistryAddress"');
270
- }
271
-
272
- public getL1Timestamp(): Promise<bigint> {
273
- throw new Error('TXE Archiver does not implement "getL1Timestamp"');
274
- }
275
-
276
- public isPendingChainInvalid(): Promise<boolean> {
277
- return Promise.resolve(false);
80
+ public getL2SlotNumber(): Promise<SlotNumber | undefined> {
81
+ throw new Error('TXE Archiver does not implement "getL2SlotNumber"');
278
82
  }
279
83
 
280
- public override getPendingChainValidationStatus(): Promise<ValidateCheckpointResult> {
281
- return Promise.resolve({ valid: true });
84
+ public getL2EpochNumber(): Promise<EpochNumber | undefined> {
85
+ throw new Error('TXE Archiver does not implement "getL2EpochNumber"');
282
86
  }
283
87
 
284
- getPublishedBlockByHash(_blockHash: Fr): Promise<PublishedL2Block | undefined> {
285
- throw new Error('Method not implemented.');
286
- }
287
- getPublishedBlockByArchive(_archive: Fr): Promise<PublishedL2Block | undefined> {
288
- throw new Error('Method not implemented.');
88
+ public isEpochComplete(_epochNumber: EpochNumber): Promise<boolean> {
89
+ throw new Error('TXE Archiver does not implement "isEpochComplete"');
289
90
  }
290
91
 
291
- getCheckpointedBlocks(_from: BlockNumber, _limit: number, _proven?: boolean): Promise<never[]> {
292
- throw new Error('TXE Archiver does not implement "getCheckpointedBlocks"');
92
+ public syncImmediate(): Promise<void> {
93
+ throw new Error('TXE Archiver does not implement "syncImmediate"');
293
94
  }
294
95
  }
@@ -1,11 +1,14 @@
1
1
  import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
2
2
  import { TestCircuitVerifier } from '@aztec/bb-prover/test';
3
+ import { CheckpointNumber } from '@aztec/foundation/branded-types';
4
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
5
  import { createLogger } from '@aztec/foundation/log';
4
6
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
5
7
  import { AnchorBlockStore } from '@aztec/pxe/server';
6
8
  import { L2Block } from '@aztec/stdlib/block';
7
- import { L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
9
+ import { Checkpoint, L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
8
10
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
11
+ import { CheckpointHeader } from '@aztec/stdlib/rollup';
9
12
  import { getPackageVersion } from '@aztec/stdlib/update-checker';
10
13
 
11
14
  import { TXEArchiver } from './archiver.js';
@@ -59,7 +62,26 @@ export class TXEStateMachine {
59
62
  }
60
63
 
61
64
  public async handleL2Block(block: L2Block) {
62
- const checkpoint = block.toCheckpoint();
65
+ // Create a checkpoint from the block manually
66
+ const checkpoint = new Checkpoint(
67
+ block.archive,
68
+ CheckpointHeader.from({
69
+ lastArchiveRoot: block.header.lastArchive.root,
70
+ inHash: Fr.ZERO,
71
+ blobsHash: Fr.ZERO,
72
+ blockHeadersHash: Fr.ZERO,
73
+ epochOutHash: Fr.ZERO,
74
+ slotNumber: block.header.globalVariables.slotNumber,
75
+ timestamp: block.header.globalVariables.timestamp,
76
+ coinbase: block.header.globalVariables.coinbase,
77
+ feeRecipient: block.header.globalVariables.feeRecipient,
78
+ gasFees: block.header.globalVariables.gasFees,
79
+ totalManaUsed: block.header.totalManaUsed,
80
+ }),
81
+ [block],
82
+ CheckpointNumber.fromBlockNumber(block.number),
83
+ );
84
+
63
85
  const publishedCheckpoint = new PublishedCheckpoint(
64
86
  checkpoint,
65
87
  new L1PublishedData(
@@ -70,9 +92,9 @@ export class TXEStateMachine {
70
92
  [],
71
93
  );
72
94
  await Promise.all([
73
- this.synchronizer.handleL2Block(block.toL2Block()),
95
+ this.synchronizer.handleL2Block(block),
74
96
  this.archiver.addCheckpoints([publishedCheckpoint], undefined),
75
- this.anchorBlockStore.setHeader(block.getBlockHeader()),
97
+ this.anchorBlockStore.setHeader(block.header),
76
98
  ]);
77
99
  }
78
100
  }
@@ -12,14 +12,16 @@ export class MockEpochCache implements EpochCacheInterface {
12
12
  committee: undefined,
13
13
  seed: 0n,
14
14
  epoch: EpochNumber.ZERO,
15
+ isEscapeHatchOpen: false,
15
16
  });
16
17
  }
17
18
 
18
- getEpochAndSlotNow(): EpochAndSlot {
19
+ getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
19
20
  return {
20
21
  epoch: EpochNumber.ZERO,
21
22
  slot: SlotNumber(0),
22
23
  ts: 0n,
24
+ nowMs: 0n,
23
25
  };
24
26
  }
25
27
 
@@ -40,18 +42,11 @@ export class MockEpochCache implements EpochCacheInterface {
40
42
  return 0n;
41
43
  }
42
44
 
43
- getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
44
- currentProposer: EthAddress | undefined;
45
- nextProposer: EthAddress | undefined;
46
- currentSlot: SlotNumber;
47
- nextSlot: SlotNumber;
48
- }> {
49
- return Promise.resolve({
50
- currentProposer: undefined,
51
- nextProposer: undefined,
45
+ getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
46
+ return {
52
47
  currentSlot: SlotNumber(0),
53
48
  nextSlot: SlotNumber(0),
54
- });
49
+ };
55
50
  }
56
51
 
57
52
  getProposerAttesterAddressInSlot(_slot: SlotNumber): Promise<EthAddress | undefined> {
@@ -1,7 +1,7 @@
1
1
  import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
2
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
3
  import { Fr } from '@aztec/foundation/curves/bn254';
4
- import type { L2BlockNew } from '@aztec/stdlib/block';
4
+ import type { L2Block } from '@aztec/stdlib/block';
5
5
  import type {
6
6
  MerkleTreeReadOperations,
7
7
  MerkleTreeWriteOperations,
@@ -23,7 +23,7 @@ export class TXESynchronizer implements WorldStateSynchronizer {
23
23
  return new this(nativeWorldStateService);
24
24
  }
25
25
 
26
- public async handleL2Block(block: L2BlockNew) {
26
+ public async handleL2Block(block: L2Block) {
27
27
  await this.nativeWorldStateService.handleL2BlockAndMessages(
28
28
  block,
29
29
  Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero),
@@ -7,6 +7,7 @@ import type { ProtocolContract } from '@aztec/protocol-contracts';
7
7
  import {
8
8
  AddressStore,
9
9
  CapsuleStore,
10
+ JobCoordinator,
10
11
  NoteService,
11
12
  NoteStore,
12
13
  PrivateEventStore,
@@ -43,7 +44,7 @@ import { CallContext, GlobalVariables, TxContext } from '@aztec/stdlib/tx';
43
44
 
44
45
  import { z } from 'zod';
45
46
 
46
- import { DEFAULT_ADDRESS, TXE_JOB_ID } from './constants.js';
47
+ import { DEFAULT_ADDRESS } from './constants.js';
47
48
  import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
48
49
  import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
49
50
  import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
@@ -74,7 +75,6 @@ type SessionState =
74
75
  | {
75
76
  name: 'PRIVATE';
76
77
  nextBlockGlobalVariables: GlobalVariables;
77
- protocolNullifier: Fr;
78
78
  noteCache: ExecutionNoteCache;
79
79
  taggingIndexCache: ExecutionTaggingIndexCache;
80
80
  }
@@ -139,6 +139,8 @@ export class TXESession implements TXESessionStateHandler {
139
139
  private senderAddressBookStore: SenderAddressBookStore,
140
140
  private capsuleStore: CapsuleStore,
141
141
  private privateEventStore: PrivateEventStore,
142
+ private jobCoordinator: JobCoordinator,
143
+ private currentJobId: string,
142
144
  private chainId: Fr,
143
145
  private version: Fr,
144
146
  private nextBlockTimestamp: bigint,
@@ -150,7 +152,7 @@ export class TXESession implements TXESessionStateHandler {
150
152
  const addressStore = new AddressStore(store);
151
153
  const privateEventStore = new PrivateEventStore(store);
152
154
  const contractStore = new TXEContractStore(store);
153
- const noteStore = await NoteStore.create(store);
155
+ const noteStore = new NoteStore(store);
154
156
  const senderTaggingStore = new SenderTaggingStore(store);
155
157
  const recipientTaggingStore = new RecipientTaggingStore(store);
156
158
  const senderAddressBookStore = new SenderAddressBookStore(store);
@@ -158,6 +160,16 @@ export class TXESession implements TXESessionStateHandler {
158
160
  const keyStore = new KeyStore(store);
159
161
  const accountStore = new TXEAccountStore(store);
160
162
 
163
+ // Create job coordinator and register staged stores
164
+ const jobCoordinator = new JobCoordinator(store);
165
+ jobCoordinator.registerStores([
166
+ capsuleStore,
167
+ senderTaggingStore,
168
+ recipientTaggingStore,
169
+ privateEventStore,
170
+ noteStore,
171
+ ]);
172
+
161
173
  // Register protocol contracts.
162
174
  for (const { contractClass, instance, artifact } of protocolContracts) {
163
175
  await contractStore.addContractArtifact(contractClass.id, artifact);
@@ -170,6 +182,8 @@ export class TXESession implements TXESessionStateHandler {
170
182
  const version = new Fr(await stateMachine.node.getVersion());
171
183
  const chainId = new Fr(await stateMachine.node.getChainId());
172
184
 
185
+ const initialJobId = jobCoordinator.beginJob();
186
+
173
187
  const topLevelOracleHandler = new TXEOracleTopLevelContext(
174
188
  stateMachine,
175
189
  contractStore,
@@ -182,6 +196,7 @@ export class TXESession implements TXESessionStateHandler {
182
196
  senderAddressBookStore,
183
197
  capsuleStore,
184
198
  privateEventStore,
199
+ initialJobId,
185
200
  nextBlockTimestamp,
186
201
  version,
187
202
  chainId,
@@ -203,6 +218,8 @@ export class TXESession implements TXESessionStateHandler {
203
218
  senderAddressBookStore,
204
219
  capsuleStore,
205
220
  privateEventStore,
221
+ jobCoordinator,
222
+ initialJobId,
206
223
  version,
207
224
  chainId,
208
225
  nextBlockTimestamp,
@@ -262,6 +279,10 @@ export class TXESession implements TXESessionStateHandler {
262
279
  }
263
280
  }
264
281
 
282
+ // Commit all staged stores from the job that was just completed, then begin a new job
283
+ await this.jobCoordinator.commitJob(this.currentJobId);
284
+ this.currentJobId = this.jobCoordinator.beginJob();
285
+
265
286
  this.oracleHandler = new TXEOracleTopLevelContext(
266
287
  this.stateMachine,
267
288
  this.contractStore,
@@ -274,6 +295,7 @@ export class TXESession implements TXESessionStateHandler {
274
295
  this.senderAddressBookStore,
275
296
  this.capsuleStore,
276
297
  this.privateEventStore,
298
+ this.currentJobId,
277
299
  this.nextBlockTimestamp,
278
300
  this.version,
279
301
  this.chainId,
@@ -290,16 +312,14 @@ export class TXESession implements TXESessionStateHandler {
290
312
  ): Promise<PrivateContextInputs> {
291
313
  this.exitTopLevelState();
292
314
 
293
- await new NoteService(
294
- this.noteStore,
295
- this.stateMachine.node,
296
- this.stateMachine.anchorBlockStore,
297
- ).syncNoteNullifiers(contractAddress);
298
-
299
315
  // Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
300
316
  // build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
301
317
  // a single transaction with the effects of what was done in the test.
302
318
  const anchorBlock = await this.stateMachine.node.getBlockHeader(anchorBlockNumber ?? 'latest');
319
+
320
+ await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
321
+ contractAddress,
322
+ );
303
323
  const latestBlock = await this.stateMachine.node.getBlockHeader('latest');
304
324
 
305
325
  const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
@@ -331,13 +351,12 @@ export class TXESession implements TXESessionStateHandler {
331
351
  this.keyStore,
332
352
  this.addressStore,
333
353
  this.stateMachine.node,
334
- this.stateMachine.anchorBlockStore,
335
354
  this.senderTaggingStore,
336
355
  this.recipientTaggingStore,
337
356
  this.senderAddressBookStore,
338
357
  this.capsuleStore,
339
358
  this.privateEventStore,
340
- TXE_JOB_ID,
359
+ this.currentJobId,
341
360
  );
342
361
 
343
362
  // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
@@ -345,7 +364,7 @@ export class TXESession implements TXESessionStateHandler {
345
364
  // difference resides in that the simulator has all information needed in order to run the simulation, while ours
346
365
  // will be ongoing as the different oracles will be invoked from the Noir test, until eventually the private
347
366
  // execution finishes.
348
- this.state = { name: 'PRIVATE', nextBlockGlobalVariables, protocolNullifier, noteCache, taggingIndexCache };
367
+ this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
349
368
  this.logger.debug(`Entered state ${this.state.name}`);
350
369
 
351
370
  return (this.oracleHandler as PrivateExecutionOracle).getPrivateContextInputs();
@@ -378,6 +397,8 @@ export class TXESession implements TXESessionStateHandler {
378
397
  async enterUtilityState(contractAddress: AztecAddress = DEFAULT_ADDRESS) {
379
398
  this.exitTopLevelState();
380
399
 
400
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
401
+
381
402
  // There is no automatic message discovery and contract-driven syncing process in inlined private or utility
382
403
  // contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
383
404
  // we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
@@ -386,11 +407,10 @@ export class TXESession implements TXESessionStateHandler {
386
407
  await new NoteService(
387
408
  this.noteStore,
388
409
  this.stateMachine.node,
389
- this.stateMachine.anchorBlockStore,
410
+ anchorBlockHeader,
411
+ this.currentJobId,
390
412
  ).syncNoteNullifiers(contractAddress);
391
413
 
392
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
393
-
394
414
  this.oracleHandler = new UtilityExecutionOracle(
395
415
  contractAddress,
396
416
  [],
@@ -401,12 +421,11 @@ export class TXESession implements TXESessionStateHandler {
401
421
  this.keyStore,
402
422
  this.addressStore,
403
423
  this.stateMachine.node,
404
- this.stateMachine.anchorBlockStore,
405
424
  this.recipientTaggingStore,
406
425
  this.senderAddressBookStore,
407
426
  this.capsuleStore,
408
427
  this.privateEventStore,
409
- TXE_JOB_ID,
428
+ this.currentJobId,
410
429
  );
411
430
 
412
431
  this.state = { name: 'UTILITY' };
@@ -442,11 +461,7 @@ export class TXESession implements TXESessionStateHandler {
442
461
  // We rely on the note cache to determine the effects of the transaction. This is incomplete as it doesn't private
443
462
  // logs (other effects like enqueued public calls don't need to be considered since those are not allowed).
444
463
 
445
- const txEffect = await makeTxEffect(
446
- this.state.noteCache,
447
- this.state.protocolNullifier,
448
- this.state.nextBlockGlobalVariables.blockNumber,
449
- );
464
+ const txEffect = await makeTxEffect(this.state.noteCache, this.state.nextBlockGlobalVariables.blockNumber);
450
465
 
451
466
  // We build a block holding just this transaction
452
467
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
@@ -496,12 +511,11 @@ export class TXESession implements TXESessionStateHandler {
496
511
  this.keyStore,
497
512
  this.addressStore,
498
513
  this.stateMachine.node,
499
- this.stateMachine.anchorBlockStore,
500
514
  this.recipientTaggingStore,
501
515
  this.senderAddressBookStore,
502
516
  this.capsuleStore,
503
517
  this.privateEventStore,
504
- TXE_JOB_ID,
518
+ this.currentJobId,
505
519
  );
506
520
  await new WASMSimulator()
507
521
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())