@aztec/archiver 0.0.1-commit.6d3c34e → 0.0.1-commit.7035c9bd6

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 (204) hide show
  1. package/README.md +156 -22
  2. package/dest/archiver.d.ts +138 -0
  3. package/dest/archiver.d.ts.map +1 -0
  4. package/dest/archiver.js +732 -0
  5. package/dest/config.d.ts +30 -0
  6. package/dest/config.d.ts.map +1 -0
  7. package/dest/{archiver/config.js → config.js} +11 -1
  8. package/dest/errors.d.ts +53 -0
  9. package/dest/errors.d.ts.map +1 -0
  10. package/dest/errors.js +75 -0
  11. package/dest/factory.d.ts +8 -7
  12. package/dest/factory.d.ts.map +1 -1
  13. package/dest/factory.js +90 -8
  14. package/dest/index.d.ts +11 -4
  15. package/dest/index.d.ts.map +1 -1
  16. package/dest/index.js +9 -3
  17. package/dest/interfaces.d.ts +9 -0
  18. package/dest/interfaces.d.ts.map +1 -0
  19. package/dest/interfaces.js +3 -0
  20. package/dest/{archiver/l1 → l1}/bin/retrieve-calldata.d.ts +1 -1
  21. package/dest/l1/bin/retrieve-calldata.d.ts.map +1 -0
  22. package/dest/{archiver/l1 → l1}/bin/retrieve-calldata.js +35 -32
  23. package/dest/l1/calldata_retriever.d.ts +135 -0
  24. package/dest/l1/calldata_retriever.d.ts.map +1 -0
  25. package/dest/l1/calldata_retriever.js +402 -0
  26. package/dest/l1/data_retrieval.d.ts +88 -0
  27. package/dest/l1/data_retrieval.d.ts.map +1 -0
  28. package/dest/{archiver/l1 → l1}/data_retrieval.js +54 -71
  29. package/dest/{archiver/l1 → l1}/debug_tx.d.ts +1 -1
  30. package/dest/l1/debug_tx.d.ts.map +1 -0
  31. package/dest/{archiver/l1 → l1}/spire_proposer.d.ts +5 -5
  32. package/dest/l1/spire_proposer.d.ts.map +1 -0
  33. package/dest/{archiver/l1 → l1}/spire_proposer.js +9 -17
  34. package/dest/{archiver/l1 → l1}/trace_tx.d.ts +1 -1
  35. package/dest/l1/trace_tx.d.ts.map +1 -0
  36. package/dest/l1/types.d.ts +12 -0
  37. package/dest/l1/types.d.ts.map +1 -0
  38. package/dest/{archiver/l1 → l1}/validate_trace.d.ts +6 -3
  39. package/dest/l1/validate_trace.d.ts.map +1 -0
  40. package/dest/{archiver/l1 → l1}/validate_trace.js +13 -9
  41. package/dest/modules/data_source_base.d.ts +89 -0
  42. package/dest/modules/data_source_base.d.ts.map +1 -0
  43. package/dest/modules/data_source_base.js +216 -0
  44. package/dest/modules/data_store_updater.d.ts +88 -0
  45. package/dest/modules/data_store_updater.d.ts.map +1 -0
  46. package/dest/modules/data_store_updater.js +342 -0
  47. package/dest/modules/instrumentation.d.ts +50 -0
  48. package/dest/modules/instrumentation.d.ts.map +1 -0
  49. package/dest/{archiver → modules}/instrumentation.js +36 -12
  50. package/dest/modules/l1_synchronizer.d.ts +72 -0
  51. package/dest/modules/l1_synchronizer.d.ts.map +1 -0
  52. package/dest/modules/l1_synchronizer.js +1147 -0
  53. package/dest/{archiver → modules}/validation.d.ts +1 -1
  54. package/dest/modules/validation.d.ts.map +1 -0
  55. package/dest/{archiver → modules}/validation.js +6 -0
  56. package/dest/store/block_store.d.ts +195 -0
  57. package/dest/store/block_store.d.ts.map +1 -0
  58. package/dest/{archiver/kv_archiver_store → store}/block_store.js +248 -101
  59. package/dest/store/contract_class_store.d.ts +18 -0
  60. package/dest/store/contract_class_store.d.ts.map +1 -0
  61. package/dest/{archiver/kv_archiver_store → store}/contract_class_store.js +12 -8
  62. package/dest/store/contract_instance_store.d.ts +24 -0
  63. package/dest/store/contract_instance_store.d.ts.map +1 -0
  64. package/dest/{archiver/kv_archiver_store → store}/contract_instance_store.js +1 -1
  65. package/dest/store/kv_archiver_store.d.ts +367 -0
  66. package/dest/store/kv_archiver_store.d.ts.map +1 -0
  67. package/dest/store/kv_archiver_store.js +481 -0
  68. package/dest/store/l2_tips_cache.d.ts +19 -0
  69. package/dest/store/l2_tips_cache.d.ts.map +1 -0
  70. package/dest/store/l2_tips_cache.js +89 -0
  71. package/dest/store/log_store.d.ts +57 -0
  72. package/dest/store/log_store.d.ts.map +1 -0
  73. package/dest/store/log_store.js +533 -0
  74. package/dest/store/message_store.d.ts +44 -0
  75. package/dest/store/message_store.d.ts.map +1 -0
  76. package/dest/{archiver/kv_archiver_store → store}/message_store.js +14 -1
  77. package/dest/{archiver/structs → structs}/data_retrieval.d.ts +1 -1
  78. package/dest/structs/data_retrieval.d.ts.map +1 -0
  79. package/dest/structs/inbox_message.d.ts +15 -0
  80. package/dest/structs/inbox_message.d.ts.map +1 -0
  81. package/dest/{archiver/structs → structs}/published.d.ts +1 -1
  82. package/dest/structs/published.d.ts.map +1 -0
  83. package/dest/test/fake_l1_state.d.ts +202 -0
  84. package/dest/test/fake_l1_state.d.ts.map +1 -0
  85. package/dest/test/fake_l1_state.js +455 -0
  86. package/dest/test/index.d.ts +2 -1
  87. package/dest/test/index.d.ts.map +1 -1
  88. package/dest/test/index.js +4 -1
  89. package/dest/test/mock_archiver.d.ts +2 -2
  90. package/dest/test/mock_archiver.d.ts.map +1 -1
  91. package/dest/test/mock_archiver.js +3 -3
  92. package/dest/test/mock_l2_block_source.d.ts +38 -19
  93. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  94. package/dest/test/mock_l2_block_source.js +183 -77
  95. package/dest/test/mock_structs.d.ts +81 -3
  96. package/dest/test/mock_structs.d.ts.map +1 -1
  97. package/dest/test/mock_structs.js +152 -7
  98. package/dest/test/noop_l1_archiver.d.ts +26 -0
  99. package/dest/test/noop_l1_archiver.d.ts.map +1 -0
  100. package/dest/test/noop_l1_archiver.js +72 -0
  101. package/package.json +16 -17
  102. package/src/archiver.ts +486 -0
  103. package/src/{archiver/config.ts → config.ts} +19 -1
  104. package/src/{archiver/errors.ts → errors.ts} +52 -24
  105. package/src/factory.ts +141 -10
  106. package/src/index.ts +11 -3
  107. package/src/interfaces.ts +9 -0
  108. package/src/l1/README.md +55 -0
  109. package/src/{archiver/l1 → l1}/bin/retrieve-calldata.ts +45 -33
  110. package/src/l1/calldata_retriever.ts +511 -0
  111. package/src/{archiver/l1 → l1}/data_retrieval.ts +75 -94
  112. package/src/{archiver/l1 → l1}/spire_proposer.ts +7 -15
  113. package/src/{archiver/l1 → l1}/validate_trace.ts +24 -6
  114. package/src/modules/data_source_base.ts +333 -0
  115. package/src/modules/data_store_updater.ts +464 -0
  116. package/src/{archiver → modules}/instrumentation.ts +46 -14
  117. package/src/modules/l1_synchronizer.ts +967 -0
  118. package/src/{archiver → modules}/validation.ts +5 -0
  119. package/src/{archiver/kv_archiver_store → store}/block_store.ts +309 -141
  120. package/src/{archiver/kv_archiver_store → store}/contract_class_store.ts +12 -8
  121. package/src/{archiver/kv_archiver_store → store}/contract_instance_store.ts +1 -1
  122. package/src/{archiver/kv_archiver_store → store}/kv_archiver_store.ts +294 -39
  123. package/src/store/l2_tips_cache.ts +89 -0
  124. package/src/store/log_store.ts +736 -0
  125. package/src/{archiver/kv_archiver_store → store}/message_store.ts +20 -1
  126. package/src/test/fake_l1_state.ts +698 -0
  127. package/src/test/index.ts +4 -0
  128. package/src/test/mock_archiver.ts +4 -3
  129. package/src/test/mock_l2_block_source.ts +233 -93
  130. package/src/test/mock_structs.ts +283 -8
  131. package/src/test/noop_l1_archiver.ts +115 -0
  132. package/dest/archiver/archiver.d.ts +0 -307
  133. package/dest/archiver/archiver.d.ts.map +0 -1
  134. package/dest/archiver/archiver.js +0 -2102
  135. package/dest/archiver/archiver_store.d.ts +0 -315
  136. package/dest/archiver/archiver_store.d.ts.map +0 -1
  137. package/dest/archiver/archiver_store.js +0 -4
  138. package/dest/archiver/archiver_store_test_suite.d.ts +0 -8
  139. package/dest/archiver/archiver_store_test_suite.d.ts.map +0 -1
  140. package/dest/archiver/archiver_store_test_suite.js +0 -2770
  141. package/dest/archiver/config.d.ts +0 -22
  142. package/dest/archiver/config.d.ts.map +0 -1
  143. package/dest/archiver/errors.d.ts +0 -36
  144. package/dest/archiver/errors.d.ts.map +0 -1
  145. package/dest/archiver/errors.js +0 -54
  146. package/dest/archiver/index.d.ts +0 -7
  147. package/dest/archiver/index.d.ts.map +0 -1
  148. package/dest/archiver/index.js +0 -4
  149. package/dest/archiver/instrumentation.d.ts +0 -37
  150. package/dest/archiver/instrumentation.d.ts.map +0 -1
  151. package/dest/archiver/kv_archiver_store/block_store.d.ts +0 -164
  152. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +0 -1
  153. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +0 -18
  154. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +0 -1
  155. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +0 -24
  156. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +0 -1
  157. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +0 -159
  158. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +0 -1
  159. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +0 -316
  160. package/dest/archiver/kv_archiver_store/log_store.d.ts +0 -45
  161. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +0 -1
  162. package/dest/archiver/kv_archiver_store/log_store.js +0 -401
  163. package/dest/archiver/kv_archiver_store/message_store.d.ts +0 -40
  164. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +0 -1
  165. package/dest/archiver/l1/bin/retrieve-calldata.d.ts.map +0 -1
  166. package/dest/archiver/l1/calldata_retriever.d.ts +0 -112
  167. package/dest/archiver/l1/calldata_retriever.d.ts.map +0 -1
  168. package/dest/archiver/l1/calldata_retriever.js +0 -471
  169. package/dest/archiver/l1/data_retrieval.d.ts +0 -90
  170. package/dest/archiver/l1/data_retrieval.d.ts.map +0 -1
  171. package/dest/archiver/l1/debug_tx.d.ts.map +0 -1
  172. package/dest/archiver/l1/spire_proposer.d.ts.map +0 -1
  173. package/dest/archiver/l1/trace_tx.d.ts.map +0 -1
  174. package/dest/archiver/l1/types.d.ts +0 -12
  175. package/dest/archiver/l1/types.d.ts.map +0 -1
  176. package/dest/archiver/l1/validate_trace.d.ts.map +0 -1
  177. package/dest/archiver/structs/data_retrieval.d.ts.map +0 -1
  178. package/dest/archiver/structs/inbox_message.d.ts +0 -15
  179. package/dest/archiver/structs/inbox_message.d.ts.map +0 -1
  180. package/dest/archiver/structs/published.d.ts.map +0 -1
  181. package/dest/archiver/validation.d.ts.map +0 -1
  182. package/dest/rpc/index.d.ts +0 -9
  183. package/dest/rpc/index.d.ts.map +0 -1
  184. package/dest/rpc/index.js +0 -15
  185. package/src/archiver/archiver.ts +0 -2265
  186. package/src/archiver/archiver_store.ts +0 -380
  187. package/src/archiver/archiver_store_test_suite.ts +0 -2842
  188. package/src/archiver/index.ts +0 -6
  189. package/src/archiver/kv_archiver_store/log_store.ts +0 -516
  190. package/src/archiver/l1/README.md +0 -98
  191. package/src/archiver/l1/calldata_retriever.ts +0 -641
  192. package/src/rpc/index.ts +0 -16
  193. /package/dest/{archiver/l1 → l1}/debug_tx.js +0 -0
  194. /package/dest/{archiver/l1 → l1}/trace_tx.js +0 -0
  195. /package/dest/{archiver/l1 → l1}/types.js +0 -0
  196. /package/dest/{archiver/structs → structs}/data_retrieval.js +0 -0
  197. /package/dest/{archiver/structs → structs}/inbox_message.js +0 -0
  198. /package/dest/{archiver/structs → structs}/published.js +0 -0
  199. /package/src/{archiver/l1 → l1}/debug_tx.ts +0 -0
  200. /package/src/{archiver/l1 → l1}/trace_tx.ts +0 -0
  201. /package/src/{archiver/l1 → l1}/types.ts +0 -0
  202. /package/src/{archiver/structs → structs}/data_retrieval.ts +0 -0
  203. /package/src/{archiver/structs → structs}/inbox_message.ts +0 -0
  204. /package/src/{archiver/structs → structs}/published.ts +0 -0
