@aztec/archiver 0.47.0 → 0.48.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.
Files changed (37) hide show
  1. package/dest/archiver/archiver.d.ts.map +1 -1
  2. package/dest/archiver/archiver.js +32 -17
  3. package/dest/archiver/archiver_store.d.ts +1 -1
  4. package/dest/archiver/archiver_store.d.ts.map +1 -1
  5. package/dest/archiver/config.d.ts +5 -15
  6. package/dest/archiver/config.d.ts.map +1 -1
  7. package/dest/archiver/config.js +30 -13
  8. package/dest/archiver/data_retrieval.d.ts +7 -1
  9. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  10. package/dest/archiver/data_retrieval.js +19 -1
  11. package/dest/archiver/eth_log_handlers.d.ts.map +1 -1
  12. package/dest/archiver/eth_log_handlers.js +35 -13
  13. package/dest/archiver/instrumentation.d.ts +3 -1
  14. package/dest/archiver/instrumentation.d.ts.map +1 -1
  15. package/dest/archiver/instrumentation.js +15 -6
  16. package/dest/archiver/kv_archiver_store/block_body_store.d.ts +4 -3
  17. package/dest/archiver/kv_archiver_store/block_body_store.d.ts.map +1 -1
  18. package/dest/archiver/kv_archiver_store/block_body_store.js +13 -6
  19. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +1 -1
  20. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  21. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +2 -2
  22. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
  23. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +3 -7
  24. package/dest/index.d.ts +1 -0
  25. package/dest/index.d.ts.map +1 -1
  26. package/dest/index.js +4 -2
  27. package/package.json +10 -10
  28. package/src/archiver/archiver.ts +36 -17
  29. package/src/archiver/archiver_store.ts +1 -1
  30. package/src/archiver/config.ts +33 -37
  31. package/src/archiver/data_retrieval.ts +25 -2
  32. package/src/archiver/eth_log_handlers.ts +43 -13
  33. package/src/archiver/instrumentation.ts +26 -6
  34. package/src/archiver/kv_archiver_store/block_body_store.ts +12 -6
  35. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +1 -1
  36. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +5 -9
  37. package/src/index.ts +4 -1
@@ -5,7 +5,16 @@ import { Fr } from '@aztec/foundation/fields';
5
5
  import { numToUInt32BE } from '@aztec/foundation/serialize';
