@aztec/stdlib 0.84.0-nightly.20250409 → 0.84.0-nightly.20250412

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 (61) hide show
  1. package/dest/avm/avm.d.ts +627 -5
  2. package/dest/avm/avm.d.ts.map +1 -1
  3. package/dest/avm/avm.js +13 -7
  4. package/dest/avm/avm_proving_request.d.ts +331 -0
  5. package/dest/avm/avm_proving_request.d.ts.map +1 -1
  6. package/dest/block/index.d.ts +1 -1
  7. package/dest/block/index.d.ts.map +1 -1
  8. package/dest/block/index.js +1 -1
  9. package/dest/block/l2_block_source.d.ts +2 -0
  10. package/dest/block/l2_block_source.d.ts.map +1 -1
  11. package/dest/block/l2_block_source.js +9 -0
  12. package/dest/block/l2_block_stream/index.d.ts +4 -0
  13. package/dest/block/l2_block_stream/index.d.ts.map +1 -0
  14. package/dest/block/l2_block_stream/index.js +3 -0
  15. package/dest/block/l2_block_stream/interfaces.d.ts +26 -0
  16. package/dest/block/l2_block_stream/interfaces.d.ts.map +1 -0
  17. package/dest/block/l2_block_stream/interfaces.js +1 -0
  18. package/dest/block/{l2_block_downloader → l2_block_stream}/l2_block_stream.d.ts +4 -24
  19. package/dest/block/l2_block_stream/l2_block_stream.d.ts.map +1 -0
  20. package/dest/block/{l2_block_downloader → l2_block_stream}/l2_block_stream.js +29 -10
  21. package/dest/block/l2_block_stream/l2_tips_memory_store.d.ts +18 -0
  22. package/dest/block/l2_block_stream/l2_tips_memory_store.d.ts.map +1 -0
  23. package/dest/block/l2_block_stream/l2_tips_memory_store.js +70 -0
  24. package/dest/block/test/index.d.ts +2 -0
  25. package/dest/block/test/index.d.ts.map +1 -0
  26. package/dest/block/test/index.js +1 -0
  27. package/dest/block/test/l2_tips_store_test_suite.d.ts +3 -0
  28. package/dest/block/test/l2_tips_store_test_suite.d.ts.map +1 -0
  29. package/dest/block/test/l2_tips_store_test_suite.js +107 -0
  30. package/dest/database-version/version_manager.d.ts +21 -5
  31. package/dest/database-version/version_manager.d.ts.map +1 -1
  32. package/dest/database-version/version_manager.js +25 -15
  33. package/dest/interfaces/proving-job.d.ts +331 -0
  34. package/dest/interfaces/proving-job.d.ts.map +1 -1
  35. package/dest/proofs/proof.d.ts +4 -1
  36. package/dest/proofs/proof.d.ts.map +1 -1
  37. package/dest/proofs/proof.js +9 -17
  38. package/dest/tests/factories.d.ts.map +1 -1
  39. package/dest/tests/factories.js +3 -2
  40. package/package.json +8 -6
  41. package/src/avm/avm.ts +19 -2
  42. package/src/block/index.ts +1 -1
  43. package/src/block/l2_block_source.ts +8 -0
  44. package/src/block/l2_block_stream/index.ts +3 -0
  45. package/src/block/l2_block_stream/interfaces.ts +33 -0
  46. package/src/block/{l2_block_downloader → l2_block_stream}/l2_block_stream.ts +34 -44
  47. package/src/block/l2_block_stream/l2_tips_memory_store.ts +75 -0
  48. package/src/block/test/index.ts +1 -0
  49. package/src/block/test/l2_tips_store_test_suite.ts +87 -0
  50. package/src/database-version/version_manager.ts +56 -17
  51. package/src/proofs/proof.ts +9 -19
  52. package/src/tests/factories.ts +3 -0
  53. package/dest/block/l2_block_downloader/index.d.ts +0 -3
  54. package/dest/block/l2_block_downloader/index.d.ts.map +0 -1
  55. package/dest/block/l2_block_downloader/index.js +0 -2
  56. package/dest/block/l2_block_downloader/l2_block_downloader.d.ts +0 -58
  57. package/dest/block/l2_block_downloader/l2_block_downloader.d.ts.map +0 -1
  58. package/dest/block/l2_block_downloader/l2_block_downloader.js +0 -124
  59. package/dest/block/l2_block_downloader/l2_block_stream.d.ts.map +0 -1
  60. package/src/block/l2_block_downloader/index.ts +0 -2
  61. package/src/block/l2_block_downloader/l2_block_downloader.ts +0 -149