@@ -1,27 +1,31 @@
1
1
  import { INITIAL_CHECKPOINT_NUMBER, INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
2
- import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
2
+ import { BlockNumber, CheckpointNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
4
  import { toArray } from '@aztec/foundation/iterable';
4
5
  import { createLogger } from '@aztec/foundation/log';
5
6
  import { BufferReader } from '@aztec/foundation/serialize';
6
7
  import { bufferToHex } from '@aztec/foundation/string';
7
8
  import { isDefined } from '@aztec/foundation/types';
8
- import { Body, CheckpointedL2Block, CommitteeAttestation, L2BlockHash, L2BlockNew, deserializeValidateCheckpointResult, serializeValidateCheckpointResult } from '@aztec/stdlib/block';
9
+ import { Body, CheckpointedL2Block, CommitteeAttestation, L2Block, deserializeValidateCheckpointResult, serializeValidateCheckpointResult } from '@aztec/stdlib/block';
9
10
  import { L1PublishedData } from '@aztec/stdlib/checkpoint';
11
+ import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
10
12
  import { CheckpointHeader } from '@aztec/stdlib/rollup';
11
13
  import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
12
- import { BlockHeader, TxHash, TxReceipt, deserializeIndexedTxEffect, serializeIndexedTxEffect } from '@aztec/stdlib/tx';
13
- import { BlockArchiveNotConsistentError, BlockIndexNotSequentialError, BlockNotFoundError, BlockNumberNotSequentialError, CheckpointNotFoundError, CheckpointNumberNotConsistentError, CheckpointNumberNotSequentialError, InitialBlockNumberNotSequentialError, InitialCheckpointNumberNotSequentialError } from '../errors.js';
14
+ import { BlockHeader, TxHash, TxReceipt, TxStatus, deserializeIndexedTxEffect, serializeIndexedTxEffect } from '@aztec/stdlib/tx';
15
+ import { BlockAlreadyCheckpointedError, BlockArchiveNotConsistentError, BlockIndexNotSequentialError, BlockNotFoundError, BlockNumberNotSequentialError, CannotOverwriteCheckpointedBlockError, CheckpointNotFoundError, CheckpointNumberNotSequentialError, InitialCheckpointNumberNotSequentialError } from '../errors.js';
14
16
  export { TxReceipt } from '@aztec/stdlib/tx';
15
17
  /**
16
- * LMDB implementation of the ArchiverDataStore interface.
18
+ * LMDB-based block storage for the archiver.
17
19
  */ export class BlockStore {
18
20
  db;
19
21
  /** Map block number to block data */ #blocks;
20
22
  /** Map checkpoint number to checkpoint data */ #checkpoints;
23
+ /** Map slot number to checkpoint number, for looking up checkpoints by slot range. */ #slotToCheckpoint;
21
24
  /** Map block hash to list of tx hashes */ #blockTxs;
22
25
  /** Tx hash to serialized IndexedTxEffect */ #txEffects;
23
26
  /** Stores L1 block number in which the last processed L2 block was included */ #lastSynchedL1Block;
24
27
  /** Stores last proven checkpoint */ #lastProvenCheckpoint;
28
+ /** Stores last finalized checkpoint (proven at or before the finalized L1 block) */ #lastFinalizedCheckpoint;
25
29
  /** Stores the pending chain validation status */ #pendingChainValidationStatus;
26
30
  /** Index mapping a contract's address (as a string) to its location in a block */ #contractIndex;
27
31
  /** Index mapping block hash to block number */ #blockHashIndex;
@@ -38,72 +42,78 @@ export { TxReceipt } from '@aztec/stdlib/tx';
38
42
  this.#blockArchiveIndex = db.openMap('archiver_block_archive_index');
39
43
  this.#lastSynchedL1Block = db.openSingleton('archiver_last_synched_l1_block');
40
44
  this.#lastProvenCheckpoint = db.openSingleton('archiver_last_proven_l2_checkpoint');
45
+ this.#lastFinalizedCheckpoint = db.openSingleton('archiver_last_finalized_l2_checkpoint');
41
46
  this.#pendingChainValidationStatus = db.openSingleton('archiver_pending_chain_validation_status');
42
47
  this.#checkpoints = db.openMap('archiver_checkpoints');
48
+ this.#slotToCheckpoint = db.openMap('archiver_slot_to_checkpoint');
43
49
  }
44
50
  /**
45
- * Append new blocks to the store's list. All blocks must be for the 'current' checkpoint
46
- * @param blocks - The L2 blocks to be added to the store.
47
- * @returns True if the operation is successful.
48
- */ async addBlocks(blocks, opts = {}) {
49
- if (blocks.length === 0) {
50
- return true;
51
+ * Returns the finalized L2 block number. An L2 block is finalized when it was proven
52
+ * in an L1 block that has itself been finalized on Ethereum.
53
+ * @returns The finalized block number.
54
+ */ async getFinalizedL2BlockNumber() {
55
+ const finalizedCheckpointNumber = await this.getFinalizedCheckpointNumber();
56
+ if (finalizedCheckpointNumber === INITIAL_CHECKPOINT_NUMBER - 1) {
57
+ return BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
58
+ }
59
+ const checkpointStorage = await this.#checkpoints.getAsync(finalizedCheckpointNumber);
60
+ if (!checkpointStorage) {
61
+ throw new CheckpointNotFoundError(finalizedCheckpointNumber);
51
62
  }
63
+ return BlockNumber(checkpointStorage.startBlock + checkpointStorage.blockCount - 1);
64
+ }
65
+ /**
66
+ * Append a new proposed block to the store.
67
+ * This is an uncheckpointed block that has been proposed by the sequencer but not yet included in a checkpoint on L1.
68
+ * For checkpointed blocks (already published to L1), use addCheckpoints() instead.
69
+ * @param block - The proposed L2 block to be added to the store.
70
+ * @returns True if the operation is successful.
71
+ */ async addProposedBlock(block, opts = {}) {
52
72
  return await this.db.transactionAsync(async ()=>{
53
- // Check that the block immediately before the first block to be added is present in the store.
54
- const firstBlockNumber = blocks[0].number;
55
- const firstBlockCheckpointNumber = blocks[0].checkpointNumber;
56
- const firstBlockIndex = blocks[0].indexWithinCheckpoint;
57
- const firstBlockLastArchive = blocks[0].header.lastArchive.root;
73
+ const blockNumber = block.number;
74
+ const blockCheckpointNumber = block.checkpointNumber;
75
+ const blockIndex = block.indexWithinCheckpoint;
76
+ const blockLastArchive = block.header.lastArchive.root;
58
77
  // Extract the latest block and checkpoint numbers
59
78
  const previousBlockNumber = await this.getLatestBlockNumber();
60
79
  const previousCheckpointNumber = await this.getLatestCheckpointNumber();
61
- // Check that the first block number is the expected one
62
- if (!opts.force && previousBlockNumber !== firstBlockNumber - 1) {
63
- throw new InitialBlockNumberNotSequentialError(firstBlockNumber, previousBlockNumber);
80
+ // Verify we're not overwriting checkpointed blocks
81
+ const lastCheckpointedBlockNumber = await this.getCheckpointedL2BlockNumber();
82
+ if (!opts.force && blockNumber <= lastCheckpointedBlockNumber) {
83
+ // Check if the proposed block matches the already-checkpointed one
84
+ const existingBlock = await this.getBlock(BlockNumber(blockNumber));
85
+ if (existingBlock && existingBlock.archive.root.equals(block.archive.root)) {
86
+ throw new BlockAlreadyCheckpointedError(blockNumber);
87
+ }
88
+ throw new CannotOverwriteCheckpointedBlockError(blockNumber, lastCheckpointedBlockNumber);
89
+ }
90
+ // Check that the block number is the expected one
91
+ if (!opts.force && previousBlockNumber !== blockNumber - 1) {
92
+ throw new BlockNumberNotSequentialError(blockNumber, previousBlockNumber);
64
93
  }
65
94
  // The same check as above but for checkpoints
66
- if (!opts.force && previousCheckpointNumber !== firstBlockCheckpointNumber - 1) {
67
- throw new InitialCheckpointNumberNotSequentialError(firstBlockCheckpointNumber, previousCheckpointNumber);
95
+ if (!opts.force && previousCheckpointNumber !== blockCheckpointNumber - 1) {
96
+ throw new CheckpointNumberNotSequentialError(blockCheckpointNumber, previousCheckpointNumber);
68
97
  }
69
98
  // Extract the previous block if there is one and see if it is for the same checkpoint or not
70
99
  const previousBlockResult = await this.getBlock(previousBlockNumber);
71
- let expectedFirstblockIndex = 0;
100
+ let expectedBlockIndex = 0;
72
101
  let previousBlockIndex = undefined;
73
102
  if (previousBlockResult !== undefined) {
74
- if (previousBlockResult.checkpointNumber === firstBlockCheckpointNumber) {
103
+ if (previousBlockResult.checkpointNumber === blockCheckpointNumber) {
75
104
  // The previous block is for the same checkpoint, therefore our index should follow it
76
105
  previousBlockIndex = previousBlockResult.indexWithinCheckpoint;
77
- expectedFirstblockIndex = previousBlockIndex + 1;
106
+ expectedBlockIndex = previousBlockIndex + 1;
78
107
  }
79
- if (!previousBlockResult.archive.root.equals(firstBlockLastArchive)) {
80
- throw new BlockArchiveNotConsistentError(firstBlockNumber, previousBlockResult.number, firstBlockLastArchive, previousBlockResult.archive.root);
108
+ if (!previousBlockResult.archive.root.equals(blockLastArchive)) {
109
+ throw new BlockArchiveNotConsistentError(blockNumber, previousBlockResult.number, blockLastArchive, previousBlockResult.archive.root);
81
110
  }
82
111
  }
83
- // Now check that the first block has the expected index value
84
- if (!opts.force && expectedFirstblockIndex !== firstBlockIndex) {
85
- throw new BlockIndexNotSequentialError(firstBlockIndex, previousBlockIndex);
86
- }
87
- // Iterate over blocks array and insert them, checking that the block numbers and indexes are sequential. Also check they are for the correct checkpoint.
88
- let previousBlock = undefined;
89
- for (const block of blocks){
90
- if (!opts.force && previousBlock) {
91
- if (previousBlock.number + 1 !== block.number) {
92
- throw new BlockNumberNotSequentialError(block.number, previousBlock.number);
93
- }
94
- if (previousBlock.indexWithinCheckpoint + 1 !== block.indexWithinCheckpoint) {
95
- throw new BlockIndexNotSequentialError(block.indexWithinCheckpoint, previousBlock.indexWithinCheckpoint);
96
- }
97
- if (!previousBlock.archive.root.equals(block.header.lastArchive.root)) {
98
- throw new BlockArchiveNotConsistentError(block.number, previousBlock.number, block.header.lastArchive.root, previousBlock.archive.root);
99
- }
100
- }
101
- if (!opts.force && firstBlockCheckpointNumber !== block.checkpointNumber) {
102
- throw new CheckpointNumberNotConsistentError(block.checkpointNumber, firstBlockCheckpointNumber);
103
- }
104
- previousBlock = block;
105
- await this.addBlockToDatabase(block, block.checkpointNumber, block.indexWithinCheckpoint);
112
+ // Now check that the block has the expected index value
113
+ if (!opts.force && expectedBlockIndex !== blockIndex) {
114
+ throw new BlockIndexNotSequentialError(blockIndex, previousBlockIndex);
106
115
  }
116
+ await this.addBlockToDatabase(block, block.checkpointNumber, block.indexWithinCheckpoint);
107
117
  return true;
108
118
  });
109
119
  }
@@ -135,7 +145,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
135
145
  let previousBlock = undefined;
136
146
  // If we have a previous checkpoint then we need to get the previous block number
137
147
  if (previousCheckpointData !== undefined) {
138
- previousBlockNumber = BlockNumber(previousCheckpointData.startBlock + previousCheckpointData.numBlocks - 1);
148
+ previousBlockNumber = BlockNumber(previousCheckpointData.startBlock + previousCheckpointData.blockCount - 1);
139
149
  previousBlock = await this.getBlock(previousBlockNumber);
140
150
  if (previousBlock === undefined) {
141
151
  // We should be able to get the required previous block
@@ -180,19 +190,22 @@ export { TxReceipt } from '@aztec/stdlib/tx';
180
190
  await this.#checkpoints.set(checkpoint.checkpoint.number, {
181
191
  header: checkpoint.checkpoint.header.toBuffer(),
182
192
  archive: checkpoint.checkpoint.archive.toBuffer(),
193
+ checkpointOutHash: checkpoint.checkpoint.getCheckpointOutHash().toBuffer(),
183
194
  l1: checkpoint.l1.toBuffer(),
184
195
  attestations: checkpoint.attestations.map((attestation)=>attestation.toBuffer()),
185
196
  checkpointNumber: checkpoint.checkpoint.number,
186
197
  startBlock: checkpoint.checkpoint.blocks[0].number,
187
- numBlocks: checkpoint.checkpoint.blocks.length
198
+ blockCount: checkpoint.checkpoint.blocks.length
188
199
  });
200
+ // Update slot-to-checkpoint index
201
+ await this.#slotToCheckpoint.set(checkpoint.checkpoint.header.slotNumber, checkpoint.checkpoint.number);
189
202
  }
190
203
  await this.#lastSynchedL1Block.set(checkpoints[checkpoints.length - 1].l1.blockNumber);
191
204
  return true;
192
205
  });
193
206
  }
194
207
  async addBlockToDatabase(block, checkpointNumber, indexWithinCheckpoint) {
195
- const blockHash = L2BlockHash.fromField(await block.hash());
208
+ const blockHash = await block.hash();
196
209
  await this.#blocks.set(block.number, {
197
210
  header: block.header.toBuffer(),
198
211
  blockHash: blockHash.toBuffer(),
@@ -214,48 +227,63 @@ export { TxReceipt } from '@aztec/stdlib/tx';
214
227
  await this.#blockHashIndex.set(blockHash.toString(), block.number);
215
228
  await this.#blockArchiveIndex.set(block.archive.root.toString(), block.number);
216
229
  }
230
+ /** Deletes a block and all associated data (tx effects, indices). */ async deleteBlock(block) {
231
+ // Delete the block from the main blocks map
232
+ await this.#blocks.delete(block.number);
233
+ // Delete all tx effects for this block
234
+ await Promise.all(block.body.txEffects.map((tx)=>this.#txEffects.delete(tx.txHash.toString())));
235
+ // Delete block txs mapping
236
+ const blockHash = (await block.hash()).toString();
237
+ await this.#blockTxs.delete(blockHash);
238
+ // Clean up indices
239
+ await this.#blockHashIndex.delete(blockHash);
240
+ await this.#blockArchiveIndex.delete(block.archive.root.toString());
241
+ }
217
242
  /**
218
- * Unwinds checkpoints from the database
219
- * @param from - The tip of the chain, passed for verification purposes,
220
- * ensuring that we don't end up deleting something we did not intend
221
- * @param checkpointsToUnwind - The number of checkpoints we are to unwind
222
- * @returns True if the operation is successful
223
- */ async unwindCheckpoints(from, checkpointsToUnwind) {
243
+ * Removes all checkpoints with checkpoint number > checkpointNumber.
244
+ * Also removes ALL blocks (both checkpointed and uncheckpointed) after the last block of the given checkpoint.
245
+ * @param checkpointNumber - Remove all checkpoints strictly after this one.
246
+ */ async removeCheckpointsAfter(checkpointNumber) {
224
247
  return await this.db.transactionAsync(async ()=>{
225
- const last = await this.getLatestCheckpointNumber();
226
- if (from !== last) {
227
- throw new Error(`Can only unwind checkpoints from the tip (requested ${from} but current tip is ${last})`);
248
+ const latestCheckpointNumber = await this.getLatestCheckpointNumber();
249
+ if (checkpointNumber >= latestCheckpointNumber) {
250
+ this.#log.warn(`No checkpoints to remove after ${checkpointNumber} (latest is ${latestCheckpointNumber})`);
251
+ return {
252
+ blocksRemoved: undefined
253
+ };
228
254
  }
255
+ // If the proven checkpoint is beyond the target, update it
229
256
  const proven = await this.getProvenCheckpointNumber();
230
- if (from - checkpointsToUnwind < proven) {
231
- await this.setProvenCheckpointNumber(CheckpointNumber(from - checkpointsToUnwind));
257
+ if (proven > checkpointNumber) {
258
+ this.#log.warn(`Updating proven checkpoint ${proven} to last valid checkpoint ${checkpointNumber}`);
259
+ await this.setProvenCheckpointNumber(checkpointNumber);
232
260
  }
233
- for(let i = 0; i < checkpointsToUnwind; i++){
234
- const checkpointNumber = from - i;
235
- const checkpoint = await this.#checkpoints.getAsync(checkpointNumber);
236
- if (checkpoint === undefined) {
237
- this.#log.warn(`Cannot remove checkpoint ${checkpointNumber} from the store since we don't have it`);
238
- continue;
261
+ // Find the last block number to keep (last block of the given checkpoint, or 0 if no checkpoint)
262
+ let lastBlockToKeep;
263
+ if (checkpointNumber <= 0) {
264
+ lastBlockToKeep = BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
265
+ } else {
266
+ const targetCheckpoint = await this.#checkpoints.getAsync(checkpointNumber);
267
+ if (!targetCheckpoint) {
268
+ throw new Error(`Target checkpoint ${checkpointNumber} not found in store`);
239
269
  }
240
- await this.#checkpoints.delete(checkpointNumber);
241
- const maxBlock = checkpoint.startBlock + checkpoint.numBlocks - 1;
242
- for(let blockNumber = checkpoint.startBlock; blockNumber <= maxBlock; blockNumber++){
243
- const block = await this.getBlock(BlockNumber(blockNumber));
244
- if (block === undefined) {
245
- this.#log.warn(`Cannot remove block ${blockNumber} from the store since we don't have it`);
246
- continue;
247
- }
248
- await this.#blocks.delete(block.number);
249
- await Promise.all(block.body.txEffects.map((tx)=>this.#txEffects.delete(tx.txHash.toString())));
250
- const blockHash = (await block.hash()).toString();
251
- await this.#blockTxs.delete(blockHash);
252
- // Clean up indices
253
- await this.#blockHashIndex.delete(blockHash);
254
- await this.#blockArchiveIndex.delete(block.archive.root.toString());
255
- this.#log.debug(`Unwound block ${blockNumber} ${blockHash} for checkpoint ${checkpointNumber}`);
270
+ lastBlockToKeep = BlockNumber(targetCheckpoint.startBlock + targetCheckpoint.blockCount - 1);
271
+ }
272
+ // Remove all blocks after lastBlockToKeep (both checkpointed and uncheckpointed)
273
+ const blocksRemoved = await this.removeBlocksAfter(lastBlockToKeep);
274
+ // Remove all checkpoints after the target
275
+ for(let c = latestCheckpointNumber; c > checkpointNumber; c = CheckpointNumber(c - 1)){
276
+ const checkpointStorage = await this.#checkpoints.getAsync(c);
277
+ if (checkpointStorage) {
278
+ const slotNumber = CheckpointHeader.fromBuffer(checkpointStorage.header).slotNumber;
279
+ await this.#slotToCheckpoint.delete(slotNumber);
256
280
  }
281
+ await this.#checkpoints.delete(c);
282
+ this.#log.debug(`Removed checkpoint ${c}`);
257
283
  }
258
- return true;
284
+ return {
285
+ blocksRemoved
286
+ };
259
287
  });
260
288
  }
261
289
  async getCheckpointData(checkpointNumber) {
@@ -276,17 +304,30 @@ export { TxReceipt } from '@aztec/stdlib/tx';
276
304
  }
277
305
  return checkpoints;
278
306
  }
307
+ /** Returns checkpoint data for all checkpoints whose slot falls within the given range (inclusive). */ async getCheckpointDataForSlotRange(startSlot, endSlot) {
308
+ const result = [];
309
+ for await (const [, checkpointNumber] of this.#slotToCheckpoint.entriesAsync({
310
+ start: startSlot,
311
+ end: endSlot + 1
312
+ })){
313
+ const checkpointStorage = await this.#checkpoints.getAsync(checkpointNumber);
314
+ if (checkpointStorage) {
315
+ result.push(this.checkpointDataFromCheckpointStorage(checkpointStorage));
316
+ }
317
+ }
318
+ return result;
319
+ }
279
320
  checkpointDataFromCheckpointStorage(checkpointStorage) {
280
- const data = {
321
+ return {
281
322
  header: CheckpointHeader.fromBuffer(checkpointStorage.header),
282
323
  archive: AppendOnlyTreeSnapshot.fromBuffer(checkpointStorage.archive),
324
+ checkpointOutHash: Fr.fromBuffer(checkpointStorage.checkpointOutHash),
283
325
  checkpointNumber: CheckpointNumber(checkpointStorage.checkpointNumber),
284
- startBlock: checkpointStorage.startBlock,
285
- numBlocks: checkpointStorage.numBlocks,
326
+ startBlock: BlockNumber(checkpointStorage.startBlock),
327
+ blockCount: checkpointStorage.blockCount,
286
328
  l1: L1PublishedData.fromBuffer(checkpointStorage.l1),
287
- attestations: checkpointStorage.attestations
329
+ attestations: checkpointStorage.attestations.map((buf)=>CommitteeAttestation.fromBuffer(buf))
288
330
  };
289
- return data;
290
331
  }
291
332
  async getBlocksForCheckpoint(checkpointNumber) {
292
333
  const checkpoint = await this.#checkpoints.getAsync(checkpointNumber);
@@ -295,11 +336,58 @@ export { TxReceipt } from '@aztec/stdlib/tx';
295
336
  }
296
337
  const blocksForCheckpoint = await toArray(this.#blocks.entriesAsync({
297
338
  start: checkpoint.startBlock,
298
- end: checkpoint.startBlock + checkpoint.numBlocks
339
+ end: checkpoint.startBlock + checkpoint.blockCount
299
340
  }));
300
341
  const converted = await Promise.all(blocksForCheckpoint.map((x)=>this.getBlockFromBlockStorage(x[0], x[1])));
301
342
  return converted.filter(isDefined);
302
343
  }
344
+ /**
345
+ * Gets all blocks that have the given slot number.
346
+ * Iterates backwards through blocks for efficiency since we usually query for the last slot.
347
+ * @param slotNumber - The slot number to search for.
348
+ * @returns All blocks with the given slot number, in ascending block number order.
349
+ */ async getBlocksForSlot(slotNumber) {
350
+ const blocks = [];
351
+ // Iterate backwards through all blocks and filter by slot number
352
+ // This is more efficient since we usually query for the most recent slot
353
+ for await (const [blockNumber, blockStorage] of this.#blocks.entriesAsync({
354
+ reverse: true
355
+ })){
356
+ const block = await this.getBlockFromBlockStorage(blockNumber, blockStorage);
357
+ const blockSlot = block?.header.globalVariables.slotNumber;
358
+ if (block && blockSlot === slotNumber) {
359
+ blocks.push(block);
360
+ } else if (blockSlot && blockSlot < slotNumber) {
361
+ break; // Blocks are stored in slot ascending order, so we can stop searching
362
+ }
363
+ }
364
+ // Reverse to return blocks in ascending order (block number order)
365
+ return blocks.reverse();
366
+ }
367
+ /**
368
+ * Removes all blocks with block number > blockNumber.
369
+ * Does not remove any associated checkpoints.
370
+ * @param blockNumber - The block number to remove after.
371
+ * @returns The removed blocks (for event emission).
372
+ */ async removeBlocksAfter(blockNumber) {
373
+ return await this.db.transactionAsync(async ()=>{
374
+ const removedBlocks = [];
375
+ // Get the latest block number to determine the range
376
+ const latestBlockNumber = await this.getLatestBlockNumber();
377
+ // Iterate from blockNumber + 1 to latestBlockNumber
378
+ for(let bn = blockNumber + 1; bn <= latestBlockNumber; bn++){
379
+ const block = await this.getBlock(BlockNumber(bn));
380
+ if (block === undefined) {
381
+ this.#log.warn(`Cannot remove block ${bn} from the store since we don't have it`);
382
+ continue;
383
+ }
384
+ removedBlocks.push(block);
385
+ await this.deleteBlock(block);
386
+ this.#log.debug(`Removed block ${bn} ${(await block.hash()).toString()}`);
387
+ }
388
+ return removedBlocks;
389
+ });
390
+ }
303
391
  async getProvenBlockNumber() {
304
392
  const provenCheckpointNumber = await this.getProvenCheckpointNumber();
305
393
  if (provenCheckpointNumber === INITIAL_CHECKPOINT_NUMBER - 1) {
@@ -309,7 +397,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
309
397
  if (!checkpointStorage) {
310
398
  throw new CheckpointNotFoundError(provenCheckpointNumber);
311
399
  } else {
312
- return BlockNumber(checkpointStorage.startBlock + checkpointStorage.numBlocks - 1);
400
+ return BlockNumber(checkpointStorage.startBlock + checkpointStorage.blockCount - 1);
313
401
  }
314
402
  }
315
403
  async getLatestBlockNumber() {
@@ -391,6 +479,28 @@ export { TxReceipt } from '@aztec/stdlib/tx';
391
479
  }
392
480
  }
393
481
  /**
482
+ * Gets block metadata (without tx data) by block number.
483
+ * @param blockNumber - The number of the block to return.
484
+ * @returns The requested block data.
485
+ */ async getBlockData(blockNumber) {
486
+ const blockStorage = await this.#blocks.getAsync(blockNumber);
487
+ if (!blockStorage || !blockStorage.header) {
488
+ return undefined;
489
+ }
490
+ return this.getBlockDataFromBlockStorage(blockStorage);
491
+ }
492
+ /**
493
+ * Gets block metadata (without tx data) by archive root.
494
+ * @param archive - The archive root of the block to return.
495
+ * @returns The requested block data.
496
+ */ async getBlockDataByArchive(archive) {
497
+ const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
498
+ if (blockNumber === undefined) {
499
+ return undefined;
500
+ }
501
+ return this.getBlockData(BlockNumber(blockNumber));
502
+ }
503
+ /**
394
504
  * Gets an L2 block.
395
505
  * @param blockNumber - The number of the block to return.
396
506
  * @returns The requested L2 block.
@@ -480,11 +590,19 @@ export { TxReceipt } from '@aztec/stdlib/tx';
480
590
  ];
481
591
  }
482
592
  }
593
+ getBlockDataFromBlockStorage(blockStorage) {
594
+ return {
595
+ header: BlockHeader.fromBuffer(blockStorage.header),
596
+ archive: AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive),
597
+ blockHash: Fr.fromBuffer(blockStorage.blockHash),
598
+ checkpointNumber: CheckpointNumber(blockStorage.checkpointNumber),
599
+ indexWithinCheckpoint: IndexWithinCheckpoint(blockStorage.indexWithinCheckpoint)
600
+ };
601
+ }
483
602
  async getBlockFromBlockStorage(blockNumber, blockStorage) {
484
- const header = BlockHeader.fromBuffer(blockStorage.header);
485
- const archive = AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive);
486
- const blockHash = blockStorage.blockHash;
487
- const blockHashString = bufferToHex(blockHash);
603
+ const { header, archive, blockHash, checkpointNumber, indexWithinCheckpoint } = this.getBlockDataFromBlockStorage(blockStorage);
604
+ header.setHash(blockHash);
605
+ const blockHashString = bufferToHex(blockStorage.blockHash);
488
606
  const blockTxsBuffer = await this.#blockTxs.getAsync(blockHashString);
489
607
  if (blockTxsBuffer === undefined) {
490
608
  this.#log.warn(`Could not find body for block ${header.globalVariables.blockNumber} ${blockHash}`);
@@ -502,7 +620,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
502
620
  txEffects.push(deserializeIndexedTxEffect(txEffect).data);
503
621
  }
504
622
  const body = new Body(txEffects);
505
- const block = new L2BlockNew(archive, header, body, CheckpointNumber(blockStorage.checkpointNumber), blockStorage.indexWithinCheckpoint);
623
+ const block = new L2Block(archive, header, body, checkpointNumber, indexWithinCheckpoint);
506
624
  if (block.number !== blockNumber) {
507
625
  throw new Error(`Block number mismatch when retrieving block from archive (expected ${blockNumber} but got ${block.number} with hash ${blockHashString})`);
508
626
  }
@@ -523,12 +641,31 @@ export { TxReceipt } from '@aztec/stdlib/tx';
523
641
  * Gets a receipt of a settled tx.
524
642
  * @param txHash - The hash of a tx we try to get the receipt for.
525
643
  * @returns The requested tx receipt (or undefined if not found).
526
- */ async getSettledTxReceipt(txHash) {
644
+ */ async getSettledTxReceipt(txHash, l1Constants) {
527
645
  const txEffect = await this.getTxEffect(txHash);
528
646
  if (!txEffect) {
529
647
  return undefined;
530
648
  }
531
- return new TxReceipt(txHash, TxReceipt.statusFromRevertCode(txEffect.data.revertCode), '', txEffect.data.transactionFee.toBigInt(), txEffect.l2BlockHash, BlockNumber(txEffect.l2BlockNumber));
649
+ const blockNumber = BlockNumber(txEffect.l2BlockNumber);
650
+ // Use existing archiver methods to determine finalization level
651
+ const [provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber, blockData] = await Promise.all([
652
+ this.getProvenBlockNumber(),
653
+ this.getCheckpointedL2BlockNumber(),
654
+ this.getFinalizedL2BlockNumber(),
655
+ this.getBlockData(blockNumber)
656
+ ]);
657
+ let status;
658
+ if (blockNumber <= finalizedBlockNumber) {
659
+ status = TxStatus.FINALIZED;
660
+ } else if (blockNumber <= provenBlockNumber) {
661
+ status = TxStatus.PROVEN;
662
+ } else if (blockNumber <= checkpointedBlockNumber) {
663
+ status = TxStatus.CHECKPOINTED;
664
+ } else {
665
+ status = TxStatus.PROPOSED;
666
+ }
667
+ const epochNumber = blockData && l1Constants ? getEpochAtSlot(blockData.header.globalVariables.slotNumber, l1Constants) : undefined;
668
+ return new TxReceipt(txHash, status, TxReceipt.executionResultFromRevertCode(txEffect.data.revertCode), undefined, txEffect.data.transactionFee.toBigInt(), txEffect.l2BlockHash, blockNumber, epochNumber);
532
669
  }
533
670
  /**
534
671
  * Looks up which block included the requested tx effect.
@@ -561,7 +698,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
561
698
  if (!checkpoint) {
562
699
  return BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
563
700
  }
564
- return BlockNumber(checkpoint.startBlock + checkpoint.numBlocks - 1);
701
+ return BlockNumber(checkpoint.startBlock + checkpoint.blockCount - 1);
565
702
  }
566
703
  async getLatestL2BlockNumber() {
567
704
  const [lastBlockNumber] = await toArray(this.#blocks.keysAsync({
@@ -590,6 +727,16 @@ export { TxReceipt } from '@aztec/stdlib/tx';
590
727
  const result = await this.#lastProvenCheckpoint.set(checkpointNumber);
591
728
  return result;
592
729
  }
730
+ async getFinalizedCheckpointNumber() {
731
+ const [latestCheckpointNumber, finalizedCheckpointNumber] = await Promise.all([
732
+ this.getLatestCheckpointNumber(),
733
+ this.#lastFinalizedCheckpoint.getAsync()
734
+ ]);
735
+ return (finalizedCheckpointNumber ?? 0) > latestCheckpointNumber ? latestCheckpointNumber : CheckpointNumber(finalizedCheckpointNumber ?? 0);
736
+ }
737
+ setFinalizedCheckpointNumber(checkpointNumber) {
738
+ return this.#lastFinalizedCheckpoint.set(checkpointNumber);
739
+ }
593
740
  #computeBlockRange(start, limit) {
594
741
  if (limit < 1) {
595
742
  throw new Error(`Invalid limit: ${limit}`);
@@ -0,0 +1,18 @@
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
+ import type { AztecAsyncKVStore } from '@aztec/kv-store';
3
+ import type { ContractClassPublic, ExecutablePrivateFunctionWithMembershipProof, UtilityFunctionWithMembershipProof } from '@aztec/stdlib/contract';
4
+ /**
5
+ * LMDB-based contract class storage for the archiver.
6
+ */
7
+ export declare class ContractClassStore {
8
+ #private;
9
+ private db;
10
+ constructor(db: AztecAsyncKVStore);
11
+ addContractClass(contractClass: ContractClassPublic, bytecodeCommitment: Fr, blockNumber: number): Promise<void>;
12
+ deleteContractClasses(contractClass: ContractClassPublic, blockNumber: number): Promise<void>;
13
+ getContractClass(id: Fr): Promise<ContractClassPublic | undefined>;
14
+ getBytecodeCommitment(id: Fr): Promise<Fr | undefined>;
15
+ getContractClassIds(): Promise<Fr[]>;
16
+ addFunctions(contractClassId: Fr, newPrivateFunctions: ExecutablePrivateFunctionWithMembershipProof[], newUtilityFunctions: UtilityFunctionWithMembershipProof[]): Promise<boolean>;
17
+ }
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RfY2xhc3Nfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9jb250cmFjdF9jbGFzc19zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHcEQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQWlCLE1BQU0saUJBQWlCLENBQUM7QUFFeEUsT0FBTyxLQUFLLEVBQ1YsbUJBQW1CLEVBRW5CLDRDQUE0QyxFQUM1QyxrQ0FBa0MsRUFDbkMsTUFBTSx3QkFBd0IsQ0FBQztBQUdoQzs7R0FFRztBQUNILHFCQUFhLGtCQUFrQjs7SUFJakIsT0FBTyxDQUFDLEVBQUU7SUFBdEIsWUFBb0IsRUFBRSxFQUFFLGlCQUFpQixFQUd4QztJQUVLLGdCQUFnQixDQUNwQixhQUFhLEVBQUUsbUJBQW1CLEVBQ2xDLGtCQUFrQixFQUFFLEVBQUUsRUFDdEIsV0FBVyxFQUFFLE1BQU0sR0FDbEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQVFmO0lBRUsscUJBQXFCLENBQUMsYUFBYSxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQVFsRztJQUVLLGdCQUFnQixDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixHQUFHLFNBQVMsQ0FBQyxDQUd2RTtJQUVLLHFCQUFxQixDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FHM0Q7SUFFSyxtQkFBbUIsSUFBSSxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FFekM7SUFFSyxZQUFZLENBQ2hCLGVBQWUsRUFBRSxFQUFFLEVBQ25CLG1CQUFtQixFQUFFLDRDQUE0QyxFQUFFLEVBQ25FLG1CQUFtQixFQUFFLGtDQUFrQyxFQUFFLEdBQ3hELE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0F5QmxCO0NBQ0YifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract_class_store.d.ts","sourceRoot":"","sources":["../../src/store/contract_class_store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AAExE,OAAO,KAAK,EACV,mBAAmB,EAEnB,4CAA4C,EAC5C,kCAAkC,EACnC,MAAM,wBAAwB,CAAC;AAGhC;;GAEG;AACH,qBAAa,kBAAkB;;IAIjB,OAAO,CAAC,EAAE;IAAtB,YAAoB,EAAE,EAAE,iBAAiB,EAGxC;IAEK,gBAAgB,CACpB,aAAa,EAAE,mBAAmB,EAClC,kBAAkB,EAAE,EAAE,EACtB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAQf;IAEK,qBAAqB,CAAC,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlG;IAEK,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAGvE;IAEK,qBAAqB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAG3D;IAEK,mBAAmB,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAEzC;IAEK,YAAY,CAChB,eAAe,EAAE,EAAE,EACnB,mBAAmB,EAAE,4CAA4C,EAAE,EACnE,mBAAmB,EAAE,kCAAkC,EAAE,GACxD,OAAO,CAAC,OAAO,CAAC,CAyBlB;CACF"}
@@ -4,7 +4,7 @@ import { BufferReader, numToUInt8, serializeToBuffer } from '@aztec/foundation/s
4
4
  import { FunctionSelector } from '@aztec/stdlib/abi';
5
5
  import { Vector } from '@aztec/stdlib/types';
6
6
  /**
7
- * LMDB implementation of the ArchiverDataStore interface.
7
+ * LMDB-based contract class storage for the archiver.
8
8
  */ export class ContractClassStore {
9
9
  db;
10
10
  #contractClasses;
@@ -15,17 +15,21 @@ import { Vector } from '@aztec/stdlib/types';
15
15
  this.#bytecodeCommitments = db.openMap('archiver_bytecode_commitments');
16
16
  }
17
17
  async addContractClass(contractClass, bytecodeCommitment, blockNumber) {
18
- await this.#contractClasses.setIfNotExists(contractClass.id.toString(), serializeContractClassPublic({
19
- ...contractClass,
20
- l2BlockNumber: blockNumber
21
- }));
22
- await this.#bytecodeCommitments.setIfNotExists(contractClass.id.toString(), bytecodeCommitment.toBuffer());
18
+ await this.db.transactionAsync(async ()=>{
19
+ await this.#contractClasses.setIfNotExists(contractClass.id.toString(), serializeContractClassPublic({
20
+ ...contractClass,
21
+ l2BlockNumber: blockNumber
22
+ }));
23
+ await this.#bytecodeCommitments.setIfNotExists(contractClass.id.toString(), bytecodeCommitment.toBuffer());
24
+ });
23
25
  }
24
26
  async deleteContractClasses(contractClass, blockNumber) {
25
27
  const restoredContractClass = await this.#contractClasses.getAsync(contractClass.id.toString());
26
28
  if (restoredContractClass && deserializeContractClassPublic(restoredContractClass).l2BlockNumber >= blockNumber) {
27
- await this.#contractClasses.delete(contractClass.id.toString());
28
- await this.#bytecodeCommitments.delete(contractClass.id.toString());
29
+ await this.db.transactionAsync(async ()=>{
30
+ await this.#contractClasses.delete(contractClass.id.toString());
31
+ await this.#bytecodeCommitments.delete(contractClass.id.toString());
32
+ });
29
33
  }
30
34
  }
31
35
  async getContractClass(id) {
@@ -0,0 +1,24 @@
1
+ import type { Fr } from '@aztec/foundation/curves/bn254';
2
+ import type { AztecAsyncKVStore } from '@aztec/kv-store';
3
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
4
+ import { type ContractInstanceUpdateWithAddress, type ContractInstanceWithAddress } from '@aztec/stdlib/contract';
5
+ import type { UInt64 } from '@aztec/stdlib/types';
6
+ type ContractInstanceUpdateKey = [string, string] | [string, string, number];
7
+ /**
8
+ * LMDB-based contract instance storage for the archiver.
9
+ */
10
+ export declare class ContractInstanceStore {
11
+ #private;
12
+ private db;
13
+ constructor(db: AztecAsyncKVStore);
14
+ addContractInstance(contractInstance: ContractInstanceWithAddress, blockNumber: number): Promise<void>;
15
+ deleteContractInstance(contractInstance: ContractInstanceWithAddress): Promise<void>;
16
+ getUpdateKey(contractAddress: AztecAddress, timestamp: UInt64, logIndex?: number): ContractInstanceUpdateKey;
17
+ addContractInstanceUpdate(contractInstanceUpdate: ContractInstanceUpdateWithAddress, timestamp: UInt64, logIndex: number): Promise<void>;
18
+ deleteContractInstanceUpdate(contractInstanceUpdate: ContractInstanceUpdateWithAddress, timestamp: UInt64, logIndex: number): Promise<void>;
19
+ getCurrentContractInstanceClassId(address: AztecAddress, timestamp: UInt64, originalClassId: Fr): Promise<Fr>;
20
+ getContractInstance(address: AztecAddress, timestamp: UInt64): Promise<ContractInstanceWithAddress | undefined>;
21
+ getContractInstanceDeploymentBlockNumber(address: AztecAddress): Promise<number | undefined>;
22
+ }
23
+ export {};
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RfaW5zdGFuY2Vfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9jb250cmFjdF9pbnN0YW5jZV9zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBaUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEVBQ0wsS0FBSyxpQ0FBaUMsRUFDdEMsS0FBSywyQkFBMkIsRUFHakMsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVsRCxLQUFLLHlCQUF5QixHQUFHLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztBQUU3RTs7R0FFRztBQUNILHFCQUFhLHFCQUFxQjs7SUFLcEIsT0FBTyxDQUFDLEVBQUU7SUFBdEIsWUFBb0IsRUFBRSxFQUFFLGlCQUFpQixFQUl4QztJQUVELG1CQUFtQixDQUFDLGdCQUFnQixFQUFFLDJCQUEyQixFQUFFLFdBQVcsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQVFyRztJQUVELHNCQUFzQixDQUFDLGdCQUFnQixFQUFFLDJCQUEyQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FLbkY7SUFFRCxZQUFZLENBQUMsZUFBZSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxFQUFFLE1BQU0sR0FBRyx5QkFBeUIsQ0FNM0c7SUFFRCx5QkFBeUIsQ0FDdkIsc0JBQXNCLEVBQUUsaUNBQWlDLEVBQ3pELFNBQVMsRUFBRSxNQUFNLEVBQ2pCLFFBQVEsRUFBRSxNQUFNLEdBQ2YsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUtmO0lBRUQsNEJBQTRCLENBQzFCLHNCQUFzQixFQUFFLGlDQUFpQyxFQUN6RCxTQUFTLEVBQUUsTUFBTSxFQUNqQixRQUFRLEVBQUUsTUFBTSxHQUNmLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFZjtJQUVLLGlDQUFpQyxDQUFDLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FvQmxIO0lBRUssbUJBQW1CLENBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQ3JCLFNBQVMsRUFBRSxNQUFNLEdBQ2hCLE9BQU8sQ0FBQywyQkFBMkIsR0FBRyxTQUFTLENBQUMsQ0FhbEQ7SUFFRCx3Q0FBd0MsQ0FBQyxPQUFPLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBRTNGO0NBQ0YifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract_instance_store.d.ts","sourceRoot":"","sources":["../../src/store/contract_instance_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,KAAK,iCAAiC,EACtC,KAAK,2BAA2B,EAGjC,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,KAAK,yBAAyB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7E;;GAEG;AACH,qBAAa,qBAAqB;;IAKpB,OAAO,CAAC,EAAE;IAAtB,YAAoB,EAAE,EAAE,iBAAiB,EAIxC;IAED,mBAAmB,CAAC,gBAAgB,EAAE,2BAA2B,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQrG;IAED,sBAAsB,CAAC,gBAAgB,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnF;IAED,YAAY,CAAC,eAAe,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,yBAAyB,CAM3G;IAED,yBAAyB,CACvB,sBAAsB,EAAE,iCAAiC,EACzD,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,4BAA4B,CAC1B,sBAAsB,EAAE,iCAAiC,EACzD,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAEf;IAEK,iCAAiC,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAoBlH;IAEK,mBAAmB,CACvB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAalD;IAED,wCAAwC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE3F;CACF"}
@@ -1,6 +1,6 @@
1
1
  import { SerializableContractInstance, SerializableContractInstanceUpdate } from '@aztec/stdlib/contract';
2
2
  /**
3
- * LMDB implementation of the ArchiverDataStore interface.
3
+ * LMDB-based contract instance storage for the archiver.
4
4
  */ export class ContractInstanceStore {
5
5
  db;
6
6
  #contractInstances;