@aztec/validator-client 0.0.1-commit.bf2612ae → 0.0.1-commit.c0b82b2

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 (46) hide show
  1. package/README.md +21 -18
  2. package/dest/block_proposal_handler.d.ts +2 -2
  3. package/dest/block_proposal_handler.d.ts.map +1 -1
  4. package/dest/block_proposal_handler.js +20 -34
  5. package/dest/checkpoint_builder.d.ts +13 -11
  6. package/dest/checkpoint_builder.d.ts.map +1 -1
  7. package/dest/checkpoint_builder.js +50 -30
  8. package/dest/config.d.ts +1 -1
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +7 -4
  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 +3 -3
  14. package/dest/index.d.ts +1 -2
  15. package/dest/index.d.ts.map +1 -1
  16. package/dest/index.js +0 -1
  17. package/dest/key_store/ha_key_store.d.ts +1 -1
  18. package/dest/key_store/ha_key_store.d.ts.map +1 -1
  19. package/dest/key_store/ha_key_store.js +2 -2
  20. package/dest/metrics.d.ts +4 -3
  21. package/dest/metrics.d.ts.map +1 -1
  22. package/dest/metrics.js +34 -5
  23. package/dest/validator.d.ts +33 -9
  24. package/dest/validator.d.ts.map +1 -1
  25. package/dest/validator.js +167 -44
  26. package/package.json +19 -19
  27. package/src/block_proposal_handler.ts +29 -48
  28. package/src/checkpoint_builder.ts +73 -29
  29. package/src/config.ts +7 -4
  30. package/src/duties/validation_service.ts +9 -2
  31. package/src/index.ts +0 -1
  32. package/src/key_store/ha_key_store.ts +2 -2
  33. package/src/metrics.ts +45 -6
  34. package/src/validator.ts +221 -53
  35. package/dest/tx_validator/index.d.ts +0 -3
  36. package/dest/tx_validator/index.d.ts.map +0 -1
  37. package/dest/tx_validator/index.js +0 -2
  38. package/dest/tx_validator/nullifier_cache.d.ts +0 -14
  39. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  40. package/dest/tx_validator/nullifier_cache.js +0 -24
  41. package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
  42. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  43. package/dest/tx_validator/tx_validator_factory.js +0 -54
  44. package/src/tx_validator/index.ts +0 -2
  45. package/src/tx_validator/nullifier_cache.ts +0 -30
  46. package/src/tx_validator/tx_validator_factory.ts +0 -135
@@ -1,10 +1,10 @@
1
1
  import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
2
2
  import { merge, pick } from '@aztec/foundation/collection';
3
3
  import { Fr } from '@aztec/foundation/curves/bn254';
4
- import { createLogger } from '@aztec/foundation/log';
4
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
5
5
  import { bufferToHex } from '@aztec/foundation/string';
