@aztec/validator-client 0.0.1-commit.3469e52 → 0.0.1-commit.54489865
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/README.md +1 -1
- package/dest/block_proposal_handler.d.ts +5 -7
- package/dest/block_proposal_handler.d.ts.map +1 -1
- package/dest/block_proposal_handler.js +17 -32
- package/dest/checkpoint_builder.d.ts +9 -6
- package/dest/checkpoint_builder.d.ts.map +1 -1
- package/dest/checkpoint_builder.js +26 -19
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +4 -6
- 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 +25 -46
- package/src/checkpoint_builder.ts +42 -16
- package/src/config.ts +4 -6
- package/src/metrics.ts +45 -6
- package/src/tx_validator/tx_validator_factory.ts +51 -32
- package/src/validator.ts +22 -33
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { merge, pick } from '@aztec/foundation/collection';
|
|
3
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
5
5
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
6
6
|
import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
|
|
7
7
|
import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
PublicProcessor,
|
|
13
13
|
createPublicTxSimulatorForBlockBuilding,
|
|
14
14
|
} from '@aztec/simulator/server';
|
|
15
|
-
import {
|
|
15
|
+
import { L2Block } from '@aztec/stdlib/block';
|
|
16
16
|
import { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
17
17
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
18
18
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
@@ -36,8 +36,6 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
|
|
|
36
36
|
// Re-export for backward compatibility
|
|
37
37
|
export type { BuildBlockInCheckpointResult } from '@aztec/stdlib/interfaces/server';
|
|
38
38
|
|
|
39
|
-
const log = createLogger('checkpoint-builder');
|
|
40
|
-
|
|
41
39
|
/** Result of building a block within a checkpoint. Extends the base interface with timer. */
|
|
42
40
|
export interface BuildBlockInCheckpointResultWithTimer extends BuildBlockInCheckpointResult {
|
|
43
41
|
blockBuildingTimer: Timer;
|
|
@@ -48,6 +46,8 @@ export interface BuildBlockInCheckpointResultWithTimer extends BuildBlockInCheck
|
|
|
48
46
|
* and completing it.
|
|
49
47
|
*/
|
|
50
48
|
export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
49
|
+
private log: Logger;
|
|
50
|
+
|
|
51
51
|
constructor(
|
|
52
52
|
private checkpointBuilder: LightweightCheckpointBuilder,
|
|
53
53
|
private fork: MerkleTreeWriteOperations,
|
|
@@ -55,7 +55,13 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
55
55
|
private contractDataSource: ContractDataSource,
|
|
56
56
|
private dateProvider: DateProvider,
|
|
57
57
|
private telemetryClient: TelemetryClient,
|
|
58
|
-
|
|
58
|
+
bindings?: LoggerBindings,
|
|
59
|
+
) {
|
|
60
|
+
this.log = createLogger('checkpoint-builder', {
|
|
61
|
+
...bindings,
|
|
62
|
+
instanceId: `checkpoint-${checkpointBuilder.checkpointNumber}`,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
59
65
|
|
|
60
66
|
getConstantData(): CheckpointGlobalVariables {
|
|
61
67
|
return this.checkpointBuilder.constants;
|
|
@@ -68,12 +74,12 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
68
74
|
pendingTxs: Iterable<Tx> | AsyncIterable<Tx>,
|
|
69
75
|
blockNumber: BlockNumber,
|
|
70
76
|
timestamp: bigint,
|
|
71
|
-
opts: PublicProcessorLimits & { expectedEndState?: StateReference },
|
|
77
|
+
opts: PublicProcessorLimits & { expectedEndState?: StateReference } = {},
|
|
72
78
|
): Promise<BuildBlockInCheckpointResultWithTimer> {
|
|
73
79
|
const blockBuildingTimer = new Timer();
|
|
74
80
|
const slot = this.checkpointBuilder.constants.slotNumber;
|
|
75
81
|
|
|
76
|
-
log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
|
|
82
|
+
this.log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
|
|
77
83
|
slot,
|
|
78
84
|
blockNumber,
|
|
79
85
|
...opts,
|
|
@@ -115,7 +121,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
115
121
|
usedTxs,
|
|
116
122
|
usedTxBlobFields,
|
|
117
123
|
};
|
|
118
|
-
log.debug('Built block within checkpoint', res.block.header);
|
|
124
|
+
this.log.debug('Built block within checkpoint', res.block.header);
|
|
119
125
|
return res;
|
|
120
126
|
}
|
|
121
127
|
|
|
@@ -123,7 +129,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
123
129
|
async completeCheckpoint(): Promise<Checkpoint> {
|
|
124
130
|
const checkpoint = await this.checkpointBuilder.completeCheckpoint();
|
|
125
131
|
|
|
126
|
-
log.verbose(`Completed checkpoint ${checkpoint.number}`, {
|
|
132
|
+
this.log.verbose(`Completed checkpoint ${checkpoint.number}`, {
|
|
127
133
|
checkpointNumber: checkpoint.number,
|
|
128
134
|
numBlocks: checkpoint.blocks.length,
|
|
129
135
|
archiveRoot: checkpoint.archive.root.toString(),
|
|
@@ -139,14 +145,16 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
139
145
|
|
|
140
146
|
protected async makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations) {
|
|
141
147
|
const txPublicSetupAllowList = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
|
|
142
|
-
const contractsDB = new PublicContractsDB(this.contractDataSource);
|
|
148
|
+
const contractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings());
|
|
143
149
|
const guardedFork = new GuardedMerkleTreeOperations(fork);
|
|
144
150
|
|
|
151
|
+
const bindings = this.log.getBindings();
|
|
145
152
|
const publicTxSimulator = createPublicTxSimulatorForBlockBuilding(
|
|
146
153
|
guardedFork,
|
|
147
154
|
contractsDB,
|
|
148
155
|
globalVariables,
|
|
149
156
|
this.telemetryClient,
|
|
157
|
+
bindings,
|
|
150
158
|
);
|
|
151
159
|
|
|
152
160
|
const processor = new PublicProcessor(
|
|
@@ -156,7 +164,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
156
164
|
publicTxSimulator,
|
|
157
165
|
this.dateProvider,
|
|
158
166
|
this.telemetryClient,
|
|
159
|
-
|
|
167
|
+
createLogger('simulator:public-processor', bindings),
|
|
160
168
|
this.config,
|
|
161
169
|
);
|
|
162
170
|
|
|
@@ -165,6 +173,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
165
173
|
this.contractDataSource,
|
|
166
174
|
globalVariables,
|
|
167
175
|
txPublicSetupAllowList,
|
|
176
|
+
this.log.getBindings(),
|
|
168
177
|
);
|
|
169
178
|
|
|
170
179
|
return {
|
|
@@ -176,13 +185,17 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
176
185
|
|
|
177
186
|
/** Factory for creating checkpoint builders. */
|
|
178
187
|
export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
188
|
+
private log: Logger;
|
|
189
|
+
|
|
179
190
|
constructor(
|
|
180
191
|
private config: FullNodeBlockBuilderConfig & Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>,
|
|
181
192
|
private worldState: WorldStateSynchronizer,
|
|
182
193
|
private contractDataSource: ContractDataSource,
|
|
183
194
|
private dateProvider: DateProvider,
|
|
184
195
|
private telemetryClient: TelemetryClient = getTelemetryClient(),
|
|
185
|
-
) {
|
|
196
|
+
) {
|
|
197
|
+
this.log = createLogger('checkpoint-builder');
|
|
198
|
+
}
|
|
186
199
|
|
|
187
200
|
public getConfig(): FullNodeBlockBuilderConfig {
|
|
188
201
|
return this.config;
|
|
@@ -201,11 +214,12 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
201
214
|
l1ToL2Messages: Fr[],
|
|
202
215
|
previousCheckpointOutHashes: Fr[],
|
|
203
216
|
fork: MerkleTreeWriteOperations,
|
|
217
|
+
bindings?: LoggerBindings,
|
|
204
218
|
): Promise<CheckpointBuilder> {
|
|
205
219
|
const stateReference = await fork.getStateReference();
|
|
206
220
|
const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
207
221
|
|
|
208
|
-
log.verbose(`Building new checkpoint ${checkpointNumber}`, {
|
|
222
|
+
this.log.verbose(`Building new checkpoint ${checkpointNumber}`, {
|
|
209
223
|
checkpointNumber,
|
|
210
224
|
msgCount: l1ToL2Messages.length,
|
|
211
225
|
initialStateReference: stateReference.toInspect(),
|
|
@@ -219,6 +233,7 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
219
233
|
l1ToL2Messages,
|
|
220
234
|
previousCheckpointOutHashes,
|
|
221
235
|
fork,
|
|
236
|
+
bindings,
|
|
222
237
|
);
|
|
223
238
|
|
|
224
239
|
return new CheckpointBuilder(
|
|
@@ -228,6 +243,7 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
228
243
|
this.contractDataSource,
|
|
229
244
|
this.dateProvider,
|
|
230
245
|
this.telemetryClient,
|
|
246
|
+
bindings,
|
|
231
247
|
);
|
|
232
248
|
}
|
|
233
249
|
|
|
@@ -240,16 +256,24 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
240
256
|
l1ToL2Messages: Fr[],
|
|
241
257
|
previousCheckpointOutHashes: Fr[],
|
|
242
258
|
fork: MerkleTreeWriteOperations,
|
|
243
|
-
existingBlocks:
|
|
259
|
+
existingBlocks: L2Block[] = [],
|
|
260
|
+
bindings?: LoggerBindings,
|
|
244
261
|
): Promise<CheckpointBuilder> {
|
|
245
262
|
const stateReference = await fork.getStateReference();
|
|
246
263
|
const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
247
264
|
|
|
248
265
|
if (existingBlocks.length === 0) {
|
|
249
|
-
return this.startCheckpoint(
|
|
266
|
+
return this.startCheckpoint(
|
|
267
|
+
checkpointNumber,
|
|
268
|
+
constants,
|
|
269
|
+
l1ToL2Messages,
|
|
270
|
+
previousCheckpointOutHashes,
|
|
271
|
+
fork,
|
|
272
|
+
bindings,
|
|
273
|
+
);
|
|
250
274
|
}
|
|
251
275
|
|
|
252
|
-
log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
|
|
276
|
+
this.log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
|
|
253
277
|
checkpointNumber,
|
|
254
278
|
msgCount: l1ToL2Messages.length,
|
|
255
279
|
existingBlockCount: existingBlocks.length,
|
|
@@ -265,6 +289,7 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
265
289
|
previousCheckpointOutHashes,
|
|
266
290
|
fork,
|
|
267
291
|
existingBlocks,
|
|
292
|
+
bindings,
|
|
268
293
|
);
|
|
269
294
|
|
|
270
295
|
return new CheckpointBuilder(
|
|
@@ -274,6 +299,7 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
274
299
|
this.contractDataSource,
|
|
275
300
|
this.dateProvider,
|
|
276
301
|
this.telemetryClient,
|
|
302
|
+
bindings,
|
|
277
303
|
);
|
|
278
304
|
}
|
|
279
305
|
|
package/src/config.ts
CHANGED
|
@@ -65,15 +65,13 @@ export const validatorClientConfigMappings: ConfigMappingsType<ValidatorClientCo
|
|
|
65
65
|
'Whether to run in fisherman mode: validates all proposals and attestations but does not broadcast attestations or participate in consensus.',
|
|
66
66
|
...booleanConfigHelper(false),
|
|
67
67
|
},
|
|
68
|
-
// TODO(palla/mbps): Change default to false once checkpoint validation is stable
|
|
69
68
|
skipCheckpointProposalValidation: {
|
|
70
|
-
description: 'Skip checkpoint proposal validation and always attest (default:
|
|
71
|
-
defaultValue:
|
|
69
|
+
description: 'Skip checkpoint proposal validation and always attest (default: false)',
|
|
70
|
+
defaultValue: false,
|
|
72
71
|
},
|
|
73
|
-
// TODO(palla/mbps): Change default to false once block sync is stable
|
|
74
72
|
skipPushProposedBlocksToArchiver: {
|
|
75
|
-
description: 'Skip pushing re-executed blocks to archiver (default:
|
|
76
|
-
defaultValue:
|
|
73
|
+
description: 'Skip pushing re-executed blocks to archiver (default: false)',
|
|
74
|
+
defaultValue: false,
|
|
77
75
|
},
|
|
78
76
|
...validatorHASignerConfigMappings,
|
|
79
77
|
};
|
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,19 +18,20 @@ 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';
|
|
25
|
-
import type { CommitteeAttestationsAndSigners,
|
|
25
|
+
import type { CommitteeAttestationsAndSigners, L2Block, L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
|
|
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' };
|
|
@@ -664,7 +653,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
664
653
|
/**
|
|
665
654
|
* Extract checkpoint global variables from a block.
|
|
666
655
|
*/
|
|
667
|
-
private extractCheckpointConstants(block:
|
|
656
|
+
private extractCheckpointConstants(block: L2Block): CheckpointGlobalVariables {
|
|
668
657
|
const gv = block.header.globalVariables;
|
|
669
658
|
return {
|
|
670
659
|
chainId: gv.chainId,
|
|
@@ -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(
|