@aztec/validator-client 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 (69) hide show
  1. package/README.md +94 -24
  2. package/dest/block_proposal_handler.d.ts +12 -11
  3. package/dest/block_proposal_handler.d.ts.map +1 -1
  4. package/dest/block_proposal_handler.js +140 -77
  5. package/dest/checkpoint_builder.d.ts +35 -26
  6. package/dest/checkpoint_builder.d.ts.map +1 -1
  7. package/dest/checkpoint_builder.js +144 -48
  8. package/dest/config.d.ts +1 -1
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +33 -14
  11. package/dest/duties/validation_service.d.ts +20 -7
  12. package/dest/duties/validation_service.d.ts.map +1 -1
  13. package/dest/duties/validation_service.js +69 -22
  14. package/dest/factory.d.ts +4 -2
  15. package/dest/factory.d.ts.map +1 -1
  16. package/dest/factory.js +4 -3
  17. package/dest/index.d.ts +1 -2
  18. package/dest/index.d.ts.map +1 -1
  19. package/dest/index.js +0 -1
  20. package/dest/key_store/ha_key_store.d.ts +99 -0
  21. package/dest/key_store/ha_key_store.d.ts.map +1 -0
  22. package/dest/key_store/ha_key_store.js +208 -0
  23. package/dest/key_store/index.d.ts +2 -1
  24. package/dest/key_store/index.d.ts.map +1 -1
  25. package/dest/key_store/index.js +1 -0
  26. package/dest/key_store/interface.d.ts +36 -6
  27. package/dest/key_store/interface.d.ts.map +1 -1
  28. package/dest/key_store/local_key_store.d.ts +10 -5
  29. package/dest/key_store/local_key_store.d.ts.map +1 -1
  30. package/dest/key_store/local_key_store.js +8 -4
  31. package/dest/key_store/node_keystore_adapter.d.ts +18 -5
  32. package/dest/key_store/node_keystore_adapter.d.ts.map +1 -1
  33. package/dest/key_store/node_keystore_adapter.js +18 -4
  34. package/dest/key_store/web3signer_key_store.d.ts +10 -5
  35. package/dest/key_store/web3signer_key_store.d.ts.map +1 -1
  36. package/dest/key_store/web3signer_key_store.js +8 -4
  37. package/dest/metrics.d.ts +12 -3
  38. package/dest/metrics.d.ts.map +1 -1
  39. package/dest/metrics.js +46 -5
  40. package/dest/validator.d.ts +45 -18
  41. package/dest/validator.d.ts.map +1 -1
  42. package/dest/validator.js +276 -107
  43. package/package.json +21 -17
  44. package/src/block_proposal_handler.ts +171 -95
  45. package/src/checkpoint_builder.ts +211 -61
  46. package/src/config.ts +32 -13
  47. package/src/duties/validation_service.ts +94 -25
  48. package/src/factory.ts +5 -0
  49. package/src/index.ts +0 -1
  50. package/src/key_store/ha_key_store.ts +269 -0
  51. package/src/key_store/index.ts +1 -0
  52. package/src/key_store/interface.ts +44 -5
  53. package/src/key_store/local_key_store.ts +13 -4
  54. package/src/key_store/node_keystore_adapter.ts +27 -4
  55. package/src/key_store/web3signer_key_store.ts +17 -4
  56. package/src/metrics.ts +63 -6
  57. package/src/validator.ts +354 -130
  58. package/dest/tx_validator/index.d.ts +0 -3
  59. package/dest/tx_validator/index.d.ts.map +0 -1
  60. package/dest/tx_validator/index.js +0 -2
  61. package/dest/tx_validator/nullifier_cache.d.ts +0 -14
  62. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  63. package/dest/tx_validator/nullifier_cache.js +0 -24
  64. package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
  65. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  66. package/dest/tx_validator/tx_validator_factory.js +0 -53
  67. package/src/tx_validator/index.ts +0 -2
  68. package/src/tx_validator/nullifier_cache.ts +0 -30
  69. package/src/tx_validator/tx_validator_factory.ts +0 -133
@@ -65,14 +65,17 @@ function _ts_dispose_resources(env) {
65
65
  }
66
66
  import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
67
67
  import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
68
+ import { pick } from '@aztec/foundation/collection';
68
69
  import { Fr } from '@aztec/foundation/curves/bn254';
69
70
  import { TimeoutError } from '@aztec/foundation/error';
70
71
  import { createLogger } from '@aztec/foundation/log';
71
72
  import { retryUntil } from '@aztec/foundation/retry';
72
73
  import { DateProvider, Timer } from '@aztec/foundation/timer';
