@aztec/archiver 0.55.0 → 0.56.0
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/archiver/archiver.d.ts +4 -5
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +89 -110
- package/dest/archiver/archiver_store.d.ts +11 -17
- package/dest/archiver/archiver_store.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.js +1 -25
- package/dest/archiver/config.d.ts +0 -4
- package/dest/archiver/config.d.ts.map +1 -1
- package/dest/archiver/config.js +1 -6
- package/dest/archiver/data_retrieval.d.ts +33 -5
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +124 -15
- package/dest/archiver/kv_archiver_store/block_store.d.ts +2 -2
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +16 -10
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +3 -15
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +12 -25
- package/dest/archiver/kv_archiver_store/message_store.d.ts +1 -0
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/message_store.js +11 -8
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +3 -20
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +9 -28
- package/dest/index.d.ts +0 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -2
- package/package.json +10 -10
- package/src/archiver/archiver.ts +140 -156
- package/src/archiver/archiver_store.ts +12 -18
- package/src/archiver/archiver_store_test_suite.ts +1 -28
- package/src/archiver/config.ts +0 -10
- package/src/archiver/data_retrieval.ts +189 -29
- package/src/archiver/kv_archiver_store/block_store.ts +17 -10
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +11 -25
- package/src/archiver/kv_archiver_store/message_store.ts +9 -5
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +10 -32
- package/src/index.ts +0 -2
- package/dest/archiver/eth_log_handlers.d.ts +0 -59
- package/dest/archiver/eth_log_handlers.d.ts.map +0 -1
- package/dest/archiver/eth_log_handlers.js +0 -155
- package/dest/archiver/kv_archiver_store/block_body_store.d.ts +0 -34
- package/dest/archiver/kv_archiver_store/block_body_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/block_body_store.js +0 -65
- package/src/archiver/eth_log_handlers.ts +0 -213
- package/src/archiver/kv_archiver_store/block_body_store.ts +0 -74
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Fr,
|
|
1
|
+
import { Body, InboxLeaf, L2Block } from '@aztec/circuit-types';
|
|
2
|
+
import { AppendOnlyTreeSnapshot, Fr, Header, Proof } from '@aztec/circuits.js';
|
|
3
3
|
import { type EthAddress } from '@aztec/foundation/eth-address';
|
|
4
|
+
import { type ViemSignature } from '@aztec/foundation/eth-signature';
|
|
4
5
|
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import { type Hex, type PublicClient, getAbiItem } from 'viem';
|
|
6
|
+
import { numToUInt32BE } from '@aztec/foundation/serialize';
|
|
7
|
+
import { type InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
type Chain,
|
|
11
|
+
type GetContractEventsReturnType,
|
|
12
|
+
type GetContractReturnType,
|
|
13
|
+
type Hex,
|
|
14
|
+
type HttpTransport,
|
|
15
|
+
type PublicClient,
|
|
16
|
+
decodeFunctionData,
|
|
17
|
+
getAbiItem,
|
|
18
|
+
hexToBytes,
|
|
19
|
+
} from 'viem';
|
|
20
|
+
|
|
16
21
|
import { type DataRetrieval } from './structs/data_retrieval.js';
|
|
17
|
-
import { type L1Published } from './structs/published.js';
|
|
22
|
+
import { type L1Published, type L1PublishedData } from './structs/published.js';
|
|
18
23
|
|
|
19
24
|
/**
|
|
20
25
|
* Fetches new L2 blocks.
|
|
@@ -27,12 +32,11 @@ import { type L1Published } from './structs/published.js';
|
|
|
27
32
|
* @returns An array of block; as well as the next eth block to search from.
|
|
28
33
|
*/
|
|
29
34
|
export async function retrieveBlockFromRollup(
|
|
35
|
+
rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>,
|
|
30
36
|
publicClient: PublicClient,
|
|
31
|
-
rollupAddress: EthAddress,
|
|
32
37
|
blockUntilSynced: boolean,
|
|
33
38
|
searchStartBlock: bigint,
|
|
34
39
|
searchEndBlock: bigint,
|
|
35
|
-
expectedNextL2BlockNum: bigint,
|
|
36
40
|
logger: DebugLogger = createDebugLogger('aztec:archiver'),
|
|
37
41
|
): Promise<L1Published<L2Block>[]> {
|
|
38
42
|
const retrievedBlocks: L1Published<L2Block>[] = [];
|
|
@@ -40,29 +44,120 @@ export async function retrieveBlockFromRollup(
|
|
|
40
44
|
if (searchStartBlock > searchEndBlock) {
|
|
41
45
|
break;
|
|
42
46
|
}
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
const l2BlockProposedLogs = await rollup.getEvents.L2BlockProposed(
|
|
48
|
+
{},
|
|
49
|
+
{
|
|
50
|
+
fromBlock: searchStartBlock,
|
|
51
|
+
toBlock: searchEndBlock + 1n,
|
|
52
|
+
},
|
|
48
53
|
);
|
|
49
|
-
|
|
54
|
+
|
|
55
|
+
if (l2BlockProposedLogs.length === 0) {
|
|
50
56
|
break;
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
const lastLog =
|
|
59
|
+
const lastLog = l2BlockProposedLogs[l2BlockProposedLogs.length - 1];
|
|
54
60
|
logger.debug(
|
|
55
|
-
`Got L2 block processed logs for ${
|
|
61
|
+
`Got L2 block processed logs for ${l2BlockProposedLogs[0].blockNumber}-${lastLog.blockNumber} between ${searchStartBlock}-${searchEndBlock} L1 blocks`,
|
|
56
62
|
);
|
|
57
63
|
|
|
58
|
-
const newBlocks = await processL2BlockProposedLogs(publicClient,
|
|
64
|
+
const newBlocks = await processL2BlockProposedLogs(rollup, publicClient, l2BlockProposedLogs, logger);
|
|
59
65
|
retrievedBlocks.push(...newBlocks);
|
|
60
66
|
searchStartBlock = lastLog.blockNumber! + 1n;
|
|
61
|
-
expectedNextL2BlockNum += BigInt(newBlocks.length);
|
|
62
67
|
} while (blockUntilSynced && searchStartBlock <= searchEndBlock);
|
|
63
68
|
return retrievedBlocks;
|
|
64
69
|
}
|
|
65
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Processes newly received L2BlockProposed logs.
|
|
73
|
+
* @param rollup - The rollup contract
|
|
74
|
+
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
75
|
+
* @param logs - L2BlockProposed logs.
|
|
76
|
+
* @returns - An array blocks.
|
|
77
|
+
*/
|
|
78
|
+
export async function processL2BlockProposedLogs(
|
|
79
|
+
rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>,
|
|
80
|
+
publicClient: PublicClient,
|
|
81
|
+
logs: GetContractEventsReturnType<typeof RollupAbi, 'L2BlockProposed'>,
|
|
82
|
+
logger: DebugLogger,
|
|
83
|
+
): Promise<L1Published<L2Block>[]> {
|
|
84
|
+
const retrievedBlocks: L1Published<L2Block>[] = [];
|
|
85
|
+
for (const log of logs) {
|
|
86
|
+
const l2BlockNumber = log.args.blockNumber!;
|
|
87
|
+
const archive = log.args.archive!;
|
|
88
|
+
const archiveFromChain = await rollup.read.archiveAt([l2BlockNumber]);
|
|
89
|
+
|
|
90
|
+
// The value from the event and contract will match only if the block is in the chain.
|
|
91
|
+
if (archive === archiveFromChain) {
|
|
92
|
+
// TODO: Fetch blocks from calldata in parallel
|
|
93
|
+
const block = await getBlockFromRollupTx(publicClient, log.transactionHash!, l2BlockNumber);
|
|
94
|
+
|
|
95
|
+
const l1: L1PublishedData = {
|
|
96
|
+
blockNumber: log.blockNumber,
|
|
97
|
+
blockHash: log.blockHash,
|
|
98
|
+
timestamp: await getL1BlockTime(publicClient, log.blockNumber),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
retrievedBlocks.push({ data: block, l1 });
|
|
102
|
+
} else {
|
|
103
|
+
logger.warn(
|
|
104
|
+
`Archive mismatch matching, ignoring block ${l2BlockNumber} with archive: ${archive}, expected ${archiveFromChain}`,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return retrievedBlocks;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function getL1BlockTime(publicClient: PublicClient, blockNumber: bigint): Promise<bigint> {
|
|
113
|
+
const block = await publicClient.getBlock({ blockNumber, includeTransactions: false });
|
|
114
|
+
return block.timestamp;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Gets block from the calldata of an L1 transaction.
|
|
119
|
+
* Assumes that the block was published from an EOA.
|
|
120
|
+
* TODO: Add retries and error management.
|
|
121
|
+
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
122
|
+
* @param txHash - Hash of the tx that published it.
|
|
123
|
+
* @param l2BlockNum - L2 block number.
|
|
124
|
+
* @returns L2 block from the calldata, deserialized
|
|
125
|
+
*/
|
|
126
|
+
async function getBlockFromRollupTx(
|
|
127
|
+
publicClient: PublicClient,
|
|
128
|
+
txHash: `0x${string}`,
|
|
129
|
+
l2BlockNum: bigint,
|
|
130
|
+
): Promise<L2Block> {
|
|
131
|
+
const { input: data } = await publicClient.getTransaction({ hash: txHash });
|
|
132
|
+
const { functionName, args } = decodeFunctionData({
|
|
133
|
+
abi: RollupAbi,
|
|
134
|
+
data,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (!(functionName === 'propose')) {
|
|
138
|
+
throw new Error(`Unexpected method called ${functionName}`);
|
|
139
|
+
}
|
|
140
|
+
const [headerHex, archiveRootHex, , , , bodyHex] = args! as readonly [Hex, Hex, Hex, Hex[], ViemSignature[], Hex];
|
|
141
|
+
|
|
142
|
+
const header = Header.fromBuffer(Buffer.from(hexToBytes(headerHex)));
|
|
143
|
+
const blockBody = Body.fromBuffer(Buffer.from(hexToBytes(bodyHex)));
|
|
144
|
+
|
|
145
|
+
const blockNumberFromHeader = header.globalVariables.blockNumber.toBigInt();
|
|
146
|
+
|
|
147
|
+
if (blockNumberFromHeader !== l2BlockNum) {
|
|
148
|
+
throw new Error(`Block number mismatch: expected ${l2BlockNum} but got ${blockNumberFromHeader}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const archive = AppendOnlyTreeSnapshot.fromBuffer(
|
|
152
|
+
Buffer.concat([
|
|
153
|
+
Buffer.from(hexToBytes(archiveRootHex)), // L2Block.archive.root
|
|
154
|
+
numToUInt32BE(Number(l2BlockNum + 1n)), // L2Block.archive.nextAvailableLeafIndex
|
|
155
|
+
]),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
return new L2Block(archive, header, blockBody);
|
|
159
|
+
}
|
|
160
|
+
|
|
66
161
|
/**
|
|
67
162
|
* Fetch L1 to L2 messages.
|
|
68
163
|
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
@@ -73,8 +168,7 @@ export async function retrieveBlockFromRollup(
|
|
|
73
168
|
* @returns An array of InboxLeaf and next eth block to search from.
|
|
74
169
|
*/
|
|
75
170
|
export async function retrieveL1ToL2Messages(
|
|
76
|
-
|
|
77
|
-
inboxAddress: EthAddress,
|
|
171
|
+
inbox: GetContractReturnType<typeof InboxAbi, PublicClient<HttpTransport, Chain>>,
|
|
78
172
|
blockUntilSynced: boolean,
|
|
79
173
|
searchStartBlock: bigint,
|
|
80
174
|
searchEndBlock: bigint,
|
|
@@ -84,12 +178,24 @@ export async function retrieveL1ToL2Messages(
|
|
|
84
178
|
if (searchStartBlock > searchEndBlock) {
|
|
85
179
|
break;
|
|
86
180
|
}
|
|
87
|
-
|
|
181
|
+
|
|
182
|
+
const messageSentLogs = await inbox.getEvents.MessageSent(
|
|
183
|
+
{},
|
|
184
|
+
{
|
|
185
|
+
fromBlock: searchStartBlock,
|
|
186
|
+
toBlock: searchEndBlock + 1n,
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
|
|
88
190
|
if (messageSentLogs.length === 0) {
|
|
89
191
|
break;
|
|
90
192
|
}
|
|
91
|
-
|
|
92
|
-
|
|
193
|
+
|
|
194
|
+
for (const log of messageSentLogs) {
|
|
195
|
+
const { l2BlockNumber, index, hash } = log.args;
|
|
196
|
+
retrievedL1ToL2Messages.push(new InboxLeaf(l2BlockNumber!, index!, Fr.fromString(hash!)));
|
|
197
|
+
}
|
|
198
|
+
|
|
93
199
|
// handles the case when there are no new messages:
|
|
94
200
|
searchStartBlock = (messageSentLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock) + 1n;
|
|
95
201
|
} while (blockUntilSynced && searchStartBlock <= searchEndBlock);
|
|
@@ -139,3 +245,57 @@ export async function retrieveL2ProofsFromRollup(
|
|
|
139
245
|
lastProcessedL1BlockNumber,
|
|
140
246
|
};
|
|
141
247
|
}
|
|
248
|
+
|
|
249
|
+
export type SubmitBlockProof = {
|
|
250
|
+
header: Header;
|
|
251
|
+
archiveRoot: Fr;
|
|
252
|
+
proverId: Fr;
|
|
253
|
+
aggregationObject: Buffer;
|
|
254
|
+
proof: Proof;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Gets block metadata (header and archive snapshot) from the calldata of an L1 transaction.
|
|
259
|
+
* Assumes that the block was published from an EOA.
|
|
260
|
+
* TODO: Add retries and error management.
|
|
261
|
+
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
262
|
+
* @param txHash - Hash of the tx that published it.
|
|
263
|
+
* @param l2BlockNum - L2 block number.
|
|
264
|
+
* @returns L2 block metadata (header and archive) from the calldata, deserialized
|
|
265
|
+
*/
|
|
266
|
+
export async function getBlockProofFromSubmitProofTx(
|
|
267
|
+
publicClient: PublicClient,
|
|
268
|
+
txHash: `0x${string}`,
|
|
269
|
+
l2BlockNum: bigint,
|
|
270
|
+
expectedProverId: Fr,
|
|
271
|
+
): Promise<SubmitBlockProof> {
|
|
272
|
+
const { input: data } = await publicClient.getTransaction({ hash: txHash });
|
|
273
|
+
const { functionName, args } = decodeFunctionData({
|
|
274
|
+
abi: RollupAbi,
|
|
275
|
+
data,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
if (!(functionName === 'submitBlockRootProof')) {
|
|
279
|
+
throw new Error(`Unexpected method called ${functionName}`);
|
|
280
|
+
}
|
|
281
|
+
const [headerHex, archiveHex, proverIdHex, aggregationObjectHex, proofHex] = args!;
|
|
282
|
+
|
|
283
|
+
const header = Header.fromBuffer(Buffer.from(hexToBytes(headerHex)));
|
|
284
|
+
const proverId = Fr.fromString(proverIdHex);
|
|
285
|
+
|
|
286
|
+
const blockNumberFromHeader = header.globalVariables.blockNumber.toBigInt();
|
|
287
|
+
if (blockNumberFromHeader !== l2BlockNum) {
|
|
288
|
+
throw new Error(`Block number mismatch: expected ${l2BlockNum} but got ${blockNumberFromHeader}`);
|
|
289
|
+
}
|
|
290
|
+
if (!proverId.equals(expectedProverId)) {
|
|
291
|
+
throw new Error(`Prover ID mismatch: expected ${expectedProverId} but got ${proverId}`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
header,
|
|
296
|
+
proverId,
|
|
297
|
+
aggregationObject: Buffer.from(hexToBytes(aggregationObjectHex)),
|
|
298
|
+
archiveRoot: Fr.fromString(archiveHex),
|
|
299
|
+
proof: Proof.fromBuffer(Buffer.from(hexToBytes(proofHex))),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { L2Block, type TxEffect, type TxHash, TxReceipt } from '@aztec/circuit-types';
|
|
1
|
+
import { Body, L2Block, type TxEffect, type TxHash, TxReceipt } from '@aztec/circuit-types';
|
|
2
2
|
import { AppendOnlyTreeSnapshot, type AztecAddress, Header, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js';
|
|
3
3
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { type AztecKVStore, type AztecMap, type AztecSingleton, type Range } from '@aztec/kv-store';
|
|
5
5
|
|
|
6
6
|
import { type L1Published, type L1PublishedData } from '../structs/published.js';
|
|
7
|
-
import { type BlockBodyStore } from './block_body_store.js';
|
|
8
7
|
|
|
9
8
|
type BlockIndexValue = [blockNumber: number, index: number];
|
|
10
9
|
|
|
@@ -20,6 +19,10 @@ type BlockStorage = {
|
|
|
20
19
|
export class BlockStore {
|
|
21
20
|
/** Map block number to block data */
|
|
22
21
|
#blocks: AztecMap<number, BlockStorage>;
|
|
22
|
+
|
|
23
|
+
/** Map block body hash to block body */
|
|
24
|
+
#blockBodies: AztecMap<string, Buffer>;
|
|
25
|
+
|
|
23
26
|
/** Stores L1 block number in which the last processed L2 block was included */
|
|
24
27
|
#lastSynchedL1Block: AztecSingleton<bigint>;
|
|
25
28
|
|
|
@@ -31,12 +34,9 @@ export class BlockStore {
|
|
|
31
34
|
|
|
32
35
|
#log = createDebugLogger('aztec:archiver:block_store');
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
constructor(private db: AztecKVStore, blockBodyStore: BlockBodyStore) {
|
|
37
|
-
this.#blockBodyStore = blockBodyStore;
|
|
38
|
-
|
|
37
|
+
constructor(private db: AztecKVStore) {
|
|
39
38
|
this.#blocks = db.openMap('archiver_blocks');
|
|
39
|
+
this.#blockBodies = db.openMap('archiver_block_bodies');
|
|
40
40
|
this.#txIndex = db.openMap('archiver_tx_index');
|
|
41
41
|
this.#contractIndex = db.openMap('archiver_contract_index');
|
|
42
42
|
this.#lastSynchedL1Block = db.openSingleton('archiver_last_synched_l1_block');
|
|
@@ -63,6 +63,8 @@ export class BlockStore {
|
|
|
63
63
|
block.data.body.txEffects.forEach((tx, i) => {
|
|
64
64
|
void this.#txIndex.set(tx.txHash.toString(), [block.data.number, i]);
|
|
65
65
|
});
|
|
66
|
+
|
|
67
|
+
void this.#blockBodies.set(block.data.body.getTxsEffectsHash().toString('hex'), block.data.body.toBuffer());
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
void this.#lastSynchedL1Block.set(blocks[blocks.length - 1].l1.blockNumber);
|
|
@@ -100,11 +102,12 @@ export class BlockStore {
|
|
|
100
102
|
private getBlockFromBlockStorage(blockStorage: BlockStorage) {
|
|
101
103
|
const header = Header.fromBuffer(blockStorage.header);
|
|
102
104
|
const archive = AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive);
|
|
103
|
-
const body = this.#blockBodyStore.getBlockBody(header.contentCommitment.txsEffectsHash);
|
|
104
105
|
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
const blockBodyBuffer = this.#blockBodies.get(header.contentCommitment.txsEffectsHash.toString('hex'));
|
|
107
|
+
if (blockBodyBuffer === undefined) {
|
|
108
|
+
throw new Error('Body could not be retrieved');
|
|
107
109
|
}
|
|
110
|
+
const body = Body.fromBuffer(blockBodyBuffer);
|
|
108
111
|
|
|
109
112
|
const l2Block = L2Block.fromFields({ header, archive, body });
|
|
110
113
|
return { data: l2Block, l1: blockStorage.l1 };
|
|
@@ -184,6 +187,10 @@ export class BlockStore {
|
|
|
184
187
|
return this.#lastSynchedL1Block.get();
|
|
185
188
|
}
|
|
186
189
|
|
|
190
|
+
setSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
191
|
+
void this.#lastSynchedL1Block.set(l1BlockNumber);
|
|
192
|
+
}
|
|
193
|
+
|
|
187
194
|
#computeBlockRange(start: number, limit: number): Required<Pick<Range<number>, 'start' | 'end'>> {
|
|
188
195
|
if (limit < 1) {
|
|
189
196
|
throw new Error(`Invalid limit: ${limit}`);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type Body,
|
|
3
2
|
type EncryptedL2BlockL2Logs,
|
|
4
3
|
type EncryptedNoteL2BlockL2Logs,
|
|
5
4
|
type FromLogType,
|
|
@@ -29,7 +28,6 @@ import {
|
|
|
29
28
|
import { type ArchiverDataStore, type ArchiverL1SynchPoint } from '../archiver_store.js';
|
|
30
29
|
import { type DataRetrieval, type SingletonDataRetrieval } from '../structs/data_retrieval.js';
|
|
31
30
|
import { type L1Published } from '../structs/published.js';
|
|
32
|
-
import { BlockBodyStore } from './block_body_store.js';
|
|
33
31
|
import { BlockStore } from './block_store.js';
|
|
34
32
|
import { ContractArtifactsStore } from './contract_artifacts_store.js';
|
|
35
33
|
import { ContractClassStore } from './contract_class_store.js';
|
|
@@ -42,7 +40,6 @@ import { ProvenStore } from './proven_store.js';
|
|
|
42
40
|
* LMDB implementation of the ArchiverDataStore interface.
|
|
43
41
|
*/
|
|
44
42
|
export class KVArchiverDataStore implements ArchiverDataStore {
|
|
45
|
-
#blockBodyStore: BlockBodyStore;
|
|
46
43
|
#blockStore: BlockStore;
|
|
47
44
|
#provenStore: ProvenStore;
|
|
48
45
|
#logStore: LogStore;
|
|
@@ -54,8 +51,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
54
51
|
#log = createDebugLogger('aztec:archiver:data-store');
|
|
55
52
|
|
|
56
53
|
constructor(db: AztecKVStore, logsMaxPageSize: number = 1000) {
|
|
57
|
-
this.#
|
|
58
|
-
this.#blockStore = new BlockStore(db, this.#blockBodyStore);
|
|
54
|
+
this.#blockStore = new BlockStore(db);
|
|
59
55
|
this.#provenStore = new ProvenStore(db);
|
|
60
56
|
this.#logStore = new LogStore(db, this.#blockStore, logsMaxPageSize);
|
|
61
57
|
this.#messageStore = new MessageStore(db);
|
|
@@ -100,25 +96,6 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
100
96
|
return (await Promise.all(data.map(c => this.#contractInstanceStore.addContractInstance(c)))).every(Boolean);
|
|
101
97
|
}
|
|
102
98
|
|
|
103
|
-
/**
|
|
104
|
-
* Append new block bodies to the store's list.
|
|
105
|
-
* @param blockBodies - The L2 block bodies to be added to the store.
|
|
106
|
-
* @returns True if the operation is successful.
|
|
107
|
-
*/
|
|
108
|
-
addBlockBodies(blockBodies: DataRetrieval<Body>): Promise<boolean> {
|
|
109
|
-
return this.#blockBodyStore.addBlockBodies(blockBodies);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Gets block bodies that have the same txHashes as we supply.
|
|
114
|
-
*
|
|
115
|
-
* @param txsEffectsHashes - A list of txsEffectsHashes (body hashes).
|
|
116
|
-
* @returns The requested L2 block bodies
|
|
117
|
-
*/
|
|
118
|
-
getBlockBodies(txsEffectsHashes: Buffer[]): Promise<(Body | undefined)[]> {
|
|
119
|
-
return this.#blockBodyStore.getBlockBodies(txsEffectsHashes);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
99
|
/**
|
|
123
100
|
* Append new blocks to the store's list.
|
|
124
101
|
* @param blocks - The L2 blocks to be added to the store and the last processed L1 block.
|
|
@@ -258,13 +235,22 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
258
235
|
await this.#provenStore.setProvenL2BlockNumber(blockNumber);
|
|
259
236
|
}
|
|
260
237
|
|
|
238
|
+
setBlockSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
239
|
+
this.#blockStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
240
|
+
return Promise.resolve();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
setMessageSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
244
|
+
this.#messageStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
245
|
+
return Promise.resolve();
|
|
246
|
+
}
|
|
247
|
+
|
|
261
248
|
/**
|
|
262
249
|
* Gets the last L1 block number processed by the archiver
|
|
263
250
|
*/
|
|
264
251
|
getSynchPoint(): Promise<ArchiverL1SynchPoint> {
|
|
265
252
|
return Promise.resolve({
|
|
266
253
|
blocksSynchedTo: this.#blockStore.getSynchedL1BlockNumber(),
|
|
267
|
-
blockBodiesSynchedTo: this.#blockBodyStore.getSynchedL1BlockNumber(),
|
|
268
254
|
messagesSynchedTo: this.#messageStore.getSynchedL1BlockNumber(),
|
|
269
255
|
provenLogsSynchedTo: this.#provenStore.getSynchedL1BlockNumber(),
|
|
270
256
|
});
|
|
@@ -16,7 +16,7 @@ import { type DataRetrieval } from '../structs/data_retrieval.js';
|
|
|
16
16
|
export class MessageStore {
|
|
17
17
|
#l1ToL2Messages: AztecMap<string, Buffer>;
|
|
18
18
|
#l1ToL2MessageIndices: AztecMap<string, bigint[]>; // We store array of bigints here because there can be duplicate messages
|
|
19
|
-
#
|
|
19
|
+
#lastSynchedL1Block: AztecSingleton<bigint>;
|
|
20
20
|
|
|
21
21
|
#log = createDebugLogger('aztec:archiver:message_store');
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ export class MessageStore {
|
|
|
25
25
|
constructor(private db: AztecKVStore) {
|
|
26
26
|
this.#l1ToL2Messages = db.openMap('archiver_l1_to_l2_messages');
|
|
27
27
|
this.#l1ToL2MessageIndices = db.openMap('archiver_l1_to_l2_message_indices');
|
|
28
|
-
this.#
|
|
28
|
+
this.#lastSynchedL1Block = db.openSingleton('archiver_last_l1_block_new_messages');
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -33,7 +33,11 @@ export class MessageStore {
|
|
|
33
33
|
* @returns The last L1 block number processed
|
|
34
34
|
*/
|
|
35
35
|
getSynchedL1BlockNumber(): bigint | undefined {
|
|
36
|
-
return this.#
|
|
36
|
+
return this.#lastSynchedL1Block.get();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
40
|
+
void this.#lastSynchedL1Block.set(l1BlockNumber);
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
/**
|
|
@@ -43,12 +47,12 @@ export class MessageStore {
|
|
|
43
47
|
*/
|
|
44
48
|
addL1ToL2Messages(messages: DataRetrieval<InboxLeaf>): Promise<boolean> {
|
|
45
49
|
return this.db.transaction(() => {
|
|
46
|
-
const lastL1BlockNumber = this.#
|
|
50
|
+
const lastL1BlockNumber = this.#lastSynchedL1Block.get() ?? 0n;
|
|
47
51
|
if (lastL1BlockNumber >= messages.lastProcessedL1BlockNumber) {
|
|
48
52
|
return false;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
void this.#
|
|
55
|
+
void this.#lastSynchedL1Block.set(messages.lastProcessedL1BlockNumber);
|
|
52
56
|
|
|
53
57
|
for (const message of messages.retrievedData) {
|
|
54
58
|
if (message.index >= this.#l1ToL2MessagesSubtreeSize) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type Body,
|
|
3
2
|
type EncryptedL2BlockL2Logs,
|
|
4
3
|
type EncryptedNoteL2BlockL2Logs,
|
|
5
4
|
ExtendedUnencryptedL2Log,
|
|
@@ -40,11 +39,6 @@ export class MemoryArchiverStore implements ArchiverDataStore {
|
|
|
40
39
|
*/
|
|
41
40
|
private l2Blocks: L1Published<L2Block>[] = [];
|
|
42
41
|
|
|
43
|
-
/**
|
|
44
|
-
* A mapping of body hash to body
|
|
45
|
-
*/
|
|
46
|
-
private l2BlockBodies: Map<string, Body> = new Map();
|
|
47
|
-
|
|
48
42
|
/**
|
|
49
43
|
* An array containing all the tx effects in the L2 blocks that have been fetched so far.
|
|
50
44
|
*/
|
|
@@ -84,7 +78,6 @@ export class MemoryArchiverStore implements ArchiverDataStore {
|
|
|
84
78
|
private contractInstances: Map<string, ContractInstanceWithAddress> = new Map();
|
|
85
79
|
|
|
86
80
|
private lastL1BlockNewBlocks: bigint | undefined = undefined;
|
|
87
|
-
private lastL1BlockNewBlockBodies: bigint | undefined = undefined;
|
|
88
81
|
private lastL1BlockNewMessages: bigint | undefined = undefined;
|
|
89
82
|
private lastL1BlockNewProvenLogs: bigint | undefined = undefined;
|
|
90
83
|
|
|
@@ -163,34 +156,10 @@ export class MemoryArchiverStore implements ArchiverDataStore {
|
|
|
163
156
|
this.lastL1BlockNewBlocks = blocks[blocks.length - 1].l1.blockNumber;
|
|
164
157
|
this.l2Blocks.push(...blocks);
|
|
165
158
|
this.txEffects.push(...blocks.flatMap(b => b.data.body.txEffects));
|
|
166
|
-
return Promise.resolve(true);
|
|
167
|
-
}
|
|
168
159
|
|
|
169
|
-
/**
|
|
170
|
-
* Append new block bodies to the store's list.
|
|
171
|
-
* @param blockBodies - The L2 block bodies to be added to the store.
|
|
172
|
-
* @returns True if the operation is successful.
|
|
173
|
-
*/
|
|
174
|
-
addBlockBodies(blockBodies: DataRetrieval<Body>): Promise<boolean> {
|
|
175
|
-
for (const body of blockBodies.retrievedData) {
|
|
176
|
-
void this.l2BlockBodies.set(body.getTxsEffectsHash().toString('hex'), body);
|
|
177
|
-
}
|
|
178
|
-
this.lastL1BlockNewBlockBodies = blockBodies.lastProcessedL1BlockNumber;
|
|
179
160
|
return Promise.resolve(true);
|
|
180
161
|
}
|
|
181
162
|
|
|
182
|
-
/**
|
|
183
|
-
* Gets block bodies that have the same txHashes as we supply.
|
|
184
|
-
*
|
|
185
|
-
* @param txsEffectsHashes - A list of txsEffectsHashes (body hashes).
|
|
186
|
-
* @returns The requested L2 block bodies
|
|
187
|
-
*/
|
|
188
|
-
getBlockBodies(txsEffectsHashes: Buffer[]): Promise<(Body | undefined)[]> {
|
|
189
|
-
return Promise.resolve(
|
|
190
|
-
txsEffectsHashes.map(txsEffectsHash => this.l2BlockBodies.get(txsEffectsHash.toString('hex'))),
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
163
|
/**
|
|
195
164
|
* Append new logs to the store's list.
|
|
196
165
|
* @param encryptedLogs - The encrypted logs to be added to the store.
|
|
@@ -451,11 +420,20 @@ export class MemoryArchiverStore implements ArchiverDataStore {
|
|
|
451
420
|
return Promise.resolve();
|
|
452
421
|
}
|
|
453
422
|
|
|
423
|
+
setBlockSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
424
|
+
this.lastL1BlockNewBlocks = l1BlockNumber;
|
|
425
|
+
return Promise.resolve();
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
setMessageSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
429
|
+
this.lastL1BlockNewMessages = l1BlockNumber;
|
|
430
|
+
return Promise.resolve();
|
|
431
|
+
}
|
|
432
|
+
|
|
454
433
|
public getSynchPoint(): Promise<ArchiverL1SynchPoint> {
|
|
455
434
|
return Promise.resolve({
|
|
456
435
|
blocksSynchedTo: this.lastL1BlockNewBlocks,
|
|
457
436
|
messagesSynchedTo: this.lastL1BlockNewMessages,
|
|
458
|
-
blockBodiesSynchedTo: this.lastL1BlockNewBlockBodies,
|
|
459
437
|
provenLogsSynchedTo: this.lastL1BlockNewProvenLogs,
|
|
460
438
|
});
|
|
461
439
|
}
|
package/src/index.ts
CHANGED
|
@@ -15,8 +15,6 @@ export * from './factory.js';
|
|
|
15
15
|
|
|
16
16
|
export { retrieveL2ProofVerifiedEvents, retrieveBlockFromRollup } from './archiver/data_retrieval.js';
|
|
17
17
|
|
|
18
|
-
export { getL2BlockProposedLogs } from './archiver/eth_log_handlers.js';
|
|
19
|
-
|
|
20
18
|
const log = createDebugLogger('aztec:archiver');
|
|
21
19
|
|
|
22
20
|
/**
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import { InboxLeaf, L2Block } from '@aztec/circuit-types';
|
|
3
|
-
import { Header, Proof } from '@aztec/circuits.js';
|
|
4
|
-
import { type EthAddress } from '@aztec/foundation/eth-address';
|
|
5
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
6
|
-
import { InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
7
|
-
import { type Log, type PublicClient } from 'viem';
|
|
8
|
-
import { type L1Published } from './structs/published.js';
|
|
9
|
-
/**
|
|
10
|
-
* Processes newly received MessageSent (L1 to L2) logs.
|
|
11
|
-
* @param logs - MessageSent logs.
|
|
12
|
-
* @returns Array of all processed MessageSent logs
|
|
13
|
-
*/
|
|
14
|
-
export declare function processMessageSentLogs(logs: Log<bigint, number, false, undefined, true, typeof InboxAbi, 'MessageSent'>[]): InboxLeaf[];
|
|
15
|
-
/**
|
|
16
|
-
* Processes newly received L2BlockProposed logs.
|
|
17
|
-
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
18
|
-
* @param expectedL2BlockNumber - The next expected L2 block number.
|
|
19
|
-
* @param logs - L2BlockProposed logs.
|
|
20
|
-
* @returns - An array blocks.
|
|
21
|
-
*/
|
|
22
|
-
export declare function processL2BlockProposedLogs(publicClient: PublicClient, expectedL2BlockNumber: bigint, logs: Log<bigint, number, false, undefined, true, typeof RollupAbi, 'L2BlockProposed'>[]): Promise<L1Published<L2Block>[]>;
|
|
23
|
-
export declare function getL1BlockTime(publicClient: PublicClient, blockNumber: bigint): Promise<bigint>;
|
|
24
|
-
/**
|
|
25
|
-
* Gets relevant `L2BlockProposed` logs from chain.
|
|
26
|
-
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
27
|
-
* @param rollupAddress - The address of the rollup contract.
|
|
28
|
-
* @param fromBlock - First block to get logs from (inclusive).
|
|
29
|
-
* @param toBlock - Last block to get logs from (inclusive).
|
|
30
|
-
* @returns An array of `L2BlockProposed` logs.
|
|
31
|
-
*/
|
|
32
|
-
export declare function getL2BlockProposedLogs(publicClient: PublicClient, rollupAddress: EthAddress, fromBlock: bigint, toBlock: bigint): Promise<Log<bigint, number, false, undefined, true, typeof RollupAbi, 'L2BlockProposed'>[]>;
|
|
33
|
-
/**
|
|
34
|
-
* Get relevant `MessageSent` logs emitted by Inbox on chain.
|
|
35
|
-
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
36
|
-
* @param inboxAddress - The address of the inbox contract.
|
|
37
|
-
* @param fromBlock - First block to get logs from (inclusive).
|
|
38
|
-
* @param toBlock - Last block to get logs from (inclusive).
|
|
39
|
-
* @returns An array of `MessageSent` logs.
|
|
40
|
-
*/
|
|
41
|
-
export declare function getMessageSentLogs(publicClient: PublicClient, inboxAddress: EthAddress, fromBlock: bigint, toBlock: bigint): Promise<Log<bigint, number, false, undefined, true, typeof InboxAbi, 'MessageSent'>[]>;
|
|
42
|
-
export type SubmitBlockProof = {
|
|
43
|
-
header: Header;
|
|
44
|
-
archiveRoot: Fr;
|
|
45
|
-
proverId: Fr;
|
|
46
|
-
aggregationObject: Buffer;
|
|
47
|
-
proof: Proof;
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* Gets block metadata (header and archive snapshot) from the calldata of an L1 transaction.
|
|
51
|
-
* Assumes that the block was published from an EOA.
|
|
52
|
-
* TODO: Add retries and error management.
|
|
53
|
-
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
54
|
-
* @param txHash - Hash of the tx that published it.
|
|
55
|
-
* @param l2BlockNum - L2 block number.
|
|
56
|
-
* @returns L2 block metadata (header and archive) from the calldata, deserialized
|
|
57
|
-
*/
|
|
58
|
-
export declare function getBlockProofFromSubmitProofTx(publicClient: PublicClient, txHash: `0x${string}`, l2BlockNum: bigint, expectedProverId: Fr): Promise<SubmitBlockProof>;
|
|
59
|
-
//# sourceMappingURL=eth_log_handlers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"eth_log_handlers.d.ts","sourceRoot":"","sources":["../../src/archiver/eth_log_handlers.ts"],"names":[],"mappings":";AAAA,OAAO,EAAQ,SAAS,EAAE,OAAO,EAAsB,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAA0B,MAAM,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAY,KAAK,GAAG,EAAE,KAAK,YAAY,EAA0D,MAAM,MAAM,CAAC;AAErH,OAAO,EAAE,KAAK,WAAW,EAAwB,MAAM,wBAAwB,CAAC;AAEhF;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,QAAQ,EAAE,aAAa,CAAC,EAAE,GAClF,SAAS,EAAE,CAOb;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,YAAY,EAC1B,qBAAqB,EAAE,MAAM,EAC7B,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,SAAS,EAAE,iBAAiB,CAAC,EAAE,GACvF,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAqBjC;AAED,wBAAsB,cAAc,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrG;AA8CD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,YAAY,EAC1B,aAAa,EAAE,UAAU,EACzB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,SAAS,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAU7F;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,UAAU,EACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC,CAUxF;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,EAAE,CAAC;IAChB,QAAQ,EAAE,EAAE,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,8BAA8B,CAClD,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,KAAK,MAAM,EAAE,EACrB,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,EAAE,GACnB,OAAO,CAAC,gBAAgB,CAAC,CA8B3B"}
|