@lodestar/validator 1.35.0-dev.c85be4e26c → 1.35.0-dev.c9deb9b59f
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/lib/buckets.d.ts.map +1 -0
- package/lib/defaults.d.ts.map +1 -0
- package/lib/genesis.d.ts.map +1 -0
- package/lib/index.d.ts +7 -7
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +5 -5
- package/lib/index.js.map +1 -1
- package/lib/metrics.d.ts.map +1 -0
- package/lib/metrics.js +14 -14
- package/lib/metrics.js.map +1 -1
- package/lib/repositories/index.d.ts.map +1 -0
- package/lib/repositories/metaDataRepository.d.ts.map +1 -0
- package/lib/repositories/metaDataRepository.js +4 -3
- package/lib/repositories/metaDataRepository.js.map +1 -1
- package/lib/services/attestation.d.ts.map +1 -0
- package/lib/services/attestation.js +77 -60
- package/lib/services/attestation.js.map +1 -1
- package/lib/services/attestationDuties.d.ts.map +1 -0
- package/lib/services/attestationDuties.js +105 -98
- package/lib/services/attestationDuties.js.map +1 -1
- package/lib/services/block.d.ts.map +1 -0
- package/lib/services/block.js +64 -56
- package/lib/services/block.js.map +1 -1
- package/lib/services/blockDuties.d.ts +2 -2
- package/lib/services/blockDuties.d.ts.map +1 -0
- package/lib/services/blockDuties.js +35 -26
- package/lib/services/blockDuties.js.map +1 -1
- package/lib/services/chainHeaderTracker.d.ts.map +1 -0
- package/lib/services/chainHeaderTracker.js +30 -27
- package/lib/services/chainHeaderTracker.js.map +1 -1
- package/lib/services/doppelgangerService.d.ts.map +1 -0
- package/lib/services/doppelgangerService.js +52 -45
- package/lib/services/doppelgangerService.js.map +1 -1
- package/lib/services/emitter.d.ts +1 -1
- package/lib/services/emitter.d.ts.map +1 -0
- package/lib/services/externalSignerSync.d.ts.map +1 -0
- package/lib/services/externalSignerSync.js +1 -1
- package/lib/services/externalSignerSync.js.map +1 -1
- package/lib/services/indices.d.ts.map +1 -0
- package/lib/services/indices.js +8 -5
- package/lib/services/indices.js.map +1 -1
- package/lib/services/prepareBeaconProposer.d.ts.map +1 -0
- package/lib/services/prepareBeaconProposer.js.map +1 -1
- package/lib/services/syncCommittee.d.ts.map +1 -0
- package/lib/services/syncCommittee.js +80 -61
- package/lib/services/syncCommittee.js.map +1 -1
- package/lib/services/syncCommitteeDuties.d.ts.map +1 -0
- package/lib/services/syncCommitteeDuties.js +28 -23
- package/lib/services/syncCommitteeDuties.js.map +1 -1
- package/lib/services/syncingStatusTracker.d.ts.map +1 -0
- package/lib/services/syncingStatusTracker.js +32 -27
- package/lib/services/syncingStatusTracker.js.map +1 -1
- package/lib/services/utils.d.ts.map +1 -0
- package/lib/services/validatorStore.d.ts.map +1 -0
- package/lib/services/validatorStore.js +9 -3
- package/lib/services/validatorStore.js.map +1 -1
- package/lib/slashingProtection/attestation/attestationByTargetRepository.d.ts.map +1 -0
- package/lib/slashingProtection/attestation/attestationByTargetRepository.js +7 -3
- package/lib/slashingProtection/attestation/attestationByTargetRepository.js.map +1 -1
- package/lib/slashingProtection/attestation/attestationLowerBoundRepository.d.ts.map +1 -0
- package/lib/slashingProtection/attestation/attestationLowerBoundRepository.js +5 -3
- package/lib/slashingProtection/attestation/attestationLowerBoundRepository.js.map +1 -1
- package/lib/slashingProtection/attestation/errors.d.ts.map +1 -0
- package/lib/slashingProtection/attestation/index.d.ts.map +1 -0
- package/lib/slashingProtection/attestation/index.js +3 -0
- package/lib/slashingProtection/attestation/index.js.map +1 -1
- package/lib/slashingProtection/block/blockBySlotRepository.d.ts.map +1 -0
- package/lib/slashingProtection/block/blockBySlotRepository.js +7 -3
- package/lib/slashingProtection/block/blockBySlotRepository.js.map +1 -1
- package/lib/slashingProtection/block/errors.d.ts.map +1 -0
- package/lib/slashingProtection/block/index.d.ts.map +1 -0
- package/lib/slashingProtection/block/index.js +1 -0
- package/lib/slashingProtection/block/index.js.map +1 -1
- package/lib/slashingProtection/index.d.ts +1 -1
- package/lib/slashingProtection/index.d.ts.map +1 -0
- package/lib/slashingProtection/index.js +3 -0
- package/lib/slashingProtection/index.js.map +1 -1
- package/lib/slashingProtection/interchange/errors.d.ts.map +1 -0
- package/lib/slashingProtection/interchange/formats/completeV4.d.ts.map +1 -0
- package/lib/slashingProtection/interchange/formats/index.d.ts.map +1 -0
- package/lib/slashingProtection/interchange/formats/v5.d.ts.map +1 -0
- package/lib/slashingProtection/interchange/index.d.ts.map +1 -0
- package/lib/slashingProtection/interchange/parseInterchange.d.ts.map +1 -0
- package/lib/slashingProtection/interchange/serializeInterchange.d.ts.map +1 -0
- package/lib/slashingProtection/interchange/types.d.ts.map +1 -0
- package/lib/slashingProtection/interface.d.ts.map +1 -0
- package/lib/slashingProtection/minMaxSurround/distanceStoreRepository.d.ts.map +1 -0
- package/lib/slashingProtection/minMaxSurround/distanceStoreRepository.js +8 -0
- package/lib/slashingProtection/minMaxSurround/distanceStoreRepository.js.map +1 -1
- package/lib/slashingProtection/minMaxSurround/errors.d.ts.map +1 -0
- package/lib/slashingProtection/minMaxSurround/index.d.ts.map +1 -0
- package/lib/slashingProtection/minMaxSurround/interface.d.ts.map +1 -0
- package/lib/slashingProtection/minMaxSurround/minMaxSurround.d.ts.map +1 -0
- package/lib/slashingProtection/minMaxSurround/minMaxSurround.js +2 -0
- package/lib/slashingProtection/minMaxSurround/minMaxSurround.js.map +1 -1
- package/lib/slashingProtection/types.d.ts.map +1 -0
- package/lib/slashingProtection/utils.d.ts +1 -1
- package/lib/slashingProtection/utils.d.ts.map +1 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/util/batch.d.ts.map +1 -0
- package/lib/util/clock.d.ts +3 -0
- package/lib/util/clock.d.ts.map +1 -0
- package/lib/util/clock.js +16 -9
- package/lib/util/clock.js.map +1 -1
- package/lib/util/difference.d.ts.map +1 -0
- package/lib/util/externalSignerClient.d.ts.map +1 -0
- package/lib/util/format.d.ts.map +1 -0
- package/lib/util/index.d.ts.map +1 -0
- package/lib/util/logger.d.ts.map +1 -0
- package/lib/util/params.d.ts.map +1 -0
- package/lib/util/params.js +18 -2
- package/lib/util/params.js.map +1 -1
- package/lib/util/url.d.ts.map +1 -0
- package/lib/validator.d.ts.map +1 -0
- package/lib/validator.js +16 -1
- package/lib/validator.js.map +1 -1
- package/package.json +19 -16
- package/src/buckets.ts +30 -0
- package/src/defaults.ts +8 -0
- package/src/genesis.ts +19 -0
- package/src/index.ts +22 -0
- package/src/metrics.ts +417 -0
- package/src/repositories/index.ts +1 -0
- package/src/repositories/metaDataRepository.ts +42 -0
- package/src/services/attestation.ts +362 -0
- package/src/services/attestationDuties.ts +406 -0
- package/src/services/block.ts +261 -0
- package/src/services/blockDuties.ts +217 -0
- package/src/services/chainHeaderTracker.ts +89 -0
- package/src/services/doppelgangerService.ts +286 -0
- package/src/services/emitter.ts +43 -0
- package/src/services/externalSignerSync.ts +81 -0
- package/src/services/indices.ts +165 -0
- package/src/services/prepareBeaconProposer.ts +119 -0
- package/src/services/syncCommittee.ts +338 -0
- package/src/services/syncCommitteeDuties.ts +337 -0
- package/src/services/syncingStatusTracker.ts +74 -0
- package/src/services/utils.ts +58 -0
- package/src/services/validatorStore.ts +830 -0
- package/src/slashingProtection/attestation/attestationByTargetRepository.ts +77 -0
- package/src/slashingProtection/attestation/attestationLowerBoundRepository.ts +44 -0
- package/src/slashingProtection/attestation/errors.ts +66 -0
- package/src/slashingProtection/attestation/index.ts +171 -0
- package/src/slashingProtection/block/blockBySlotRepository.ts +78 -0
- package/src/slashingProtection/block/errors.ts +28 -0
- package/src/slashingProtection/block/index.ts +94 -0
- package/src/slashingProtection/index.ts +95 -0
- package/src/slashingProtection/interchange/errors.ts +15 -0
- package/src/slashingProtection/interchange/formats/completeV4.ts +125 -0
- package/src/slashingProtection/interchange/formats/index.ts +7 -0
- package/src/slashingProtection/interchange/formats/v5.ts +120 -0
- package/src/slashingProtection/interchange/index.ts +5 -0
- package/src/slashingProtection/interchange/parseInterchange.ts +55 -0
- package/src/slashingProtection/interchange/serializeInterchange.ts +35 -0
- package/src/slashingProtection/interchange/types.ts +18 -0
- package/src/slashingProtection/interface.ts +28 -0
- package/src/slashingProtection/minMaxSurround/distanceStoreRepository.ts +57 -0
- package/src/slashingProtection/minMaxSurround/errors.ts +27 -0
- package/src/slashingProtection/minMaxSurround/index.ts +4 -0
- package/src/slashingProtection/minMaxSurround/interface.ts +23 -0
- package/src/slashingProtection/minMaxSurround/minMaxSurround.ts +104 -0
- package/src/slashingProtection/types.ts +12 -0
- package/src/slashingProtection/utils.ts +42 -0
- package/src/types.ts +31 -0
- package/src/util/batch.ts +15 -0
- package/src/util/clock.ts +169 -0
- package/src/util/difference.ts +10 -0
- package/src/util/externalSignerClient.ts +277 -0
- package/src/util/format.ts +3 -0
- package/src/util/index.ts +6 -0
- package/src/util/logger.ts +51 -0
- package/src/util/params.ts +320 -0
- package/src/util/url.ts +16 -0
- package/src/validator.ts +418 -0
package/src/buckets.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Buckets are separate database namespaces
|
|
2
|
+
export enum Bucket {
|
|
3
|
+
// validator
|
|
4
|
+
// validator = 16, // DEPRECATED on v0.11.0
|
|
5
|
+
// lastProposedBlock = 17, // DEPRECATED on v0.11.0
|
|
6
|
+
// proposedAttestations = 18, // DEPRECATED on v0.11.0
|
|
7
|
+
// validator slashing protection
|
|
8
|
+
slashingProtectionBlockBySlot = 20,
|
|
9
|
+
slashingProtectionAttestationByTarget = 21,
|
|
10
|
+
slashingProtectionAttestationLowerBound = 22,
|
|
11
|
+
slashingProtectionMinSpanDistance = 23,
|
|
12
|
+
slashingProtectionMaxSpanDistance = 24,
|
|
13
|
+
// allForks_pendingBlock = 25, // Root -> SignedBeaconBlock // DEPRECATED on v0.30.0
|
|
14
|
+
|
|
15
|
+
validator_metaData = 41,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getBucketNameByValue<T extends Bucket>(enumValue: T): keyof typeof Bucket {
|
|
19
|
+
const keys = Object.keys(Bucket).filter((x) => {
|
|
20
|
+
if (Number.isNaN(parseInt(x))) {
|
|
21
|
+
return Bucket[x as keyof typeof Bucket] === enumValue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return false;
|
|
25
|
+
}) as (keyof typeof Bucket)[];
|
|
26
|
+
if (keys.length > 0) {
|
|
27
|
+
return keys[0];
|
|
28
|
+
}
|
|
29
|
+
throw new Error("Missing bucket for value " + enumValue);
|
|
30
|
+
}
|
package/src/defaults.ts
ADDED
package/src/genesis.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {ApiClient} from "@lodestar/api";
|
|
2
|
+
import {Genesis} from "@lodestar/types/phase0";
|
|
3
|
+
import {Logger, sleep} from "@lodestar/utils";
|
|
4
|
+
|
|
5
|
+
/** The time between polls when waiting for genesis */
|
|
6
|
+
const WAITING_FOR_GENESIS_POLL_MS = 12 * 1000;
|
|
7
|
+
|
|
8
|
+
export async function waitForGenesis(api: ApiClient, logger: Logger, signal?: AbortSignal): Promise<Genesis> {
|
|
9
|
+
while (true) {
|
|
10
|
+
try {
|
|
11
|
+
return (await api.beacon.getGenesis()).value();
|
|
12
|
+
} catch (e) {
|
|
13
|
+
// TODO: Search for a 404 error which indicates that genesis has not yet occurred.
|
|
14
|
+
// Note: Lodestar API does not become online after genesis is found
|
|
15
|
+
logger.info("Waiting for genesis", {message: (e as Error).message});
|
|
16
|
+
await sleep(WAITING_FOR_GENESIS_POLL_MS, signal);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export {waitForGenesis} from "./genesis.js";
|
|
2
|
+
export {type Metrics, getMetrics} from "./metrics.js";
|
|
3
|
+
export * from "./repositories/index.js";
|
|
4
|
+
export type {
|
|
5
|
+
ProposerConfig,
|
|
6
|
+
Signer,
|
|
7
|
+
SignerLocal,
|
|
8
|
+
SignerRemote,
|
|
9
|
+
ValidatorProposerConfig,
|
|
10
|
+
} from "./services/validatorStore.js";
|
|
11
|
+
export {MAX_BUILDER_BOOST_FACTOR, SignerType, ValidatorStore, defaultOptions} from "./services/validatorStore.js";
|
|
12
|
+
export * from "./slashingProtection/index.js";
|
|
13
|
+
// Types
|
|
14
|
+
export type {ProcessShutdownCallback} from "./types.js";
|
|
15
|
+
// Remote signer client
|
|
16
|
+
export {
|
|
17
|
+
SignableMessageType,
|
|
18
|
+
externalSignerGetKeys,
|
|
19
|
+
externalSignerPostSignature,
|
|
20
|
+
externalSignerUpCheck,
|
|
21
|
+
} from "./util/externalSignerClient.js";
|
|
22
|
+
export {Validator, type ValidatorOptions} from "./validator.js";
|
package/src/metrics.ts
ADDED
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import {routes} from "@lodestar/api";
|
|
2
|
+
import {MetricsRegisterExtra} from "@lodestar/utils";
|
|
3
|
+
|
|
4
|
+
export enum MessageSource {
|
|
5
|
+
forward = "forward",
|
|
6
|
+
publish = "publish",
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export enum BeaconHealth {
|
|
10
|
+
READY = 0,
|
|
11
|
+
SYNCING = 1,
|
|
12
|
+
ERROR = 2,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type Metrics = ReturnType<typeof getMetrics>;
|
|
16
|
+
|
|
17
|
+
export type LodestarGitData = {
|
|
18
|
+
/** "0.16.0 developer/feature-1 ac99f2b5" */
|
|
19
|
+
version: string;
|
|
20
|
+
/** "4f816b16dfde718e2d74f95f2c8292596138c248" */
|
|
21
|
+
commit: string;
|
|
22
|
+
/** "holesky" */
|
|
23
|
+
network: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A collection of metrics used by the validator client
|
|
28
|
+
*/
|
|
29
|
+
export function getMetrics(register: MetricsRegisterExtra, gitData: LodestarGitData) {
|
|
30
|
+
// Using function style instead of class to prevent having to re-declare all MetricsPrometheus types.
|
|
31
|
+
|
|
32
|
+
// Track version, same as https://github.com/ChainSafe/lodestar/blob/6df28de64f12ea90b341b219229a47c8a25c9343/packages/lodestar/src/metrics/metrics/lodestar.ts#L17
|
|
33
|
+
register
|
|
34
|
+
.gauge<LodestarGitData>({
|
|
35
|
+
name: "lodestar_version",
|
|
36
|
+
help: "Lodestar version",
|
|
37
|
+
labelNames: Object.keys(gitData) as [keyof LodestarGitData],
|
|
38
|
+
})
|
|
39
|
+
.set(gitData, 1);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
defaultConfiguration: register.gauge<{
|
|
43
|
+
builderSelection: routes.validator.BuilderSelection;
|
|
44
|
+
broadcastValidation: routes.beacon.BroadcastValidation;
|
|
45
|
+
}>({
|
|
46
|
+
name: "vc_default_configuration",
|
|
47
|
+
help: "Default validator configuration",
|
|
48
|
+
labelNames: ["builderSelection", "broadcastValidation"],
|
|
49
|
+
}),
|
|
50
|
+
|
|
51
|
+
// Attestation journey:
|
|
52
|
+
// - Wait for block or ATTESTATION_DUE_BPS, call prepare attestation
|
|
53
|
+
// - Get attestation, sign, call publish
|
|
54
|
+
// - Wait AGGREGATE_DUE_BPS, call prepare aggregate
|
|
55
|
+
// - Get aggregate, sign, call publish
|
|
56
|
+
|
|
57
|
+
attesterStepCallProduceAttestation: register.histogram({
|
|
58
|
+
name: "vc_attester_step_call_produce_attestation_seconds",
|
|
59
|
+
help: "Time between ATTESTATION_DUE_BPS of slot and call produce attestation",
|
|
60
|
+
// Attester flow can start early if block is imported before ATTESTATION_DUE_BPS of the slot
|
|
61
|
+
// This measure is critical so we need very good resolution around the 0 second mark
|
|
62
|
+
buckets: [-3, -1, 0, 1, 2, 3, 6, 12],
|
|
63
|
+
}),
|
|
64
|
+
attesterStepCallPublishAttestation: register.histogram({
|
|
65
|
+
name: "vc_attester_step_call_publish_attestation_seconds",
|
|
66
|
+
help: "Time between ATTESTATION_DUE_BPS of slot and call publish attestation",
|
|
67
|
+
buckets: [-3, -1, 0, 1, 2, 3, 6, 12],
|
|
68
|
+
}),
|
|
69
|
+
|
|
70
|
+
attesterStepCallProduceAggregate: register.histogram({
|
|
71
|
+
name: "vc_attester_step_call_produce_aggregate_seconds",
|
|
72
|
+
help: "Time between AGGREGATE_DUE_BPS of slot and call produce aggregate",
|
|
73
|
+
// Aggregate production starts at AGGREGATE_DUE_BPS the earliest.
|
|
74
|
+
// Track values close to 0 (expected) in greater resolution, values over 12 overflow into the next slot.
|
|
75
|
+
buckets: [0.5, 1, 2, 3, 6, 12],
|
|
76
|
+
}),
|
|
77
|
+
attesterStepCallPublishAggregate: register.histogram({
|
|
78
|
+
name: "vc_attester_step_call_publish_aggregate_seconds",
|
|
79
|
+
help: "Time between AGGREGATE_DUE_BPS of slot and call publish aggregate",
|
|
80
|
+
buckets: [0.5, 1, 2, 3, 6, 12],
|
|
81
|
+
}),
|
|
82
|
+
|
|
83
|
+
syncCommitteeStepCallProduceMessage: register.histogram({
|
|
84
|
+
name: "vc_sync_committee_step_call_produce_message_seconds",
|
|
85
|
+
help: "Time between SYNC_MESSAGE_DUE_BPS of slot and call produce message",
|
|
86
|
+
// Max wait time is SYNC_MESSAGE_DUE_BPS of slot
|
|
87
|
+
buckets: [0.5, 1, 2, 3, 6, 12],
|
|
88
|
+
}),
|
|
89
|
+
syncCommitteeStepCallPublishMessage: register.histogram({
|
|
90
|
+
name: "vc_sync_committee_step_call_publish_message_seconds",
|
|
91
|
+
help: "Time between SYNC_MESSAGE_DUE_BPS of slot and call publish message",
|
|
92
|
+
buckets: [0.5, 1, 2, 3, 6, 12],
|
|
93
|
+
}),
|
|
94
|
+
|
|
95
|
+
syncCommitteeStepCallProduceAggregate: register.histogram({
|
|
96
|
+
name: "vc_sync_committee_step_call_produce_aggregate_seconds",
|
|
97
|
+
help: "Time between CONTRIBUTION_DUE_BPS of slot and call produce aggregate",
|
|
98
|
+
// Min wait time is CONTRIBUTION_DUE_BPS of slot
|
|
99
|
+
buckets: [0.5, 1, 2, 3, 6, 12],
|
|
100
|
+
}),
|
|
101
|
+
syncCommitteeStepCallPublishAggregate: register.histogram({
|
|
102
|
+
name: "vc_sync_committee_step_call_publish_aggregate_seconds",
|
|
103
|
+
help: "Time between CONTRIBUTION_DUE_BPS of slot and call publish aggregate",
|
|
104
|
+
buckets: [0.5, 1, 2, 3, 6, 12],
|
|
105
|
+
}),
|
|
106
|
+
|
|
107
|
+
// Min wait time it 0. CallProduceBlock step is a bit redundant since it must be 0, but let's check
|
|
108
|
+
proposerStepCallProduceBlock: register.histogram({
|
|
109
|
+
name: "vc_proposer_step_call_produce_block_seconds",
|
|
110
|
+
help: "Time between start of slot and call produce block",
|
|
111
|
+
buckets: [0.5, 1, 2, 3, 6, 8],
|
|
112
|
+
}),
|
|
113
|
+
proposerStepCallPublishBlock: register.histogram({
|
|
114
|
+
name: "vc_proposer_step_call_publish_block_seconds",
|
|
115
|
+
help: "Time between start of slot and call publish block",
|
|
116
|
+
buckets: [0.5, 1, 2, 3, 6, 8],
|
|
117
|
+
}),
|
|
118
|
+
|
|
119
|
+
// AttestationService
|
|
120
|
+
|
|
121
|
+
publishedAttestations: register.gauge({
|
|
122
|
+
name: "vc_published_attestations_total",
|
|
123
|
+
help: "Total published attestations",
|
|
124
|
+
}),
|
|
125
|
+
|
|
126
|
+
publishedAggregates: register.gauge({
|
|
127
|
+
name: "vc_published_aggregates_total",
|
|
128
|
+
help: "Total published aggregates",
|
|
129
|
+
}),
|
|
130
|
+
|
|
131
|
+
numParticipantsInAggregate: register.histogram({
|
|
132
|
+
name: "vc_attestation_service_participants_in_aggregate_total",
|
|
133
|
+
help: "Number of attestations in the published AggregatedAttestation",
|
|
134
|
+
buckets: [1, 25, 50, 100, 250, 400, 500, 600],
|
|
135
|
+
}),
|
|
136
|
+
|
|
137
|
+
attestaterError: register.gauge<{error: "produce" | "sign" | "publish"}>({
|
|
138
|
+
name: "vc_attestation_service_errors",
|
|
139
|
+
help: "Total errors in AttestationService",
|
|
140
|
+
labelNames: ["error"],
|
|
141
|
+
}),
|
|
142
|
+
|
|
143
|
+
// AttestationDutiesService
|
|
144
|
+
|
|
145
|
+
attesterDutiesCount: register.gauge({
|
|
146
|
+
name: "vc_attester_duties_count",
|
|
147
|
+
help: "Current count of duties in AttestationDutiesService",
|
|
148
|
+
}),
|
|
149
|
+
|
|
150
|
+
attesterDutiesEpochCount: register.gauge({
|
|
151
|
+
name: "vc_attester_duties_epoch_count",
|
|
152
|
+
help: "Current count of epoch duties in AttestationDutiesService",
|
|
153
|
+
}),
|
|
154
|
+
|
|
155
|
+
attesterDutiesReorg: register.gauge({
|
|
156
|
+
name: "vc_attestation_duties_reorg_total",
|
|
157
|
+
help: "Total count of instances the attester duties dependent root changed",
|
|
158
|
+
}),
|
|
159
|
+
|
|
160
|
+
attesterDutiesNextSlot: register.gauge({
|
|
161
|
+
// Metric is used by Rocket Pool dashboard (18391) to determine seconds until next attestation.
|
|
162
|
+
// It works without requiring any modification to the dashboard as the metric name is the
|
|
163
|
+
// same as Lighthouse uses for this.
|
|
164
|
+
name: "vc_attestation_duty_slot",
|
|
165
|
+
help: "Slot of next scheduled attestation duty",
|
|
166
|
+
}),
|
|
167
|
+
|
|
168
|
+
// BlockProposingService
|
|
169
|
+
|
|
170
|
+
blocksProduced: register.gauge({
|
|
171
|
+
name: "vc_block_produced_total",
|
|
172
|
+
help: "Total count of blocks produced",
|
|
173
|
+
}),
|
|
174
|
+
|
|
175
|
+
blocksPublished: register.gauge({
|
|
176
|
+
name: "vc_block_published_total",
|
|
177
|
+
help: "Total count of blocks published",
|
|
178
|
+
}),
|
|
179
|
+
|
|
180
|
+
blockProposingErrors: register.gauge<{error: "produce" | "publish"}>({
|
|
181
|
+
name: "vc_block_proposing_errors_total",
|
|
182
|
+
help: "Total count of errors producing or publishing a block",
|
|
183
|
+
labelNames: ["error"],
|
|
184
|
+
}),
|
|
185
|
+
|
|
186
|
+
// BlockDutiesService
|
|
187
|
+
|
|
188
|
+
proposerDutiesEpochCount: register.gauge({
|
|
189
|
+
name: "vc_proposer_duties_epoch_count",
|
|
190
|
+
help: "Current count of epoch duties in BlockDutiesService",
|
|
191
|
+
}),
|
|
192
|
+
|
|
193
|
+
proposerDutiesReorg: register.gauge({
|
|
194
|
+
name: "vc_proposer_duties_reorg_total",
|
|
195
|
+
help: "Total count of instances the proposer duties dependent root changed",
|
|
196
|
+
}),
|
|
197
|
+
|
|
198
|
+
newProposalDutiesDetected: register.gauge({
|
|
199
|
+
name: "vc_new_proposal_duties_detected_total",
|
|
200
|
+
help: "Total count of times new proposal duties were detected",
|
|
201
|
+
}),
|
|
202
|
+
|
|
203
|
+
// IndicesService
|
|
204
|
+
|
|
205
|
+
indices: register.gauge({
|
|
206
|
+
name: "vc_indices_count",
|
|
207
|
+
help: "Current count of indices in IndicesService",
|
|
208
|
+
}),
|
|
209
|
+
|
|
210
|
+
discoveredIndices: register.gauge({
|
|
211
|
+
name: "vc_discovered_indices_total",
|
|
212
|
+
help: "Total count of validator indices discovered",
|
|
213
|
+
}),
|
|
214
|
+
|
|
215
|
+
// SyncCommitteeService
|
|
216
|
+
|
|
217
|
+
publishedSyncCommitteeMessage: register.gauge({
|
|
218
|
+
name: "vc_published_sync_committee_message_total",
|
|
219
|
+
help: "Total published SyncCommitteeMessage",
|
|
220
|
+
}),
|
|
221
|
+
|
|
222
|
+
publishedSyncCommitteeContribution: register.gauge({
|
|
223
|
+
name: "vc_published_sync_committee_contribution_total",
|
|
224
|
+
help: "Total published SyncCommitteeContribution",
|
|
225
|
+
}),
|
|
226
|
+
|
|
227
|
+
// SyncCommitteeDutiesService
|
|
228
|
+
|
|
229
|
+
syncCommitteeDutiesCount: register.gauge({
|
|
230
|
+
name: "vc_sync_committee_duties_count",
|
|
231
|
+
help: "Current count of duties in SyncCommitteeDutiesService",
|
|
232
|
+
}),
|
|
233
|
+
|
|
234
|
+
syncCommitteeDutiesEpochCount: register.gauge({
|
|
235
|
+
name: "vc_sync_committee_duties_epoch_count",
|
|
236
|
+
help: "Current count of epoch duties in SyncCommitteeDutiesService",
|
|
237
|
+
}),
|
|
238
|
+
|
|
239
|
+
syncCommitteeDutiesReorg: register.gauge({
|
|
240
|
+
name: "vc_sync_committee_duties_reorg_total",
|
|
241
|
+
help: "Total count of instances the sync committee duties dependent root changed",
|
|
242
|
+
}),
|
|
243
|
+
|
|
244
|
+
// ValidatorStore
|
|
245
|
+
|
|
246
|
+
signers: register.gauge({
|
|
247
|
+
name: "vc_signers_count",
|
|
248
|
+
help: "Total count of instances the sync committee duties dependent root changed",
|
|
249
|
+
}),
|
|
250
|
+
|
|
251
|
+
localSignTime: register.histogram({
|
|
252
|
+
name: "vc_local_sign_time_seconds",
|
|
253
|
+
help: "Histogram of sign time for any signature with local signer",
|
|
254
|
+
// When using a local keystores, signing time is ~ 1ms
|
|
255
|
+
buckets: [0.0001, 0.001, 0.01, 0.1],
|
|
256
|
+
}),
|
|
257
|
+
|
|
258
|
+
remoteSignTime: register.histogram({
|
|
259
|
+
name: "vc_remote_sign_time_seconds",
|
|
260
|
+
help: "Histogram of sign time for any signature with remote signer",
|
|
261
|
+
// When using a remote signer sign time can be ~ 50-500ms
|
|
262
|
+
buckets: [0.01, 0.1, 1, 5],
|
|
263
|
+
}),
|
|
264
|
+
|
|
265
|
+
remoteSignErrors: register.gauge({
|
|
266
|
+
name: "vc_remote_sign_errors_total",
|
|
267
|
+
help: "Total count of errors calling a remote signer",
|
|
268
|
+
}),
|
|
269
|
+
|
|
270
|
+
signError: register.gauge({
|
|
271
|
+
name: "vc_sign_errors_total",
|
|
272
|
+
help: "Total count of errors calling a signer",
|
|
273
|
+
}),
|
|
274
|
+
|
|
275
|
+
slashingProtectionBlockError: register.gauge({
|
|
276
|
+
name: "vc_slashing_protection_block_errors_total",
|
|
277
|
+
help: "Total count of errors on slashingProtection.checkAndInsertBlockProposal",
|
|
278
|
+
}),
|
|
279
|
+
|
|
280
|
+
slashingProtectionAttestationError: register.gauge({
|
|
281
|
+
name: "vc_slashing_protection_attestation_errors_total",
|
|
282
|
+
help: "Total count of errors on slashingProtection.checkAndInsertAttestation",
|
|
283
|
+
}),
|
|
284
|
+
|
|
285
|
+
// REST API client
|
|
286
|
+
|
|
287
|
+
beaconHealth: register.gauge({
|
|
288
|
+
name: "vc_beacon_health",
|
|
289
|
+
help: `Current health status of the beacon(s) the validator is connected to. ${renderEnumNumeric(BeaconHealth)}`,
|
|
290
|
+
}),
|
|
291
|
+
|
|
292
|
+
restApiClient: {
|
|
293
|
+
requestTime: register.histogram<{routeId: string}>({
|
|
294
|
+
name: "vc_rest_api_client_request_time_seconds",
|
|
295
|
+
help: "Histogram of REST API client request time by routeId",
|
|
296
|
+
labelNames: ["routeId"],
|
|
297
|
+
// Expected times are ~ 50-500ms, but in an overload NodeJS they can be greater
|
|
298
|
+
buckets: [0.01, 0.1, 1, 2, 5],
|
|
299
|
+
}),
|
|
300
|
+
|
|
301
|
+
streamTime: register.histogram<{routeId: string}>({
|
|
302
|
+
name: "vc_rest_api_client_stream_time_seconds",
|
|
303
|
+
help: "Histogram of REST API client streaming time by routeId",
|
|
304
|
+
labelNames: ["routeId"],
|
|
305
|
+
// Expected times are ~ 50-500ms, but in an overload NodeJS they can be greater
|
|
306
|
+
buckets: [0.01, 0.1, 1, 2, 5],
|
|
307
|
+
}),
|
|
308
|
+
|
|
309
|
+
requestErrors: register.gauge<{routeId: string; baseUrl: string}>({
|
|
310
|
+
name: "vc_rest_api_client_request_errors_total",
|
|
311
|
+
help: "Total count of errors on REST API client requests by routeId",
|
|
312
|
+
labelNames: ["routeId", "baseUrl"],
|
|
313
|
+
}),
|
|
314
|
+
|
|
315
|
+
requestToFallbacks: register.gauge<{routeId: string; baseUrl: string}>({
|
|
316
|
+
name: "vc_rest_api_client_request_to_fallbacks_total",
|
|
317
|
+
help: "Total count of requests to fallback URLs on REST API by routeId",
|
|
318
|
+
labelNames: ["routeId", "baseUrl"],
|
|
319
|
+
}),
|
|
320
|
+
|
|
321
|
+
urlsScore: register.gauge<{urlIndex: number; baseUrl: string}>({
|
|
322
|
+
name: "vc_rest_api_client_urls_score",
|
|
323
|
+
help: "Current score of REST API URLs by url index",
|
|
324
|
+
labelNames: ["urlIndex", "baseUrl"],
|
|
325
|
+
}),
|
|
326
|
+
},
|
|
327
|
+
|
|
328
|
+
keymanagerApiRest: {
|
|
329
|
+
responseTime: register.histogram<{operationId: string}>({
|
|
330
|
+
name: "vc_keymanager_api_rest_response_time_seconds",
|
|
331
|
+
help: "REST API time to fulfill a request by operationId",
|
|
332
|
+
labelNames: ["operationId"],
|
|
333
|
+
// Request times range between 1ms to 100ms in normal conditions. Can get to 1-5 seconds if overloaded
|
|
334
|
+
buckets: [0.01, 0.1, 1],
|
|
335
|
+
}),
|
|
336
|
+
requests: register.gauge<{operationId: string}>({
|
|
337
|
+
name: "vc_keymanager_api_rest_requests_total",
|
|
338
|
+
help: "REST API total count requests by operationId",
|
|
339
|
+
labelNames: ["operationId"],
|
|
340
|
+
}),
|
|
341
|
+
errors: register.gauge<{operationId: string}>({
|
|
342
|
+
name: "vc_keymanager_api_rest_errors_total",
|
|
343
|
+
help: "REST API total count of errors by operationId",
|
|
344
|
+
labelNames: ["operationId"],
|
|
345
|
+
}),
|
|
346
|
+
// Metrics for HttpActiveSocketsTracker, defined there
|
|
347
|
+
activeSockets: register.gauge({
|
|
348
|
+
name: "vc_keymanager_api_rest_active_sockets_count",
|
|
349
|
+
help: "REST API current count of active sockets",
|
|
350
|
+
}),
|
|
351
|
+
socketsBytesRead: register.gauge({
|
|
352
|
+
name: "vc_keymanager_api_rest_sockets_bytes_read_total",
|
|
353
|
+
help: "REST API total count of bytes read on all sockets",
|
|
354
|
+
}),
|
|
355
|
+
socketsBytesWritten: register.gauge({
|
|
356
|
+
name: "vc_keymanager_api_rest_sockets_bytes_written_total",
|
|
357
|
+
help: "REST API total count of bytes written on all sockets",
|
|
358
|
+
}),
|
|
359
|
+
},
|
|
360
|
+
|
|
361
|
+
db: {
|
|
362
|
+
dbReadReq: register.gauge<{bucket: string}>({
|
|
363
|
+
name: "vc_db_read_req_total",
|
|
364
|
+
help: "Total count of db read requests, may read 0 or more items",
|
|
365
|
+
labelNames: ["bucket"],
|
|
366
|
+
}),
|
|
367
|
+
dbReadItems: register.gauge<{bucket: string}>({
|
|
368
|
+
name: "vc_db_read_items_total",
|
|
369
|
+
help: "Total count of db read items, item = key | value | entry",
|
|
370
|
+
labelNames: ["bucket"],
|
|
371
|
+
}),
|
|
372
|
+
dbWriteReq: register.gauge<{bucket: string}>({
|
|
373
|
+
name: "vc_db_write_req_total",
|
|
374
|
+
help: "Total count of db write requests, may write 0 or more items",
|
|
375
|
+
labelNames: ["bucket"],
|
|
376
|
+
}),
|
|
377
|
+
dbWriteItems: register.gauge<{bucket: string}>({
|
|
378
|
+
name: "vc_db_write_items_total",
|
|
379
|
+
help: "Total count of db write items",
|
|
380
|
+
labelNames: ["bucket"],
|
|
381
|
+
}),
|
|
382
|
+
dbSizeTotal: register.gauge({
|
|
383
|
+
name: "vc_db_size_bytes_total",
|
|
384
|
+
help: "Approximate number of bytes of file system space used by db",
|
|
385
|
+
}),
|
|
386
|
+
dbApproximateSizeTime: register.histogram({
|
|
387
|
+
name: "vc_db_approximate_size_time_seconds",
|
|
388
|
+
help: "Time to approximate db size in seconds",
|
|
389
|
+
buckets: [0.0001, 0.001, 0.01, 0.1, 1],
|
|
390
|
+
}),
|
|
391
|
+
},
|
|
392
|
+
|
|
393
|
+
doppelganger: {
|
|
394
|
+
statusCount: register.gauge<{status: string}>({
|
|
395
|
+
name: "vc_doppelganger_validator_status_count",
|
|
396
|
+
help: "Count of validators per status",
|
|
397
|
+
labelNames: ["status"],
|
|
398
|
+
}),
|
|
399
|
+
epochsChecked: register.gauge({
|
|
400
|
+
name: "vc_doppelganger_epochs_checked_total",
|
|
401
|
+
help: "Total count of epochs checked",
|
|
402
|
+
}),
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export function renderEnumNumeric(obj: Record<string, unknown>): string {
|
|
408
|
+
const out: string[] = [];
|
|
409
|
+
|
|
410
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
411
|
+
if (typeof value === "number") {
|
|
412
|
+
out.push(`${key}=${value}`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return out.join(", ");
|
|
417
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./metaDataRepository.js";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {DbReqOpts, encodeKey} from "@lodestar/db";
|
|
2
|
+
import {Root, UintNum64, ssz} from "@lodestar/types";
|
|
3
|
+
import {Bucket, getBucketNameByValue} from "../buckets.js";
|
|
4
|
+
import {LodestarValidatorDatabaseController} from "../types.js";
|
|
5
|
+
|
|
6
|
+
const GENESIS_VALIDATORS_ROOT = Buffer.from("GENESIS_VALIDATORS_ROOT");
|
|
7
|
+
const GENESIS_TIME = Buffer.from("GENESIS_TIME");
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Store MetaData of validator.
|
|
11
|
+
*/
|
|
12
|
+
export class MetaDataRepository {
|
|
13
|
+
protected bucket = Bucket.validator_metaData;
|
|
14
|
+
|
|
15
|
+
private readonly bucketId = getBucketNameByValue(this.bucket);
|
|
16
|
+
private readonly dbReqOpts: DbReqOpts = {bucketId: this.bucketId};
|
|
17
|
+
|
|
18
|
+
constructor(protected db: LodestarValidatorDatabaseController) {
|
|
19
|
+
this.dbReqOpts = {bucketId: this.bucketId};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async getGenesisValidatorsRoot(): Promise<Root | null> {
|
|
23
|
+
return this.db.get(this.encodeKey(GENESIS_VALIDATORS_ROOT), this.dbReqOpts);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async setGenesisValidatorsRoot(genesisValidatorsRoot: Root): Promise<void> {
|
|
27
|
+
await this.db.put(this.encodeKey(GENESIS_VALIDATORS_ROOT), genesisValidatorsRoot, this.dbReqOpts);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async getGenesisTime(): Promise<UintNum64 | null> {
|
|
31
|
+
const bytes = await this.db.get(this.encodeKey(GENESIS_TIME), this.dbReqOpts);
|
|
32
|
+
return bytes ? ssz.UintNum64.deserialize(bytes) : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async setGenesisTime(genesisTime: UintNum64): Promise<void> {
|
|
36
|
+
await this.db.put(this.encodeKey(GENESIS_TIME), ssz.UintNum64.serialize(genesisTime), this.dbReqOpts);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private encodeKey(key: Uint8Array): Uint8Array {
|
|
40
|
+
return encodeKey(this.bucket, key);
|
|
41
|
+
}
|
|
42
|
+
}
|