@aztec-labs/archiver 6.0.0-nightly.20260829

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 (174) hide show
  1. package/README.md +178 -0
  2. package/dest/archiver.d.ts +194 -0
  3. package/dest/archiver.d.ts.map +1 -0
  4. package/dest/archiver.js +948 -0
  5. package/dest/config.d.ts +34 -0
  6. package/dest/config.d.ts.map +1 -0
  7. package/dest/config.js +100 -0
  8. package/dest/errors.d.ts +97 -0
  9. package/dest/errors.d.ts.map +1 -0
  10. package/dest/errors.js +141 -0
  11. package/dest/factory.d.ts +32 -0
  12. package/dest/factory.d.ts.map +1 -0
  13. package/dest/factory.js +183 -0
  14. package/dest/index.d.ts +20 -0
  15. package/dest/index.d.ts.map +1 -0
  16. package/dest/index.js +18 -0
  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/l1/bin/retrieve-calldata.d.ts +3 -0
  21. package/dest/l1/bin/retrieve-calldata.d.ts.map +1 -0
  22. package/dest/l1/bin/retrieve-calldata.js +152 -0
  23. package/dest/l1/calldata_retriever.d.ts +143 -0
  24. package/dest/l1/calldata_retriever.d.ts.map +1 -0
  25. package/dest/l1/calldata_retriever.js +413 -0
  26. package/dest/l1/data_retrieval.d.ts +102 -0
  27. package/dest/l1/data_retrieval.d.ts.map +1 -0
  28. package/dest/l1/data_retrieval.js +308 -0
  29. package/dest/l1/debug_tx.d.ts +19 -0
  30. package/dest/l1/debug_tx.d.ts.map +1 -0
  31. package/dest/l1/debug_tx.js +73 -0
  32. package/dest/l1/spire_proposer.d.ts +70 -0
  33. package/dest/l1/spire_proposer.d.ts.map +1 -0
  34. package/dest/l1/spire_proposer.js +149 -0
  35. package/dest/l1/trace_tx.d.ts +43 -0
  36. package/dest/l1/trace_tx.d.ts.map +1 -0
  37. package/dest/l1/trace_tx.js +91 -0
  38. package/dest/l1/types.d.ts +12 -0
  39. package/dest/l1/types.d.ts.map +1 -0
  40. package/dest/l1/types.js +3 -0
  41. package/dest/l1/validate_historical_logs.d.ts +23 -0
  42. package/dest/l1/validate_historical_logs.d.ts.map +1 -0
  43. package/dest/l1/validate_historical_logs.js +108 -0
  44. package/dest/l1/validate_trace.d.ts +32 -0
  45. package/dest/l1/validate_trace.d.ts.map +1 -0
  46. package/dest/l1/validate_trace.js +154 -0
  47. package/dest/modules/contract_data_source_adapter.d.ts +25 -0
  48. package/dest/modules/contract_data_source_adapter.d.ts.map +1 -0
  49. package/dest/modules/contract_data_source_adapter.js +32 -0
  50. package/dest/modules/data_source_base.d.ts +116 -0
  51. package/dest/modules/data_source_base.d.ts.map +1 -0
  52. package/dest/modules/data_source_base.js +334 -0
  53. package/dest/modules/data_store_updater.d.ts +105 -0
  54. package/dest/modules/data_store_updater.d.ts.map +1 -0
  55. package/dest/modules/data_store_updater.js +392 -0
  56. package/dest/modules/instrumentation.d.ts +63 -0
  57. package/dest/modules/instrumentation.d.ts.map +1 -0
  58. package/dest/modules/instrumentation.js +166 -0
  59. package/dest/modules/l1_synchronizer.d.ts +77 -0
  60. package/dest/modules/l1_synchronizer.d.ts.map +1 -0
  61. package/dest/modules/l1_synchronizer.js +1369 -0
  62. package/dest/modules/outbox_trees_resolver.d.ts +64 -0
  63. package/dest/modules/outbox_trees_resolver.d.ts.map +1 -0
  64. package/dest/modules/outbox_trees_resolver.js +184 -0
  65. package/dest/modules/validation.d.ts +40 -0
  66. package/dest/modules/validation.d.ts.map +1 -0
  67. package/dest/modules/validation.js +122 -0
  68. package/dest/store/block_store.d.ts +304 -0
  69. package/dest/store/block_store.d.ts.map +1 -0
  70. package/dest/store/block_store.js +1252 -0
  71. package/dest/store/contract_class_store.d.ts +31 -0
  72. package/dest/store/contract_class_store.d.ts.map +1 -0
  73. package/dest/store/contract_class_store.js +98 -0
  74. package/dest/store/contract_instance_store.d.ts +51 -0
  75. package/dest/store/contract_instance_store.d.ts.map +1 -0
  76. package/dest/store/contract_instance_store.js +129 -0
  77. package/dest/store/data_stores.d.ts +68 -0
  78. package/dest/store/data_stores.d.ts.map +1 -0
  79. package/dest/store/data_stores.js +54 -0
  80. package/dest/store/function_names_cache.d.ts +17 -0
  81. package/dest/store/function_names_cache.d.ts.map +1 -0
  82. package/dest/store/function_names_cache.js +30 -0
  83. package/dest/store/l2_tips_cache.d.ts +25 -0
  84. package/dest/store/l2_tips_cache.d.ts.map +1 -0
  85. package/dest/store/l2_tips_cache.js +26 -0
  86. package/dest/store/log_store.d.ts +59 -0
  87. package/dest/store/log_store.d.ts.map +1 -0
  88. package/dest/store/log_store.js +310 -0
  89. package/dest/store/log_store_codec.d.ts +78 -0
  90. package/dest/store/log_store_codec.d.ts.map +1 -0
  91. package/dest/store/log_store_codec.js +110 -0
  92. package/dest/store/message_store.d.ts +111 -0
  93. package/dest/store/message_store.d.ts.map +1 -0
  94. package/dest/store/message_store.js +522 -0
  95. package/dest/structs/data_retrieval.d.ts +27 -0
  96. package/dest/structs/data_retrieval.d.ts.map +1 -0
  97. package/dest/structs/data_retrieval.js +5 -0
  98. package/dest/structs/inbox_message.d.ts +17 -0
  99. package/dest/structs/inbox_message.d.ts.map +1 -0
  100. package/dest/structs/inbox_message.js +33 -0
  101. package/dest/structs/published.d.ts +2 -0
  102. package/dest/structs/published.d.ts.map +1 -0
  103. package/dest/structs/published.js +1 -0
  104. package/dest/test/fake_l1_state.d.ts +220 -0
  105. package/dest/test/fake_l1_state.d.ts.map +1 -0
  106. package/dest/test/fake_l1_state.js +565 -0
  107. package/dest/test/index.d.ts +5 -0
  108. package/dest/test/index.d.ts.map +1 -0
  109. package/dest/test/index.js +6 -0
  110. package/dest/test/mock_archiver.d.ts +35 -0
  111. package/dest/test/mock_archiver.d.ts.map +1 -0
  112. package/dest/test/mock_archiver.js +93 -0
  113. package/dest/test/mock_l1_to_l2_message_source.d.ts +24 -0
  114. package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -0
  115. package/dest/test/mock_l1_to_l2_message_source.js +79 -0
  116. package/dest/test/mock_l2_block_source.d.ts +139 -0
  117. package/dest/test/mock_l2_block_source.d.ts.map +1 -0
  118. package/dest/test/mock_l2_block_source.js +489 -0
  119. package/dest/test/mock_structs.d.ts +92 -0
  120. package/dest/test/mock_structs.d.ts.map +1 -0
  121. package/dest/test/mock_structs.js +188 -0
  122. package/dest/test/noop_l1_archiver.d.ts +34 -0
  123. package/dest/test/noop_l1_archiver.d.ts.map +1 -0
  124. package/dest/test/noop_l1_archiver.js +88 -0
  125. package/package.json +108 -0
  126. package/src/archiver.ts +785 -0
  127. package/src/config.ts +133 -0
  128. package/src/errors.ts +211 -0
  129. package/src/factory.ts +262 -0
  130. package/src/index.ts +29 -0
  131. package/src/interfaces.ts +9 -0
  132. package/src/l1/README.md +55 -0
  133. package/src/l1/bin/retrieve-calldata.ts +194 -0
  134. package/src/l1/calldata_retriever.ts +529 -0
  135. package/src/l1/data_retrieval.ts +498 -0
  136. package/src/l1/debug_tx.ts +98 -0
  137. package/src/l1/spire_proposer.ts +151 -0
  138. package/src/l1/trace_tx.ts +127 -0
  139. package/src/l1/types.ts +12 -0
  140. package/src/l1/validate_historical_logs.ts +140 -0
  141. package/src/l1/validate_trace.ts +228 -0
  142. package/src/modules/contract_data_source_adapter.ts +46 -0
  143. package/src/modules/data_source_base.ts +482 -0
  144. package/src/modules/data_store_updater.ts +520 -0
  145. package/src/modules/instrumentation.ts +217 -0
  146. package/src/modules/l1_synchronizer.ts +1296 -0
  147. package/src/modules/outbox_trees_resolver.ts +220 -0
  148. package/src/modules/validation.ts +186 -0
  149. package/src/store/block_store.ts +1604 -0
  150. package/src/store/contract_class_store.ts +126 -0
  151. package/src/store/contract_instance_store.ts +178 -0
  152. package/src/store/data_stores.ts +103 -0
  153. package/src/store/function_names_cache.ts +37 -0
  154. package/src/store/l2_tips_cache.ts +35 -0
  155. package/src/store/log_store.ts +380 -0
  156. package/src/store/log_store_codec.ts +143 -0
  157. package/src/store/message_store.ts +621 -0
  158. package/src/structs/data_retrieval.ts +27 -0
  159. package/src/structs/inbox_message.ts +48 -0
  160. package/src/structs/published.ts +1 -0
  161. package/src/test/fake_l1_state.ts +807 -0
  162. package/src/test/fixtures/debug_traceTransaction-multicall3.json +88 -0
  163. package/src/test/fixtures/debug_traceTransaction-multiplePropose.json +153 -0
  164. package/src/test/fixtures/debug_traceTransaction-proxied.json +122 -0
  165. package/src/test/fixtures/trace_transaction-multicall3.json +65 -0
  166. package/src/test/fixtures/trace_transaction-multiplePropose.json +319 -0
  167. package/src/test/fixtures/trace_transaction-proxied.json +128 -0
  168. package/src/test/fixtures/trace_transaction-randomRevert.json +216 -0
  169. package/src/test/index.ts +7 -0
  170. package/src/test/mock_archiver.ts +122 -0
  171. package/src/test/mock_l1_to_l2_message_source.ts +81 -0
  172. package/src/test/mock_l2_block_source.ts +620 -0
  173. package/src/test/mock_structs.ts +317 -0
  174. package/src/test/noop_l1_archiver.ts +157 -0
