@aztec/archiver 0.48.0 → 0.50.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/archiver/archiver.d.ts +4 -0
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +26 -10
- package/dest/archiver/archiver_store.d.ts +4 -2
- 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 +21 -5
- package/dest/archiver/data_retrieval.d.ts +4 -4
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +8 -5
- package/dest/archiver/eth_log_handlers.js +6 -6
- package/dest/archiver/instrumentation.js +2 -2
- package/dest/archiver/kv_archiver_store/block_body_store.d.ts +7 -1
- package/dest/archiver/kv_archiver_store/block_body_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_body_store.js +15 -4
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +2 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +2 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +5 -2
- package/package.json +10 -10
- package/src/archiver/archiver.ts +32 -12
- package/src/archiver/archiver_store.ts +4 -2
- package/src/archiver/archiver_store_test_suite.ts +26 -9
- package/src/archiver/data_retrieval.ts +14 -6
- package/src/archiver/eth_log_handlers.ts +5 -5
- package/src/archiver/instrumentation.ts +1 -1
- package/src/archiver/kv_archiver_store/block_body_store.ts +18 -4
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +2 -1
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +5 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InboxLeaf, L2Block, LogId, LogType, TxHash } from '@aztec/circuit-types';
|
|
1
|
+
import { type Body, InboxLeaf, L2Block, LogId, LogType, TxHash } from '@aztec/circuit-types';
|
|
2
2
|
import '@aztec/circuit-types/jest';
|
|
3
3
|
import { AztecAddress, Fr, INITIAL_L2_BLOCK_NUM, L1_TO_L2_MSG_SUBTREE_HEIGHT } from '@aztec/circuits.js';
|
|
4
4
|
import {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
SerializableContractInstance,
|
|
15
15
|
} from '@aztec/types/contracts';
|
|
16
16
|
|
|
17
|
-
import { type ArchiverDataStore } from './archiver_store.js';
|
|
17
|
+
import { type ArchiverDataStore, type ArchiverL1SynchPoint } from './archiver_store.js';
|
|
18
18
|
import { type DataRetrieval } from './data_retrieval.js';
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -25,6 +25,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
|
|
|
25
25
|
describe(testName, () => {
|
|
26
26
|
let store: ArchiverDataStore;
|
|
27
27
|
let blocks: DataRetrieval<L2Block>;
|
|
28
|
+
let blockBodies: DataRetrieval<Body>;
|
|
28
29
|
const blockTests: [number, number, () => L2Block[]][] = [
|
|
29
30
|
[1, 1, () => blocks.retrievedData.slice(0, 1)],
|
|
30
31
|
[10, 1, () => blocks.retrievedData.slice(9, 10)],
|
|
@@ -39,11 +40,15 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
|
|
|
39
40
|
lastProcessedL1BlockNumber: 5n,
|
|
40
41
|
retrievedData: Array.from({ length: 10 }).map((_, i) => L2Block.random(i + 1)),
|
|
41
42
|
};
|
|
43
|
+
blockBodies = {
|
|
44
|
+
retrievedData: blocks.retrievedData.map(block => block.body),
|
|
45
|
+
lastProcessedL1BlockNumber: 4n,
|
|
46
|
+
};
|
|
42
47
|
});
|
|
43
48
|
|
|
44
49
|
describe('addBlocks', () => {
|
|
45
50
|
it('returns success when adding block bodies', async () => {
|
|
46
|
-
await expect(store.addBlockBodies(
|
|
51
|
+
await expect(store.addBlockBodies(blockBodies)).resolves.toBe(true);
|
|
47
52
|
});
|
|
48
53
|
|
|
49
54
|
it('returns success when adding blocks', async () => {
|
|
@@ -59,7 +64,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
|
|
|
59
64
|
describe('getBlocks', () => {
|
|
60
65
|
beforeEach(async () => {
|
|
61
66
|
await store.addBlocks(blocks);
|
|
62
|
-
await store.addBlockBodies(
|
|
67
|
+
await store.addBlockBodies(blockBodies);
|
|
63
68
|
});
|
|
64
69
|
|
|
65
70
|
it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks) => {
|
|
@@ -95,7 +100,8 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
|
|
|
95
100
|
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
96
101
|
blocksSynchedTo: 0n,
|
|
97
102
|
messagesSynchedTo: 0n,
|
|
98
|
-
|
|
103
|
+
blockBodiesSynchedTo: 0n,
|
|
104
|
+
} satisfies ArchiverL1SynchPoint);
|
|
99
105
|
});
|
|
100
106
|
|
|
101
107
|
it('returns the L1 block number in which the most recent L2 block was published', async () => {
|
|
@@ -103,7 +109,17 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
|
|
|
103
109
|
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
104
110
|
blocksSynchedTo: blocks.lastProcessedL1BlockNumber,
|
|
105
111
|
messagesSynchedTo: 0n,
|
|
106
|
-
|
|
112
|
+
blockBodiesSynchedTo: 0n,
|
|
113
|
+
} satisfies ArchiverL1SynchPoint);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('returns the L1 block number in which the most recent L2 block body was published', async () => {
|
|
117
|
+
await store.addBlockBodies(blockBodies);
|
|
118
|
+
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
119
|
+
blocksSynchedTo: 0n,
|
|
120
|
+
messagesSynchedTo: 0n,
|
|
121
|
+
blockBodiesSynchedTo: blockBodies.lastProcessedL1BlockNumber,
|
|
122
|
+
} satisfies ArchiverL1SynchPoint);
|
|
107
123
|
});
|
|
108
124
|
|
|
109
125
|
it('returns the L1 block number that most recently added messages from inbox', async () => {
|
|
@@ -114,7 +130,8 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
|
|
|
114
130
|
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
115
131
|
blocksSynchedTo: 0n,
|
|
116
132
|
messagesSynchedTo: 1n,
|
|
117
|
-
|
|
133
|
+
blockBodiesSynchedTo: 0n,
|
|
134
|
+
} satisfies ArchiverL1SynchPoint);
|
|
118
135
|
});
|
|
119
136
|
});
|
|
120
137
|
|
|
@@ -179,7 +196,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
|
|
|
179
196
|
),
|
|
180
197
|
);
|
|
181
198
|
await store.addBlocks(blocks);
|
|
182
|
-
await store.addBlockBodies(
|
|
199
|
+
await store.addBlockBodies(blockBodies);
|
|
183
200
|
});
|
|
184
201
|
|
|
185
202
|
it.each([
|
|
@@ -335,7 +352,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
|
|
|
335
352
|
};
|
|
336
353
|
|
|
337
354
|
await store.addBlocks(blocks);
|
|
338
|
-
await store.addBlockBodies(
|
|
355
|
+
await store.addBlockBodies(blockBodies);
|
|
339
356
|
|
|
340
357
|
await Promise.all(
|
|
341
358
|
blocks.retrievedData.map(block =>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Body, type InboxLeaf } from '@aztec/circuit-types';
|
|
2
2
|
import { type AppendOnlyTreeSnapshot, Fr, type Header } from '@aztec/circuits.js';
|
|
3
3
|
import { type EthAddress } from '@aztec/foundation/eth-address';
|
|
4
|
+
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
|
|
4
5
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
5
6
|
|
|
6
7
|
import { type PublicClient, getAbiItem } from 'viem';
|
|
@@ -45,6 +46,7 @@ export async function retrieveBlockMetadataFromRollup(
|
|
|
45
46
|
searchStartBlock: bigint,
|
|
46
47
|
searchEndBlock: bigint,
|
|
47
48
|
expectedNextL2BlockNum: bigint,
|
|
49
|
+
logger: DebugLogger = createDebugLogger('aztec:archiver'),
|
|
48
50
|
): Promise<DataRetrieval<[Header, AppendOnlyTreeSnapshot]>> {
|
|
49
51
|
const retrievedBlockMetadata: [Header, AppendOnlyTreeSnapshot][] = [];
|
|
50
52
|
do {
|
|
@@ -61,13 +63,18 @@ export async function retrieveBlockMetadataFromRollup(
|
|
|
61
63
|
break;
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
const lastLog = l2BlockProcessedLogs[l2BlockProcessedLogs.length - 1];
|
|
67
|
+
logger.debug(
|
|
68
|
+
`Got L2 block processed logs for ${l2BlockProcessedLogs[0].blockNumber}-${lastLog.blockNumber} between ${searchStartBlock}-${searchEndBlock} L1 blocks`,
|
|
69
|
+
);
|
|
70
|
+
|
|
64
71
|
const newBlockMetadata = await processL2BlockProcessedLogs(
|
|
65
72
|
publicClient,
|
|
66
73
|
expectedNextL2BlockNum,
|
|
67
74
|
l2BlockProcessedLogs,
|
|
68
75
|
);
|
|
69
76
|
retrievedBlockMetadata.push(...newBlockMetadata);
|
|
70
|
-
searchStartBlock =
|
|
77
|
+
searchStartBlock = lastLog.blockNumber! + 1n;
|
|
71
78
|
expectedNextL2BlockNum += BigInt(newBlockMetadata.length);
|
|
72
79
|
} while (blockUntilSynced && searchStartBlock <= searchEndBlock);
|
|
73
80
|
return { lastProcessedL1BlockNumber: searchStartBlock - 1n, retrievedData: retrievedBlockMetadata };
|
|
@@ -80,7 +87,7 @@ export async function retrieveBlockMetadataFromRollup(
|
|
|
80
87
|
* @param blockUntilSynced - If true, blocks until the archiver has fully synced.
|
|
81
88
|
* @param searchStartBlock - The block number to use for starting the search.
|
|
82
89
|
* @param searchEndBlock - The highest block number that we should search up to.
|
|
83
|
-
* @returns A array of
|
|
90
|
+
* @returns A array of L2 block bodies as well as the next eth block to search from
|
|
84
91
|
*/
|
|
85
92
|
export async function retrieveBlockBodiesFromAvailabilityOracle(
|
|
86
93
|
publicClient: PublicClient,
|
|
@@ -88,8 +95,8 @@ export async function retrieveBlockBodiesFromAvailabilityOracle(
|
|
|
88
95
|
blockUntilSynced: boolean,
|
|
89
96
|
searchStartBlock: bigint,
|
|
90
97
|
searchEndBlock: bigint,
|
|
91
|
-
): Promise<DataRetrieval<
|
|
92
|
-
const retrievedBlockBodies:
|
|
98
|
+
): Promise<DataRetrieval<Body>> {
|
|
99
|
+
const retrievedBlockBodies: Body[] = [];
|
|
93
100
|
|
|
94
101
|
do {
|
|
95
102
|
if (searchStartBlock > searchEndBlock) {
|
|
@@ -106,9 +113,10 @@ export async function retrieveBlockBodiesFromAvailabilityOracle(
|
|
|
106
113
|
}
|
|
107
114
|
|
|
108
115
|
const newBlockBodies = await processTxsPublishedLogs(publicClient, l2TxsPublishedLogs);
|
|
109
|
-
retrievedBlockBodies.push(...newBlockBodies);
|
|
110
|
-
searchStartBlock = l2TxsPublishedLogs[l2TxsPublishedLogs.length - 1].blockNumber
|
|
116
|
+
retrievedBlockBodies.push(...newBlockBodies.map(([body]) => body));
|
|
117
|
+
searchStartBlock = l2TxsPublishedLogs[l2TxsPublishedLogs.length - 1].blockNumber + 1n;
|
|
111
118
|
} while (blockUntilSynced && searchStartBlock <= searchEndBlock);
|
|
119
|
+
|
|
112
120
|
return { lastProcessedL1BlockNumber: searchStartBlock - 1n, retrievedData: retrievedBlockBodies };
|
|
113
121
|
}
|
|
114
122
|
|
|
@@ -100,7 +100,7 @@ async function getBlockMetadataFromRollupTx(
|
|
|
100
100
|
if (!(functionName === 'process' || functionName === 'publishAndProcess')) {
|
|
101
101
|
throw new Error(`Unexpected method called ${functionName}`);
|
|
102
102
|
}
|
|
103
|
-
const [headerHex, archiveRootHex] = args! as readonly [Hex, Hex];
|
|
103
|
+
const [headerHex, archiveRootHex, _] = args! as readonly [Hex, Hex, Hex];
|
|
104
104
|
|
|
105
105
|
const header = Header.fromBuffer(Buffer.from(hexToBytes(headerHex)));
|
|
106
106
|
|
|
@@ -133,16 +133,16 @@ async function getBlockBodiesFromAvailabilityOracleTx(
|
|
|
133
133
|
txHash: `0x${string}`,
|
|
134
134
|
): Promise<Body> {
|
|
135
135
|
const { input: data } = await publicClient.getTransaction({ hash: txHash });
|
|
136
|
-
const DATA_INDEX = [
|
|
136
|
+
const DATA_INDEX = [4, 3, 0];
|
|
137
137
|
|
|
138
138
|
// @note Use `forge inspect Rollup methodIdentifiers to get this,
|
|
139
139
|
// If using `forge sig` you will get an INVALID value for the case with a struct.
|
|
140
140
|
// [
|
|
141
|
-
// "publishAndProcess(bytes calldata _header,bytes32 _archive,SignatureLib.Signature[] memory _signatures,bytes calldata _body)",
|
|
142
|
-
// "publishAndProcess(bytes calldata _header,bytes32 _archive,bytes calldata _body)",
|
|
141
|
+
// "publishAndProcess(bytes calldata _header,bytes32 _archive,bytes32 _blockHash,SignatureLib.Signature[] memory _signatures,bytes calldata _body)",
|
|
142
|
+
// "publishAndProcess(bytes calldata _header,bytes32 _archive,bytes32 _blockHash,bytes calldata _body)",
|
|
143
143
|
// "publish(bytes calldata _body)"
|
|
144
144
|
// ]
|
|
145
|
-
const SUPPORTED_SIGS = ['
|
|
145
|
+
const SUPPORTED_SIGS = ['0x64450c6c', '0xde36c478', '0x7fd28346'];
|
|
146
146
|
|
|
147
147
|
const signature = slice(data, 0, 4);
|
|
148
148
|
|
|
@@ -37,7 +37,7 @@ export class ArchiverInstrumentation {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
public processNewBlocks(syncTimePerBlock: number, blocks: L2Block[]) {
|
|
40
|
-
this.syncDuration.record(syncTimePerBlock);
|
|
40
|
+
this.syncDuration.record(Math.ceil(syncTimePerBlock));
|
|
41
41
|
this.blockHeight.record(Math.max(...blocks.map(b => b.number)));
|
|
42
42
|
for (const block of blocks) {
|
|
43
43
|
this.blockSize.record(block.body.txEffects.length);
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { Body } from '@aztec/circuit-types';
|
|
2
2
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
3
|
-
import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';
|
|
3
|
+
import { type AztecKVStore, type AztecMap, type AztecSingleton } from '@aztec/kv-store';
|
|
4
|
+
|
|
5
|
+
import { type DataRetrieval } from '../data_retrieval.js';
|
|
4
6
|
|
|
5
7
|
export class BlockBodyStore {
|
|
6
8
|
/** Map block body hash to block body */
|
|
7
9
|
#blockBodies: AztecMap<string, Buffer>;
|
|
8
10
|
|
|
11
|
+
/** Stores L1 block number in which the last processed L2 block body was included */
|
|
12
|
+
#lastSynchedL1Block: AztecSingleton<bigint>;
|
|
13
|
+
|
|
9
14
|
constructor(private db: AztecKVStore, private log = createDebugLogger('aztec:archiver:block_body_store')) {
|
|
10
15
|
this.#blockBodies = db.openMap('archiver_block_bodies');
|
|
16
|
+
this.#lastSynchedL1Block = db.openSingleton('archiver_block_bodies_last_synched_l1_block');
|
|
11
17
|
}
|
|
12
18
|
|
|
13
19
|
/**
|
|
@@ -15,12 +21,12 @@ export class BlockBodyStore {
|
|
|
15
21
|
* @param blockBodies - The L2 block bodies to be added to the store.
|
|
16
22
|
* @returns True if the operation is successful.
|
|
17
23
|
*/
|
|
18
|
-
addBlockBodies(blockBodies: Body
|
|
24
|
+
addBlockBodies(blockBodies: DataRetrieval<Body>): Promise<boolean> {
|
|
19
25
|
return this.db.transaction(() => {
|
|
20
|
-
for (const body of blockBodies) {
|
|
26
|
+
for (const body of blockBodies.retrievedData) {
|
|
21
27
|
void this.#blockBodies.set(body.getTxsEffectsHash().toString('hex'), body.toBuffer());
|
|
22
28
|
}
|
|
23
|
-
|
|
29
|
+
void this.#lastSynchedL1Block.set(blockBodies.lastProcessedL1BlockNumber);
|
|
24
30
|
return true;
|
|
25
31
|
});
|
|
26
32
|
}
|
|
@@ -57,4 +63,12 @@ export class BlockBodyStore {
|
|
|
57
63
|
|
|
58
64
|
return blockBody && Body.fromBuffer(blockBody);
|
|
59
65
|
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Gets the last L1 block number in which a L2 block body was included
|
|
69
|
+
* @returns The L1 block number
|
|
70
|
+
*/
|
|
71
|
+
getSynchedL1BlockNumber(): bigint {
|
|
72
|
+
return this.#lastSynchedL1Block.get() ?? 0n;
|
|
73
|
+
}
|
|
60
74
|
}
|
|
@@ -101,7 +101,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
101
101
|
* @param blockBodies - The L2 block bodies to be added to the store.
|
|
102
102
|
* @returns True if the operation is successful.
|
|
103
103
|
*/
|
|
104
|
-
addBlockBodies(blockBodies: Body
|
|
104
|
+
addBlockBodies(blockBodies: DataRetrieval<Body>): Promise<boolean> {
|
|
105
105
|
return this.#blockBodyStore.addBlockBodies(blockBodies);
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -260,6 +260,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
260
260
|
getSynchPoint(): Promise<ArchiverL1SynchPoint> {
|
|
261
261
|
return Promise.resolve({
|
|
262
262
|
blocksSynchedTo: this.#blockStore.getSynchedL1BlockNumber(),
|
|
263
|
+
blockBodiesSynchedTo: this.#blockBodyStore.getSynchedL1BlockNumber(),
|
|
263
264
|
messagesSynchedTo: this.#messageStore.getSynchedL1BlockNumber(),
|
|
264
265
|
});
|
|
265
266
|
}
|
|
@@ -83,6 +83,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
|
|
|
83
83
|
private contractInstances: Map<string, ContractInstanceWithAddress> = new Map();
|
|
84
84
|
|
|
85
85
|
private lastL1BlockNewBlocks: bigint = 0n;
|
|
86
|
+
private lastL1BlockNewBlockBodies: bigint = 0n;
|
|
86
87
|
private lastL1BlockNewMessages: bigint = 0n;
|
|
87
88
|
private lastProvenL2BlockNumber: number = 0;
|
|
88
89
|
|
|
@@ -163,11 +164,11 @@ export class MemoryArchiverStore implements ArchiverDataStore {
|
|
|
163
164
|
* @param blockBodies - The L2 block bodies to be added to the store.
|
|
164
165
|
* @returns True if the operation is successful.
|
|
165
166
|
*/
|
|
166
|
-
addBlockBodies(blockBodies: Body
|
|
167
|
-
for (const body of blockBodies) {
|
|
167
|
+
addBlockBodies(blockBodies: DataRetrieval<Body>): Promise<boolean> {
|
|
168
|
+
for (const body of blockBodies.retrievedData) {
|
|
168
169
|
void this.l2BlockBodies.set(body.getTxsEffectsHash().toString('hex'), body);
|
|
169
170
|
}
|
|
170
|
-
|
|
171
|
+
this.lastL1BlockNewBlockBodies = blockBodies.lastProcessedL1BlockNumber;
|
|
171
172
|
return Promise.resolve(true);
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -443,6 +444,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
|
|
|
443
444
|
return Promise.resolve({
|
|
444
445
|
blocksSynchedTo: this.lastL1BlockNewBlocks,
|
|
445
446
|
messagesSynchedTo: this.lastL1BlockNewMessages,
|
|
447
|
+
blockBodiesSynchedTo: this.lastL1BlockNewBlockBodies,
|
|
446
448
|
});
|
|
447
449
|
}
|
|
448
450
|
|