mirror of
https://github.com/ChainSafe/lodestar.git
synced 2026-01-09 15:48:08 -05:00
fix: add bucketId to all db operations (#8347)
**Motivation** Similar to https://github.com/ChainSafe/lodestar/pull/8346 adds missing `bucketId` to all db operations to avoid `unknown` This is from `stable-lg1k-hzax41-dkr` which shows it's already an issue there <img width="1890" height="684" alt="image" src="https://github.com/user-attachments/assets/cfbdb335-b3ec-49b7-9ae2-be345ce8071e" /> **Description** Add `bucketId` to all db operations deployed to `feat3` to make sure I didn't miss anything
This commit is contained in:
@@ -5,7 +5,7 @@ import {bytesToInt} from "@lodestar/utils";
|
||||
import all from "it-all";
|
||||
import {getSignedBlockTypeFromBytes} from "../../util/multifork.js";
|
||||
import {Bucket, getBucketNameByValue} from "../buckets.js";
|
||||
import {getParentRootIndexKey, getRootIndexKey} from "./blockArchiveIndex.js";
|
||||
import {getParentRootIndex, getRootIndex} from "./blockArchiveIndex.js";
|
||||
import {deleteParentRootIndex, deleteRootIndex, storeParentRootIndex, storeRootIndex} from "./blockArchiveIndex.js";
|
||||
|
||||
export interface BlockFilterOptions extends FilterOptions<Slot> {
|
||||
@@ -136,11 +136,11 @@ export class BlockArchiveRepository extends Repository<Slot, SignedBeaconBlock>
|
||||
}
|
||||
|
||||
async getSlotByRoot(root: Root): Promise<Slot | null> {
|
||||
return this.parseSlot(await this.db.get(getRootIndexKey(root)));
|
||||
return this.parseSlot(await getRootIndex(this.db, root));
|
||||
}
|
||||
|
||||
async getSlotByParentRoot(root: Root): Promise<Slot | null> {
|
||||
return this.parseSlot(await this.db.get(getParentRootIndexKey(root)));
|
||||
return this.parseSlot(await getParentRootIndex(this.db, root));
|
||||
}
|
||||
|
||||
private parseSlot(slotBytes: Uint8Array | null): Slot | null {
|
||||
|
||||
@@ -2,14 +2,25 @@ import {Db, encodeKey} from "@lodestar/db";
|
||||
import {ForkAll} from "@lodestar/params";
|
||||
import {Root, SSZTypesFor, SignedBeaconBlock, Slot, ssz} from "@lodestar/types";
|
||||
import {intToBytes} from "@lodestar/utils";
|
||||
import {Bucket} from "../buckets.js";
|
||||
import {Bucket, getBucketNameByValue} from "../buckets.js";
|
||||
|
||||
export const rootIndexBucketId = getBucketNameByValue(Bucket.index_blockArchiveRootIndex);
|
||||
export const parentRootIndexBucketId = getBucketNameByValue(Bucket.index_blockArchiveParentRootIndex);
|
||||
|
||||
export async function getRootIndex(db: Db, blockRoot: Root): Promise<Uint8Array | null> {
|
||||
return db.get(getRootIndexKey(blockRoot), {bucketId: rootIndexBucketId});
|
||||
}
|
||||
|
||||
export async function getParentRootIndex(db: Db, parentRoot: Root): Promise<Uint8Array | null> {
|
||||
return db.get(getParentRootIndexKey(parentRoot), {bucketId: parentRootIndexBucketId});
|
||||
}
|
||||
|
||||
export async function storeRootIndex(db: Db, slot: Slot, blockRoot: Root): Promise<void> {
|
||||
return db.put(getRootIndexKey(blockRoot), intToBytes(slot, 8, "be"));
|
||||
return db.put(getRootIndexKey(blockRoot), intToBytes(slot, 8, "be"), {bucketId: rootIndexBucketId});
|
||||
}
|
||||
|
||||
export async function storeParentRootIndex(db: Db, slot: Slot, parentRoot: Root): Promise<void> {
|
||||
return db.put(getParentRootIndexKey(parentRoot), intToBytes(slot, 8, "be"));
|
||||
return db.put(getParentRootIndexKey(parentRoot), intToBytes(slot, 8, "be"), {bucketId: parentRootIndexBucketId});
|
||||
}
|
||||
|
||||
export async function deleteRootIndex(
|
||||
@@ -18,11 +29,11 @@ export async function deleteRootIndex(
|
||||
block: SignedBeaconBlock
|
||||
): Promise<void> {
|
||||
const beaconBlockType = (signedBeaconBlockType as typeof ssz.phase0.SignedBeaconBlock).fields.message;
|
||||
return db.delete(getRootIndexKey(beaconBlockType.hashTreeRoot(block.message)));
|
||||
return db.delete(getRootIndexKey(beaconBlockType.hashTreeRoot(block.message)), {bucketId: rootIndexBucketId});
|
||||
}
|
||||
|
||||
export async function deleteParentRootIndex(db: Db, block: SignedBeaconBlock): Promise<void> {
|
||||
return db.delete(getParentRootIndexKey(block.message.parentRoot));
|
||||
return db.delete(getParentRootIndexKey(block.message.parentRoot), {bucketId: parentRootIndexBucketId});
|
||||
}
|
||||
|
||||
export function getParentRootIndexKey(parentRoot: Root): Uint8Array {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Epoch, Root, RootHex, Slot, ssz} from "@lodestar/types";
|
||||
import {bytesToInt, toHex} from "@lodestar/utils";
|
||||
import {getStateTypeFromBytes} from "../../util/multifork.js";
|
||||
import {Bucket, getBucketNameByValue} from "../buckets.js";
|
||||
import {getRootIndexKey, storeRootIndex} from "./stateArchiveIndex.js";
|
||||
import {getRootIndex, getRootIndexKey, storeRootIndex} from "./stateArchiveIndex.js";
|
||||
|
||||
export class StateArchiveRepository extends Repository<Slot, BeaconStateAllForks> {
|
||||
constructor(config: ChainForkConfig, db: Db) {
|
||||
@@ -54,6 +54,7 @@ export class StateArchiveRepository extends Repository<Slot, BeaconStateAllForks
|
||||
const entries = await this.db.entries({
|
||||
lte: getRootIndexKey(Buffer.alloc(32, 0xff)),
|
||||
gte: getRootIndexKey(Buffer.alloc(32, 0x00)),
|
||||
bucketId: this.bucketId,
|
||||
});
|
||||
return entries.map((entry) => ({
|
||||
root: toHex(entry.key),
|
||||
@@ -62,7 +63,7 @@ export class StateArchiveRepository extends Repository<Slot, BeaconStateAllForks
|
||||
}
|
||||
|
||||
private async getSlotByRoot(root: Root): Promise<Slot | null> {
|
||||
const value = await this.db.get(getRootIndexKey(root));
|
||||
const value = await getRootIndex(this.db, root);
|
||||
return value && bytesToInt(value, "be");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import {Db, encodeKey} from "@lodestar/db";
|
||||
import {Root, Slot} from "@lodestar/types";
|
||||
import {intToBytes} from "@lodestar/utils";
|
||||
import {Bucket} from "../buckets.js";
|
||||
import {Bucket, getBucketNameByValue} from "../buckets.js";
|
||||
|
||||
const bucketId = getBucketNameByValue(Bucket.index_stateArchiveRootIndex);
|
||||
|
||||
export function getRootIndex(db: Db, stateRoot: Root): Promise<Uint8Array | null> {
|
||||
return db.get(getRootIndexKey(stateRoot), {bucketId});
|
||||
}
|
||||
|
||||
export function storeRootIndex(db: Db, slot: Slot, stateRoot: Root): Promise<void> {
|
||||
return db.put(getRootIndexKey(stateRoot), intToBytes(slot, 8, "be"));
|
||||
return db.put(getRootIndexKey(stateRoot), intToBytes(slot, 8, "be"), {bucketId});
|
||||
}
|
||||
|
||||
export function getRootIndexKey(root: Root): Uint8Array {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {ChainForkConfig} from "@lodestar/config";
|
||||
import {Db} from "@lodestar/db";
|
||||
import {Db, DbReqOpts} from "@lodestar/db";
|
||||
import {ForkAll, GENESIS_SLOT} from "@lodestar/params";
|
||||
import {BeaconStateAllForks} from "@lodestar/state-transition";
|
||||
import {SSZTypesFor} from "@lodestar/types";
|
||||
import {Bucket} from "../buckets.js";
|
||||
import {Bucket, getBucketNameByValue} from "../buckets.js";
|
||||
|
||||
export class PreGenesisState {
|
||||
private readonly config: ChainForkConfig;
|
||||
@@ -11,6 +11,7 @@ export class PreGenesisState {
|
||||
private readonly db: Db;
|
||||
private readonly key: Uint8Array;
|
||||
private readonly type: SSZTypesFor<ForkAll, "BeaconState">;
|
||||
private readonly dbReqOpts: DbReqOpts;
|
||||
|
||||
constructor(config: ChainForkConfig, db: Db) {
|
||||
this.config = config;
|
||||
@@ -18,18 +19,19 @@ export class PreGenesisState {
|
||||
this.bucket = Bucket.phase0_preGenesisState;
|
||||
this.key = new Uint8Array([this.bucket]);
|
||||
this.type = this.config.getForkTypes(GENESIS_SLOT).BeaconState;
|
||||
this.dbReqOpts = {bucketId: getBucketNameByValue(this.bucket)};
|
||||
}
|
||||
|
||||
async put(value: BeaconStateAllForks): Promise<void> {
|
||||
await this.db.put(this.key, value.serialize());
|
||||
await this.db.put(this.key, value.serialize(), this.dbReqOpts);
|
||||
}
|
||||
|
||||
async get(): Promise<BeaconStateAllForks | null> {
|
||||
const value = await this.db.get(this.key);
|
||||
const value = await this.db.get(this.key, this.dbReqOpts);
|
||||
return value ? this.type.deserializeToViewDU(value) : null;
|
||||
}
|
||||
|
||||
async delete(): Promise<void> {
|
||||
await this.db.delete(this.key);
|
||||
await this.db.delete(this.key, this.dbReqOpts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
import {UintNumberType} from "@chainsafe/ssz";
|
||||
import {ChainForkConfig} from "@lodestar/config";
|
||||
import {Db} from "@lodestar/db";
|
||||
import {Db, DbReqOpts} from "@lodestar/db";
|
||||
import {ssz} from "@lodestar/types";
|
||||
import {Bucket} from "../buckets.js";
|
||||
import {Bucket, getBucketNameByValue} from "../buckets.js";
|
||||
|
||||
export class PreGenesisStateLastProcessedBlock {
|
||||
private readonly bucket: Bucket;
|
||||
private readonly type: UintNumberType;
|
||||
private readonly db: Db;
|
||||
private readonly key: Uint8Array;
|
||||
private readonly dbReqOpts: DbReqOpts;
|
||||
|
||||
constructor(_config: ChainForkConfig, db: Db) {
|
||||
this.db = db;
|
||||
this.type = ssz.UintNum64;
|
||||
this.bucket = Bucket.phase0_preGenesisStateLastProcessedBlock;
|
||||
this.key = new Uint8Array([this.bucket]);
|
||||
this.dbReqOpts = {bucketId: getBucketNameByValue(this.bucket)};
|
||||
}
|
||||
|
||||
async put(value: number): Promise<void> {
|
||||
await this.db.put(this.key, this.type.serialize(value));
|
||||
await this.db.put(this.key, this.type.serialize(value), this.dbReqOpts);
|
||||
}
|
||||
|
||||
async get(): Promise<number | null> {
|
||||
const value = await this.db.get(this.key);
|
||||
const value = await this.db.get(this.key, this.dbReqOpts);
|
||||
return value ? this.type.deserialize(value) : null;
|
||||
}
|
||||
|
||||
async delete(): Promise<void> {
|
||||
await this.db.delete(this.key);
|
||||
await this.db.delete(this.key, this.dbReqOpts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {intToBytes} from "@lodestar/utils";
|
||||
import {rimraf} from "rimraf";
|
||||
import {afterEach, beforeEach, describe, expect, it, vi} from "vitest";
|
||||
|
||||
import {Bucket} from "../../../../../src/db/buckets.js";
|
||||
import {Bucket, getBucketNameByValue} from "../../../../../src/db/buckets.js";
|
||||
import {BlockArchiveRepository} from "../../../../../src/db/repositories/index.js";
|
||||
import {testLogger} from "../../../../utils/logger.js";
|
||||
|
||||
@@ -112,11 +112,13 @@ describe("block archive repository", () => {
|
||||
await blockArchive.add(block);
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
encodeKey(Bucket.index_blockArchiveRootIndex, ssz.phase0.BeaconBlock.hashTreeRoot(block.message)),
|
||||
intToBytes(block.message.slot, 8, "be")
|
||||
intToBytes(block.message.slot, 8, "be"),
|
||||
{bucketId: getBucketNameByValue(Bucket.index_blockArchiveRootIndex)}
|
||||
);
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
encodeKey(Bucket.index_blockArchiveParentRootIndex, block.message.parentRoot),
|
||||
intToBytes(block.message.slot, 8, "be")
|
||||
intToBytes(block.message.slot, 8, "be"),
|
||||
{bucketId: getBucketNameByValue(Bucket.index_blockArchiveParentRootIndex)}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -131,10 +133,12 @@ describe("block archive repository", () => {
|
||||
[
|
||||
encodeKey(Bucket.index_blockArchiveRootIndex, ssz.phase0.BeaconBlock.hashTreeRoot(blocks[0].message)),
|
||||
intToBytes(blocks[0].message.slot, 8, "be"),
|
||||
{bucketId: getBucketNameByValue(Bucket.index_blockArchiveRootIndex)},
|
||||
],
|
||||
[
|
||||
encodeKey(Bucket.index_blockArchiveRootIndex, ssz.phase0.BeaconBlock.hashTreeRoot(blocks[0].message)),
|
||||
intToBytes(blocks[0].message.slot, 8, "be"),
|
||||
{bucketId: getBucketNameByValue(Bucket.index_blockArchiveRootIndex)},
|
||||
],
|
||||
])
|
||||
);
|
||||
@@ -143,10 +147,12 @@ describe("block archive repository", () => {
|
||||
[
|
||||
encodeKey(Bucket.index_blockArchiveParentRootIndex, blocks[0].message.parentRoot),
|
||||
intToBytes(blocks[0].message.slot, 8, "be"),
|
||||
{bucketId: getBucketNameByValue(Bucket.index_blockArchiveParentRootIndex)},
|
||||
],
|
||||
[
|
||||
encodeKey(Bucket.index_blockArchiveParentRootIndex, blocks[0].message.parentRoot),
|
||||
intToBytes(blocks[0].message.slot, 8, "be"),
|
||||
{bucketId: getBucketNameByValue(Bucket.index_blockArchiveParentRootIndex)},
|
||||
],
|
||||
])
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@ export abstract class Repository<I extends Id, T> {
|
||||
protected db: Db,
|
||||
protected bucket: number,
|
||||
protected type: Type<T>,
|
||||
private readonly bucketId: string
|
||||
protected readonly bucketId: string
|
||||
) {
|
||||
this.dbReqOpts = {bucketId: this.bucketId};
|
||||
this.minKey = _encodeKey(bucket, Buffer.alloc(0));
|
||||
|
||||
Reference in New Issue
Block a user