@aztec/validator-client 0.0.1-commit.d431d1c → 0.0.1-commit.d58ff9d0

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 (58) hide show
  1. package/README.md +64 -19
  2. package/dest/checkpoint_builder.d.ts +29 -15
  3. package/dest/checkpoint_builder.d.ts.map +1 -1
  4. package/dest/checkpoint_builder.js +144 -45
  5. package/dest/config.d.ts +9 -3
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +49 -13
  8. package/dest/duties/validation_service.d.ts +12 -13
  9. package/dest/duties/validation_service.d.ts.map +1 -1
  10. package/dest/duties/validation_service.js +33 -45
  11. package/dest/factory.d.ts +10 -4
  12. package/dest/factory.d.ts.map +1 -1
  13. package/dest/factory.js +19 -6
  14. package/dest/index.d.ts +2 -3
  15. package/dest/index.d.ts.map +1 -1
  16. package/dest/index.js +1 -2
  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 +3 -3
  20. package/dest/key_store/web3signer_key_store.d.ts +10 -2
  21. package/dest/key_store/web3signer_key_store.d.ts.map +1 -1
  22. package/dest/key_store/web3signer_key_store.js +32 -41
  23. package/dest/metrics.d.ts +16 -3
  24. package/dest/metrics.d.ts.map +1 -1
  25. package/dest/metrics.js +58 -5
  26. package/dest/proposal_handler.d.ts +165 -0
  27. package/dest/proposal_handler.d.ts.map +1 -0
  28. package/dest/proposal_handler.js +1207 -0
  29. package/dest/validator.d.ts +65 -25
  30. package/dest/validator.d.ts.map +1 -1
  31. package/dest/validator.js +377 -240
  32. package/package.json +19 -17
  33. package/src/checkpoint_builder.ts +196 -54
  34. package/src/config.ts +57 -15
  35. package/src/duties/validation_service.ts +59 -54
  36. package/src/factory.ts +29 -4
  37. package/src/index.ts +1 -2
  38. package/src/key_store/ha_key_store.ts +3 -3
  39. package/src/key_store/web3signer_key_store.ts +43 -59
  40. package/src/metrics.ts +81 -6
  41. package/src/proposal_handler.ts +1314 -0
  42. package/src/validator.ts +512 -291
  43. package/dest/block_proposal_handler.d.ts +0 -65
  44. package/dest/block_proposal_handler.d.ts.map +0 -1
  45. package/dest/block_proposal_handler.js +0 -561
  46. package/dest/tx_validator/index.d.ts +0 -3
  47. package/dest/tx_validator/index.d.ts.map +0 -1
  48. package/dest/tx_validator/index.js +0 -2
  49. package/dest/tx_validator/nullifier_cache.d.ts +0 -14
  50. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  51. package/dest/tx_validator/nullifier_cache.js +0 -24
  52. package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
  53. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  54. package/dest/tx_validator/tx_validator_factory.js +0 -54
  55. package/src/block_proposal_handler.ts +0 -576
  56. package/src/tx_validator/index.ts +0 -2
  57. package/src/tx_validator/nullifier_cache.ts +0 -30
  58. package/src/tx_validator/tx_validator_factory.ts +0 -135
@@ -1,5 +1,6 @@
1
1
  import { normalizeSignature } from '@aztec/foundation/crypto/secp256k1-signer';
2
2
  import { Signature } from '@aztec/foundation/eth-signature';