73
- import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
74
+ import { getEpochAtSlot, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
75
+ import { Gas } from '@aztec/stdlib/gas';
74
76
  import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
75
- import { ReExFailedTxsError, ReExStateMismatchError, ReExTimeoutError, TransactionsNotAvailableError } from '@aztec/stdlib/validators';
77
+ import { MerkleTreeId } from '@aztec/stdlib/trees';
78
+ import { ReExFailedTxsError, ReExInitialStateMismatchError, ReExStateMismatchError, ReExTimeoutError, TransactionsNotAvailableError } from '@aztec/stdlib/validators';
76
79
  import { getTelemetryClient } from '@aztec/telemetry-client';
77
80
  export class BlockProposalHandler {
78
81
  checkpointsBuilder;
@@ -81,18 +84,20 @@ export class BlockProposalHandler {
81
84
  l1ToL2MessageSource;
82
85
  txProvider;
83
86
  blockProposalValidator;
87
+ epochCache;
84
88
  config;
85
89
  metrics;
86
90
  dateProvider;
87
91
  log;
88
92
  tracer;
89
- constructor(checkpointsBuilder, worldState, blockSource, l1ToL2MessageSource, txProvider, blockProposalValidator, config, metrics, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator:block-proposal-handler')){
93
+ constructor(checkpointsBuilder, worldState, blockSource, l1ToL2MessageSource, txProvider, blockProposalValidator, epochCache, config, metrics, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator:block-proposal-handler')){
90
94
  this.checkpointsBuilder = checkpointsBuilder;
91
95
  this.worldState = worldState;
92
96
  this.blockSource = blockSource;
93
97
  this.l1ToL2MessageSource = l1ToL2MessageSource;
94
98
  this.txProvider = txProvider;
95
99
  this.blockProposalValidator = blockProposalValidator;
100
+ this.epochCache = epochCache;
96
101
  this.config = config;
97
102
  this.metrics = metrics;
98
103
  this.dateProvider = dateProvider;
@@ -102,23 +107,27 @@ export class BlockProposalHandler {
102
107
  }
103
108
  this.tracer = telemetry.getTracer('BlockProposalHandler');
104
109
  }
105
- registerForReexecution(p2pClient) {
106
- // Non-validator handler that re-executes for monitoring but does not attest.
110
+ register(p2pClient, shouldReexecute) {
111
+ // Non-validator handler that processes or re-executes for monitoring but does not attest.
107
112
  // Returns boolean indicating whether the proposal was valid.
108
113
  const handler = async (proposal, proposalSender)=>{
109
114
  try {
110
- const result = await this.handleBlockProposal(proposal, proposalSender, true);
115
+ const { slotNumber, blockNumber } = proposal;
116
+ const result = await this.handleBlockProposal(proposal, proposalSender, shouldReexecute);
111
117
  if (result.isValid) {
112
- this.log.info(`Non-validator reexecution completed for slot ${proposal.slotNumber}`, {
118
+ this.log.info(`Non-validator block proposal ${blockNumber} at slot ${slotNumber} handled`, {
113
119
  blockNumber: result.blockNumber,
120
+ slotNumber,
114
121
  reexecutionTimeMs: result.reexecutionResult?.reexecutionTimeMs,
115
122
  totalManaUsed: result.reexecutionResult?.totalManaUsed,
116
- numTxs: result.reexecutionResult?.block?.body?.txEffects?.length ?? 0
123
+ numTxs: result.reexecutionResult?.block?.body?.txEffects?.length ?? 0,
124
+ reexecuted: shouldReexecute
117
125
  });
118
126
  return true;
119
127
  } else {
120
- this.log.warn(`Non-validator reexecution failed for slot ${proposal.slotNumber}`, {
128
+ this.log.warn(`Non-validator block proposal ${blockNumber} at slot ${slotNumber} failed processing with ${result.reason}`, {
121
129
  blockNumber: result.blockNumber,
130
+ slotNumber,
122
131
  reason: result.reason
123
132
  });
124
133
  return false;
@@ -145,7 +154,9 @@ export class BlockProposalHandler {
145
154
  }
146
155
  const proposalInfo = {
147
156
  ...proposal.toBlockInfo(),
148
- proposer: proposer.toString()
157
+ proposer: proposer.toString(),
158
+ blockNumber: undefined,
159
+ checkpointNumber: undefined
149
160
  };
150
161
  this.log.info(`Processing proposal for slot ${slotNumber}`, {
151
162
  ...proposalInfo,
@@ -153,27 +164,46 @@ export class BlockProposalHandler {
153
164
  });
154
165
  // Check that the proposal is from the current proposer, or the next proposer
155
166
  // This should have been handled by the p2p layer, but we double check here out of caution
156
- const invalidProposal = await this.blockProposalValidator.validate(proposal);
157
- if (invalidProposal) {
167
+ const validationResult = await this.blockProposalValidator.validate(proposal);
168
+ if (validationResult.result !== 'accept') {
158
169
  this.log.warn(`Proposal is not valid, skipping processing`, proposalInfo);
159
170
  return {
160
171
  isValid: false,
161
172
  reason: 'invalid_proposal'
162
173
  };
163
174
  }
164
- // Check that the parent proposal is a block we know, otherwise reexecution would fail
165
- const parentBlockHeader = await this.getParentBlock(proposal);
166
- if (parentBlockHeader === undefined) {
175
+ // Ensure the block source is synced before checking for existing blocks,
176
+ // since a pending checkpoint prune may remove blocks we'd otherwise find.
177
+ // This affects mostly the block_number_already_exists check, since a pending
178
+ // checkpoint prune could remove a block that would conflict with this proposal.
179
+ // When pipelining is enabled, the proposer builds ahead of L1 submission, so the
180
+ // block source won't have synced to the proposed slot yet. Skip the sync wait to
181
+ // avoid eating into the attestation window.
182
+ if (!this.epochCache.isProposerPipeliningEnabled()) {
183
+ const blockSourceSync = await this.waitForBlockSourceSync(slotNumber);
184
+ if (!blockSourceSync) {
185
+ this.log.warn(`Block source is not synced, skipping processing`, proposalInfo);
186
+ return {
187
+ isValid: false,
188
+ reason: 'block_source_not_synced'
189
+ };
190
+ }
191
+ }
192
+ // Check that the parent proposal is a block we know, otherwise reexecution would fail.
193
+ // If we don't find it immediately, we keep retrying for a while; it may be we still
194
+ // need to process other block proposals to get to it.
195
+ const parentBlock = await this.getParentBlock(proposal);
196
+ if (parentBlock === undefined) {
167
197
  this.log.warn(`Parent block for proposal not found, skipping processing`, proposalInfo);
168
198
  return {
169
199
  isValid: false,
170
200
  reason: 'parent_block_not_found'
171
201
  };
172
202
  }
173
- // Check that the parent block's slot is less than the proposal's slot (should not happen, but we check anyway)
174
- if (parentBlockHeader !== 'genesis' && parentBlockHeader.getSlot() >= slotNumber) {
175
- this.log.warn(`Parent block slot is greater than or equal to proposal slot, skipping processing`, {
176
- parentBlockSlot: parentBlockHeader.getSlot().toString(),
203
+ // Check that the parent block's slot is not greater than the proposal's slot.
204
+ if (parentBlock !== 'genesis' && parentBlock.header.getSlot() > slotNumber) {
205
+ this.log.warn(`Parent block slot is greater than proposal slot, skipping processing`, {
206
+ parentBlockSlot: parentBlock.header.getSlot().toString(),
177
207
  proposalSlot: slotNumber.toString(),
178
208
  ...proposalInfo
179
209
  });
@@ -183,7 +213,8 @@ export class BlockProposalHandler {
183
213
  };
184
214
  }
185
215
  // Compute the block number based on the parent block
186
- const blockNumber = parentBlockHeader === 'genesis' ? BlockNumber(INITIAL_L2_BLOCK_NUM) : BlockNumber(parentBlockHeader.getBlockNumber() + 1);
216
+ const blockNumber = parentBlock === 'genesis' ? BlockNumber(INITIAL_L2_BLOCK_NUM) : BlockNumber(parentBlock.header.getBlockNumber() + 1);
217
+ proposalInfo.blockNumber = blockNumber;
187
218
  // Check that this block number does not exist already
188
219
  const existingBlock = await this.blockSource.getBlockHeader(blockNumber);
189
220
  if (existingBlock) {
@@ -200,8 +231,16 @@ export class BlockProposalHandler {
200
231
  pinnedPeer: proposalSender,
201
232
  deadline: this.getReexecutionDeadline(slotNumber, config)
202
233
  });
234
+ // If reexecution is disabled, bail. We were just interested in triggering tx collection.
235
+ if (!shouldReexecute) {
236
+ this.log.info(`Received valid block ${blockNumber} proposal at index ${proposal.indexWithinCheckpoint} on slot ${slotNumber}`, proposalInfo);
237
+ return {
238
+ isValid: true,
239
+ blockNumber
240
+ };
241
+ }
203
242
  // Compute the checkpoint number for this block and validate checkpoint consistency
204
- const checkpointResult = await this.computeCheckpointNumber(proposal, parentBlockHeader, proposalInfo);
243
+ const checkpointResult = this.computeCheckpointNumber(proposal, parentBlock, proposalInfo);
205
244
  if (checkpointResult.reason) {
206
245
  return {
207
246
  isValid: false,
@@ -210,6 +249,7 @@ export class BlockProposalHandler {
210
249
  };
211
250
  }
212
251
  const checkpointNumber = checkpointResult.checkpointNumber;
252
+ proposalInfo.checkpointNumber = checkpointNumber;
213
253
  // Check that I have the same set of l1ToL2Messages as the proposal
214
254
  const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(checkpointNumber);
215
255
  const computedInHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
@@ -238,29 +278,32 @@ export class BlockProposalHandler {
238
278
  reason: 'txs_not_available'
239
279
  };
240
280
  }
281
+ // Collect the out hashes of all the checkpoints before this one in the same epoch
282
+ const epoch = getEpochAtSlot(slotNumber, this.epochCache.getL1Constants());
283
+ const previousCheckpointOutHashes = (await this.blockSource.getCheckpointsDataForEpoch(epoch)).filter((c)=>c.checkpointNumber < checkpointNumber).map((c)=>c.checkpointOutHash);
241
284
  // Try re-executing the transactions in the proposal if needed
242
285
  let reexecutionResult;
243
- if (shouldReexecute) {
244
- try {
245
- this.log.verbose(`Re-executing transactions in the proposal`, proposalInfo);
246
- reexecutionResult = await this.reexecuteTransactions(proposal, blockNumber, checkpointNumber, txs, l1ToL2Messages);
247
- } catch (error) {
248
- this.log.error(`Error reexecuting txs while processing block proposal`, error, proposalInfo);
249
- const reason = this.getReexecuteFailureReason(error);
250
- return {
251
- isValid: false,
252
- blockNumber,
253
- reason,
254
- reexecutionResult
255
- };
256
- }
286
+ try {
287
+ this.log.verbose(`Re-executing transactions in the proposal`, proposalInfo);
288
+ reexecutionResult = await this.reexecuteTransactions(proposal, blockNumber, checkpointNumber, txs, l1ToL2Messages, previousCheckpointOutHashes);
289
+ } catch (error) {
290
+ this.log.error(`Error reexecuting txs while processing block proposal`, error, proposalInfo);
291
+ const reason = this.getReexecuteFailureReason(error);
292
+ return {
293
+ isValid: false,
294
+ blockNumber,
295
+ reason,
296
+ reexecutionResult
297
+ };
257
298
  }
258
299
  // If we succeeded, push this block into the archiver (unless disabled)
259
- // TODO(palla/mbps): Change default to false once block sync is stable.
260
300
  if (reexecutionResult?.block && this.config.skipPushProposedBlocksToArchiver === false) {
261
301
  await this.blockSource.addBlock(reexecutionResult?.block);
262
302
  }
263
- this.log.info(`Successfully processed block ${blockNumber} proposal at index ${proposal.indexWithinCheckpoint} on slot ${slotNumber}`, proposalInfo);
303
+ this.log.info(`Successfully re-executed block ${blockNumber} proposal at index ${proposal.indexWithinCheckpoint} on slot ${slotNumber}`, {
304
+ ...proposalInfo,
305
+ ...pick(reexecutionResult, 'reexecutionTimeMs', 'totalManaUsed')
306
+ });
264
307
  return {
265
308
  isValid: true,
266
309
  blockNumber,
@@ -279,7 +322,7 @@ export class BlockProposalHandler {
279
322
  const currentTime = this.dateProvider.now();
280
323
  const timeoutDurationMs = deadline.getTime() - currentTime;
281
324
  try {
282
- return await this.blockSource.getBlockHeaderByArchive(parentArchive) ?? (timeoutDurationMs <= 0 ? undefined : await retryUntil(()=>this.blockSource.syncImmediate().then(()=>this.blockSource.getBlockHeaderByArchive(parentArchive)), 'force archiver sync', timeoutDurationMs / 1000, 0.5));
325
+ return await this.blockSource.getBlockDataByArchive(parentArchive) ?? (timeoutDurationMs <= 0 ? undefined : await retryUntil(()=>this.blockSource.syncImmediate().then(()=>this.blockSource.getBlockDataByArchive(parentArchive)), 'force archiver sync', timeoutDurationMs / 1000, 0.5));
283
326
  } catch (err) {
284
327
  if (err instanceof TimeoutError) {
285
328
  this.log.debug(`Timed out getting parent block by archive root`, {
@@ -293,8 +336,8 @@ export class BlockProposalHandler {
293
336
  return undefined;
294
337
  }
295
338
  }
296
- async computeCheckpointNumber(proposal, parentBlockHeader, proposalInfo) {
297
- if (parentBlockHeader === 'genesis') {
339
+ computeCheckpointNumber(proposal, parentBlock, proposalInfo) {
340
+ if (parentBlock === 'genesis') {
298
341
  // First block is in checkpoint 1
299
342
  if (proposal.indexWithinCheckpoint !== 0) {
300
343
  this.log.warn(`First block proposal has non-zero indexWithinCheckpoint`, proposalInfo);
@@ -306,20 +349,9 @@ export class BlockProposalHandler {
306
349
  checkpointNumber: CheckpointNumber.INITIAL
307
350
  };
308
351
  }
309
- // Get the parent block to find its checkpoint number
310
- // TODO(palla/mbps): The block header should include the checkpoint number to avoid this lookup,
311
- // or at least the L2BlockSource should return a different struct that includes it.
312
- const parentBlockNumber = parentBlockHeader.getBlockNumber();
313
- const parentBlock = await this.blockSource.getL2BlockNew(parentBlockNumber);
314
- if (!parentBlock) {
315
- this.log.warn(`Parent block ${parentBlockNumber} not found in archiver`, proposalInfo);
316
- return {
317
- reason: 'invalid_proposal'
318
- };
319
- }
320
352
  if (proposal.indexWithinCheckpoint === 0) {
321
353
  // If this is the first block in a new checkpoint, increment the checkpoint number
322
- if (!(proposal.blockHeader.getSlot() > parentBlockHeader.getSlot())) {
354
+ if (!(proposal.blockHeader.getSlot() > parentBlock.header.getSlot())) {
323
355
  this.log.warn(`Slot should be greater than parent block slot for first block in checkpoint`, proposalInfo);
324
356
  return {
325
357
  reason: 'invalid_proposal'
@@ -336,7 +368,7 @@ export class BlockProposalHandler {
336
368
  reason: 'invalid_proposal'
337
369
  };
338
370
  }
339
- if (proposal.blockHeader.getSlot() !== parentBlockHeader.getSlot()) {
371
+ if (proposal.blockHeader.getSlot() !== parentBlock.header.getSlot()) {
340
372
  this.log.warn(`Slot should be equal to parent block slot for non-first block in checkpoint`, proposalInfo);
341
373
  return {
342
374
  reason: 'invalid_proposal'
@@ -434,26 +466,41 @@ export class BlockProposalHandler {
434
466
  }
435
467
  getReexecutionDeadline(slot, config) {
436
468
  const nextSlotTimestampSeconds = Number(getTimestampForSlot(SlotNumber(slot + 1), config));
437
- const msNeededForPropagationAndPublishing = this.config.validatorReexecuteDeadlineMs;
438
- return new Date(nextSlotTimestampSeconds * 1000 - msNeededForPropagationAndPublishing);
469
+ return new Date(nextSlotTimestampSeconds * 1000);
439
470
  }
440
- /**
441
- * Gets all prior blocks in the same checkpoint (same slot and checkpoint number) up to but not including upToBlockNumber.
442
- */ async getBlocksInCheckpoint(slot, upToBlockNumber, checkpointNumber) {
443
- const blocks = [];
444
- let currentBlockNumber = BlockNumber(upToBlockNumber - 1);
445
- while(currentBlockNumber >= INITIAL_L2_BLOCK_NUM){
446
- const block = await this.blockSource.getL2BlockNew(currentBlockNumber);
447
- if (!block || block.header.getSlot() !== slot || block.checkpointNumber !== checkpointNumber) {
448
- break;
471
+ /** Waits for the block source to sync L1 data up to at least the slot before the given one. */ async waitForBlockSourceSync(slot) {
472
+ const deadline = this.getReexecutionDeadline(slot, this.checkpointsBuilder.getConfig());
473
+ const timeoutMs = deadline.getTime() - this.dateProvider.now();
474
+ if (slot === 0) {
475
+ return true;
476
+ }
477
+ // Make a quick check before triggering an archiver sync
478
+ const syncedSlot = await this.blockSource.getSyncedL2SlotNumber();
479
+ if (syncedSlot !== undefined && syncedSlot + 1 >= slot) {
480
+ return true;
481
+ }
482
+ try {
483
+ // Trigger an immediate sync of the block source, and wait until it reports being synced to the required slot
484
+ return await retryUntil(async ()=>{
485
+ await this.blockSource.syncImmediate();
486
+ const syncedSlot = await this.blockSource.getSyncedL2SlotNumber();
487
+ return syncedSlot !== undefined && syncedSlot + 1 >= slot;
488
+ }, 'wait for block source sync', timeoutMs / 1000, 0.5);
489
+ } catch (err) {
490
+ if (err instanceof TimeoutError) {
491
+ this.log.warn(`Timed out waiting for block source to sync to slot ${slot}`);
492
+ return false;
493
+ } else {
494
+ throw err;
449
495
  }
450
- blocks.unshift(block);
451
- currentBlockNumber = BlockNumber(currentBlockNumber - 1);
452
496
  }
453
- return blocks;
454
497
  }
455
498
  getReexecuteFailureReason(err) {
456
- if (err instanceof ReExStateMismatchError) {
499
+ if (err instanceof TransactionsNotAvailableError) {
500
+ return 'txs_not_available';
501
+ } else if (err instanceof ReExInitialStateMismatchError) {
502
+ return 'initial_state_mismatch';
503
+ } else if (err instanceof ReExStateMismatchError) {
457
504
  return 'state_mismatch';
458
505
  } else if (err instanceof ReExFailedTxsError) {
459
506
  return 'failed_txs';
@@ -463,7 +510,7 @@ export class BlockProposalHandler {
463
510
  return 'unknown_error';
464
511
  }
465
512
  }
466
- async reexecuteTransactions(proposal, blockNumber, checkpointNumber, txs, l1ToL2Messages) {
513
+ async reexecuteTransactions(proposal, blockNumber, checkpointNumber, txs, l1ToL2Messages, previousCheckpointOutHashes) {
467
514
  const env = {
468
515
  stack: [],
469
516
  error: void 0,
@@ -480,34 +527,49 @@ export class BlockProposalHandler {
480
527
  const timer = new Timer();
481
528
  const slot = proposal.slotNumber;
482
529
  const config = this.checkpointsBuilder.getConfig();
483
- // Get prior blocks in this checkpoint (same slot and checkpoint number)
484
- const priorBlocks = await this.getBlocksInCheckpoint(slot, blockNumber, checkpointNumber);
530
+ // Get prior blocks in this checkpoint (same slot before current block)
531
+ const allBlocksInSlot = await this.blockSource.getBlocksForSlot(slot);
532
+ const priorBlocks = allBlocksInSlot.filter((b)=>b.number < blockNumber && b.header.getSlot() === slot);
485
533
  // Fork before the block to be built
486
534
  const parentBlockNumber = BlockNumber(blockNumber - 1);
487
- const fork = _ts_add_disposable_resource(env, await this.worldState.fork(parentBlockNumber), false);
488
- // Build checkpoint constants from proposal (excludes blockNumber and timestamp which are per-block)
535
+ await this.worldState.syncImmediate(parentBlockNumber);
536
+ const fork = _ts_add_disposable_resource(env, await this.worldState.fork(parentBlockNumber), true);
537
+ // Verify the fork's archive root matches the proposal's expected last archive.
538
+ // If they don't match, our world state synced to a different chain and reexecution would fail.
539
+ const forkArchiveRoot = new Fr((await fork.getTreeInfo(MerkleTreeId.ARCHIVE)).root);
540
+ if (!forkArchiveRoot.equals(proposal.blockHeader.lastArchive.root)) {
541
+ throw new ReExInitialStateMismatchError(proposal.blockHeader.lastArchive.root, forkArchiveRoot);
542
+ }
543
+ // Build checkpoint constants from proposal (excludes blockNumber which is per-block)
489
544
  const constants = {
490
545
  chainId: new Fr(config.l1ChainId),
491
546
  version: new Fr(config.rollupVersion),
492
547
  slotNumber: slot,
548
+ timestamp: blockHeader.globalVariables.timestamp,
493
549
  coinbase: blockHeader.globalVariables.coinbase,
494
550
  feeRecipient: blockHeader.globalVariables.feeRecipient,
495
551
  gasFees: blockHeader.globalVariables.gasFees
496
552
  };
497
553
  // Create checkpoint builder with prior blocks
498
- const checkpointBuilder = await this.checkpointsBuilder.openCheckpoint(checkpointNumber, constants, l1ToL2Messages, fork, priorBlocks);
554
+ const checkpointBuilder = await this.checkpointsBuilder.openCheckpoint(checkpointNumber, constants, 0n, l1ToL2Messages, previousCheckpointOutHashes, fork, priorBlocks, this.log.getBindings());
499
555
  // Build the new block
500
556
  const deadline = this.getReexecutionDeadline(slot, config);
557
+ const maxBlockGas = this.config.validateMaxL2BlockGas !== undefined || this.config.validateMaxDABlockGas !== undefined ? new Gas(this.config.validateMaxDABlockGas ?? Infinity, this.config.validateMaxL2BlockGas ?? Infinity) : undefined;
501
558
  const result = await checkpointBuilder.buildBlock(txs, blockNumber, blockHeader.globalVariables.timestamp, {
559
+ isBuildingProposal: false,
560
+ minValidTxs: 0,
502
561
  deadline,
503
- expectedEndState: blockHeader.state
562
+ expectedEndState: blockHeader.state,
563
+ maxTransactions: this.config.validateMaxTxsPerBlock,
564
+ maxBlockGas
504
565
  });
505
566
  const { block, failedTxs } = result;
506
567
  const numFailedTxs = failedTxs.length;
507
- this.log.verbose(`Transaction re-execution complete for slot ${slot}`, {
568
+ this.log.verbose(`Block proposal ${blockNumber} at slot ${slot} transaction re-execution complete`, {
508
569
  numFailedTxs,
509
570
  numProposalTxs: txHashes.length,
510
571
  numProcessedTxs: block.body.txEffects.length,
572
+ blockNumber,
511
573
  slot
512
574
  });
513
575
  if (numFailedTxs > 0) {
@@ -545,7 +607,8 @@ export class BlockProposalHandler {
545
607
  env.error = e;
546
608
  env.hasError = true;
547
609
  } finally{
548
- _ts_dispose_resources(env);
610
+ const result = _ts_dispose_resources(env);
611
+ if (result) await result;
549
612
  }
550
613
  }
551
614
  }
@@ -1,70 +1,79 @@
1
1
  import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
2
2
  import { Fr } from '@aztec/foundation/curves/bn254';
3
- import { DateProvider, Timer } from '@aztec/foundation/timer';
3
+ import { type LoggerBindings } from '@aztec/foundation/log';
4
+ import { DateProvider } from '@aztec/foundation/timer';
4
5
  import { LightweightCheckpointBuilder } from '@aztec/prover-client/light';
5
- import { PublicProcessor } from '@aztec/simulator/server';
6
- import { L2BlockNew } from '@aztec/stdlib/block';
6
+ import { PublicContractsDB, PublicProcessor } from '@aztec/simulator/server';
7
+ import { L2Block } from '@aztec/stdlib/block';
7
8
  import { Checkpoint } from '@aztec/stdlib/checkpoint';
8
9
  import type { ContractDataSource } from '@aztec/stdlib/contract';
9
- import { Gas } from '@aztec/stdlib/gas';
10
- import { type FullNodeBlockBuilderConfig, type MerkleTreeWriteOperations, type PublicProcessorLimits } from '@aztec/stdlib/interfaces/server';
11
- import { type CheckpointGlobalVariables, type FailedTx, GlobalVariables, StateReference, Tx } from '@aztec/stdlib/tx';
10
+ import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
11
+ import { type BlockBuilderOptions, type BuildBlockInCheckpointResult, type FullNodeBlockBuilderConfig, type ICheckpointBlockBuilder, type ICheckpointsBuilder, type MerkleTreeWriteOperations, type PublicProcessorLimits, type WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
12
+ import { type DebugLogStore } from '@aztec/stdlib/logs';
13
+ import { type CheckpointGlobalVariables, GlobalVariables, StateReference, Tx } from '@aztec/stdlib/tx';
12
14
  import { type TelemetryClient } from '@aztec/telemetry-client';
13
- export interface BuildBlockInCheckpointResult {
14
- block: L2BlockNew;
15
- publicGas: Gas;
16
- publicProcessorDuration: number;
17
- numTxs: number;
18
- failedTxs: FailedTx[];
19
- blockBuildingTimer: Timer;
20
- usedTxs: Tx[];
21
- }
15
+ export type { BuildBlockInCheckpointResult } from '@aztec/stdlib/interfaces/server';
22
16
  /**
23
17
  * Builder for a single checkpoint. Handles building blocks within the checkpoint
24
18
  * and completing it.
25
19
  */
26
- export declare class CheckpointBuilder {
20
+ export declare class CheckpointBuilder implements ICheckpointBlockBuilder {
27
21
  private checkpointBuilder;
28
22
  private fork;
29
23
  private config;
30
24
  private contractDataSource;
31
25
  private dateProvider;
32
26
  private telemetryClient;
33
- constructor(checkpointBuilder: LightweightCheckpointBuilder, fork: MerkleTreeWriteOperations, config: FullNodeBlockBuilderConfig, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient: TelemetryClient);
27
+ private debugLogStore;
28
+ private log;
29
+ /** Persistent contracts DB shared across all blocks in this checkpoint. */
30
+ protected contractsDB: PublicContractsDB;
31
+ constructor(checkpointBuilder: LightweightCheckpointBuilder, fork: MerkleTreeWriteOperations, config: FullNodeBlockBuilderConfig, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient: TelemetryClient, bindings?: LoggerBindings, debugLogStore?: DebugLogStore);
34
32
  getConstantData(): CheckpointGlobalVariables;
35
33
  /**
36
34
  * Builds a single block within this checkpoint.
35
+ * Automatically caps gas and blob field limits based on checkpoint-level budgets and prior blocks.
37
36
  */
38
- buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, blockNumber: BlockNumber, timestamp: bigint, opts: PublicProcessorLimits & {
37
+ buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, blockNumber: BlockNumber, timestamp: bigint, opts: BlockBuilderOptions & {
39
38
  expectedEndState?: StateReference;
40
39
  }): Promise<BuildBlockInCheckpointResult>;
41
40
  /** Completes the checkpoint and returns it. */
42
41
  completeCheckpoint(): Promise<Checkpoint>;
43
42
  /** Gets the checkpoint currently in progress. */
44
43
  getCheckpoint(): Promise<Checkpoint>;
44
+ /**
45
+ * Caps per-block gas and blob field limits by remaining checkpoint-level budgets.
46
+ * When building a proposal (isBuildingProposal=true), computes a fair share of remaining budget
47
+ * across remaining blocks scaled by the multiplier. When validating, only caps by per-block limit
48
+ * and remaining checkpoint budget (no redistribution or multiplier).
49
+ */
50
+ protected capLimitsByCheckpointBudgets(opts: BlockBuilderOptions): Pick<PublicProcessorLimits, 'maxBlockGas' | 'maxBlobFields' | 'maxTransactions'>;
45
51
  protected makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations): Promise<{
46
52
  processor: PublicProcessor;
47
53
  validator: import("@aztec/stdlib/interfaces/server").PublicProcessorValidator;
48
54
  }>;
49
55
  }
50
- /**
51
- * Factory for creating checkpoint builders.
52
- */
53
- export declare class FullNodeCheckpointsBuilder {
56
+ /** Factory for creating checkpoint builders. */
57
+ export declare class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
54
58
  private config;
59
+ private worldState;
55
60
  private contractDataSource;
56
61
  private dateProvider;
57
62
  private telemetryClient;
58
- constructor(config: FullNodeBlockBuilderConfig, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient?: TelemetryClient);
63
+ private debugLogStore;
64
+ private log;
65
+ constructor(config: FullNodeBlockBuilderConfig & Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>, worldState: WorldStateSynchronizer, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient?: TelemetryClient, debugLogStore?: DebugLogStore);
59
66
  getConfig(): FullNodeBlockBuilderConfig;
60
67
  updateConfig(config: Partial<FullNodeBlockBuilderConfig>): void;
61
68
  /**
62
69
  * Starts a new checkpoint and returns a CheckpointBuilder to build blocks within it.
63
70
  */
64
- startCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, l1ToL2Messages: Fr[], fork: MerkleTreeWriteOperations): Promise<CheckpointBuilder>;
71
+ startCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, feeAssetPriceModifier: bigint, l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[], fork: MerkleTreeWriteOperations, bindings?: LoggerBindings): Promise<CheckpointBuilder>;
65
72
  /**
66
73
  * Opens a checkpoint, either starting fresh or resuming from existing blocks.
67
74
  */
68
- openCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, l1ToL2Messages: Fr[], fork: MerkleTreeWriteOperations, existingBlocks?: L2BlockNew[]): Promise<CheckpointBuilder>;
75
+ openCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, feeAssetPriceModifier: bigint, l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[], fork: MerkleTreeWriteOperations, existingBlocks?: L2Block[], bindings?: LoggerBindings): Promise<CheckpointBuilder>;
76
+ /** Returns a fork of the world state at the given block number. */
77
+ getFork(blockNumber: BlockNumber): Promise<MerkleTreeWriteOperations>;
69
78
  }
70
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF9idWlsZGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2hlY2twb2ludF9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVoRixPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHcEQsT0FBTyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUV2RSxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRSxPQUFPLEVBR0wsZUFBZSxFQUVoQixNQUFNLHlCQUF5QixDQUFDO0FBQ2pDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdEQsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNqRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDeEMsT0FBTyxFQUNMLEtBQUssMEJBQTBCLEVBRS9CLEtBQUsseUJBQXlCLEVBQzlCLEtBQUsscUJBQXFCLEVBQzNCLE1BQU0saUNBQWlDLENBQUM7QUFFekMsT0FBTyxFQUFFLEtBQUsseUJBQXlCLEVBQUUsS0FBSyxRQUFRLEVBQUUsZUFBZSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN0SCxPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFNbkYsTUFBTSxXQUFXLDRCQUE0QjtJQUMzQyxLQUFLLEVBQUUsVUFBVSxDQUFDO0lBQ2xCLFNBQVMsRUFBRSxHQUFHLENBQUM7SUFDZix1QkFBdUIsRUFBRSxNQUFNLENBQUM7SUFDaEMsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLFNBQVMsRUFBRSxRQUFRLEVBQUUsQ0FBQztJQUN0QixrQkFBa0IsRUFBRSxLQUFLLENBQUM7SUFDMUIsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDO0NBQ2Y7QUFFRDs7O0dBR0c7QUFDSCxxQkFBYSxpQkFBaUI7SUFFMUIsT0FBTyxDQUFDLGlCQUFpQjtJQUN6QixPQUFPLENBQUMsSUFBSTtJQUNaLE9BQU8sQ0FBQyxNQUFNO0lBQ2QsT0FBTyxDQUFDLGtCQUFrQjtJQUMxQixPQUFPLENBQUMsWUFBWTtJQUNwQixPQUFPLENBQUMsZUFBZTtJQU56QixZQUNVLGlCQUFpQixFQUFFLDRCQUE0QixFQUMvQyxJQUFJLEVBQUUseUJBQXlCLEVBQy9CLE1BQU0sRUFBRSwwQkFBMEIsRUFDbEMsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQ3RDLFlBQVksRUFBRSxZQUFZLEVBQzFCLGVBQWUsRUFBRSxlQUFlLEVBQ3RDO0lBRUosZUFBZSxJQUFJLHlCQUF5QixDQUUzQztJQUVEOztPQUVHO0lBQ0csVUFBVSxDQUNkLFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxDQUFDLEVBQUUsQ0FBQyxFQUM1QyxXQUFXLEVBQUUsV0FBVyxFQUN4QixTQUFTLEVBQUUsTUFBTSxFQUNqQixJQUFJLEVBQUUscUJBQXFCLEdBQUc7UUFBRSxnQkFBZ0IsQ0FBQyxFQUFFLGNBQWMsQ0FBQTtLQUFFLEdBQ2xFLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxDQTBDdkM7SUFFRCwrQ0FBK0M7SUFDekMsa0JBQWtCLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQVU5QztJQUVELGlEQUFpRDtJQUNqRCxhQUFhLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUVuQztJQUVELFVBQWdCLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLHlCQUF5Qjs7O09Ba0NyRztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxxQkFBYSwwQkFBMEI7SUFFbkMsT0FBTyxDQUFDLE1BQU07SUFDZCxPQUFPLENBQUMsa0JBQWtCO0lBQzFCLE9BQU8sQ0FBQyxZQUFZO0lBQ3BCLE9BQU8sQ0FBQyxlQUFlO0lBSnpCLFlBQ1UsTUFBTSxFQUFFLDBCQUEwQixFQUNsQyxrQkFBa0IsRUFBRSxrQkFBa0IsRUFDdEMsWUFBWSxFQUFFLFlBQVksRUFDMUIsZUFBZSxHQUFFLGVBQXNDLEVBQzdEO0lBRUcsU0FBUyxJQUFJLDBCQUEwQixDQUU3QztJQUVNLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLDBCQUEwQixDQUFDLFFBRTlEO0lBRUQ7O09BRUc7SUFDRyxlQUFlLENBQ25CLGdCQUFnQixFQUFFLGdCQUFnQixFQUNsQyxTQUFTLEVBQUUseUJBQXlCLEVBQ3BDLGNBQWMsRUFBRSxFQUFFLEVBQUUsRUFDcEIsSUFBSSxFQUFFLHlCQUF5QixHQUM5QixPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0EyQjVCO0lBRUQ7O09BRUc7SUFDRyxjQUFjLENBQ2xCLGdCQUFnQixFQUFFLGdCQUFnQixFQUNsQyxTQUFTLEVBQUUseUJBQXlCLEVBQ3BDLGNBQWMsRUFBRSxFQUFFLEVBQUUsRUFDcEIsSUFBSSxFQUFFLHlCQUF5QixFQUMvQixjQUFjLEdBQUUsVUFBVSxFQUFPLEdBQ2hDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQWlDNUI7Q0FDRiJ9
79
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF9idWlsZGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2hlY2twb2ludF9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVoRixPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxFQUFlLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sRUFBRSxZQUFZLEVBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRSxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLGVBQWUsRUFFaEIsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RELE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVyRSxPQUFPLEVBQ0wsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSyw0QkFBNEIsRUFDakMsS0FBSywwQkFBMEIsRUFFL0IsS0FBSyx1QkFBdUIsRUFDNUIsS0FBSyxtQkFBbUIsRUFFeEIsS0FBSyx5QkFBeUIsRUFDOUIsS0FBSyxxQkFBcUIsRUFDMUIsS0FBSyxzQkFBc0IsRUFDNUIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsS0FBSyxhQUFhLEVBQXFCLE1BQU0sb0JBQW9CLENBQUM7QUFFM0UsT0FBTyxFQUFFLEtBQUsseUJBQXlCLEVBQUUsZUFBZSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsTUFBTSxr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
@@ -1 +1 @@
1
- {"version":3,"file":"checkpoint_builder.d.ts","sourceRoot":"","sources":["../src/checkpoint_builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkpoint_builder.d.ts","sourceRoot":"","sources":["../src/checkpoint_builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,EAAE,YAAY,EAAW,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAEL,iBAAiB,EACjB,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAE/B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EAExB,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC5B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,aAAa,EAAqB,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EAAE,KAAK,yBAAyB,EAAE,eAAe,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACvG,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAInF,YAAY,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAEpF;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,uBAAuB;IAO7D,OAAO,CAAC,iBAAiB;IACzB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IAEvB,OAAO,CAAC,aAAa;IAbvB,OAAO,CAAC,GAAG,CAAS;IAEpB,2EAA2E;IAC3E,SAAS,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAEzC,YACU,iBAAiB,EAAE,4BAA4B,EAC/C,IAAI,EAAE,yBAAyB,EAC/B,MAAM,EAAE,0BAA0B,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,EAAE,eAAe,EACxC,QAAQ,CAAC,EAAE,cAAc,EACjB,aAAa,GAAE,aAAuC,EAO/D;IAED,eAAe,IAAI,yBAAyB,CAE3C;IAED;;;OAGG;IACG,UAAU,CACd,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,CAAC,EAC5C,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,mBAAmB,GAAG;QAAE,gBAAgB,CAAC,EAAE,cAAc,CAAA;KAAE,GAChE,OAAO,CAAC,4BAA4B,CAAC,CA6EvC;IAED,+CAA+C;IACzC,kBAAkB,IAAI,OAAO,CAAC,UAAU,CAAC,CAU9C;IAED,iDAAiD;IACjD,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAEnC;IAED;;;;;OAKG;IACH,SAAS,CAAC,4BAA4B,CACpC,IAAI,EAAE,mBAAmB,GACxB,IAAI,CAAC,qBAAqB,EAAE,aAAa,GAAG,eAAe,GAAG,iBAAiB,CAAC,CA8ClF;IAED,UAAgB,oBAAoB,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB;;;OA4CrG;CACF;AAED,gDAAgD;AAChD,qBAAa,0BAA2B,YAAW,mBAAmB;IAIlE,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,aAAa;IARvB,OAAO,CAAC,GAAG,CAAS;IAEpB,YACU,MAAM,EAAE,0BAA0B,GAAG,IAAI,CAAC,iBAAiB,EAAE,eAAe,GAAG,cAAc,CAAC,EAC9F,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC,EACvD,aAAa,GAAE,aAAuC,EAG/D;IAEM,SAAS,IAAI,0BAA0B,CAE7C;IAEM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC,QAE9D;IAED;;OAEG;IACG,eAAe,CACnB,gBAAgB,EAAE,gBAAgB,EAClC,SAAS,EAAE,yBAAyB,EACpC,qBAAqB,EAAE,MAAM,EAC7B,cAAc,EAAE,EAAE,EAAE,EACpB,2BAA2B,EAAE,EAAE,EAAE,EACjC,IAAI,EAAE,yBAAyB,EAC/B,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,iBAAiB,CAAC,CAiC5B;IAED;;OAEG;IACG,cAAc,CAClB,gBAAgB,EAAE,gBAAgB,EAClC,SAAS,EAAE,yBAAyB,EACpC,qBAAqB,EAAE,MAAM,EAC7B,cAAc,EAAE,EAAE,EAAE,EACpB,2BAA2B,EAAE,EAAE,EAAE,EACjC,IAAI,EAAE,yBAAyB,EAC/B,cAAc,GAAE,OAAO,EAAO,EAC9B,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,iBAAiB,CAAC,CA+C5B;IAED,mEAAmE;IACnE,OAAO,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAEpE;CACF"}