@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.
- package/dest/constants.d.ts +1 -2
- package/dest/constants.d.ts.map +1 -1
- package/dest/constants.js +0 -1
- package/dest/oracle/interfaces.d.ts +3 -3
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +3 -3
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +6 -6
- package/dest/oracle/txe_oracle_top_level_context.d.ts +3 -2
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +30 -22
- package/dest/rpc_translator.d.ts +16 -10
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +53 -40
- package/dest/state_machine/archiver.d.ts +20 -69
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +34 -178
- package/dest/state_machine/index.d.ts +1 -1
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +22 -4
- package/dest/state_machine/mock_epoch_cache.d.ts +6 -6
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +7 -7
- package/dest/state_machine/synchronizer.d.ts +3 -3
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/txe_session.d.ts +5 -3
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +31 -15
- package/dest/util/encoding.d.ts +17 -17
- package/dest/utils/block_creation.d.ts +4 -4
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +16 -4
- package/dest/utils/tx_effect_creation.d.ts +2 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +3 -6
- package/package.json +16 -16
- package/src/constants.ts +0 -1
- package/src/oracle/interfaces.ts +2 -2
- package/src/oracle/txe_oracle_public_context.ts +6 -8
- package/src/oracle/txe_oracle_top_level_context.ts +50 -24
- package/src/rpc_translator.ts +62 -47
- package/src/state_machine/archiver.ts +35 -234
- package/src/state_machine/index.ts +26 -4
- package/src/state_machine/mock_epoch_cache.ts +6 -11
- package/src/state_machine/synchronizer.ts +2 -2
- package/src/txe_session.ts +38 -24
- package/src/utils/block_creation.ts +17 -16
- package/src/utils/tx_effect_creation.ts +3 -11
|
@@ -1,216 +1,48 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ArchiverDataSourceBase, ArchiverDataStoreUpdater, KVArchiverDataStore } from '@aztec/archiver';
|
|
2
2
|
import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
|
|
3
|
-
import {
|
|
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 {
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
|
193
|
-
|
|
24
|
+
public async addCheckpoints(checkpoints: PublishedCheckpoint[], result?: ValidateCheckpointResult): Promise<void> {
|
|
25
|
+
await this.updater.addCheckpoints(checkpoints, result);
|
|
194
26
|
}
|
|
195
27
|
|
|
196
|
-
public
|
|
197
|
-
throw new Error('TXE Archiver does not implement "
|
|
28
|
+
public getRollupAddress(): Promise<EthAddress> {
|
|
29
|
+
throw new Error('TXE Archiver does not implement "getRollupAddress"');
|
|
198
30
|
}
|
|
199
31
|
|
|
200
|
-
public
|
|
201
|
-
throw new Error('TXE Archiver does not implement "
|
|
32
|
+
public getRegistryAddress(): Promise<EthAddress> {
|
|
33
|
+
throw new Error('TXE Archiver does not implement "getRegistryAddress"');
|
|
202
34
|
}
|
|
203
35
|
|
|
204
|
-
public
|
|
205
|
-
throw new Error('TXE Archiver does not implement "
|
|
36
|
+
public getL1Constants(): Promise<L1RollupConstants> {
|
|
37
|
+
throw new Error('TXE Archiver does not implement "getL1Constants"');
|
|
206
38
|
}
|
|
207
39
|
|
|
208
|
-
public
|
|
209
|
-
|
|
40
|
+
public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
|
|
41
|
+
return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
210
42
|
}
|
|
211
43
|
|
|
212
|
-
public
|
|
213
|
-
throw new Error('TXE Archiver does not implement "
|
|
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
|
|
249
|
-
throw new Error('TXE Archiver does not implement "
|
|
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
|
|
281
|
-
|
|
84
|
+
public getL2EpochNumber(): Promise<EpochNumber | undefined> {
|
|
85
|
+
throw new Error('TXE Archiver does not implement "getL2EpochNumber"');
|
|
282
86
|
}
|
|
283
87
|
|
|
284
|
-
|
|
285
|
-
throw new Error('
|
|
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
|
-
|
|
292
|
-
throw new Error('TXE Archiver does not implement "
|
|
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
|
-
|
|
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
|
|
95
|
+
this.synchronizer.handleL2Block(block),
|
|
74
96
|
this.archiver.addCheckpoints([publishedCheckpoint], undefined),
|
|
75
|
-
this.anchorBlockStore.setHeader(block.
|
|
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
|
-
|
|
44
|
-
|
|
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 {
|
|
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:
|
|
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),
|
package/src/txe_session.ts
CHANGED
|
@@ -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
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
518
|
+
this.currentJobId,
|
|
505
519
|
);
|
|
506
520
|
await new WASMSimulator()
|
|
507
521
|
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|