3
+ /** Default hard timeout (ms) applied to each Web3Signer HTTP request. */ const DEFAULT_WEB3SIGNER_REQUEST_TIMEOUT_MS = 30_000;
3
4
  /**
4
5
  * Web3Signer Key Store
5
6
  *
@@ -8,9 +9,11 @@ import { Signature } from '@aztec/foundation/eth-signature';
8
9
  */ export class Web3SignerKeyStore {
9
10
  addresses;
10
11
  baseUrl;
11
- constructor(addresses, baseUrl){
12
+ requestTimeoutMs;
13
+ constructor(addresses, baseUrl, requestTimeoutMs = DEFAULT_WEB3SIGNER_REQUEST_TIMEOUT_MS){
12
14
  this.addresses = addresses;
13
15
  this.baseUrl = baseUrl;
16
+ this.requestTimeoutMs = requestTimeoutMs;
14
17
  }
15
18
  /**
16
19
  * Get the address of a signer by index
@@ -78,10 +81,9 @@ import { Signature } from '@aztec/foundation/eth-signature';
78
81
  * @param address - The Ethereum address to sign with
79
82
  * @param data - The data to sign
80
83
  * @returns The signature
81
- */ async makeJsonRpcSignRequest(address, data) {
82
- const url = this.baseUrl;
83
- // Use JSON-RPC eth_sign method which automatically applies Ethereum message prefixing
84
- const body = {
84
+ */ makeJsonRpcSignRequest(address, data) {
85
+ // eth_sign automatically applies Ethereum message prefixing to the raw data.
86
+ return this.sendSignRequest({
85
87
  jsonrpc: '2.0',
86
88
  method: 'eth_sign',
87
89
  params: [
@@ -89,37 +91,10 @@ import { Signature } from '@aztec/foundation/eth-signature';
89
91
  data.toString()
90
92
  ],
91
93
  id: 1
92
- };
93
- const response = await fetch(url, {
94
- method: 'POST',
95
- headers: {
96
- 'Content-Type': 'application/json'
97
- },
98
- body: JSON.stringify(body)
99
94
  });
100
- if (!response.ok) {
101
- const errorText = await response.text();
102
- throw new Error(`Web3Signer request failed: ${response.status} ${response.statusText} - ${errorText}`);
103
- }
104
- const result = await response.json();
105
- // Handle JSON-RPC response format
106
- if (result.error) {
107
- throw new Error(`Web3Signer JSON-RPC error: ${result.error.code} - ${result.error.message}`);
108
- }
109
- if (!result.result) {
110
- throw new Error('Invalid response from Web3Signer: no result found');
111
- }
112
- let signatureHex = result.result;
113
- // Ensure the signature has the 0x prefix
114
- if (!signatureHex.startsWith('0x')) {
115
- signatureHex = '0x' + signatureHex;
116
- }
117
- // Parse the signature from the hex string
118
- return normalizeSignature(Signature.fromString(signatureHex));
119
95
  }
120
- async makeJsonRpcSignTypedDataRequest(address, typedData) {
121
- const url = this.baseUrl;
122
- const body = {
96
+ makeJsonRpcSignTypedDataRequest(address, typedData) {
97
+ return this.sendSignRequest({
123
98
  jsonrpc: '2.0',
124
99
  method: 'eth_signTypedData',
125
100
  params: [
@@ -127,19 +102,35 @@ import { Signature } from '@aztec/foundation/eth-signature';
127
102
  JSON.stringify(typedData)
128
103
  ],
129
104
  id: 1
130
- };
131
- const response = await fetch(url, {
132
- method: 'POST',
133
- headers: {
134
- 'Content-Type': 'application/json'
135
- },
136
- body: JSON.stringify(body)
137
105
  });
106
+ }
107
+ /**
108
+ * Send a JSON-RPC request to Web3Signer under a hard request timeout and parse the signature.
109
+ * A timed-out or aborted request is surfaced as a clear timeout error rather than hanging, so a
110
+ * slow or unreachable signer cannot stall an HA signing operation past its own timeout budget.
111
+ */ async sendSignRequest(body) {
112
+ let response;
113
+ try {
114
+ response = await fetch(this.baseUrl, {
115
+ method: 'POST',
116
+ headers: {
117
+ 'Content-Type': 'application/json'
118
+ },
119
+ body: JSON.stringify(body),
120
+ signal: AbortSignal.timeout(this.requestTimeoutMs)
121
+ });
122
+ } catch (err) {
123
+ if ((err instanceof Error || err instanceof DOMException) && (err.name === 'TimeoutError' || err.name === 'AbortError')) {
124
+ throw new Error(`Web3Signer request timed out after ${this.requestTimeoutMs}ms`);
125
+ }
126
+ throw err;
127
+ }
138
128
  if (!response.ok) {
139
129
  const errorText = await response.text();
140
130
  throw new Error(`Web3Signer request failed: ${response.status} ${response.statusText} - ${errorText}`);
141
131
  }
142
132
  const result = await response.json();
133
+ // Handle JSON-RPC response format
143
134
  if (result.error) {
144
135
  throw new Error(`Web3Signer JSON-RPC error: ${result.error.code} - ${result.error.message}`);
145
136
  }
package/dest/metrics.d.ts CHANGED
@@ -1,18 +1,31 @@
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';
5
+ import type { BlockProposalValidationFailureReason } from './proposal_handler.js';
3
6
  export declare class ValidatorMetrics {
4
7
  private failedReexecutionCounter;
5
8
  private successfulAttestationsCount;
6
9
  private failedAttestationsBadProposalCount;
7
10
  private failedAttestationsNodeIssueCount;
11
+ private currentEpoch;
12
+ private attestedEpochCount;
8
13
  private reexMana;
9
14
  private reexTx;
10
15
  private reexDuration;
16
+ private checkpointProposalToPipelinedStateDuration;
17
+ private checkpointProposalReceiveOffsetFromNextSlotBoundary;
11
18
  constructor(telemetryClient: TelemetryClient);
12
19
  recordReex(time: number, txs: number, mManaTotal: number): void;
20
+ recordCheckpointProposalToPipelinedStateDuration(durationMs: number): void;
21
+ recordCheckpointProposalReceiveOffsetFromNextSlotBoundary(offsetMs: number): void;
13
22
  recordFailedReexecution(proposal: BlockProposal): void;
14
23
  incSuccessfulAttestations(num: number): void;
15
- incFailedAttestationsBadProposal(num: number, reason: string, inCommittee: boolean): void;
16
- incFailedAttestationsNodeIssue(num: number, reason: string, inCommittee: boolean): void;
24
+ incFailedAttestationsBadProposal(num: number, reason: BlockProposalValidationFailureReason, inCommittee: boolean): void;
25
+ incFailedAttestationsNodeIssue(num: number, reason: BlockProposalValidationFailureReason, inCommittee: boolean): void;
26
+ /** Update the gauge tracking the current epoch number (proxy for total epochs elapsed). */
27
+ setCurrentEpoch(epoch: EpochNumber): void;
28
+ /** Increment the count of epochs in which the given attester submitted at least one attestation. */
29
+ incAttestedEpochCount(attester: EthAddress): void;
17
30
  }
18
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ldHJpY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUtMLEtBQUssZUFBZSxFQUVyQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLHFCQUFhLGdCQUFnQjtJQUMzQixPQUFPLENBQUMsd0JBQXdCLENBQWdCO0lBQ2hELE9BQU8sQ0FBQywyQkFBMkIsQ0FBZ0I7SUFDbkQsT0FBTyxDQUFDLGtDQUFrQyxDQUFnQjtJQUMxRCxPQUFPLENBQUMsZ0NBQWdDLENBQWdCO0lBRXhELE9BQU8sQ0FBQyxRQUFRLENBQVk7SUFDNUIsT0FBTyxDQUFDLE1BQU0sQ0FBWTtJQUMxQixPQUFPLENBQUMsWUFBWSxDQUFRO0lBRTVCLFlBQVksZUFBZSxFQUFFLGVBQWUsRUFvQjNDO0lBRU0sVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUk5RDtJQUVNLHVCQUF1QixDQUFDLFFBQVEsRUFBRSxhQUFhLFFBTXJEO0lBRU0seUJBQXlCLENBQUMsR0FBRyxFQUFFLE1BQU0sUUFFM0M7SUFFTSxnQ0FBZ0MsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sUUFLeEY7SUFFTSw4QkFBOEIsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sUUFLdEY7Q0FDRiJ9
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ldHJpY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUtMLEtBQUssZUFBZSxFQUdyQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sS0FBSyxFQUFFLG9DQUFvQyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFbEYscUJBQWEsZ0JBQWdCO0lBQzNCLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBZ0I7SUFDaEQsT0FBTyxDQUFDLDJCQUEyQixDQUFnQjtJQUNuRCxPQUFPLENBQUMsa0NBQWtDLENBQWdCO0lBQzFELE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBZ0I7SUFDeEQsT0FBTyxDQUFDLFlBQVksQ0FBUTtJQUM1QixPQUFPLENBQUMsa0JBQWtCLENBQWdCO0lBRTFDLE9BQU8sQ0FBQyxRQUFRLENBQVk7SUFDNUIsT0FBTyxDQUFDLE1BQU0sQ0FBWTtJQUMxQixPQUFPLENBQUMsWUFBWSxDQUFRO0lBQzVCLE9BQU8sQ0FBQywwQ0FBMEMsQ0FBWTtJQUM5RCxPQUFPLENBQUMsbURBQW1ELENBQVk7SUFFdkUsWUFBWSxlQUFlLEVBQUUsZUFBZSxFQTBEM0M7SUFFTSxVQUFVLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBSTlEO0lBRU0sZ0RBQWdELENBQUMsVUFBVSxFQUFFLE1BQU0sUUFFekU7SUFFTSx5REFBeUQsQ0FBQyxRQUFRLEVBQUUsTUFBTSxRQUloRjtJQUVNLHVCQUF1QixDQUFDLFFBQVEsRUFBRSxhQUFhLFFBTXJEO0lBRU0seUJBQXlCLENBQUMsR0FBRyxFQUFFLE1BQU0sUUFFM0M7SUFFTSxnQ0FBZ0MsQ0FDckMsR0FBRyxFQUFFLE1BQU0sRUFDWCxNQUFNLEVBQUUsb0NBQW9DLEVBQzVDLFdBQVcsRUFBRSxPQUFPLFFBTXJCO0lBRU0sOEJBQThCLENBQ25DLEdBQUcsRUFBRSxNQUFNLEVBQ1gsTUFBTSxFQUFFLG9DQUFvQyxFQUM1QyxXQUFXLEVBQUUsT0FBTyxRQU1yQjtJQUVELDJGQUEyRjtJQUNwRixlQUFlLENBQUMsS0FBSyxFQUFFLFdBQVcsUUFFeEM7SUFFRCxvR0FBb0c7SUFDN0YscUJBQXFCLENBQUMsUUFBUSxFQUFFLFVBQVUsUUFFaEQ7Q0FDRiJ9
@@ -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,EAErB,MAAM,yBAAyB,CAAC;AAEjC,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,EAoB3C;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,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,QAKxF;IAEM,8BAA8B,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,QAKtF;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,uBAAuB,CAAC;AAElF,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;IAC5B,OAAO,CAAC,0CAA0C,CAAY;IAC9D,OAAO,CAAC,mDAAmD,CAAY;IAEvE,YAAY,eAAe,EAAE,eAAe,EA0D3C;IAEM,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAI9D;IAEM,gDAAgD,CAAC,UAAU,EAAE,MAAM,QAEzE;IAEM,yDAAyD,CAAC,QAAQ,EAAE,MAAM,QAIhF;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
@@ -1,27 +1,72 @@
1
- import { Attributes, Metrics } from '@aztec/telemetry-client';
1
+ import { Attributes, Metrics, createUpDownCounterWithDefault } from '@aztec/telemetry-client';
2
2
  export class ValidatorMetrics {
3
3
  failedReexecutionCounter;
4
4
  successfulAttestationsCount;
5
5
  failedAttestationsBadProposalCount;
6
6
  failedAttestationsNodeIssueCount;
7
+ currentEpoch;
8
+ attestedEpochCount;
7
9
  reexMana;
8
10
  reexTx;
9
11
  reexDuration;
12
+ checkpointProposalToPipelinedStateDuration;
13
+ checkpointProposalReceiveOffsetFromNextSlotBoundary;
10
14
  constructor(telemetryClient){
11
15
  const meter = telemetryClient.getMeter('Validator');
12
- this.failedReexecutionCounter = meter.createUpDownCounter(Metrics.VALIDATOR_FAILED_REEXECUTION_COUNT);
13
- this.successfulAttestationsCount = meter.createUpDownCounter(Metrics.VALIDATOR_ATTESTATION_SUCCESS_COUNT);
14
- this.failedAttestationsBadProposalCount = meter.createUpDownCounter(Metrics.VALIDATOR_ATTESTATION_FAILED_BAD_PROPOSAL_COUNT);
15
- this.failedAttestationsNodeIssueCount = meter.createUpDownCounter(Metrics.VALIDATOR_ATTESTATION_FAILED_NODE_ISSUE_COUNT);
16
+ this.failedReexecutionCounter = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_FAILED_REEXECUTION_COUNT, {
17
+ [Attributes.STATUS]: [
18
+ 'failed'
19
+ ]
20
+ });
21
+ this.successfulAttestationsCount = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_ATTESTATION_SUCCESS_COUNT);
22
+ this.failedAttestationsBadProposalCount = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_ATTESTATION_FAILED_BAD_PROPOSAL_COUNT, {
23
+ [Attributes.ERROR_TYPE]: [
24
+ 'invalid_proposal',
25
+ 'state_mismatch',
26
+ 'failed_txs',
27
+ 'in_hash_mismatch',
28
+ 'parent_block_wrong_slot'
29
+ ],
30
+ [Attributes.IS_COMMITTEE_MEMBER]: [
31
+ true,
32
+ false
33
+ ]
34
+ });
35
+ this.failedAttestationsNodeIssueCount = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_ATTESTATION_FAILED_NODE_ISSUE_COUNT, {
36
+ [Attributes.ERROR_TYPE]: [
37
+ 'parent_block_not_found',
38
+ 'global_variables_mismatch',
39
+ 'block_number_already_exists',
40
+ 'txs_not_available',
41
+ 'timeout',
42
+ 'unknown_error'
43
+ ],
44
+ [Attributes.IS_COMMITTEE_MEMBER]: [
45
+ true,
46
+ false
47
+ ]
48
+ });
49
+ this.currentEpoch = meter.createGauge(Metrics.VALIDATOR_CURRENT_EPOCH);
50
+ this.attestedEpochCount = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_ATTESTED_EPOCH_COUNT);
16
51
  this.reexMana = meter.createHistogram(Metrics.VALIDATOR_RE_EXECUTION_MANA);
17
52
  this.reexTx = meter.createHistogram(Metrics.VALIDATOR_RE_EXECUTION_TX_COUNT);
18
53
  this.reexDuration = meter.createGauge(Metrics.VALIDATOR_RE_EXECUTION_TIME);
54
+ this.checkpointProposalToPipelinedStateDuration = meter.createHistogram(Metrics.VALIDATOR_CHECKPOINT_PROPOSAL_TO_PIPELINED_STATE_DURATION);
55
+ this.checkpointProposalReceiveOffsetFromNextSlotBoundary = meter.createHistogram(Metrics.VALIDATOR_CHECKPOINT_PROPOSAL_RECEIVE_OFFSET_FROM_NEXT_SLOT_BOUNDARY);
19
56
  }
20
57
  recordReex(time, txs, mManaTotal) {
21
58
  this.reexDuration.record(Math.ceil(time));
22
59
  this.reexTx.record(txs);
23
60
  this.reexMana.record(mManaTotal);
24
61
  }
62
+ recordCheckpointProposalToPipelinedStateDuration(durationMs) {
63
+ this.checkpointProposalToPipelinedStateDuration.record(Math.ceil(durationMs));
64
+ }
65
+ recordCheckpointProposalReceiveOffsetFromNextSlotBoundary(offsetMs) {
66
+ this.checkpointProposalReceiveOffsetFromNextSlotBoundary.record(Math.ceil(Math.abs(offsetMs)), {
67
+ [Attributes.SLOT_BOUNDARY_SIDE]: offsetMs < 0 ? 'before' : 'after'
68
+ });
69
+ }
25
70
  recordFailedReexecution(proposal) {
26
71
  const proposer = proposal.getSender();
27
72
  this.failedReexecutionCounter.add(1, {
@@ -44,4 +89,12 @@ export class ValidatorMetrics {
44
89
  [Attributes.IS_COMMITTEE_MEMBER]: inCommittee
45
90
  });
46
91
  }
92
+ /** Update the gauge tracking the current epoch number (proxy for total epochs elapsed). */ setCurrentEpoch(epoch) {
93
+ this.currentEpoch.record(Number(epoch));
94
+ }
95
+ /** Increment the count of epochs in which the given attester submitted at least one attestation. */ incAttestedEpochCount(attester) {
96
+ this.attestedEpochCount.add(1, {
97
+ [Attributes.ATTESTER_ADDRESS]: attester.toString()
98
+ });
99
+ }
47
100
  }
@@ -0,0 +1,165 @@
1
+ import type { Archiver } from '@aztec/archiver';
2
+ import type { BlobClientInterface } from '@aztec/blob-client/client';
3
+ import type { EpochCache } from '@aztec/epoch-cache';
4
+ import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
5
+ import { Fr } from '@aztec/foundation/curves/bn254';
6
+ import type { LogData } from '@aztec/foundation/log';
7
+ import { DateProvider } from '@aztec/foundation/timer';
8
+ import type { P2P, PeerId } from '@aztec/p2p';
9
+ import { BlockProposalValidator } from '@aztec/p2p/msg_validators';
10
+ import type { L2Block, L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
11
+ import type { CheckpointReexecutionTracker } from '@aztec/stdlib/checkpoint';
12
+ import type { ITxProvider, ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
13
+ import { type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
14
+ import type { BlockProposal, CheckpointProposalCore } from '@aztec/stdlib/p2p';
15
+ import type { ConsensusTimetable } from '@aztec/stdlib/timetable';
16
+ import type { FailedTx, Tx } from '@aztec/stdlib/tx';
17
+ import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
18
+ import type { FullNodeCheckpointsBuilder } from './checkpoint_builder.js';
19
+ import type { ValidatorMetrics } from './metrics.js';
20
+ export type BlockProposalValidationFailureReason = 'invalid_signature' | 'invalid_proposal' | 'parent_block_not_found' | 'parent_block_wrong_slot' | 'in_hash_mismatch' | 'global_variables_mismatch' | 'block_number_already_exists' | 'txs_not_available' | 'state_mismatch' | 'failed_txs' | 'initial_state_mismatch' | 'timeout' | 'block_proposal_beyond_checkpoint' | 'checkpoint_proposal_equivocation' | 'unknown_error';
21
+ type ReexecuteTransactionsResult = {
22
+ block: L2Block;
23
+ failedTxs: FailedTx[];
24
+ reexecutionTimeMs: number;
25
+ totalManaUsed: number;
26
+ };
27
+ export type BlockProposalValidationSuccessResult = {
28
+ isValid: true;
29
+ blockNumber: BlockNumber;
30
+ reexecutionResult?: ReexecuteTransactionsResult;
31
+ };
32
+ export type BlockProposalValidationFailureResult = {
33
+ isValid: false;
34
+ reason: BlockProposalValidationFailureReason;
35
+ blockNumber?: BlockNumber;
36
+ reexecutionResult?: ReexecuteTransactionsResult;
37
+ };
38
+ export type BlockProposalValidationResult = BlockProposalValidationSuccessResult | BlockProposalValidationFailureResult;
39
+ export type CheckpointProposalValidationFailureReason = 'invalid_signature' | 'invalid_fee_asset_price_modifier' | 'last_block_not_found' | 'block_fetch_error' | 'checkpoint_already_published' | 'no_blocks_for_slot' | 'last_block_archive_mismatch' | 'too_many_blocks_in_checkpoint' | 'checkpoint_header_mismatch' | 'archive_mismatch' | 'out_hash_mismatch' | 'checkpoint_validation_failed';
40
+ export type CheckpointProposalValidationSuccessResult = {
41
+ isValid: true;
42
+ checkpointNumber: CheckpointNumber;
43
+ };
44
+ export type CheckpointProposalValidationFailureResult = {
45
+ isValid: false;
46
+ reason: CheckpointProposalValidationFailureReason;
47
+ checkpointNumber?: CheckpointNumber;
48
+ };
49
+ export type CheckpointProposalValidationResult = CheckpointProposalValidationSuccessResult | CheckpointProposalValidationFailureResult;
50
+ export type CheckpointProposalValidationFailureCallback = (proposal: CheckpointProposalCore, result: CheckpointProposalValidationFailureResult, proposalInfo: LogData) => void | Promise<void>;
51
+ /** Block-proposal validation failures that constitute a slashable invalid-block offense. */
52
+ export declare const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT: BlockProposalValidationFailureReason[];
53
+ /** Checkpoint-proposal validation failures that constitute a slashable invalid-checkpoint offense. */
54
+ export declare const SLASHABLE_CHECKPOINT_PROPOSAL_VALIDATION_RESULT: Record<CheckpointProposalValidationFailureReason, boolean>;
55
+ /**
56
+ * Handles block and checkpoint proposals for both validator and non-validator nodes. Also tracks which slots
57
+ * had a slashable invalid proposal or a proposal equivocation, exposing them via the
58
+ * `InvalidProposalSlotSource` interface consumed by the attested-invalid-proposal slashing watcher. The
59
+ * tracking is populated as a side effect of validating/re-executing proposals, so any node that re-executes
60
+ * proposals (the default) can serve it — not only validators.
61
+ */
62
+ export declare class ProposalHandler {
63
+ private checkpointsBuilder;
64
+ private worldState;
65
+ private blockSource;
66
+ private l1ToL2MessageSource;
67
+ private txProvider;
68
+ private blockProposalValidator;
69
+ private epochCache;
70
+ private timetable;
71
+ private config;
72
+ private blobClient;
73
+ private reexecutionTracker;
74
+ private metrics?;
75
+ private dateProvider;
76
+ private log;
77
+ readonly tracer: Tracer;
78
+ /** Cached last checkpoint validation result to avoid double-validation on validator nodes.
79
+ * Keyed by signed-payload hash so two proposals at the same (slot, archive) but with a
80
+ * different `feeAssetPriceModifier` (or any other signed field) are validated independently. */
81
+ private lastCheckpointValidationResult?;
82
+ /** Archiver reference for setting proposed checkpoints (pipelining). Set via register(). */
83
+ private archiver?;
84
+ /** Returns current validator addresses for own-proposal detection. Set via register(). */
85
+ private getOwnValidatorAddresses?;
86
+ /** P2P proposal pool access for deciding when retained proposals should block archiver processing. */
87
+ private p2pClient?;
88
+ private checkpointProposalValidationFailureCallback?;
89
+ /** Slots at which a slashable invalid block or checkpoint proposal was observed. */
90
+ private readonly slotsWithInvalidProposals;
91
+ /** Slots at which a proposal equivocation was observed; suppresses attested-to-invalid-proposal slashing. */
92
+ private readonly slotsWithProposalEquivocation;
93
+ constructor(checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, blockSource: L2BlockSource & L2BlockSink, l1ToL2MessageSource: L1ToL2MessageSource, txProvider: ITxProvider, blockProposalValidator: BlockProposalValidator, epochCache: EpochCache, timetable: ConsensusTimetable, config: ValidatorClientFullConfig, blobClient: BlobClientInterface, reexecutionTracker: CheckpointReexecutionTracker, metrics?: ValidatorMetrics | undefined, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: import("@aztec/foundation/log").Logger);
94
+ updateConfig(config: Partial<ValidatorClientFullConfig>): void;
95
+ setCheckpointProposalValidationFailureCallback(callback?: CheckpointProposalValidationFailureCallback): void;
96
+ /**
97
+ * Records the proposer's own checkpoint proposal as a `valid` outcome in the re-execution
98
+ * tracker. Without this, the node's own checkpoint proposals never flow through
99
+ * `handleCheckpointProposal` (proposers don't validate their own proposals), so its sentinel
100
+ * sees no outcome for slots where it was the proposer and reports itself as inactive.
101
+ *
102
+ * `archive` should be the locally-computed archive (NOT the broadcast archive, which may have
103
+ * been deliberately corrupted in tests via `broadcastInvalidBlockProposal` /
104
+ * `broadcastInvalidCheckpointProposalOnly`). Recording the local archive correctly models the
105
+ * proposer's own view of its own work.
106
+ */
107
+ recordOwnCheckpointProposalAsValid(slot: SlotNumber, archive: Fr, checkpointNumber: CheckpointNumber): void;
108
+ /** Whether a slashable invalid block or checkpoint proposal was observed at the given slot (InvalidProposalSlotSource). */
109
+ hasInvalidProposals(slotNumber: SlotNumber): boolean;
110
+ /** Whether a proposal equivocation was observed at the given slot (InvalidProposalSlotSource). */
111
+ hasProposalEquivocation(slotNumber: SlotNumber): boolean;
112
+ /** Records a slot as having a slashable invalid proposal, for offense observers (sentinel/slasher watchers). */
113
+ markInvalidProposalSlot(slotNumber: SlotNumber): void;
114
+ /** Records a slot as having a proposal equivocation, which suppresses attested-to-invalid-proposal slashing. */
115
+ markProposalEquivocation(slotNumber: SlotNumber): void;
116
+ /**
117
+ * Registers handlers for block and checkpoint proposals on the p2p client.
118
+ * Records the p2p client so validation can inspect retained proposals.
119
+ * Block proposals are registered for non-validator nodes (validators register their own enhanced handler).
120
+ * The all-nodes checkpoint proposal handler is always registered for validation, caching, and pipelining.
121
+ * @param archiver - Archiver reference for setting proposed checkpoints (pipelining)
122
+ * @param getOwnValidatorAddresses - Returns current validator addresses for own-proposal detection
123
+ */
124
+ register(p2pClient: P2P, shouldReexecute: boolean, archiver?: Pick<Archiver, 'addProposedCheckpoint' | 'getProposedCheckpointData'>, getOwnValidatorAddresses?: () => string[]): ProposalHandler;
125
+ handleBlockProposal(proposal: BlockProposal, proposalSender: PeerId, shouldReexecute: boolean): Promise<BlockProposalValidationResult>;
126
+ private validateNewBlockInSlot;
127
+ private getParentBlock;
128
+ private resolveExistingBlockAtNumber;
129
+ private computeCheckpointNumber;
130
+ /**
131
+ * Validates that a non-first block in a checkpoint has consistent global variables with its parent.
132
+ * For blocks with indexWithinCheckpoint > 0, all global variables except blockNumber must match the parent.
133
+ * @returns A failure result if validation fails, undefined if validation passes
134
+ */
135
+ private validateNonFirstBlockInCheckpoint;
136
+ /**
137
+ * Hard re-execution/validation deadline for any block or checkpoint proposal targeting `slotNumber`:
138
+ * the single consensus `attestation_deadline` (`target_slot_start + S - 2E`). This is the latest the
139
+ * checkpoint can land on L1 in the target slot; all nodes agree on it. Loosened from the previous
140
+ * next-wall-clock-slot-boundary bound (see the timetable spec / refactor notes).
141
+ */
142
+ private getReexecutionDeadline;
143
+ private getReexecuteFailureReason;
144
+ reexecuteTransactions(proposal: BlockProposal, blockNumber: BlockNumber, checkpointNumber: CheckpointNumber, txs: Tx[], l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[]): Promise<ReexecuteTransactionsResult>;
145
+ /**
146
+ * Validates a checkpoint proposal, caches the result, and uploads blobs if configured.
147
+ * Returns a cached result if the same proposal (archive + slot) was already validated.
148
+ * Used by both the all-nodes callback (via register) and the validator client (via delegation).
149
+ */
150
+ handleCheckpointProposal(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<CheckpointProposalValidationResult>;
151
+ /**
152
+ * Validates a checkpoint proposal by building the full checkpoint and comparing it with the proposal.
153
+ * @returns Validation result with isValid flag and reason if invalid.
154
+ */
155
+ validateCheckpointProposal(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<CheckpointProposalValidationResult>;
156
+ /** Extracts checkpoint global variables from a block. */
157
+ private extractCheckpointConstants;
158
+ /** Triggers blob upload for a checkpoint if the blob client can upload (fire and forget). */
159
+ protected tryUploadBlobsForCheckpoint(proposal: CheckpointProposalCore, proposalInfo: LogData): void;
160
+ /** Uploads blobs for a checkpoint to the filestore. */
161
+ protected uploadBlobsForCheckpoint(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<void>;
162
+ private setProposedCheckpoint;
163
+ }
164
+ export {};
165
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvcG9zYWxfaGFuZGxlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Byb3Bvc2FsX2hhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUdyRSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVyRCxPQUFPLEVBQ0wsV0FBVyxFQUNYLGdCQUFnQixFQUVoQixVQUFVLEVBQ1gsTUFBTSxpQ0FBaUMsQ0FBQztBQUV6QyxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHcEQsT0FBTyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFHckQsT0FBTyxFQUFFLFlBQVksRUFBUyxNQUFNLHlCQUF5QixDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDOUMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQWEsT0FBTyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRixPQUFPLEtBQUssRUFBRSw0QkFBNEIsRUFBc0IsTUFBTSwwQkFBMEIsQ0FBQztBQUlqRyxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUseUJBQXlCLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN0SCxPQUFPLEVBQ0wsS0FBSyxtQkFBbUIsRUFHekIsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQXlCLHNCQUFzQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdEcsT0FBTyxLQUFLLEVBQUUsa0JBQWtC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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proposal_handler.d.ts","sourceRoot":"","sources":["../src/proposal_handler.ts"],"names":[],"mappings":"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"}