@@ -59,20 +59,26 @@ export class Proof {
59
59
  return bufferToHex(this.toBuffer());
60
60
  }
61
61
 
62
+ /**
63
+ * Returns the proof without the public inputs, but includes the pairing point object as part of the proof.
64
+ * @returns Proof in bytes form, including the pairing point object at the start.
65
+ */
62
66
  public withoutPublicInputs(): Buffer {
63
67
  if (this.isEmpty()) {
64
68
  return this.buffer;
65
69
  }
66
70
  // We are indexing to this particular size because we are assuming the proof buffer looks like:
67
71
  // [binary public inputs, binary proof]
68
- const proofStart = Fr.SIZE_IN_BYTES * this.numPublicInputs;
72
+ // Here, we are assuming the pairing point object is the last 16 fields of the public inputs.
73
+ assert(this.numPublicInputs >= AGGREGATION_OBJECT_LENGTH, 'Proof does not contain an aggregation object');
74
+ const proofStart = Fr.SIZE_IN_BYTES * (this.numPublicInputs - AGGREGATION_OBJECT_LENGTH);
69
75
  assert(this.buffer.length >= proofStart, 'Proof buffer is not appropriately sized to call withoutPublicInputs()');
70
76
  return this.buffer.subarray(proofStart);
71
77
  }
72
78
 
73
79
  // This function assumes that the proof will contain an aggregation object and look something like:
74
80
  // [binary public inputs, aggregation object, rest of proof]
