@aztec/validator-client 0.87.7 → 1.0.0-nightly.20250604
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/config.d.ts +4 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +9 -5
- package/dest/duties/validation_service.d.ts +6 -4
- package/dest/duties/validation_service.d.ts.map +1 -1
- package/dest/duties/validation_service.js +9 -8
- package/dest/factory.d.ts +2 -0
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +5 -3
- package/dest/key_store/interface.d.ts +14 -5
- package/dest/key_store/interface.d.ts.map +1 -1
- package/dest/key_store/local_key_store.d.ts +38 -9
- package/dest/key_store/local_key_store.d.ts.map +1 -1
- package/dest/key_store/local_key_store.js +58 -15
- package/dest/metrics.d.ts +2 -2
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +4 -4
- package/dest/validator.d.ts +15 -35
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +69 -53
- package/package.json +8 -8
- package/src/config.ts +14 -7
- package/src/duties/validation_service.ts +12 -8
- package/src/factory.ts +5 -2
- package/src/key_store/interface.ts +15 -5
- package/src/key_store/local_key_store.ts +62 -16
- package/src/metrics.ts +4 -4
- package/src/validator.ts +92 -76
package/dest/config.d.ts
CHANGED
|
@@ -3,14 +3,16 @@ import { type ConfigMappingsType } from '@aztec/foundation/config';
|
|
|
3
3
|
* The Validator Configuration
|
|
4
4
|
*/
|
|
5
5
|
export interface ValidatorClientConfig {
|
|
6
|
-
/** The private
|
|
7
|
-
|
|
6
|
+
/** The private keys of the validators participating in attestation duties */
|
|
7
|
+
validatorPrivateKeys?: `0x${string}`[];
|
|
8
8
|
/** Do not run the validator */
|
|
9
9
|
disableValidator: boolean;
|
|
10
10
|
/** Interval between polling for new attestations from peers */
|
|
11
11
|
attestationPollingIntervalMs: number;
|
|
12
12
|
/** Re-execute transactions before attesting */
|
|
13
13
|
validatorReexecute: boolean;
|
|
14
|
+
/** Will re-execute until this many milliseconds are left in the slot */
|
|
15
|
+
validatorReexecuteDeadlineMs: number;
|
|
14
16
|
}
|
|
15
17
|
export declare const validatorClientConfigMappings: ConfigMappingsType<ValidatorClientConfig>;
|
|
16
18
|
/**
|
package/dest/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAIxB,MAAM,0BAA0B,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,6EAA6E;IAC7E,oBAAoB,CAAC,EAAE,KAAK,MAAM,EAAE,EAAE,CAAC;IAEvC,+BAA+B;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAE1B,+DAA+D;IAC/D,4BAA4B,EAAE,MAAM,CAAC;IAErC,+CAA+C;IAC/C,kBAAkB,EAAE,OAAO,CAAC;IAE5B,wEAAwE;IACxE,4BAA4B,EAAE,MAAM,CAAC;CACtC;AAED,eAAO,MAAM,6BAA6B,EAAE,kBAAkB,CAAC,qBAAqB,CA0BnF,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAExD"}
|
package/dest/config.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { NULL_KEY } from '@aztec/ethereum';
|
|
2
1
|
import { booleanConfigHelper, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
|
|
3
2
|
export const validatorClientConfigMappings = {
|
|
4
|
-
|
|
5
|
-
env: '
|
|
6
|
-
parseEnv: (val)=>val
|
|
7
|
-
description: '
|
|
3
|
+
validatorPrivateKeys: {
|
|
4
|
+
env: 'VALIDATOR_PRIVATE_KEYS',
|
|
5
|
+
parseEnv: (val)=>val.split(',').map((key)=>`0x${key.replace('0x', '')}`),
|
|
6
|
+
description: 'List of private keys of the validators participating in attestation duties'
|
|
8
7
|
},
|
|
9
8
|
disableValidator: {
|
|
10
9
|
env: 'VALIDATOR_DISABLED',
|
|
@@ -20,6 +19,11 @@ export const validatorClientConfigMappings = {
|
|
|
20
19
|
env: 'VALIDATOR_REEXECUTE',
|
|
21
20
|
description: 'Re-execute transactions before attesting',
|
|
22
21
|
...booleanConfigHelper(true)
|
|
22
|
+
},
|
|
23
|
+
validatorReexecuteDeadlineMs: {
|
|
24
|
+
env: 'VALIDATOR_REEXECUTE_DEADLINE_MS',
|
|
25
|
+
description: 'Will re-execute until this many milliseconds are left in the slot',
|
|
26
|
+
...numberConfigHelper(6000)
|
|
23
27
|
}
|
|
24
28
|
};
|
|
25
29
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
1
2
|
import type { Fr } from '@aztec/foundation/fields';
|
|
2
3
|
import { BlockAttestation, BlockProposal, type BlockProposalOptions } from '@aztec/stdlib/p2p';
|
|
3
4
|
import type { ProposedBlockHeader, StateReference, Tx } from '@aztec/stdlib/tx';
|
|
@@ -15,16 +16,17 @@ export declare class ValidationService {
|
|
|
15
16
|
*
|
|
16
17
|
* @returns A block proposal signing the above information (not the current implementation!!!)
|
|
17
18
|
*/
|
|
18
|
-
createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: Tx[], options: BlockProposalOptions): Promise<BlockProposal>;
|
|
19
|
+
createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: Tx[], proposerAttesterAddress: EthAddress, options: BlockProposalOptions): Promise<BlockProposal>;
|
|
19
20
|
/**
|
|
20
|
-
* Attest to the given block proposal constructed by the current sequencer
|
|
21
|
+
* Attest with selection of validators to the given block proposal, constructed by the current sequencer
|
|
21
22
|
*
|
|
22
23
|
* NOTE: This is just a blind signing.
|
|
23
24
|
* We assume that the proposal is valid and DA guarantees have been checked previously.
|
|
24
25
|
*
|
|
25
26
|
* @param proposal - The proposal to attest to
|
|
26
|
-
* @
|
|
27
|
+
* @param attestors - The validators to attest with
|
|
28
|
+
* @returns attestations
|
|
27
29
|
*/
|
|
28
|
-
attestToProposal(proposal: BlockProposal): Promise<BlockAttestation>;
|
|
30
|
+
attestToProposal(proposal: BlockProposal, attestors: EthAddress[]): Promise<BlockAttestation[]>;
|
|
29
31
|
}
|
|
30
32
|
//# sourceMappingURL=validation_service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation_service.d.ts","sourceRoot":"","sources":["../../src/duties/validation_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,iBAAiB;IAE/C;;;;;;;;;OASG;IACG,mBAAmB,CACvB,WAAW,EAAE,EAAE,EACf,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,EAAE,EACX,cAAc,EAAE,cAAc,EAC9B,GAAG,EAAE,EAAE,EAAE,EACT,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC;IAazB
|
|
1
|
+
{"version":3,"file":"validation_service.d.ts","sourceRoot":"","sources":["../../src/duties/validation_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,iBAAiB;IAE/C;;;;;;;;;OASG;IACG,mBAAmB,CACvB,WAAW,EAAE,EAAE,EACf,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,EAAE,EACX,cAAc,EAAE,cAAc,EAC9B,GAAG,EAAE,EAAE,EAAE,EACT,uBAAuB,EAAE,UAAU,EACnC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC;IAazB;;;;;;;;;OASG;IACG,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAUtG"}
|
|
@@ -15,24 +15,25 @@ export class ValidationService {
|
|
|
15
15
|
* @param txs - TxHash[] ordered list of transactions
|
|
16
16
|
*
|
|
17
17
|
* @returns A block proposal signing the above information (not the current implementation!!!)
|
|
18
|
-
*/ async createBlockProposal(blockNumber, header, archive, stateReference, txs, options) {
|
|
19
|
-
const payloadSigner = (payload)=>this.keyStore.
|
|
18
|
+
*/ async createBlockProposal(blockNumber, header, archive, stateReference, txs, proposerAttesterAddress, options) {
|
|
19
|
+
const payloadSigner = (payload)=>this.keyStore.signMessageWithAddress(proposerAttesterAddress, payload);
|
|
20
20
|
// TODO: check if this is calculated earlier / can not be recomputed
|
|
21
21
|
const txHashes = await Promise.all(txs.map((tx)=>tx.getTxHash()));
|
|
22
22
|
return BlockProposal.createProposalFromSigner(blockNumber, new ConsensusPayload(header, archive, stateReference, txHashes), options.publishFullTxs ? txs : undefined, payloadSigner);
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* Attest to the given block proposal constructed by the current sequencer
|
|
25
|
+
* Attest with selection of validators to the given block proposal, constructed by the current sequencer
|
|
26
26
|
*
|
|
27
27
|
* NOTE: This is just a blind signing.
|
|
28
28
|
* We assume that the proposal is valid and DA guarantees have been checked previously.
|
|
29
29
|
*
|
|
30
30
|
* @param proposal - The proposal to attest to
|
|
31
|
-
* @
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
* @param attestors - The validators to attest with
|
|
32
|
+
* @returns attestations
|
|
33
|
+
*/ async attestToProposal(proposal, attestors) {
|
|
34
34
|
const buf = Buffer32.fromBuffer(keccak256(proposal.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation)));
|
|
35
|
-
const
|
|
36
|
-
|
|
35
|
+
const signatures = await Promise.all(attestors.map((attestor)=>this.keyStore.signMessageWithAddress(attestor, buf)));
|
|
36
|
+
//await this.keyStore.signMessage(buf);
|
|
37
|
+
return signatures.map((sig)=>new BlockAttestation(proposal.blockNumber, proposal.payload, sig));
|
|
37
38
|
}
|
|
38
39
|
}
|
package/dest/factory.d.ts
CHANGED
|
@@ -2,10 +2,12 @@ import type { EpochCache } from '@aztec/epoch-cache';
|
|
|
2
2
|
import type { DateProvider } from '@aztec/foundation/timer';
|
|
3
3
|
import type { P2P } from '@aztec/p2p';
|
|
4
4
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
5
|
+
import type { IFullNodeBlockBuilder } from '@aztec/stdlib/interfaces/server';
|
|
5
6
|
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
6
7
|
import type { ValidatorClientConfig } from './config.js';
|
|
7
8
|
import { ValidatorClient } from './validator.js';
|
|
8
9
|
export declare function createValidatorClient(config: ValidatorClientConfig, deps: {
|
|
10
|
+
blockBuilder: IFullNodeBlockBuilder;
|
|
9
11
|
p2pClient: P2P;
|
|
10
12
|
blockSource: L2BlockSource;
|
|
11
13
|
telemetry: TelemetryClient;
|
package/dest/factory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE;IACJ,SAAS,EAAE,GAAG,CAAC;IACf,WAAW,EAAE,aAAa,CAAC;IAC3B,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;CACxB,+
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE;IACJ,YAAY,EAAE,qBAAqB,CAAC;IACpC,SAAS,EAAE,GAAG,CAAC;IACf,WAAW,EAAE,aAAa,CAAC;IAC3B,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;CACxB,+BAkBF"}
|
package/dest/factory.js
CHANGED
|
@@ -4,8 +4,10 @@ export function createValidatorClient(config, deps) {
|
|
|
4
4
|
if (config.disableValidator) {
|
|
5
5
|
return undefined;
|
|
6
6
|
}
|
|
7
|
-
if (config.
|
|
8
|
-
config.
|
|
7
|
+
if (config.validatorPrivateKeys === undefined || !config.validatorPrivateKeys?.length) {
|
|
8
|
+
config.validatorPrivateKeys = [
|
|
9
|
+
generatePrivateKey()
|
|
10
|
+
];
|
|
9
11
|
}
|
|
10
|
-
return ValidatorClient.new(config, deps.epochCache, deps.p2pClient, deps.blockSource, deps.dateProvider, deps.telemetry);
|
|
12
|
+
return ValidatorClient.new(config, deps.blockBuilder, deps.epochCache, deps.p2pClient, deps.blockSource, deps.dateProvider, deps.telemetry);
|
|
11
13
|
}
|
|
@@ -7,19 +7,28 @@ import type { Signature } from '@aztec/foundation/eth-signature';
|
|
|
7
7
|
*/
|
|
8
8
|
export interface ValidatorKeyStore {
|
|
9
9
|
/**
|
|
10
|
-
* Get the address of
|
|
10
|
+
* Get the address of a signer by index
|
|
11
11
|
*
|
|
12
|
+
* @param index - The index of the signer
|
|
12
13
|
* @returns the address
|
|
13
14
|
*/
|
|
14
|
-
getAddress(): EthAddress;
|
|
15
|
-
|
|
15
|
+
getAddress(index: number): EthAddress;
|
|
16
|
+
/**
|
|
17
|
+
* Get all addresses
|
|
18
|
+
*
|
|
19
|
+
* @returns all addresses
|
|
20
|
+
*/
|
|
21
|
+
getAddresses(): EthAddress[];
|
|
22
|
+
sign(message: Buffer32): Promise<Signature[]>;
|
|
23
|
+
signWithAddress(address: EthAddress, message: Buffer32): Promise<Signature>;
|
|
16
24
|
/**
|
|
17
25
|
* Flavor of sign message that followed EIP-712 eth signed message prefix
|
|
18
26
|
* Note: this is only required when we are using ecdsa signatures over secp256k1
|
|
19
27
|
*
|
|
20
28
|
* @param message - The message to sign.
|
|
21
|
-
* @returns The
|
|
29
|
+
* @returns The signatures.
|
|
22
30
|
*/
|
|
23
|
-
signMessage(message: Buffer32): Promise<Signature>;
|
|
31
|
+
signMessage(message: Buffer32): Promise<Signature[]>;
|
|
32
|
+
signMessageWithAddress(address: EthAddress, message: Buffer32): Promise<Signature>;
|
|
24
33
|
}
|
|
25
34
|
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/key_store/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/key_store/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC;IAEtC;;;;OAIG;IACH,YAAY,IAAI,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC9C,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5E;;;;;;OAMG;IACH,WAAW,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACrD,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACpF"}
|
|
@@ -5,24 +5,53 @@ import type { ValidatorKeyStore } from './interface.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* Local Key Store
|
|
7
7
|
*
|
|
8
|
-
* An implementation of the Key store using
|
|
8
|
+
* An implementation of the Key store using in memory private keys.
|
|
9
9
|
*/
|
|
10
10
|
export declare class LocalKeyStore implements ValidatorKeyStore {
|
|
11
|
-
private
|
|
12
|
-
|
|
11
|
+
private signers;
|
|
12
|
+
private signersByAddress;
|
|
13
|
+
constructor(privateKeys: Buffer32[]);
|
|
13
14
|
/**
|
|
14
|
-
* Get the address of
|
|
15
|
+
* Get the address of a signer by index
|
|
15
16
|
*
|
|
17
|
+
* @param index - The index of the signer
|
|
16
18
|
* @returns the address
|
|
17
19
|
*/
|
|
18
|
-
getAddress(): EthAddress;
|
|
20
|
+
getAddress(index: number): EthAddress;
|
|
19
21
|
/**
|
|
20
|
-
*
|
|
22
|
+
* Get the addresses of all signers
|
|
21
23
|
*
|
|
22
|
-
* @
|
|
24
|
+
* @returns the addresses
|
|
25
|
+
*/
|
|
26
|
+
getAddresses(): EthAddress[];
|
|
27
|
+
/**
|
|
28
|
+
* Sign a message with all keystore private keys
|
|
29
|
+
* @param digest - The message buffer to sign
|
|
23
30
|
* @return signature
|
|
24
31
|
*/
|
|
25
|
-
sign(digest: Buffer32): Promise<Signature>;
|
|
26
|
-
|
|
32
|
+
sign(digest: Buffer32): Promise<Signature[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Sign a message with a specific address's private key
|
|
35
|
+
* @param address - The address of the signer to use
|
|
36
|
+
* @param digest - The message buffer to sign
|
|
37
|
+
* @returns signature for the specified address
|
|
38
|
+
* @throws Error if the address is not found in the keystore
|
|
39
|
+
*/
|
|
40
|
+
signWithAddress(address: EthAddress, digest: Buffer32): Promise<Signature>;
|
|
41
|
+
/**
|
|
42
|
+
* Sign a message with all keystore private keys
|
|
43
|
+
*
|
|
44
|
+
* @param message - The message to sign
|
|
45
|
+
* @return signatures
|
|
46
|
+
*/
|
|
47
|
+
signMessage(message: Buffer32): Promise<Signature[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Sign a message with a specific address's private key
|
|
50
|
+
* @param address - The address of the signer to use
|
|
51
|
+
* @param message - The message to sign
|
|
52
|
+
* @returns signature for the specified address
|
|
53
|
+
* @throws Error if the address is not found in the keystore
|
|
54
|
+
*/
|
|
55
|
+
signMessageWithAddress(address: EthAddress, message: Buffer32): Promise<Signature>;
|
|
27
56
|
}
|
|
28
57
|
//# sourceMappingURL=local_key_store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local_key_store.d.ts","sourceRoot":"","sources":["../../src/key_store/local_key_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD;;;;GAIG;AACH,qBAAa,aAAc,YAAW,iBAAiB;IACrD,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"local_key_store.d.ts","sourceRoot":"","sources":["../../src/key_store/local_key_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD;;;;GAIG;AACH,qBAAa,aAAc,YAAW,iBAAiB;IACrD,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,gBAAgB,CAAsC;gBAElD,WAAW,EAAE,QAAQ,EAAE;IAKnC;;;;;OAKG;IACI,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAO5C;;;;OAIG;IACI,YAAY,IAAI,UAAU,EAAE;IAInC;;;;OAIG;IACI,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAInD;;;;;;OAMG;IACI,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAQjF;;;;;OAKG;IACI,WAAW,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAI3D;;;;;;OAMG;IACI,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;CAO1F"}
|
|
@@ -2,31 +2,74 @@ import { Secp256k1Signer } from '@aztec/foundation/crypto';
|
|
|
2
2
|
/**
|
|
3
3
|
* Local Key Store
|
|
4
4
|
*
|
|
5
|
-
* An implementation of the Key store using
|
|
5
|
+
* An implementation of the Key store using in memory private keys.
|
|
6
6
|
*/ export class LocalKeyStore {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
signers;
|
|
8
|
+
signersByAddress;
|
|
9
|
+
constructor(privateKeys){
|
|
10
|
+
this.signers = privateKeys.map((privateKey)=>new Secp256k1Signer(privateKey));
|
|
11
|
+
this.signersByAddress = new Map(this.signers.map((signer)=>[
|
|
12
|
+
signer.address.toString(),
|
|
13
|
+
signer
|
|
14
|
+
]));
|
|
10
15
|
}
|
|
11
16
|
/**
|
|
12
|
-
* Get the address of
|
|
17
|
+
* Get the address of a signer by index
|
|
13
18
|
*
|
|
19
|
+
* @param index - The index of the signer
|
|
14
20
|
* @returns the address
|
|
15
|
-
*/ getAddress() {
|
|
16
|
-
|
|
21
|
+
*/ getAddress(index) {
|
|
22
|
+
if (index >= this.signers.length) {
|
|
23
|
+
throw new Error(`Index ${index} is out of bounds.`);
|
|
24
|
+
}
|
|
25
|
+
return this.signers[index].address;
|
|
17
26
|
}
|
|
18
27
|
/**
|
|
19
|
-
*
|
|
28
|
+
* Get the addresses of all signers
|
|
20
29
|
*
|
|
21
|
-
* @
|
|
30
|
+
* @returns the addresses
|
|
31
|
+
*/ getAddresses() {
|
|
32
|
+
return this.signers.map((signer)=>signer.address);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sign a message with all keystore private keys
|
|
36
|
+
* @param digest - The message buffer to sign
|
|
22
37
|
* @return signature
|
|
23
38
|
*/ sign(digest) {
|
|
24
|
-
|
|
25
|
-
|
|
39
|
+
return Promise.all(this.signers.map((signer)=>signer.sign(digest)));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Sign a message with a specific address's private key
|
|
43
|
+
* @param address - The address of the signer to use
|
|
44
|
+
* @param digest - The message buffer to sign
|
|
45
|
+
* @returns signature for the specified address
|
|
46
|
+
* @throws Error if the address is not found in the keystore
|
|
47
|
+
*/ signWithAddress(address, digest) {
|
|
48
|
+
const signer = this.signersByAddress.get(address.toString());
|
|
49
|
+
if (!signer) {
|
|
50
|
+
throw new Error(`No signer found for address ${address.toString()}`);
|
|
51
|
+
}
|
|
52
|
+
return Promise.resolve(signer.sign(digest));
|
|
26
53
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Sign a message with all keystore private keys
|
|
56
|
+
*
|
|
57
|
+
* @param message - The message to sign
|
|
58
|
+
* @return signatures
|
|
59
|
+
*/ signMessage(message) {
|
|
60
|
+
return Promise.all(this.signers.map((signer)=>signer.signMessage(message)));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Sign a message with a specific address's private key
|
|
64
|
+
* @param address - The address of the signer to use
|
|
65
|
+
* @param message - The message to sign
|
|
66
|
+
* @returns signature for the specified address
|
|
67
|
+
* @throws Error if the address is not found in the keystore
|
|
68
|
+
*/ signMessageWithAddress(address, message) {
|
|
69
|
+
const signer = this.signersByAddress.get(address.toString());
|
|
70
|
+
if (!signer) {
|
|
71
|
+
throw new Error(`No signer found for address ${address.toString()}`);
|
|
72
|
+
}
|
|
73
|
+
return Promise.resolve(signer.signMessage(message));
|
|
31
74
|
}
|
|
32
75
|
}
|
package/dest/metrics.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare class ValidatorMetrics {
|
|
|
9
9
|
reExecutionTimer(): () => void;
|
|
10
10
|
recordReExecutionTime(time: number): void;
|
|
11
11
|
recordFailedReexecution(proposal: BlockProposal): void;
|
|
12
|
-
incAttestations(): void;
|
|
13
|
-
incFailedAttestations(reason: string): void;
|
|
12
|
+
incAttestations(num: number): void;
|
|
13
|
+
incFailedAttestations(num: number, reason: string): void;
|
|
14
14
|
}
|
|
15
15
|
//# sourceMappingURL=metrics.d.ts.map
|
package/dest/metrics.d.ts.map
CHANGED
|
@@ -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,EAIL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,uBAAuB,CAAgB;gBAEnC,eAAe,EAAE,eAAe;IA0BrC,gBAAgB,IAAI,MAAM,IAAI;IAQ9B,qBAAqB,CAAC,IAAI,EAAE,MAAM;IAIlC,uBAAuB,CAAC,QAAQ,EAAE,aAAa;IAO/C,eAAe;
|
|
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,EAIL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,uBAAuB,CAAgB;gBAEnC,eAAe,EAAE,eAAe;IA0BrC,gBAAgB,IAAI,MAAM,IAAI;IAQ9B,qBAAqB,CAAC,IAAI,EAAE,MAAM;IAIlC,uBAAuB,CAAC,QAAQ,EAAE,aAAa;IAO/C,eAAe,CAAC,GAAG,EAAE,MAAM;IAI3B,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAKzD"}
|
package/dest/metrics.js
CHANGED
|
@@ -41,11 +41,11 @@ export class ValidatorMetrics {
|
|
|
41
41
|
[Attributes.BLOCK_PROPOSER]: proposal.getSender().toString()
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
-
incAttestations() {
|
|
45
|
-
this.attestationsCount.add(
|
|
44
|
+
incAttestations(num) {
|
|
45
|
+
this.attestationsCount.add(num);
|
|
46
46
|
}
|
|
47
|
-
incFailedAttestations(reason) {
|
|
48
|
-
this.failedAttestationsCount.add(
|
|
47
|
+
incFailedAttestations(num, reason) {
|
|
48
|
+
this.failedAttestationsCount.add(num, {
|
|
49
49
|
[Attributes.ERROR_TYPE]: reason
|
|
50
50
|
});
|
|
51
51
|
}
|
package/dest/validator.d.ts
CHANGED
|
@@ -1,34 +1,20 @@
|
|
|
1
1
|
import type { EpochCache } from '@aztec/epoch-cache';
|
|
2
2
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import { Fr } from '@aztec/foundation/fields';
|
|
4
|
-
import { DateProvider
|
|
5
|
-
import {
|
|
6
|
-
import type {
|
|
4
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
5
|
+
import type { P2P, PeerId } from '@aztec/p2p';
|
|
6
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
7
|
+
import type { IFullNodeBlockBuilder } from '@aztec/stdlib/interfaces/server';
|
|
7
8
|
import type { BlockAttestation, BlockProposal, BlockProposalOptions } from '@aztec/stdlib/p2p';
|
|
8
|
-
import type
|
|
9
|
+
import { type ProposedBlockHeader, type StateReference, type Tx } from '@aztec/stdlib/tx';
|
|
9
10
|
import { type TelemetryClient, WithTracer } from '@aztec/telemetry-client';
|
|
10
11
|
import type { ValidatorClientConfig } from './config.js';
|
|
11
12
|
import type { ValidatorKeyStore } from './key_store/interface.js';
|
|
12
|
-
/**
|
|
13
|
-
* Callback function for building a block
|
|
14
|
-
*
|
|
15
|
-
* We reuse the sequencer's block building functionality for re-execution
|
|
16
|
-
*/
|
|
17
|
-
type BlockBuilderCallback = (blockNumber: Fr, header: ProposedBlockHeader, txs: Iterable<Tx> | AsyncIterableIterator<Tx>, opts?: {
|
|
18
|
-
validateOnly?: boolean;
|
|
19
|
-
}) => Promise<{
|
|
20
|
-
block: L2Block;
|
|
21
|
-
publicProcessorDuration: number;
|
|
22
|
-
numTxs: number;
|
|
23
|
-
numFailedTxs: number;
|
|
24
|
-
blockBuildingTimer: Timer;
|
|
25
|
-
}>;
|
|
26
13
|
export interface Validator {
|
|
27
14
|
start(): Promise<void>;
|
|
28
15
|
registerBlockProposalHandler(): void;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
attestToProposal(proposal: BlockProposal, sender: PeerId): Promise<BlockAttestation | undefined>;
|
|
16
|
+
createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: Tx[], proposerAddress: EthAddress, options: BlockProposalOptions): Promise<BlockProposal | undefined>;
|
|
17
|
+
attestToProposal(proposal: BlockProposal, sender: PeerId): Promise<BlockAttestation[] | undefined>;
|
|
32
18
|
broadcastBlockProposal(proposal: BlockProposal): Promise<void>;
|
|
33
19
|
collectAttestations(proposal: BlockProposal, required: number, deadline: Date): Promise<BlockAttestation[]>;
|
|
34
20
|
}
|
|
@@ -36,6 +22,7 @@ export interface Validator {
|
|
|
36
22
|
* Validator Client
|
|
37
23
|
*/
|
|
38
24
|
export declare class ValidatorClient extends WithTracer implements Validator {
|
|
25
|
+
private blockBuilder;
|
|
39
26
|
private keyStore;
|
|
40
27
|
private epochCache;
|
|
41
28
|
private p2pClient;
|
|
@@ -46,35 +33,28 @@ export declare class ValidatorClient extends WithTracer implements Validator {
|
|
|
46
33
|
private validationService;
|
|
47
34
|
private metrics;
|
|
48
35
|
private previousProposal?;
|
|
49
|
-
private
|
|
50
|
-
private myAddress;
|
|
36
|
+
private myAddresses;
|
|
51
37
|
private lastEpoch;
|
|
52
38
|
private epochCacheUpdateLoop;
|
|
53
39
|
private blockProposalValidator;
|
|
54
40
|
private txCollector;
|
|
55
|
-
constructor(keyStore: ValidatorKeyStore, epochCache: EpochCache, p2pClient: P2P, blockSource: L2BlockSource, config: ValidatorClientConfig, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: import("@aztec/foundation/log").Logger);
|
|
41
|
+
constructor(blockBuilder: IFullNodeBlockBuilder, keyStore: ValidatorKeyStore, epochCache: EpochCache, p2pClient: P2P, blockSource: L2BlockSource, config: ValidatorClientConfig, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: import("@aztec/foundation/log").Logger);
|
|
56
42
|
private handleEpochCommitteeUpdate;
|
|
57
|
-
static new(config: ValidatorClientConfig, epochCache: EpochCache, p2pClient: P2P, blockSource: L2BlockSource, dateProvider?: DateProvider, telemetry?: TelemetryClient): ValidatorClient;
|
|
58
|
-
|
|
43
|
+
static new(config: ValidatorClientConfig, blockBuilder: IFullNodeBlockBuilder, epochCache: EpochCache, p2pClient: P2P, blockSource: L2BlockSource, dateProvider?: DateProvider, telemetry?: TelemetryClient): ValidatorClient;
|
|
44
|
+
getValidatorAddresses(): EthAddress[];
|
|
59
45
|
start(): Promise<void>;
|
|
60
46
|
stop(): Promise<void>;
|
|
61
47
|
registerBlockProposalHandler(): void;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*
|
|
65
|
-
* We reuse the sequencer's block building functionality for re-execution
|
|
66
|
-
*/
|
|
67
|
-
registerBlockBuilder(blockBuilder: BlockBuilderCallback): void;
|
|
68
|
-
attestToProposal(proposal: BlockProposal, proposalSender: PeerId): Promise<BlockAttestation | undefined>;
|
|
48
|
+
attestToProposal(proposal: BlockProposal, proposalSender: PeerId): Promise<BlockAttestation[] | undefined>;
|
|
49
|
+
private getReexecutionDeadline;
|
|
69
50
|
/**
|
|
70
51
|
* Re-execute the transactions in the proposal and check that the state updates match the header state
|
|
71
52
|
* @param proposal - The proposal to re-execute
|
|
72
53
|
*/
|
|
73
54
|
reExecuteTransactions(proposal: BlockProposal, txs: Tx[]): Promise<void>;
|
|
74
|
-
createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: Tx[], options: BlockProposalOptions): Promise<BlockProposal | undefined>;
|
|
55
|
+
createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: Tx[], proposerAddress: EthAddress, options: BlockProposalOptions): Promise<BlockProposal | undefined>;
|
|
75
56
|
broadcastBlockProposal(proposal: BlockProposal): Promise<void>;
|
|
76
57
|
collectAttestations(proposal: BlockProposal, required: number, deadline: Date): Promise<BlockAttestation[]>;
|
|
77
58
|
private doAttestToProposal;
|
|
78
59
|
}
|
|
79
|
-
export {};
|
|
80
60
|
//# sourceMappingURL=validator.d.ts.map
|
package/dest/validator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAI9C,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
|