@aztec/stdlib 5.0.0-nightly.20260611 → 5.0.0-nightly.20260613

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 (123) hide show
  1. package/dest/block/l2_block_source.d.ts +7 -1
  2. package/dest/block/l2_block_source.d.ts.map +1 -1
  3. package/dest/block/l2_block_stream/interfaces.d.ts +44 -8
  4. package/dest/block/l2_block_stream/interfaces.d.ts.map +1 -1
  5. package/dest/block/l2_block_stream/l2_block_stream.d.ts +1 -1
  6. package/dest/block/l2_block_stream/l2_block_stream.d.ts.map +1 -1
  7. package/dest/block/l2_block_stream/l2_block_stream.js +13 -4
  8. package/dest/block/l2_block_stream/l2_tips_memory_store.d.ts +6 -12
  9. package/dest/block/l2_block_stream/l2_tips_memory_store.d.ts.map +1 -1
  10. package/dest/block/l2_block_stream/l2_tips_memory_store.js +8 -32
  11. package/dest/block/l2_block_stream/l2_tips_store_base.d.ts +9 -18
  12. package/dest/block/l2_block_stream/l2_tips_store_base.d.ts.map +1 -1
  13. package/dest/block/l2_block_stream/l2_tips_store_base.js +52 -58
  14. package/dest/block/test/l2_tips_store_test_suite.d.ts +1 -1
  15. package/dest/block/test/l2_tips_store_test_suite.d.ts.map +1 -1
  16. package/dest/block/test/l2_tips_store_test_suite.js +202 -34
  17. package/dest/config/index.d.ts +2 -1
  18. package/dest/config/index.d.ts.map +1 -1
  19. package/dest/config/index.js +1 -0
  20. package/dest/config/network-consensus-config.d.ts +72 -0
  21. package/dest/config/network-consensus-config.d.ts.map +1 -0
  22. package/dest/config/network-consensus-config.js +231 -0
  23. package/dest/config/sequencer-config.d.ts +3 -1
  24. package/dest/config/sequencer-config.d.ts.map +1 -1
  25. package/dest/config/sequencer-config.js +5 -4
  26. package/dest/contract/interfaces/node-info.d.ts +11 -1
  27. package/dest/contract/interfaces/node-info.d.ts.map +1 -1
  28. package/dest/contract/interfaces/node-info.js +7 -1
  29. package/dest/gas/gas_settings.d.ts +7 -13
  30. package/dest/gas/gas_settings.d.ts.map +1 -1
  31. package/dest/gas/gas_settings.js +9 -16
  32. package/dest/gas/index.d.ts +2 -1
  33. package/dest/gas/index.d.ts.map +1 -1
  34. package/dest/gas/index.js +1 -0
  35. package/dest/gas/tx_gas_limits.d.ts +72 -0
  36. package/dest/gas/tx_gas_limits.d.ts.map +1 -0
  37. package/dest/gas/tx_gas_limits.js +85 -0
  38. package/dest/interfaces/aztec-node-admin.d.ts +18 -17
  39. package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
  40. package/dest/interfaces/aztec-node-admin.js +1 -1
  41. package/dest/interfaces/aztec-node-debug.d.ts +15 -2
  42. package/dest/interfaces/aztec-node-debug.d.ts.map +1 -1
  43. package/dest/interfaces/aztec-node-debug.js +9 -1
  44. package/dest/interfaces/aztec-node.d.ts +40 -11
  45. package/dest/interfaces/aztec-node.d.ts.map +1 -1
  46. package/dest/interfaces/aztec-node.js +42 -5
  47. package/dest/interfaces/block-builder.d.ts +3 -1
  48. package/dest/interfaces/block-builder.d.ts.map +1 -1
  49. package/dest/interfaces/client.d.ts +2 -1
  50. package/dest/interfaces/client.d.ts.map +1 -1
  51. package/dest/interfaces/configs.d.ts +12 -6
  52. package/dest/interfaces/configs.d.ts.map +1 -1
  53. package/dest/interfaces/configs.js +2 -1
  54. package/dest/interfaces/get_tx_by_hash_options.d.ts +9 -0
  55. package/dest/interfaces/get_tx_by_hash_options.d.ts.map +1 -0
  56. package/dest/interfaces/get_tx_by_hash_options.js +4 -0
  57. package/dest/interfaces/p2p.d.ts +32 -8
  58. package/dest/interfaces/p2p.d.ts.map +1 -1
  59. package/dest/interfaces/p2p.js +12 -2
  60. package/dest/interfaces/proving-job.d.ts +70 -70
  61. package/dest/interfaces/validator.d.ts +3 -3
  62. package/dest/interfaces/validator.d.ts.map +1 -1
  63. package/dest/interfaces/validator.js +1 -1
  64. package/dest/tests/factories.d.ts +1 -1
  65. package/dest/tests/factories.d.ts.map +1 -1
  66. package/dest/tests/factories.js +4 -1
  67. package/dest/tests/mocks.d.ts +1 -1
  68. package/dest/tests/mocks.d.ts.map +1 -1
  69. package/dest/tests/mocks.js +3 -2
  70. package/dest/timetable/budgets.d.ts +4 -2
  71. package/dest/timetable/budgets.d.ts.map +1 -1
  72. package/dest/timetable/budgets.js +2 -1
  73. package/dest/timetable/build_proposer_timetable.d.ts +21 -0
  74. package/dest/timetable/build_proposer_timetable.d.ts.map +1 -0
  75. package/dest/timetable/build_proposer_timetable.js +17 -0
  76. package/dest/timetable/consensus_timetable.d.ts +5 -7
  77. package/dest/timetable/consensus_timetable.d.ts.map +1 -1
  78. package/dest/timetable/consensus_timetable.js +6 -8
  79. package/dest/timetable/index.d.ts +2 -1
  80. package/dest/timetable/index.d.ts.map +1 -1
  81. package/dest/timetable/index.js +1 -0
  82. package/dest/timetable/proposer_timetable.d.ts +18 -24
  83. package/dest/timetable/proposer_timetable.d.ts.map +1 -1
  84. package/dest/timetable/proposer_timetable.js +26 -55
  85. package/dest/tx/fee_provider.d.ts +2 -2
  86. package/dest/tx/fee_provider.d.ts.map +1 -1
  87. package/dest/tx/validator/error_texts.d.ts +2 -2
  88. package/dest/tx/validator/error_texts.d.ts.map +1 -1
  89. package/dest/tx/validator/error_texts.js +1 -1
  90. package/package.json +8 -8
  91. package/src/block/l2_block_source.ts +7 -0
  92. package/src/block/l2_block_stream/interfaces.ts +39 -7
  93. package/src/block/l2_block_stream/l2_block_stream.ts +21 -3
  94. package/src/block/l2_block_stream/l2_tips_memory_store.ts +12 -41
  95. package/src/block/l2_block_stream/l2_tips_store_base.ts +63 -93
  96. package/src/block/test/l2_tips_store_test_suite.ts +197 -24
  97. package/src/config/index.ts +1 -0
  98. package/src/config/network-consensus-config.ts +302 -0
  99. package/src/config/sequencer-config.ts +7 -5
  100. package/src/contract/interfaces/node-info.ts +11 -0
  101. package/src/gas/README.md +92 -0
  102. package/src/gas/gas_settings.ts +11 -21
  103. package/src/gas/index.ts +1 -0
  104. package/src/gas/tx_gas_limits.ts +123 -0
  105. package/src/interfaces/aztec-node-admin.ts +1 -1
  106. package/src/interfaces/aztec-node-debug.ts +17 -2
  107. package/src/interfaces/aztec-node.ts +74 -13
  108. package/src/interfaces/block-builder.ts +2 -0
  109. package/src/interfaces/client.ts +1 -0
  110. package/src/interfaces/configs.ts +10 -6
  111. package/src/interfaces/get_tx_by_hash_options.ts +14 -0
  112. package/src/interfaces/p2p.ts +21 -8
  113. package/src/interfaces/validator.ts +5 -5
  114. package/src/tests/factories.ts +7 -1
  115. package/src/tests/mocks.ts +7 -2
  116. package/src/timetable/README.md +10 -2
  117. package/src/timetable/budgets.ts +5 -2
  118. package/src/timetable/build_proposer_timetable.ts +42 -0
  119. package/src/timetable/consensus_timetable.ts +8 -14
  120. package/src/timetable/index.ts +1 -0
  121. package/src/timetable/proposer_timetable.ts +37 -61
  122. package/src/tx/fee_provider.ts +1 -1
  123. package/src/tx/validator/error_texts.ts +2 -1
