@aztec/validator-client 0.0.1-commit.f1df4d2 → 0.0.1-commit.f224bb98b

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 (48) hide show
  1. package/README.md +63 -18
  2. package/dest/block_proposal_handler.d.ts +5 -4
  3. package/dest/block_proposal_handler.d.ts.map +1 -1
  4. package/dest/block_proposal_handler.js +122 -62
  5. package/dest/checkpoint_builder.d.ts +15 -5
  6. package/dest/checkpoint_builder.d.ts.map +1 -1
  7. package/dest/checkpoint_builder.js +80 -25
  8. package/dest/config.d.ts +1 -1
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +26 -1
  11. package/dest/duties/validation_service.d.ts +2 -2
  12. package/dest/duties/validation_service.d.ts.map +1 -1
  13. package/dest/duties/validation_service.js +5 -11
  14. package/dest/factory.d.ts +1 -1
  15. package/dest/factory.d.ts.map +1 -1
  16. package/dest/factory.js +2 -1
  17. package/dest/index.d.ts +1 -2
  18. package/dest/index.d.ts.map +1 -1
  19. package/dest/index.js +0 -1
  20. package/dest/key_store/ha_key_store.js +1 -1
  21. package/dest/metrics.d.ts +9 -1
  22. package/dest/metrics.d.ts.map +1 -1
  23. package/dest/metrics.js +12 -0
  24. package/dest/validator.d.ts +35 -8
  25. package/dest/validator.d.ts.map +1 -1
  26. package/dest/validator.js +196 -34
  27. package/package.json +19 -19
  28. package/src/block_proposal_handler.ts +149 -80
  29. package/src/checkpoint_builder.ts +90 -14
  30. package/src/config.ts +26 -1
  31. package/src/duties/validation_service.ts +11 -10
  32. package/src/factory.ts +1 -0
  33. package/src/index.ts +0 -1
  34. package/src/key_store/ha_key_store.ts +1 -1
  35. package/src/metrics.ts +18 -0
  36. package/src/validator.ts +246 -40
  37. package/dest/tx_validator/index.d.ts +0 -3
  38. package/dest/tx_validator/index.d.ts.map +0 -1
  39. package/dest/tx_validator/index.js +0 -2
  40. package/dest/tx_validator/nullifier_cache.d.ts +0 -14
  41. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  42. package/dest/tx_validator/nullifier_cache.js +0 -24
  43. package/dest/tx_validator/tx_validator_factory.d.ts +0 -19
  44. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  45. package/dest/tx_validator/tx_validator_factory.js +0 -54
  46. package/src/tx_validator/index.ts +0 -2
  47. package/src/tx_validator/nullifier_cache.ts +0 -30
  48. package/src/tx_validator/tx_validator_factory.ts +0 -154
@@ -1,16 +1,18 @@
1
- import { merge, pick } from '@aztec/foundation/collection';
1
+ import { NUM_CHECKPOINT_END_MARKER_FIELDS, getNumBlockEndBlobFields } from '@aztec/blob-lib/encoding';
2
+ import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB, MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT } from '@aztec/constants';
3
+ import { merge, pick, sum } from '@aztec/foundation/collection';
2
4
  import { createLogger } from '@aztec/foundation/log';
3
5
  import { bufferToHex } from '@aztec/foundation/string';
4
6
  import { elapsed } from '@aztec/foundation/timer';
5
- import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
7
+ import { createTxValidatorForBlockBuilding, getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
6
8
  import { LightweightCheckpointBuilder } from '@aztec/prover-client/light';
7
9
  import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, createPublicTxSimulatorForBlockBuilding } from '@aztec/simulator/server';
8
10
  import { Gas } from '@aztec/stdlib/gas';
9
11
  import { FullNodeBlockBuilderConfigKeys, NoValidTxsError } from '@aztec/stdlib/interfaces/server';
12
+ import { NullDebugLogStore } from '@aztec/stdlib/logs';
10
13
  import { MerkleTreeId } from '@aztec/stdlib/trees';
11
14
  import { GlobalVariables } from '@aztec/stdlib/tx';
12
15
  import { getTelemetryClient } from '@aztec/telemetry-client';
13
- import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_factory.js';
14
16
  /**
15
17
  * Builder for a single checkpoint. Handles building blocks within the checkpoint
16
18
  * and completing it.
@@ -21,14 +23,16 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
21
23
  contractDataSource;
22
24
  dateProvider;
23
25
  telemetryClient;
26
+ debugLogStore;
24
27
  log;
25
- constructor(checkpointBuilder, fork, config, contractDataSource, dateProvider, telemetryClient, bindings){
28
+ constructor(checkpointBuilder, fork, config, contractDataSource, dateProvider, telemetryClient, bindings, debugLogStore = new NullDebugLogStore()){
26
29
  this.checkpointBuilder = checkpointBuilder;
27
30
  this.fork = fork;
28
31
  this.config = config;
29
32
  this.contractDataSource = contractDataSource;
30
33
  this.dateProvider = dateProvider;
31
34
  this.telemetryClient = telemetryClient;
35
+ this.debugLogStore = debugLogStore;
32
36
  this.log = createLogger('checkpoint-builder', {
33
37
  ...bindings,
34
38
  instanceId: `checkpoint-${checkpointBuilder.checkpointNumber}`
@@ -39,6 +43,7 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
39
43
  }
40
44
  /**
41
45
  * Builds a single block within this checkpoint.
46
+ * Automatically caps gas and blob field limits based on checkpoint-level budgets and prior blocks.
42
47
  */ async buildBlock(pendingTxs, blockNumber, timestamp, opts = {}) {
43
48
  const slot = this.checkpointBuilder.constants.slotNumber;
44
49
  this.log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
@@ -59,18 +64,21 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
59
64
  gasFees: constants.gasFees
60
65
  });
61
66
  const { processor, validator } = await this.makeBlockBuilderDeps(globalVariables, this.fork);
62
- const [publicProcessorDuration, [processedTxs, failedTxs, usedTxs, _, usedTxBlobFields]] = await elapsed(()=>processor.process(pendingTxs, opts, validator));
67
+ // Cap gas limits amd available blob fields by remaining checkpoint-level budgets
68
+ const cappedOpts = {
69
+ ...opts,
70
+ ...this.capLimitsByCheckpointBudgets(opts)
71
+ };
72
+ const [publicProcessorDuration, [processedTxs, failedTxs, usedTxs]] = await elapsed(()=>processor.process(pendingTxs, cappedOpts, validator));
63
73
  // Throw if we didn't collect a single valid tx and we're not allowed to build empty blocks
64
74
  // (only the first block in a checkpoint can be empty)
65
75
  if (processedTxs.length === 0 && this.checkpointBuilder.getBlockCount() > 0) {
66
76
  throw new NoValidTxsError(failedTxs);
67
77
  }
68
78
  // Add block to checkpoint
69
- const block = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
79
+ const { block } = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
70
80
  expectedEndState: opts.expectedEndState
71
81
  });
72
- // How much public gas was processed
73
- const publicGas = processedTxs.reduce((acc, tx)=>acc.add(tx.gasUsed.publicGas), Gas.empty());
74
82
  this.log.debug('Built block within checkpoint', {
75
83
  header: block.header.toInspect(),
76
84
  processedTxs: processedTxs.map((tx)=>tx.hash.toString()),
@@ -78,12 +86,10 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
78
86
  });
