@aztec/ethereum 0.0.1-commit.f504929 → 0.0.1-commit.f5a9928

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 +27 -3
  2. package/dest/client.d.ts.map +1 -1
  3. package/dest/client.js +63 -8
  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 +127 -12
  31. package/dest/contracts/multicall.d.ts.map +1 -1
  32. package/dest/contracts/multicall.js +201 -94
  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 +5433 -30
  37. package/dest/contracts/rollup.d.ts.map +1 -1
  38. package/dest/contracts/rollup.js +436 -102
  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 +5 -5
  60. package/dest/l1_reader.d.ts.map +1 -1
  61. package/dest/l1_reader.js +9 -7
  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 +57 -23
  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 +34 -8
  73. package/dest/publisher_manager.d.ts.map +1 -1
  74. package/dest/publisher_manager.js +119 -8
  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 +55 -4
  82. package/dest/test/chain_monitor.d.ts.map +1 -1
  83. package/dest/test/chain_monitor.js +104 -3
  84. package/dest/test/eth_cheat_codes.d.ts +31 -6
  85. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  86. package/dest/test/eth_cheat_codes.js +67 -44
  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 +15 -1
  97. package/dest/test/start_anvil.d.ts.map +1 -1
  98. package/dest/test/start_anvil.js +58 -7
  99. package/dest/utils.d.ts +9 -2
  100. package/dest/utils.d.ts.map +1 -1
  101. package/dest/utils.js +59 -24
  102. package/package.json +6 -6
  103. package/src/client.ts +72 -2
  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 +243 -105
  114. package/src/contracts/outbox.ts +42 -8
  115. package/src/contracts/rollup.ts +487 -103
  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 +17 -10
  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 +57 -17
  127. package/src/l1_tx_utils/tx_delayer.ts +16 -7
  128. package/src/publisher_manager.ts +143 -12
  129. package/src/queries.ts +70 -4
  130. package/src/test/blob_kzg_warmup.ts +65 -0
  131. package/src/test/chain_monitor.ts +148 -3
  132. package/src/test/eth_cheat_codes.ts +63 -47
  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 +71 -8
  137. package/src/utils.ts +56 -29
  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;
