@aztec/validator-client 0.85.0 → 0.86.0

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.
@@ -28,7 +28,7 @@ export class ValidationService {
28
28
  * @returns attestation
29
29
  */ async attestToProposal(proposal) {
30
30
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7961): check that the current validator is correct
31
- const buf = Buffer32.fromBuffer(keccak256(await proposal.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation)));
31
+ const buf = Buffer32.fromBuffer(keccak256(proposal.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation)));
32
32
  const sig = await this.keyStore.signMessage(buf);
33
33
  return new BlockAttestation(proposal.payload, sig);
34
34
  }
package/dest/metrics.d.ts CHANGED
@@ -3,9 +3,13 @@ import { type TelemetryClient } from '@aztec/telemetry-client';
3
3
  export declare class ValidatorMetrics {
4
4
  private reExecutionTime;
5
5
  private failedReexecutionCounter;
6
+ private attestationsCount;
7
+ private failedAttestationsCount;
6
8
  constructor(telemetryClient: TelemetryClient);
7
9
  reExecutionTimer(): () => void;
8
10
  recordReExecutionTime(time: number): void;
9
- recordFailedReexecution(proposal: BlockProposal): Promise<void>;
11
+ recordFailedReexecution(proposal: BlockProposal): void;
12
+ incAttestations(): void;
13
+ incFailedAttestations(reason: string): void;
10
14
  }
11
15
  //# sourceMappingURL=metrics.d.ts.map
