@aztec-labs/validator-client 6.0.0-nightly.20260829

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 (62) hide show
  1. package/README.md +327 -0
  2. package/dest/checkpoint_builder.d.ts +92 -0
  3. package/dest/checkpoint_builder.d.ts.map +1 -0
  4. package/dest/checkpoint_builder.js +272 -0
  5. package/dest/config.d.ts +17 -0
  6. package/dest/config.d.ts.map +1 -0
  7. package/dest/config.js +102 -0
  8. package/dest/duties/validation_service.d.ts +65 -0
  9. package/dest/duties/validation_service.d.ts.map +1 -0
  10. package/dest/duties/validation_service.js +128 -0
  11. package/dest/factory.d.ts +41 -0
  12. package/dest/factory.d.ts.map +1 -0
  13. package/dest/factory.js +19 -0
  14. package/dest/index.d.ts +7 -0
  15. package/dest/index.d.ts.map +1 -0
  16. package/dest/index.js +6 -0
  17. package/dest/key_store/ha_key_store.d.ts +99 -0
  18. package/dest/key_store/ha_key_store.d.ts.map +1 -0
  19. package/dest/key_store/ha_key_store.js +208 -0
  20. package/dest/key_store/index.d.ts +6 -0
  21. package/dest/key_store/index.d.ts.map +1 -0
  22. package/dest/key_store/index.js +5 -0
  23. package/dest/key_store/interface.d.ts +104 -0
  24. package/dest/key_store/interface.d.ts.map +1 -0
  25. package/dest/key_store/interface.js +4 -0
  26. package/dest/key_store/local_key_store.d.ts +63 -0
  27. package/dest/key_store/local_key_store.d.ts.map +1 -0
  28. package/dest/key_store/local_key_store.js +83 -0
  29. package/dest/key_store/node_keystore_adapter.d.ts +151 -0
  30. package/dest/key_store/node_keystore_adapter.d.ts.map +1 -0
  31. package/dest/key_store/node_keystore_adapter.js +330 -0
  32. package/dest/key_store/web3signer_key_store.d.ts +74 -0
  33. package/dest/key_store/web3signer_key_store.d.ts.map +1 -0
  34. package/dest/key_store/web3signer_key_store.js +147 -0
  35. package/dest/metrics.d.ts +31 -0
  36. package/dest/metrics.d.ts.map +1 -0
  37. package/dest/metrics.js +101 -0
  38. package/dest/proposal_handler.d.ts +188 -0
  39. package/dest/proposal_handler.d.ts.map +1 -0
  40. package/dest/proposal_handler.js +1438 -0
  41. package/dest/streaming_inbox_checks.d.ts +103 -0
  42. package/dest/streaming_inbox_checks.d.ts.map +1 -0
  43. package/dest/streaming_inbox_checks.js +112 -0
  44. package/dest/validator.d.ts +137 -0
  45. package/dest/validator.d.ts.map +1 -0
  46. package/dest/validator.js +771 -0
  47. package/package.json +110 -0
  48. package/src/checkpoint_builder.ts +449 -0
  49. package/src/config.ts +130 -0
  50. package/src/duties/validation_service.ts +224 -0
  51. package/src/factory.ts +95 -0
  52. package/src/index.ts +6 -0
  53. package/src/key_store/ha_key_store.ts +268 -0
  54. package/src/key_store/index.ts +5 -0
  55. package/src/key_store/interface.ts +120 -0
  56. package/src/key_store/local_key_store.ts +104 -0
  57. package/src/key_store/node_keystore_adapter.ts +397 -0
  58. package/src/key_store/web3signer_key_store.ts +188 -0
  59. package/src/metrics.ts +150 -0
  60. package/src/proposal_handler.ts +1598 -0
  61. package/src/streaming_inbox_checks.ts +198 -0
  62. package/src/validator.ts +1125 -0
