@aztec/validator-client 0.0.1-commit.e61ad554 → 0.0.1-commit.ee80a48
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.
- package/dest/block_proposal_handler.d.ts +3 -4
- package/dest/block_proposal_handler.d.ts.map +1 -1
- package/dest/block_proposal_handler.js +5 -4
- package/dest/checkpoint_builder.d.ts +10 -11
- package/dest/checkpoint_builder.d.ts.map +1 -1
- package/dest/checkpoint_builder.js +38 -25
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +2 -3
- package/dest/metrics.d.ts +4 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +34 -5
- package/dest/tx_validator/tx_validator_factory.d.ts +4 -3
- package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
- package/dest/tx_validator/tx_validator_factory.js +16 -16
- package/dest/validator.d.ts +7 -8
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +21 -27
- package/package.json +19 -17
- package/src/block_proposal_handler.ts +7 -6
- package/src/checkpoint_builder.ts +55 -25
- package/src/config.ts +2 -3
- package/src/metrics.ts +45 -6
- package/src/tx_validator/tx_validator_factory.ts +51 -32
- package/src/validator.ts +20 -31
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
|
|
27
|
+
this.failedReexecutionCounter = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_FAILED_REEXECUTION_COUNT, {
|
|
28
|
+
[Attributes.STATUS]: ['failed'],
|
|
29
|
+
});
|
|
25
30
|
|
|
26
|
-
this.successfulAttestationsCount =
|
|
31
|
+
this.successfulAttestationsCount = createUpDownCounterWithDefault(
|
|
32
|
+
meter,
|
|
33
|
+
Metrics.VALIDATOR_ATTESTATION_SUCCESS_COUNT,
|
|
34
|
+
);
|
|
27
35
|
|
|
28
|
-
this.failedAttestationsBadProposalCount =
|
|
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 =
|
|
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(
|
|
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(
|
|
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,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
+
import type { LoggerBindings } from '@aztec/foundation/log';
|
|
3
4
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
4
5
|
import {
|
|
5
6
|
AggregateTxValidator,
|
|
@@ -53,32 +54,41 @@ export function createValidatorForAcceptingTxs(
|
|
|
53
54
|
blockNumber: BlockNumber;
|
|
54
55
|
txsPermitted: boolean;
|
|
55
56
|
},
|
|
57
|
+
bindings?: LoggerBindings,
|
|
56
58
|
): TxValidator<Tx> {
|
|
57
59
|
const validators: TxValidator<Tx>[] = [
|
|
58
|
-
new TxPermittedValidator(txsPermitted),
|
|
59
|
-
new SizeTxValidator(),
|
|
60
|
-
new DataTxValidator(),
|
|
61
|
-
new MetadataTxValidator(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
60
|
+
new TxPermittedValidator(txsPermitted, bindings),
|
|
61
|
+
new SizeTxValidator(bindings),
|
|
62
|
+
new DataTxValidator(bindings),
|
|
63
|
+
new MetadataTxValidator(
|
|
64
|
+
{
|
|
65
|
+
l1ChainId: new Fr(l1ChainId),
|
|
66
|
+
rollupVersion: new Fr(rollupVersion),
|
|
67
|
+
protocolContractsHash,
|
|
68
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
69
|
+
},
|
|
70
|
+
bindings,
|
|
71
|
+
),
|
|
72
|
+
new TimestampTxValidator(
|
|
73
|
+
{
|
|
74
|
+
timestamp,
|
|
75
|
+
blockNumber,
|
|
76
|
+
},
|
|
77
|
+
bindings,
|
|
78
|
+
),
|
|
79
|
+
new DoubleSpendTxValidator(new NullifierCache(db), bindings),
|
|
80
|
+
new PhasesTxValidator(contractDataSource, setupAllowList, timestamp, bindings),
|
|
81
|
+
new BlockHeaderTxValidator(new ArchiveCache(db), bindings),
|
|
74
82
|
];
|
|
75
83
|
|
|
76
84
|
if (!skipFeeEnforcement) {
|
|
77
|
-
validators.push(
|
|
85
|
+
validators.push(
|
|
86
|
+
new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, gasFees, bindings),
|
|
87
|
+
);
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
if (verifier) {
|
|
81
|
-
validators.push(new TxProofValidator(verifier));
|
|
91
|
+
validators.push(new TxProofValidator(verifier, bindings));
|
|
82
92
|
}
|
|
83
93
|
|
|
84
94
|
return new AggregateTxValidator(...validators);
|
|
@@ -89,6 +99,7 @@ export function createValidatorForBlockBuilding(
|
|
|
89
99
|
contractDataSource: ContractDataSource,
|
|
90
100
|
globalVariables: GlobalVariables,
|
|
91
101
|
setupAllowList: AllowedElement[],
|
|
102
|
+
bindings?: LoggerBindings,
|
|
92
103
|
): PublicProcessorValidator {
|
|
93
104
|
const nullifierCache = new NullifierCache(db);
|
|
94
105
|
const archiveCache = new ArchiveCache(db);
|
|
@@ -102,6 +113,7 @@ export function createValidatorForBlockBuilding(
|
|
|
102
113
|
contractDataSource,
|
|
103
114
|
globalVariables,
|
|
104
115
|
setupAllowList,
|
|
116
|
+
bindings,
|
|
105
117
|
),
|
|
106
118
|
nullifierCache,
|
|
107
119
|
};
|
|
@@ -114,22 +126,29 @@ function preprocessValidator(
|
|
|
114
126
|
contractDataSource: ContractDataSource,
|
|
115
127
|
globalVariables: GlobalVariables,
|
|
116
128
|
setupAllowList: AllowedElement[],
|
|
129
|
+
bindings?: LoggerBindings,
|
|
117
130
|
): TxValidator<Tx> {
|
|
118
131
|
// We don't include the TxProofValidator nor the DataTxValidator here because they are already checked by the time we get to block building.
|
|
119
132
|
return new AggregateTxValidator(
|
|
120
|
-
new MetadataTxValidator(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
new MetadataTxValidator(
|
|
134
|
+
{
|
|
135
|
+
l1ChainId: globalVariables.chainId,
|
|
136
|
+
rollupVersion: globalVariables.version,
|
|
137
|
+
protocolContractsHash,
|
|
138
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
139
|
+
},
|
|
140
|
+
bindings,
|
|
141
|
+
),
|
|
142
|
+
new TimestampTxValidator(
|
|
143
|
+
{
|
|
144
|
+
timestamp: globalVariables.timestamp,
|
|
145
|
+
blockNumber: globalVariables.blockNumber,
|
|
146
|
+
},
|
|
147
|
+
bindings,
|
|
148
|
+
),
|
|
149
|
+
new DoubleSpendTxValidator(nullifierCache, bindings),
|
|
150
|
+
new PhasesTxValidator(contractDataSource, setupAllowList, globalVariables.timestamp, bindings),
|
|
151
|
+
new GasTxValidator(publicStateSource, ProtocolContractAddress.FeeJuice, globalVariables.gasFees, bindings),
|
|
152
|
+
new BlockHeaderTxValidator(archiveCache, bindings),
|
|
134
153
|
);
|
|
135
154
|
}
|
package/src/validator.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
|
18
18
|
import { sleep } from '@aztec/foundation/sleep';
|
|
19
19
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
20
20
|
import type { KeystoreManager } from '@aztec/node-keystore';
|
|
21
|
-
import type { P2P, PeerId
|
|
21
|
+
import type { P2P, PeerId } from '@aztec/p2p';
|
|
22
22
|
import { AuthRequest, AuthResponse, BlockProposalValidator, ReqRespSubProtocol } from '@aztec/p2p';
|
|
23
23
|
import { OffenseType, WANT_TO_SLASH_EVENT, type Watcher, type WatcherEmitter } from '@aztec/slasher';
|
|
24
24
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
@@ -26,11 +26,12 @@ import type { CommitteeAttestationsAndSigners, L2Block, L2BlockSink, L2BlockSour
|
|
|
26
26
|
import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
27
27
|
import type {
|
|
28
28
|
CreateCheckpointProposalLastBlockData,
|
|
29
|
+
ITxProvider,
|
|
29
30
|
Validator,
|
|
30
31
|
ValidatorClientFullConfig,
|
|
31
32
|
WorldStateSynchronizer,
|
|
32
33
|
} from '@aztec/stdlib/interfaces/server';
|
|
33
|
-
import type
|
|
34
|
+
import { type L1ToL2MessageSource, accumulateCheckpointOutHashes } from '@aztec/stdlib/messaging';
|
|
34
35
|
import type {
|
|
35
36
|
BlockProposal,
|
|
36
37
|
BlockProposalOptions,
|
|
@@ -87,11 +88,6 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
87
88
|
|
|
88
89
|
private proposersOfInvalidBlocks: Set<string> = new Set();
|
|
89
90
|
|
|
90
|
-
// TODO(palla/mbps): Remove this once checkpoint validation is stable and we can validate all blocks properly.
|
|
91
|
-
// Tracks slots for which we have successfully validated a block proposal, so we can attest to checkpoint proposals for those slots.
|
|
92
|
-
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
93
|
-
private validatedBlockSlots: Set<SlotNumber> = new Set();
|
|
94
|
-
|
|
95
91
|
protected constructor(
|
|
96
92
|
private keyStore: ExtendedValidatorKeyStore,
|
|
97
93
|
private epochCache: EpochCache,
|
|
@@ -184,7 +180,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
184
180
|
p2pClient: P2P,
|
|
185
181
|
blockSource: L2BlockSource & L2BlockSink,
|
|
186
182
|
l1ToL2MessageSource: L1ToL2MessageSource,
|
|
187
|
-
txProvider:
|
|
183
|
+
txProvider: ITxProvider,
|
|
188
184
|
keyStoreManager: KeystoreManager,
|
|
189
185
|
blobClient: BlobClientInterface,
|
|
190
186
|
dateProvider: DateProvider = new DateProvider(),
|
|
@@ -413,10 +409,6 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
413
409
|
return false;
|
|
414
410
|
}
|
|
415
411
|
|
|
416
|
-
// TODO(palla/mbps): Remove this once checkpoint validation is stable.
|
|
417
|
-
// Track that we successfully validated a block for this slot, so we can attest to checkpoint proposals for it.
|
|
418
|
-
this.validatedBlockSlots.add(slotNumber);
|
|
419
|
-
|
|
420
412
|
return true;
|
|
421
413
|
}
|
|
422
414
|
|
|
@@ -461,17 +453,9 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
461
453
|
fishermanMode: this.config.fishermanMode || false,
|
|
462
454
|
});
|
|
463
455
|
|
|
464
|
-
// TODO(palla/mbps): Remove this once checkpoint validation is stable.
|
|
465
|
-
// Check that we have successfully validated a block for this slot before attesting to the checkpoint.
|
|
466
|
-
if (!this.validatedBlockSlots.has(slotNumber)) {
|
|
467
|
-
this.log.warn(`No validated block found for slot ${slotNumber}, refusing to attest to checkpoint`, proposalInfo);
|
|
468
|
-
return undefined;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
456
|
// Validate the checkpoint proposal before attesting (unless skipCheckpointProposalValidation is set)
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
this.log.verbose(`Skipping checkpoint proposal validation for slot ${slotNumber}`, proposalInfo);
|
|
457
|
+
if (this.config.skipCheckpointProposalValidation) {
|
|
458
|
+
this.log.warn(`Skipping checkpoint proposal validation for slot ${slotNumber}`, proposalInfo);
|
|
475
459
|
} else {
|
|
476
460
|
const validationResult = await this.validateCheckpointProposal(proposal, proposalInfo);
|
|
477
461
|
if (!validationResult.isValid) {
|
|
@@ -547,7 +531,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
547
531
|
proposalInfo: LogData,
|
|
548
532
|
): Promise<{ isValid: true } | { isValid: false; reason: string }> {
|
|
549
533
|
const slot = proposal.slotNumber;
|
|
550
|
-
const timeoutSeconds = 10;
|
|
534
|
+
const timeoutSeconds = 10; // TODO(palla/mbps): This should map to the timetable settings
|
|
551
535
|
|
|
552
536
|
// Wait for last block to sync by archive
|
|
553
537
|
let lastBlockHeader: BlockHeader | undefined;
|
|
@@ -617,6 +601,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
617
601
|
previousCheckpointOutHashes,
|
|
618
602
|
fork,
|
|
619
603
|
blocks,
|
|
604
|
+
this.log.getBindings(),
|
|
620
605
|
);
|
|
621
606
|
|
|
622
607
|
// Complete the checkpoint to get computed values
|
|
@@ -642,13 +627,17 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
642
627
|
return { isValid: false, reason: 'archive_mismatch' };
|
|
643
628
|
}
|
|
644
629
|
|
|
645
|
-
// Check that the accumulated out hash matches the value in the proposal.
|
|
646
|
-
|
|
647
|
-
const
|
|
648
|
-
|
|
630
|
+
// Check that the accumulated epoch out hash matches the value in the proposal.
|
|
631
|
+
// The epoch out hash is the accumulated hash of all checkpoint out hashes in the epoch.
|
|
632
|
+
const checkpointOutHash = computedCheckpoint.getCheckpointOutHash();
|
|
633
|
+
const computedEpochOutHash = accumulateCheckpointOutHashes([...previousCheckpointOutHashes, checkpointOutHash]);
|
|
634
|
+
const proposalEpochOutHash = proposal.checkpointHeader.epochOutHash;
|
|
635
|
+
if (!computedEpochOutHash.equals(proposalEpochOutHash)) {
|
|
649
636
|
this.log.warn(`Epoch out hash mismatch`, {
|
|
650
|
-
|
|
651
|
-
|
|
637
|
+
proposalEpochOutHash: proposalEpochOutHash.toString(),
|
|
638
|
+
computedEpochOutHash: computedEpochOutHash.toString(),
|
|
639
|
+
checkpointOutHash: checkpointOutHash.toString(),
|
|
640
|
+
previousCheckpointOutHashes: previousCheckpointOutHashes.map(h => h.toString()),
|
|
652
641
|
...proposalInfo,
|
|
653
642
|
});
|
|
654
643
|
return { isValid: false, reason: 'out_hash_mismatch' };
|
|
@@ -739,7 +728,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
739
728
|
archive: Fr,
|
|
740
729
|
txs: Tx[],
|
|
741
730
|
proposerAddress: EthAddress | undefined,
|
|
742
|
-
options: BlockProposalOptions,
|
|
731
|
+
options: BlockProposalOptions = {},
|
|
743
732
|
): Promise<BlockProposal> {
|
|
744
733
|
// TODO(palla/mbps): Prevent double proposals properly
|
|
745
734
|
// if (this.previousProposal?.slotNumber === blockHeader.globalVariables.slotNumber) {
|
|
@@ -771,7 +760,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
771
760
|
archive: Fr,
|
|
772
761
|
lastBlockInfo: CreateCheckpointProposalLastBlockData | undefined,
|
|
773
762
|
proposerAddress: EthAddress | undefined,
|
|
774
|
-
options: CheckpointProposalOptions,
|
|
763
|
+
options: CheckpointProposalOptions = {},
|
|
775
764
|
): Promise<CheckpointProposal> {
|
|
776
765
|
this.log.info(`Assembling checkpoint proposal for slot ${checkpointHeader.slotNumber}`);
|
|
777
766
|
return await this.validationService.createCheckpointProposal(
|