79
87
  return {
80
88
  block,
81
- publicGas,
82
89
  publicProcessorDuration,
83
90
  numTxs: processedTxs.length,
84
91
  failedTxs,
85
- usedTxs,
86
- usedTxBlobFields
92
+ usedTxs
87
93
  };
88
94
  }
89
95
  /** Completes the checkpoint and returns it. */ async completeCheckpoint() {
@@ -98,14 +104,59 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
98
104
  /** Gets the checkpoint currently in progress. */ getCheckpoint() {
99
105
  return this.checkpointBuilder.clone().completeCheckpoint();
100
106
  }
107
+ /**
108
+ * Caps per-block gas and blob field limits by remaining checkpoint-level budgets.
109
+ * Computes remaining L2 gas (mana), DA gas, and blob fields from blocks already added to the checkpoint,
110
+ * then returns opts with maxBlockGas and maxBlobFields capped accordingly.
111
+ */ capLimitsByCheckpointBudgets(opts) {
112
+ const existingBlocks = this.checkpointBuilder.getBlocks();
113
+ // Remaining L2 gas (mana)
114
+ // IMPORTANT: This assumes mana is computed solely based on L2 gas used in transactions.
115
+ // This may change in the future.
116
+ const usedMana = sum(existingBlocks.map((b)=>b.header.totalManaUsed.toNumber()));
117
+ const remainingMana = this.config.rollupManaLimit - usedMana;
118
+ // Remaining DA gas
119
+ const usedDAGas = sum(existingBlocks.map((b)=>b.computeDAGasUsed())) ?? 0;
120
+ const remainingDAGas = MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT - usedDAGas;
121
+ // Remaining blob fields (block blob fields include both tx data and block-end overhead)
122
+ const usedBlobFields = sum(existingBlocks.map((b)=>b.toBlobFields().length));
123
+ const totalBlobCapacity = BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB - NUM_CHECKPOINT_END_MARKER_FIELDS;
124
+ const isFirstBlock = existingBlocks.length === 0;
125
+ const blockEndOverhead = getNumBlockEndBlobFields(isFirstBlock);
126
+ const maxBlobFieldsForTxs = totalBlobCapacity - usedBlobFields - blockEndOverhead;
127
+ // Cap L2 gas by remaining checkpoint mana
128
+ const cappedL2Gas = Math.min(opts.maxBlockGas?.l2Gas ?? remainingMana, remainingMana);
129
+ // Cap DA gas by remaining checkpoint DA gas budget
130
+ const cappedDAGas = Math.min(opts.maxBlockGas?.daGas ?? remainingDAGas, remainingDAGas);
131
+ // Cap blob fields by remaining checkpoint blob capacity
132
+ const cappedBlobFields = opts.maxBlobFields !== undefined ? Math.min(opts.maxBlobFields, maxBlobFieldsForTxs) : maxBlobFieldsForTxs;
133
+ // Cap transaction count by remaining checkpoint tx budget
134
+ let cappedMaxTransactions;
135
+ if (this.config.maxTxsPerCheckpoint !== undefined) {
136
+ const usedTxs = sum(existingBlocks.map((b)=>b.body.txEffects.length));
137
+ const remainingTxs = Math.max(0, this.config.maxTxsPerCheckpoint - usedTxs);
138
+ cappedMaxTransactions = opts.maxTransactions !== undefined ? Math.min(opts.maxTransactions, remainingTxs) : remainingTxs;
139
+ } else {
140
+ cappedMaxTransactions = opts.maxTransactions;
141
+ }
142
+ return {
143
+ maxBlockGas: new Gas(cappedDAGas, cappedL2Gas),
144
+ maxBlobFields: cappedBlobFields,
145
+ maxTransactions: cappedMaxTransactions
146
+ };
147
+ }
101
148
  async makeBlockBuilderDeps(globalVariables, fork) {
102
- const txPublicSetupAllowList = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
149
+ const txPublicSetupAllowList = [
150
+ ...await getDefaultAllowedSetupFunctions(),
151
+ ...this.config.txPublicSetupAllowListExtend ?? []
152
+ ];
103
153
  const contractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings());
104
154
  const guardedFork = new GuardedMerkleTreeOperations(fork);
155
+ const collectDebugLogs = this.debugLogStore.isEnabled;
105
156
  const bindings = this.log.getBindings();
106
- const publicTxSimulator = createPublicTxSimulatorForBlockBuilding(guardedFork, contractsDB, globalVariables, this.telemetryClient, bindings);
107
- const processor = new PublicProcessor(globalVariables, guardedFork, contractsDB, publicTxSimulator, this.dateProvider, this.telemetryClient, createLogger('simulator:public-processor', bindings), this.config);
108
- const validator = createValidatorForBlockBuilding(fork, this.contractDataSource, globalVariables, txPublicSetupAllowList, this.log.getBindings());
157
+ const publicTxSimulator = createPublicTxSimulatorForBlockBuilding(guardedFork, contractsDB, globalVariables, this.telemetryClient, bindings, collectDebugLogs);
158
+ const processor = new PublicProcessor(globalVariables, guardedFork, contractsDB, publicTxSimulator, this.dateProvider, this.telemetryClient, createLogger('simulator:public-processor', bindings), this.config, this.debugLogStore);
159
+ const validator = createTxValidatorForBlockBuilding(fork, this.contractDataSource, globalVariables, txPublicSetupAllowList, this.log.getBindings());
109
160
  return {
110
161
  processor,
111
162
  validator
@@ -118,13 +169,15 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
118
169
  contractDataSource;
119
170
  dateProvider;
120
171
  telemetryClient;
172
+ debugLogStore;
121
173
  log;
122
- constructor(config, worldState, contractDataSource, dateProvider, telemetryClient = getTelemetryClient()){
174
+ constructor(config, worldState, contractDataSource, dateProvider, telemetryClient = getTelemetryClient(), debugLogStore = new NullDebugLogStore()){
123
175
  this.config = config;
124
176
  this.worldState = worldState;
125
177
  this.contractDataSource = contractDataSource;
126
178
  this.dateProvider = dateProvider;
127
179
  this.telemetryClient = telemetryClient;
180
+ this.debugLogStore = debugLogStore;
128
181
  this.log = createLogger('checkpoint-builder');
129
182
  }
130
183
  getConfig() {
@@ -135,7 +188,7 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
135
188
  }
136
189
  /**
137
190
  * Starts a new checkpoint and returns a CheckpointBuilder to build blocks within it.
138
- */ async startCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings) {
191
+ */ async startCheckpoint(checkpointNumber, constants, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings) {
139
192
  const stateReference = await fork.getStateReference();
140
193
  const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
141
194
  this.log.verbose(`Building new checkpoint ${checkpointNumber}`, {
@@ -143,18 +196,19 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
143
196
  msgCount: l1ToL2Messages.length,
144
197
  initialStateReference: stateReference.toInspect(),
145
198
  initialArchiveRoot: bufferToHex(archiveTree.root),
146
- constants
199
+ constants,
200
+ feeAssetPriceModifier
147
201
  });
148
- const lightweightBuilder = await LightweightCheckpointBuilder.startNewCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings);
149
- return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient, bindings);
202
+ const lightweightBuilder = await LightweightCheckpointBuilder.startNewCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings, feeAssetPriceModifier);
203
+ return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient, bindings, this.debugLogStore);
150
204
  }