@@ -17,18 +17,16 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '../l2_block_source.js';
17
17
  }
18
18
  getL2Tips() {
19
19
  return this.runInTransaction(async ()=>{
20
- const [proposedBlockId, finalizedBlockId, provenBlockId, checkpointedBlockId, proposedCheckpointBlockId] = await Promise.all([
20
+ const [proposedBlockId, finalizedBlockId, provenBlockId, checkpointedBlockId] = await Promise.all([
21
21
  this.getBlockId('proposed'),
22
22
  this.getBlockId('finalized'),
23
23
  this.getBlockId('proven'),
24
- this.getBlockId('checkpointed'),
25
- this.getBlockId('proposedCheckpoint')
24
+ this.getBlockId('checkpointed')
26
25
  ]);
27
- const [finalizedCheckpointId, provenCheckpointId, checkpointedCheckpointId, proposedCheckpointId] = await Promise.all([
26
+ const [finalizedCheckpointId, provenCheckpointId, checkpointedCheckpointId] = await Promise.all([
28
27
  this.getCheckpointId('finalized'),
29
28
  this.getCheckpointId('proven'),
30
- this.getCheckpointId('checkpointed'),
31
- this.getCheckpointId('proposedCheckpoint')
29
+ this.getCheckpointId('checkpointed')
32
30
  ]);
33
31
  return {
34
32
  proposed: proposedBlockId,
@@ -43,10 +41,6 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '../l2_block_source.js';
43
41
  checkpointed: {
44
42
  block: checkpointedBlockId,
45
43
  checkpoint: checkpointedCheckpointId
46
- },
47
- proposedCheckpoint: {
48
- block: proposedCheckpointBlockId,
49
- checkpoint: proposedCheckpointId
50
44
  }
51
45
  };
52
46
  });
@@ -95,25 +89,22 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '../l2_block_source.js';
95
89
  async getCheckpointId(tag) {
96
90
  const blockNumber = await this.getTip(tag);
97
91
  if (blockNumber === undefined || blockNumber === 0) {
98
- return {
99
- number: CheckpointNumber.ZERO,
100
- hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
101
- };
102
- }
103
- const checkpointNumber = await this.getCheckpointNumberForBlock(blockNumber);
104
- if (checkpointNumber === undefined) {
105
- return {
106
- number: CheckpointNumber.ZERO,
107
- hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
108
- };
92
+ return this.genesisCheckpointId();
109
93
  }
110
- const checkpoint = await this.getCheckpoint(checkpointNumber);
111
- if (!checkpoint) {
112
- throw new Error(`Checkpoint not found for checkpoint number ${checkpointNumber}`);
94
+ // The checkpoint id recorded for this cursor when it was last advanced is the single source of truth.
95
+ // The writers (handleChainCheckpointed/Proven/Finalized/Pruned) always record an id alongside any
96
+ // non-genesis cursor advance, so a missing id on a real block is genuine store corruption. Fail loudly
97
+ // rather than silently reporting checkpoint zero, which would drive a checkpoint-replay storm.
98
+ const storedCheckpoint = await this.getTipCheckpoint(tag);
99
+ if (storedCheckpoint !== undefined) {
100
+ return storedCheckpoint;
113
101
  }
102
+ throw new Error(`No checkpoint id recorded for ${tag} tip at block ${blockNumber}; the L2 tips store is corrupted`);
103
+ }
104
+ genesisCheckpointId() {
114
105
  return {
115
- number: checkpointNumber,
116
- hash: checkpoint.checkpoint.hash().toString()
106
+ number: CheckpointNumber.ZERO,
107
+ hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
117
108
  };
118
109
  }
119
110
  async handleBlocksAdded(event) {
@@ -133,14 +124,12 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '../l2_block_source.js';
133
124
  return;
134
125
  }
135
126
  await this.runInTransaction(async ()=>{
127
+ const checkpointId = {
128
+ number: event.checkpoint.checkpoint.number,
129
+ hash: event.checkpoint.checkpoint.hash().toString()
130
+ };
136
131
  await this.saveTag('checkpointed', event.block);
137
- await this.saveCheckpoint(event.checkpoint);
138
- // proposedCheckpoint is always >= checkpointed. If checkpointed has caught up
139
- // or surpassed it, advance proposedCheckpoint to match.
140
- const proposedCheckpointBlock = await this.getBlockId('proposedCheckpoint');
141
- if (event.block.number > proposedCheckpointBlock.number) {
142
- await this.saveTag('proposedCheckpoint', event.block);
143
- }
132
+ await this.setTipCheckpoint('checkpointed', checkpointId);
144
133
  });
145
134
  }
146
135
  async handleChainPruned(event) {
@@ -148,12 +137,32 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '../l2_block_source.js';
148
137
  return;
149
138
  }
150
139
  await this.runInTransaction(async ()=>{
140
+ // A prune is a rollback: the proposed tip moves to the prune target unconditionally, but
141
+ // checkpoint-bearing cursors may only move backward. Forward-advancing them onto an
142
+ // uncheckpointed block leaves them on a block with no recorded checkpoint id, which getCheckpointId
143
+ // would then throw on.
151
144
  await this.saveTag('proposed', event.block);
152
- await this.saveTag('checkpointed', event.block);
153
- await this.saveTag('proposedCheckpoint', event.block);
154
- const storeProven = await this.getBlockId('proven');
155
- if (storeProven.number > event.block.number) {
156
- await this.saveTag('proven', event.block);
145
+ // Clamp each checkpoint-bearing cursor down to its OWN source tip when it leads it. Clamping the proven
146
+ // cursor onto the checkpointed tip would transiently report unproven blocks as proven (the source's proven
147
+ // tip can sit below its checkpointed tip after a proof-tx reorg), until the corrective chain-proven event
148
+ // lands at the end of the same sync iteration. The event carries a valid (block, id) pair for each
149
+ // boundary, so the clamped cursor always resolves to a recorded id. The source guarantees proven <=
150
+ // checkpointed, so clamping each cursor to its own tip preserves the local proven <= checkpointed invariant.
151
+ for (const { tag, sourceTip } of [
152
+ {
153
+ tag: 'checkpointed',
154
+ sourceTip: event.checkpointed
155
+ },
156
+ {
157
+ tag: 'proven',
158
+ sourceTip: event.proven
159
+ }
160
+ ]){
161
+ const current = await this.getTip(tag);
162
+ if (current !== undefined && current > sourceTip.block.number) {
163
+ await this.saveTag(tag, sourceTip.block);
164
+ await this.setTipCheckpoint(tag, sourceTip.checkpoint);
165
+ }
157
166
  }
158
167
  });
159
168
  }
@@ -163,6 +172,7 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '../l2_block_source.js';
163
172
  }
164
173
  await this.runInTransaction(async ()=>{
165
174
  await this.saveTag('proven', event.block);
175
+ await this.setTipCheckpoint('proven', event.checkpoint);
166
176
  });
167
177
  }
168
178
  async handleChainFinalized(event) {
@@ -171,26 +181,19 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '../l2_block_source.js';
171
181
  }
172
182
  await this.runInTransaction(async ()=>{
173
183
  await this.saveTag('finalized', event.block);
174
- const finalizedCheckpointNumber = await this.getCheckpointNumberForBlock(event.block.number);
175
- // Cap the deletion bound at the lowest live tip. This should always be the finalized tip, but
176
- // we have hit bugs where this is not the case. Deleting the block hash, block-to-checkpoint mapping,
177
- // or enclosing checkpoint object for a live tip would dangle subsequent `getBlockId`/`getCheckpointId`
184
+ await this.setTipCheckpoint('finalized', event.checkpoint);
185
+ // Prune block hashes below the lowest live tip. Cap the deletion bound at the lowest live tip rather
186
+ // than the finalized tip alone: this should always be the finalized tip, but we have hit bugs where
187
+ // this is not the case. Deleting the block hash for a live tip would dangle subsequent `getBlockId`
178
188
  // lookups and lock the block stream into an error loop.
179
189
  const tips = await Promise.all([
180
190
  this.getTip('proposed'),
181
- this.getTip('proposedCheckpoint'),
182
191
  this.getTip('checkpointed'),
183
192
  this.getTip('proven')
184
193
  ]);
185
194
  const liveTipBlocks = tips.filter((t)=>t !== undefined && t > 0);
186
195
  const safeBlockBound = BlockNumber(Math.min(event.block.number, ...liveTipBlocks));
187
196
  await this.deleteBlockHashesBefore(safeBlockBound);
188
- await this.deleteBlockToCheckpointBefore(safeBlockBound);
189
- if (finalizedCheckpointNumber !== undefined) {
190
- const tipCheckpoints = await Promise.all(liveTipBlocks.map((b)=>this.getCheckpointNumberForBlock(b)));
191
- const safeCheckpointBound = CheckpointNumber(Math.min(finalizedCheckpointNumber, ...tipCheckpoints.filter((c)=>c !== undefined && c > 0)));
192
- await this.deleteCheckpointsBefore(safeCheckpointBound);
193
- }
194
197
  });
195
198
  }
196
199
  async saveTag(name, block) {
@@ -199,13 +202,4 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '../l2_block_source.js';
199
202
  await this.setBlockHash(block.number, block.hash);
200
203
  }
201
204
  }
202
- async saveCheckpoint(publishedCheckpoint) {
203
- const checkpoint = publishedCheckpoint.checkpoint;
204
- const lastBlock = checkpoint.blocks.at(-1);
205
- // Only store the mapping for the last block since tips only point to checkpoint boundaries
206
- await Promise.all([
207
- this.setCheckpointNumberForBlock(lastBlock.number, checkpoint.number),
208
- this.saveCheckpointData(publishedCheckpoint)
209
- ]);
210
- }
211
205
  }