6
- import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
7
- import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
6
+ import { DateProvider, elapsed } from '@aztec/foundation/timer';
7
+ import { createTxValidatorForBlockBuilding, getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
8
8
  import { LightweightCheckpointBuilder } from '@aztec/prover-client/light';
9
9
  import {
10
10
  GuardedMerkleTreeOperations,
@@ -24,30 +24,25 @@ import {
24
24
  type ICheckpointBlockBuilder,
25
25
  type ICheckpointsBuilder,
26
26
  type MerkleTreeWriteOperations,
27
+ NoValidTxsError,
27
28
  type PublicProcessorLimits,
28
29
  type WorldStateSynchronizer,
29
30
  } from '@aztec/stdlib/interfaces/server';
31
+ import { type DebugLogStore, NullDebugLogStore } from '@aztec/stdlib/logs';
30
32
  import { MerkleTreeId } from '@aztec/stdlib/trees';
31
33
  import { type CheckpointGlobalVariables, GlobalVariables, StateReference, Tx } from '@aztec/stdlib/tx';
32
34
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
33
35
 
34
- import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_factory.js';
35
-
36
36
  // Re-export for backward compatibility
37
37
  export type { BuildBlockInCheckpointResult } from '@aztec/stdlib/interfaces/server';
38
38
 
39
- const log = createLogger('checkpoint-builder');
40
-
41
- /** Result of building a block within a checkpoint. Extends the base interface with timer. */
42
- export interface BuildBlockInCheckpointResultWithTimer extends BuildBlockInCheckpointResult {
43
- blockBuildingTimer: Timer;
44
- }
45
-
46
39
  /**
47
40
  * Builder for a single checkpoint. Handles building blocks within the checkpoint
48
41
  * and completing it.
49
42
  */
50
43
  export class CheckpointBuilder implements ICheckpointBlockBuilder {
44
+ private log: Logger;
45
+
51
46
  constructor(
52
47
  private checkpointBuilder: LightweightCheckpointBuilder,
53
48
  private fork: MerkleTreeWriteOperations,
@@ -55,7 +50,14 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
55
50
  private contractDataSource: ContractDataSource,
56
51
  private dateProvider: DateProvider,
57
52
  private telemetryClient: TelemetryClient,
58
- ) {}
53
+ bindings?: LoggerBindings,
54
+ private debugLogStore: DebugLogStore = new NullDebugLogStore(),
55
+ ) {
56
+ this.log = createLogger('checkpoint-builder', {
57
+ ...bindings,
58
+ instanceId: `checkpoint-${checkpointBuilder.checkpointNumber}`,
59
+ });
60
+ }
59
61
 
60
62
  getConstantData(): CheckpointGlobalVariables {
61
63
  return this.checkpointBuilder.constants;
@@ -69,11 +71,10 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
69
71
  blockNumber: BlockNumber,
70
72
  timestamp: bigint,
71
73
  opts: PublicProcessorLimits & { expectedEndState?: StateReference } = {},
72
- ): Promise<BuildBlockInCheckpointResultWithTimer> {
73
- const blockBuildingTimer = new Timer();
74
+ ): Promise<BuildBlockInCheckpointResult> {
74
75
  const slot = this.checkpointBuilder.constants.slotNumber;
75
76
 
76
- log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
77
+ this.log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
77
78
  slot,
78
79
  blockNumber,
79
80
  ...opts,
@@ -97,33 +98,42 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
97
98
  processor.process(pendingTxs, opts, validator),
98
99
  );
99
100
 
101
+ // Throw if we didn't collect a single valid tx and we're not allowed to build empty blocks
102
+ // (only the first block in a checkpoint can be empty)
103
+ if (processedTxs.length === 0 && this.checkpointBuilder.getBlockCount() > 0) {
104
+ throw new NoValidTxsError(failedTxs);
105
+ }
106
+
100
107
  // Add block to checkpoint
101
- const block = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
108
+ const { block } = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
102
109
  expectedEndState: opts.expectedEndState,
103
110
  });
104
111
 
105
112
  // How much public gas was processed
106
113
  const publicGas = processedTxs.reduce((acc, tx) => acc.add(tx.gasUsed.publicGas), Gas.empty());
107
114
 
108
- const res = {
115
+ this.log.debug('Built block within checkpoint', {
116
+ header: block.header.toInspect(),
117
+ processedTxs: processedTxs.map(tx => tx.hash.toString()),
118
+ failedTxs: failedTxs.map(tx => tx.tx.txHash.toString()),
119
+ });
120
+
121
+ return {
109
122
  block,
110
123
  publicGas,
111
124
  publicProcessorDuration,
112
125
  numTxs: processedTxs.length,
113
126
  failedTxs,
114
- blockBuildingTimer,
115
127
  usedTxs,
116
128
  usedTxBlobFields,
117
129
  };
118
- log.debug('Built block within checkpoint', res.block.header);
119
- return res;
120
130
  }
121
131
 
122
132
  /** Completes the checkpoint and returns it. */