@@ -0,0 +1,522 @@
1
+ import { Buffer32 } from '@aztec-labs/foundation/buffer';
2
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
3
+ import { toArray } from '@aztec-labs/foundation/iterable';
4
+ import { createLogger } from '@aztec-labs/foundation/log';
5
+ import { BufferReader, bigintToUInt64BE, numToUInt32BE, serializeToBuffer } from '@aztec-labs/foundation/serialize';
6
+ import { mapRange } from '@aztec-labs/kv-store';
7
+ import { updateInboxRollingHash } from '@aztec-labs/stdlib/messaging';
8
+ import { InboxBucketBoundaryNotSyncedError, InboxBucketNotSyncedError } from '../errors.js';
9
+ import { deserializeInboxMessage, serializeInboxMessage } from '../structs/inbox_message.js';
10
+ function serializeBucketSnapshot(snapshot) {
11
+ return serializeToBuffer([
12
+ snapshot.inboxRollingHash,
13
+ bigintToUInt64BE(snapshot.totalMsgCount),
14
+ bigintToUInt64BE(snapshot.timestamp),
15
+ bigintToUInt64BE(snapshot.l1BlockNumber),
16
+ numToUInt32BE(snapshot.msgCount),
17
+ bigintToUInt64BE(snapshot.firstMessageIndex),
18
+ bigintToUInt64BE(snapshot.lastMessageIndex)
19
+ ]);
20
+ }
21
+ function deserializeBucketSnapshot(buffer) {
22
+ const reader = BufferReader.asReader(buffer);
23
+ const inboxRollingHash = reader.readObject(Fr);
24
+ const totalMsgCount = reader.readUInt64();
25
+ const timestamp = reader.readUInt64();
26
+ const l1BlockNumber = reader.readUInt64();
27
+ const msgCount = reader.readNumber();
28
+ const firstMessageIndex = reader.readUInt64();
29
+ const lastMessageIndex = reader.readUInt64();
30
+ return {
31
+ inboxRollingHash,
32
+ totalMsgCount,
33
+ timestamp,
34
+ l1BlockNumber,
35
+ msgCount,
36
+ firstMessageIndex,
37
+ lastMessageIndex
38
+ };
39
+ }
40
+ /**
41
+ * Splits an incoming batch of messages into per-bucket groups, in delivery order. Messages arrive ordered by index
42
+ * and a bucket's messages are contiguous within that order, so a group ends as soon as the bucket sequence changes.
43
+ */ function groupMessagesByBucket(messages) {
44
+ const buckets = [];
45
+ for (const message of messages){
46
+ const current = buckets.at(-1);
47
+ if (current !== undefined && current.seq === message.bucketSeq) {
48
+ current.messages.push(message);
49
+ } else {
50
+ buckets.push({
51
+ seq: message.bucketSeq,
52
+ messages: [
53
+ message
54
+ ]
55
+ });
56
+ }
57
+ }
58
+ return buckets;
59
+ }
60
+ // The genesis sentinel bucket: sequence 0 with a zero rolling hash and no messages, mirroring the
61
+ // on-chain Inbox's base case. The archiver never ingests a snapshot for it (no message is absorbed into sequence 0), so
62
+ // it is synthesized on read. Consumers use its sequence number and zero total; its deploy-time timestamp is not tracked
63
+ // here and is unused.
64
+ const GENESIS_INBOX_BUCKET = {
65
+ seq: 0n,
66
+ inboxRollingHash: Fr.ZERO,
67
+ totalMsgCount: 0n,
68
+ timestamp: 0n,
69
+ msgCount: 0,
70
+ lastMessageIndex: 0n
71
+ };
72
+ export class MessageStoreError extends Error {
73
+ inboxMessage;
74
+ constructor(message, inboxMessage){
75
+ super(message), this.inboxMessage = inboxMessage;
76
+ this.name = 'MessageStoreError';
77
+ }
78
+ }
79
+ export class MessageStore {
80
+ db;
81
+ /** Maps from message index to serialized InboxMessage */ #l1ToL2Messages;
82
+ /** Maps from hex-stringified message leaf to its index */ #l1ToL2MessageIndices;
83
+ /** Stores L1 block number and hash of the L1 synchpoint */ #lastSynchedL1Block;
84
+ /** Stores total messages stored */ #totalMessageCount;
85
+ /** Stores the L1 finalized block as of the last successful message sync. */ #messagesFinalizedL1Block;
86
+ /** Maps from Inbox bucket sequence number to its serialized snapshot. */ #inboxBuckets;
87
+ /**
88
+ * Maps from a bucket's L1 timestamp (key) to the sequence numbers of the buckets opened at that timestamp. Holds
89
+ * several sequences per timestamp when a full bucket rolls over within one L1 block, so that deleting one bucket
90
+ * leaves its rollover siblings indexed.
91
+ */ #bucketTimestampToSeq;
92
+ #log;
93
+ constructor(db){
94
+ this.db = db;
95
+ this.#log = createLogger('archiver:message_store');
96
+ this.#l1ToL2Messages = db.openMap('archiver_l1_to_l2_messages');
97
+ this.#l1ToL2MessageIndices = db.openMap('archiver_l1_to_l2_message_indices');
98
+ this.#lastSynchedL1Block = db.openSingleton('archiver_last_l1_block_id');
99
+ this.#totalMessageCount = db.openSingleton('archiver_l1_to_l2_message_count');
100
+ this.#messagesFinalizedL1Block = db.openSingleton('archiver_messages_finalized_l1_block');
101
+ this.#inboxBuckets = db.openMap('archiver_inbox_buckets');
102
+ this.#bucketTimestampToSeq = db.openMultiMap('archiver_inbox_bucket_timestamps');
103
+ }
104
+ async getTotalL1ToL2MessageCount() {
105
+ return await this.#totalMessageCount.getAsync() ?? 0n;
106
+ }
107
+ /** Gets the last L1 block synced. */ async getSynchedL1Block() {
108
+ const buffer = await this.#lastSynchedL1Block.getAsync();
109
+ if (!buffer) {
110
+ return undefined;
111
+ }
112
+ const reader = BufferReader.asReader(buffer);
113
+ return {
114
+ l1BlockNumber: reader.readUInt256(),
115
+ l1BlockHash: Buffer32.fromBuffer(reader.readBytes(Buffer32.SIZE))
116
+ };
117
+ }
118
+ /** Sets the last L1 block synced */ async setSynchedL1Block(l1Block) {
119
+ const buffer = serializeToBuffer([
120
+ l1Block.l1BlockNumber,
121
+ l1Block.l1BlockHash
122
+ ]);
123
+ await this.#lastSynchedL1Block.set(buffer);
124
+ }
125
+ /** Gets the L1 finalized block as of the last successful message sync. */ async getMessagesFinalizedL1Block() {
126
+ const buffer = await this.#messagesFinalizedL1Block.getAsync();
127
+ if (!buffer) {
128
+ return undefined;
129
+ }
130
+ const reader = BufferReader.asReader(buffer);
131
+ return {
132
+ l1BlockNumber: reader.readUInt256(),
133
+ l1BlockHash: Buffer32.fromBuffer(reader.readBytes(Buffer32.SIZE))
134
+ };
135
+ }
136
+ /** Monotonically advances the persisted L1 finalized block for message sync. Never regresses. */ async maybeAdvanceFinalizedL1Block(l1Block) {
137
+ const existing = await this.getMessagesFinalizedL1Block();
138
+ if (existing && l1Block.l1BlockNumber <= existing.l1BlockNumber) {
139
+ return;
140
+ }
141
+ const buffer = serializeToBuffer([
142
+ l1Block.l1BlockNumber,
143
+ l1Block.l1BlockHash
144
+ ]);
145
+ await this.#messagesFinalizedL1Block.set(buffer);
146
+ }
147
+ /**
148
+ * Appends L1 to L2 messages to the store, one whole Inbox bucket at a time.
149
+ *
150
+ * A bucket is opened and closed within a single L1 block, and callers retrieve Inbox logs in whole-L1-block ranges,
151
+ * so every message of a bucket reaches this method in the same call — including the rollover buckets a full block
152
+ * spills into. The bucket snapshots are derived from that: the batch is split per bucket sequence and each bucket
153
+ * gets a single snapshot built from its complete message set. Delivering only part of a bucket already held in the
154
+ * store is rejected, since the snapshot would then undercount the bucket. Delivering a stored bucket again from its
155
+ * first message is allowed: an L1 reorg can replace a bucket's tail, and the re-sync that follows replays the whole
156
+ * L1 block it lives in.
157
+ *
158
+ * Requires messages to be ordered by index and to continue the stored chain. Throws a `MessageStoreError` if
159
+ * messages arrive out of order, if the rolling hash chain breaks, or if a bucket arrives incomplete.
160
+ */ addL1ToL2MessageBuckets(messages) {
161
+ if (messages.length === 0) {
162
+ return Promise.resolve();
163
+ }
164
+ return this.db.transactionAsync(async ()=>{
165
+ let lastMessage = await this.getLastMessage();
166
+ let messageCount = 0;
167
+ const incomingBuckets = groupMessagesByBucket(messages);
168
+ await this.assertIncomingBucketsAreComplete(incomingBuckets);
169
+ for (const message of messages){
170
+ // Check messages are inserted in increasing order, but allow reinserting messages.
171
+ if (lastMessage && message.index <= lastMessage.index) {
172
+ const existing = await this.#l1ToL2Messages.getAsync(this.indexToKey(message.index));
173
+ if (existing && deserializeInboxMessage(existing).inboxRollingHash.equals(message.inboxRollingHash)) {
174
+ // We reinsert instead of skipping in case the message was re-orged and got added in a different L1 block.
175
+ this.#log.trace(`Reinserting message with index ${message.index} in the store`);
176
+ await this.#l1ToL2Messages.set(this.indexToKey(message.index), serializeInboxMessage(message));
177
+ continue;
178
+ }
179
+ throw new MessageStoreError(`Cannot insert L1 to L2 message with index ${message.index} before last message with index ${lastMessage.index}`, message);
180
+ }
181
+ // Check the compact-indexed messages arrive contiguously: the global insertion index of
182
+ // each message is exactly one past the previous one.
183
+ const expectedIndex = lastMessage === undefined ? 0n : lastMessage.index + 1n;
184
+ if (message.index !== expectedIndex) {
185
+ throw new MessageStoreError(`Invalid index ${message.index} for incoming L1 to L2 message ${message.leaf.toString()} ` + `(expected ${expectedIndex})`, message);
186
+ }
187
+ // Check the consensus rolling-hash chain is valid: each message's rolling hash must
188
+ // continue the chain from the previously inserted message.
189
+ const previousInboxRollingHash = lastMessage?.inboxRollingHash ?? Fr.ZERO;
190
+ const expectedInboxRollingHash = updateInboxRollingHash(previousInboxRollingHash, message.leaf);
191
+ if (!expectedInboxRollingHash.equals(message.inboxRollingHash)) {
192
+ throw new MessageStoreError(`Invalid inbox rolling hash for incoming L1 to L2 message ${message.leaf.toString()} ` + `with index ${message.index} ` + `(expected ${expectedInboxRollingHash.toString()} from previous hash ${previousInboxRollingHash.toString()} ` + `but got ${message.inboxRollingHash.toString()})`, message);
193
+ }
194
+ // Perform the insertions.
195
+ await this.#l1ToL2Messages.set(this.indexToKey(message.index), serializeInboxMessage(message));
196
+ await this.#l1ToL2MessageIndices.set(this.leafToIndexKey(message.leaf), message.index);
197
+ messageCount++;
198
+ this.#log.trace(`Inserted L1 to L2 message ${message.leaf} with index ${message.index} into the store`);
199
+ lastMessage = message;
200
+ }
201
+ await this.writeIncomingBucketSnapshots(incomingBuckets);
202
+ // Update total message count with the number of inserted messages.
203
+ await this.increaseTotalMessageCount(messageCount);
204
+ });
205
+ }
206
+ /**
207
+ * Rejects a batch that delivers an Inbox bucket the store already holds without replaying it from its first message,
208
+ * or that opens a bucket older than the newest one stored. Either would produce a snapshot that disagrees with the
209
+ * messages it covers, since each snapshot is derived from the batch's messages for that bucket alone.
210
+ */ async assertIncomingBucketsAreComplete(incomingBuckets) {
211
+ const newestStoredSeq = await this.getNewestBucketSeq();
212
+ let previousSeq;
213
+ for (const bucket of incomingBuckets){
214
+ if (previousSeq !== undefined && bucket.seq <= previousSeq) {
215
+ throw new MessageStoreError(`Inbox bucket ${bucket.seq} arrives after bucket ${previousSeq} in the same batch`, bucket.messages[0]);
216
+ }
217
+ previousSeq = bucket.seq;
218
+ const stored = await this.getBucketSnapshotBySeq(bucket.seq);
219
+ if (stored === undefined) {
220
+ if (newestStoredSeq !== undefined && bucket.seq <= newestStoredSeq) {
221
+ throw new MessageStoreError(`Cannot open Inbox bucket ${bucket.seq} after bucket ${newestStoredSeq} has been stored`, bucket.messages[0]);
222
+ }
223
+ } else if (stored.firstMessageIndex !== bucket.messages[0].index) {
224
+ throw new MessageStoreError(`Incomplete Inbox bucket ${bucket.seq}: stored messages start at index ${stored.firstMessageIndex} ` + `but the batch starts at index ${bucket.messages[0].index}`, bucket.messages[0]);
225
+ }
226
+ }
227
+ }
228
+ /**
229
+ * Writes one snapshot per bucket in the batch, each derived from the bucket's complete message set. Cumulative
230
+ * totals thread forward from the bucket preceding the batch, so a bucket re-delivered with extra messages shifts
231
+ * the totals of the buckets after it within the same batch.
232
+ */ async writeIncomingBucketSnapshots(incomingBuckets) {
233
+ let cumulativeTotal = await this.getTotalMsgCountBeforeBucket(incomingBuckets[0].seq);
234
+ for (const { seq, messages } of incomingBuckets){
235
+ const lastInBucket = messages.at(-1);
236
+ cumulativeTotal += BigInt(messages.length);
237
+ await this.writeBucketSnapshot(seq, {
238
+ inboxRollingHash: lastInBucket.inboxRollingHash,
239
+ totalMsgCount: cumulativeTotal,
240
+ timestamp: lastInBucket.bucketTimestamp,
241
+ l1BlockNumber: lastInBucket.l1BlockNumber,
242
+ msgCount: messages.length,
243
+ firstMessageIndex: messages[0].index,
244
+ lastMessageIndex: lastInBucket.index
245
+ });
246
+ }
247
+ }
248
+ /**
249
+ * Gets the L1 to L2 message index in the L1 to L2 message tree.
250
+ * @param l1ToL2Message - The L1 to L2 message.
251
+ * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found).
252
+ */ getL1ToL2MessageIndex(l1ToL2Message) {
253
+ return this.#l1ToL2MessageIndices.getAsync(this.leafToIndexKey(l1ToL2Message));
254
+ }
255
+ async getLastMessage() {
256
+ const [msg] = await toArray(this.#l1ToL2Messages.valuesAsync({
257
+ reverse: true,
258
+ limit: 1
259
+ }));
260
+ return msg ? deserializeInboxMessage(msg) : undefined;
261
+ }
262
+ /**
263
+ * Atomically updates the message sync state: the L1 sync point and (optionally) the L1 finalized block as of this
264
+ * sync. The finalized block is advanced monotonically.
265
+ */ setMessageSyncState(l1Block, finalizedL1Block) {
266
+ return this.db.transactionAsync(async ()=>{
267
+ await this.setSynchedL1Block(l1Block);
268
+ if (finalizedL1Block !== undefined) {
269
+ await this.maybeAdvanceFinalizedL1Block(finalizedL1Block);
270
+ }
271
+ });
272
+ }
273
+ async *iterateL1ToL2Messages(range = {}) {
274
+ const entriesRange = mapRange(range, this.indexToKey);
275
+ for await (const msgBuffer of this.#l1ToL2Messages.valuesAsync(entriesRange)){
276
+ yield deserializeInboxMessage(msgBuffer);
277
+ }
278
+ }
279
+ removeL1ToL2Messages(startIndex) {
280
+ this.#log.debug(`Deleting L1 to L2 messages from index ${startIndex}`);
281
+ let deleteCount = 0;
282
+ return this.db.transactionAsync(async ()=>{
283
+ for await (const [key, msgBuffer] of this.#l1ToL2Messages.entriesAsync({
284
+ start: this.indexToKey(startIndex)
285
+ })){
286
+ this.#log.trace(`Deleting L1 to L2 message with index ${key - 1} from the store`);
287
+ await this.#l1ToL2Messages.delete(key);
288
+ await this.#l1ToL2MessageIndices.delete(this.leafToIndexKey(deserializeInboxMessage(msgBuffer).leaf));
289
+ deleteCount++;
290
+ }
291
+ await this.increaseTotalMessageCount(-deleteCount);
292
+ await this.rewindBucketsAfterRemoval();
293
+ this.#log.warn(`Deleted ${deleteCount} L1 to L2 messages from index ${startIndex} from the store`);
294
+ });
295
+ }
296
+ /**
297
+ * Rewinds the Inbox bucket snapshots to match the messages left after a removal. Each bucket past the surviving tip
298
+ * is deleted together with its own timestamp index entry, leaving the entries of the rollover siblings it shares a
299
+ * timestamp with in place.
300
+ *
301
+ * The bucket holding the last surviving message is rewritten from the messages it has left, because a removal can
302
+ * cut inside a bucket: the synchronizer rolls back to the last message it still shares with L1 after a reorg, and
303
+ * that message need not be the last of its bucket. Must run inside the removal transaction, after the total message
304
+ * count has been updated.
305
+ */ async rewindBucketsAfterRemoval() {
306
+ const lastRemaining = await this.getLastMessage();
307
+ const boundarySeq = lastRemaining?.bucketSeq;
308
+ const deleteFromKey = boundarySeq === undefined ? 0 : this.bucketSeqToKey(boundarySeq) + 1;
309
+ for await (const [seqKey, snapBuffer] of this.#inboxBuckets.entriesAsync({
310
+ start: deleteFromKey
311
+ })){
312
+ const snapshot = deserializeBucketSnapshot(snapBuffer);
313
+ await this.#bucketTimestampToSeq.deleteValue(this.timestampToKey(snapshot.timestamp), seqKey);
314
+ await this.#inboxBuckets.delete(seqKey);
315
+ }
316
+ if (lastRemaining === undefined || boundarySeq === undefined) {
317
+ return;
318
+ }
319
+ let msgCount = 0;
320
+ for await (const msg of this.iterateL1ToL2Messages({
321
+ reverse: true
322
+ })){
323
+ if (msg.bucketSeq !== boundarySeq) {
324
+ break;
325
+ }
326
+ msgCount += 1;
327
+ }
328
+ const stored = await this.getSyncedBucketSnapshot(boundarySeq);
329
+ await this.writeBucketSnapshot(boundarySeq, {
330
+ ...stored,
331
+ inboxRollingHash: lastRemaining.inboxRollingHash,
332
+ totalMsgCount: await this.getTotalL1ToL2MessageCount(),
333
+ msgCount,
334
+ lastMessageIndex: lastRemaining.index
335
+ });
336
+ }
337
+ /**
338
+ * Returns the Inbox bucket with the given sequence number, or undefined if it has not been synced. Sequence 0 is
339
+ * the genesis sentinel: the on-chain Inbox reserves it as the "consumed nothing" base case
340
+ * and never absorbs a message into it, so the archiver ingests no snapshot for it; it is synthesized here (rolling
341
+ * hash 0, total 0) so streaming consumers can resolve a genesis parent or an empty checkpoint's last-consumed bucket.
342
+ */ async getInboxBucket(seq) {
343
+ const snapshot = await this.getBucketSnapshotBySeq(seq);
344
+ if (snapshot !== undefined) {
345
+ return this.toInboxBucket(seq, snapshot);
346
+ }
347
+ return seq === 0n ? GENESIS_INBOX_BUCKET : undefined;
348
+ }
349
+ /**
350
+ * Returns the Inbox bucket whose cumulative message total equals `totalMsgCount`, or undefined if no synced bucket
351
+ * sits on that boundary. Sequence 0 (total 0) is the genesis sentinel base case; otherwise the
352
+ * message at global index `totalMsgCount - 1` is the last message of the bucket with that cumulative total, so its
353
+ * `bucketSeq` resolves the bucket. A total that does not land on a bucket boundary returns undefined.
354
+ */ async getInboxBucketByTotalMsgCount(totalMsgCount) {
355
+ if (totalMsgCount === 0n) {
356
+ return this.getInboxBucket(0n);
357
+ }
358
+ const buffer = await this.#l1ToL2Messages.getAsync(this.indexToKey(totalMsgCount - 1n));
359
+ if (buffer === undefined) {
360
+ return undefined;
361
+ }
362
+ const bucket = await this.getInboxBucket(deserializeInboxMessage(buffer).bucketSeq);
363
+ return bucket !== undefined && bucket.totalMsgCount === totalMsgCount ? bucket : undefined;
364
+ }
365
+ /**
366
+ * Returns the message leaves in the cumulative Inbox message-count range `[startLeafCount, endLeafCount)`, in
367
+ * insertion order. The bounds are compact L1-to-L2 tree leaf counts, which every block header
368
+ * carries, so consumers can ask for the messages a block or checkpoint consumed without resolving buckets
369
+ * themselves. Both bounds must land on a bucket boundary this archiver has synced; it throws otherwise, since a
370
+ * caller asking for a range always expects the messages in it.
371
+ */ async getL1ToL2MessagesBetweenLeafCounts(startLeafCount, endLeafCount) {
372
+ if (startLeafCount > endLeafCount) {
373
+ throw new Error(`Invalid Inbox leaf count range [${startLeafCount}, ${endLeafCount})`);
374
+ }
375
+ const startBucket = await this.getBucketAtBoundary(startLeafCount);
376
+ const endBucket = await this.getBucketAtBoundary(endLeafCount);
377
+ return this.getL1ToL2MessagesBetweenBuckets(startBucket.seq, endBucket.seq);
378
+ }
379
+ /** Resolves the bucket ending at the given cumulative message count, failing loudly if there is none. */ async getBucketAtBoundary(totalMsgCount) {
380
+ const bucket = await this.getInboxBucketByTotalMsgCount(totalMsgCount);
381
+ if (bucket === undefined) {
382
+ throw new InboxBucketBoundaryNotSyncedError(totalMsgCount);
383
+ }
384
+ return bucket;
385
+ }
386
+ /**
387
+ * Returns the latest Inbox bucket opened at or before the given L1 timestamp, or undefined if every synced bucket
388
+ * was opened strictly after it.
389
+ */ async getLatestInboxBucketAtOrBefore(timestamp) {
390
+ // Bucket timestamps are non-decreasing in sequence number, so the bucket we want is the highest sequence indexed
391
+ // at the largest timestamp at-or-before the requested one. A reverse scan bounded above (inclusively) by that
392
+ // timestamp visits it first; rollover buckets share a timestamp, so keep the highest of its sequences.
393
+ let latestTimestampKey;
394
+ let latestSeqKey;
395
+ for await (const [timestampKey, seqKey] of this.#bucketTimestampToSeq.entriesAsync({
396
+ end: this.timestampToKey(timestamp),
397
+ reverse: true
398
+ })){
399
+ if (latestTimestampKey !== undefined && timestampKey !== latestTimestampKey) {
400
+ break;
401
+ }
402
+ latestTimestampKey = timestampKey;
403
+ latestSeqKey = latestSeqKey === undefined ? seqKey : Math.max(latestSeqKey, seqKey);
404
+ }
405
+ return latestSeqKey === undefined ? undefined : this.getInboxBucket(BigInt(latestSeqKey));
406
+ }
407
+ /**
408
+ * Returns the message leaves absorbed into buckets in the range `(fromExclusive, toInclusive]`, in insertion order.
409
+ * Both bounds must name buckets this archiver has synced, so that an empty result means the
410
+ * range holds no messages rather than hiding an unsynced bound; callers route the
411
+ * `InboxBucketNotSyncedError` to their own catch-up handling. Sequence 0 is the genesis base case and always
412
+ * resolves: the range then starts at the first message of the Inbox.
413
+ */ async getL1ToL2MessagesBetweenBuckets(fromExclusive, toInclusive) {
414
+ if (fromExclusive > toInclusive) {
415
+ throw new Error(`Invalid Inbox bucket range (${fromExclusive}, ${toInclusive}]`);
416
+ }
417
+ if (toInclusive === 0n) {
418
+ return [];
419
+ }
420
+ const endIndexExclusive = (await this.getSyncedBucketSnapshot(toInclusive)).lastMessageIndex + 1n;
421
+ const startIndex = fromExclusive === 0n ? 0n : (await this.getSyncedBucketSnapshot(fromExclusive)).lastMessageIndex + 1n;
422
+ return this.getMessageLeavesInIndexRange(startIndex, endIndexExclusive);
423
+ }
424
+ /** Collects the message leaves in the global index range `[startIndex, endIndexExclusive)`, in insertion order. */ async getMessageLeavesInIndexRange(startIndex, endIndexExclusive) {
425
+ const leaves = [];
426
+ for await (const msgBuffer of this.#l1ToL2Messages.valuesAsync({
427
+ start: this.indexToKey(startIndex),
428
+ end: this.indexToKey(endIndexExclusive)
429
+ })){
430
+ leaves.push(deserializeInboxMessage(msgBuffer).leaf);
431
+ }
432
+ return leaves;
433
+ }
434
+ async getBucketSnapshotBySeq(seq) {
435
+ const buffer = await this.#inboxBuckets.getAsync(this.bucketSeqToKey(seq));
436
+ return buffer && deserializeBucketSnapshot(buffer);
437
+ }
438
+ /** Reads a bucket snapshot, failing loudly if the archiver has not synced that bucket. */ async getSyncedBucketSnapshot(seq) {
439
+ const snapshot = await this.getBucketSnapshotBySeq(seq);
440
+ if (snapshot === undefined) {
441
+ throw new InboxBucketNotSyncedError(seq);
442
+ }
443
+ return snapshot;
444
+ }
445
+ async writeBucketSnapshot(seq, snapshot) {
446
+ // A reorg can re-deliver a bucket from an L1 block mined at a different timestamp, so drop the stale index entry.
447
+ const stored = await this.getBucketSnapshotBySeq(seq);
448
+ if (stored !== undefined && stored.timestamp !== snapshot.timestamp) {
449
+ await this.#bucketTimestampToSeq.deleteValue(this.timestampToKey(stored.timestamp), this.bucketSeqToKey(seq));
450
+ }
451
+ await this.#inboxBuckets.set(this.bucketSeqToKey(seq), serializeBucketSnapshot(snapshot));
452
+ await this.#bucketTimestampToSeq.set(this.timestampToKey(snapshot.timestamp), this.bucketSeqToKey(seq));
453
+ }
454
+ /** Returns the sequence number of the newest stored bucket, or undefined if none has been stored yet. */ async getNewestBucketSeq() {
455
+ const [seqKey] = await toArray(this.#inboxBuckets.keysAsync({
456
+ reverse: true,
457
+ limit: 1
458
+ }));
459
+ return seqKey === undefined ? undefined : BigInt(seqKey);
460
+ }
461
+ /** Returns the cumulative Inbox message count through the newest stored bucket before the given sequence number. */ async getTotalMsgCountBeforeBucket(seq) {
462
+ const [snapBuffer] = await toArray(this.#inboxBuckets.valuesAsync({
463
+ end: this.bucketSeqToKey(seq) - 1,
464
+ reverse: true,
465
+ limit: 1
466
+ }));
467
+ return snapBuffer === undefined ? 0n : deserializeBucketSnapshot(snapBuffer).totalMsgCount;
468
+ }
469
+ toInboxBucket(seq, snapshot) {
470
+ return {
471
+ seq,
472
+ inboxRollingHash: snapshot.inboxRollingHash,
473
+ totalMsgCount: snapshot.totalMsgCount,
474
+ timestamp: snapshot.timestamp,
475
+ msgCount: snapshot.msgCount,
476
+ lastMessageIndex: snapshot.lastMessageIndex
477
+ };
478
+ }
479
+ bucketSeqToKey(seq) {
480
+ return Number(seq);
481
+ }
482
+ timestampToKey(timestamp) {
483
+ return Number(timestamp);
484
+ }
485
+ /**
486
+ * Removes every L1 to L2 message inserted after the given L1 block, so the message store matches the L1 Inbox state
487
+ * as of that block. Used when rolling the archiver back to an earlier checkpoint, whose L1 block is passed here.
488
+ *
489
+ * A bucket lives entirely within one L1 block, so the cut always falls on a bucket boundary and can be found from
490
+ * the bucket snapshots alone, without reading the messages being removed.
491
+ */ async rollbackL1ToL2MessagesAfterL1Block(l1BlockNumber) {
492
+ this.#log.debug(`Deleting L1 to L2 messages inserted after L1 block ${l1BlockNumber}`);
493
+ let removeFromIndex;
494
+ for await (const snapBuffer of this.#inboxBuckets.valuesAsync({
495
+ reverse: true
496
+ })){
497
+ const snapshot = deserializeBucketSnapshot(snapBuffer);
498
+ if (snapshot.l1BlockNumber <= l1BlockNumber) {
499
+ break;
500
+ }
501
+ removeFromIndex = snapshot.firstMessageIndex;
502
+ }
503
+ if (removeFromIndex !== undefined) {
504
+ await this.removeL1ToL2Messages(removeFromIndex);
505
+ }
506
+ }
507
+ indexToKey(index) {
508
+ return Number(index);
509
+ }
510
+ leafToIndexKey(leaf) {
511
+ return leaf.toString();
512
+ }
513
+ async increaseTotalMessageCount(count) {
514
+ if (count === 0) {
515
+ return;
516
+ }
517
+ return await this.db.transactionAsync(async ()=>{
518
+ const lastTotalMessageCount = await this.getTotalL1ToL2MessageCount();
519
+ await this.#totalMessageCount.set(lastTotalMessageCount + BigInt(count));
520
+ });
521
+ }
522
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Data retrieved from logs
3
+ */
4
+ export type DataRetrieval<T> = {
5
+ /**
6
+ * Blocknumber of the last L1 block from which we obtained data.
7
+ */
8
+ lastProcessedL1BlockNumber: bigint;
9
+ /**
10
+ * The data returned.
11
+ */
12
+ retrievedData: T[];
13
+ };
14
+ /**
15
+ * Data retrieved from logs
16
+ */
17
+ export type SingletonDataRetrieval<T> = {
18
+ /**
19
+ * Blocknumber of the last L1 block from which we obtained data.
20
+ */
21
+ lastProcessedL1BlockNumber: bigint;
22
+ /**
23
+ * The data returned.
24
+ */
25
+ retrievedData: T;
26
+ };
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YV9yZXRyaWV2YWwuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdHJ1Y3RzL2RhdGFfcmV0cmlldmFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxNQUFNLGFBQWEsQ0FBQyxDQUFDLElBQUk7SUFDN0I7O09BRUc7SUFDSCwwQkFBMEIsRUFBRSxNQUFNLENBQUM7SUFDbkM7O09BRUc7SUFDSCxhQUFhLEVBQUUsQ0FBQyxFQUFFLENBQUM7Q0FDcEIsQ0FBQztBQUVGOztHQUVHO0FBQ0gsTUFBTSxNQUFNLHNCQUFzQixDQUFDLENBQUMsSUFBSTtJQUN0Qzs7T0FFRztJQUNILDBCQUEwQixFQUFFLE1BQU0sQ0FBQztJQUNuQzs7T0FFRztJQUNILGFBQWEsRUFBRSxDQUFDLENBQUM7Q0FDbEIsQ0FBQyJ9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data_retrieval.d.ts","sourceRoot":"","sources":["../../src/structs/data_retrieval.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B;;OAEG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC;;OAEG;IACH,aAAa,EAAE,CAAC,EAAE,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,IAAI;IACtC;;OAEG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC;;OAEG;IACH,aAAa,EAAE,CAAC,CAAC;CAClB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Data retrieved from logs
3
+ */ /**
4
+ * Data retrieved from logs
5
+ */ export { };
@@ -0,0 +1,17 @@
1
+ import { Buffer32 } from '@aztec-labs/foundation/buffer';
2
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
3
+ export type InboxMessage = {
4
+ index: bigint;
5
+ leaf: Fr;
6
+ l1BlockNumber: bigint;
7
+ l1BlockHash: Buffer32;
8
+ /** Consensus rolling hash (truncated sha256 chain) of all messages up to and including this one. */
9
+ inboxRollingHash: Fr;
10
+ /** Sequence number of the Inbox bucket this message was absorbed into. */
11
+ bucketSeq: bigint;
12
+ /** L1 block timestamp at which this message's bucket was opened; the bucket's recency key, in seconds. */
13
+ bucketTimestamp: bigint;
14
+ };
15
+ export declare function serializeInboxMessage(message: InboxMessage): Buffer;
16
+ export declare function deserializeInboxMessage(buffer: Buffer): InboxMessage;
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5ib3hfbWVzc2FnZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0cnVjdHMvaW5ib3hfbWVzc2FnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDekQsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBR3pELE1BQU0sTUFBTSxZQUFZLEdBQUc7SUFDekIsS0FBSyxFQUFFLE1BQU0sQ0FBQztJQUNkLElBQUksRUFBRSxFQUFFLENBQUM7SUFDVCxhQUFhLEVBQUUsTUFBTSxDQUFDO0lBQ3RCLFdBQVcsRUFBRSxRQUFRLENBQUM7SUFDdEIsb0dBQW9HO0lBQ3BHLGdCQUFnQixFQUFFLEVBQUUsQ0FBQztJQUNyQiwwRUFBMEU7SUFDMUUsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQiwwR0FBMEc7SUFDMUcsZUFBZSxFQUFFLE1BQU0sQ0FBQztDQUN6QixDQUFDO0FBRUYsd0JBQWdCLHFCQUFxQixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsTUFBTSxDQVVuRTtBQUVELHdCQUFnQix1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLFlBQVksQ0FrQnBFIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox_message.d.ts","sourceRoot":"","sources":["../../src/structs/inbox_message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,qCAAqC,CAAC;AAGzD,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,EAAE,CAAC;IACT,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,QAAQ,CAAC;IACtB,oGAAoG;IACpG,gBAAgB,EAAE,EAAE,CAAC;IACrB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,0GAA0G;IAC1G,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAUnE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAkBpE"}
@@ -0,0 +1,33 @@
1
+ import { Buffer32 } from '@aztec-labs/foundation/buffer';
2
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
3
+ import { BufferReader, bigintToUInt64BE, serializeToBuffer } from '@aztec-labs/foundation/serialize';
4
+ export function serializeInboxMessage(message) {
5
+ return serializeToBuffer([
6
+ bigintToUInt64BE(message.index),
7
+ message.leaf,
8
+ message.l1BlockHash,
9
+ bigintToUInt64BE(message.l1BlockNumber),
10
+ message.inboxRollingHash,
11
+ bigintToUInt64BE(message.bucketSeq),
12
+ bigintToUInt64BE(message.bucketTimestamp)
13
+ ]);
14
+ }
15
+ export function deserializeInboxMessage(buffer) {
16
+ const reader = BufferReader.asReader(buffer);
17
+ const index = reader.readUInt64();
18
+ const leaf = reader.readObject(Fr);
19
+ const l1BlockHash = reader.readObject(Buffer32);
20
+ const l1BlockNumber = reader.readUInt64();
21
+ const inboxRollingHash = reader.readObject(Fr);
22
+ const bucketSeq = reader.readUInt64();
23
+ const bucketTimestamp = reader.readUInt64();
24
+ return {
25
+ index,
26
+ leaf,
27
+ l1BlockHash,
28
+ l1BlockNumber,
29
+ inboxRollingHash,
30
+ bucketSeq,
31
+ bucketTimestamp
32
+ };
33
+ }
@@ -0,0 +1,2 @@
1
+ export type { L1PublishedData, PublishedCheckpoint } from '@aztec-labs/stdlib/checkpoint';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaGVkLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RydWN0cy9wdWJsaXNoZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWSxFQUFFLGVBQWUsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLCtCQUErQixDQUFDIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"published.d.ts","sourceRoot":"","sources":["../../src/structs/published.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1 @@
1
+ export { };