@aztec/validator-client 0.0.1-commit.b2a5d0dd1 → 0.0.1-commit.b3d3157a
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 +10 -9
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +15 -5
- package/dest/duties/validation_service.d.ts +6 -5
- package/dest/duties/validation_service.d.ts.map +1 -1
- package/dest/duties/validation_service.js +24 -18
- package/dest/factory.d.ts +4 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +8 -3
- package/dest/proposal_handler.d.ts +38 -12
- package/dest/proposal_handler.d.ts.map +1 -1
- package/dest/proposal_handler.js +232 -134
- package/dest/validator.d.ts +15 -2
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +182 -42
- package/package.json +19 -19
- package/src/config.ts +15 -4
- package/src/duties/validation_service.ts +38 -21
- package/src/factory.ts +10 -0
- package/src/proposal_handler.ts +278 -159
- package/src/validator.ts +227 -52
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { type CheckpointNumber, IndexWithinCheckpoint, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
-
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
3
|
-
import { keccak256 } from '@aztec/foundation/crypto/keccak';
|
|
4
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
3
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
4
|
import type { Signature } from '@aztec/foundation/eth-signature';
|
|
7
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
|
-
import
|
|
6
|
+
import { CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
9
7
|
import {
|
|
10
8
|
BlockProposal,
|
|
11
9
|
type BlockProposalOptions,
|
|
@@ -14,9 +12,10 @@ import {
|
|
|
14
12
|
type CheckpointProposalCore,
|
|
15
13
|
type CheckpointProposalOptions,
|
|
16
14
|
ConsensusPayload,
|
|
17
|
-
|
|
15
|
+
type CoordinationSignatureContext,
|
|
16
|
+
getCoordinationSignatureTypedData,
|
|
18
17
|
} from '@aztec/stdlib/p2p';
|
|
19
|
-
import
|
|
18
|
+
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
20
19
|
import type { BlockHeader, Tx } from '@aztec/stdlib/tx';
|
|
21
20
|
import { DutyAlreadySignedError, SlashingProtectionError } from '@aztec/validator-ha-signer/errors';
|
|
22
21
|
import { DutyType, type SigningContext } from '@aztec/validator-ha-signer/types';
|
|
@@ -26,6 +25,7 @@ import type { ValidatorKeyStore } from '../key_store/interface.js';
|
|
|
26
25
|
export class ValidationService {
|
|
27
26
|
constructor(
|
|
28
27
|
private keyStore: ValidatorKeyStore,
|
|
28
|
+
private signatureContext: CoordinationSignatureContext,
|
|
29
29
|
private log = createLogger('validator:validation-service'),
|
|
30
30
|
) {}
|
|
31
31
|
|
|
@@ -62,8 +62,14 @@ export class ValidationService {
|
|
|
62
62
|
|
|
63
63
|
// Create a signer that uses the appropriate address
|
|
64
64
|
const address = proposerAttesterAddress ?? this.keyStore.getAddress(0);
|
|
65
|
-
const payloadSigner = (
|
|
66
|
-
|
|
65
|
+
const payloadSigner = (
|
|
66
|
+
typedData: Parameters<ValidatorKeyStore['signTypedDataWithAddress']>[1],
|
|
67
|
+
context: SigningContext,
|
|
68
|
+
) => this.keyStore.signTypedDataWithAddress(address, typedData, context);
|
|
69
|
+
const txsSigner = (
|
|
70
|
+
typedData: Parameters<ValidatorKeyStore['signTypedDataWithAddress']>[1],
|
|
71
|
+
context: SigningContext,
|
|
72
|
+
) => this.keyStore.signTypedDataWithAddress(address, typedData, context);
|
|
67
73
|
|
|
68
74
|
return BlockProposal.createProposalFromSigner(
|
|
69
75
|
blockHeader,
|
|
@@ -73,7 +79,9 @@ export class ValidationService {
|
|
|
73
79
|
archive,
|
|
74
80
|
txs.map(tx => tx.getTxHash()),
|
|
75
81
|
options.publishFullTxs ? txs : undefined,
|
|
82
|
+
this.signatureContext,
|
|
76
83
|
payloadSigner,
|
|
84
|
+
txsSigner,
|
|
77
85
|
);
|
|
78
86
|
}
|
|
79
87
|
|
|
@@ -97,18 +105,26 @@ export class ValidationService {
|
|
|
97
105
|
proposerAttesterAddress: EthAddress | undefined,
|
|
98
106
|
options: CheckpointProposalOptions,
|
|
99
107
|
): Promise<CheckpointProposal> {
|
|
100
|
-
// For testing:
|
|
101
|
-
//
|
|
102
|
-
//
|
|
108
|
+
// For testing: corrupt the checkpoint so observers' checkpoint validation fails.
|
|
109
|
+
//
|
|
110
|
+
// Keep `archive` aligned with `lastBlockProposal.archiveRoot` so the archive-based lookup
|
|
111
|
+
// in `validateCheckpointProposal` (`getBlockData({ archive })`) still succeeds
|
|
103
112
|
if (options.broadcastInvalidCheckpointProposal) {
|
|
104
113
|
archive = lastBlockProposal?.archiveRoot ?? Fr.random();
|
|
114
|
+
checkpointHeader = CheckpointHeader.from({
|
|
115
|
+
...checkpointHeader,
|
|
116
|
+
epochOutHash: Fr.random(),
|
|
117
|
+
});
|
|
105
118
|
this.log.warn(`Creating INVALID checkpoint proposal for slot ${checkpointHeader.slotNumber}`);
|
|
106
119
|
}
|
|
107
120
|
|
|
108
121
|
// Create a signer that takes payload and context, and uses the appropriate address
|
|
109
|
-
const payloadSigner = (
|
|
122
|
+
const payloadSigner = (
|
|
123
|
+
typedData: Parameters<ValidatorKeyStore['signTypedDataWithAddress']>[1],
|
|
124
|
+
context: SigningContext,
|
|
125
|
+
) => {
|
|
110
126
|
const address = proposerAttesterAddress ?? this.keyStore.getAddress(0);
|
|
111
|
-
return this.keyStore.
|
|
127
|
+
return this.keyStore.signTypedDataWithAddress(address, typedData, context);
|
|
112
128
|
};
|
|
113
129
|
|
|
114
130
|
return CheckpointProposal.createProposalFromSigner(
|
|
@@ -117,6 +133,7 @@ export class ValidationService {
|
|
|
117
133
|
checkpointNumber,
|
|
118
134
|
feeAssetPriceModifier,
|
|
119
135
|
lastBlockProposal,
|
|
136
|
+
this.signatureContext,
|
|
120
137
|
payloadSigner,
|
|
121
138
|
);
|
|
122
139
|
}
|
|
@@ -137,10 +154,13 @@ export class ValidationService {
|
|
|
137
154
|
checkpointNumber: CheckpointNumber,
|
|
138
155
|
): Promise<CheckpointAttestation[]> {
|
|
139
156
|
// Create the attestation payload from the checkpoint proposal
|
|
140
|
-
const payload = new ConsensusPayload(
|
|
141
|
-
|
|
142
|
-
|
|
157
|
+
const payload = new ConsensusPayload(
|
|
158
|
+
proposal.checkpointHeader,
|
|
159
|
+
proposal.archive,
|
|
160
|
+
proposal.feeAssetPriceModifier,
|
|
161
|
+
this.signatureContext,
|
|
143
162
|
);
|
|
163
|
+
const typedData = getCoordinationSignatureTypedData(payload);
|
|
144
164
|
|
|
145
165
|
const context: SigningContext = {
|
|
146
166
|
slot: proposal.slotNumber,
|
|
@@ -151,8 +171,7 @@ export class ValidationService {
|
|
|
151
171
|
// Sign each attestor in parallel, catching HA errors per-attestor
|
|
152
172
|
const results = await Promise.allSettled(
|
|
153
173
|
attestors.map(async attestor => {
|
|
154
|
-
const sig = await this.keyStore.
|
|
155
|
-
// return new BlockAttestation(proposal.payload, sig, proposal.signature);
|
|
174
|
+
const sig = await this.keyStore.signTypedDataWithAddress(attestor, typedData, context);
|
|
156
175
|
return new CheckpointAttestation(payload, sig, proposal.signature);
|
|
157
176
|
}),
|
|
158
177
|
);
|
|
@@ -199,9 +218,7 @@ export class ValidationService {
|
|
|
199
218
|
dutyType: DutyType.ATTESTATIONS_AND_SIGNERS,
|
|
200
219
|
};
|
|
201
220
|
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
);
|
|
205
|
-
return this.keyStore.signMessageWithAddress(proposer, buf, context);
|
|
221
|
+
const typedData = getCoordinationSignatureTypedData(attestationsAndSigners);
|
|
222
|
+
return this.keyStore.signTypedDataWithAddress(proposer, typedData, context);
|
|
206
223
|
}
|
|
207
224
|
}
|
package/src/factory.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { DateProvider } from '@aztec/foundation/timer';
|
|
|
4
4
|
import type { KeystoreManager } from '@aztec/node-keystore';
|
|
5
5
|
import { BlockProposalValidator, type P2PClient } from '@aztec/p2p';
|
|
6
6
|
import type { L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
|
|
7
|
+
import type { CheckpointReexecutionTracker } from '@aztec/stdlib/checkpoint';
|
|
7
8
|
import type { ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
8
9
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
9
10
|
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
@@ -26,12 +27,18 @@ export function createProposalHandler(
|
|
|
26
27
|
blobClient: BlobClientInterface;
|
|
27
28
|
dateProvider: DateProvider;
|
|
28
29
|
telemetry: TelemetryClient;
|
|
30
|
+
reexecutionTracker: CheckpointReexecutionTracker;
|
|
29
31
|
},
|
|
30
32
|
) {
|
|
31
33
|
const metrics = new ValidatorMetrics(deps.telemetry);
|
|
32
34
|
const blockProposalValidator = new BlockProposalValidator(deps.epochCache, {
|
|
33
35
|
txsPermitted: !config.disableTransactions,
|
|
34
36
|
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
37
|
+
maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
|
|
38
|
+
signatureContext: {
|
|
39
|
+
chainId: config.l1ChainId,
|
|
40
|
+
rollupAddress: config.rollupAddress,
|
|
41
|
+
},
|
|
35
42
|
});
|
|
36
43
|
return new ProposalHandler(
|
|
37
44
|
deps.checkpointsBuilder,
|
|
@@ -43,6 +50,7 @@ export function createProposalHandler(
|
|
|
43
50
|
deps.epochCache,
|
|
44
51
|
config,
|
|
45
52
|
deps.blobClient,
|
|
53
|
+
deps.reexecutionTracker,
|
|
46
54
|
metrics,
|
|
47
55
|
deps.dateProvider,
|
|
48
56
|
deps.telemetry,
|
|
@@ -63,6 +71,7 @@ export function createValidatorClient(
|
|
|
63
71
|
epochCache: EpochCache;
|
|
64
72
|
keyStoreManager: KeystoreManager | undefined;
|
|
65
73
|
blobClient: BlobClientInterface;
|
|
74
|
+
reexecutionTracker: CheckpointReexecutionTracker;
|
|
66
75
|
slashingProtectionDb?: SlashingProtectionDatabase;
|
|
67
76
|
},
|
|
68
77
|
) {
|
|
@@ -82,6 +91,7 @@ export function createValidatorClient(
|
|
|
82
91
|
txProvider,
|
|
83
92
|
deps.keyStoreManager,
|
|
84
93
|
deps.blobClient,
|
|
94
|
+
deps.reexecutionTracker,
|
|
85
95
|
deps.dateProvider,
|
|
86
96
|
deps.telemetry,
|
|
87
97
|
deps.slashingProtectionDb,
|