@aztec/archiver 0.80.0 → 0.82.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 +8 -20
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +72 -102
- package/dest/archiver/archiver_store.d.ts +5 -19
- 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 +105 -142
- package/dest/archiver/config.d.ts +2 -0
- package/dest/archiver/config.d.ts.map +1 -1
- package/dest/archiver/config.js +5 -0
- package/dest/archiver/data_retrieval.d.ts +3 -4
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +8 -3
- package/dest/archiver/index.d.ts +1 -2
- package/dest/archiver/index.d.ts.map +1 -1
- package/dest/archiver/index.js +0 -1
- package/dest/archiver/kv_archiver_store/block_store.d.ts +6 -6
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +24 -21
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +6 -14
- 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 -19
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/log_store.js +11 -42
- package/dest/archiver/structs/published.d.ts +1 -10
- package/dest/archiver/structs/published.d.ts.map +1 -1
- package/dest/archiver/structs/published.js +1 -1
- package/dest/factory.d.ts +1 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +6 -24
- package/dest/test/mock_l2_block_source.d.ts +10 -0
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +16 -0
- package/package.json +12 -13
- package/src/archiver/archiver.ts +86 -124
- package/src/archiver/archiver_store.ts +5 -21
- package/src/archiver/archiver_store_test_suite.ts +116 -147
- package/src/archiver/config.ts +8 -0
- package/src/archiver/data_retrieval.ts +12 -11
- package/src/archiver/index.ts +1 -2
- package/src/archiver/kv_archiver_store/block_store.ts +28 -27
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +6 -27
- package/src/archiver/kv_archiver_store/log_store.ts +12 -59
- package/src/archiver/structs/published.ts +1 -11
- package/src/factory.ts +3 -28
- package/src/test/mock_l2_block_source.ts +18 -0
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts +0 -12
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/nullifier_store.js +0 -73
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +0 -175
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +0 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +0 -636
- package/src/archiver/kv_archiver_store/nullifier_store.ts +0 -97
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +0 -801
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
2
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
2
3
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
5
|
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncSingleton, Range } from '@aztec/kv-store';
|
|
@@ -7,9 +8,9 @@ import { Body, type InBlock, L2Block, L2BlockHash } from '@aztec/stdlib/block';
|
|
|
7
8
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
8
9
|
import { BlockHeader, TxEffect, TxHash, TxReceipt } from '@aztec/stdlib/tx';
|
|
9
10
|
|
|
10
|
-
import type {
|
|
11
|
+
import type { L1PublishedData, PublishedL2Block } from '../structs/published.js';
|
|
11
12
|
|
|
12
|
-
export { type TxEffect, type TxHash
|
|
13
|
+
export { TxReceipt, type TxEffect, type TxHash } from '@aztec/stdlib/tx';
|
|
13
14
|
|
|
14
15
|
type BlockIndexValue = [blockNumber: number, index: number];
|
|
15
16
|
|
|
@@ -17,6 +18,7 @@ type BlockStorage = {
|
|
|
17
18
|
header: Buffer;
|
|
18
19
|
archive: Buffer;
|
|
19
20
|
l1: L1PublishedData;
|
|
21
|
+
signatures: Buffer[];
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
/**
|
|
@@ -61,25 +63,26 @@ export class BlockStore {
|
|
|
61
63
|
* @param blocks - The L2 blocks to be added to the store.
|
|
62
64
|
* @returns True if the operation is successful.
|
|
63
65
|
*/
|
|
64
|
-
async addBlocks(blocks:
|
|
66
|
+
async addBlocks(blocks: PublishedL2Block[]): Promise<boolean> {
|
|
65
67
|
if (blocks.length === 0) {
|
|
66
68
|
return true;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
return await this.db.transactionAsync(async () => {
|
|
70
72
|
for (const block of blocks) {
|
|
71
|
-
await this.#blocks.set(block.
|
|
72
|
-
header: block.
|
|
73
|
-
archive: block.
|
|
73
|
+
await this.#blocks.set(block.block.number, {
|
|
74
|
+
header: block.block.header.toBuffer(),
|
|
75
|
+
archive: block.block.archive.toBuffer(),
|
|
74
76
|
l1: block.l1,
|
|
77
|
+
signatures: block.signatures.map(sig => sig.toBuffer()),
|
|
75
78
|
});
|
|
76
79
|
|
|
77
|
-
for (let i = 0; i < block.
|
|
78
|
-
const txEffect = block.
|
|
79
|
-
await this.#txIndex.set(txEffect.txHash.toString(), [block.
|
|
80
|
+
for (let i = 0; i < block.block.body.txEffects.length; i++) {
|
|
81
|
+
const txEffect = block.block.body.txEffects[i];
|
|
82
|
+
await this.#txIndex.set(txEffect.txHash.toString(), [block.block.number, i]);
|
|
80
83
|
}
|
|
81
84
|
|
|
82
|
-
await this.#blockBodies.set((await block.
|
|
85
|
+
await this.#blockBodies.set((await block.block.hash()).toString(), block.block.body.toBuffer());
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
await this.#lastSynchedL1Block.set(blocks[blocks.length - 1].l1.blockNumber);
|
|
@@ -109,9 +112,9 @@ export class BlockStore {
|
|
|
109
112
|
this.#log.warn(`Cannot remove block ${blockNumber} from the store since we don't have it`);
|
|
110
113
|
continue;
|
|
111
114
|
}
|
|
112
|
-
await this.#blocks.delete(block.
|
|
113
|
-
await Promise.all(block.
|
|
114
|
-
const blockHash = (await block.
|
|
115
|
+
await this.#blocks.delete(block.block.number);
|
|
116
|
+
await Promise.all(block.block.body.txEffects.map(tx => this.#txIndex.delete(tx.txHash.toString())));
|
|
117
|
+
const blockHash = (await block.block.hash()).toString();
|
|
115
118
|
await this.#blockBodies.delete(blockHash);
|
|
116
119
|
this.#log.debug(`Unwound block ${blockNumber} ${blockHash}`);
|
|
117
120
|
}
|
|
@@ -126,10 +129,9 @@ export class BlockStore {
|
|
|
126
129
|
* @param limit - The number of blocks to return.
|
|
127
130
|
* @returns The requested L2 blocks
|
|
128
131
|
*/
|
|
129
|
-
async *getBlocks(start: number, limit: number): AsyncIterableIterator<
|
|
132
|
+
async *getBlocks(start: number, limit: number): AsyncIterableIterator<PublishedL2Block> {
|
|
130
133
|
for await (const blockStorage of this.#blocks.valuesAsync(this.#computeBlockRange(start, limit))) {
|
|
131
|
-
|
|
132
|
-
yield block;
|
|
134
|
+
yield await this.getBlockFromBlockStorage(blockStorage);
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
@@ -138,12 +140,11 @@ export class BlockStore {
|
|
|
138
140
|
* @param blockNumber - The number of the block to return.
|
|
139
141
|
* @returns The requested L2 block.
|
|
140
142
|
*/
|
|
141
|
-
async getBlock(blockNumber: number): Promise<
|
|
143
|
+
async getBlock(blockNumber: number): Promise<PublishedL2Block | undefined> {
|
|
142
144
|
const blockStorage = await this.#blocks.getAsync(blockNumber);
|
|
143
145
|
if (!blockStorage || !blockStorage.header) {
|
|
144
146
|
return Promise.resolve(undefined);
|
|
145
147
|
}
|
|
146
|
-
|
|
147
148
|
return this.getBlockFromBlockStorage(blockStorage);
|
|
148
149
|
}
|
|
149
150
|
|
|
@@ -170,9 +171,9 @@ export class BlockStore {
|
|
|
170
171
|
);
|
|
171
172
|
}
|
|
172
173
|
const body = Body.fromBuffer(blockBodyBuffer);
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
return {
|
|
174
|
+
const block = new L2Block(archive, header, body);
|
|
175
|
+
const signatures = blockStorage.signatures.map(Signature.fromBuffer);
|
|
176
|
+
return { block, l1: blockStorage.l1, signatures };
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
/**
|
|
@@ -192,9 +193,9 @@ export class BlockStore {
|
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
return {
|
|
195
|
-
data: block.
|
|
196
|
-
l2BlockNumber: block.
|
|
197
|
-
l2BlockHash: (await block.
|
|
196
|
+
data: block.block.body.txEffects[txIndex],
|
|
197
|
+
l2BlockNumber: block.block.number,
|
|
198
|
+
l2BlockHash: (await block.block.hash()).toString(),
|
|
198
199
|
};
|
|
199
200
|
}
|
|
200
201
|
|
|
@@ -210,15 +211,15 @@ export class BlockStore {
|
|
|
210
211
|
}
|
|
211
212
|
|
|
212
213
|
const block = (await this.getBlock(blockNumber))!;
|
|
213
|
-
const tx = block.
|
|
214
|
+
const tx = block.block.body.txEffects[txIndex];
|
|
214
215
|
|
|
215
216
|
return new TxReceipt(
|
|
216
217
|
txHash,
|
|
217
218
|
TxReceipt.statusFromRevertCode(tx.revertCode),
|
|
218
219
|
'',
|
|
219
220
|
tx.transactionFee.toBigInt(),
|
|
220
|
-
L2BlockHash.fromField(await block.
|
|
221
|
-
block.
|
|
221
|
+
L2BlockHash.fromField(await block.block.hash()),
|
|
222
|
+
block.block.number,
|
|
222
223
|
);
|
|
223
224
|
}
|
|
224
225
|
|
|
@@ -4,7 +4,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
4
4
|
import type { AztecAsyncKVStore, StoreSize } from '@aztec/kv-store';
|
|
5
5
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
6
6
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
7
|
-
import type {
|
|
7
|
+
import type { L2Block } from '@aztec/stdlib/block';
|
|
8
8
|
import type {
|
|
9
9
|
ContractClassPublic,
|
|
10
10
|
ContractInstanceUpdateWithAddress,
|
|
@@ -19,13 +19,12 @@ import type { BlockHeader, TxHash, TxReceipt } from '@aztec/stdlib/tx';
|
|
|
19
19
|
|
|
20
20
|
import type { ArchiverDataStore, ArchiverL1SynchPoint } from '../archiver_store.js';
|
|
21
21
|
import type { DataRetrieval } from '../structs/data_retrieval.js';
|
|
22
|
-
import type {
|
|
22
|
+
import type { PublishedL2Block } from '../structs/published.js';
|
|
23
23
|
import { BlockStore } from './block_store.js';
|
|
24
24
|
import { ContractClassStore } from './contract_class_store.js';
|
|
25
25
|
import { ContractInstanceStore } from './contract_instance_store.js';
|
|
26
26
|
import { LogStore } from './log_store.js';
|
|
27
27
|
import { MessageStore } from './message_store.js';
|
|
28
|
-
import { NullifierStore } from './nullifier_store.js';
|
|
29
28
|
|
|
30
29
|
/**
|
|
31
30
|
* LMDB implementation of the ArchiverDataStore interface.
|
|
@@ -35,7 +34,6 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
35
34
|
|
|
36
35
|
#blockStore: BlockStore;
|
|
37
36
|
#logStore: LogStore;
|
|
38
|
-
#nullifierStore: NullifierStore;
|
|
39
37
|
#messageStore: MessageStore;
|
|
40
38
|
#contractClassStore: ContractClassStore;
|
|
41
39
|
#contractInstanceStore: ContractInstanceStore;
|
|
@@ -49,7 +47,6 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
49
47
|
this.#messageStore = new MessageStore(db);
|
|
50
48
|
this.#contractClassStore = new ContractClassStore(db);
|
|
51
49
|
this.#contractInstanceStore = new ContractInstanceStore(db);
|
|
52
|
-
this.#nullifierStore = new NullifierStore(db);
|
|
53
50
|
}
|
|
54
51
|
|
|
55
52
|
// TODO: These function names are in memory only as they are for development/debugging. They require the full contract
|
|
@@ -78,9 +75,8 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
78
75
|
return this.#contractClassStore.getContractClassIds();
|
|
79
76
|
}
|
|
80
77
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return contract;
|
|
78
|
+
getContractInstance(address: AztecAddress, blockNumber: number): Promise<ContractInstanceWithAddress | undefined> {
|
|
79
|
+
return this.#contractInstanceStore.getContractInstance(address, blockNumber);
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
async addContractClasses(
|
|
@@ -148,7 +144,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
148
144
|
* @param blocks - The L2 blocks to be added to the store and the last processed L1 block.
|
|
149
145
|
* @returns True if the operation is successful.
|
|
150
146
|
*/
|
|
151
|
-
addBlocks(blocks:
|
|
147
|
+
addBlocks(blocks: PublishedL2Block[]): Promise<boolean> {
|
|
152
148
|
return this.#blockStore.addBlocks(blocks);
|
|
153
149
|
}
|
|
154
150
|
|
|
@@ -170,7 +166,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
170
166
|
* @param limit - The number of blocks to return.
|
|
171
167
|
* @returns The requested L2 blocks
|
|
172
168
|
*/
|
|
173
|
-
getBlocks(start: number, limit: number): Promise<
|
|
169
|
+
getBlocks(start: number, limit: number): Promise<PublishedL2Block[]> {
|
|
174
170
|
return toArray(this.#blockStore.getBlocks(start, limit));
|
|
175
171
|
}
|
|
176
172
|
|
|
@@ -216,23 +212,6 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
216
212
|
return this.#logStore.deleteLogs(blocks);
|
|
217
213
|
}
|
|
218
214
|
|
|
219
|
-
/**
|
|
220
|
-
* Append new nullifiers to the store's list.
|
|
221
|
-
* @param blocks - The blocks for which to add the nullifiers.
|
|
222
|
-
* @returns True if the operation is successful.
|
|
223
|
-
*/
|
|
224
|
-
addNullifiers(blocks: L2Block[]): Promise<boolean> {
|
|
225
|
-
return this.#nullifierStore.addNullifiers(blocks);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
deleteNullifiers(blocks: L2Block[]): Promise<boolean> {
|
|
229
|
-
return this.#nullifierStore.deleteNullifiers(blocks);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
findNullifiersIndexesWithBlock(blockNumber: number, nullifiers: Fr[]): Promise<(InBlock<bigint> | undefined)[]> {
|
|
233
|
-
return this.#nullifierStore.findNullifiersIndexesWithBlock(blockNumber, nullifiers);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
215
|
getTotalL1ToL2MessageCount(): Promise<bigint> {
|
|
237
216
|
return this.#messageStore.getTotalL1ToL2MessageCount();
|
|
238
217
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX
|
|
1
|
+
import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX } from '@aztec/constants';
|
|
2
2
|
import type { Fr } from '@aztec/foundation/fields';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';
|
|
@@ -40,7 +40,7 @@ export class LogStore {
|
|
|
40
40
|
this.#logsMaxPageSize = logsMaxPageSize;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
#
|
|
43
|
+
#extractTaggedLogs(block: L2Block) {
|
|
44
44
|
const taggedLogs = new Map<string, Buffer[]>();
|
|
45
45
|
const dataStartIndexForBlock =
|
|
46
46
|
block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
|
|
@@ -48,68 +48,22 @@ export class LogStore {
|
|
|
48
48
|
block.body.txEffects.forEach((txEffect, txIndex) => {
|
|
49
49
|
const txHash = txEffect.txHash;
|
|
50
50
|
const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
|
|
51
|
+
|
|
51
52
|
txEffect.privateLogs.forEach(log => {
|
|
52
53
|
const tag = log.fields[0];
|
|
54
|
+
this.#log.debug(`Found private log with tag ${tag.toString()} in block ${block.number}`);
|
|
55
|
+
|
|
53
56
|
const currentLogs = taggedLogs.get(tag.toString()) ?? [];
|
|
54
|
-
currentLogs.push(
|
|
55
|
-
new TxScopedL2Log(
|
|
56
|
-
txHash,
|
|
57
|
-
dataStartIndexForTx,
|
|
58
|
-
block.number,
|
|
59
|
-
/* isFromPublic */ false,
|
|
60
|
-
log.toBuffer(),
|
|
61
|
-
).toBuffer(),
|
|
62
|
-
);
|
|
57
|
+
currentLogs.push(new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, log).toBuffer());
|
|
63
58
|
taggedLogs.set(tag.toString(), currentLogs);
|
|
64
59
|
});
|
|
65
|
-
});
|
|
66
|
-
return taggedLogs;
|
|
67
|
-
}
|
|
68
60
|
|
|
69
|
-
#extractTaggedLogsFromPublic(block: L2Block) {
|
|
70
|
-
const taggedLogs = new Map<string, Buffer[]>();
|
|
71
|
-
const dataStartIndexForBlock =
|
|
72
|
-
block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
|
|
73
|
-
block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX;
|
|
74
|
-
block.body.txEffects.forEach((txEffect, txIndex) => {
|
|
75
|
-
const txHash = txEffect.txHash;
|
|
76
|
-
const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
|
|
77
61
|
txEffect.publicLogs.forEach(log => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// See macros/note/mod/ and see how finalization_log[0] is constructed, to understand this monstrosity. (It wasn't me).
|
|
81
|
-
// Search the codebase for "disgusting encoding" to see other hardcoded instances of this encoding, that you might need to change if you ever find yourself here.
|
|
82
|
-
if (!firstFieldBuf.subarray(0, 27).equals(Buffer.alloc(27)) || firstFieldBuf[29] !== 0) {
|
|
83
|
-
// See parseLogFromPublic - the first field of a tagged log is 5 bytes structured:
|
|
84
|
-
// [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1]]
|
|
85
|
-
this.#log.warn(`Skipping public log with invalid first field: ${log.log[0]}`);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
// Check that the length values line up with the log contents
|
|
89
|
-
const publicValuesLength = firstFieldBuf.subarray(-5).readUint16BE();
|
|
90
|
-
const privateValuesLength = firstFieldBuf.subarray(-5).readUint16BE(3);
|
|
91
|
-
// Add 1 for the first field holding lengths
|
|
92
|
-
const totalLogLength = 1 + publicValuesLength + privateValuesLength;
|
|
93
|
-
// Note that zeroes can be valid log values, so we can only assert that we do not go over the given length
|
|
94
|
-
if (totalLogLength > PUBLIC_LOG_DATA_SIZE_IN_FIELDS || log.log.slice(totalLogLength).find(f => !f.isZero())) {
|
|
95
|
-
this.#log.warn(`Skipping invalid tagged public log with first field: ${log.log[0]}`);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// The first elt stores lengths as above => tag is in fields[1]
|
|
100
|
-
const tag = log.log[1];
|
|
62
|
+
const tag = log.log[0];
|
|
63
|
+
this.#log.debug(`Found public log with tag ${tag.toString()} in block ${block.number}`);
|
|
101
64
|
|
|
102
|
-
this.#log.debug(`Found tagged public log with tag ${tag.toString()} in block ${block.number}`);
|
|
103
65
|
const currentLogs = taggedLogs.get(tag.toString()) ?? [];
|
|
104
|
-
currentLogs.push(
|
|
105
|
-
new TxScopedL2Log(
|
|
106
|
-
txHash,
|
|
107
|
-
dataStartIndexForTx,
|
|
108
|
-
block.number,
|
|
109
|
-
/* isFromPublic */ true,
|
|
110
|
-
log.toBuffer(),
|
|
111
|
-
).toBuffer(),
|
|
112
|
-
);
|
|
66
|
+
currentLogs.push(new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, log).toBuffer());
|
|
113
67
|
taggedLogs.set(tag.toString(), currentLogs);
|
|
114
68
|
});
|
|
115
69
|
});
|
|
@@ -123,7 +77,7 @@ export class LogStore {
|
|
|
123
77
|
*/
|
|
124
78
|
addLogs(blocks: L2Block[]): Promise<boolean> {
|
|
125
79
|
const taggedLogsToAdd = blocks
|
|
126
|
-
.
|
|
80
|
+
.map(block => this.#extractTaggedLogs(block))
|
|
127
81
|
.reduce((acc, val) => {
|
|
128
82
|
for (const [tag, logs] of val.entries()) {
|
|
129
83
|
const currentLogs = acc.get(tag) ?? [];
|
|
@@ -204,6 +158,7 @@ export class LogStore {
|
|
|
204
158
|
this.#privateLogsByBlock.delete(block.number),
|
|
205
159
|
this.#publicLogsByBlock.delete(block.number),
|
|
206
160
|
this.#logTagsByBlock.delete(block.number),
|
|
161
|
+
this.#contractClassLogsByBlock.delete(block.number),
|
|
207
162
|
]),
|
|
208
163
|
),
|
|
209
164
|
);
|
|
@@ -238,9 +193,7 @@ export class LogStore {
|
|
|
238
193
|
*/
|
|
239
194
|
async getLogsByTags(tags: Fr[]): Promise<TxScopedL2Log[][]> {
|
|
240
195
|
const logs = await Promise.all(tags.map(tag => this.#logsByTag.getAsync(tag.toString())));
|
|
241
|
-
return logs.map(
|
|
242
|
-
noteLogBuffers => noteLogBuffers?.map(noteLogBuffer => TxScopedL2Log.fromBuffer(noteLogBuffer)) ?? [],
|
|
243
|
-
);
|
|
196
|
+
return logs.map(logBuffers => logBuffers?.map(logBuffer => TxScopedL2Log.fromBuffer(logBuffer)) ?? []);
|
|
244
197
|
}
|
|
245
198
|
|
|
246
199
|
/**
|
|
@@ -1,11 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export type L1Published<T> = {
|
|
3
|
-
data: T;
|
|
4
|
-
l1: L1PublishedData;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export type L1PublishedData = {
|
|
8
|
-
blockNumber: bigint;
|
|
9
|
-
timestamp: bigint;
|
|
10
|
-
blockHash: string;
|
|
11
|
-
};
|
|
1
|
+
export type { PublishedL2Block, L1PublishedData } from '@aztec/stdlib/block';
|
package/src/factory.ts
CHANGED
|
@@ -2,18 +2,12 @@ import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
|
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
4
4
|
import { createStore } from '@aztec/kv-store/lmdb-v2';
|
|
5
|
-
import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
|
|
6
|
-
import { TokenBridgeContractArtifact } from '@aztec/noir-contracts.js/TokenBridge';
|
|
7
5
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
8
6
|
import { protocolContractNames, protocolContractTreeRoot } from '@aztec/protocol-contracts';
|
|
9
7
|
import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
|
|
10
8
|
import { FunctionType, decodeFunctionSignature } from '@aztec/stdlib/abi';
|
|
11
9
|
import type { L2BlockSourceEventEmitter } from '@aztec/stdlib/block';
|
|
12
|
-
import {
|
|
13
|
-
type ContractClassPublic,
|
|
14
|
-
computePublicBytecodeCommitment,
|
|
15
|
-
getContractClassFromArtifact,
|
|
16
|
-
} from '@aztec/stdlib/contract';
|
|
10
|
+
import { type ContractClassPublic, computePublicBytecodeCommitment } from '@aztec/stdlib/contract';
|
|
17
11
|
import type { ArchiverApi, Service } from '@aztec/stdlib/interfaces/server';
|
|
18
12
|
import { getComponentsVersionsFromConfig } from '@aztec/stdlib/versioning';
|
|
19
13
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
@@ -32,11 +26,12 @@ import { createArchiverClient } from './rpc/index.js';
|
|
|
32
26
|
* @returns The local archiver.
|
|
33
27
|
*/
|
|
34
28
|
export async function createArchiver(
|
|
35
|
-
|
|
29
|
+
_config: ArchiverConfig & DataStoreConfig,
|
|
36
30
|
blobSinkClient: BlobSinkClientInterface,
|
|
37
31
|
opts: { blockUntilSync: boolean } = { blockUntilSync: true },
|
|
38
32
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
39
33
|
): Promise<ArchiverApi & Service & L2BlockSourceEventEmitter> {
|
|
34
|
+
const config = { ..._config, dataStoreMapSizeKB: _config.archiverStoreMapSizeKb ?? _config.dataStoreMapSizeKB };
|
|
40
35
|
const store = await createStore(
|
|
41
36
|
'archiver',
|
|
42
37
|
KVArchiverDataStore.SCHEMA_VERSION,
|
|
@@ -45,7 +40,6 @@ export async function createArchiver(
|
|
|
45
40
|
);
|
|
46
41
|
const archiverStore = new KVArchiverDataStore(store, config.maxLogs);
|
|
47
42
|
await registerProtocolContracts(archiverStore);
|
|
48
|
-
await registerCommonContracts(archiverStore);
|
|
49
43
|
return Archiver.createAndSync(config, archiverStore, { telemetry, blobSinkClient }, opts.blockUntilSync);
|
|
50
44
|
}
|
|
51
45
|
|
|
@@ -86,22 +80,3 @@ async function registerProtocolContracts(store: KVArchiverDataStore) {
|
|
|
86
80
|
await store.addContractInstances([contract.instance], blockNumber);
|
|
87
81
|
}
|
|
88
82
|
}
|
|
89
|
-
|
|
90
|
-
// TODO(#10007): Remove this method. We are explicitly registering these contracts
|
|
91
|
-
// here to ensure they are available to all nodes and all prover nodes, since the PXE
|
|
92
|
-
// was tweaked to automatically push contract classes to the node it is registered,
|
|
93
|
-
// but other nodes in the network may require the contract classes to be registered as well.
|
|
94
|
-
// TODO(#10007): Remove the dependency on noir-contracts.js from this package once we remove this.
|
|
95
|
-
async function registerCommonContracts(store: KVArchiverDataStore) {
|
|
96
|
-
const blockNumber = 0;
|
|
97
|
-
const artifacts = [TokenBridgeContractArtifact, TokenContractArtifact];
|
|
98
|
-
const classes = await Promise.all(
|
|
99
|
-
artifacts.map(async artifact => ({
|
|
100
|
-
...(await getContractClassFromArtifact(artifact)),
|
|
101
|
-
privateFunctions: [],
|
|
102
|
-
unconstrainedFunctions: [],
|
|
103
|
-
})),
|
|
104
|
-
);
|
|
105
|
-
const bytecodeCommitments = await Promise.all(classes.map(x => computePublicBytecodeCommitment(x.packedBytecode)));
|
|
106
|
-
await store.addContractClasses(classes, bytecodeCommitments, blockNumber);
|
|
107
|
-
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DefaultL1ContractsConfig } from '@aztec/ethereum';
|
|
2
|
+
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
2
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
5
|
import { L2Block, L2BlockHash, type L2BlockSource, type L2Tips } from '@aztec/stdlib/block';
|
|
@@ -90,6 +91,19 @@ export class MockL2BlockSource implements L2BlockSource {
|
|
|
90
91
|
);
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
public async getPublishedBlocks(from: number, limit: number, proven?: boolean) {
|
|
95
|
+
const blocks = await this.getBlocks(from, limit, proven);
|
|
96
|
+
return blocks.map(block => ({
|
|
97
|
+
block,
|
|
98
|
+
l1: {
|
|
99
|
+
blockNumber: BigInt(block.number),
|
|
100
|
+
blockHash: Buffer32.random().toString(),
|
|
101
|
+
timestamp: BigInt(block.number),
|
|
102
|
+
},
|
|
103
|
+
signatures: [],
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
|
|
94
108
|
return Promise.resolve(this.l2Blocks.at(typeof number === 'number' ? number - 1 : -1)?.header);
|
|
95
109
|
}
|
|
@@ -104,6 +118,10 @@ export class MockL2BlockSource implements L2BlockSource {
|
|
|
104
118
|
return Promise.resolve(blocks);
|
|
105
119
|
}
|
|
106
120
|
|
|
121
|
+
getBlockHeadersForEpoch(epochNumber: bigint): Promise<BlockHeader[]> {
|
|
122
|
+
return this.getBlocksForEpoch(epochNumber).then(blocks => blocks.map(b => b.header));
|
|
123
|
+
}
|
|
124
|
+
|
|
107
125
|
/**
|
|
108
126
|
* Gets a tx effect.
|
|
109
127
|
* @param txHash - The hash of a transaction which resulted in the returned tx effect.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
-
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
3
|
-
import type { InBlock, L2Block } from '@aztec/stdlib/block';
|
|
4
|
-
export declare class NullifierStore {
|
|
5
|
-
#private;
|
|
6
|
-
private db;
|
|
7
|
-
constructor(db: AztecAsyncKVStore);
|
|
8
|
-
addNullifiers(blocks: L2Block[]): Promise<boolean>;
|
|
9
|
-
deleteNullifiers(blocks: L2Block[]): Promise<boolean>;
|
|
10
|
-
findNullifiersIndexesWithBlock(blockNumber: number, nullifiers: Fr[]): Promise<(InBlock<bigint> | undefined)[]>;
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=nullifier_store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nullifier_store.d.ts","sourceRoot":"","sources":["../../../src/archiver/kv_archiver_store/nullifier_store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAEnD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE5D,qBAAa,cAAc;;IAMb,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,iBAAiB;IAMnC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BlD,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAerD,8BAA8B,CAClC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,EAAE,EAAE,GACf,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;CAkC5C"}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { MAX_NULLIFIERS_PER_TX } from '@aztec/constants';
|
|
2
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
-
export class NullifierStore {
|
|
4
|
-
db;
|
|
5
|
-
#nullifiersToBlockNumber;
|
|
6
|
-
#nullifiersToBlockHash;
|
|
7
|
-
#nullifiersToIndex;
|
|
8
|
-
#log;
|
|
9
|
-
constructor(db){
|
|
10
|
-
this.db = db;
|
|
11
|
-
this.#log = createLogger('archiver:log_store');
|
|
12
|
-
this.#nullifiersToBlockNumber = db.openMap('archiver_nullifiers_to_block_number');
|
|
13
|
-
this.#nullifiersToBlockHash = db.openMap('archiver_nullifiers_to_block_hash');
|
|
14
|
-
this.#nullifiersToIndex = db.openMap('archiver_nullifiers_to_index');
|
|
15
|
-
}
|
|
16
|
-
async addNullifiers(blocks) {
|
|
17
|
-
const blockHashes = await Promise.all(blocks.map((block)=>block.hash()));
|
|
18
|
-
await this.db.transactionAsync(async ()=>{
|
|
19
|
-
await Promise.all(blocks.map((block, i)=>{
|
|
20
|
-
const dataStartIndexForBlock = block.header.state.partial.nullifierTree.nextAvailableLeafIndex - block.body.txEffects.length * MAX_NULLIFIERS_PER_TX;
|
|
21
|
-
return Promise.all(block.body.txEffects.map((txEffects, txIndex)=>{
|
|
22
|
-
const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NULLIFIERS_PER_TX;
|
|
23
|
-
return Promise.all(txEffects.nullifiers.map(async (nullifier, nullifierIndex)=>{
|
|
24
|
-
await this.#nullifiersToBlockNumber.set(nullifier.toString(), block.number);
|
|
25
|
-
await this.#nullifiersToBlockHash.set(nullifier.toString(), blockHashes[i].toString());
|
|
26
|
-
await this.#nullifiersToIndex.set(nullifier.toString(), dataStartIndexForTx + nullifierIndex);
|
|
27
|
-
}));
|
|
28
|
-
}));
|
|
29
|
-
}));
|
|
30
|
-
});
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
async deleteNullifiers(blocks) {
|
|
34
|
-
await this.db.transactionAsync(async ()=>{
|
|
35
|
-
for (const block of blocks){
|
|
36
|
-
for (const nullifier of block.body.txEffects.flatMap((tx)=>tx.nullifiers)){
|
|
37
|
-
await Promise.all([
|
|
38
|
-
this.#nullifiersToBlockNumber.delete(nullifier.toString()),
|
|
39
|
-
this.#nullifiersToBlockHash.delete(nullifier.toString()),
|
|
40
|
-
this.#nullifiersToIndex.delete(nullifier.toString())
|
|
41
|
-
]);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
async findNullifiersIndexesWithBlock(blockNumber, nullifiers) {
|
|
48
|
-
const asStrings = nullifiers.map((x)=>x.toString());
|
|
49
|
-
const maybeNullifiers = await Promise.all(asStrings.map(async (nullifier)=>{
|
|
50
|
-
const [data, l2BlockNumber, l2BlockHash] = await Promise.all([
|
|
51
|
-
this.#nullifiersToIndex.getAsync(nullifier),
|
|
52
|
-
this.#nullifiersToBlockNumber.getAsync(nullifier),
|
|
53
|
-
this.#nullifiersToBlockHash.getAsync(nullifier)
|
|
54
|
-
]);
|
|
55
|
-
return {
|
|
56
|
-
data,
|
|
57
|
-
l2BlockNumber,
|
|
58
|
-
l2BlockHash
|
|
59
|
-
};
|
|
60
|
-
}));
|
|
61
|
-
return maybeNullifiers.map(({ data, l2BlockNumber, l2BlockHash })=>{
|
|
62
|
-
if (data === undefined || l2BlockNumber === undefined || l2BlockHash === undefined || l2BlockNumber > blockNumber) {
|
|
63
|
-
return undefined;
|
|
64
|
-
} else {
|
|
65
|
-
return {
|
|
66
|
-
data: BigInt(data),
|
|
67
|
-
l2BlockNumber,
|
|
68
|
-
l2BlockHash
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|