151
205
  /**
152
206
  * Opens a checkpoint, either starting fresh or resuming from existing blocks.
153
- */ async openCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, existingBlocks = [], bindings) {
207
+ */ async openCheckpoint(checkpointNumber, constants, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, existingBlocks = [], bindings) {
154
208
  const stateReference = await fork.getStateReference();
155
209
  const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
156
210
  if (existingBlocks.length === 0) {
157
- return this.startCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings);
211
+ return this.startCheckpoint(checkpointNumber, constants, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings);
158
212
  }
159
213
  this.log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
160
214
  checkpointNumber,
@@ -162,10 +216,11 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
162
216
  existingBlockCount: existingBlocks.length,
163
217
  initialStateReference: stateReference.toInspect(),
164
218
  initialArchiveRoot: bufferToHex(archiveTree.root),
165
- constants
219
+ constants,
220
+ feeAssetPriceModifier
166
221
  });
167
- const lightweightBuilder = await LightweightCheckpointBuilder.resumeCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, existingBlocks, bindings);
168
- return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient, bindings);
222
+ const lightweightBuilder = await LightweightCheckpointBuilder.resumeCheckpoint(checkpointNumber, constants, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, existingBlocks, bindings);
223
+ return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient, bindings, this.debugLogStore);
169
224
  }