@@ -1,3 +1,3 @@
1
1
  import type { L2TipsStore } from '../l2_block_stream/index.js';
2
2
  export declare function testL2TipsStore(makeTipsStore: () => Promise<L2TipsStore>): void;
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibDJfdGlwc19zdG9yZV90ZXN0X3N1aXRlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYmxvY2svdGVzdC9sMl90aXBzX3N0b3JlX3Rlc3Rfc3VpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZUEsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFL0Qsd0JBQWdCLGVBQWUsQ0FBQyxhQUFhLEVBQUUsTUFBTSxPQUFPLENBQUMsV0FBVyxDQUFDLFFBOGdCeEUifQ==
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibDJfdGlwc19zdG9yZV90ZXN0X3N1aXRlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYmxvY2svdGVzdC9sMl90aXBzX3N0b3JlX3Rlc3Rfc3VpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZ0JBLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRS9ELHdCQUFnQixlQUFlLENBQUMsYUFBYSxFQUFFLE1BQU0sT0FBTyxDQUFDLFdBQVcsQ0FBQyxRQTByQnhFIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"l2_tips_store_test_suite.d.ts","sourceRoot":"","sources":["../../../src/block/test/l2_tips_store_test_suite.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,QA8gBxE"}
1
+ {"version":3,"file":"l2_tips_store_test_suite.d.ts","sourceRoot":"","sources":["../../../src/block/test/l2_tips_store_test_suite.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,QA0rBxE"}
@@ -62,12 +62,11 @@ export function testL2TipsStore(makeTipsStore) {
62
62
  block: makeTip(blockNumber),
63
63
  checkpoint: makeCheckpointIdForBlock(blockNumber)
64
64
  });
