@aztec/ethereum 0.0.1-commit.3fd054f6 → 0.0.1-commit.431c48d

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 (144) hide show
  1. package/dest/client.d.ts +19 -3
  2. package/dest/client.d.ts.map +1 -1
  3. package/dest/client.js +52 -3
  4. package/dest/config.d.ts +15 -6
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +29 -9
  7. package/dest/contracts/chain_state_override.d.ts +78 -0
  8. package/dest/contracts/chain_state_override.d.ts.map +1 -0
  9. package/dest/contracts/chain_state_override.js +137 -0
  10. package/dest/contracts/empire_base.d.ts +1 -3
  11. package/dest/contracts/empire_base.d.ts.map +1 -1
  12. package/dest/contracts/fee_asset_price_oracle.d.ts +6 -2
  13. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -1
  14. package/dest/contracts/fee_asset_price_oracle.js +11 -6
  15. package/dest/contracts/governance.d.ts +135 -35
  16. package/dest/contracts/governance.d.ts.map +1 -1
  17. package/dest/contracts/governance.js +226 -15
  18. package/dest/contracts/governance_proposer.d.ts +33 -4
  19. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  20. package/dest/contracts/governance_proposer.js +52 -13
  21. package/dest/contracts/gse.d.ts +4 -2
  22. package/dest/contracts/gse.d.ts.map +1 -1
  23. package/dest/contracts/gse.js +2 -2
  24. package/dest/contracts/inbox.d.ts +3 -3
  25. package/dest/contracts/inbox.d.ts.map +1 -1
  26. package/dest/contracts/inbox.js +12 -7
  27. package/dest/contracts/index.d.ts +3 -3
  28. package/dest/contracts/index.d.ts.map +1 -1
  29. package/dest/contracts/index.js +2 -2
  30. package/dest/contracts/multicall.d.ts +79 -13
  31. package/dest/contracts/multicall.d.ts.map +1 -1
  32. package/dest/contracts/multicall.js +117 -95
  33. package/dest/contracts/outbox.d.ts +27 -4
  34. package/dest/contracts/outbox.d.ts.map +1 -1
  35. package/dest/contracts/outbox.js +34 -7
  36. package/dest/contracts/rollup.d.ts +5418 -28
  37. package/dest/contracts/rollup.d.ts.map +1 -1
  38. package/dest/contracts/rollup.js +389 -95
  39. package/dest/contracts/slashing_proposer.d.ts +171 -0
  40. package/dest/contracts/slashing_proposer.d.ts.map +1 -0
  41. package/dest/contracts/slashing_proposer.js +753 -0
  42. package/dest/contracts/watch_event.d.ts +36 -0
  43. package/dest/contracts/watch_event.d.ts.map +1 -0
  44. package/dest/contracts/watch_event.js +66 -0
  45. package/dest/deploy_aztec_l1_contracts.d.ts +4 -7
  46. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
  47. package/dest/deploy_aztec_l1_contracts.js +15 -8
  48. package/dest/foundry_binary.d.ts +13 -0
  49. package/dest/foundry_binary.d.ts.map +1 -0
  50. package/dest/foundry_binary.js +52 -0
  51. package/dest/generated/l1-contracts-defaults.d.ts +2 -2
  52. package/dest/generated/l1-contracts-defaults.js +2 -2
  53. package/dest/l1_artifacts.d.ts +14941 -16273
  54. package/dest/l1_artifacts.d.ts.map +1 -1
  55. package/dest/l1_artifacts.js +9 -24
  56. package/dest/l1_contract_addresses.d.ts +61 -65
  57. package/dest/l1_contract_addresses.d.ts.map +1 -1
  58. package/dest/l1_contract_addresses.js +101 -82
  59. package/dest/l1_reader.d.ts +3 -5
  60. package/dest/l1_reader.d.ts.map +1 -1
  61. package/dest/l1_reader.js +3 -6
  62. package/dest/l1_tx_utils/config.js +3 -3
  63. package/dest/l1_tx_utils/l1_tx_utils.d.ts +9 -1
  64. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
  65. package/dest/l1_tx_utils/l1_tx_utils.js +115 -54
  66. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -1
  67. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  68. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +49 -19
  69. package/dest/l1_tx_utils/tx_delayer.d.ts +5 -3
  70. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -1
  71. package/dest/l1_tx_utils/tx_delayer.js +7 -5
  72. package/dest/publisher_manager.d.ts +18 -6
  73. package/dest/publisher_manager.d.ts.map +1 -1
  74. package/dest/publisher_manager.js +44 -7
  75. package/dest/queries.d.ts +13 -2
  76. package/dest/queries.d.ts.map +1 -1
  77. package/dest/queries.js +62 -3
  78. package/dest/test/blob_kzg_warmup.d.ts +19 -0
  79. package/dest/test/blob_kzg_warmup.d.ts.map +1 -0
  80. package/dest/test/blob_kzg_warmup.js +64 -0
  81. package/dest/test/chain_monitor.d.ts +34 -2
  82. package/dest/test/chain_monitor.d.ts.map +1 -1
  83. package/dest/test/chain_monitor.js +76 -6
  84. package/dest/test/eth_cheat_codes.d.ts +26 -3
  85. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  86. package/dest/test/eth_cheat_codes.js +61 -40
  87. package/dest/test/index.d.ts +2 -1
  88. package/dest/test/index.d.ts.map +1 -1
  89. package/dest/test/index.js +1 -0
  90. package/dest/test/recording_rpc_server.d.ts +18 -0
  91. package/dest/test/recording_rpc_server.d.ts.map +1 -0
  92. package/dest/test/recording_rpc_server.js +68 -0
  93. package/dest/test/rollup_cheat_codes.d.ts +60 -3
  94. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  95. package/dest/test/rollup_cheat_codes.js +86 -7
  96. package/dest/test/start_anvil.d.ts +1 -1
  97. package/dest/test/start_anvil.d.ts.map +1 -1
  98. package/dest/test/start_anvil.js +41 -5
  99. package/dest/utils.d.ts +9 -2
  100. package/dest/utils.d.ts.map +1 -1
  101. package/dest/utils.js +45 -14
  102. package/package.json +6 -6
  103. package/src/client.ts +63 -1
  104. package/src/config.ts +44 -13
  105. package/src/contracts/chain_state_override.ts +200 -0
  106. package/src/contracts/empire_base.ts +0 -2
  107. package/src/contracts/fee_asset_price_oracle.ts +10 -5
  108. package/src/contracts/governance.ts +310 -10
  109. package/src/contracts/governance_proposer.ts +56 -13
  110. package/src/contracts/gse.ts +7 -2
  111. package/src/contracts/inbox.ts +13 -5
  112. package/src/contracts/index.ts +2 -2
  113. package/src/contracts/multicall.ts +179 -105
  114. package/src/contracts/outbox.ts +42 -8
  115. package/src/contracts/rollup.ts +429 -86
  116. package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +119 -45
  117. package/src/contracts/watch_event.ts +110 -0
  118. package/src/deploy_aztec_l1_contracts.ts +19 -10
  119. package/src/foundry_binary.ts +57 -0
  120. package/src/generated/l1-contracts-defaults.ts +2 -2
  121. package/src/l1_artifacts.ts +12 -35
  122. package/src/l1_contract_addresses.ts +120 -94
  123. package/src/l1_reader.ts +4 -9
  124. package/src/l1_tx_utils/config.ts +3 -3
  125. package/src/l1_tx_utils/l1_tx_utils.ts +107 -50
  126. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +49 -13
  127. package/src/l1_tx_utils/tx_delayer.ts +16 -7
  128. package/src/publisher_manager.ts +54 -18
  129. package/src/queries.ts +70 -4
  130. package/src/test/blob_kzg_warmup.ts +65 -0
  131. package/src/test/chain_monitor.ts +93 -5
  132. package/src/test/eth_cheat_codes.ts +57 -43
  133. package/src/test/index.ts +1 -0
  134. package/src/test/recording_rpc_server.ts +69 -0
  135. package/src/test/rollup_cheat_codes.ts +115 -6
  136. package/src/test/start_anvil.ts +38 -6
  137. package/src/utils.ts +41 -17
  138. package/dest/contracts/empire_slashing_proposer.d.ts +0 -69
  139. package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
  140. package/dest/contracts/empire_slashing_proposer.js +0 -216
  141. package/dest/contracts/tally_slashing_proposer.d.ts +0 -140
  142. package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
  143. package/dest/contracts/tally_slashing_proposer.js +0 -320
  144. package/src/contracts/empire_slashing_proposer.ts +0 -265