@@ -78,9 +96,10 @@ export class ReadOnlyL1TxUtils {
78
96
  const numBlocks = Math.ceil(gasConfig.stallTimeMs / BLOCK_TIME_MS);
79
97
  for(let i = 0; i < numBlocks; i++){
80
98
  // each block can go up 12.5% from previous baseFee
81
- maxFeePerGas = maxFeePerGas * (1_000n + 125n) / 1_000n;
99
+ // ceil, (a+b-1)/b, to avoid truncation at small values (e.g. 1 wei blob base fee)
100
+ maxFeePerGas = (maxFeePerGas * (1_000n + 125n) + 999n) / 1_000n;
82
101
  // same for blob gas fee
83
- maxFeePerBlobGas = maxFeePerBlobGas * (1_000n + 125n) / 1_000n;
102
+ maxFeePerBlobGas = (maxFeePerBlobGas * (1_000n + 125n) + 999n) / 1_000n;
84
103
  }
85
104
  if (attempt > 0) {
86
105
  const configBump = gasConfig.priorityFeeRetryBumpPercentage ?? defaultL1TxUtilsConfig.priorityFeeRetryBumpPercentage;
@@ -163,13 +182,16 @@ export class ReadOnlyL1TxUtils {
163
182
  };
164
183
  let initialEstimate = 0n;
165
184
  if (_blobInputs) {
166
- // @note requests with blobs also require maxFeePerBlobGas to be set
185
+ // @note requests with blobs also require maxFeePerBlobGas to be set.
186
+ // Use 2x buffer for maxFeePerBlobGas to avoid stale fees and to pass EIP-4844 validation (even if it is a gas estimation call).
187
+ // 1. maxFeePerBlobGas >= blobBaseFee
188
+ // 2. account balance >= gas * maxFeePerGas + maxFeePerBlobGas * blobCount + value
167
189
  const gasPrice = await this.getGasPrice(gasConfig, true, 0);
168
190
  initialEstimate = await this.client.estimateGas({
169
191
  account,
170
192
  ...request,
171
193
  ..._blobInputs,
172
- maxFeePerBlobGas: gasPrice.maxFeePerBlobGas,
194
+ maxFeePerBlobGas: gasPrice.maxFeePerBlobGas * 2n,
173
195
  gas: MAX_L1_TX_LIMIT,
174
196
  blockTag: 'latest'
175
197
  });
@@ -264,8 +286,7 @@ export class ReadOnlyL1TxUtils {
264
286
  return await this._simulate(call, blockOverrides, stateOverrides, gasConfig, abi);
265
287
  }
266
288
  async _simulate(call, blockOverrides = {}, stateOverrides = [], gasConfig, abi) {
267
- try {
268
- const result = await this.client.simulateBlocks({
289
+ const simulateBlocks = ()=>this.client.simulateBlocks({
269
290
  validation: false,
270
291
  blocks: [
271
292
  {
@@ -277,23 +298,13 @@ export class ReadOnlyL1TxUtils {
277
298
  }
278
299
  ]
279
300
  });
280
- if (result[0].calls[0].status === 'failure') {
281
- this.logger?.error('L1 transaction simulation failed', result[0].calls[0].error);
282
- const decodedError = decodeErrorResult({
283
- abi,
284
- data: result[0].calls[0].data
285
- });
286
- throw new Error(`L1 transaction simulation failed with error ${decodedError.errorName}(${decodedError.args?.join(',')})`);
287
- }
288
- this.logger?.debug(`L1 transaction simulation succeeded`, {
289
- ...result[0].calls[0]
290
- });
291
- return {
292
- gasUsed: result[0].gasUsed,
293
- result: result[0].calls[0].data
294
- };
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();
295
306
  } catch (err) {
296
- if (err instanceof MethodNotFoundRpcError || err instanceof MethodNotSupportedRpcError) {
307
+ if (getErrorCause(err, MethodNotFoundRpcError) || getErrorCause(err, MethodNotSupportedRpcError)) {
297
308
  if (gasConfig.fallbackGasEstimate) {
298
309
  this.logger?.warn(`Node does not support eth_simulateV1 API. Using fallback gas estimate: ${gasConfig.fallbackGasEstimate}`);
299
310
  return {
@@ -303,8 +314,31 @@ export class ReadOnlyL1TxUtils {
303
314
  }
304
315
  this.logger?.error('Node does not support eth_simulateV1 API');
305
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
+ }
306
325
  throw err;
307
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
+ };
308
342
  }
309
343
  bumpGasLimit(gasLimit, _gasConfig) {
310
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,16 +1,42 @@
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;
5
+ /** Config accepted by PublisherManager. */
6
+ type PublisherManagerConfig = {
7
+ publisherAllowInvalidStates?: boolean;
8
+ publisherFundingThreshold?: bigint;
9
+ publisherFundingAmount?: bigint;
10
+ };
4
11
  export declare class PublisherManager<UtilsType extends L1TxUtils = L1TxUtils> {
5
- private publishers;
12
+ protected publishers: UtilsType[];
6
13
  private log;
7
14
  private config;
8
- constructor(publishers: UtilsType[], config: {
9
- publisherAllowInvalidStates?: boolean;
10
- }, bindings?: LoggerBindings);
11
- /** Loads the state of all publishers and resumes monitoring any pending txs */
12
- loadState(): Promise<void>;
15
+ private static readonly FUNDING_CHECK_INTERVAL_MS;
16
+ protected funder?: UtilsType;
17
+ protected readonly fundingPromise?: RunningPromise;
18
+ private started;
19
+ constructor(publishers: UtilsType[], config: PublisherManagerConfig, opts?: {
20
+ bindings?: LoggerBindings;
21
+ funder?: UtilsType;
22
+ });
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
+ */
30
+ start(): Promise<void>;
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
+ */
36
+ stop(): Promise<void>;
13
37
  getAvailablePublisher(filter?: PublisherFilter<UtilsType>): Promise<UtilsType>;
14
- interrupt(): void;
38
+ private triggerFundingIfNeeded;
39
+ private fundPublishers;
15
40
  }
16
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaGVyX21hbmFnZXIuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wdWJsaXNoZXJfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQWUsS0FBSyxjQUFjLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFFdkYsT0FBTyxFQUFFLFNBQVMsRUFBZ0IsTUFBTSx3QkFBd0IsQ0FBQztBQXdCakUsTUFBTSxNQUFNLGVBQWUsQ0FBQyxTQUFTLFNBQVMsU0FBUyxJQUFJLENBQUMsS0FBSyxFQUFFLFNBQVMsS0FBSyxPQUFPLENBQUM7QUFFekYscUJBQWEsZ0JBQWdCLENBQUMsU0FBUyxTQUFTLFNBQVMsR0FBRyxTQUFTO0lBS2pFLE9BQU8sQ0FBQyxVQUFVO0lBSnBCLE9BQU8sQ0FBQyxHQUFHLENBQVM7SUFDcEIsT0FBTyxDQUFDLE1BQU0sQ0FBNEM7SUFFMUQsWUFDVSxVQUFVLEVBQUUsU0FBUyxFQUFFLEVBQy9CLE1BQU0sRUFBRTtRQUFFLDJCQUEyQixDQUFDLEVBQUUsT0FBTyxDQUFBO0tBQUUsRUFDakQsUUFBUSxDQUFDLEVBQUUsY0FBYyxFQU0xQjtJQUVELCtFQUErRTtJQUNsRSxTQUFTLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUV0QztJQVFZLHFCQUFxQixDQUFDLE1BQU0sR0FBRSxlQUFlLENBQUMsU0FBUyxDQUFjLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQStDdEc7SUFFTSxTQUFTLFNBRWY7Q0FDRiJ9
41
+ export {};
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;AAEvF,OAAO,EAAE,SAAS,EAAgB,MAAM,wBAAwB,CAAC;AAwBjE,MAAM,MAAM,eAAe,CAAC,SAAS,SAAS,SAAS,IAAI,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;AAEzF,qBAAa,gBAAgB,CAAC,SAAS,SAAS,SAAS,GAAG,SAAS;IAKjE,OAAO,CAAC,UAAU;IAJpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAA4C;IAE1D,YACU,UAAU,EAAE,SAAS,EAAE,EAC/B,MAAM,EAAE;QAAE,2BAA2B,CAAC,EAAE,OAAO,CAAA;KAAE,EACjD,QAAQ,CAAC,EAAE,cAAc,EAM1B;IAED,+EAA+E;IAClE,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAEtC;IAQY,qBAAqB,CAAC,MAAM,GAAE,eAAe,CAAC,SAAS,CAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CA+CtG;IAEM,SAAS,SAEf;CACF"}
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"}
@@ -1,5 +1,7 @@
1
1
  import { pick } from '@aztec/foundation/collection';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
+ import { RunningPromise } from '@aztec/foundation/running-promise';
4
+ import { Multicall3 } from './contracts/multicall.js';
3
5
  import { TxUtilsState } from './l1_tx_utils/index.js';
4
6
  // Defines the order in which we prioritise publishers based on their state (first is better)
5
7
  const sortOrder = [
@@ -25,15 +27,72 @@ export class PublisherManager {
25
27
  publishers;
26
28
  log;
27
29
  config;
28
- constructor(publishers, config, bindings){
30
+ static FUNDING_CHECK_INTERVAL_MS = 2 * 60 * 1000;
31
+ funder;
32
+ fundingPromise;
33
+ started;
34
+ constructor(publishers, config, opts){
29
35
  this.publishers = publishers;
30
- this.log = createLogger('publisher:manager', bindings);
36
+ this.started = false;
37
+ this.funder = opts?.funder;
38
+ this.log = createLogger('publisher:manager', opts?.bindings);
31
39
  this.log.info(`PublisherManager initialized with ${publishers.length} publishers.`);
32
40
  this.publishers = publishers;
33
- this.config = pick(config, 'publisherAllowInvalidStates');
41
+ this.config = pick(config, 'publisherAllowInvalidStates', 'publisherFundingThreshold', 'publisherFundingAmount');
42
+ const hasThreshold = this.config.publisherFundingThreshold !== undefined;
43
+ const hasAmount = this.config.publisherFundingAmount !== undefined;
44
+ if (hasThreshold !== hasAmount) {
45
+ this.log.warn(`Incomplete funding config: both publisherFundingThreshold and publisherFundingAmount must be set`);
46
+ }
47
+ if (this.funder) {
48
+ const funderAddress = this.funder.getSenderAddress();
49
+ if (publishers.some((p)=>p.getSenderAddress().equals(funderAddress))) {
50
+ this.log.error(`Funding account ${funderAddress} is also a publisher, disabling funding to avoid self-funding`);
51
+ this.funder = undefined;
52
+ }
53
+ }
54
+ if (this.funder && hasThreshold && hasAmount) {
55
+ this.fundingPromise = new RunningPromise(()=>this.triggerFundingIfNeeded(), this.log, PublisherManager.FUNDING_CHECK_INTERVAL_MS);
56
+ }
34
57
  }
35
- /** Loads the state of all publishers and resumes monitoring any pending txs */ async loadState() {
36
- await Promise.all(this.publishers.map((pub)=>pub.loadStateAndResumeMonitoring()));
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();
73
+ await Promise.all([
74
+ ...this.publishers.map((pub)=>pub.loadStateAndResumeMonitoring()),
75
+ this.funder?.loadStateAndResumeMonitoring()
76
+ ]);
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;
80
+ }
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;
87
+ await this.fundingPromise?.stop();
88
+ this.publishers.forEach((pub)=>pub.interrupt());
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
+ ]);
37
96
  }
38
97
  // Finds and prioritises available publishers based on
39
98
  // 1. Validity as per the provided filter function
@@ -67,8 +126,16 @@ export class PublisherManager {
67
126
  publisher: pub
68
127
  };
69
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
+ }
70
137
  // Sort based on state, then balance, then time since last use
71
- const sortedPublishers = publishersWithBalance.sort((a, b)=>{
138
+ const sortedPublishers = fundedPublishers.sort((a, b)=>{
72
139
  const stateComparison = sortOrder.indexOf(a.publisher.state) - sortOrder.indexOf(b.publisher.state);
73
140
  if (stateComparison !== 0) {
74
141
  return stateComparison;
@@ -82,7 +149,51 @@ export class PublisherManager {
82
149
  });
83
150
  return sortedPublishers[0].publisher;
84
151
  }
85
- interrupt() {
86
- this.publishers.forEach((pub)=>pub.interrupt());
152
+ /** Check all publisher balances and fund those below threshold. */ async triggerFundingIfNeeded() {
153
+ const { funder, config } = this;
154
+ if (!funder || config.publisherFundingThreshold === undefined || config.publisherFundingAmount === undefined) {
155
+ return;
156
+ }
157
+ const allBalances = await Promise.all(this.publishers.map(async (pub)=>({
158
+ balance: await pub.getSenderBalance(),
159
+ publisher: pub
160
+ })));
161
+ const lowBalance = allBalances.filter((p)=>p.balance < config.publisherFundingThreshold);
162
+ if (lowBalance.length === 0) {
163
+ return;
164
+ }
165
+ const fundingAmount = config.publisherFundingAmount;
166
+ const funderBalance = await funder.getSenderBalance();
167
+ if (funderBalance < 10n * fundingAmount) {
168
+ this.log.warn(`Funding account balance is low`, {
169
+ funderBalance,
170
+ threshold: 10n * fundingAmount
171
+ });
172
+ }
173
+ const affordableCount = Number(funderBalance / fundingAmount);
174
+ if (affordableCount === 0) {
175
+ this.log.error(`Funding account balance too low to fund any publisher`, {
176
+ funderBalance,
177
+ fundingAmount
178
+ });
179
+ return;
180
+ }
181
+ if (affordableCount < lowBalance.length) {
182
+ this.log.warn(`Funder can only afford ${affordableCount}/${lowBalance.length} publishers`, {
183
+ funderBalance,
184
+ fundingAmount
185
+ });
186
+ }
187
+ const toFund = lowBalance.slice(0, affordableCount).map((p)=>p.publisher);
188
+ await this.fundPublishers(toFund);
189
+ }
190
+ /** Fund publishers via a single Multicall3 aggregate3Value transaction. */ async fundPublishers(publishers) {
191
+ const fundingAmount = this.config.publisherFundingAmount;
192
+ const calls = publishers.map((pub)=>({
193
+ to: pub.getSenderAddress().toString(),
194
+ value: fundingAmount
195
+ }));
196
+ await Multicall3.forwardValue(calls, this.funder, this.log);
197
+ this.log.info(`Funded ${publishers.length} publishers`);
87
198
  }
88
199
  }
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"}