75
- // We are extracting the binary public inputs and reading them as Frs, and also extracting the aggregation object.
81
+ // We are extracting the binary public inputs and reading them as Frs.
76
82
  public extractPublicInputs(): Fr[] {
77
83
  if (this.isEmpty()) {
78
84
  // return array of this.numPublicInputs 0s
@@ -81,26 +87,10 @@ export class Proof {
81
87
  assert(this.numPublicInputs >= AGGREGATION_OBJECT_LENGTH, 'Proof does not contain an aggregation object');
82
88
  const numInnerPublicInputs = this.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
83
89
  const reader = BufferReader.asReader(this.buffer.subarray(0, Fr.SIZE_IN_BYTES * numInnerPublicInputs));
84
- let publicInputs = reader.readArray(numInnerPublicInputs, Fr);
85
- // concatenate Fr[] with aggregation object
86
- publicInputs = publicInputs.concat(this.extractAggregationObject());
90
+ const publicInputs = reader.readArray(numInnerPublicInputs, Fr);
87
91
  return publicInputs;
88
92
  }
89
93
 
90
- public extractAggregationObject(): Fr[] {
91
- if (this.isEmpty()) {
92
- // return array of 16 0s
93
- return new Array(16).fill(Fr.zero());
94
- }
95
- assert(this.numPublicInputs >= AGGREGATION_OBJECT_LENGTH, 'Proof does not contain an aggregation object');
96
- const numInnerPublicInputs = this.numPublicInputs - AGGREGATION_OBJECT_LENGTH;
97
- // The aggregation object is currently stored after the initial inner public inputs.
98
- const reader = BufferReader.asReader(
99
- this.buffer.subarray(Fr.SIZE_IN_BYTES * numInnerPublicInputs, Fr.SIZE_IN_BYTES * this.numPublicInputs),
100
- );
101
- return reader.readArray(AGGREGATION_OBJECT_LENGTH, Fr);
102
- }
103
-
104
94
  /**
105
95
  * Deserialize a Proof instance from a hex string.
106
96
  * @param str - A hex string to deserialize from.
@@ -1471,6 +1471,7 @@ export function makeAvmEnqueuedCallHint(seed = 0): AvmEnqueuedCallHint {
1471
1471
  export function makeAvmTxHint(seed = 0): AvmTxHint {
1472
1472
  return new AvmTxHint(
1473
1473
  `txhash-${seed}`,
1474
+ makeGlobalVariables(seed),
1474
1475
  {
1475
1476
  noteHashes: makeArray((seed % 20) + 4, i => new Fr(i), seed + 0x1000),
1476
1477
  nullifiers: makeArray((seed % 20) + 4, i => new Fr(i), seed + 0x2000),
@@ -1503,6 +1504,7 @@ export async function makeAvmExecutionHints(
1503
1504
  contractInstances: makeArray(baseLength + 2, makeAvmContractInstanceHint, seed + 0x4700),
1504
1505
  contractClasses: makeArray(baseLength + 5, makeAvmContractClassHint, seed + 0x4900),
1505
1506
  bytecodeCommitments: await makeArrayAsync(baseLength + 5, makeAvmBytecodeCommitmentHint, seed + 0x4900),
1507
+ startingTreeRoots: makeTreeSnapshots(seed + 0x4900),
1506
1508
  getSiblingPathHints: makeArray(baseLength + 5, makeAvmGetSiblingPathHint, seed + 0x4b00),
1507
1509
  getPreviousValueIndexHints: makeArray(baseLength + 5, makeAvmGetPreviousValueIndexHint, seed + 0x4d00),
1508
1510
  getLeafPreimageHintPublicDataTree: makeArray(
@@ -1534,6 +1536,7 @@ export async function makeAvmExecutionHints(
1534
1536
  fields.contractInstances,
1535
1537
  fields.contractClasses,
1536
1538
  fields.bytecodeCommitments,
1539
+ fields.startingTreeRoots,
1537
1540
  fields.getSiblingPathHints,
1538
1541
  fields.getPreviousValueIndexHints,
1539
1542
  fields.getLeafPreimageHintPublicDataTree,
@@ -1,3 +0,0 @@
1
- export * from './l2_block_downloader.js';
2
- export * from './l2_block_stream.js';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/block/l2_block_downloader/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './l2_block_downloader.js';
2
- export * from './l2_block_stream.js';
@@ -1,58 +0,0 @@
1
- import type { L2Block } from '../l2_block.js';
2
- import type { L2BlockSource } from '../l2_block_source.js';
3
- /**
4
- * Downloads L2 blocks from a L2BlockSource.
5
- * The blocks are stored in a queue and can be retrieved using the getBlocks method.
6
- * The queue size is limited by the maxQueueSize parameter.
7
- * The downloader will pause when the queue is full or when the L2BlockSource is out of blocks.
8
- */
9
- export declare class L2BlockDownloader {
10
- private l2BlockSource;
11
- private runningPromise?;
12
- private running;
13
- private from;
14
- private interruptibleSleep;
15
- private readonly semaphore;
16
- private readonly jobQueue;
17
- private readonly blockQueue;
18
- private readonly proven;
19
- private readonly pollIntervalMS;
20
- constructor(l2BlockSource: L2BlockSource, opts: {
21
- maxQueueSize: number;
22
- proven?: boolean;
23
- pollIntervalMS?: number;
24
- });
25
- /**
26
- * Starts the downloader.
27
- * @param from - The block number to start downloading from. Defaults to INITIAL_L2_BLOCK_NUM.
28
- */
29
- start(from?: number): void;
30
- /**
31
- * Repeatedly queries the block source and adds the received blocks to the block queue.
32
- * Stops when no further blocks are received.
33
- * @param targetBlockNumber - Optional block number to stop at.
34
- * @param proven - Optional override of the default "proven" setting.
35
- * @returns The total number of blocks added to the block queue.
36
- */
37
- private collectBlocks;
38
- /**
39
- * Stops the downloader.
40
- */
41
- stop(): Promise<void>;
42
- /**
43
- * Gets the next batch of blocks from the queue.
44
- * @param timeout - optional timeout value to prevent permanent blocking
45
- * @returns The next batch of blocks from the queue.
46
- */
47
- getBlocks(timeout?: number): Promise<L2Block[]>;
48
- /**
49
- * Forces an immediate request for blocks.
50
- * Repeatedly queries the block source and adds the received blocks to the block queue.
51
- * Stops when no further blocks are received.
52
- * @param targetBlockNumber - Optional block number to stop at.
53
- * @param proven - Optional override of the default "proven" setting.
54
- * @returns A promise that fulfills once the poll is complete
55
- */
56
- pollImmediate(targetBlockNumber?: number, onlyProven?: boolean): Promise<number>;
57
- }
58
- //# sourceMappingURL=l2_block_downloader.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"l2_block_downloader.d.ts","sourceRoot":"","sources":["../../../src/block/l2_block_downloader/l2_block_downloader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3D;;;;;GAKG;AACH,qBAAa,iBAAiB;IAY1B,OAAO,CAAC,aAAa;IAXvB,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAG9B,aAAa,EAAE,aAAa,EACpC,IAAI,EAAE;QACJ,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB;IAOH;;;OAGG;IACI,KAAK,CAAC,IAAI,SAAuB;IAuBxC;;;;;;OAMG;YACW,aAAa;IAiC3B;;OAEG;IACU,IAAI;IAQjB;;;;OAIG;IACU,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAc5D;;;;;;;OAOG;IACI,aAAa,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CAGxF"}
@@ -1,124 +0,0 @@
1
- import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
2
- import { createLogger } from '@aztec/foundation/log';
3
- import { FifoMemoryQueue, Semaphore, SerialQueue } from '@aztec/foundation/queue';
4
- import { InterruptibleSleep } from '@aztec/foundation/sleep';
5
- const log = createLogger('types:l2_block_downloader');
6
- /**
7
- * Downloads L2 blocks from a L2BlockSource.
8
- * The blocks are stored in a queue and can be retrieved using the getBlocks method.
9
- * The queue size is limited by the maxQueueSize parameter.
10
- * The downloader will pause when the queue is full or when the L2BlockSource is out of blocks.
11
- */ export class L2BlockDownloader {
12
- l2BlockSource;
13
- runningPromise;
14
- running;
15
- from;
16
- interruptibleSleep;
17
- semaphore;
18
- jobQueue;
19
- blockQueue;
20
- proven;
21
- pollIntervalMS;
22
- constructor(l2BlockSource, opts){
23
- this.l2BlockSource = l2BlockSource;
24
- this.running = false;
25
- this.from = 0;
26
- this.interruptibleSleep = new InterruptibleSleep();
27
- this.jobQueue = new SerialQueue();
28
- this.blockQueue = new FifoMemoryQueue();
29
- this.pollIntervalMS = opts.pollIntervalMS ?? 1000;
30
- this.proven = opts.proven ?? false;
31
- this.semaphore = new Semaphore(opts.maxQueueSize);
32
- }
33
- /**
34
- * Starts the downloader.
35
- * @param from - The block number to start downloading from. Defaults to INITIAL_L2_BLOCK_NUM.
36
- */ start(from = INITIAL_L2_BLOCK_NUM) {
37
- if (this.running) {
38
- this.interruptibleSleep.interrupt();
39
- return;
40
- }
41
- this.from = from;
42
- this.running = true;
43
- const fn = async ()=>{
44
- while(this.running){
45
- try {
46
- await this.jobQueue.put(()=>this.collectBlocks());
47
- await this.interruptibleSleep.sleep(this.pollIntervalMS);
48
- } catch (err) {
49
- log.error(`Error downloading L2 block`, err);
50
- await this.interruptibleSleep.sleep(this.pollIntervalMS);
51
- }
52
- }
53
- };
54
- this.jobQueue.start();
55
- this.runningPromise = fn();
56
- }
57
- /**
58
- * Repeatedly queries the block source and adds the received blocks to the block queue.
59
- * Stops when no further blocks are received.
60
- * @param targetBlockNumber - Optional block number to stop at.
61
- * @param proven - Optional override of the default "proven" setting.
62
- * @returns The total number of blocks added to the block queue.
63
- */ async collectBlocks(targetBlockNumber, onlyProven) {
64
- let totalBlocks = 0;
65
- while(true){
66
- // If we have a target and have reached it, return
67
- if (targetBlockNumber !== undefined && this.from > targetBlockNumber) {
68
- log.verbose(`Reached target block number ${targetBlockNumber}`);
69
- return totalBlocks;
70
- }
71
- // If we have a target, then request at most the number of blocks to get to it
72
- const limit = targetBlockNumber !== undefined ? Math.min(targetBlockNumber - this.from + 1, 10) : 10;
73
- const proven = onlyProven === undefined ? this.proven : onlyProven;
74
- // Hit the archiver for blocks
75
- const blocks = await this.l2BlockSource.getBlocks(this.from, limit, proven);
76
- // If there are no more blocks, return
77
- if (!blocks.length) {
78
- return totalBlocks;
79
- }
80
- log.verbose(`Received ${blocks.length} blocks from archiver after querying from ${this.from} limit ${limit} (proven ${proven})`);
81
- // Push new blocks into the queue and loop
82
- await this.semaphore.acquire();
83
- this.blockQueue.put(blocks);
84
- this.from += blocks.length;
85
- totalBlocks += blocks.length;
86
- }
87
- }
88
- /**
89
- * Stops the downloader.
90
- */ async stop() {
91
- this.running = false;
92
- this.interruptibleSleep.interrupt();
93
- await this.jobQueue.cancel();
94
- this.blockQueue.cancel();
95
- await this.runningPromise;
96
- }
97
- /**
98
- * Gets the next batch of blocks from the queue.
99
- * @param timeout - optional timeout value to prevent permanent blocking
100
- * @returns The next batch of blocks from the queue.
101
- */ async getBlocks(timeout) {
102
- try {
103
- const blocks = await this.blockQueue.get(timeout);
104
- if (!blocks) {
105
- return [];
106
- }
107
- this.semaphore.release();
108
- return blocks;
109
- } catch (err) {
110
- // nothing to do
111
- return [];
112
- }
113
- }
114
- /**
115
- * Forces an immediate request for blocks.
116
- * Repeatedly queries the block source and adds the received blocks to the block queue.
117
- * Stops when no further blocks are received.
118
- * @param targetBlockNumber - Optional block number to stop at.
119
- * @param proven - Optional override of the default "proven" setting.
120
- * @returns A promise that fulfills once the poll is complete
121
- */ pollImmediate(targetBlockNumber, onlyProven) {
122
- return this.jobQueue.put(()=>this.collectBlocks(targetBlockNumber, onlyProven));
123
- }
124
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"l2_block_stream.d.ts","sourceRoot":"","sources":["../../../src/block/l2_block_downloader/l2_block_stream.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,uHAAuH;AACvH,qBAAa,aAAa;IAMtB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,IAAI;IATd,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;gBAGjB,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,oBAAoB,GAAG,gBAAgB,GAAG,WAAW,CAAC,EACzF,SAAS,EAAE,8BAA8B,EACzC,OAAO,EAAE,yBAAyB,EACzB,GAAG,yCAAqC,EACjD,IAAI,GAAE;QACZ,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;KACnB;IAKD,KAAK;IAKC,IAAI;IAIV,SAAS;IAIH,IAAI;cAMD,IAAI;IA+EpB;;;;OAIG;YACW,qBAAqB;IAenC,OAAO,CAAC,sBAAsB;YAOhB,SAAS;CASxB;AAsBD,8FAA8F;AAC9F,MAAM,WAAW,8BAA8B;IAC7C,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC5D,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED,gDAAgD;AAChD,MAAM,WAAW,yBAAyB;IACxC,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED,MAAM,MAAM,kBAAkB,GAC1B,uCAAuC,CAAC;IACtC,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B,GACD,kEAAkE,CAAC;IACjE,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;CAClB,GACD,gCAAgC,CAAC;IAC/B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;CAClB,GACD,gEAAgE,CAAC;IAC/D,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './l2_block_downloader.js';
2
- export * from './l2_block_stream.js';
@@ -1,149 +0,0 @@
1
- import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
2
- import { createLogger } from '@aztec/foundation/log';
3
- import { FifoMemoryQueue, Semaphore, SerialQueue } from '@aztec/foundation/queue';
4
- import { InterruptibleSleep } from '@aztec/foundation/sleep';
5
-
6
- import type { L2Block } from '../l2_block.js';
7
- import type { L2BlockSource } from '../l2_block_source.js';
8
-
9
- const log = createLogger('types:l2_block_downloader');
10
-
11
- /**
12
- * Downloads L2 blocks from a L2BlockSource.
13
- * The blocks are stored in a queue and can be retrieved using the getBlocks method.
14
- * The queue size is limited by the maxQueueSize parameter.
15
- * The downloader will pause when the queue is full or when the L2BlockSource is out of blocks.
16
- */
17
- export class L2BlockDownloader {
18
- private runningPromise?: Promise<void>;
19
- private running = false;
20
- private from = 0;
21
- private interruptibleSleep = new InterruptibleSleep();
22
- private readonly semaphore: Semaphore;
23
- private readonly jobQueue = new SerialQueue();
24
- private readonly blockQueue = new FifoMemoryQueue<L2Block[]>();
25
- private readonly proven: boolean;
26
- private readonly pollIntervalMS: number;
27
-
28
- constructor(
29
- private l2BlockSource: L2BlockSource,
30
- opts: {
31
- maxQueueSize: number;
32
- proven?: boolean;
33
- pollIntervalMS?: number;
34
- },
35
- ) {
36
- this.pollIntervalMS = opts.pollIntervalMS ?? 1000;
37
- this.proven = opts.proven ?? false;
38
- this.semaphore = new Semaphore(opts.maxQueueSize);
39
- }
40
-
41
- /**
42
- * Starts the downloader.
43
- * @param from - The block number to start downloading from. Defaults to INITIAL_L2_BLOCK_NUM.
44
- */
45
- public start(from = INITIAL_L2_BLOCK_NUM) {
46
- if (this.running) {
47
- this.interruptibleSleep.interrupt();
48
- return;
49
- }
50
- this.from = from;
51
- this.running = true;
52
-
53
- const fn = async () => {
54
- while (this.running) {
55
- try {
56
- await this.jobQueue.put(() => this.collectBlocks());
57
- await this.interruptibleSleep.sleep(this.pollIntervalMS);
58
- } catch (err) {
59
- log.error(`Error downloading L2 block`, err);
60
- await this.interruptibleSleep.sleep(this.pollIntervalMS);
61
- }
62
- }
63
- };
64
- this.jobQueue.start();
65
- this.runningPromise = fn();
66
- }
67
-
68
- /**
69
- * Repeatedly queries the block source and adds the received blocks to the block queue.
70
- * Stops when no further blocks are received.
71
- * @param targetBlockNumber - Optional block number to stop at.
72
- * @param proven - Optional override of the default "proven" setting.
73
- * @returns The total number of blocks added to the block queue.
74
- */
75
- private async collectBlocks(targetBlockNumber?: number, onlyProven?: boolean) {
76
- let totalBlocks = 0;
77
- while (true) {
78
- // If we have a target and have reached it, return
79
- if (targetBlockNumber !== undefined && this.from > targetBlockNumber) {
80
- log.verbose(`Reached target block number ${targetBlockNumber}`);
81
- return totalBlocks;
82
- }
83
-
84
- // If we have a target, then request at most the number of blocks to get to it
85
- const limit = targetBlockNumber !== undefined ? Math.min(targetBlockNumber - this.from + 1, 10) : 10;
86
- const proven = onlyProven === undefined ? this.proven : onlyProven;
87
-
88
- // Hit the archiver for blocks
89
- const blocks = await this.l2BlockSource.getBlocks(this.from, limit, proven);
90
-
91
- // If there are no more blocks, return
92
- if (!blocks.length) {
93
- return totalBlocks;
94
- }
95
-
96
- log.verbose(
97
- `Received ${blocks.length} blocks from archiver after querying from ${this.from} limit ${limit} (proven ${proven})`,
98
- );
99
-
100
- // Push new blocks into the queue and loop
101
- await this.semaphore.acquire();
102
- this.blockQueue.put(blocks);
103
- this.from += blocks.length;
104
- totalBlocks += blocks.length;
105
- }
106
- }
107
-
108
- /**
109
- * Stops the downloader.
110
- */
111
- public async stop() {
112
- this.running = false;
113
- this.interruptibleSleep.interrupt();
114
- await this.jobQueue.cancel();
115
- this.blockQueue.cancel();
116
- await this.runningPromise;
117
- }
118
-
119
- /**
120
- * Gets the next batch of blocks from the queue.
121
- * @param timeout - optional timeout value to prevent permanent blocking
122
- * @returns The next batch of blocks from the queue.
123
- */
124
- public async getBlocks(timeout?: number): Promise<L2Block[]> {
125
- try {
126
- const blocks = await this.blockQueue.get(timeout);
127
- if (!blocks) {
128
- return [];
129
- }
130
- this.semaphore.release();
131
- return blocks;
132
- } catch (err) {
133
- // nothing to do
134
- return [];
135
- }
136
- }
137
-
138
- /**
139
- * Forces an immediate request for blocks.
140
- * Repeatedly queries the block source and adds the received blocks to the block queue.
141
- * Stops when no further blocks are received.
142
- * @param targetBlockNumber - Optional block number to stop at.
143
- * @param proven - Optional override of the default "proven" setting.
144
- * @returns A promise that fulfills once the poll is complete
145
- */
146
- public pollImmediate(targetBlockNumber?: number, onlyProven?: boolean): Promise<number> {
147
- return this.jobQueue.put(() => this.collectBlocks(targetBlockNumber, onlyProven));
148
- }
149
- }