@@ -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,EAIL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,wBAAwB,CAAgB;gBAEpC,eAAe,EAAE,eAAe;IAgBrC,gBAAgB,IAAI,MAAM,IAAI;IAQ9B,qBAAqB,CAAC,IAAI,EAAE,MAAM;IAI5B,uBAAuB,CAAC,QAAQ,EAAE,aAAa;CAM7D"}
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,EAIL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,uBAAuB,CAAgB;gBAEnC,eAAe,EAAE,eAAe;IA0BrC,gBAAgB,IAAI,MAAM,IAAI;IAQ9B,qBAAqB,CAAC,IAAI,EAAE,MAAM;IAIlC,uBAAuB,CAAC,QAAQ,EAAE,aAAa;IAO/C,eAAe;IAIf,qBAAqB,CAAC,MAAM,EAAE,MAAM;CAK5C"}
package/dest/metrics.js CHANGED
@@ -2,6 +2,8 @@ import { Attributes, Metrics, ValueType } from '@aztec/telemetry-client';
2
2
  export class ValidatorMetrics {
3
3
  reExecutionTime;
4
4
  failedReexecutionCounter;
5
+ attestationsCount;
6
+ failedAttestationsCount;
5
7
  constructor(telemetryClient){
6
8
  const meter = telemetryClient.getMeter('Validator');
7
9
  this.failedReexecutionCounter = meter.createUpDownCounter(Metrics.VALIDATOR_FAILED_REEXECUTION_COUNT, {
@@ -14,6 +16,14 @@ export class ValidatorMetrics {
14
16
  unit: 'ms',
15
17
  valueType: ValueType.DOUBLE
16
18
  });
19
+ this.attestationsCount = meter.createUpDownCounter(Metrics.VALIDATOR_ATTESTATION_COUNT, {
20
+ description: 'The number of attestations',
21
+ valueType: ValueType.INT
22
+ });
23
+ this.failedAttestationsCount = meter.createUpDownCounter(Metrics.VALIDATOR_FAILED_ATTESTATION_COUNT, {
24
+ description: 'The number of failed attestations',
25
+ valueType: ValueType.INT
26
+ });
17
27
  }
18
28
  reExecutionTimer() {
19
29
  const start = performance.now();
@@ -25,10 +35,18 @@ export class ValidatorMetrics {
25
35
  recordReExecutionTime(time) {
26
36
  this.reExecutionTime.record(time);
27
37
  }
28
- async recordFailedReexecution(proposal) {
38
+ recordFailedReexecution(proposal) {
29
39
  this.failedReexecutionCounter.add(1, {
30
40
  [Attributes.STATUS]: 'failed',
31
- [Attributes.BLOCK_PROPOSER]: (await proposal.getSender())?.toString()
41
+ [Attributes.BLOCK_PROPOSER]: proposal.getSender().toString()
42
+ });
43
+ }
44
+ incAttestations() {
45
+ this.attestationsCount.add(1);
46
+ }
47
+ incFailedAttestations(reason) {
48
+ this.failedAttestationsCount.add(1, {
49
+ [Attributes.ERROR_TYPE]: reason
32
50
  });
33
51
  }
34
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAInD,OAAO,EAAE,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,KAAK,eAAe,EAAE,UAAU,EAAsB,MAAM,yBAAyB,CAAC;AAE/F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAWzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAIlE;;;;GAIG;AACH,KAAK,oBAAoB,GAAG,CAC1B,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,qBAAqB,CAAC,EAAE,CAAC,EAC7C,eAAe,EAAE,eAAe,EAChC,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,KAC9B,OAAO,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;IACf,uBAAuB,EAAE,MAAM,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,KAAK,CAAC;CAC3B,CAAC,CAAC;AAEH,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,4BAA4B,IAAI,IAAI,CAAC;IACrC,oBAAoB,CAAC,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAG/D,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IACzG,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAEhD,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IACtD,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CAC7G;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,UAAW,YAAW,SAAS;IAiBhE,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,YAAY;IAEpB,OAAO,CAAC,GAAG;IAtBb,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,OAAO,CAAmB;IAGlC,OAAO,CAAC,gBAAgB,CAAC,CAAgB;IAGzC,OAAO,CAAC,YAAY,CAAC,CAAmC;IAExD,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,oBAAoB,CAAiB;IAE7C,OAAO,CAAC,sBAAsB,CAAyB;gBAG7C,QAAQ,EAAE,iBAAiB,EAC3B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,GAAG,EACd,MAAM,EAAE,qBAAqB,EAC7B,YAAY,GAAE,YAAiC,EACvD,SAAS,GAAE,eAAsC,EACzC,GAAG,yCAA4B;YAiB3B,yBAAyB;IAiBvC,MAAM,CAAC,GAAG,CACR,MAAM,EAAE,qBAAqB,EAC7B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,GAAG,EACd,YAAY,GAAE,YAAiC,EAC/C,SAAS,GAAE,eAAsC;IAc5C,mBAAmB;IAIb,KAAK;IAeL,IAAI;IAIV,4BAA4B;IAOnC;;;;OAIG;IACI,oBAAoB,CAAC,YAAY,EAAE,oBAAoB;IAIxD,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IA4DtF;;;OAGG;IACG,qBAAqB,CAAC,QAAQ,EAAE,aAAa;IA2CnD;;;;;;;OAOG;IACG,8BAA8B,CAAC,QAAQ,EAAE,aAAa;IAkBtD,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAW9G,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAK/C,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;YA2CnG,kBAAkB;CAKjC"}
package/dest/validator.js CHANGED
@@ -116,6 +116,7 @@ import { ValidatorMetrics } from './metrics.js';
116
116
  const invalidProposal = await this.blockProposalValidator.validate(proposal);
117
117
  if (invalidProposal) {
118
118
  this.log.verbose(`Proposal is not valid, skipping attestation`);
119
+ this.metrics.incFailedAttestations('invalid_proposal');
119
120
  return undefined;
120
121
  }
121
122
  // Check that all of the transactions in the proposal are available in the tx pool before attesting
@@ -127,6 +128,11 @@ import { ValidatorMetrics } from './metrics.js';
127
128
  await this.reExecuteTransactions(proposal);
128
129
  }
129
130
  } catch (error) {
131
+ if (error instanceof Error) {
132
+ this.metrics.incFailedAttestations(error.name);
133
+ } else {
134
+ this.metrics.incFailedAttestations('unknown');
135
+ }
130
136
  // If the transactions are not available, then we should not attempt to attest
131
137
  if (error instanceof TransactionsNotAvailableError) {
132
138
  this.log.error(`Transactions not available, skipping attestation`, error, proposalInfo);
@@ -139,6 +145,7 @@ import { ValidatorMetrics } from './metrics.js';
139
145
  }
140
146
  // Provided all of the above checks pass, we can attest to the proposal
141
147
  this.log.info(`Attesting to proposal for slot ${slotNumber}`, proposalInfo);
148
+ this.metrics.incAttestations();
142
149
  // If the above function does not throw an error, then we can attest to the proposal
143
150
  return this.doAttestToProposal(proposal);
144
151
  }
@@ -164,16 +171,16 @@ import { ValidatorMetrics } from './metrics.js';
164
171
  stopTimer();
165
172
  this.log.verbose(`Transaction re-execution complete`);
166
173
  if (numFailedTxs > 0) {
167
- await this.metrics.recordFailedReexecution(proposal);
174
+ this.metrics.recordFailedReexecution(proposal);
168
175
  throw new ReExFailedTxsError(numFailedTxs);
169
176
  }
170
177
  if (block.body.txEffects.length !== txHashes.length) {
171
- await this.metrics.recordFailedReexecution(proposal);
178
+ this.metrics.recordFailedReexecution(proposal);
172
179
  throw new ReExTimeoutError();
173
180
  }
174
181
  // This function will throw an error if state updates do not match
175
182
  if (!block.archive.root.equals(proposal.archive)) {
176
- await this.metrics.recordFailedReexecution(proposal);
183
+ this.metrics.recordFailedReexecution(proposal);
177
184
  throw new ReExStateMismatchError();
178
185
  }
179
186
  }
@@ -227,9 +234,9 @@ import { ValidatorMetrics } from './metrics.js';
227
234
  let attestations = [];
228
235
  while(true){
229
236
  const collectedAttestations = await this.p2pClient.getAttestationsForSlot(slot, proposalId);
230
- const oldSenders = await Promise.all(attestations.map((attestation)=>attestation.getSender()));
237
+ const oldSenders = attestations.map((attestation)=>attestation.getSender());
231
238
  for (const collected of collectedAttestations){
232
- const collectedSender = await collected.getSender();
239
+ const collectedSender = collected.getSender();
233
240
  if (!collectedSender.equals(me) && !oldSenders.some((sender)=>sender.equals(collectedSender))) {
234
241
  this.log.debug(`Received attestation for slot ${slot} from ${collectedSender.toString()}`);
235
242
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/validator-client",
3
- "version": "0.85.0",
3
+ "version": "0.86.0",
4
4
  "main": "dest/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -21,8 +21,6 @@
21
21
  "build": "yarn clean && tsc -b",
22
22
  "build:dev": "tsc -b --watch",
23
23
  "clean": "rm -rf ./dest .tsbuildinfo",
24
- "formatting": "run -T prettier --check ./src && run -T eslint ./src",
25
- "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
26
24
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
27
25
  },
28
26
  "inherits": [
@@ -62,12 +60,12 @@
62
60
  ]
63
61
  },
64
62
  "dependencies": {
65
- "@aztec/epoch-cache": "0.85.0",
66
- "@aztec/ethereum": "0.85.0",
67
- "@aztec/foundation": "0.85.0",
68
- "@aztec/p2p": "0.85.0",
69
- "@aztec/stdlib": "0.85.0",
70
- "@aztec/telemetry-client": "0.85.0",
63
+ "@aztec/epoch-cache": "0.86.0",
64
+ "@aztec/ethereum": "0.86.0",
65
+ "@aztec/foundation": "0.86.0",
66
+ "@aztec/p2p": "0.86.0",
67
+ "@aztec/stdlib": "0.86.0",
68
+ "@aztec/telemetry-client": "0.86.0",
71
69
  "koa": "^2.16.1",
72
70
  "koa-router": "^12.0.0",
73
71
  "tslib": "^2.4.0",
@@ -37,7 +37,7 @@ export class ValidationService {
37
37
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7961): check that the current validator is correct
38
38
 
39
39
  const buf = Buffer32.fromBuffer(
40
- keccak256(await proposal.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation)),
40
+ keccak256(proposal.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation)),
41
41
  );
42
42
  const sig = await this.keyStore.signMessage(buf);
43
43
  return new BlockAttestation(proposal.payload, sig);
package/src/metrics.ts CHANGED
@@ -11,6 +11,8 @@ import {
11
11
  export class ValidatorMetrics {
12
12
  private reExecutionTime: Gauge;
13
13
  private failedReexecutionCounter: UpDownCounter;
14
+ private attestationsCount: UpDownCounter;
15
+ private failedAttestationsCount: UpDownCounter;
14
16
 
15
17
  constructor(telemetryClient: TelemetryClient) {
16
18
  const meter = telemetryClient.getMeter('Validator');
@@ -26,6 +28,16 @@ export class ValidatorMetrics {
26
28
  unit: 'ms',
27
29
  valueType: ValueType.DOUBLE,
28
30
  });
31
+
32
+ this.attestationsCount = meter.createUpDownCounter(Metrics.VALIDATOR_ATTESTATION_COUNT, {
33
+ description: 'The number of attestations',
34
+ valueType: ValueType.INT,
35
+ });
36
+
37
+ this.failedAttestationsCount = meter.createUpDownCounter(Metrics.VALIDATOR_FAILED_ATTESTATION_COUNT, {
38
+ description: 'The number of failed attestations',
39
+ valueType: ValueType.INT,
40
+ });
29
41
  }
30
42
 
31
43
  public reExecutionTimer(): () => void {
@@ -40,10 +52,20 @@ export class ValidatorMetrics {
40
52
  this.reExecutionTime.record(time);
41
53
  }
42
54
 
43
- public async recordFailedReexecution(proposal: BlockProposal) {
55
+ public recordFailedReexecution(proposal: BlockProposal) {
44
56
  this.failedReexecutionCounter.add(1, {
45
57
  [Attributes.STATUS]: 'failed',
46
- [Attributes.BLOCK_PROPOSER]: (await proposal.getSender())?.toString(),
58
+ [Attributes.BLOCK_PROPOSER]: proposal.getSender().toString(),
59
+ });
60
+ }
61
+
62
+ public incAttestations() {
63
+ this.attestationsCount.add(1);
64
+ }
65
+
66
+ public incFailedAttestations(reason: string) {
67
+ this.failedAttestationsCount.add(1, {
68
+ [Attributes.ERROR_TYPE]: reason,
47
69
  });
48
70
  }
49
71
  }
package/src/validator.ts CHANGED
@@ -197,6 +197,7 @@ export class ValidatorClient extends WithTracer implements Validator {
197
197
  const invalidProposal = await this.blockProposalValidator.validate(proposal);
198
198
  if (invalidProposal) {
199
199
  this.log.verbose(`Proposal is not valid, skipping attestation`);
200
+ this.metrics.incFailedAttestations('invalid_proposal');
200
201
  return undefined;
201
202
  }
202
203
 
@@ -210,6 +211,12 @@ export class ValidatorClient extends WithTracer implements Validator {
210
211
  await this.reExecuteTransactions(proposal);
211
212
  }
212
213
  } catch (error: any) {
214
+ if (error instanceof Error) {
215
+ this.metrics.incFailedAttestations(error.name);
216
+ } else {
217
+ this.metrics.incFailedAttestations('unknown');
218
+ }
219
+
213
220
  // If the transactions are not available, then we should not attempt to attest
214
221
  if (error instanceof TransactionsNotAvailableError) {
215
222
  this.log.error(`Transactions not available, skipping attestation`, error, proposalInfo);
@@ -223,6 +230,7 @@ export class ValidatorClient extends WithTracer implements Validator {
223
230
 
224
231
  // Provided all of the above checks pass, we can attest to the proposal
225
232
  this.log.info(`Attesting to proposal for slot ${slotNumber}`, proposalInfo);
233
+ this.metrics.incAttestations();
226
234
 
227
235
  // If the above function does not throw an error, then we can attest to the proposal
228
236
  return this.doAttestToProposal(proposal);
@@ -259,18 +267,18 @@ export class ValidatorClient extends WithTracer implements Validator {
259
267
  this.log.verbose(`Transaction re-execution complete`);
260
268
 
261
269
  if (numFailedTxs > 0) {
262
- await this.metrics.recordFailedReexecution(proposal);
270
+ this.metrics.recordFailedReexecution(proposal);
263
271
  throw new ReExFailedTxsError(numFailedTxs);
264
272
  }
265
273
 
266
274
  if (block.body.txEffects.length !== txHashes.length) {
267
- await this.metrics.recordFailedReexecution(proposal);
275
+ this.metrics.recordFailedReexecution(proposal);
268
276
  throw new ReExTimeoutError();
269
277
  }
270
278
 
271
279
  // This function will throw an error if state updates do not match
272
280
  if (!block.archive.root.equals(proposal.archive)) {
273
- await this.metrics.recordFailedReexecution(proposal);
281
+ this.metrics.recordFailedReexecution(proposal);
274
282
  throw new ReExStateMismatchError();
275
283
  }
276
284
  }
@@ -336,9 +344,9 @@ export class ValidatorClient extends WithTracer implements Validator {
336
344
  let attestations: BlockAttestation[] = [];
337
345
  while (true) {
338
346
  const collectedAttestations = await this.p2pClient.getAttestationsForSlot(slot, proposalId);
339
- const oldSenders = await Promise.all(attestations.map(attestation => attestation.getSender()));
347
+ const oldSenders = attestations.map(attestation => attestation.getSender());
340
348
  for (const collected of collectedAttestations) {
341
- const collectedSender = await collected.getSender();
349
+ const collectedSender = collected.getSender();
342
350
  if (!collectedSender.equals(me) && !oldSenders.some(sender => sender.equals(collectedSender))) {
343
351
  this.log.debug(`Received attestation for slot ${slot} from ${collectedSender.toString()}`);
344
352
  }