170
225
  /** Returns a fork of the world state at the given block number. */ getFork(blockNumber) {
171
226
  return this.worldState.fork(blockNumber);
package/dest/config.d.ts CHANGED
@@ -8,4 +8,4 @@ export declare const validatorClientConfigMappings: ConfigMappingsType<Validator
8
8
  * @returns The validator configuration.
9
9
  */
10
10
  export declare function getProverEnvVars(): ValidatorClientConfig;
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxLQUFLLGtCQUFrQixFQUt4QixNQUFNLDBCQUEwQixDQUFDO0FBRWxDLE9BQU8sS0FBSyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFHN0UsWUFBWSxFQUFFLHFCQUFxQixFQUFFLENBQUM7QUFFdEMsZUFBTyxNQUFNLDZCQUE2QixFQUFFLGtCQUFrQixDQUFDLHFCQUFxQixDQStEbkYsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCx3QkFBZ0IsZ0JBQWdCLElBQUkscUJBQXFCLENBRXhEIn0=
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxLQUFLLGtCQUFrQixFQUt4QixNQUFNLDBCQUEwQixDQUFDO0FBR2xDLE9BQU8sS0FBSyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFN0UsWUFBWSxFQUFFLHFCQUFxQixFQUFFLENBQUM7QUFFdEMsZUFBTyxNQUFNLDZCQUE2QixFQUFFLGtCQUFrQixDQUFDLHFCQUFxQixDQXdGbkYsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCx3QkFBZ0IsZ0JBQWdCLElBQUkscUJBQXFCLENBRXhEIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAG7E,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAEtC,eAAO,MAAM,6BAA6B,EAAE,kBAAkB,CAAC,qBAAqB,CA+DnF,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAExD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAEtC,eAAO,MAAM,6BAA6B,EAAE,kBAAkB,CAAC,qBAAqB,CAwFnF,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAExD"}
package/dest/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { booleanConfigHelper, getConfigFromMappings, numberConfigHelper, secretValueConfigHelper } from '@aztec/foundation/config';
2
2
  import { EthAddress } from '@aztec/foundation/eth-address';
3
- import { validatorHASignerConfigMappings } from '@aztec/validator-ha-signer/config';
3
+ import { localSignerConfigMappings, validatorHASignerConfigMappings } from '@aztec/stdlib/ha-signing';
4
4
  export const validatorClientConfigMappings = {
5
5
  validatorPrivateKeys: {
6
6
  env: 'VALIDATOR_PRIVATE_KEYS',
@@ -53,6 +53,31 @@ export const validatorClientConfigMappings = {
53
53
  description: 'Skip pushing re-executed blocks to archiver (default: false)',
54
54
  defaultValue: false
55
55
  },
56
+ attestToEquivocatedProposals: {
57
+ description: 'Agree to attest to equivocated checkpoint proposals (for testing purposes only)',
58
+ ...booleanConfigHelper(false)
59
+ },
60
+ validateMaxL2BlockGas: {
61
+ env: 'VALIDATOR_MAX_L2_BLOCK_GAS',
62
+ description: 'Maximum L2 block gas for validation. Proposals exceeding this limit are rejected.',
63
+ parseEnv: (val)=>val ? parseInt(val, 10) : undefined
64
+ },
65
+ validateMaxDABlockGas: {
66
+ env: 'VALIDATOR_MAX_DA_BLOCK_GAS',
67
+ description: 'Maximum DA block gas for validation. Proposals exceeding this limit are rejected.',
68
+ parseEnv: (val)=>val ? parseInt(val, 10) : undefined
69
+ },
70
+ validateMaxTxsPerBlock: {
71
+ env: 'VALIDATOR_MAX_TX_PER_BLOCK',
72
+ description: 'Maximum transactions per block for validation. Proposals exceeding this limit are rejected.',
73
+ parseEnv: (val)=>val ? parseInt(val, 10) : undefined
74
+ },
75
+ validateMaxTxsPerCheckpoint: {
76
+ env: 'VALIDATOR_MAX_TX_PER_CHECKPOINT',
77
+ description: 'Maximum transactions per checkpoint for validation. Proposals exceeding this limit are rejected.',
78
+ parseEnv: (val)=>val ? parseInt(val, 10) : undefined
79
+ },
80
+ ...localSignerConfigMappings,
56
81
  ...validatorHASignerConfigMappings
57
82
  };
58
83
  /**
@@ -39,7 +39,7 @@ export declare class ValidationService {
39
39
  *
40
40
  * @returns A checkpoint proposal signing the above information
41
41
  */
42
- createCheckpointProposal(checkpointHeader: CheckpointHeader, archive: Fr, lastBlockInfo: CreateCheckpointProposalLastBlockData | undefined, proposerAttesterAddress: EthAddress | undefined, options: CheckpointProposalOptions): Promise<CheckpointProposal>;
42
+ createCheckpointProposal(checkpointHeader: CheckpointHeader, archive: Fr, feeAssetPriceModifier: bigint, lastBlockInfo: CreateCheckpointProposalLastBlockData | undefined, proposerAttesterAddress: EthAddress | undefined, options: CheckpointProposalOptions): Promise<CheckpointProposal>;
43
43
  /**
44
44
  * Attest with selection of validators to the given checkpoint proposal
45
45
  *
@@ -63,4 +63,4 @@ export declare class ValidationService {
63
63
  */
64
64
  signAttestationsAndSigners(attestationsAndSigners: CommitteeAttestationsAndSigners, proposer: EthAddress, slot: SlotNumber, blockNumber: BlockNumber | CheckpointNumber): Promise<Signature>;
65
65
  }
66
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGlvbl9zZXJ2aWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZHV0aWVzL3ZhbGlkYXRpb25fc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsV0FBVyxFQUNYLEtBQUssZ0JBQWdCLEVBQ3JCLHFCQUFxQixFQUNyQixLQUFLLFVBQVUsRUFDaEIsTUFBTSxpQ0FBaUMsQ0FBQztBQUd6QyxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFakUsT0FBTyxLQUFLLEVBQUUsK0JBQStCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMzRSxPQUFPLEtBQUssRUFBRSxxQ0FBcUMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzdGLE9BQU8sRUFDTCxhQUFhLEVBQ2IsS0FBSyxvQkFBb0IsRUFDekIscUJBQXFCLEVBQ3JCLGtCQUFrQixFQUNsQixLQUFLLHNCQUFzQixFQUMzQixLQUFLLHlCQUF5QixFQUcvQixNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDN0QsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBSXhELE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFbkUscUJBQWEsaUJBQWlCO0lBRTFCLE9BQU8sQ0FBQyxRQUFRO0lBQ2hCLE9BQU8sQ0FBQyxHQUFHO0lBRmIsWUFDVSxRQUFRLEVBQUUsaUJBQWlCLEVBQzNCLEdBQUcseUNBQStDLEVBQ3hEO0lBRUo7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDSSxtQkFBbUIsQ0FDeEIsV0FBVyxFQUFFLFdBQVcsRUFDeEIsMEJBQTBCLEVBQUUscUJBQXFCLEVBQ2pELE1BQU0sRUFBRSxFQUFFLEVBQ1YsT0FBTyxFQUFFLEVBQUUsRUFDWCxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQ1QsdUJBQXVCLEVBQUUsVUFBVSxHQUFHLFNBQVMsRUFDL0MsT0FBTyxFQUFFLG9CQUFvQixHQUM1QixPQUFPLENBQUMsYUFBYSxDQUFDLENBcUJ4QjtJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSSx3QkFBd0IsQ0FDN0IsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQ2xDLE9BQU8sRUFBRSxFQUFFLEVBQ1gsYUFBYSxFQUFFLHFDQUFxQyxHQUFHLFNBQVMsRUFDaEUsdUJBQXVCLEVBQUUsVUFBVSxHQUFHLFNBQVMsRUFDL0MsT0FBTyxFQUFFLHlCQUF5QixHQUNqQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FzQjdCO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0csMEJBQTBCLENBQzlCLFFBQVEsRUFBRSxzQkFBc0IsRUFDaEMsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUN0QixPQUFPLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQW9EbEM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSCwwQkFBMEIsQ0FDeEIsc0JBQXNCLEVBQUUsK0JBQStCLEVBQ3ZELFFBQVEsRUFBRSxVQUFVLEVBQ3BCLElBQUksRUFBRSxVQUFVLEVBQ2hCLFdBQVcsRUFBRSxXQUFXLEdBQUcsZ0JBQWdCLEdBQzFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FXcEI7Q0FDRiJ9
66
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGlvbl9zZXJ2aWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZHV0aWVzL3ZhbGlkYXRpb25fc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsV0FBVyxFQUNYLEtBQUssZ0JBQWdCLEVBQ3JCLHFCQUFxQixFQUNyQixLQUFLLFVBQVUsRUFDaEIsTUFBTSxpQ0FBaUMsQ0FBQztBQUd6QyxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFakUsT0FBTyxLQUFLLEVBQUUsK0JBQStCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMzRSxPQUFPLEtBQUssRUFBRSxxQ0FBcUMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzdGLE9BQU8sRUFDTCxhQUFhLEVBQ2IsS0FBSyxvQkFBb0IsRUFDekIscUJBQXFCLEVBQ3JCLGtCQUFrQixFQUNsQixLQUFLLHNCQUFzQixFQUMzQixLQUFLLHlCQUF5QixFQUcvQixNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDN0QsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBSXhELE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFbkUscUJBQWEsaUJBQWlCO0lBRTFCLE9BQU8sQ0FBQyxRQUFRO0lBQ2hCLE9BQU8sQ0FBQyxHQUFHO0lBRmIsWUFDVSxRQUFRLEVBQUUsaUJBQWlCLEVBQzNCLEdBQUcseUNBQStDLEVBQ3hEO0lBRUo7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDSSxtQkFBbUIsQ0FDeEIsV0FBVyxFQUFFLFdBQVcsRUFDeEIsMEJBQTBCLEVBQUUscUJBQXFCLEVBQ2pELE1BQU0sRUFBRSxFQUFFLEVBQ1YsT0FBTyxFQUFFLEVBQUUsRUFDWCxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQ1QsdUJBQXVCLEVBQUUsVUFBVSxHQUFHLFNBQVMsRUFDL0MsT0FBTyxFQUFFLG9CQUFvQixHQUM1QixPQUFPLENBQUMsYUFBYSxDQUFDLENBcUJ4QjtJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSSx3QkFBd0IsQ0FDN0IsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQ2xDLE9BQU8sRUFBRSxFQUFFLEVBQ1gscUJBQXFCLEVBQUUsTUFBTSxFQUM3QixhQUFhLEVBQUUscUNBQXFDLEdBQUcsU0FBUyxFQUNoRSx1QkFBdUIsRUFBRSxVQUFVLEdBQUcsU0FBUyxFQUMvQyxPQUFPLEVBQUUseUJBQXlCLEdBQ2pDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQTRCN0I7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDRywwQkFBMEIsQ0FDOUIsUUFBUSxFQUFFLHNCQUFzQixFQUNoQyxTQUFTLEVBQUUsVUFBVSxFQUFFLEdBQ3RCLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLENBOENsQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNILDBCQUEwQixDQUN4QixzQkFBc0IsRUFBRSwrQkFBK0IsRUFDdkQsUUFBUSxFQUFFLFVBQVUsRUFDcEIsSUFBSSxFQUFFLFVBQVUsRUFDaEIsV0FBVyxFQUFFLFdBQVcsR0FBRyxnQkFBZ0IsR0FDMUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVdwQjtDQUNGIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"validation_service.d.ts","sourceRoot":"","sources":["../../src/duties/validation_service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,qBAAqB,EACrB,KAAK,UAAU,EAChB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,iCAAiC,CAAC;AAC7F,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAG/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAIxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,GAAG;IAFb,YACU,QAAQ,EAAE,iBAAiB,EAC3B,GAAG,yCAA+C,EACxD;IAEJ;;;;;;;;;;;;;;OAcG;IACI,mBAAmB,CACxB,WAAW,EAAE,WAAW,EACxB,0BAA0B,EAAE,qBAAqB,EACjD,MAAM,EAAE,EAAE,EACV,OAAO,EAAE,EAAE,EACX,GAAG,EAAE,EAAE,EAAE,EACT,uBAAuB,EAAE,UAAU,GAAG,SAAS,EAC/C,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC,CAqBxB;IAED;;;;;;;;;;OAUG;IACI,wBAAwB,CAC7B,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,EAAE,EAAE,EACX,aAAa,EAAE,qCAAqC,GAAG,SAAS,EAChE,uBAAuB,EAAE,UAAU,GAAG,SAAS,EAC/C,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAsB7B;IAED;;;;;;;;;OASG;IACG,0BAA0B,CAC9B,QAAQ,EAAE,sBAAsB,EAChC,SAAS,EAAE,UAAU,EAAE,GACtB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAoDlC;IAED;;;;;;;;;OASG;IACH,0BAA0B,CACxB,sBAAsB,EAAE,+BAA+B,EACvD,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,WAAW,GAAG,gBAAgB,GAC1C,OAAO,CAAC,SAAS,CAAC,CAWpB;CACF"}
1
+ {"version":3,"file":"validation_service.d.ts","sourceRoot":"","sources":["../../src/duties/validation_service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,qBAAqB,EACrB,KAAK,UAAU,EAChB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,iCAAiC,CAAC;AAC7F,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAG/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAIxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,GAAG;IAFb,YACU,QAAQ,EAAE,iBAAiB,EAC3B,GAAG,yCAA+C,EACxD;IAEJ;;;;;;;;;;;;;;OAcG;IACI,mBAAmB,CACxB,WAAW,EAAE,WAAW,EACxB,0BAA0B,EAAE,qBAAqB,EACjD,MAAM,EAAE,EAAE,EACV,OAAO,EAAE,EAAE,EACX,GAAG,EAAE,EAAE,EAAE,EACT,uBAAuB,EAAE,UAAU,GAAG,SAAS,EAC/C,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC,CAqBxB;IAED;;;;;;;;;;OAUG;IACI,wBAAwB,CAC7B,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,EAAE,EAAE,EACX,qBAAqB,EAAE,MAAM,EAC7B,aAAa,EAAE,qCAAqC,GAAG,SAAS,EAChE,uBAAuB,EAAE,UAAU,GAAG,SAAS,EAC/C,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,kBAAkB,CAAC,CA4B7B;IAED;;;;;;;;;OASG;IACG,0BAA0B,CAC9B,QAAQ,EAAE,sBAAsB,EAChC,SAAS,EAAE,UAAU,EAAE,GACtB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CA8ClC;IAED;;;;;;;;;OASG;IACH,0BAA0B,CACxB,sBAAsB,EAAE,+BAA+B,EACvD,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,WAAW,GAAG,gBAAgB,GAC1C,OAAO,CAAC,SAAS,CAAC,CAWpB;CACF"}
@@ -48,7 +48,7 @@ export class ValidationService {
48
48
  * @param options - Checkpoint proposal options
49
49
  *
50
50
  * @returns A checkpoint proposal signing the above information
51
- */ createCheckpointProposal(checkpointHeader, archive, lastBlockInfo, proposerAttesterAddress, options) {
51
+ */ createCheckpointProposal(checkpointHeader, archive, feeAssetPriceModifier, lastBlockInfo, proposerAttesterAddress, options) {
52
52
  // For testing: change the archive to trigger state_mismatch validation failure
53
53
  if (options.broadcastInvalidCheckpointProposal) {
54
54
  archive = Fr.random();
@@ -66,7 +66,7 @@ export class ValidationService {
66
66
  txHashes: lastBlockInfo.txs.map((tx)=>tx.getTxHash()),
67
67
  txs: options.publishFullTxs ? lastBlockInfo.txs : undefined
68
68
  };
69
- return CheckpointProposal.createProposalFromSigner(checkpointHeader, archive, lastBlock, payloadSigner);
69
+ return CheckpointProposal.createProposalFromSigner(checkpointHeader, archive, feeAssetPriceModifier, lastBlock, payloadSigner);
70
70
  }
71
71
  /**
72
72
  * Attest with selection of validators to the given checkpoint proposal
@@ -79,19 +79,13 @@ export class ValidationService {
79
79
  * @returns checkpoint attestations
80
80
  */ async attestToCheckpointProposal(proposal, attestors) {
81
81
  // Create the attestation payload from the checkpoint proposal
82
- const payload = new ConsensusPayload(proposal.checkpointHeader, proposal.archive);
82
+ const payload = new ConsensusPayload(proposal.checkpointHeader, proposal.archive, proposal.feeAssetPriceModifier);
83
83
  const buf = Buffer32.fromBuffer(keccak256(payload.getPayloadToSign(SignatureDomainSeparator.checkpointAttestation)));
84
84
  // TODO(spy/ha): Use checkpointNumber instead of blockNumber once CheckpointHeader includes it.
85
- // Currently using lastBlock.blockNumber as a proxy for checkpoint identification in HA signing.
85
+ // CheckpointProposalCore doesn't have lastBlock info, so use 0 as a proxy.
86
86
  // blockNumber is NOT used for the primary key so it's safe to use here.
87
87
  // See CheckpointHeader TODO and SigningContext types documentation.
88
- let blockNumber;
89
- try {
90
- blockNumber = proposal.blockNumber;
91
- } catch {
92
- // Checkpoint proposal may not have lastBlock, use 0 as fallback
93
- blockNumber = BlockNumber(0);
94
- }
88
+ const blockNumber = BlockNumber(0);
95
89
  const context = {
96
90
  slot: proposal.slotNumber,
97
91
  blockNumber,
package/dest/factory.d.ts CHANGED
@@ -32,4 +32,4 @@ export declare function createValidatorClient(config: ValidatorClientFullConfig,
32
32
  keyStoreManager: KeystoreManager | undefined;
33
33
  blobClient: BlobClientInterface;
34
34
  }): Promise<ValidatorClient> | undefined;
35
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEVBQTBCLEtBQUssU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3BFLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RSxPQUFPLEtBQUssRUFBRSx5QkFBeUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pHLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFL0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUxRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFakQsd0JBQWdCLDBCQUEwQixDQUN4QyxNQUFNLEVBQUUseUJBQXlCLEVBQ2pDLElBQUksRUFBRTtJQUNKLGtCQUFrQixFQUFFLDBCQUEwQixDQUFDO0lBQy9DLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQztJQUNuQyxXQUFXLEVBQUUsYUFBYSxHQUFHLFdBQVcsQ0FBQztJQUN6QyxtQkFBbUIsRUFBRSxtQkFBbUIsQ0FBQztJQUN6QyxTQUFTLEVBQUUsU0FBUyxDQUFDO0lBQ3JCLFVBQVUsRUFBRSxVQUFVLENBQUM7SUFDdkIsWUFBWSxFQUFFLFlBQVksQ0FBQztJQUMzQixTQUFTLEVBQUUsZUFBZSxDQUFDO0NBQzVCLHdCQW1CRjtBQUVELHdCQUFnQixxQkFBcUIsQ0FDbkMsTUFBTSxFQUFFLHlCQUF5QixFQUNqQyxJQUFJLEVBQUU7SUFDSixrQkFBa0IsRUFBRSwwQkFBMEIsQ0FBQztJQUMvQyxVQUFVLEVBQUUsc0JBQXNCLENBQUM7SUFDbkMsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUNyQixXQUFXLEVBQUUsYUFBYSxHQUFHLFdBQVcsQ0FBQztJQUN6QyxtQkFBbUIsRUFBRSxtQkFBbUIsQ0FBQztJQUN6QyxTQUFTLEVBQUUsZUFBZSxDQUFDO0lBQzNCLFlBQVksRUFBRSxZQUFZLENBQUM7SUFDM0IsVUFBVSxFQUFFLFVBQVUsQ0FBQztJQUN2QixlQUFlLEVBQUUsZUFBZSxHQUFHLFNBQVMsQ0FBQztJQUM3QyxVQUFVLEVBQUUsbUJBQW1CLENBQUM7Q0FDakMsd0NBcUJGIn0=
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEVBQTBCLEtBQUssU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3BFLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RSxPQUFPLEtBQUssRUFBRSx5QkFBeUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pHLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFL0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUxRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFakQsd0JBQWdCLDBCQUEwQixDQUN4QyxNQUFNLEVBQUUseUJBQXlCLEVBQ2pDLElBQUksRUFBRTtJQUNKLGtCQUFrQixFQUFFLDBCQUEwQixDQUFDO0lBQy9DLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQztJQUNuQyxXQUFXLEVBQUUsYUFBYSxHQUFHLFdBQVcsQ0FBQztJQUN6QyxtQkFBbUIsRUFBRSxtQkFBbUIsQ0FBQztJQUN6QyxTQUFTLEVBQUUsU0FBUyxDQUFDO0lBQ3JCLFVBQVUsRUFBRSxVQUFVLENBQUM7SUFDdkIsWUFBWSxFQUFFLFlBQVksQ0FBQztJQUMzQixTQUFTLEVBQUUsZUFBZSxDQUFDO0NBQzVCLHdCQW9CRjtBQUVELHdCQUFnQixxQkFBcUIsQ0FDbkMsTUFBTSxFQUFFLHlCQUF5QixFQUNqQyxJQUFJLEVBQUU7SUFDSixrQkFBa0IsRUFBRSwwQkFBMEIsQ0FBQztJQUMvQyxVQUFVLEVBQUUsc0JBQXNCLENBQUM7SUFDbkMsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUNyQixXQUFXLEVBQUUsYUFBYSxHQUFHLFdBQVcsQ0FBQztJQUN6QyxtQkFBbUIsRUFBRSxtQkFBbUIsQ0FBQztJQUN6QyxTQUFTLEVBQUUsZUFBZSxDQUFDO0lBQzNCLFlBQVksRUFBRSxZQUFZLENBQUM7SUFDM0IsVUFBVSxFQUFFLFVBQVUsQ0FBQztJQUN2QixlQUFlLEVBQUUsZUFBZSxHQUFHLFNBQVMsQ0FBQztJQUM3QyxVQUFVLEVBQUUsbUJBQW1CLENBQUM7Q0FDakMsd0NBcUJGIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,EAAE,eAAe,CAAC;CAC5B,wBAmBF;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,UAAU,EAAE,mBAAmB,CAAC;CACjC,wCAqBF"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,EAAE,eAAe,CAAC;CAC5B,wBAoBF;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,UAAU,EAAE,mBAAmB,CAAC;CACjC,wCAqBF"}
package/dest/factory.js CHANGED
@@ -5,7 +5,8 @@ import { ValidatorClient } from './validator.js';
5
5
  export function createBlockProposalHandler(config, deps) {
6
6
  const metrics = new ValidatorMetrics(deps.telemetry);
7
7
  const blockProposalValidator = new BlockProposalValidator(deps.epochCache, {
8
- txsPermitted: !config.disableTransactions
8
+ txsPermitted: !config.disableTransactions,
9
+ maxTxsPerBlock: config.validateMaxTxsPerBlock
9
10
  });
10
11
  return new BlockProposalHandler(deps.checkpointsBuilder, deps.worldState, deps.blockSource, deps.l1ToL2MessageSource, deps.p2pClient.getTxProvider(), blockProposalValidator, deps.epochCache, config, metrics, deps.dateProvider, deps.telemetry);
11
12
  }
package/dest/index.d.ts CHANGED
@@ -4,5 +4,4 @@ export * from './config.js';
4
4
  export * from './factory.js';
5
5
  export * from './validator.js';
6
6
  export * from './key_store/index.js';
7
- export * from './tx_validator/index.js';
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMseUJBQXlCLENBQUMifQ==
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLHNCQUFzQixDQUFDIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
package/dest/index.js CHANGED
@@ -4,4 +4,3 @@ export * from './config.js';
4
4
  export * from './factory.js';
5
5
  export * from './validator.js';
6
6
  export * from './key_store/index.js';
7
- export * from './tx_validator/index.js';
@@ -184,7 +184,7 @@ import { hashTypedData } from 'viem';
184
184
  return;
185
185
  }
186
186
  if (error instanceof SlashingProtectionError) {
187
- this.log.warn(`Duty already signed by another node with different payload`, {
187
+ this.log.info(`Duty already signed by another node with different payload`, {
188
188
  dutyType: context.dutyType,
189
189
  slot: context.slot,
190
190
  existingMessageHash: error.existingMessageHash,
package/dest/metrics.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { EpochNumber } from '@aztec/foundation/branded-types';
2
+ import type { EthAddress } from '@aztec/foundation/eth-address';
1
3
  import type { BlockProposal } from '@aztec/stdlib/p2p';
2
4
  import { type TelemetryClient } from '@aztec/telemetry-client';
3
5
  import type { BlockProposalValidationFailureReason } from './block_proposal_handler.js';
@@ -6,6 +8,8 @@ export declare class ValidatorMetrics {
6
8
  private successfulAttestationsCount;
7
9
  private failedAttestationsBadProposalCount;
8
10
  private failedAttestationsNodeIssueCount;
11
+ private currentEpoch;
12
+ private attestedEpochCount;
9
13
  private reexMana;
10
14
  private reexTx;
11
15
  private reexDuration;
@@ -15,5 +19,9 @@ export declare class ValidatorMetrics {
15
19
  incSuccessfulAttestations(num: number): void;
16
20
  incFailedAttestationsBadProposal(num: number, reason: BlockProposalValidationFailureReason, inCommittee: boolean): void;
17
21
  incFailedAttestationsNodeIssue(num: number, reason: BlockProposalValidationFailureReason, inCommittee: boolean): void;
22
+ /** Update the gauge tracking the current epoch number (proxy for total epochs elapsed). */
23
+ setCurrentEpoch(epoch: EpochNumber): void;
24
+ /** Increment the count of epochs in which the given attester submitted at least one attestation. */
25
+ incAttestedEpochCount(attester: EthAddress): void;
18
26
  }
19
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ldHJpY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUtMLEtBQUssZUFBZSxFQUdyQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sS0FBSyxFQUFFLG9DQUFvQyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFeEYscUJBQWEsZ0JBQWdCO0lBQzNCLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBZ0I7SUFDaEQsT0FBTyxDQUFDLDJCQUEyQixDQUFnQjtJQUNuRCxPQUFPLENBQUMsa0NBQWtDLENBQWdCO0lBQzFELE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBZ0I7SUFFeEQsT0FBTyxDQUFDLFFBQVEsQ0FBWTtJQUM1QixPQUFPLENBQUMsTUFBTSxDQUFZO0lBQzFCLE9BQU8sQ0FBQyxZQUFZLENBQVE7SUFFNUIsWUFBWSxlQUFlLEVBQUUsZUFBZSxFQWdEM0M7SUFFTSxVQUFVLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBSTlEO0lBRU0sdUJBQXVCLENBQUMsUUFBUSxFQUFFLGFBQWEsUUFNckQ7SUFFTSx5QkFBeUIsQ0FBQyxHQUFHLEVBQUUsTUFBTSxRQUUzQztJQUVNLGdDQUFnQyxDQUNyQyxHQUFHLEVBQUUsTUFBTSxFQUNYLE1BQU0sRUFBRSxvQ0FBb0MsRUFDNUMsV0FBVyxFQUFFLE9BQU8sUUFNckI7SUFFTSw4QkFBOEIsQ0FDbkMsR0FBRyxFQUFFLE1BQU0sRUFDWCxNQUFNLEVBQUUsb0NBQW9DLEVBQzVDLFdBQVcsRUFBRSxPQUFPLFFBTXJCO0NBQ0YifQ==
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ldHJpY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUtMLEtBQUssZUFBZSxFQUdyQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sS0FBSyxFQUFFLG9DQUFvQyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFeEYscUJBQWEsZ0JBQWdCO0lBQzNCLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBZ0I7SUFDaEQsT0FBTyxDQUFDLDJCQUEyQixDQUFnQjtJQUNuRCxPQUFPLENBQUMsa0NBQWtDLENBQWdCO0lBQzFELE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBZ0I7SUFDeEQsT0FBTyxDQUFDLFlBQVksQ0FBUTtJQUM1QixPQUFPLENBQUMsa0JBQWtCLENBQWdCO0lBRTFDLE9BQU8sQ0FBQyxRQUFRLENBQVk7SUFDNUIsT0FBTyxDQUFDLE1BQU0sQ0FBWTtJQUMxQixPQUFPLENBQUMsWUFBWSxDQUFRO0lBRTVCLFlBQVksZUFBZSxFQUFFLGVBQWUsRUFvRDNDO0lBRU0sVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUk5RDtJQUVNLHVCQUF1QixDQUFDLFFBQVEsRUFBRSxhQUFhLFFBTXJEO0lBRU0seUJBQXlCLENBQUMsR0FBRyxFQUFFLE1BQU0sUUFFM0M7SUFFTSxnQ0FBZ0MsQ0FDckMsR0FBRyxFQUFFLE1BQU0sRUFDWCxNQUFNLEVBQUUsb0NBQW9DLEVBQzVDLFdBQVcsRUFBRSxPQUFPLFFBTXJCO0lBRU0sOEJBQThCLENBQ25DLEdBQUcsRUFBRSxNQUFNLEVBQ1gsTUFBTSxFQUFFLG9DQUFvQyxFQUM1QyxXQUFXLEVBQUUsT0FBTyxRQU1yQjtJQUVELDJGQUEyRjtJQUNwRixlQUFlLENBQUMsS0FBSyxFQUFFLFdBQVcsUUFFeEM7SUFFRCxvR0FBb0c7SUFDN0YscUJBQXFCLENBQUMsUUFBUSxFQUFFLFVBQVUsUUFFaEQ7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAKL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,6BAA6B,CAAC;AAExF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,2BAA2B,CAAgB;IACnD,OAAO,CAAC,kCAAkC,CAAgB;IAC1D,OAAO,CAAC,gCAAgC,CAAgB;IAExD,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAE5B,YAAY,eAAe,EAAE,eAAe,EAgD3C;IAEM,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAI9D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,aAAa,QAMrD;IAEM,yBAAyB,CAAC,GAAG,EAAE,MAAM,QAE3C;IAEM,gCAAgC,CACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,oCAAoC,EAC5C,WAAW,EAAE,OAAO,QAMrB;IAEM,8BAA8B,CACnC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,oCAAoC,EAC5C,WAAW,EAAE,OAAO,QAMrB;CACF"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAKL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,6BAA6B,CAAC;AAExF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,2BAA2B,CAAgB;IACnD,OAAO,CAAC,kCAAkC,CAAgB;IAC1D,OAAO,CAAC,gCAAgC,CAAgB;IACxD,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,kBAAkB,CAAgB;IAE1C,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAE5B,YAAY,eAAe,EAAE,eAAe,EAoD3C;IAEM,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAI9D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,aAAa,QAMrD;IAEM,yBAAyB,CAAC,GAAG,EAAE,MAAM,QAE3C;IAEM,gCAAgC,CACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,oCAAoC,EAC5C,WAAW,EAAE,OAAO,QAMrB;IAEM,8BAA8B,CACnC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,oCAAoC,EAC5C,WAAW,EAAE,OAAO,QAMrB;IAED,2FAA2F;IACpF,eAAe,CAAC,KAAK,EAAE,WAAW,QAExC;IAED,oGAAoG;IAC7F,qBAAqB,CAAC,QAAQ,EAAE,UAAU,QAEhD;CACF"}
package/dest/metrics.js CHANGED
@@ -4,6 +4,8 @@ export class ValidatorMetrics {
4
4
  successfulAttestationsCount;
5
5
  failedAttestationsBadProposalCount;
6
6
  failedAttestationsNodeIssueCount;
7
+ currentEpoch;
8
+ attestedEpochCount;
7
9
  reexMana;
8
10
  reexTx;
9
11
  reexDuration;
@@ -42,6 +44,8 @@ export class ValidatorMetrics {
42
44
  false
43
45
  ]
44
46
  });
47
+ this.currentEpoch = meter.createGauge(Metrics.VALIDATOR_CURRENT_EPOCH);
48
+ this.attestedEpochCount = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_ATTESTED_EPOCH_COUNT);
45
49
  this.reexMana = meter.createHistogram(Metrics.VALIDATOR_RE_EXECUTION_MANA);
46
50
  this.reexTx = meter.createHistogram(Metrics.VALIDATOR_RE_EXECUTION_TX_COUNT);
47
51
  this.reexDuration = meter.createGauge(Metrics.VALIDATOR_RE_EXECUTION_TIME);
@@ -73,4 +77,12 @@ export class ValidatorMetrics {
73
77
  [Attributes.IS_COMMITTEE_MEMBER]: inCommittee
74
78
  });
75
79
  }
80
+ /** Update the gauge tracking the current epoch number (proxy for total epochs elapsed). */ setCurrentEpoch(epoch) {
81
+ this.currentEpoch.record(Number(epoch));
82
+ }
83
+ /** Increment the count of epochs in which the given attester submitted at least one attestation. */ incAttestedEpochCount(attester) {
84
+ this.attestedEpochCount.add(1, {
85
+ [Attributes.ATTESTER_ADDRESS]: attester.toString()
86
+ });
87
+ }
76
88
  }
@@ -4,7 +4,7 @@ import { BlockNumber, CheckpointNumber, IndexWithinCheckpoint, SlotNumber } from
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import type { EthAddress } from '@aztec/foundation/eth-address';
6
6
  import type { Signature } from '@aztec/foundation/eth-signature';
7
- import { type Logger } from '@aztec/foundation/log';
7
+ import { type LogData, type Logger } from '@aztec/foundation/log';
8
8
  import { DateProvider } from '@aztec/foundation/timer';
9
9
  import type { KeystoreManager } from '@aztec/node-keystore';
10
10
  import type { P2P, PeerId } from '@aztec/p2p';
@@ -13,12 +13,12 @@ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
13
13
  import type { CommitteeAttestationsAndSigners, L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
14
14
  import type { CreateCheckpointProposalLastBlockData, ITxProvider, Validator, ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
15
15
  import { type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
16
- import type { BlockProposal, BlockProposalOptions, CheckpointAttestation, CheckpointProposalCore, CheckpointProposalOptions } from '@aztec/stdlib/p2p';
17
- import { CheckpointProposal } from '@aztec/stdlib/p2p';
16
+ import { type BlockProposal, type BlockProposalOptions, type CheckpointAttestation, CheckpointProposal, type CheckpointProposalCore, type CheckpointProposalOptions } from '@aztec/stdlib/p2p';
18
17
  import type { CheckpointHeader } from '@aztec/stdlib/rollup';
19
18
  import type { BlockHeader, Tx } from '@aztec/stdlib/tx';
20
19
  import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
21
20
  import { type SigningContext } from '@aztec/validator-ha-signer/types';
21
+ import type { ValidatorHASigner } from '@aztec/validator-ha-signer/validator-ha-signer';
22
22
  import type { TypedDataDefinition } from 'viem';
23
23
  import { BlockProposalHandler } from './block_proposal_handler.js';
24
24
  import type { FullNodeCheckpointsBuilder } from './checkpoint_builder.js';
@@ -38,17 +38,25 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
38
38
  private l1ToL2MessageSource;
39
39
  private config;
40
40
  private blobClient;
41
+ private slashingProtectionSigner;
41
42
  private dateProvider;
42
43
  readonly tracer: Tracer;
43
44
  private validationService;
44
45
  private metrics;
45
46
  private log;
46
47
  private hasRegisteredHandlers;
47
- private previousProposal?;
48
+ /** Tracks the last block proposal we created, to detect duplicate proposal attempts. */
49
+ private lastProposedBlock?;
50
+ /** Tracks the last checkpoint proposal we created. */
51
+ private lastProposedCheckpoint?;
48
52
  private lastEpochForCommitteeUpdateLoop;
49
53
  private epochCacheUpdateLoop;
54
+ /** Tracks the last epoch in which each attester successfully submitted at least one attestation. */
55
+ private lastAttestedEpochByAttester;
50
56
  private proposersOfInvalidBlocks;
51
- protected constructor(keyStore: ExtendedValidatorKeyStore, epochCache: EpochCache, p2pClient: P2P, blockProposalHandler: BlockProposalHandler, blockSource: L2BlockSource, checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, l1ToL2MessageSource: L1ToL2MessageSource, config: ValidatorClientFullConfig, blobClient: BlobClientInterface, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: Logger);
57
+ /** Tracks the last checkpoint proposal we attested to, to prevent equivocation. */
58
+ private lastAttestedProposal?;
59
+ protected constructor(keyStore: ExtendedValidatorKeyStore, epochCache: EpochCache, p2pClient: P2P, blockProposalHandler: BlockProposalHandler, blockSource: L2BlockSource, checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, l1ToL2MessageSource: L1ToL2MessageSource, config: ValidatorClientFullConfig, blobClient: BlobClientInterface, slashingProtectionSigner: ValidatorHASigner, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: Logger);
52
60
  static validateKeyStoreConfiguration(keyStoreManager: KeystoreManager, logger?: Logger): void;
53
61
  private handleEpochCommitteeUpdate;
54
62
  static new(config: ValidatorClientFullConfig, checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, epochCache: EpochCache, p2pClient: P2P, blockSource: L2BlockSource & L2BlockSink, l1ToL2MessageSource: L1ToL2MessageSource, txProvider: ITxProvider, keyStoreManager: KeystoreManager, blobClient: BlobClientInterface, dateProvider?: DateProvider, telemetry?: TelemetryClient): Promise<ValidatorClient>;
@@ -59,6 +67,7 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
59
67
  getFeeRecipientForAttestor(attestor: EthAddress): AztecAddress;
60
68
  getConfig(): ValidatorClientFullConfig;
61
69
  updateConfig(config: Partial<ValidatorClientFullConfig>): void;
70
+ reloadKeystore(newManager: KeystoreManager): void;
62
71
  start(): Promise<void>;
63
72
  stop(): Promise<void>;
64
73
  /** Register handlers on the p2p client */
@@ -76,16 +85,34 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
76
85
  * @returns Checkpoint attestations if valid, undefined otherwise
77
86
  */
78
87
  attestToCheckpointProposal(proposal: CheckpointProposalCore, _proposalSender: PeerId): Promise<CheckpointAttestation[] | undefined>;
88
+ /**
89
+ * Checks if we should attest to a slot based on equivocation prevention rules.
90
+ * @returns true if we should attest, false if we should skip
91
+ */
92
+ private shouldAttestToSlot;
79
93
  private createCheckpointAttestationsFromProposal;
80
94
  private validateCheckpointProposal;
81
95
  /**
82
96
  * Extract checkpoint global variables from a block.
83
97
  */
84
98
  private extractCheckpointConstants;
85
- private uploadBlobsForCheckpoint;
99
+ /**
100
+ * Uploads blobs for a checkpoint to the filestore (fire and forget).
101
+ */
102
+ protected uploadBlobsForCheckpoint(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<void>;
86
103
  private slashInvalidBlock;
104
+ /**
105
+ * Handle detection of a duplicate proposal (equivocation).
106
+ * Emits a slash event when a proposer sends multiple proposals for the same position.
107
+ */
108
+ private handleDuplicateProposal;
109
+ /**
110
+ * Handle detection of a duplicate attestation (equivocation).
111
+ * Emits a slash event when an attester signs attestations for different proposals at the same slot.
112
+ */
113
+ private handleDuplicateAttestation;
87
114
  createBlockProposal(blockHeader: BlockHeader, indexWithinCheckpoint: IndexWithinCheckpoint, inHash: Fr, archive: Fr, txs: Tx[], proposerAddress: EthAddress | undefined, options?: BlockProposalOptions): Promise<BlockProposal>;
88
- createCheckpointProposal(checkpointHeader: CheckpointHeader, archive: Fr, lastBlockInfo: CreateCheckpointProposalLastBlockData | undefined, proposerAddress: EthAddress | undefined, options?: CheckpointProposalOptions): Promise<CheckpointProposal>;
115
+ createCheckpointProposal(checkpointHeader: CheckpointHeader, archive: Fr, feeAssetPriceModifier: bigint, lastBlockInfo: CreateCheckpointProposalLastBlockData | undefined, proposerAddress: EthAddress | undefined, options?: CheckpointProposalOptions): Promise<CheckpointProposal>;
89
116
  broadcastBlockProposal(proposal: BlockProposal): Promise<void>;
90
117
  signAttestationsAndSigners(attestationsAndSigners: CommitteeAttestationsAndSigners, proposer: EthAddress, slot: SlotNumber, blockNumber: BlockNumber | CheckpointNumber): Promise<Signature>;
91
118
  collectOwnAttestations(proposal: CheckpointProposal): Promise<CheckpointAttestation[]>;
@@ -93,4 +120,4 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
93
120
  private handleAuthRequest;
94
121
  }
95
122
  export {};
96
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFckUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUNMLFdBQVcsRUFDWCxnQkFBZ0IsRUFFaEIscUJBQXFCLEVBQ3JCLFVBQVUsRUFDWCxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUVwRCxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQWdCLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBSWhGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTlDLE9BQU8sRUFBb0MsS0FBSyxPQUFPLEVBQUUsS0FBSyxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyRyxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSwrQkFBK0IsRUFBVyxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFaEgsT0FBTyxLQUFLLEVBQ1YscUNBQXFDLEVBQ3JDLFdBQVcsRUFDWCxTQUFTLEVBQ1QseUJBQXlCLEVBQ3pCLHNCQUFzQixFQUN2QixNQUFNLGlDQUFpQyxDQUFD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
123
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFckUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFckQsT0FBTyxFQUNMLFdBQVcsRUFDWCxnQkFBZ0IsRUFFaEIscUJBQXFCLEVBQ3JCLFVBQVUsRUFDWCxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUVwRCxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsS0FBSyxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFJaEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFtRCxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRS9GLE9BQU8sRUFBb0MsS0FBSyxPQUFPLEVBQUUsS0FBSyxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyRyxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSwrQkFBK0IsRUFBVyxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFHaEgsT0FBTyxLQUFLLEVBQ1YscUNBQXFDLEVBQ3JDLFdBQVcsRUFDWCxTQUFTLEVBQ1QseUJBQXlCLEVBQ3pCLHNCQUFzQixFQUN2QixN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