@@ -0,0 +1,147 @@
1
+ import { normalizeSignature } from '@aztec-labs/foundation/crypto/secp256k1-signer';
2
+ import { Signature } from '@aztec-labs/foundation/eth-signature';
3
+ /** Default hard timeout (ms) applied to each Web3Signer HTTP request. */ const DEFAULT_WEB3SIGNER_REQUEST_TIMEOUT_MS = 30_000;
4
+ /**
5
+ * Web3Signer Key Store
6
+ *
7
+ * An implementation of the Key store using Web3Signer remote signing service.
8
+ * This implementation uses the Web3Signer JSON-RPC API for secp256k1 signatures.
9
+ */ export class Web3SignerKeyStore {
10
+ addresses;
11
+ baseUrl;
12
+ requestTimeoutMs;
13
+ constructor(addresses, baseUrl, requestTimeoutMs = DEFAULT_WEB3SIGNER_REQUEST_TIMEOUT_MS){
14
+ this.addresses = addresses;
15
+ this.baseUrl = baseUrl;
16
+ this.requestTimeoutMs = requestTimeoutMs;
17
+ }
18
+ /**
19
+ * Get the address of a signer by index
20
+ *
21
+ * @param index - The index of the signer
22
+ * @returns the address
23
+ */ getAddress(index) {
24
+ if (index >= this.addresses.length) {
25
+ throw new Error(`Index ${index} is out of bounds.`);
26
+ }
27
+ return this.addresses[index];
28
+ }
29
+ /**
30
+ * Get all addresses
31
+ *
32
+ * @returns all addresses
33
+ */ getAddresses() {
34
+ return this.addresses;
35
+ }
36
+ /**
37
+ * Sign EIP-712 typed data with all keystore addresses
38
+ * @param typedData - The complete EIP-712 typed data structure (domain, types, primaryType, message)
39
+ * @param _context - Signing context (ignored by Web3SignerKeyStore, used for HA protection)
40
+ * @return signatures
41
+ */ signTypedData(typedData, _context) {
42
+ return Promise.all(this.addresses.map((address)=>this.makeJsonRpcSignTypedDataRequest(address, typedData)));
43
+ }
44
+ /**
45
+ * Sign EIP-712 typed data with a specific address
46
+ * @param address - The address of the signer to use
47
+ * @param typedData - The complete EIP-712 typed data structure (domain, types, primaryType, message)
48
+ * @param _context - Signing context (ignored by Web3SignerKeyStore, used for HA protection)
49
+ * @returns signature for the specified address
50
+ * @throws Error if the address is not found in the keystore or signing fails
51
+ */ async signTypedDataWithAddress(address, typedData, _context) {
52
+ if (!this.addresses.some((addr)=>addr.equals(address))) {
53
+ throw new Error(`Address ${address.toString()} not found in keystore`);
54
+ }
55
+ return await this.makeJsonRpcSignTypedDataRequest(address, typedData);
56
+ }
57
+ /**
58
+ * Sign a message with all keystore addresses using EIP-191 prefix
59
+ *
60
+ * @param message - The message to sign
61
+ * @param _context - Signing context (ignored by Web3SignerKeyStore, used for HA protection)
62
+ * @return signatures
63
+ */ signMessage(message, _context) {
64
+ return Promise.all(this.addresses.map((address)=>this.makeJsonRpcSignRequest(address, message)));
65
+ }
66
+ /**
67
+ * Sign a message with a specific address using EIP-191 prefix
68
+ * @param address - The address of the signer to use
69
+ * @param message - The message to sign
70
+ * @param _context - Signing context (ignored by Web3SignerKeyStore, used for HA protection)
71
+ * @returns signature for the specified address
72
+ * @throws Error if the address is not found in the keystore or signing fails
73
+ */ async signMessageWithAddress(address, message, _context) {
74
+ if (!this.addresses.some((addr)=>addr.equals(address))) {
75
+ throw new Error(`Address ${address.toString()} not found in keystore`);
76
+ }
77
+ return await this.makeJsonRpcSignRequest(address, message);
78
+ }
79
+ /**
80
+ * Make a JSON-RPC sign request to Web3Signer using eth_sign
81
+ * @param address - The Ethereum address to sign with
82
+ * @param data - The data to sign
83
+ * @returns The signature
84
+ */ makeJsonRpcSignRequest(address, data) {
85
+ // eth_sign automatically applies Ethereum message prefixing to the raw data.
86
+ return this.sendSignRequest({
87
+ jsonrpc: '2.0',
88
+ method: 'eth_sign',
89
+ params: [
90
+ address.toString(),
91
+ data.toString()
92
+ ],
93
+ id: 1
94
+ });
95
+ }
96
+ makeJsonRpcSignTypedDataRequest(address, typedData) {
97
+ return this.sendSignRequest({
98
+ jsonrpc: '2.0',
99
+ method: 'eth_signTypedData',
100
+ params: [
101
+ address.toString(),
102
+ JSON.stringify(typedData)
103
+ ],
104
+ id: 1
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
+ }
128
+ if (!response.ok) {
129
+ const errorText = await response.text();
130
+ throw new Error(`Web3Signer request failed: ${response.status} ${response.statusText} - ${errorText}`);
131
+ }
132
+ const result = await response.json();
133
+ // Handle JSON-RPC response format
134
+ if (result.error) {
135
+ throw new Error(`Web3Signer JSON-RPC error: ${result.error.code} - ${result.error.message}`);
136
+ }
137
+ if (!result.result) {
138
+ throw new Error('Invalid response from Web3Signer: no result found');
139
+ }
140
+ let signatureHex = result.result;
141
+ // Ensure the signature has the 0x prefix
142
+ if (!signatureHex.startsWith('0x')) {
143
+ signatureHex = '0x' + signatureHex;
144
+ }
145
+ return normalizeSignature(Signature.fromString(signatureHex));
146
+ }
147
+ }
@@ -0,0 +1,31 @@
1
+ import type { EpochNumber } from '@aztec-labs/foundation/branded-types';
2
+ import type { EthAddress } from '@aztec-labs/foundation/eth-address';
3
+ import type { BlockProposal } from '@aztec-labs/stdlib/p2p';
4
+ import { type TelemetryClient } from '@aztec-labs/telemetry-client';
5
+ import type { BlockProposalValidationFailureReason } from './proposal_handler.js';
6
+ export declare class ValidatorMetrics {
7
+ private failedReexecutionCounter;
8
+ private successfulAttestationsCount;
9
+ private failedAttestationsBadProposalCount;
10
+ private failedAttestationsNodeIssueCount;
11
+ private currentEpoch;
12
+ private attestedEpochCount;
13
+ private reexMana;
14
+ private reexTx;
15
+ private reexDuration;
16
+ private checkpointProposalToPipelinedStateDuration;
17
+ private checkpointProposalReceiveOffsetFromNextSlotBoundary;
18
+ constructor(telemetryClient: TelemetryClient);
19
+ recordReex(time: number, txs: number, mManaTotal: number): void;
20
+ recordCheckpointProposalToPipelinedStateDuration(durationMs: number): void;
21
+ recordCheckpointProposalReceiveOffsetFromNextSlotBoundary(offsetMs: number): void;
22
+ recordFailedReexecution(proposal: BlockProposal): void;
23
+ incSuccessfulAttestations(num: number): 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;
30
+ }
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ldHJpY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDeEUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDckUsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDNUQsT0FBTyxFQUtMLEtBQUssZUFBZSxFQUdyQixNQUFNLDhCQUE4QixDQUFDO0FBRXRDLE9BQU8sS0FBSyxFQUFFLG9DQUFvQyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFbEYscUJBQWEsZ0JBQWdCO0lBQzNCLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBZ0I7SUFDaEQsT0FBTyxDQUFDLDJCQUEyQixDQUFnQjtJQUNuRCxPQUFPLENBQUMsa0NBQWtDLENBQWdCO0lBQzFELE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBZ0I7SUFDeEQsT0FBTyxDQUFDLFlBQVksQ0FBUTtJQUM1QixPQUFPLENBQUMsa0JBQWtCLENBQWdCO0lBRTFDLE9BQU8sQ0FBQyxRQUFRLENBQVk7SUFDNUIsT0FBTyxDQUFDLE1BQU0sQ0FBWTtJQUMxQixPQUFPLENBQUMsWUFBWSxDQUFRO0lBQzVCLE9BQU8sQ0FBQywwQ0FBMEMsQ0FBWTtJQUM5RCxPQUFPLENBQUMsbURBQW1ELENBQVk7SUFFdkUsWUFBWSxlQUFlLEVBQUUsZUFBZSxFQTJEM0M7SUFFTSxVQUFVLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBSTlEO0lBRU0sZ0RBQWdELENBQUMsVUFBVSxFQUFFLE1BQU0sUUFFekU7SUFFTSx5REFBeUQsQ0FBQyxRQUFRLEVBQUUsTUFBTSxRQUloRjtJQUVNLHVCQUF1QixDQUFDLFFBQVEsRUFBRSxhQUFhLFFBTXJEO0lBRU0seUJBQXlCLENBQUMsR0FBRyxFQUFFLE1BQU0sUUFFM0M7SUFFTSxnQ0FBZ0MsQ0FDckMsR0FBRyxFQUFFLE1BQU0sRUFDWCxNQUFNLEVBQUUsb0NBQW9DLEVBQzVDLFdBQVcsRUFBRSxPQUFPLFFBTXJCO0lBRU0sOEJBQThCLENBQ25DLEdBQUcsRUFBRSxNQUFNLEVBQ1gsTUFBTSxFQUFFLG9DQUFvQyxFQUM1QyxXQUFXLEVBQUUsT0FBTyxRQU1yQjtJQUVELDJGQUEyRjtJQUNwRixlQUFlLENBQUMsS0FBSyxFQUFFLFdBQVcsUUFFeEM7SUFFRCxvR0FBb0c7SUFDN0YscUJBQXFCLENBQUMsUUFBUSxFQUFFLFVBQVUsUUFFaEQ7Q0FDRiJ9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAKL,KAAK,eAAe,EAGrB,MAAM,8BAA8B,CAAC;AAEtC,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,EA2D3C;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"}
@@ -0,0 +1,101 @@
1
+ import { Attributes, Metrics, createUpDownCounterWithDefault } from '@aztec-labs/telemetry-client';
2
+ export class ValidatorMetrics {
3
+ failedReexecutionCounter;
4
+ successfulAttestationsCount;
5
+ failedAttestationsBadProposalCount;
6
+ failedAttestationsNodeIssueCount;
7
+ currentEpoch;
8
+ attestedEpochCount;
9
+ reexMana;
10
+ reexTx;
11
+ reexDuration;
12
+ checkpointProposalToPipelinedStateDuration;
13
+ checkpointProposalReceiveOffsetFromNextSlotBoundary;
14
+ constructor(telemetryClient){
15
+ const meter = telemetryClient.getMeter('Validator');
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
+ 'parent_block_wrong_slot',
28
+ 'duplicate_txs',
29
+ 'invalid_embedded_txs'
30
+ ],
31
+ [Attributes.IS_COMMITTEE_MEMBER]: [
32
+ true,
33
+ false
34
+ ]
35
+ });
36
+ this.failedAttestationsNodeIssueCount = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_ATTESTATION_FAILED_NODE_ISSUE_COUNT, {
37
+ [Attributes.ERROR_TYPE]: [
38
+ 'parent_block_not_found',
39
+ 'global_variables_mismatch',
40
+ 'block_number_already_exists',
41
+ 'txs_not_available',
42
+ 'timeout',
43
+ 'unknown_error'
44
+ ],
45
+ [Attributes.IS_COMMITTEE_MEMBER]: [
46
+ true,
47
+ false
48
+ ]
49
+ });
50
+ this.currentEpoch = meter.createGauge(Metrics.VALIDATOR_CURRENT_EPOCH);
51
+ this.attestedEpochCount = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_ATTESTED_EPOCH_COUNT);
52
+ this.reexMana = meter.createHistogram(Metrics.VALIDATOR_RE_EXECUTION_MANA);
53
+ this.reexTx = meter.createHistogram(Metrics.VALIDATOR_RE_EXECUTION_TX_COUNT);
54
+ this.reexDuration = meter.createGauge(Metrics.VALIDATOR_RE_EXECUTION_TIME);
55
+ this.checkpointProposalToPipelinedStateDuration = meter.createHistogram(Metrics.VALIDATOR_CHECKPOINT_PROPOSAL_TO_PIPELINED_STATE_DURATION);
56
+ this.checkpointProposalReceiveOffsetFromNextSlotBoundary = meter.createHistogram(Metrics.VALIDATOR_CHECKPOINT_PROPOSAL_RECEIVE_OFFSET_FROM_NEXT_SLOT_BOUNDARY);
57
+ }
58
+ recordReex(time, txs, mManaTotal) {
59
+ this.reexDuration.record(Math.ceil(time));
60
+ this.reexTx.record(txs);
61
+ this.reexMana.record(mManaTotal);
62
+ }
63
+ recordCheckpointProposalToPipelinedStateDuration(durationMs) {
64
+ this.checkpointProposalToPipelinedStateDuration.record(Math.ceil(durationMs));
65
+ }
66
+ recordCheckpointProposalReceiveOffsetFromNextSlotBoundary(offsetMs) {
67
+ this.checkpointProposalReceiveOffsetFromNextSlotBoundary.record(Math.ceil(Math.abs(offsetMs)), {
68
+ [Attributes.SLOT_BOUNDARY_SIDE]: offsetMs < 0 ? 'before' : 'after'
69
+ });
70
+ }
71
+ recordFailedReexecution(proposal) {
72
+ const proposer = proposal.getSender();
73
+ this.failedReexecutionCounter.add(1, {
74
+ [Attributes.STATUS]: 'failed',
75
+ [Attributes.BLOCK_PROPOSER]: proposer?.toString() ?? 'unknown'
76
+ });
77
+ }
78
+ incSuccessfulAttestations(num) {
79
+ this.successfulAttestationsCount.add(num);
80
+ }
81
+ incFailedAttestationsBadProposal(num, reason, inCommittee) {
82
+ this.failedAttestationsBadProposalCount.add(num, {
83
+ [Attributes.ERROR_TYPE]: reason,
84
+ [Attributes.IS_COMMITTEE_MEMBER]: inCommittee
85
+ });
86
+ }
87
+ incFailedAttestationsNodeIssue(num, reason, inCommittee) {
88
+ this.failedAttestationsNodeIssueCount.add(num, {
89
+ [Attributes.ERROR_TYPE]: reason,
90
+ [Attributes.IS_COMMITTEE_MEMBER]: inCommittee
91
+ });
92
+ }
93
+ /** Update the gauge tracking the current epoch number (proxy for total epochs elapsed). */ setCurrentEpoch(epoch) {
94
+ this.currentEpoch.record(Number(epoch));
95
+ }
96
+ /** Increment the count of epochs in which the given attester submitted at least one attestation. */ incAttestedEpochCount(attester) {
97
+ this.attestedEpochCount.add(1, {
98
+ [Attributes.ATTESTER_ADDRESS]: attester.toString()
99
+ });
100
+ }
101
+ }
@@ -0,0 +1,188 @@
1
+ import type { Archiver } from '@aztec-labs/archiver';
2
+ import type { BlobClientInterface } from '@aztec-labs/blob-client/client';
3
+ import type { EpochCache } from '@aztec-labs/epoch-cache';
4
+ import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec-labs/foundation/branded-types';
5
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
6
+ import type { LogData } from '@aztec-labs/foundation/log';
7
+ import { DateProvider } from '@aztec-labs/foundation/timer';
8
+ import type { P2P, PeerId } from '@aztec-labs/p2p';
9
+ import type { L2Block, L2BlockSink, L2BlockSource } from '@aztec-labs/stdlib/block';
10
+ import type { CheckpointReexecutionTracker } from '@aztec-labs/stdlib/checkpoint';
11
+ import type { ITxProvider, ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec-labs/stdlib/interfaces/server';
12
+ import { type L1ToL2MessageSource } from '@aztec-labs/stdlib/messaging';
13
+ import type { BlockProposal, CheckpointProposalCore, ValidatedBlockProposal, ValidatedCheckpointProposalCore } from '@aztec-labs/stdlib/p2p';
14
+ import type { ConsensusTimetable } from '@aztec-labs/stdlib/timetable';
15
+ import type { FailedTx, Tx } from '@aztec-labs/stdlib/tx';
16
+ import { type TelemetryClient, type Tracer } from '@aztec-labs/telemetry-client';
17
+ import type { FullNodeCheckpointsBuilder } from './checkpoint_builder.js';
18
+ import type { ValidatorMetrics } from './metrics.js';
19
+ import { type StreamingBlockCheckReason } from './streaming_inbox_checks.js';
20
+ export type BlockProposalValidationFailureReason = 'invalid_signature' | 'invalid_proposal' | 'parent_block_not_found' | 'parent_block_wrong_slot' | StreamingBlockCheckReason | 'global_variables_mismatch' | 'block_number_already_exists' | 'txs_not_available' | 'duplicate_txs' | 'invalid_embedded_txs' | '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' | 'world_state_not_synced' | 'checkpoint_already_published' | 'no_blocks_for_slot' | 'last_block_archive_mismatch' | 'too_many_blocks_in_checkpoint' | 'initial_archive_mismatch' | 'checkpoint_header_mismatch' | 'archive_mismatch' | 'out_hash_mismatch' | 'inbox_consumption_insufficient' | '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 epochCache;
69
+ private timetable;
70
+ private config;
71
+ private blobClient;
72
+ private reexecutionTracker;
73
+ private metrics?;
74
+ private dateProvider;
75
+ private log;
76
+ readonly tracer: Tracer;
77
+ /** Cached last checkpoint validation result to avoid double-validation on validator nodes.
78
+ * Keyed by signed-payload hash so two proposals at the same (slot, archive) but with a
79
+ * different `feeAssetPriceModifier` (or any other signed field) are validated independently. */
80
+ private lastCheckpointValidationResult?;
81
+ /** Archiver reference for setting proposed checkpoints (pipelining). Set via register(). */
82
+ private archiver?;
83
+ /** Returns current validator addresses for own-proposal detection. Set via register(). */
84
+ private getOwnValidatorAddresses?;
85
+ /** P2P proposal pool access for deciding when retained proposals should block archiver processing. */
86
+ private p2pClient?;
87
+ private checkpointProposalValidationFailureCallback?;
88
+ /** Slots at which a slashable invalid block or checkpoint proposal was observed. */
89
+ private readonly slotsWithInvalidProposals;
90
+ /** Slots at which a proposal equivocation was observed; suppresses attested-to-invalid-proposal slashing. */
91
+ private readonly slotsWithProposalEquivocation;
92
+ constructor(checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, blockSource: L2BlockSource & L2BlockSink, l1ToL2MessageSource: L1ToL2MessageSource, txProvider: ITxProvider, epochCache: EpochCache, timetable: ConsensusTimetable, config: ValidatorClientFullConfig, blobClient: BlobClientInterface, reexecutionTracker: CheckpointReexecutionTracker, metrics?: ValidatorMetrics | undefined, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: import("@aztec-labs/foundation/log").Logger);
93
+ updateConfig(config: Partial<ValidatorClientFullConfig>): void;
94
+ setCheckpointProposalValidationFailureCallback(callback?: CheckpointProposalValidationFailureCallback): void;
95
+ /**
96
+ * Records the proposer's own checkpoint proposal as a `valid` outcome in the re-execution
97
+ * tracker. Without this, the node's own checkpoint proposals never flow through
98
+ * `handleCheckpointProposal` (proposers don't validate their own proposals), so its sentinel
99
+ * sees no outcome for slots where it was the proposer and reports itself as inactive.
100
+ *
101
+ * `archive` should be the locally-computed archive (NOT the broadcast archive, which may have
102
+ * been deliberately corrupted in tests via `broadcastInvalidBlockProposal` /
103
+ * `broadcastInvalidCheckpointProposalOnly`). Recording the local archive correctly models the
104
+ * proposer's own view of its own work.
105
+ */
106
+ recordOwnCheckpointProposalAsValid(slot: SlotNumber, archive: Fr, checkpointNumber: CheckpointNumber): void;
107
+ /** Whether a slashable invalid block or checkpoint proposal was observed at the given slot (InvalidProposalSlotSource). */
108
+ hasInvalidProposals(slotNumber: SlotNumber): boolean;
109
+ /** Whether a proposal equivocation was observed at the given slot (InvalidProposalSlotSource). */
110
+ hasProposalEquivocation(slotNumber: SlotNumber): boolean;
111
+ /** Records a slot as having a slashable invalid proposal, for offense observers (sentinel/slasher watchers). */
112
+ markInvalidProposalSlot(slotNumber: SlotNumber): void;
113
+ /** Records a slot as having a proposal equivocation, which suppresses attested-to-invalid-proposal slashing. */
114
+ markProposalEquivocation(slotNumber: SlotNumber): void;
115
+ /**
116
+ * Registers handlers for block and checkpoint proposals on the p2p client.
117
+ * Records the p2p client so validation can inspect retained proposals.
118
+ * Block proposals are registered for non-validator nodes (validators register their own enhanced handler).
119
+ * The all-nodes checkpoint proposal handler is always registered for validation, caching, and pipelining.
120
+ * @param archiver - Archiver reference for setting proposed checkpoints (pipelining)
121
+ * @param getOwnValidatorAddresses - Returns current validator addresses for own-proposal detection
122
+ */
123
+ register(p2pClient: P2P, shouldReexecute: boolean, archiver?: Pick<Archiver, 'addProposedCheckpoint' | 'getProposedCheckpointData'>, getOwnValidatorAddresses?: () => string[]): ProposalHandler;
124
+ /**
125
+ * Processes a block proposal: collects its txs and, if requested, re-executes them to check the resulting
126
+ * block against the proposal. Expects the proposal to have already passed p2p ingress validation (signature
127
+ * context, signature, expected proposer, index within checkpoint, tx field checks, and the receive-window
128
+ * timeliness check) — none of those are re-applied here, and only deterministic properties of the payload
129
+ * are validated before processing.
130
+ */
131
+ handleBlockProposal(proposal: ValidatedBlockProposal, proposalSender: PeerId, shouldReexecute: boolean): Promise<BlockProposalValidationResult>;
132
+ private collectProposalTxs;
133
+ private validateNewBlockInSlot;
134
+ private getParentBlock;
135
+ private resolveExistingBlockAtNumber;
136
+ private computeCheckpointNumber;
137
+ /**
138
+ * Validates that a non-first block in a checkpoint has consistent global variables with its parent.
139
+ * For blocks with indexWithinCheckpoint > 0, all global variables except blockNumber must match the parent.
140
+ * @returns A failure result if validation fails, undefined if validation passes
141
+ */
142
+ private validateNonFirstBlockInCheckpoint;
143
+ /**
144
+ * Hard re-execution/validation deadline for any block or checkpoint proposal targeting `slotNumber`:
145
+ * the single consensus `attestation_deadline` (`target_slot_start + S - 2E`). This is the latest the
146
+ * checkpoint can land on L1 in the target slot; all nodes agree on it. Loosened from the previous
147
+ * next-wall-clock-slot-boundary bound (see the timetable spec / refactor notes).
148
+ */
149
+ private getReexecutionDeadline;
150
+ private getReexecuteFailureReason;
151
+ private checkStreamingBlockMetadata;
152
+ /** A block's L1-to-L2 message tree leaf count: the cumulative Inbox message count it consumed through. */
153
+ private blockLeafCount;
154
+ /** The cumulative Inbox message count consumed through a block: its L1-to-L2 tree leaf count (0 at genesis). */
155
+ private getConsumedMsgTotal;
156
+ /**
157
+ * The cumulative Inbox message count consumed as of the parent checkpoint (the per-checkpoint cap origin). For a
158
+ * checkpoint's first block this is the parent block's total; for a later block it is the leaf count of the block
159
+ * before the checkpoint's first block. Returns undefined when that block has not synced locally.
160
+ */
161
+ private resolveCheckpointStartTotal;
162
+ private getPreBlockConsumedTotal;
163
+ private isLastBlockConsumptionSufficient;
164
+ private deriveCheckpointConsumedMessages;
165
+ reexecuteTransactions(proposal: BlockProposal, blockNumber: BlockNumber, checkpointNumber: CheckpointNumber, txs: Tx[], l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[], previousInboxRollingHash: Fr): Promise<ReexecuteTransactionsResult>;
166
+ /**
167
+ * Validates a checkpoint proposal, caches the result, and uploads blobs if configured.
168
+ * Returns a cached result if the same proposal (archive + slot) was already validated.
169
+ * Used by both the all-nodes callback (via register) and the validator client (via delegation).
170
+ * Expects the proposal to have already passed p2p ingress validation (expected proposer and receive-window
171
+ * timeliness); only deterministic properties of the signed payload are checked here.
172
+ */
173
+ handleCheckpointProposal(proposal: ValidatedCheckpointProposalCore, proposalInfo: LogData): Promise<CheckpointProposalValidationResult>;
174
+ /**
175
+ * Validates a checkpoint proposal by building the full checkpoint and comparing it with the proposal.
176
+ * @returns Validation result with isValid flag and reason if invalid.
177
+ */
178
+ validateCheckpointProposal(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<CheckpointProposalValidationResult>;
179
+ /** Extracts checkpoint global variables from a block. */
180
+ private extractCheckpointConstants;
181
+ /** Triggers blob upload for a checkpoint if the blob client can upload (fire and forget). */
182
+ protected tryUploadBlobsForCheckpoint(proposal: CheckpointProposalCore, proposalInfo: LogData): void;
183
+ /** Uploads blobs for a checkpoint to the filestore. */
184
+ protected uploadBlobsForCheckpoint(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<void>;
185
+ private setProposedCheckpoint;
186
+ }
187
+ export {};
188
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvcG9zYWxfaGFuZGxlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Byb3Bvc2FsX2hhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDckQsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQVExRSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUxRCxPQUFPLEVBQ0wsV0FBVyxFQUNYLGdCQUFnQixFQUVoQixVQUFVLEVBQ1gsTUFBTSxzQ0FBc0MsQ0FBQztBQUU5QyxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFHekQsT0FBTyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFHMUQsT0FBTyxFQUFFLFlBQVksRUFBUyxNQUFNLDhCQUE4QixDQUFDO0FBRW5FLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssRUFBYSxPQUFPLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQy9GLE9BQU8sS0FBSyxFQUFFLDRCQUE0QixFQUFzQixNQUFNLCtCQUErQixDQUFDO0FBUXRHLE9BQU8sS0FBSyxFQUNWLFdBQVcsRUFFWCx5QkFBeUIsRUFDekIsc0JBQXNCLEVBQ3ZCLE1BQU0sc0NBQXNDLENBQUM7QUFDOUMsT0FBTyxFQUNMLEtBQUssbUJBQW1CLEVBSXpCLE1BQU0sOEJBQThCLENBQUM7QUFDdEMsT0FBTyxLQUFLLEVBQ1YsYUFBYSxFQUViLHNCQUFzQixFQUN0QixzQkFBc0IsRUFDdEIsK0JBQStCLEVBQ2hDLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw4QkFB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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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"}