@@ -1 +1 @@
1
- {"version":3,"file":"readonly_l1_tx_utils.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/readonly_l1_tx_utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"readonly_l1_tx_utils.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/readonly_l1_tx_utils.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,33 @@
1
1
  import { getKeys, merge, pick, times } from '@aztec/foundation/collection';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
3
  import { makeBackoff, retry } from '@aztec/foundation/retry';
4
+ import { getErrorCause } from '@aztec/foundation/types';
4
5
  import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
5
6
  import pickBy from 'lodash.pickby';
6
- import { MethodNotFoundRpcError, MethodNotSupportedRpcError, decodeErrorResult, formatGwei, getContractError, hexToBytes } from 'viem';
7
+ import { MethodNotFoundRpcError, MethodNotSupportedRpcError, RpcRequestError, decodeErrorResult, formatGwei, getContractError, hexToBytes } from 'viem';
8
+ import { getL1RpcErrorCode } from '../client.js';
7
9
  import { defaultL1TxUtilsConfig, l1TxUtilsConfigMappings } from './config.js';
8
10
  import { BLOCK_TIME_MS, MAX_L1_TX_LIMIT, MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE, MIN_REPLACEMENT_BUMP_PERCENTAGE, WEI_CONST } from './constants.js';
9
11
  import { P75AllTxsPriorityFeeStrategy } from './fee-strategies/index.js';
10
12
  import { getCalldataGasUsage, tryGetCustomErrorNameContractFunction } from './utils.js';
11
13
  // Change this to the current strategy we want to use
12
14
  const CurrentStrategy = P75AllTxsPriorityFeeStrategy;
15
+ /** Error code returned by eth_simulateV1 for `insufficient funds for gas * price + value`. */ const INSUFFICIENT_FUNDS_RPC_ERROR_CODE = -38014;
16
+ /**
17
+ * Returns true when an RPC transport error reports the node's upfront funds check
18
+ * (sender balance >= gasLimit * maxFeePerGas) rejecting the request. Matches on the message as well as on the
19
+ * error code, since RPC gateways differ in how they wrap node errors. Apply this only to transport errors: an
20
+ * execution revert string can mention insufficient funds without being this kind of rejection.
21
+ */ function isInsufficientFundsRpcError(err) {
22
+ if (getL1RpcErrorCode(err) === INSUFFICIENT_FUNDS_RPC_ERROR_CODE) {
23
+ return true;
24
+ }
25
+ const messages = [
26
+ err,
27
+ getErrorCause(err, RpcRequestError)
28
+ ].map((e)=>e instanceof Error ? e.message : '').join(' ');
29
+ return /insufficient funds/i.test(messages);
30
+ }
13
31
  export class ReadOnlyL1TxUtils {
14
32
  client;
15
33
  logger;
@@ -268,8 +286,7 @@ export class ReadOnlyL1TxUtils {
268
286
  return await this._simulate(call, blockOverrides, stateOverrides, gasConfig, abi);
269
287
  }
270
288
  async _simulate(call, blockOverrides = {}, stateOverrides = [], gasConfig, abi) {
271
- try {
272
- const result = await this.client.simulateBlocks({
289
+ const simulateBlocks = ()=>this.client.simulateBlocks({
273
290
  validation: false,
274
291
  blocks: [
275
292
  {
@@ -281,23 +298,13 @@ export class ReadOnlyL1TxUtils {
281
298
  }
282
299
  ]
283
300
  });
284
- if (result[0].calls[0].status === 'failure') {
285
- this.logger?.error('L1 transaction simulation failed', result[0].calls[0].error);
286
- const decodedError = decodeErrorResult({
287
- abi,
288
- data: result[0].calls[0].data
289
- });
290
- throw new Error(`L1 transaction simulation failed with error ${decodedError.errorName}(${decodedError.args?.join(',')})`);
291
- }
292
- this.logger?.debug(`L1 transaction simulation succeeded`, {
293
- ...result[0].calls[0]
294
- });
295
- return {
296
- gasUsed: result[0].gasUsed,
297
- result: result[0].calls[0].data
298
- };
301
+ // Only the request itself is wrapped, so that transport-level rejections are never confused with an
302
+ // execution revert (whose decoded revert string could well mention insufficient funds too).
303
+ let result;
304
+ try {
305
+ result = await simulateBlocks();
299
306
  } catch (err) {
300
- if (err instanceof MethodNotFoundRpcError || err instanceof MethodNotSupportedRpcError) {
307
+ if (getErrorCause(err, MethodNotFoundRpcError) || getErrorCause(err, MethodNotSupportedRpcError)) {
301
308
  if (gasConfig.fallbackGasEstimate) {
302
309
  this.logger?.warn(`Node does not support eth_simulateV1 API. Using fallback gas estimate: ${gasConfig.fallbackGasEstimate}`);
303
310
  return {
@@ -307,8 +314,31 @@ export class ReadOnlyL1TxUtils {
307
314
  }
308
315
  this.logger?.error('Node does not support eth_simulateV1 API');
309
316
  }
317
+ if (isInsufficientFundsRpcError(err)) {
318
+ const rpcError = getErrorCause(err, RpcRequestError);
319
+ const providerMessage = rpcError?.details ?? (err instanceof Error ? err.message : String(err));
320
+ const gas = call?.gas !== undefined ? `, gas ${call.gas}` : '';
321
+ throw new Error(`L1 node rejected the eth_simulateV1 request with an insufficient funds error before executing it ` + `(sender ${call?.from ?? 'unknown'}${gas}): ${providerMessage}`, {
322
+ cause: err
323
+ });
324
+ }
310
325
  throw err;
311
326
  }
327
+ if (result[0].calls[0].status === 'failure') {
328
+ this.logger?.error('L1 transaction simulation failed', result[0].calls[0].error);
329
+ const decodedError = decodeErrorResult({
330
+ abi,
331
+ data: result[0].calls[0].data
332
+ });
333
+ throw new Error(`L1 transaction simulation failed with error ${decodedError.errorName}(${decodedError.args?.join(',')})`);
334
+ }
335
+ this.logger?.debug(`L1 transaction simulation succeeded`, {
336
+ ...result[0].calls[0]
337
+ });
338
+ return {
339
+ gasUsed: result[0].gasUsed,
340
+ result: result[0].calls[0].data
341
+ };
312
342
  }
313
343
  bumpGasLimit(gasLimit, _gasConfig) {
314
344
  const gasConfig = {
@@ -12,8 +12,10 @@ export declare class Delayer {
12
12
  ethereumSlotDuration: bigint;
13
13
  nextWait: {
14
14
  l1Timestamp: bigint;
15
+ timeoutSeconds?: number;
15
16
  } | {
16
17
  l1BlockNumber: bigint;
18
+ timeoutSeconds?: number;
17
19
  } | {
18
20
  indefinitely: true;
19
21
  } | undefined;
@@ -29,9 +31,9 @@ export declare class Delayer {
29
31
  /** Returns the raw hex for all cancelled txs. */
30
32
  getCancelledTxs(): Hex[];
31
33
  /** Delays the next tx to be sent so it lands on the given L1 block number. */
32
- pauseNextTxUntilBlock(l1BlockNumber: number | bigint): void;
34
+ pauseNextTxUntilBlock(l1BlockNumber: number | bigint, timeoutSeconds?: number): void;
33
35
  /** Delays the next tx to be sent so it lands on the given timestamp. */
34
- pauseNextTxUntilTimestamp(l1Timestamp: number | bigint): void;
36
+ pauseNextTxUntilTimestamp(l1Timestamp: number | bigint, timeoutSeconds?: number): void;
35
37
  /** Delays the next tx to be sent indefinitely. */
36
38
  cancelNextTx(): void;
37
39
  /**
@@ -53,4 +55,4 @@ export declare function createDelayer(dateProvider: DateProvider, opts: {
53
55
  * The delayer intercepts sendRawTransaction calls and delays them based on the delayer's state.
54
56
  */
55
57
  export declare function wrapClientWithDelayer<T extends ViemClient>(client: T, delayer: Delayer): T;
56
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhfZGVsYXllci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2wxX3R4X3V0aWxzL3R4X2RlbGF5ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFFLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRzVELE9BQU8sRUFDTCxLQUFLLE1BQU0sRUFDWCxLQUFLLEdBQUcsRUFVVCxNQUFNLE1BQU0sQ0FBQztBQUVkLE9BQU8sS0FBSyxFQUE0QixVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFJeEUsd0JBQWdCLGNBQWMsQ0FBQyxDQUFDLFNBQVMsTUFBTSxFQUM3QyxNQUFNLEVBQUUsQ0FBQyxFQUNULFdBQVcsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUM1QixNQUFNLENBQUMsRUFBRSxNQUFNLEVBQ2YsT0FBTyxDQUFDLEVBQUUsTUFBTSxvQkFpQmpCO0FBRUQsd0JBQWdCLG9CQUFvQixDQUFDLENBQUMsU0FBUyxNQUFNLEVBQ25ELE1BQU0sRUFBRSxDQUFDLEVBQ1QsU0FBUyxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQzFCLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFDZixPQUFPLENBQUMsRUFBRSxNQUFNLG9CQXdCakI7QUFFRCxzR0FBc0c7QUFDdEcscUJBQWEsT0FBTztJQVVULFlBQVksRUFBRSxZQUFZO0lBVG5DLE9BQU8sQ0FBQyxNQUFNLENBQVM7SUFFaEIsd0JBQXdCLEVBQUUsTUFBTSxHQUFHLFNBQVMsQ0FBYTtJQUN6RCxvQkFBb0IsRUFBRSxNQUFNLENBQUM7SUFDN0IsUUFBUSxFQUFFO1FBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQTtLQUFFLEdBQUc7UUFBRSxhQUFhLEVBQUUsTUFBTSxDQUFBO0tBQUUsR0FBRztRQUFFLFlBQVksRUFBRSxJQUFJLENBQUE7S0FBRSxHQUFHLFNBQVMsQ0FBYTtJQUMvRyxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQU07SUFDekIsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFNO0lBRWhDLFlBQ1MsWUFBWSxFQUFFLFlBQVksRUFDakMsSUFBSSxFQUFFO1FBQUUsb0JBQW9CLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FBQTtLQUFFLEVBQy9DLFFBQVEsRUFBRSxjQUFjLEVBSXpCO0lBRUQsd0RBQXdEO0lBQ3hELFNBQVMsSUFBSSxNQUFNLENBRWxCO0lBRUQsc0RBQXNEO0lBQ3RELGVBQWUsb0JBRWQ7SUFFRCxpREFBaUQ7SUFDakQsZUFBZSxJQUFJLEdBQUcsRUFBRSxDQUV2QjtJQUVELDhFQUE4RTtJQUM5RSxxQkFBcUIsQ0FBQyxhQUFhLEVBQUUsTUFBTSxHQUFHLE1BQU0sUUFFbkQ7SUFFRCx3RUFBd0U7SUFDeEUseUJBQXlCLENBQUMsV0FBVyxFQUFFLE1BQU0sR0FBRyxNQUFNLFFBRXJEO0lBRUQsa0RBQWtEO0lBQ2xELFlBQVksU0FFWDtJQUVEOzs7O09BSUc7SUFDSCwyQkFBMkIsQ0FBQyxPQUFPLEVBQUUsTUFBTSxHQUFHLFNBQVMsUUFFdEQ7Q0FDRjtBQUVEOzs7R0FHRztBQUNILHdCQUFnQixhQUFhLENBQzNCLFlBQVksRUFBRSxZQUFZLEVBQzFCLElBQUksRUFBRTtJQUFFLG9CQUFvQixFQUFFLE1BQU0sR0FBRyxNQUFNLENBQUE7Q0FBRSxFQUMvQyxRQUFRLEVBQUUsY0FBYyxHQUN2QixPQUFPLENBRVQ7QUFhRDs7O0dBR0c7QUFDSCx3QkFBZ0IscUJBQXFCLENBQUMsQ0FBQyxTQUFTLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxPQUFPLEdBQUcsQ0FBQyxDQWtIMUYifQ==
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhfZGVsYXllci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2wxX3R4X3V0aWxzL3R4X2RlbGF5ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFFLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRzVELE9BQU8sRUFDTCxLQUFLLE1BQU0sRUFDWCxLQUFLLEdBQUcsRUFVVCxNQUFNLE1BQU0sQ0FBQztBQUVkLE9BQU8sS0FBSyxFQUE0QixVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFJeEUsd0JBQWdCLGNBQWMsQ0FBQyxDQUFDLFNBQVMsTUFBTSxFQUM3QyxNQUFNLEVBQUUsQ0FBQyxFQUNULFdBQVcsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUM1QixNQUFNLENBQUMsRUFBRSxNQUFNLEVBQ2YsT0FBTyxDQUFDLEVBQUUsTUFBTSxvQkFpQmpCO0FBRUQsd0JBQWdCLG9CQUFvQixDQUFDLENBQUMsU0FBUyxNQUFNLEVBQ25ELE1BQU0sRUFBRSxDQUFDLEVBQ1QsU0FBUyxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQzFCLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFDZixPQUFPLENBQUMsRUFBRSxNQUFNLG9CQXdCakI7QUFFRCxzR0FBc0c7QUFDdEcscUJBQWEsT0FBTztJQWNULFlBQVksRUFBRSxZQUFZO0lBYm5DLE9BQU8sQ0FBQyxNQUFNLENBQVM7SUFFaEIsd0JBQXdCLEVBQUUsTUFBTSxHQUFHLFNBQVMsQ0FBYTtJQUN6RCxvQkFBb0IsRUFBRSxNQUFNLENBQUM7SUFDN0IsUUFBUSxFQUNYO1FBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQztRQUFDLGNBQWMsQ0FBQyxFQUFFLE1BQU0sQ0FBQTtLQUFFLEdBQ2hEO1FBQUUsYUFBYSxFQUFFLE1BQU0sQ0FBQztRQUFDLGNBQWMsQ0FBQyxFQUFFLE1BQU0sQ0FBQTtLQUFFLEdBQ2xEO1FBQUUsWUFBWSxFQUFFLElBQUksQ0FBQTtLQUFFLEdBQ3RCLFNBQVMsQ0FBYTtJQUNuQixZQUFZLEVBQUUsR0FBRyxFQUFFLENBQU07SUFDekIsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFNO0lBRWhDLFlBQ1MsWUFBWSxFQUFFLFlBQVksRUFDakMsSUFBSSxFQUFFO1FBQUUsb0JBQW9CLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FBQTtLQUFFLEVBQy9DLFFBQVEsRUFBRSxjQUFjLEVBSXpCO0lBRUQsd0RBQXdEO0lBQ3hELFNBQVMsSUFBSSxNQUFNLENBRWxCO0lBRUQsc0RBQXNEO0lBQ3RELGVBQWUsb0JBRWQ7SUFFRCxpREFBaUQ7SUFDakQsZUFBZSxJQUFJLEdBQUcsRUFBRSxDQUV2QjtJQUVELDhFQUE4RTtJQUM5RSxxQkFBcUIsQ0FBQyxhQUFhLEVBQUUsTUFBTSxHQUFHLE1BQU0sRUFBRSxjQUFjLENBQUMsRUFBRSxNQUFNLFFBRTVFO0lBRUQsd0VBQXdFO0lBQ3hFLHlCQUF5QixDQUFDLFdBQVcsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUFFLGNBQWMsQ0FBQyxFQUFFLE1BQU0sUUFFOUU7SUFFRCxrREFBa0Q7SUFDbEQsWUFBWSxTQUVYO0lBRUQ7Ozs7T0FJRztJQUNILDJCQUEyQixDQUFDLE9BQU8sRUFBRSxNQUFNLEdBQUcsU0FBUyxRQUV0RDtDQUNGO0FBRUQ7OztHQUdHO0FBQ0gsd0JBQWdCLGFBQWEsQ0FDM0IsWUFBWSxFQUFFLFlBQVksRUFDMUIsSUFBSSxFQUFFO0lBQUUsb0JBQW9CLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FBQTtDQUFFLEVBQy9DLFFBQVEsRUFBRSxjQUFjLEdBQ3ZCLE9BQU8sQ0FFVDtBQWFEOzs7R0FHRztBQUNILHdCQUFnQixxQkFBcUIsQ0FBQyxDQUFDLFNBQVMsVUFBVSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQU8sR0FBRyxDQUFDLENBdUgxRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"tx_delayer.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/tx_delayer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EACL,KAAK,MAAM,EACX,KAAK,GAAG,EAUT,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAA4B,UAAU,EAAE,MAAM,aAAa,CAAC;AAIxE,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,MAAM,EAAE,CAAC,EACT,WAAW,EAAE,MAAM,GAAG,MAAM,EAC5B,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,oBAiBjB;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EACnD,MAAM,EAAE,CAAC,EACT,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,oBAwBjB;AAED,sGAAsG;AACtG,qBAAa,OAAO;IAUT,YAAY,EAAE,YAAY;IATnC,OAAO,CAAC,MAAM,CAAS;IAEhB,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAa;IACzD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,YAAY,EAAE,IAAI,CAAA;KAAE,GAAG,SAAS,CAAa;IAC/G,YAAY,EAAE,GAAG,EAAE,CAAM;IACzB,YAAY,EAAE,GAAG,EAAE,CAAM;IAEhC,YACS,YAAY,EAAE,YAAY,EACjC,IAAI,EAAE;QAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,EAC/C,QAAQ,EAAE,cAAc,EAIzB;IAED,wDAAwD;IACxD,SAAS,IAAI,MAAM,CAElB;IAED,sDAAsD;IACtD,eAAe,oBAEd;IAED,iDAAiD;IACjD,eAAe,IAAI,GAAG,EAAE,CAEvB;IAED,8EAA8E;IAC9E,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,QAEnD;IAED,wEAAwE;IACxE,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,QAErD;IAED,kDAAkD;IAClD,YAAY,SAEX;IAED;;;;OAIG;IACH,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,QAEtD;CACF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE;IAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAC/C,QAAQ,EAAE,cAAc,GACvB,OAAO,CAET;AAaD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,CAkH1F"}
1
+ {"version":3,"file":"tx_delayer.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/tx_delayer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EACL,KAAK,MAAM,EACX,KAAK,GAAG,EAUT,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAA4B,UAAU,EAAE,MAAM,aAAa,CAAC;AAIxE,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,MAAM,EAAE,CAAC,EACT,WAAW,EAAE,MAAM,GAAG,MAAM,EAC5B,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,oBAiBjB;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EACnD,MAAM,EAAE,CAAC,EACT,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,oBAwBjB;AAED,sGAAsG;AACtG,qBAAa,OAAO;IAcT,YAAY,EAAE,YAAY;IAbnC,OAAO,CAAC,MAAM,CAAS;IAEhB,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAa;IACzD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EACX;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAChD;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAClD;QAAE,YAAY,EAAE,IAAI,CAAA;KAAE,GACtB,SAAS,CAAa;IACnB,YAAY,EAAE,GAAG,EAAE,CAAM;IACzB,YAAY,EAAE,GAAG,EAAE,CAAM;IAEhC,YACS,YAAY,EAAE,YAAY,EACjC,IAAI,EAAE;QAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,EAC/C,QAAQ,EAAE,cAAc,EAIzB;IAED,wDAAwD;IACxD,SAAS,IAAI,MAAM,CAElB;IAED,sDAAsD;IACtD,eAAe,oBAEd;IAED,iDAAiD;IACjD,eAAe,IAAI,GAAG,EAAE,CAEvB;IAED,8EAA8E;IAC9E,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,QAE5E;IAED,wEAAwE;IACxE,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,QAE9E;IAED,kDAAkD;IAClD,YAAY,SAEX;IAED;;;;OAIG;IACH,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,QAEtD;CACF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE;IAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAC/C,QAAQ,EAAE,cAAc,GACvB,OAAO,CAET;AAaD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,CAuH1F"}
@@ -60,14 +60,16 @@ export function waitUntilL1Timestamp(client, timestamp, logger, timeout) {
60
60
  /** Returns the raw hex for all cancelled txs. */ getCancelledTxs() {
61
61
  return this.cancelledTxs;
62
62
  }
63
- /** Delays the next tx to be sent so it lands on the given L1 block number. */ pauseNextTxUntilBlock(l1BlockNumber) {
63
+ /** Delays the next tx to be sent so it lands on the given L1 block number. */ pauseNextTxUntilBlock(l1BlockNumber, timeoutSeconds) {
64
64
  this.nextWait = {
65
- l1BlockNumber: BigInt(l1BlockNumber)
65
+ l1BlockNumber: BigInt(l1BlockNumber),
66
+ timeoutSeconds
66
67
  };
67
68
  }
68
- /** Delays the next tx to be sent so it lands on the given timestamp. */ pauseNextTxUntilTimestamp(l1Timestamp) {
69
+ /** Delays the next tx to be sent so it lands on the given timestamp. */ pauseNextTxUntilTimestamp(l1Timestamp, timeoutSeconds) {
69
70
  this.nextWait = {
70
- l1Timestamp: BigInt(l1Timestamp)
71
+ l1Timestamp: BigInt(l1Timestamp),
72
+ timeoutSeconds
71
73
  };
72
74
  }
73
75
  /** Delays the next tx to be sent indefinitely. */ cancelNextTx() {
@@ -131,7 +133,7 @@ export function waitUntilL1Timestamp(client, timestamp, logger, timeout) {
131
133
  return Promise.resolve(txHash);
132
134
  }
133
135
  // Or wait until the desired block number or timestamp
134
- wait = 'l1BlockNumber' in waitUntil ? waitUntilBlock(publicClient, waitUntil.l1BlockNumber - 1n, logger) : 'l1Timestamp' in waitUntil ? waitUntilL1Timestamp(publicClient, waitUntil.l1Timestamp - delayer.ethereumSlotDuration, logger) : undefined;
136
+ wait = 'l1BlockNumber' in waitUntil ? waitUntilBlock(publicClient, waitUntil.l1BlockNumber - 1n, logger, waitUntil.timeoutSeconds) : 'l1Timestamp' in waitUntil ? waitUntilL1Timestamp(publicClient, waitUntil.l1Timestamp - delayer.ethereumSlotDuration, logger, waitUntil.timeoutSeconds) : undefined;
135
137
  logger.info(`Delaying tx ${txHash} until ${inspect(waitUntil)}`, {
136
138
  sender,
137
139
  argsLen: args.length,
@@ -1,4 +1,5 @@
1
1
  import { type LoggerBindings } from '@aztec/foundation/log';
2
+ import { RunningPromise } from '@aztec/foundation/running-promise';
2
3
  import { L1TxUtils } from './l1_tx_utils/index.js';
3
4
  export type PublisherFilter<UtilsType extends L1TxUtils> = (utils: UtilsType) => boolean;
4
5
  /** Config accepted by PublisherManager. */
@@ -8,23 +9,34 @@ type PublisherManagerConfig = {
8
9
  publisherFundingAmount?: bigint;
9
10
  };
10
11
  export declare class PublisherManager<UtilsType extends L1TxUtils = L1TxUtils> {
11
- private publishers;
12
+ protected publishers: UtilsType[];
12
13
  private log;
13
14
  private config;
14
15
  private static readonly FUNDING_CHECK_INTERVAL_MS;
15
- private funder?;
16
- private fundingPromise?;
16
+ protected funder?: UtilsType;
17
+ protected readonly fundingPromise?: RunningPromise;
18
+ private started;
17
19
  constructor(publishers: UtilsType[], config: PublisherManagerConfig, opts?: {
18
20
  bindings?: LoggerBindings;
19
21
  funder?: UtilsType;
20
22
  });
21
- /** Loads the state of all publishers and the funder, and starts periodic funding checks. */
23
+ /**
24
+ * Clears any interrupted flag left by a previous {@link stop} so publishing works again after a restart,
25
+ * loads the state of all publishers and the funder, and starts periodic funding checks. Idempotent: a
26
+ * start while already started is a no-op, so it never re-runs `loadStateAndResumeMonitoring` (which
27
+ * would spawn a duplicate background monitor per pending nonce). Lifecycle calls are expected to be
28
+ * serialized by the caller.
29
+ */
22
30
  start(): Promise<void>;
23
- /** Stops the funding loop and interrupts all publishers. */
31
+ /**
32
+ * Stops the funding loop, interrupts all publishers so no further L1 txs are sent, and waits (bounded)
33
+ * for their in-flight tx monitor loops to wind down. Idempotent, and the manager may be restarted
34
+ * afterwards via {@link start}, which clears the interrupted flag.
35
+ */
24
36
  stop(): Promise<void>;
25
37
  getAvailablePublisher(filter?: PublisherFilter<UtilsType>): Promise<UtilsType>;
26
38
  private triggerFundingIfNeeded;
27
39
  private fundPublishers;
28
40
  }
29
41
  export {};
30
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaGVyX21hbmFnZXIuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wdWJsaXNoZXJfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQWUsS0FBSyxjQUFjLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFJdkYsT0FBTyxFQUFFLFNBQVMsRUFBZ0IsTUFBTSx3QkFBd0IsQ0FBQztBQXdCakUsTUFBTSxNQUFNLGVBQWUsQ0FBQyxTQUFTLFNBQVMsU0FBUyxJQUFJLENBQUMsS0FBSyxFQUFFLFNBQVMsS0FBSyxPQUFPLENBQUM7QUFFekYsMkNBQTJDO0FBQzNDLEtBQUssc0JBQXNCLEdBQUc7SUFDNUIsMkJBQTJCLENBQUMsRUFBRSxPQUFPLENBQUM7SUFDdEMseUJBQXlCLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDbkMsc0JBQXNCLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDakMsQ0FBQztBQUVGLHFCQUFhLGdCQUFnQixDQUFDLFNBQVMsU0FBUyxTQUFTLEdBQUcsU0FBUztJQVFqRSxPQUFPLENBQUMsVUFBVTtJQVBwQixPQUFPLENBQUMsR0FBRyxDQUFTO0lBQ3BCLE9BQU8sQ0FBQyxNQUFNLENBQXlCO0lBQ3ZDLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLHlCQUF5QixDQUFpQjtJQUNsRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQVk7SUFDM0IsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFpQjtJQUV4QyxZQUNVLFVBQVUsRUFBRSxTQUFTLEVBQUUsRUFDL0IsTUFBTSxFQUFFLHNCQUFzQixFQUM5QixJQUFJLENBQUMsRUFBRTtRQUFFLFFBQVEsQ0FBQyxFQUFFLGNBQWMsQ0FBQztRQUFDLE1BQU0sQ0FBQyxFQUFFLFNBQVMsQ0FBQTtLQUFFLEVBcUJ6RDtJQUVELDRGQUE0RjtJQUMvRSxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQWtCbEM7SUFFRCw0REFBNEQ7SUFDL0MsSUFBSSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FJakM7SUFRWSxxQkFBcUIsQ0FBQyxNQUFNLEdBQUUsZUFBZSxDQUFDLFNBQVMsQ0FBYyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0ErQ3RHO1lBR2Esc0JBQXNCO1lBcUN0QixjQUFjO0NBVTdCIn0=
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaGVyX21hbmFnZXIuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wdWJsaXNoZXJfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQWUsS0FBSyxjQUFjLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFDdkYsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBR25FLE9BQU8sRUFBRSxTQUFTLEVBQWdCLE1BQU0sd0JBQXdCLENBQUM7QUF3QmpFLE1BQU0sTUFBTSxlQUFlLENBQUMsU0FBUyxTQUFTLFNBQVMsSUFBSSxDQUFDLEtBQUssRUFBRSxTQUFTLEtBQUssT0FBTyxDQUFDO0FBRXpGLDJDQUEyQztBQUMzQyxLQUFLLHNCQUFzQixHQUFHO0lBQzVCLDJCQUEyQixDQUFDLEVBQUUsT0FBTyxDQUFDO0lBQ3RDLHlCQUF5QixDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ25DLHNCQUFzQixDQUFDLEVBQUUsTUFBTSxDQUFDO0NBQ2pDLENBQUM7QUFFRixxQkFBYSxnQkFBZ0IsQ0FBQyxTQUFTLFNBQVMsU0FBUyxHQUFHLFNBQVM7SUFTakUsU0FBUyxDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUU7SUFSbkMsT0FBTyxDQUFDLEdBQUcsQ0FBUztJQUNwQixPQUFPLENBQUMsTUFBTSxDQUF5QjtJQUN2QyxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyx5QkFBeUIsQ0FBaUI7SUFDbEUsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFLFNBQVMsQ0FBQztJQUM3QixTQUFTLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxFQUFFLGNBQWMsQ0FBQztJQUNuRCxPQUFPLENBQUMsT0FBTyxDQUFTO0lBRXhCLFlBQ1ksVUFBVSxFQUFFLFNBQVMsRUFBRSxFQUNqQyxNQUFNLEVBQUUsc0JBQXNCLEVBQzlCLElBQUksQ0FBQyxFQUFFO1FBQUUsUUFBUSxDQUFDLEVBQUUsY0FBYyxDQUFDO1FBQUMsTUFBTSxDQUFDLEVBQUUsU0FBUyxDQUFBO0tBQUUsRUE2QnpEO0lBRUQ7Ozs7OztPQU1HO0lBQ1UsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FtQmxDO0lBRUQ7Ozs7T0FJRztJQUNVLElBQUksSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBV2pDO0lBUVkscUJBQXFCLENBQUMsTUFBTSxHQUFFLGVBQWUsQ0FBQyxTQUFTLENBQWMsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBd0R0RztZQUdhLHNCQUFzQjtZQXFDdEIsY0FBYztDQVU3QiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"publisher_manager.d.ts","sourceRoot":"","sources":["../src/publisher_manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAIvF,OAAO,EAAE,SAAS,EAAgB,MAAM,wBAAwB,CAAC;AAwBjE,MAAM,MAAM,eAAe,CAAC,SAAS,SAAS,SAAS,IAAI,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;AAEzF,2CAA2C;AAC3C,KAAK,sBAAsB,GAAG;IAC5B,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAEF,qBAAa,gBAAgB,CAAC,SAAS,SAAS,SAAS,GAAG,SAAS;IAQjE,OAAO,CAAC,UAAU;IAPpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAiB;IAClE,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,cAAc,CAAC,CAAiB;IAExC,YACU,UAAU,EAAE,SAAS,EAAE,EAC/B,MAAM,EAAE,sBAAsB,EAC9B,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAA;KAAE,EAqBzD;IAED,4FAA4F;IAC/E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAkBlC;IAED,4DAA4D;IAC/C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAIjC;IAQY,qBAAqB,CAAC,MAAM,GAAE,eAAe,CAAC,SAAS,CAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CA+CtG;YAGa,sBAAsB;YAqCtB,cAAc;CAU7B"}
1
+ {"version":3,"file":"publisher_manager.d.ts","sourceRoot":"","sources":["../src/publisher_manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAGnE,OAAO,EAAE,SAAS,EAAgB,MAAM,wBAAwB,CAAC;AAwBjE,MAAM,MAAM,eAAe,CAAC,SAAS,SAAS,SAAS,IAAI,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;AAEzF,2CAA2C;AAC3C,KAAK,sBAAsB,GAAG;IAC5B,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAEF,qBAAa,gBAAgB,CAAC,SAAS,SAAS,SAAS,GAAG,SAAS;IASjE,SAAS,CAAC,UAAU,EAAE,SAAS,EAAE;IARnC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAiB;IAClE,SAAS,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;IAC7B,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACnD,OAAO,CAAC,OAAO,CAAS;IAExB,YACY,UAAU,EAAE,SAAS,EAAE,EACjC,MAAM,EAAE,sBAAsB,EAC9B,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAA;KAAE,EA6BzD;IAED;;;;;;OAMG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBlC;IAED;;;;OAIG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAWjC;IAQY,qBAAqB,CAAC,MAAM,GAAE,eAAe,CAAC,SAAS,CAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAwDtG;YAGa,sBAAsB;YAqCtB,cAAc;CAU7B"}
@@ -30,8 +30,10 @@ export class PublisherManager {
30
30
  static FUNDING_CHECK_INTERVAL_MS = 2 * 60 * 1000;
31
31
  funder;
32
32
  fundingPromise;
33
+ started;
33
34
  constructor(publishers, config, opts){
34
35
  this.publishers = publishers;
36
+ this.started = false;
35
37
  this.funder = opts?.funder;
36
38
  this.log = createLogger('publisher:manager', opts?.bindings);
37
39
  this.log.info(`PublisherManager initialized with ${publishers.length} publishers.`);
@@ -49,21 +51,48 @@ export class PublisherManager {
49
51
  this.funder = undefined;
50
52
  }
51
53
  }
54
+ if (this.funder && hasThreshold && hasAmount) {
55
+ this.fundingPromise = new RunningPromise(()=>this.triggerFundingIfNeeded(), this.log, PublisherManager.FUNDING_CHECK_INTERVAL_MS);
56
+ }
52
57
  }
53
- /** Loads the state of all publishers and the funder, and starts periodic funding checks. */ async start() {
58
+ /**
59
+ * Clears any interrupted flag left by a previous {@link stop} so publishing works again after a restart,
60
+ * loads the state of all publishers and the funder, and starts periodic funding checks. Idempotent: a
61
+ * start while already started is a no-op, so it never re-runs `loadStateAndResumeMonitoring` (which
62
+ * would spawn a duplicate background monitor per pending nonce). Lifecycle calls are expected to be
63
+ * serialized by the caller.
64
+ */ async start() {
65
+ if (this.started) {
66
+ this.log.debug('PublisherManager already started, ignoring start');
67
+ return;
68
+ }
69
+ // Clear the interrupted flag set by a previous stop() so a restarted manager can publish again.
70
+ // On a first start this is a no-op (the flag is already clear).
71
+ this.publishers.forEach((pub)=>pub.restart());
72
+ this.funder?.restart();
54
73
  await Promise.all([
55
74
  ...this.publishers.map((pub)=>pub.loadStateAndResumeMonitoring()),
56
75
  this.funder?.loadStateAndResumeMonitoring()
57
76
  ]);
58
- if (this.funder && this.config.publisherFundingThreshold !== undefined && this.config.publisherFundingAmount !== undefined) {
59
- this.fundingPromise = new RunningPromise(()=>this.triggerFundingIfNeeded(), this.log, PublisherManager.FUNDING_CHECK_INTERVAL_MS);
60
- this.fundingPromise.start();
61
- }
77
+ this.fundingPromise?.start();
78
+ // Marked started only once fully up, so a start that failed to load state can be retried.
79
+ this.started = true;
62
80
  }
63
- /** Stops the funding loop and interrupts all publishers. */ async stop() {
81
+ /**
82
+ * Stops the funding loop, interrupts all publishers so no further L1 txs are sent, and waits (bounded)
83
+ * for their in-flight tx monitor loops to wind down. Idempotent, and the manager may be restarted
84
+ * afterwards via {@link start}, which clears the interrupted flag.
85
+ */ async stop() {
86
+ this.started = false;
64
87
  await this.fundingPromise?.stop();
65
88
  this.publishers.forEach((pub)=>pub.interrupt());
66
89
  this.funder?.interrupt();
90
+ // Wait for in-flight tx monitor loops to observe the interrupt, so no L1 requests are still
91
+ // being issued after shutdown (e.g. against an anvil instance a test is about to tear down).
92
+ await Promise.all([
93
+ ...this.publishers.map((pub)=>pub.waitMonitoringStopped()),
94
+ this.funder?.waitMonitoringStopped()
95
+ ]);
67
96
  }
68
97
  // Finds and prioritises available publishers based on
69
98
  // 1. Validity as per the provided filter function
@@ -97,8 +126,16 @@ export class PublisherManager {
97
126
  publisher: pub
98
127
  };
99
128
  }));
129
+ // Discount unfunded publishers: a publisher with no ETH cannot send a tx, so it must never win
130
+ // selection regardless of how favourable its state or last-used time is. Fall back to the full
131
+ // set only if every candidate is unfunded, so behaviour is no worse than before.
132
+ let fundedPublishers = publishersWithBalance.filter((p)=>p.balance > 0n);
133
+ if (fundedPublishers.length === 0) {
134
+ this.log.warn(`All candidate publishers have zero balance; selecting from unfunded publishers.`);
135
+ fundedPublishers = publishersWithBalance;
136
+ }
100
137
  // Sort based on state, then balance, then time since last use
101
- const sortedPublishers = publishersWithBalance.sort((a, b)=>{
138
+ const sortedPublishers = fundedPublishers.sort((a, b)=>{
102
139
  const stateComparison = sortOrder.indexOf(a.publisher.state) - sortOrder.indexOf(b.publisher.state);
103
140
  if (stateComparison !== 0) {
104
141
  return stateComparison;
package/dest/queries.d.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { type Block } from 'viem';
2
3
  import { type L1ContractsConfig } from './config.js';
3
- import type { ViemPublicClient } from './types.js';
4
+ import type { ViemClient, ViemPublicClient } from './types.js';
5
+ /**
6
+ * Returns the L1 finalized block, or `undefined` if the chain does not yet have one
7
+ * (common on freshly started devnets). Rethrows any other RPC error.
8
+ */
9
+ export declare function getFinalizedL1Block(client: ViemClient): Promise<Block<bigint, false, 'finalized'> | undefined>;
10
+ /**
11
+ * Returns true if the error originates from an RPC call that failed because
12
+ * the "finalized" (or "safe") block tag is not yet available on the chain.
13
+ */
14
+ export declare function isFinalizedBlockTagNotFoundError(err: unknown): boolean;
4
15
  /** Reads the L1ContractsConfig from L1 contracts. */
5
16
  export declare function getL1ContractsConfig(publicClient: ViemPublicClient, addresses: {
6
17
  governanceAddress: EthAddress;
@@ -11,4 +22,4 @@ export declare function getL1ContractsConfig(publicClient: ViemPublicClient, add
11
22
  rollupVersion: number;
12
23
  genesisArchiveTreeRoot: `0x${string}`;
13
24
  }>;
14
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcmllcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3F1ZXJpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBNEIsS0FBSyxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUsvRSxPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUVuRCxxREFBcUQ7QUFDckQsd0JBQXNCLG9CQUFvQixDQUN4QyxZQUFZLEVBQUUsZ0JBQWdCLEVBQzlCLFNBQVMsRUFBRTtJQUFFLGlCQUFpQixFQUFFLFVBQVUsQ0FBQztJQUFDLGFBQWEsQ0FBQyxFQUFFLFVBQVUsQ0FBQTtDQUFFLEdBQ3ZFLE9BQU8sQ0FDUixJQUFJLENBQUMsaUJBQWlCLEVBQUUsc0JBQXNCLENBQUMsR0FBRztJQUNoRCxZQUFZLEVBQUUsTUFBTSxDQUFDO0lBQ3JCLGFBQWEsRUFBRSxNQUFNLENBQUM7SUFDdEIsYUFBYSxFQUFFLE1BQU0sQ0FBQztJQUN0QixzQkFBc0IsRUFBRSxLQUFLLE1BQU0sRUFBRSxDQUFDO0NBQ3ZDLENBQ0YsQ0F1R0EifQ==
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcmllcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3F1ZXJpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBYSxLQUFLLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUU3QyxPQUFPLEVBQTRCLEtBQUssaUJBQWlCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFLL0UsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRS9EOzs7R0FHRztBQUNILHdCQUFzQixtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxXQUFXLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FTcEg7QUFtQkQ7OztHQUdHO0FBQ0gsd0JBQWdCLGdDQUFnQyxDQUFDLEdBQUcsRUFBRSxPQUFPLEdBQUcsT0FBTyxDQWtCdEU7QUFVRCxxREFBcUQ7QUFDckQsd0JBQXNCLG9CQUFvQixDQUN4QyxZQUFZLEVBQUUsZ0JBQWdCLEVBQzlCLFNBQVMsRUFBRTtJQUFFLGlCQUFpQixFQUFFLFVBQVUsQ0FBQztJQUFDLGFBQWEsQ0FBQyxFQUFFLFVBQVUsQ0FBQTtDQUFFLEdBQ3ZFLE9BQU8sQ0FDUixJQUFJLENBQUMsaUJBQWlCLEVBQUUsc0JBQXNCLENBQUMsR0FBRztJQUNoRCxZQUFZLEVBQUUsTUFBTSxDQUFDO0lBQ3JCLGFBQWEsRUFBRSxNQUFNLENBQUM7SUFDdEIsYUFBYSxFQUFFLE1BQU0sQ0FBQztJQUN0QixzQkFBc0IsRUFBRSxLQUFLLE1BQU0sRUFBRSxDQUFDO0NBQ3ZDLENBQ0YsQ0F1R0EifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAK/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,qDAAqD;AACrD,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE;IAAE,iBAAiB,EAAE,UAAU,CAAC;IAAC,aAAa,CAAC,EAAE,UAAU,CAAA;CAAE,GACvE,OAAO,CACR,IAAI,CAAC,iBAAiB,EAAE,sBAAsB,CAAC,GAAG;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,KAAK,MAAM,EAAE,CAAC;CACvC,CACF,CAuGA"}
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAa,KAAK,KAAK,EAAE,MAAM,MAAM,CAAC;AAE7C,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAK/E,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE/D;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,GAAG,SAAS,CAAC,CASpH;AAmBD;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAkBtE;AAUD,qDAAqD;AACrD,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE;IAAE,iBAAiB,EAAE,UAAU,CAAC;IAAC,aAAa,CAAC,EAAE,UAAU,CAAA;CAAE,GACvE,OAAO,CACR,IAAI,CAAC,iBAAiB,EAAE,sBAAsB,CAAC,GAAG;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,KAAK,MAAM,EAAE,CAAC;CACvC,CACF,CAuGA"}
package/dest/queries.js CHANGED
@@ -1,9 +1,68 @@
1
1
  import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { BaseError } from 'viem';
2
3
  import { DefaultL1ContractsConfig } from './config.js';
3
4
  import { ReadOnlyGovernanceContract } from './contracts/governance.js';
4
5
  import { GovernanceProposerContract } from './contracts/governance_proposer.js';
5
6
  import { InboxContract } from './contracts/inbox.js';
6
7
  import { RollupContract } from './contracts/rollup.js';
8
+ /**
9
+ * Returns the L1 finalized block, or `undefined` if the chain does not yet have one
10
+ * (common on freshly started devnets). Rethrows any other RPC error.
11
+ */ export async function getFinalizedL1Block(client) {
12
+ try {
13
+ return await client.getBlock({
14
+ blockTag: 'finalized',
15
+ includeTransactions: false
16
+ });
17
+ } catch (err) {
18
+ if (isFinalizedBlockTagNotFoundError(err)) {
19
+ return undefined;
20
+ }
21
+ throw err;
22
+ }
23
+ }
24
+ // Error messages returned by popular Ethereum execution clients when
25
+ // eth_getBlockByNumber / eth_call is called with blockTag "finalized" or
26
+ // "safe" and no such block has been produced yet:
27
+ //
28
+ // geth "finalized block not found"
29
+ // "safe block not found"
30
+ // reth "block not found: finalized"
31
+ // "block not found: safe"
32
+ // nethermind "Unknown block error" (same for both tags)
33
+ // besu "Unknown block"
34
+ // erigon 'block "finalized" not available (head block: N)'
35
+ // 'block "safe" not available (head block: N)'
36
+ //
37
+ // A combined regex covers all five:
38
+ const FINALIZED_BLOCK_TAG_NOT_FOUND_MESSAGE_RE = /(finalized|safe) block not found|block not found: (finalized|safe)|unknown block|block "(finalized|safe)" not available/i;
39
+ /**
40
+ * Returns true if the error originates from an RPC call that failed because
41
+ * the "finalized" (or "safe") block tag is not yet available on the chain.
42
+ */ export function isFinalizedBlockTagNotFoundError(err) {
43
+ if (!err) {
44
+ return false;
45
+ }
46
+ if (err instanceof BaseError) {
47
+ const hit = err.walk((e)=>matchesFinalizedBlockTagNotFound(e));
48
+ if (hit) {
49
+ return true;
50
+ }
51
+ }
52
+ for(let cur = err, i = 0; cur && i < 10; cur = cur.cause, i++){
53
+ if (matchesFinalizedBlockTagNotFound(cur)) {
54
+ return true;
55
+ }
56
+ }
57
+ return false;
58
+ }
59
+ function matchesFinalizedBlockTagNotFound(e) {
60
+ if (!e) {
61
+ return false;
62
+ }
63
+ const text = `${e.details ?? ''} ${e.message ?? ''} ${e.shortMessage ?? ''}`;
64
+ return FINALIZED_BLOCK_TAG_NOT_FOUND_MESSAGE_RE.test(text);
65
+ }
7
66
  /** Reads the L1ContractsConfig from L1 contracts. */ export async function getL1ContractsConfig(publicClient, addresses) {
8
67
  const governance = new ReadOnlyGovernanceContract(addresses.governanceAddress.toString(), publicClient);
9
68
  const governanceProposerAddress = await governance.getGovernanceProposerAddress();
@@ -33,8 +92,8 @@ import { RollupContract } from './contracts/rollup.js';
33
92
  slasherProposer?.getRoundSize() ?? 0n,
34
93
  slasherProposer?.getLifetimeInRounds() ?? 0n,
35
94
  slasherProposer?.getExecutionDelayInRounds() ?? 0n,
36
- slasherProposer?.type === 'tally' ? slasherProposer.getSlashOffsetInRounds() : 0n,
37
- slasherProposer?.type === 'tally' ? slasherProposer.getSlashingAmounts() : [
95
+ slasherProposer?.getSlashOffsetInRounds() ?? 0n,
96
+ slasherProposer?.getSlashingAmounts() ?? [
38
97
  0n,
39
98
  0n,
40
99
  0n
@@ -74,7 +133,7 @@ import { RollupContract } from './contracts/rollup.js';
74
133
  rollupVersion: Number(rollupVersion),
75
134
  genesisArchiveTreeRoot: genesisArchiveTreeRoot.toString(),
76
135
  exitDelaySeconds: Number(exitDelay),
77
- slasherFlavor: slasherProposer?.type ?? 'tally',
136
+ slasherEnabled: !!slasherProposer,
78
137
  slashingOffsetInRounds: Number(slashingOffsetInRounds),
79
138
  slashAmountSmall: slashingAmounts[0],
80
139
  slashAmountMedium: slashingAmounts[1],
@@ -0,0 +1,19 @@
1
+ import type { Logger } from '@aztec/foundation/log';
2
+ import type { ExtendedViemWalletClient } from '../types.js';
3
+ /**
4
+ * Warms both KZG trusted setups in parallel for tests against a local anvil:
5
+ * - anvil's own setup, loaded lazily when it first validates a blob sidecar in `eth_sendRawTransaction`
6
+ * - our `@crate-crypto/node-eth-kzg` singleton (`getKzg()`, a ~2.2s synchronous precomp build)
7
+ *
8
+ * Without this, the first checkpoint publish pays both serially (~4.4s). The recipe does all RPC round
9
+ * trips up front, fires a single bare raw send carrying a fake (garbage) blob sidecar that anvil rejects
10
+ * after loading its trusted setup, yields once to flush the socket write, then synchronously builds our
11
+ * own precomp tables while anvil warms in parallel. The fake tx is rejected at admission, so it never
12
+ * enters the pool, mines no block, and burns no nonce — sending it from the passed client is harmless.
13
+ *
14
+ * Best-effort: any failure is debug-logged and swallowed, leaving lazy init as the fallback. Never throws.
15
+ *
16
+ * @param l1Client - The L1 client whose account sends the (rejected) warm-up blob tx.
17
+ */
18
+ export declare function warmBlobKzg(l1Client: ExtendedViemWalletClient, logger?: Logger): Promise<void>;
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvYl9remdfd2FybXVwLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdC9ibG9iX2t6Z193YXJtdXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFcEQsT0FBTyxLQUFLLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFNUQ7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCx3QkFBc0IsV0FBVyxDQUFDLFFBQVEsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLENBQUMsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQTRDcEcifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blob_kzg_warmup.d.ts","sourceRoot":"","sources":["../../src/test/blob_kzg_warmup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE5D;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,wBAAwB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CpG"}
@@ -0,0 +1,64 @@
1
+ import { getBytesPerBlob, getBytesPerCommitment, getKzg } from '@aztec/blob-lib';
2
+ /**
3
+ * Warms both KZG trusted setups in parallel for tests against a local anvil:
4
+ * - anvil's own setup, loaded lazily when it first validates a blob sidecar in `eth_sendRawTransaction`
5
+ * - our `@crate-crypto/node-eth-kzg` singleton (`getKzg()`, a ~2.2s synchronous precomp build)
6
+ *
7
+ * Without this, the first checkpoint publish pays both serially (~4.4s). The recipe does all RPC round
8
+ * trips up front, fires a single bare raw send carrying a fake (garbage) blob sidecar that anvil rejects
9
+ * after loading its trusted setup, yields once to flush the socket write, then synchronously builds our
10
+ * own precomp tables while anvil warms in parallel. The fake tx is rejected at admission, so it never
11
+ * enters the pool, mines no block, and burns no nonce — sending it from the passed client is harmless.
12
+ *
13
+ * Best-effort: any failure is debug-logged and swallowed, leaving lazy init as the fallback. Never throws.
14
+ *
15
+ * @param l1Client - The L1 client whose account sends the (rejected) warm-up blob tx.
16
+ */ export async function warmBlobKzg(l1Client, logger) {
17
+ try {
18
+ // A pure-JS fake kzg: returns deterministic garbage of the correct lengths (commitment and proof are
19
+ // both 48 bytes). It makes viem build a syntactically valid sidecar without initializing any native
20
+ // module, so anvil loads its trusted setup to validate the (invalid) proof and then rejects the tx.
21
+ const fakeKzg = {
22
+ blobToKzgCommitment: ()=>{
23
+ const commitment = new Uint8Array(getBytesPerCommitment());
24
+ commitment.fill(0xab);
25
+ commitment[0] = 0xc0;
26
+ return commitment;
27
+ },
28
+ computeBlobKzgProof: ()=>{
29
+ const proof = new Uint8Array(getBytesPerCommitment());
30
+ proof.fill(0xcd);
31
+ proof[0] = 0xc0;
32
+ return proof;
33
+ }
34
+ };
35
+ // All RPC round trips (nonce, fees, gas) happen here, so only a single socket write remains to flush.
36
+ const prepared = await l1Client.prepareTransactionRequest({
37
+ blobs: [
38
+ new Uint8Array(getBytesPerBlob())
39
+ ],
40
+ kzg: fakeKzg,
41
+ to: '0x0000000000000000000000000000000000000000',
42
+ value: 0n,
43
+ maxFeePerBlobGas: 1_000_000_000_000n
44
+ });
45
+ const serialized = await l1Client.signTransaction(prepared);
46
+ // Fire the raw send without awaiting and swallow the expected rejection.
47
+ const sent = l1Client.request({
48
+ method: 'eth_sendRawTransaction',
49
+ params: [
50
+ serialized
51
+ ]
52
+ }).catch(()=>{});
53
+ // Flush the single socket write so anvil receives the tx and starts loading its trusted setup in its
54
+ // own process before we block the event loop below.
55
+ await new Promise((resolve)=>setImmediate(resolve));
56
+ // Synchronously build our precomp tables (~2.2s, event-loop-blocking); anvil warms in parallel.
57
+ getKzg();
58
+ await sent;
59
+ } catch (err) {
60
+ logger?.debug('Failed to warm blob KZG; falling back to lazy init', {
61
+ err
62
+ });
63
+ }
64
+ }