6
6
  import { AvailabilityOracleAbi, InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
7
7
 
8
- import { type Hex, type Log, type PublicClient, decodeFunctionData, getAbiItem, getAddress, hexToBytes } from 'viem';
8
+ import {
9
+ type Hex,
10
+ type Log,
11
+ type PublicClient,
12
+ decodeFunctionData,
13
+ getAbiItem,
14
+ getAddress,
15
+ hexToBytes,
16
+ slice,
17
+ } from 'viem';
9
18
 
10
19
  /**
11
20
  * Processes newly received MessageSent (L1 to L2) logs.
@@ -88,7 +97,7 @@ async function getBlockMetadataFromRollupTx(
88
97
  data,
89
98
  });
90
99
 
91
- if (functionName !== 'process') {
100
+ if (!(functionName === 'process' || functionName === 'publishAndProcess')) {
92
101
  throw new Error(`Unexpected method called ${functionName}`);
93
102
  }
94
103
  const [headerHex, archiveRootHex] = args! as readonly [Hex, Hex];
@@ -113,7 +122,7 @@ async function getBlockMetadataFromRollupTx(
113
122
 
114
123
  /**
115
124
  * Gets block bodies from calldata of an L1 transaction, and deserializes them into Body objects.
116
- * Assumes that the block was published from an EOA.
125
+ * @note Assumes that the block was published using `publishAndProcess` or `publish`.
117
126
  * TODO: Add retries and error management.
118
127
  * @param publicClient - The viem public client to use for transaction retrieval.
119
128
  * @param txHash - Hash of the tx that published it.
@@ -124,20 +133,41 @@ async function getBlockBodiesFromAvailabilityOracleTx(
124
133
  txHash: `0x${string}`,
125
134
  ): Promise<Body> {
126
135
  const { input: data } = await publicClient.getTransaction({ hash: txHash });
127
- const { functionName, args } = decodeFunctionData({
128
- abi: AvailabilityOracleAbi,
129
- data,
130
- });
136
+ const DATA_INDEX = [3, 2, 0];
131
137
 
132
- if (functionName !== 'publish') {
133
- throw new Error(`Unexpected method called ${functionName}`);
134
- }
138
+ // @note Use `forge inspect Rollup methodIdentifiers to get this,
139
+ // If using `forge sig` you will get an INVALID value for the case with a struct.
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)",
143
+ // "publish(bytes calldata _body)"
144
+ // ]
145
+ const SUPPORTED_SIGS = ['0xe4e90c26', '0xe86e3595', '0x7fd28346'];
135
146
 
136
- const [bodyHex] = args! as [Hex];
147
+ const signature = slice(data, 0, 4);
137
148
 
138
- const blockBody = Body.fromBuffer(Buffer.from(hexToBytes(bodyHex)));
149
+ if (!SUPPORTED_SIGS.includes(signature)) {
150
+ throw new Error(`Unexpected method called ${signature}`);
151
+ }
139
152
 
140
- return blockBody;
153
+ if (signature === SUPPORTED_SIGS[2]) {
154
+ const { args } = decodeFunctionData({
155
+ abi: AvailabilityOracleAbi,
156
+ data,
157
+ });
158
+ const [bodyHex] = args! as [Hex];
159
+ const blockBody = Body.fromBuffer(Buffer.from(hexToBytes(bodyHex)));
160
+ return blockBody;
161
+ } else {
162
+ const { args } = decodeFunctionData({
163
+ abi: RollupAbi,
164
+ data,
165
+ });
166
+ const index = SUPPORTED_SIGS.indexOf(signature);
167
+ const bodyHex = args![DATA_INDEX[index]] as Hex;
168
+ const blockBody = Body.fromBuffer(Buffer.from(hexToBytes(bodyHex)));
169
+ return blockBody;
170
+ }
141
171
  }
142
172
 
143
173
  /**
@@ -1,9 +1,18 @@
1
1
  import { type L2Block } from '@aztec/circuit-types';
2
- import { type Gauge, type Histogram, Metrics, type TelemetryClient, ValueType } from '@aztec/telemetry-client';
2
+ import {
3
+ Attributes,
4
+ type Gauge,
5
+ type Histogram,
6
+ Metrics,
7
+ type TelemetryClient,
8
+ ValueType,
9
+ exponentialBuckets,
10
+ } from '@aztec/telemetry-client';
3
11
 
4
12
  export class ArchiverInstrumentation {
5
13
  private blockHeight: Gauge;
6
- private blockSize: Histogram;
14
+ private blockSize: Gauge;
15
+ private syncDuration: Histogram;
7
16
 
8
17
  constructor(telemetry: TelemetryClient) {
9
18
  const meter = telemetry.getMeter('Archiver');
@@ -12,19 +21,30 @@ export class ArchiverInstrumentation {
12
21
  valueType: ValueType.INT,
13
22
  });
14
23
 
15
- this.blockSize = meter.createHistogram(Metrics.ARCHIVER_BLOCK_SIZE, {
16
- description: 'The number of transactions processed per block',
24
+ this.blockSize = meter.createGauge(Metrics.ARCHIVER_BLOCK_SIZE, {
25
+ description: 'The number of transactions in a block',
26
+ valueType: ValueType.INT,
27
+ });
28
+
29
+ this.syncDuration = meter.createHistogram(Metrics.ARCHIVER_SYNC_DURATION, {
30
+ unit: 'ms',
31
+ description: 'Duration to sync a block',
17
32
  valueType: ValueType.INT,
18
33
  advice: {
19
- explicitBucketBoundaries: [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192],
34
+ explicitBucketBoundaries: exponentialBuckets(1, 16),
20
35
  },
21
36
  });
22
37
  }
23
38
 
24
- public processNewBlocks(blocks: L2Block[]) {
39
+ public processNewBlocks(syncTimePerBlock: number, blocks: L2Block[]) {
40
+ this.syncDuration.record(syncTimePerBlock);
25
41
  this.blockHeight.record(Math.max(...blocks.map(b => b.number)));
26
42
  for (const block of blocks) {
27
43
  this.blockSize.record(block.body.txEffects.length);
28
44
  }
29
45
  }
46
+
47
+ public updateLastProvenBlock(blockNumber: number) {
48
+ this.blockHeight.record(blockNumber, { [Attributes.STATUS]: 'proven' });
49
+ }
30
50
  }
@@ -1,11 +1,12 @@
1
1
  import { Body } from '@aztec/circuit-types';
2
+ import { createDebugLogger } from '@aztec/foundation/log';
2
3
  import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';
3
4
 
4
5
  export class BlockBodyStore {
5
6
  /** Map block body hash to block body */
6
7
  #blockBodies: AztecMap<string, Buffer>;
7
8
 
8
- constructor(private db: AztecKVStore) {
9
+ constructor(private db: AztecKVStore, private log = createDebugLogger('aztec:archiver:block_body_store')) {
9
10
  this.#blockBodies = db.openMap('archiver_block_bodies');
10
11
  }
11
12
 
@@ -29,21 +30,26 @@ export class BlockBodyStore {
29
30
  * @param txsEffectsHashes - The txsEffectsHashes list that corresponds to the blockBodies we want to retrieve
30
31
  * @returns The requested L2 block bodies
31
32
  */
32
- async getBlockBodies(txsEffectsHashes: Buffer[]): Promise<Body[]> {
33
+ async getBlockBodies(txsEffectsHashes: Buffer[]): Promise<(Body | undefined)[]> {
33
34
  const blockBodiesBuffer = await this.db.transaction(() =>
34
35
  txsEffectsHashes.map(txsEffectsHash => this.#blockBodies.get(txsEffectsHash.toString('hex'))),
35
36
  );
36
37
 
37
- if (blockBodiesBuffer.some(bodyBuffer => bodyBuffer === undefined)) {
38
- throw new Error('Block body buffer is undefined');
38
+ const blockBodies: (Body | undefined)[] = [];
39
+ for (let i = 0; i < blockBodiesBuffer.length; i++) {
40
+ const blockBodyBuffer = blockBodiesBuffer[i];
41
+ if (blockBodyBuffer === undefined) {
42
+ this.log.warn(`Block body buffer is undefined for txsEffectsHash: ${txsEffectsHashes[i].toString('hex')}`);
43
+ }
44
+ blockBodies.push(blockBodyBuffer ? Body.fromBuffer(blockBodyBuffer) : undefined);
39
45
  }
40
46
 
41
- return blockBodiesBuffer.map(blockBodyBuffer => Body.fromBuffer(blockBodyBuffer!));
47
+ return blockBodies;
42
48
  }
43
49
 
44
50
  /**
45
51
  * Gets an L2 block body.
46
- * @param txsEffectsHash - The txHash of the the block body to return
52
+ * @param txsEffectsHash - The txHash of the block body to return
47
53
  * @returns The requested L2 block body
48
54
  */
49
55
  getBlockBody(txsEffectsHash: Buffer): Body | undefined {
@@ -111,7 +111,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
111
111
  * @param txsEffectsHashes - A list of txsEffectsHashes (body hashes).
112
112
  * @returns The requested L2 block bodies
113
113
  */
114
- getBlockBodies(txsEffectsHashes: Buffer[]): Promise<Body[]> {
114
+ getBlockBodies(txsEffectsHashes: Buffer[]): Promise<(Body | undefined)[]> {
115
115
  return this.#blockBodyStore.getBlockBodies(txsEffectsHashes);
116
116
  }
117
117
 
@@ -45,7 +45,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
45
45
  private l2BlockBodies: Map<string, Body> = new Map();
46
46
 
47
47
  /**
48
- * An array containing all the the tx effects in the L2 blocks that have been fetched so far.
48
+ * An array containing all the tx effects in the L2 blocks that have been fetched so far.
49
49
  */
50
50
  private txEffects: TxEffect[] = [];
51
51
 
@@ -177,14 +177,10 @@ export class MemoryArchiverStore implements ArchiverDataStore {
177
177
  * @param txsEffectsHashes - A list of txsEffectsHashes (body hashes).
178
178
  * @returns The requested L2 block bodies
179
179
  */
180
- getBlockBodies(txsEffectsHashes: Buffer[]): Promise<Body[]> {
181
- const blockBodies = txsEffectsHashes.map(txsEffectsHash => this.l2BlockBodies.get(txsEffectsHash.toString('hex')));
182
-
183
- if (blockBodies.some(bodyBuffer => bodyBuffer === undefined)) {
184
- throw new Error('Block body is undefined');
185
- }
186
-
187
- return Promise.resolve(blockBodies as Body[]);
180
+ getBlockBodies(txsEffectsHashes: Buffer[]): Promise<(Body | undefined)[]> {
181
+ return Promise.resolve(
182
+ txsEffectsHashes.map(txsEffectsHash => this.l2BlockBodies.get(txsEffectsHash.toString('hex'))),
183
+ );
188
184
  }
189
185
 
190
186
  /**
package/src/index.ts CHANGED
@@ -12,6 +12,9 @@ export * from './archiver/index.js';
12
12
  export * from './rpc/index.js';
13
13
  export * from './factory.js';
14
14
 
15
+ // We are not storing the info from these events in the archiver for now (and we don't really need to), so we expose this query directly
16
+ export { retrieveL2ProofVerifiedEvents } from './archiver/data_retrieval.js';
17
+
15
18
  const log = createDebugLogger('aztec:archiver');
16
19
 
17
20
  /**
@@ -20,7 +23,7 @@ const log = createDebugLogger('aztec:archiver');
20
23
  // eslint-disable-next-line require-await
21
24
  async function main() {
22
25
  const config = getArchiverConfigFromEnv();
23
- const { rpcUrl, l1Contracts } = config;
26
+ const { l1RpcUrl: rpcUrl, l1Contracts } = config;
24
27
 
25
28
  const publicClient = createPublicClient({
26
29
  chain: localhost,