65
- const makeTips = (proposed, proven, finalized, checkpointed = 0, proposedCheckpoint = 0)=>({
65
+ const makeTips = (proposed, proven, finalized, checkpointed = 0)=>({
66
66
  proposed: makeTip(proposed),
67
67
  proven: makeTipId(proven),
68
68
  finalized: makeTipId(finalized),
69
- checkpointed: makeTipId(checkpointed),
70
- proposedCheckpoint: makeTipId(proposedCheckpoint)
69
+ checkpointed: makeTipId(checkpointed)
71
70
  });
72
71
  const makeCheckpoint = async (checkpointNumber, blocks)=>{
73
72
  const checkpoint = await Checkpoint.random(CheckpointNumber(checkpointNumber), {
@@ -139,7 +138,8 @@ export function testL2TipsStore(makeTipsStore) {
139
138
  // Prove up to block 5
140
139
  await tipsStore.handleBlockStreamEvent({
141
140
  type: 'chain-proven',
142
- block: makeBlockId(5)
141
+ block: makeBlockId(5),
142
+ checkpoint: makeCheckpointIdForBlock(5)
143
143
  });
144
144
  const tips = await tipsStore.getL2Tips();
145
145
  expect(tips.proposed).toEqual(makeTip(5));
@@ -161,11 +161,13 @@ export function testL2TipsStore(makeTipsStore) {
161
161
  // Prove and finalize
162
162
  await tipsStore.handleBlockStreamEvent({
163
163
  type: 'chain-proven',
164
- block: makeBlockId(5)
164
+ block: makeBlockId(5),
165
+ checkpoint: makeCheckpointIdForBlock(5)
165
166
  });
166
167
  await tipsStore.handleBlockStreamEvent({
167
168
  type: 'chain-finalized',
168
- block: makeBlockId(5)
169
+ block: makeBlockId(5),
170
+ checkpoint: makeCheckpointIdForBlock(5)
169
171
  });
170
172
  const tips = await tipsStore.getL2Tips();
171
173
  expect(tips.proposed).toEqual(makeTip(5));
@@ -223,11 +225,13 @@ export function testL2TipsStore(makeTipsStore) {
223
225
  // Prove and finalize up to block 3 (checkpoint 1)
224
226
  await tipsStore.handleBlockStreamEvent({
225
227
  type: 'chain-proven',
226
- block: makeBlockId(3)
228
+ block: makeBlockId(3),
229
+ checkpoint: makeCheckpointIdForBlock(3)
227
230
  });
228
231
  await tipsStore.handleBlockStreamEvent({
229
232
  type: 'chain-finalized',
230
- block: makeBlockId(3)
233
+ block: makeBlockId(3),
234
+ checkpoint: makeCheckpointIdForBlock(3)
231
235
  });
232
236
  // Blocks before finalized should be cleared
233
237
  expect(await tipsStore.getL2BlockHash(1)).toBeUndefined();
@@ -247,10 +251,8 @@ export function testL2TipsStore(makeTipsStore) {
247
251
  await tipsStore.handleBlockStreamEvent({
248
252
  type: 'chain-pruned',
249
253
  block: makeBlockId(5),
250
- checkpoint: {
251
- number: CheckpointNumber.ZERO,
252
- hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
253
- }
254
+ checkpointed: makeTipId(0),
255
+ proven: makeTipId(0)
254
256
  });
255
257
  const tips = await tipsStore.getL2Tips();
256
258
  expect(tips.proposed).toEqual(makeTip(5));
@@ -272,10 +274,8 @@ export function testL2TipsStore(makeTipsStore) {
272
274
  await tipsStore.handleBlockStreamEvent({
273
275
  type: 'chain-pruned',
274
276
  block: makeTip(0),
275
- checkpoint: {
276
- number: CheckpointNumber.ZERO,
277
- hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
278
- }
277
+ checkpointed: makeTipId(0),
278
+ proven: makeTipId(0)
279
279
  });
280
280
  tips = await tipsStore.getL2Tips();
281
281
  expect(tips.proposed).toEqual(makeTip(0));
@@ -336,10 +336,8 @@ export function testL2TipsStore(makeTipsStore) {
336
336
  await tipsStore.handleBlockStreamEvent({
337
337
  type: 'chain-pruned',
338
338
  block: makeBlockId(5),
339
- checkpoint: {
340
- number: CheckpointNumber.ZERO,
341
- hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
342
- }
339
+ checkpointed: makeTipId(5),
340
+ proven: makeTipId(0)
343
341
  });
344
342
  tips = await tipsStore.getL2Tips();
345
343
  expect(tips.proposed).toEqual(makeTip(5));
@@ -399,10 +397,8 @@ export function testL2TipsStore(makeTipsStore) {
399
397
  await tipsStore.handleBlockStreamEvent({
400
398
  type: 'chain-pruned',
401
399
  block: makeBlockId(3),
402
- checkpoint: {
403
- number: CheckpointNumber.ZERO,
404
- hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
405
- }
400
+ checkpointed: makeTipId(3),
401
+ proven: makeTipId(0)
406
402
  });
407
403
  tips = await tipsStore.getL2Tips();
408
404
  expect(tips.proposed).toEqual(makeTip(3));
@@ -439,7 +435,8 @@ export function testL2TipsStore(makeTipsStore) {
439
435
  // Prove up to block 3
440
436
  await tipsStore.handleBlockStreamEvent({
441
437
  type: 'chain-proven',
442
- block: makeBlockId(3)
438
+ block: makeBlockId(3),
439
+ checkpoint: makeCheckpointIdForBlock(3)
443
440
  });
444
441
  let tips = await tipsStore.getL2Tips();
445
442
  expect(tips.proposed).toEqual(makeTip(3));
@@ -479,10 +476,8 @@ export function testL2TipsStore(makeTipsStore) {
479
476
  await tipsStore.handleBlockStreamEvent({
480
477
  type: 'chain-pruned',
481
478
  block: makeBlockId(3),
482
- checkpoint: {
483
- number: CheckpointNumber.ZERO,
484
- hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
485
- }
479
+ checkpointed: makeTipId(3),
480
+ proven: makeTipId(3)
486
481
  });
487
482
  tips = await tipsStore.getL2Tips();
488
483
  expect(tips.proposed).toEqual(makeTip(3));
@@ -525,22 +520,195 @@ export function testL2TipsStore(makeTipsStore) {
525
520
  expect(await tipsStore.getL2BlockHash(6)).not.toEqual(originalHash6);
526
521
  expect(await tipsStore.getL2BlockHash(7)).not.toEqual(originalHash7);
527
522
  });
528
- // Regression test for #13142
529
- it('does not blow up when setting proven chain on an unseen block number', async ()=>{
523
+ // Regression test for #13142: proving an unseen block number (one with no local block->checkpoint
524
+ // mapping) must not blow up. With per-cursor checkpoint ids, the proven tip resolves to the
525
+ // checkpoint id carried by the event rather than falling back to checkpoint zero.
526
+ it('resolves the proven checkpoint from the carried id when setting proven on an unseen block number', async ()=>{
530
527
  await tipsStore.handleBlockStreamEvent({
531
528
  type: 'blocks-added',
532
529
  blocks: [
533
530
  await makeBlock(5)
534
531
  ]
535
532
  });
533
+ // Block 3 has no local block->checkpoint mapping, but the event carries a real checkpoint id.
534
+ const carriedCheckpoint = {
535
+ number: CheckpointNumber(1),
536
+ hash: new Fr(42).toString()
537
+ };
536
538
  await tipsStore.handleBlockStreamEvent({
537
539
  type: 'chain-proven',
538
- block: makeBlockId(3)
540
+ block: makeBlockId(3),
541
+ checkpoint: carriedCheckpoint
539
542
  });
540
543
  const tips = await tipsStore.getL2Tips();
541
544
  expect(tips.proposed).toEqual(makeTip(5));
542
545
  expect(tips.proven.block).toEqual(makeTip(3));
543
- // No checkpoint for block 3 since it wasn't checkpointed
544
- expect(tips.proven.checkpoint.number).toEqual(CheckpointNumber.ZERO);
546
+ // Resolved from the carried id, not the (missing) local mapping.
547
+ expect(tips.proven.checkpoint).toEqual(carriedCheckpoint);
548
+ });
549
+ // proven/finalized resolve to the carried checkpoint id even when the block has no local
550
+ // block->checkpoint mapping (the cursor legitimately leads the locally-checkpointed frontier).
551
+ it('resolves proven and finalized checkpoints from carried ids without a local mapping', async ()=>{
552
+ await tipsStore.handleBlockStreamEvent({
553
+ type: 'blocks-added',
554
+ blocks: [
555
+ await makeBlock(7)
556
+ ]
557
+ });
558
+ const provenCheckpoint = {
559
+ number: CheckpointNumber(2),
560
+ hash: new Fr(101).toString()
561
+ };
562
+ const finalizedCheckpoint = {
563
+ number: CheckpointNumber(1),
564
+ hash: new Fr(100).toString()
565
+ };
566
+ await tipsStore.handleBlockStreamEvent({
567
+ type: 'chain-proven',
568
+ block: makeBlockId(5),
569
+ checkpoint: provenCheckpoint
570
+ });
571
+ await tipsStore.handleBlockStreamEvent({
572
+ type: 'chain-finalized',
573
+ block: makeBlockId(3),
574
+ checkpoint: finalizedCheckpoint
575
+ });
576
+ const tips = await tipsStore.getL2Tips();
577
+ expect(tips.proven.checkpoint).toEqual(provenCheckpoint);
578
+ expect(tips.finalized.checkpoint).toEqual(finalizedCheckpoint);
579
+ });
580
+ // Genuine corruption: a cursor points at a real (non-genesis) block that has a block hash but
581
+ // neither a stored per-cursor checkpoint id nor a block->checkpoint mapping. getL2Tips must throw
582
+ // loudly rather than silently report checkpoint zero. We reach this state by reaching past the
583
+ // event API to place the tip directly, since the normal writers always record an id.
584
+ it('throws when a cursor points at a real block with neither a stored id nor a mapping', async ()=>{
585
+ // blocks-added records the block hash for block 5 (so getBlockId succeeds) but no checkpoint id.
586
+ await tipsStore.handleBlockStreamEvent({
587
+ type: 'blocks-added',
588
+ blocks: [
589
+ await makeBlock(5)
590
+ ]
591
+ });
592
+ // Corrupt the proven cursor to point at block 5 without any id or mapping.
593
+ const internal = tipsStore;
594
+ await internal.setTip('proven', BlockNumber(5));
595
+ await expect(tipsStore.getL2Tips()).rejects.toThrow(/checkpoint/i);
596
+ });
597
+ // Backward prune of a leading cursor: a checkpoint-bearing cursor that legitimately leads the source's
598
+ // confirmed checkpointed tip is clamped down to that tip, resolving to the id the prune event carries
599
+ // (never genesis, never a throw). This is the skipped-history shape where the cursor sits on a block
600
+ // ahead of the checkpointed frontier.
601
+ it('clamps a leading checkpoint cursor down to the source checkpointed tip carried by the prune event', async ()=>{
602
+ // Checkpoint blocks 1-5 (checkpointed = block 5 / ckpt 1), then add uncheckpointed blocks 6-10.
603
+ const blocks1to5 = await Promise.all(times(5, (i)=>makeBlock(i + 1)));
604
+ await tipsStore.handleBlockStreamEvent({
605
+ type: 'blocks-added',
606
+ blocks: blocks1to5
607
+ });
608
+ const checkpoint1 = await makeCheckpoint(1, blocks1to5);
609
+ await tipsStore.handleBlockStreamEvent(await makeCheckpointedEvent(checkpoint1));
610
+ const blocks6to10 = await Promise.all(times(5, (i)=>makeBlock(i + 6)));
611
+ await tipsStore.handleBlockStreamEvent({
612
+ type: 'blocks-added',
613
+ blocks: blocks6to10
614
+ });
615
+ // Advance the proven cursor onto an uncheckpointed block (8) via a carried id, so it LEADS the
616
+ // source checkpointed tip (block 5) and will be clamped down to it on prune.
617
+ await tipsStore.handleBlockStreamEvent({
618
+ type: 'chain-proven',
619
+ block: makeBlockId(8),
620
+ checkpoint: {
621
+ number: CheckpointNumber(2),
622
+ hash: new Fr(202).toString()
623
+ }
624
+ });
625
+ // Prune to block 7, carrying the source's confirmed checkpointed and proven tips (both block 5 / ckpt 1
626
+ // here, the source's proven tip having rolled back together with its checkpointed tip).
627
+ await tipsStore.handleBlockStreamEvent({
628
+ type: 'chain-pruned',
629
+ block: makeBlockId(7),
630
+ checkpointed: makeTipId(5),
631
+ proven: makeTipId(5)
632
+ });
633
+ // Must not throw; the proven cursor is clamped to the carried proven tip, resolving to ckpt 1.
634
+ const tips = await tipsStore.getL2Tips();
635
+ expect(tips.proposed).toEqual(makeTip(7));
636
+ expect(tips.proven.block).toEqual(makeTip(5));
637
+ expect(tips.proven.checkpoint.number).toEqual(CheckpointNumber(1));
638
+ });
639
+ it('keeps the checkpointed tip when pruning to an uncheckpointed block ahead of it', async ()=>{
640
+ const blocks1to5 = await Promise.all(times(5, (i)=>makeBlock(i + 1)));
641
+ await tipsStore.handleBlockStreamEvent({
642
+ type: 'blocks-added',
643
+ blocks: blocks1to5
644
+ });
645
+ const checkpoint1 = await makeCheckpoint(1, blocks1to5);
646
+ await tipsStore.handleBlockStreamEvent(await makeCheckpointedEvent(checkpoint1)); // checkpointed = block 5 / ckpt 1
647
+ const blocks6to7 = await Promise.all(times(2, (i)=>makeBlock(i + 6)));
648
+ await tipsStore.handleBlockStreamEvent({
649
+ type: 'blocks-added',
650
+ blocks: blocks6to7
651
+ }); // proposed = 7
652
+ // Prune to block 6: an uncheckpointed block AHEAD of the checkpointed tip (block 5). The source
653
+ // checkpointed tip is still block 5 / ckpt 1, so the checkpointed cursor must not move.
654
+ await tipsStore.handleBlockStreamEvent({
655
+ type: 'chain-pruned',
656
+ block: makeBlockId(6),
657
+ checkpointed: makeTipId(5),
658
+ proven: makeTipId(0)
659
+ });
660
+ const tips = await tipsStore.getL2Tips();
661
+ expect(tips.proposed).toEqual(makeTip(6));
662
+ expect(tips.checkpointed.block).toEqual(makeTip(5));
663
+ expect(tips.checkpointed.checkpoint.number).toEqual(CheckpointNumber(1)); // must NOT be zero
664
+ });
665
+ // Per-cursor clamping on prune: when the source rolls back its proven tip below its checkpointed tip
666
+ // (e.g. a proof tx dropped by an L1 reorg), the prune event carries both source tips and each local
667
+ // cursor must clamp to its OWN source tip. Clamping the proven cursor onto the (higher) checkpointed
668
+ // tip would transiently report unproven blocks as proven until the corrective chain-proven event lands.
669
+ it('clamps the proven cursor to the source proven tip, separately from the checkpointed cursor, on prune', async ()=>{
670
+ // Checkpoint blocks 1-15 across three checkpoints (ckpt 1 = 1-5, ckpt 2 = 6-10, ckpt 3 = 11-15).
671
+ const blocks1to5 = await Promise.all(times(5, (i)=>makeBlock(i + 1)));
672
+ await tipsStore.handleBlockStreamEvent({
673
+ type: 'blocks-added',
674
+ blocks: blocks1to5
675
+ });
676
+ await tipsStore.handleBlockStreamEvent(await makeCheckpointedEvent(await makeCheckpoint(1, blocks1to5)));
677
+ const blocks6to10 = await Promise.all(times(5, (i)=>makeBlock(i + 6)));
678
+ await tipsStore.handleBlockStreamEvent({
679
+ type: 'blocks-added',
680
+ blocks: blocks6to10
681
+ });
682
+ await tipsStore.handleBlockStreamEvent(await makeCheckpointedEvent(await makeCheckpoint(2, blocks6to10)));
683
+ const blocks11to15 = await Promise.all(times(5, (i)=>makeBlock(i + 11)));
684
+ await tipsStore.handleBlockStreamEvent({
685
+ type: 'blocks-added',
686
+ blocks: blocks11to15
687
+ });
688
+ await tipsStore.handleBlockStreamEvent(await makeCheckpointedEvent(await makeCheckpoint(3, blocks11to15)));
689
+ // Prove the whole chain up to block 15 (ckpt 3), so the local proven cursor leads both source tips below.
690
+ await tipsStore.handleBlockStreamEvent({
691
+ type: 'chain-proven',
692
+ block: makeBlockId(15),
693
+ checkpoint: makeCheckpointIdForBlock(15)
694
+ });
695
+ let tips = await tipsStore.getL2Tips();
696
+ expect(tips.checkpointed.block).toEqual(makeTip(15));
697
+ expect(tips.proven.block).toEqual(makeTip(15));
698
+ // Prune arrives with the source's proven tip (block 5 / ckpt 1) BELOW its checkpointed tip (block 10 /
699
+ // ckpt 2) and below the local proven cursor (block 15). Each cursor must clamp to its own source tip.
700
+ await tipsStore.handleBlockStreamEvent({
701
+ type: 'chain-pruned',
702
+ block: makeBlockId(10),
703
+ checkpointed: makeTipId(10),
704
+ proven: makeTipId(5)
705
+ });
706
+ tips = await tipsStore.getL2Tips();
707
+ // The proven cursor lands exactly on the source proven tip, NOT on the (higher) checkpointed tip.
708
+ expect(tips.proven.block).toEqual(makeTip(5));
709
+ expect(tips.proven.checkpoint.number).toEqual(CheckpointNumber(1));
710
+ // The checkpointed cursor lands on the source checkpointed tip.
711
+ expect(tips.checkpointed.block).toEqual(makeTip(10));
712
+ expect(tips.checkpointed.checkpoint.number).toEqual(CheckpointNumber(2));
545
713
  });
546
714
  }
@@ -1,4 +1,5 @@
1
1
  export * from './chain-config.js';
2
+ export * from './network-consensus-config.js';
2
3
  export * from './node-rpc-config.js';
3
4
  export * from './sequencer-config.js';
4
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWcvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsdUJBQXVCLENBQUMifQ==
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWcvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLCtCQUErQixDQUFDO0FBQzlDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyx1QkFBdUIsQ0FBQyJ9
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export * from './chain-config.js';
2
+ export * from './network-consensus-config.js';
2
3
  export * from './node-rpc-config.js';
3
4
  export * from './sequencer-config.js';
@@ -0,0 +1,72 @@
1
+ import { type L1ContractsConfig } from '@aztec/ethereum/config';
2
+ import type { SequencerConfig } from '../interfaces/configs.js';
3
+ /**
4
+ * Environment variables whose values must be identical across every node of a network. They fall into three
5
+ * categories, all consensus-critical:
6
+ *
7
+ * - Timing/protocol consensus: slot and epoch durations, block sub-slot duration, max blocks per checkpoint, and
8
+ * the checkpoint-proposal materialization grace. Proposers and validators must agree on these to land on the
9
+ * same proposed chain and the same checkpoint-proposal receive/handoff deadlines.
10
+ * - Network identity and L1-posted deployment params: the L1 chain id and the staking/governance/slashing
11
+ * parameters baked into the deployed rollup contract (committee size, lags, thresholds, mana target, fee
12
+ * pricing, governance/slashing round sizes, quorums, slash amounts, etc.). A node disagreeing with the rollup
13
+ * it points at would compute the wrong epoch geometry, fees, or slashing rounds.
14
+ * - Node-side slashing offense consensus: the offense detection/penalty parameters validators apply locally to
15
+ * decide which payloads to sign. Validators must agree on these to reach the on-chain slashing quorum.
16
+ *
17
+ * Deliberately excluded: bootnodes, P2P/store/OTEL/sentinel settings, SEQ_MIN_TX_PER_BLOCK, SEQ_MAX_TX_PER_*,
18
+ * AZTEC_SLASHER_ENABLED, PROVER_REAL_PROOFS, TRANSACTIONS_DISABLED, and AZTEC_ENTRY_QUEUE_* (mainnet-only genesis
19
+ * params enforced by L1).
20
+ */
21
+ export declare const NETWORK_CONSENSUS_ENV_VARS: readonly ["ETHEREUM_SLOT_DURATION", "AZTEC_SLOT_DURATION", "AZTEC_EPOCH_DURATION", "SEQ_BLOCK_DURATION_MS", "MAX_BLOCKS_PER_CHECKPOINT", "CHECKPOINT_PROPOSAL_SYNC_GRACE_SECONDS", "L1_CHAIN_ID", "AZTEC_TARGET_COMMITTEE_SIZE", "AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET", "AZTEC_LAG_IN_EPOCHS_FOR_RANDAO", "AZTEC_ACTIVATION_THRESHOLD", "AZTEC_EJECTION_THRESHOLD", "AZTEC_LOCAL_EJECTION_THRESHOLD", "AZTEC_EXIT_DELAY_SECONDS", "AZTEC_INBOX_LAG", "AZTEC_PROOF_SUBMISSION_EPOCHS", "AZTEC_MANA_TARGET", "AZTEC_PROVING_COST_PER_MANA", "AZTEC_INITIAL_ETH_PER_FEE_ASSET", "AZTEC_GOVERNANCE_PROPOSER_ROUND_SIZE", "AZTEC_GOVERNANCE_PROPOSER_QUORUM", "AZTEC_SLASHING_QUORUM", "AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS", "AZTEC_SLASHING_LIFETIME_IN_ROUNDS", "AZTEC_SLASHING_OFFSET_IN_ROUNDS", "AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS", "AZTEC_SLASHING_VETOER", "AZTEC_SLASHING_DISABLE_DURATION", "AZTEC_SLASH_AMOUNT_SMALL", "AZTEC_SLASH_AMOUNT_MEDIUM", "AZTEC_SLASH_AMOUNT_LARGE", "SLASH_OFFENSE_EXPIRATION_ROUNDS", "SLASH_MAX_PAYLOAD_SIZE", "SLASH_EXECUTE_ROUNDS_LOOK_BACK", "SLASH_DATA_WITHHOLDING_TOLERANCE_SLOTS", "SLASH_DATA_WITHHOLDING_PENALTY", "SLASH_INACTIVITY_TARGET_PERCENTAGE", "SLASH_INACTIVITY_CONSECUTIVE_EPOCH_THRESHOLD", "SLASH_INACTIVITY_PENALTY", "SLASH_PROPOSE_INVALID_ATTESTATIONS_PENALTY", "SLASH_DUPLICATE_PROPOSAL_PENALTY", "SLASH_DUPLICATE_ATTESTATION_PENALTY", "SLASH_PROPOSE_DESCENDANT_OF_CHECKPOINT_WITH_INVALID_ATTESTATIONS_PENALTY", "SLASH_ATTEST_INVALID_CHECKPOINT_PROPOSAL_PENALTY", "SLASH_UNKNOWN_PENALTY", "SLASH_INVALID_BLOCK_PENALTY", "SLASH_INVALID_CHECKPOINT_PROPOSAL_PENALTY", "SLASH_GRACE_PERIOD_L2_SLOTS"];
22
+ /** A consensus-critical environment variable name; see {@link NETWORK_CONSENSUS_ENV_VARS}. */
23
+ export type ConsensusEnvVar = (typeof NETWORK_CONSENSUS_ENV_VARS)[number];
24
+ /**
25
+ * The subset of consensus-critical timing config whose geometry can be validated in isolation. Composed by
26
+ * picking the canonical fields from their owning config types so the field set never drifts from the config
27
+ * layer: slot durations from {@link L1ContractsConfig}, block sub-slot/checkpoint timings from
28
+ * {@link SequencerConfig} (whose fields are optional there, hence `Required`).
29
+ */
30
+ export type NetworkConsensusConfig = Pick<L1ContractsConfig, 'aztecSlotDuration' | 'ethereumSlotDuration'> & Required<Pick<SequencerConfig, 'blockDurationMs' | 'maxBlocksPerCheckpoint' | 'checkpointProposalSyncGraceSeconds'>>;
31
+ /**
32
+ * Extracts the timing {@link NetworkConsensusConfig} from a generated network config object. The env-var names
33
+ * and the per-field parsing both come from the canonical config mappings (`l1ContractsConfigMappings` and
34
+ * `sharedSequencerConfigMappings`), so each field is parsed exactly as the node's config layer would parse it.
35
+ * A field whose env var is absent becomes `NaN`, which {@link validateNetworkConsensusConfig} reports as an
36
+ * error. Never throws: parse helpers that would throw or yield `undefined` are coerced to `NaN`.
37
+ */
38
+ export declare function getConsensusConfigFromNetworkEnv(values: Record<string, string | number | boolean>): NetworkConsensusConfig;
39
+ /**
40
+ * Validates a {@link NetworkConsensusConfig} for self-consistency, returning a list of error messages (empty
41
+ * when valid). Used by the cli unit test that gates the generated network configs.
42
+ *
43
+ * The check requires `maxBlocksPerCheckpoint` to be *exactly* what a {@link ProposerTimetable} built from the
44
+ * same slot timings and the production default budgets derives. This exact-equality requirement ensures the
45
+ * published network value is precisely what the production default budgets produce, so every node running those
46
+ * defaults agrees on the per-checkpoint block count without clamping.
47
+ */
48
+ export declare function validateNetworkConsensusConfig(config: NetworkConsensusConfig): string[];
49
+ /**
50
+ * Enforces that operators do not silently override consensus-critical values diverging from the network config.
51
+ *
52
+ * For each var in {@link NETWORK_CONSENSUS_ENV_VARS} present in `networkConfig`: if the operator set it in `env`
53
+ * to a conflicting value, this throws unless `ALLOW_OVERRIDING_NETWORK_CONFIG` is truthy (in which case it logs
54
+ * and keeps the operator value).
55
+ *
56
+ * This function is pure: it never writes to `env`. Instead it returns the canonical env writes the caller
57
+ * should apply — a map of env-var name to canonical string value for every numeric var whose env value matched
58
+ * the network value numerically. Applying these closes a bypass where the config layer parses some vars with
59
+ * `parseInt` (which reads '6e3' as 6); rewriting them to the network value's string form keeps the operator's
60
+ * numerically-equal value but in canonical form. Vars kept under `ALLOW_OVERRIDING_NETWORK_CONFIG` (genuine
61
+ * conflicts) are not included, so the operator value is preserved untouched.
62
+ *
63
+ * @returns Canonical env writes (env-var name -> canonical string value) for the caller to apply.
64
+ */
65
+ export declare function checkConsensusEnvOverrides(networkConfig: Record<string, string | number | boolean>, env?: {
66
+ [key: string]: string | undefined;
67
+ }, log?: (msg: string) => void): Record<string, string>;
68
+ /** Whether the env opts into overriding network-wide consensus values (`ALLOW_OVERRIDING_NETWORK_CONFIG`). */
69
+ export declare function allowsNetworkConfigOverride(env?: {
70
+ [key: string]: string | undefined;
71
+ }): boolean;
72
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29yay1jb25zZW5zdXMtY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29uZmlnL25ldHdvcmstY29uc2Vuc3VzLWNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxpQkFBaUIsRUFBNkIsTUFBTSx3QkFBd0IsQ0FBQztBQUczRixPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQVVoRTs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxlQUFPLE1BQU0sMEJBQTBCLDJsREFzREQsQ0FBQztBQUV2Qyw4RkFBOEY7QUFDOUYsTUFBTSxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQU8sMEJBQTBCLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUUxRTs7Ozs7R0FLRztBQUNILE1BQU0sTUFBTSxzQkFBc0IsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsbUJBQW1CLEdBQUcsc0JBQXNCLENBQUMsR0FDeEcsUUFBUSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsaUJBQWlCLEdBQUcsd0JBQXdCLEdBQUcsb0NBQW9DLENBQUMsQ0FBQyxDQUFDO0FBWXZIOzs7Ozs7R0FNRztBQUNILHdCQUFnQixnQ0FBZ0MsQ0FDOUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLE1BQU0sR0FBRyxPQUFPLENBQUMsR0FDaEQsc0JBQXNCLENBaUJ4QjtBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsd0JBQWdCLDhCQUE4QixDQUFDLE1BQU0sRUFBRSxzQkFBc0IsR0FBRyxNQUFNLEVBQUUsQ0E4RXZGO0FBRUQ7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsd0JBQWdCLDBCQUEwQixDQUN4QyxhQUFhLEVBQUUsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsTUFBTSxHQUFHLE9BQU8sQ0FBQyxFQUN4RCxHQUFHLEdBQUU7SUFBRSxDQUFDLEdBQUcsRUFBRSxNQUFNLEdBQUcsTUFBTSxHQUFHLFNBQVMsQ0FBQTtDQUFnQixFQUN4RCxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxNQUFNLEtBQUssSUFBSSxHQUMxQixNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQWlEeEI7QUFFRCw4R0FBOEc7QUFDOUcsd0JBQWdCLDJCQUEyQixDQUFDLEdBQUcsR0FBRTtJQUFFLENBQUMsR0FBRyxFQUFFLE1BQU0sR0FBRyxNQUFNLEdBQUcsU0FBUyxDQUFBO0NBQWdCLEdBQUcsT0FBTyxDQUc3RyJ9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-consensus-config.d.ts","sourceRoot":"","sources":["../../src/config/network-consensus-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA6B,MAAM,wBAAwB,CAAC;AAG3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAUhE;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,0BAA0B,2lDAsDD,CAAC;AAEvC,8FAA8F;AAC9F,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,GAAG,sBAAsB,CAAC,GACxG,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,iBAAiB,GAAG,wBAAwB,GAAG,oCAAoC,CAAC,CAAC,CAAC;AAYvH;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAChD,sBAAsB,CAiBxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,EAAE,CA8EvF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CACxC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EACxD,GAAG,GAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAgB,EACxD,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiDxB;AAED,8GAA8G;AAC9G,wBAAgB,2BAA2B,CAAC,GAAG,GAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAgB,GAAG,OAAO,CAG7G"}