123
133
  async completeCheckpoint(): Promise<Checkpoint> {
124
134
  const checkpoint = await this.checkpointBuilder.completeCheckpoint();
125
135
 
126
- log.verbose(`Completed checkpoint ${checkpoint.number}`, {
136
+ this.log.verbose(`Completed checkpoint ${checkpoint.number}`, {
127
137
  checkpointNumber: checkpoint.number,
128
138
  numBlocks: checkpoint.blocks.length,
129
139
  archiveRoot: checkpoint.archive.root.toString(),
@@ -139,14 +149,19 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
139
149
 
140
150
  protected async makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations) {
141
151
  const txPublicSetupAllowList = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
142
- const contractsDB = new PublicContractsDB(this.contractDataSource);
152
+ const contractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings());
143
153
  const guardedFork = new GuardedMerkleTreeOperations(fork);
144
154
 
155
+ const collectDebugLogs = this.debugLogStore.isEnabled;
156
+
157
+ const bindings = this.log.getBindings();
145
158
  const publicTxSimulator = createPublicTxSimulatorForBlockBuilding(
146
159
  guardedFork,
147
160
  contractsDB,
148
161
  globalVariables,
149
162
  this.telemetryClient,
163
+ bindings,
164
+ collectDebugLogs,
150
165
  );
151
166
 
152
167
  const processor = new PublicProcessor(
@@ -156,15 +171,17 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
156
171
  publicTxSimulator,
157
172
  this.dateProvider,
158
173
  this.telemetryClient,
159
- undefined,
174
+ createLogger('simulator:public-processor', bindings),
160
175
  this.config,
176
+ this.debugLogStore,
161
177
  );
162
178
 
163
- const validator = createValidatorForBlockBuilding(
179
+ const validator = createTxValidatorForBlockBuilding(
164
180
  fork,
165
181
  this.contractDataSource,
166
182
  globalVariables,
167
183
  txPublicSetupAllowList,
184
+ this.log.getBindings(),
168
185
  );
169
186
 
170
187
  return {
@@ -176,13 +193,18 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
176
193
 
177
194
  /** Factory for creating checkpoint builders. */
178
195
  export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
196
+ private log: Logger;
197
+
179
198
  constructor(
180
199
  private config: FullNodeBlockBuilderConfig & Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>,
181
200
  private worldState: WorldStateSynchronizer,
182
201
  private contractDataSource: ContractDataSource,
183
202
  private dateProvider: DateProvider,
184
203
  private telemetryClient: TelemetryClient = getTelemetryClient(),
185
- ) {}
204
+ private debugLogStore: DebugLogStore = new NullDebugLogStore(),
205
+ ) {
206
+ this.log = createLogger('checkpoint-builder');
207
+ }
186
208
 
187
209
  public getConfig(): FullNodeBlockBuilderConfig {
188
210
  return this.config;
@@ -198,19 +220,22 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
198
220
  async startCheckpoint(
199
221
  checkpointNumber: CheckpointNumber,
200
222
  constants: CheckpointGlobalVariables,
223
+ feeAssetPriceModifier: bigint,
201
224
  l1ToL2Messages: Fr[],
202
225
  previousCheckpointOutHashes: Fr[],
203
226
  fork: MerkleTreeWriteOperations,
227
+ bindings?: LoggerBindings,
204
228
  ): Promise<CheckpointBuilder> {
205
229
  const stateReference = await fork.getStateReference();
206
230
  const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
207
231
 
208
- log.verbose(`Building new checkpoint ${checkpointNumber}`, {
232
+ this.log.verbose(`Building new checkpoint ${checkpointNumber}`, {
209
233
  checkpointNumber,
210
234
  msgCount: l1ToL2Messages.length,
211
235
  initialStateReference: stateReference.toInspect(),
212
236
  initialArchiveRoot: bufferToHex(archiveTree.root),
213
237
  constants,
238
+ feeAssetPriceModifier,
214
239
  });
215
240
 
216
241
  const lightweightBuilder = await LightweightCheckpointBuilder.startNewCheckpoint(
@@ -219,6 +244,8 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
219
244
  l1ToL2Messages,
220
245
  previousCheckpointOutHashes,
221
246
  fork,
247
+ bindings,
248
+ feeAssetPriceModifier,
222
249
  );
223
250
 
224
251
  return new CheckpointBuilder(
@@ -228,6 +255,8 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
228
255
  this.contractDataSource,
229
256
  this.dateProvider,
230
257
  this.telemetryClient,
258
+ bindings,
259
+ this.debugLogStore,
231
260
  );
232
261
  }
233
262
 
@@ -237,34 +266,47 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
237
266
  async openCheckpoint(
238
267
  checkpointNumber: CheckpointNumber,
239
268
  constants: CheckpointGlobalVariables,
269
+ feeAssetPriceModifier: bigint,
240
270
  l1ToL2Messages: Fr[],
241
271
  previousCheckpointOutHashes: Fr[],
242
272
  fork: MerkleTreeWriteOperations,
243
273
  existingBlocks: L2Block[] = [],
274
+ bindings?: LoggerBindings,
244
275
  ): Promise<CheckpointBuilder> {
245
276
  const stateReference = await fork.getStateReference();
246
277
  const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
247
278
 
248
279
  if (existingBlocks.length === 0) {
249
- return this.startCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork);
280
+ return this.startCheckpoint(
281
+ checkpointNumber,
282
+ constants,
283
+ feeAssetPriceModifier,
284
+ l1ToL2Messages,
285
+ previousCheckpointOutHashes,
286
+ fork,
287
+ bindings,
288
+ );
250
289
  }
251
290
 
252
- log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
291
+ this.log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
253
292
  checkpointNumber,
254
293
  msgCount: l1ToL2Messages.length,
255
294
  existingBlockCount: existingBlocks.length,
256
295
  initialStateReference: stateReference.toInspect(),
257
296
  initialArchiveRoot: bufferToHex(archiveTree.root),
258
297
  constants,
298
+ feeAssetPriceModifier,
259
299
  });
260
300
 
261
301
  const lightweightBuilder = await LightweightCheckpointBuilder.resumeCheckpoint(
262
302
  checkpointNumber,
263
303
  constants,
304
+ feeAssetPriceModifier,
264
305
  l1ToL2Messages,
265
306
  previousCheckpointOutHashes,
266
307
  fork,
267
308
  existingBlocks,
309
+ bindings,
268
310
  );
269
311
 
270
312
  return new CheckpointBuilder(
@@ -274,6 +316,8 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
274
316
  this.contractDataSource,
275
317
  this.dateProvider,
276
318
  this.telemetryClient,
319
+ bindings,
320
+ this.debugLogStore,
277
321
  );
278
322
  }
279
323
 
package/src/config.ts CHANGED
@@ -6,8 +6,8 @@ import {
6
6
  secretValueConfigHelper,
7
7
  } from '@aztec/foundation/config';
8
8
  import { EthAddress } from '@aztec/foundation/eth-address';
9
+ import { validatorHASignerConfigMappings } from '@aztec/stdlib/ha-signing';
9
10
  import type { ValidatorClientConfig } from '@aztec/stdlib/interfaces/server';
10
- import { validatorHASignerConfigMappings } from '@aztec/validator-ha-signer/config';
11
11
 
12
12
  export type { ValidatorClientConfig };
13
13
 
@@ -65,15 +65,18 @@ export const validatorClientConfigMappings: ConfigMappingsType<ValidatorClientCo
65
65
  'Whether to run in fisherman mode: validates all proposals and attestations but does not broadcast attestations or participate in consensus.',
66
66
  ...booleanConfigHelper(false),
67
67
  },
68
- // TODO(palla/mbps): Change default to false once checkpoint validation is stable
69
68
  skipCheckpointProposalValidation: {
70
- description: 'Skip checkpoint proposal validation and always attest (default: true)',
71
- defaultValue: true,
69
+ description: 'Skip checkpoint proposal validation and always attest (default: false)',
70
+ defaultValue: false,
72
71
  },
73
72
  skipPushProposedBlocksToArchiver: {
74
73
  description: 'Skip pushing re-executed blocks to archiver (default: false)',
75
74
  defaultValue: false,
76
75
  },
76
+ attestToEquivocatedProposals: {
77
+ description: 'Agree to attest to equivocated checkpoint proposals (for testing purposes only)',
78
+ ...booleanConfigHelper(false),
79
+ },
77
80
  ...validatorHASignerConfigMappings,
78
81
  };
79
82
 
@@ -95,6 +95,7 @@ export class ValidationService {
95
95
  public createCheckpointProposal(
96
96
  checkpointHeader: CheckpointHeader,
97
97
  archive: Fr,
98
+ feeAssetPriceModifier: bigint,
98
99
  lastBlockInfo: CreateCheckpointProposalLastBlockData | undefined,
99
100
  proposerAttesterAddress: EthAddress | undefined,
100
101
  options: CheckpointProposalOptions,
@@ -119,7 +120,13 @@ export class ValidationService {
119
120
  txs: options.publishFullTxs ? lastBlockInfo.txs : undefined,
120
121
  };
121
122
 
122
- return CheckpointProposal.createProposalFromSigner(checkpointHeader, archive, lastBlock, payloadSigner);
123
+ return CheckpointProposal.createProposalFromSigner(
124
+ checkpointHeader,
125
+ archive,
126
+ feeAssetPriceModifier,
127
+ lastBlock,
128
+ payloadSigner,
129
+ );
123
130
  }
124
131
 
125
132
  /**
@@ -137,7 +144,7 @@ export class ValidationService {
137
144
  attestors: EthAddress[],
138
145
  ): Promise<CheckpointAttestation[]> {
139
146
  // Create the attestation payload from the checkpoint proposal
140
- const payload = new ConsensusPayload(proposal.checkpointHeader, proposal.archive);
147
+ const payload = new ConsensusPayload(proposal.checkpointHeader, proposal.archive, proposal.feeAssetPriceModifier);
141
148
  const buf = Buffer32.fromBuffer(
142
149
  keccak256(payload.getPayloadToSign(SignatureDomainSeparator.checkpointAttestation)),
143
150
  );
package/src/index.ts 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';
@@ -256,8 +256,8 @@ export class HAKeyStore implements ExtendedValidatorKeyStore {
256
256
  /**
257
257
  * Start the high-availability key store
258
258
  */
259
- public start(): Promise<void> {
260
- return Promise.resolve(this.haSigner.start());
259
+ public async start() {
260
+ await this.haSigner.start();
261
261
  }
262
262
 
263
263
  /**
package/src/metrics.ts CHANGED
@@ -6,8 +6,11 @@ import {
6
6
  Metrics,
7
7
  type TelemetryClient,
8
8
  type UpDownCounter,
9
+ createUpDownCounterWithDefault,
9
10
  } from '@aztec/telemetry-client';
10
11
 
12
+ import type { BlockProposalValidationFailureReason } from './block_proposal_handler.js';
13
+
11
14
  export class ValidatorMetrics {
12
15
  private failedReexecutionCounter: UpDownCounter;
13
16
  private successfulAttestationsCount: UpDownCounter;
@@ -21,16 +24,44 @@ export class ValidatorMetrics {
21
24
  constructor(telemetryClient: TelemetryClient) {
22
25
  const meter = telemetryClient.getMeter('Validator');
23
26
 
24
- this.failedReexecutionCounter = meter.createUpDownCounter(Metrics.VALIDATOR_FAILED_REEXECUTION_COUNT);
27
+ this.failedReexecutionCounter = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_FAILED_REEXECUTION_COUNT, {
28
+ [Attributes.STATUS]: ['failed'],
29
+ });
25
30
 
26
- this.successfulAttestationsCount = meter.createUpDownCounter(Metrics.VALIDATOR_ATTESTATION_SUCCESS_COUNT);
31
+ this.successfulAttestationsCount = createUpDownCounterWithDefault(
32
+ meter,
33
+ Metrics.VALIDATOR_ATTESTATION_SUCCESS_COUNT,
34
+ );
27
35
 
28
- this.failedAttestationsBadProposalCount = meter.createUpDownCounter(
36
+ this.failedAttestationsBadProposalCount = createUpDownCounterWithDefault(
37
+ meter,
29
38
  Metrics.VALIDATOR_ATTESTATION_FAILED_BAD_PROPOSAL_COUNT,
39
+ {
40
+ [Attributes.ERROR_TYPE]: [
41
+ 'invalid_proposal',
42
+ 'state_mismatch',
43
+ 'failed_txs',
44
+ 'in_hash_mismatch',
45
+ 'parent_block_wrong_slot',
46
+ ],
47
+ [Attributes.IS_COMMITTEE_MEMBER]: [true, false],
48
+ },
30
49
  );
31
50
 
32
- this.failedAttestationsNodeIssueCount = meter.createUpDownCounter(
51
+ this.failedAttestationsNodeIssueCount = createUpDownCounterWithDefault(
52
+ meter,
33
53
  Metrics.VALIDATOR_ATTESTATION_FAILED_NODE_ISSUE_COUNT,
54
+ {
55
+ [Attributes.ERROR_TYPE]: [
56
+ 'parent_block_not_found',
57
+ 'global_variables_mismatch',
58
+ 'block_number_already_exists',
59
+ 'txs_not_available',
60
+ 'timeout',
61
+ 'unknown_error',
62
+ ],
63
+ [Attributes.IS_COMMITTEE_MEMBER]: [true, false],
64
+ },
34
65
  );
35
66
 
36
67
  this.reexMana = meter.createHistogram(Metrics.VALIDATOR_RE_EXECUTION_MANA);
@@ -58,14 +89,22 @@ export class ValidatorMetrics {
58
89
  this.successfulAttestationsCount.add(num);
59
90
  }
60
91
 
61
- public incFailedAttestationsBadProposal(num: number, reason: string, inCommittee: boolean) {
92
+ public incFailedAttestationsBadProposal(
93
+ num: number,
94
+ reason: BlockProposalValidationFailureReason,
95
+ inCommittee: boolean,
96
+ ) {
62
97
  this.failedAttestationsBadProposalCount.add(num, {
63
98
  [Attributes.ERROR_TYPE]: reason,
64
99
  [Attributes.IS_COMMITTEE_MEMBER]: inCommittee,
65
100
  });
66
101
  }
67
102
 
68
- public incFailedAttestationsNodeIssue(num: number, reason: string, inCommittee: boolean) {
103
+ public incFailedAttestationsNodeIssue(
104
+ num: number,
105
+ reason: BlockProposalValidationFailureReason,
106
+ inCommittee: boolean,
107
+ ) {
69
108
  this.failedAttestationsNodeIssueCount.add(num, {
70
109
  [Attributes.ERROR_TYPE]: reason,
71
110
  [Attributes.IS_COMMITTEE_MEMBER]: inCommittee,