Skip to content

Commit

Permalink
feat(validator): add bucket labels to db metrics (#5436)
Browse files Browse the repository at this point in the history
  • Loading branch information
nflaig authored Apr 29, 2023
1 parent 2e8f84e commit 2fbf178
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 33 deletions.
2 changes: 1 addition & 1 deletion packages/db/src/controller/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export {Db, DatabaseController, FilterOptions, KeyValue} from "./interface.js";
export {Db, DbReqOpts, DatabaseController, FilterOptions, KeyValue} from "./interface.js";
export {LevelDbController} from "./level.js";
export {LevelDbControllerMetrics} from "./metrics.js";
1 change: 1 addition & 0 deletions packages/db/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from "./abstractRepository.js";
export * from "./controller/index.js";
export * from "./schema.js";
export * from "./const.js";
export * from "./util.js";
15 changes: 10 additions & 5 deletions packages/validator/src/repositories/metaDataRepository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Bucket, encodeKey, DatabaseApiOptions} from "@lodestar/db";
import {Bucket, encodeKey, DatabaseApiOptions, DbReqOpts, getBucketNameByValue} from "@lodestar/db";
import {Root, UintNum64} from "@lodestar/types";
import {ssz} from "@lodestar/types";
import {LodestarValidatorDatabaseController} from "../types.js";
Expand All @@ -13,25 +13,30 @@ export class MetaDataRepository {
protected db: LodestarValidatorDatabaseController;
protected bucket = Bucket.validator_metaData;

private readonly bucketId: string;
private readonly dbReqOpts: DbReqOpts;

constructor(opts: DatabaseApiOptions) {
this.db = opts.controller;
this.bucketId = getBucketNameByValue(this.bucket);
this.dbReqOpts = {bucketId: this.bucketId};
}

async getGenesisValidatorsRoot(): Promise<Root | null> {
return this.db.get(this.encodeKey(GENESIS_VALIDATORS_ROOT));
return this.db.get(this.encodeKey(GENESIS_VALIDATORS_ROOT), this.dbReqOpts);
}

async setGenesisValidatorsRoot(genesisValidatorsRoot: Root): Promise<void> {
await this.db.put(this.encodeKey(GENESIS_VALIDATORS_ROOT), Buffer.from(genesisValidatorsRoot));
await this.db.put(this.encodeKey(GENESIS_VALIDATORS_ROOT), Buffer.from(genesisValidatorsRoot), this.dbReqOpts);
}

async getGenesisTime(): Promise<UintNum64 | null> {
const bytes = await this.db.get(this.encodeKey(GENESIS_TIME));
const bytes = await this.db.get(this.encodeKey(GENESIS_TIME), this.dbReqOpts);
return bytes ? ssz.UintNum64.deserialize(bytes) : null;
}

async setGenesisTime(genesisTime: UintNum64): Promise<void> {
await this.db.put(this.encodeKey(GENESIS_TIME), Buffer.from(ssz.UintNum64.serialize(genesisTime)));
await this.db.put(this.encodeKey(GENESIS_TIME), Buffer.from(ssz.UintNum64.serialize(genesisTime)), this.dbReqOpts);
}

private encodeKey(key: Uint8Array): Uint8Array {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import {BLSPubkey, Epoch, ssz} from "@lodestar/types";
import {intToBytes, bytesToInt} from "@lodestar/utils";
import {Bucket, DB_PREFIX_LENGTH, encodeKey, DatabaseApiOptions, uintLen} from "@lodestar/db";
import {
Bucket,
DatabaseApiOptions,
DB_PREFIX_LENGTH,
DbReqOpts,
encodeKey,
uintLen,
getBucketNameByValue,
} from "@lodestar/db";
import {ContainerType, Type} from "@chainsafe/ssz";
import {LodestarValidatorDatabaseController} from "../../types.js";
import {SlashingProtectionAttestation} from "../types.js";
Expand All @@ -16,17 +24,23 @@ export class AttestationByTargetRepository {
protected db: LodestarValidatorDatabaseController;
protected bucket = Bucket.phase0_slashingProtectionAttestationByTarget;

private readonly bucketId: string;
private readonly dbReqOpts: DbReqOpts;

constructor(opts: DatabaseApiOptions) {
this.db = opts.controller;
this.type = new ContainerType({
sourceEpoch: ssz.Epoch,
targetEpoch: ssz.Epoch,
signingRoot: ssz.Root,
}); // casing doesn't matter
this.bucketId = getBucketNameByValue(this.bucket);
this.dbReqOpts = {bucketId: this.bucketId};
}

async getAll(pubkey: BLSPubkey, limit?: number): Promise<SlashingProtectionAttestation[]> {
const attestations = await this.db.values({
...this.dbReqOpts,
limit,
gte: this.encodeKey(pubkey, 0),
lt: this.encodeKey(pubkey, Number.MAX_SAFE_INTEGER),
Expand All @@ -35,7 +49,7 @@ export class AttestationByTargetRepository {
}

async get(pubkey: BLSPubkey, targetEpoch: Epoch): Promise<SlashingProtectionAttestation | null> {
const att = await this.db.get(this.encodeKey(pubkey, targetEpoch));
const att = await this.db.get(this.encodeKey(pubkey, targetEpoch), this.dbReqOpts);
return att && this.type.deserialize(att);
}

Expand All @@ -44,20 +58,18 @@ export class AttestationByTargetRepository {
atts.map((att) => ({
key: this.encodeKey(pubkey, att.targetEpoch),
value: Buffer.from(this.type.serialize(att)),
}))
})),
this.dbReqOpts
);
}

async listPubkeys(): Promise<BLSPubkey[]> {
const keys = await this.db.keys();
const keys = await this.db.keys(this.dbReqOpts);
return uniqueVectorArr(keys.map((key) => this.decodeKey(key).pubkey));
}

private encodeKey(pubkey: BLSPubkey, targetEpoch: Epoch): Uint8Array {
return encodeKey(
this.bucket,
Buffer.concat([Buffer.from(pubkey as Uint8Array), intToBytes(BigInt(targetEpoch), uintLen, "be")])
);
return encodeKey(this.bucket, Buffer.concat([Buffer.from(pubkey), intToBytes(BigInt(targetEpoch), uintLen, "be")]));
}

private decodeKey(key: Uint8Array): {pubkey: BLSPubkey; targetEpoch: Epoch} {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {BLSPubkey, Epoch, ssz} from "@lodestar/types";
import {Bucket, encodeKey, DatabaseApiOptions} from "@lodestar/db";
import {Bucket, encodeKey, DatabaseApiOptions, DbReqOpts, getBucketNameByValue} from "@lodestar/db";
import {ContainerType, Type} from "@chainsafe/ssz";
import {LodestarValidatorDatabaseController} from "../../types.js";

Expand All @@ -18,24 +18,29 @@ export class AttestationLowerBoundRepository {
protected db: LodestarValidatorDatabaseController;
protected bucket = Bucket.phase0_slashingProtectionAttestationLowerBound;

private readonly bucketId: string;
private readonly dbReqOpts: DbReqOpts;

constructor(opts: DatabaseApiOptions) {
this.db = opts.controller;
this.type = new ContainerType({
minSourceEpoch: ssz.Epoch,
minTargetEpoch: ssz.Epoch,
}); // casing doesn't matter
this.bucketId = getBucketNameByValue(this.bucket);
this.dbReqOpts = {bucketId: this.bucketId};
}

async get(pubkey: BLSPubkey): Promise<SlashingProtectionLowerBound | null> {
const att = await this.db.get(this.encodeKey(pubkey));
const att = await this.db.get(this.encodeKey(pubkey), this.dbReqOpts);
return att && this.type.deserialize(att);
}

async set(pubkey: BLSPubkey, value: SlashingProtectionLowerBound): Promise<void> {
await this.db.put(this.encodeKey(pubkey), Buffer.from(this.type.serialize(value)));
await this.db.put(this.encodeKey(pubkey), Buffer.from(this.type.serialize(value)), this.dbReqOpts);
}

private encodeKey(pubkey: BLSPubkey): Uint8Array {
return encodeKey(this.bucket, Buffer.from(pubkey as Uint8Array));
return encodeKey(this.bucket, Buffer.from(pubkey));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import {BLSPubkey, Slot, ssz} from "@lodestar/types";
import {intToBytes, bytesToInt} from "@lodestar/utils";
import {Bucket, DB_PREFIX_LENGTH, encodeKey, DatabaseApiOptions, uintLen} from "@lodestar/db";
import {
Bucket,
DatabaseApiOptions,
DB_PREFIX_LENGTH,
DbReqOpts,
encodeKey,
uintLen,
getBucketNameByValue,
} from "@lodestar/db";
import {ContainerType, Type} from "@chainsafe/ssz";
import {LodestarValidatorDatabaseController} from "../../types.js";
import {SlashingProtectionBlock} from "../types.js";
Expand All @@ -16,16 +24,22 @@ export class BlockBySlotRepository {
protected db: LodestarValidatorDatabaseController;
protected bucket = Bucket.phase0_slashingProtectionBlockBySlot;

private readonly bucketId: string;
private readonly dbReqOpts: DbReqOpts;

constructor(opts: DatabaseApiOptions) {
this.db = opts.controller;
this.type = new ContainerType({
slot: ssz.Slot,
signingRoot: ssz.Root,
}); // casing doesn't matter
this.bucketId = getBucketNameByValue(this.bucket);
this.dbReqOpts = {bucketId: this.bucketId};
}

async getAll(pubkey: BLSPubkey, limit?: number): Promise<SlashingProtectionBlock[]> {
const blocks = await this.db.values({
...this.dbReqOpts,
limit,
gte: this.encodeKey(pubkey, 0),
lt: this.encodeKey(pubkey, Number.MAX_SAFE_INTEGER),
Expand All @@ -39,7 +53,7 @@ export class BlockBySlotRepository {
}

async get(pubkey: BLSPubkey, slot: Slot): Promise<SlashingProtectionBlock | null> {
const block = await this.db.get(this.encodeKey(pubkey, slot));
const block = await this.db.get(this.encodeKey(pubkey, slot), this.dbReqOpts);
return block && this.type.deserialize(block);
}

Expand All @@ -48,20 +62,18 @@ export class BlockBySlotRepository {
blocks.map((block) => ({
key: this.encodeKey(pubkey, block.slot),
value: Buffer.from(this.type.serialize(block)),
}))
})),
this.dbReqOpts
);
}

async listPubkeys(): Promise<BLSPubkey[]> {
const keys = await this.db.keys();
const keys = await this.db.keys(this.dbReqOpts);
return uniqueVectorArr(keys.map((key) => this.decodeKey(key).pubkey));
}

private encodeKey(pubkey: BLSPubkey, slot: Slot): Uint8Array {
return encodeKey(
this.bucket,
Buffer.concat([Buffer.from(pubkey as Uint8Array), intToBytes(BigInt(slot), uintLen, "be")])
);
return encodeKey(this.bucket, Buffer.concat([Buffer.from(pubkey), intToBytes(BigInt(slot), uintLen, "be")]));
}

private decodeKey(key: Uint8Array): {pubkey: BLSPubkey; slot: Slot} {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Bucket, encodeKey, DatabaseApiOptions} from "@lodestar/db";
import {Bucket, encodeKey, DatabaseApiOptions, DbReqOpts, getBucketNameByValue} from "@lodestar/db";
import {BLSPubkey, Epoch, ssz} from "@lodestar/types";
import {intToBytes} from "@lodestar/utils";
import {Type} from "@chainsafe/ssz";
Expand All @@ -23,14 +23,19 @@ class SpanDistanceRepository {
protected db: LodestarValidatorDatabaseController;
protected bucket: Bucket;

private readonly bucketId: string;
private readonly dbReqOpts: DbReqOpts;

constructor(opts: DatabaseApiOptions, bucket: Bucket) {
this.db = opts.controller;
this.type = ssz.Epoch;
this.bucket = bucket;
this.bucketId = getBucketNameByValue(this.bucket);
this.dbReqOpts = {bucketId: this.bucketId};
}

async get(pubkey: BLSPubkey, epoch: Epoch): Promise<Epoch | null> {
const distance = await this.db.get(this.encodeKey(pubkey, epoch));
const distance = await this.db.get(this.encodeKey(pubkey, epoch), this.dbReqOpts);
return distance && this.type.deserialize(distance);
}

Expand All @@ -39,14 +44,12 @@ class SpanDistanceRepository {
values.map((value) => ({
key: this.encodeKey(pubkey, value.source),
value: Buffer.from(this.type.serialize(value.distance)),
}))
})),
this.dbReqOpts
);
}

private encodeKey(pubkey: BLSPubkey, epoch: Epoch): Uint8Array {
return encodeKey(
this.bucket,
Buffer.concat([Buffer.from(pubkey as Uint8Array), intToBytes(BigInt(epoch), 8, "be")])
);
return encodeKey(this.bucket, Buffer.concat([Buffer.from(pubkey), intToBytes(BigInt(epoch), 8, "be")]));
}
}

0 comments on commit 2fbf178

Please sign in to comment.