Skip to content

Commit

Permalink
fix: use toRootHex where applicable (#7021)
Browse files Browse the repository at this point in the history
* fix: use toRootHex where applicable

* fix: toRootHex() to handle different lengths

* fix: throw error if root is not 32 bytes

* Fix eth1MergeBlockTracker unit test

---------

Co-authored-by: Nico Flaig <[email protected]>
  • Loading branch information
twoeths and nflaig committed Aug 15, 2024
1 parent 44b2156 commit 20c18ad
Show file tree
Hide file tree
Showing 31 changed files with 112 additions and 116 deletions.
16 changes: 8 additions & 8 deletions packages/beacon-node/src/api/impl/beacon/blocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
signedBeaconBlockToBlinded,
} from "@lodestar/state-transition";
import {ForkExecution, SLOTS_PER_HISTORICAL_ROOT, isForkExecution} from "@lodestar/params";
import {sleep, fromHex, toHex} from "@lodestar/utils";
import {sleep, fromHex, toRootHex} from "@lodestar/utils";
import {
deneb,
isSignedBlockContents,
Expand Down Expand Up @@ -97,9 +97,9 @@ export function getBeaconBlockApi({
// state transition to produce the stateRoot
const slot = signedBlock.message.slot;
const fork = config.getForkName(slot);
const blockRoot = toHex(chain.config.getForkTypes(slot).BeaconBlock.hashTreeRoot(signedBlock.message));
const blockRoot = toRootHex(chain.config.getForkTypes(slot).BeaconBlock.hashTreeRoot(signedBlock.message));
// bodyRoot should be the same to produced block
const bodyRoot = toHex(chain.config.getForkTypes(slot).BeaconBlockBody.hashTreeRoot(signedBlock.message.body));
const bodyRoot = toRootHex(chain.config.getForkTypes(slot).BeaconBlockBody.hashTreeRoot(signedBlock.message.body));
const blockLocallyProduced =
chain.producedBlockRoot.has(blockRoot) || chain.producedBlindedBlockRoot.has(blockRoot);
const valLogMeta = {slot, blockRoot, bodyRoot, broadcastValidation, blockLocallyProduced};
Expand Down Expand Up @@ -147,7 +147,7 @@ export function getBeaconBlockApi({
);
throw new BlockError(signedBlock, {
code: BlockErrorCode.PARENT_UNKNOWN,
parentRoot: toHex(signedBlock.message.parentRoot),
parentRoot: toRootHex(signedBlock.message.parentRoot),
});
}

Expand Down Expand Up @@ -243,7 +243,7 @@ export function getBeaconBlockApi({
opts: PublishBlockOpts = {}
) => {
const slot = signedBlindedBlock.message.slot;
const blockRoot = toHex(
const blockRoot = toRootHex(
chain.config
.getExecutionForkTypes(signedBlindedBlock.message.slot)
.BlindedBeaconBlock.hashTreeRoot(signedBlindedBlock.message)
Expand All @@ -258,7 +258,7 @@ export function getBeaconBlockApi({
chain.logger.debug("Reconstructing signedBlockOrContents", {slot, blockRoot, source});

const contents = executionPayload
? chain.producedContentsCache.get(toHex(executionPayload.blockHash)) ?? null
? chain.producedContentsCache.get(toRootHex(executionPayload.blockHash)) ?? null
: null;
const signedBlockOrContents = reconstructFullBlockOrContents(signedBlindedBlock, {executionPayload, contents});

Expand Down Expand Up @@ -354,7 +354,7 @@ export function getBeaconBlockApi({
}
finalized = false;

if (summary.blockRoot !== toHex(canonicalRoot)) {
if (summary.blockRoot !== toRootHex(canonicalRoot)) {
const block = await db.block.get(fromHex(summary.blockRoot));
if (block) {
result.push(toBeaconHeaderResponse(config, block));
Expand Down Expand Up @@ -473,7 +473,7 @@ export function getBeaconBlockApi({
}

if (!blobSidecars) {
throw Error(`blobSidecars not found in db for slot=${block.message.slot} root=${toHex(blockRoot)}`);
throw Error(`blobSidecars not found in db for slot=${block.message.slot} root=${toRootHex(blockRoot)}`);
}

return {
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/api/impl/lodestar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from "node:path";
import {routes} from "@lodestar/api";
import {ApplicationMethods} from "@lodestar/api/server";
import {Repository} from "@lodestar/db";
import {toHex} from "@lodestar/utils";
import {toHex, toRootHex} from "@lodestar/utils";
import {getLatestWeakSubjectivityCheckpointEpoch} from "@lodestar/state-transition";
import {ChainForkConfig} from "@lodestar/config";
import {ssz} from "@lodestar/types";
Expand Down Expand Up @@ -202,7 +202,7 @@ function regenRequestToJson(config: ChainForkConfig, regenRequest: RegenRequest)
case "getPreState": {
const slot = regenRequest.args[0].slot;
return {
root: toHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(regenRequest.args[0])),
root: toRootHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(regenRequest.args[0])),
slot,
};
}
Expand Down
20 changes: 10 additions & 10 deletions packages/beacon-node/src/api/impl/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
BlindedBeaconBlock,
} from "@lodestar/types";
import {ExecutionStatus, DataAvailabilityStatus} from "@lodestar/fork-choice";
import {fromHex, toHex, resolveOrRacePromises, prettyWeiToEth} from "@lodestar/utils";
import {fromHex, toHex, resolveOrRacePromises, prettyWeiToEth, toRootHex} from "@lodestar/utils";
import {
AttestationError,
AttestationErrorCode,
Expand Down Expand Up @@ -324,7 +324,7 @@ export function getValidatorApi(
function notOnOptimisticBlockRoot(beaconBlockRoot: Root): void {
const protoBeaconBlock = chain.forkChoice.getBlock(beaconBlockRoot);
if (!protoBeaconBlock) {
throw new ApiError(400, `Block not in forkChoice, beaconBlockRoot=${toHex(beaconBlockRoot)}`);
throw new ApiError(400, `Block not in forkChoice, beaconBlockRoot=${toRootHex(beaconBlockRoot)}`);
}

if (protoBeaconBlock.executionStatus === ExecutionStatus.Syncing)
Expand All @@ -336,7 +336,7 @@ export function getValidatorApi(
function notOnOutOfRangeData(beaconBlockRoot: Root): void {
const protoBeaconBlock = chain.forkChoice.getBlock(beaconBlockRoot);
if (!protoBeaconBlock) {
throw new ApiError(400, `Block not in forkChoice, beaconBlockRoot=${toHex(beaconBlockRoot)}`);
throw new ApiError(400, `Block not in forkChoice, beaconBlockRoot=${toRootHex(beaconBlockRoot)}`);
}

if (protoBeaconBlock.dataAvailabilityStatus === DataAvailabilityStatus.OutOfRange)
Expand Down Expand Up @@ -416,7 +416,7 @@ export function getValidatorApi(
slot,
executionPayloadValue,
consensusBlockValue,
root: toHex(config.getExecutionForkTypes(slot).BlindedBeaconBlock.hashTreeRoot(block)),
root: toRootHex(config.getExecutionForkTypes(slot).BlindedBeaconBlock.hashTreeRoot(block)),
});

if (chain.opts.persistProducedBlocks) {
Expand Down Expand Up @@ -494,13 +494,13 @@ export function getValidatorApi(
slot,
executionPayloadValue,
consensusBlockValue,
root: toHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(block)),
root: toRootHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(block)),
});
if (chain.opts.persistProducedBlocks) {
void chain.persistBlock(block, "produced_engine_block");
}
if (isForkBlobs(version)) {
const blockHash = toHex((block as bellatrix.BeaconBlock).body.executionPayload.blockHash);
const blockHash = toRootHex((block as bellatrix.BeaconBlock).body.executionPayload.blockHash);
const contents = chain.producedContentsCache.get(blockHash);
if (contents === undefined) {
throw Error("contents missing in cache");
Expand Down Expand Up @@ -869,7 +869,7 @@ export function getValidatorApi(
// and it hasn't been in our forkchoice since we haven't seen / processing that block
// see https://github.com/ChainSafe/lodestar/issues/5063
if (!chain.forkChoice.hasBlock(beaconBlockRoot)) {
const rootHex = toHex(beaconBlockRoot);
const rootHex = toRootHex(beaconBlockRoot);
network.searchUnknownSlotRoot({slot, root: rootHex});
// if result of this call is false, i.e. block hasn't seen after 1 slot then the below notOnOptimisticBlockRoot call will throw error
await chain.waitForBlock(slot, rootHex);
Expand Down Expand Up @@ -954,7 +954,7 @@ export function getValidatorApi(
return {
data: duties,
meta: {
dependentRoot: toHex(dependentRoot),
dependentRoot: toRootHex(dependentRoot),
executionOptimistic: isOptimisticBlock(head),
},
};
Expand Down Expand Up @@ -1006,7 +1006,7 @@ export function getValidatorApi(
return {
data: duties,
meta: {
dependentRoot: toHex(dependentRoot),
dependentRoot: toRootHex(dependentRoot),
executionOptimistic: isOptimisticBlock(head),
},
};
Expand Down Expand Up @@ -1071,7 +1071,7 @@ export function getValidatorApi(

await waitForSlot(slot); // Must never request for a future slot > currentSlot

const dataRootHex = toHex(attestationDataRoot);
const dataRootHex = toRootHex(attestationDataRoot);
const aggregate = chain.attestationPool.getAggregate(slot, dataRootHex);

if (!aggregate) {
Expand Down
6 changes: 3 additions & 3 deletions packages/beacon-node/src/chain/archiver/archiveBlocks.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {fromHexString} from "@chainsafe/ssz";
import {Epoch, Slot, RootHex} from "@lodestar/types";
import {IForkChoice} from "@lodestar/fork-choice";
import {Logger, toHex} from "@lodestar/utils";
import {Logger, toRootHex} from "@lodestar/utils";
import {ForkSeq, SLOTS_PER_EPOCH} from "@lodestar/params";
import {computeEpochAtSlot, computeStartSlotAtEpoch} from "@lodestar/state-transition";
import {KeyValue} from "@lodestar/db";
Expand Down Expand Up @@ -137,7 +137,7 @@ async function migrateBlocksFromHotToColdDb(db: IBeaconDb, blocks: BlockRootSlot
canonicalBlocks.map(async (block) => {
const blockBuffer = await db.block.getBinary(block.root);
if (!blockBuffer) {
throw Error(`No block found for slot ${block.slot} root ${toHex(block.root)}`);
throw Error(`No block found for slot ${block.slot} root ${toRootHex(block.root)}`);
}
return {
key: block.slot,
Expand Down Expand Up @@ -177,7 +177,7 @@ async function migrateBlobSidecarsFromHotToColdDb(
.map(async (block) => {
const bytes = await db.blobSidecars.getBinary(block.root);
if (!bytes) {
throw Error(`No blobSidecars found for slot ${block.slot} root ${toHex(block.root)}`);
throw Error(`No blobSidecars found for slot ${block.slot} root ${toRootHex(block.root)}`);
}
return {key: block.slot, value: bytes};
})
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/chain/blocks/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {toHex, isErrorAborted} from "@lodestar/utils";
import {isErrorAborted, toRootHex} from "@lodestar/utils";
import {SignedBeaconBlock} from "@lodestar/types";
import {JobItemQueue, isQueueErrorAborted} from "../../util/queue/index.js";
import {Metrics} from "../../metrics/metrics.js";
Expand Down Expand Up @@ -127,7 +127,7 @@ export async function processBlocks(
const blockSlot = signedBlock.message.slot;
const {preState, postState} = err.type;
const forkTypes = this.config.getForkTypes(blockSlot);
const invalidRoot = toHex(postState.hashTreeRoot());
const invalidRoot = toRootHex(postState.hashTreeRoot());

const suffix = `slot_${blockSlot}_invalid_state_root_${invalidRoot}`;
this.persistInvalidSszValue(forkTypes.SignedBeaconBlock, signedBlock, suffix);
Expand Down
9 changes: 4 additions & 5 deletions packages/beacon-node/src/chain/blocks/verifyBlock.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {toHexString} from "@chainsafe/ssz";
import {
CachedBeaconStateAllForks,
computeEpochAtSlot,
Expand All @@ -9,7 +8,7 @@ import {bellatrix, deneb} from "@lodestar/types";
import {ForkName} from "@lodestar/params";
import {ProtoBlock, ExecutionStatus, DataAvailabilityStatus} from "@lodestar/fork-choice";
import {ChainForkConfig} from "@lodestar/config";
import {Logger} from "@lodestar/utils";
import {Logger, toRootHex} from "@lodestar/utils";
import {BlockError, BlockErrorCode} from "../errors/index.js";
import {BlockProcessOpts} from "../options.js";
import {RegenCaller} from "../regen/index.js";
Expand Down Expand Up @@ -198,9 +197,9 @@ export async function verifyBlocksInEpoch(
}

function logOnPowBlock(logger: Logger, config: ChainForkConfig, mergeBlock: bellatrix.BeaconBlock): void {
const mergeBlockHash = toHexString(config.getForkTypes(mergeBlock.slot).BeaconBlock.hashTreeRoot(mergeBlock));
const mergeExecutionHash = toHexString(mergeBlock.body.executionPayload.blockHash);
const mergePowHash = toHexString(mergeBlock.body.executionPayload.parentHash);
const mergeBlockHash = toRootHex(config.getForkTypes(mergeBlock.slot).BeaconBlock.hashTreeRoot(mergeBlock));
const mergeExecutionHash = toRootHex(mergeBlock.body.executionPayload.blockHash);
const mergePowHash = toRootHex(mergeBlock.body.executionPayload.parentHash);
logger.info(POS_PANDA_MERGE_TRANSITION_BANNER);
logger.info("Execution transitioning from PoW to PoS!!!");
logger.info("Importing block referencing terminal PoW block", {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {toHexString} from "@chainsafe/ssz";
import {
CachedBeaconStateAllForks,
isExecutionStateType,
Expand All @@ -17,7 +16,7 @@ import {
LVHInvalidResponse,
} from "@lodestar/fork-choice";
import {ChainForkConfig} from "@lodestar/config";
import {ErrorAborted, Logger} from "@lodestar/utils";
import {ErrorAborted, Logger, toRootHex} from "@lodestar/utils";
import {ForkSeq, SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY} from "@lodestar/params";

import {IExecutionEngine} from "../../execution/engine/interface.js";
Expand Down Expand Up @@ -205,10 +204,8 @@ export async function verifyBlocksExecutionPayload(
// in import block
if (isMergeTransitionBlock) {
const mergeBlock = block.message as bellatrix.BeaconBlock;
const mergeBlockHash = toHexString(
chain.config.getForkTypes(mergeBlock.slot).BeaconBlock.hashTreeRoot(mergeBlock)
);
const powBlockRootHex = toHexString(mergeBlock.body.executionPayload.parentHash);
const mergeBlockHash = toRootHex(chain.config.getForkTypes(mergeBlock.slot).BeaconBlock.hashTreeRoot(mergeBlock));
const powBlockRootHex = toRootHex(mergeBlock.body.executionPayload.parentHash);
const powBlock = await chain.eth1.getPowBlock(powBlockRootHex).catch((error) => {
// Lets just warn the user here, errors if any will be reported on
// `assertValidTerminalPowBlock` checks
Expand Down Expand Up @@ -330,7 +327,7 @@ export async function verifyBlockExecutionPayload(
const lvhResponse = {
executionStatus,
latestValidExecHash: execResult.latestValidHash,
invalidateFromParentBlockRoot: toHexString(block.message.parentRoot),
invalidateFromParentBlockRoot: toRootHex(block.message.parentRoot),
};
const execError = new BlockError(block, {
code: BlockErrorCode.EXECUTION_ENGINE_ERROR,
Expand Down Expand Up @@ -407,7 +404,7 @@ function getSegmentErrorResponse(
for (let mayBeLVHIndex = blockIndex - 1; mayBeLVHIndex >= 0; mayBeLVHIndex--) {
const block = blocks[mayBeLVHIndex];
if (
toHexString((block.message.body as bellatrix.BeaconBlockBody).executionPayload.blockHash) ===
toRootHex((block.message.body as bellatrix.BeaconBlockBody).executionPayload.blockHash) ===
lvhResponse.latestValidExecHash
) {
lvhFound = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
import {ChainForkConfig} from "@lodestar/config";
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
import {Slot} from "@lodestar/types";
import {toHexString, toRootHex} from "@lodestar/utils";
import {toRootHex} from "@lodestar/utils";
import {IClock} from "../../util/clock.js";
import {BlockError, BlockErrorCode} from "../errors/index.js";
import {BlockInput, ImportBlockOpts} from "./types.js";
Expand Down Expand Up @@ -85,9 +85,7 @@ export function verifyBlocksSanityChecks(

// Not already known
// IGNORE if `partiallyVerifiedBlock.ignoreIfKnown`
const blockHash = toHexString(
chain.config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message)
);
const blockHash = toRootHex(chain.config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message));
if (chain.forkChoice.hasBlockHex(blockHash)) {
if (opts.ignoreIfKnown) {
continue;
Expand Down
6 changes: 3 additions & 3 deletions packages/beacon-node/src/chain/blocks/writeBlockInputToDb.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {toHex} from "@lodestar/utils";
import {toRootHex} from "@lodestar/utils";
import {BeaconChain} from "../chain.js";
import {BlockInput, BlockInputType} from "./types.js";

Expand All @@ -15,7 +15,7 @@ export async function writeBlockInputToDb(this: BeaconChain, blocksInput: BlockI
for (const blockInput of blocksInput) {
const {block, blockBytes} = blockInput;
const blockRoot = this.config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message);
const blockRootHex = toHex(blockRoot);
const blockRootHex = toRootHex(blockRoot);
if (blockBytes) {
// skip serializing data if we already have it
this.metrics?.importBlock.persistBlockWithSerializedDataCount.inc();
Expand Down Expand Up @@ -59,7 +59,7 @@ export async function removeEagerlyPersistedBlockInputs(this: BeaconChain, block
for (const blockInput of blockInputs) {
const {block, type} = blockInput;
const blockRoot = this.config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message);
const blockRootHex = toHex(blockRoot);
const blockRootHex = toRootHex(blockRoot);
if (!this.forkChoice.hasBlockHex(blockRootHex)) {
blockToRemove.push(block);

Expand Down
10 changes: 5 additions & 5 deletions packages/beacon-node/src/chain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from "@lodestar/types";
import {CheckpointWithHex, ExecutionStatus, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
import {ProcessShutdownCallback} from "@lodestar/validator";
import {Logger, gweiToWei, isErrorAborted, pruneSetToMax, sleep, toHex, toRootHex} from "@lodestar/utils";
import {Logger, gweiToWei, isErrorAborted, pruneSetToMax, sleep, toRootHex} from "@lodestar/utils";
import {ForkSeq, GENESIS_SLOT, SLOTS_PER_EPOCH} from "@lodestar/params";

import {GENESIS_EPOCH, ZERO_HASH} from "../constants/index.js";
Expand Down Expand Up @@ -691,7 +691,7 @@ export class BeaconChain implements IBeaconChain {
blockType === BlockType.Full
? this.config.getForkTypes(slot).BeaconBlock.hashTreeRoot(block)
: this.config.getExecutionForkTypes(slot).BlindedBeaconBlock.hashTreeRoot(block as BlindedBeaconBlock);
const blockRootHex = toHex(blockRoot);
const blockRootHex = toRootHex(blockRoot);

// track the produced block for consensus broadcast validations
if (blockType === BlockType.Full) {
Expand Down Expand Up @@ -729,7 +729,7 @@ export class BeaconChain implements IBeaconChain {
* )
*/
getContents(beaconBlock: deneb.BeaconBlock): deneb.Contents {
const blockHash = toHex(beaconBlock.body.executionPayload.blockHash);
const blockHash = toRootHex(beaconBlock.body.executionPayload.blockHash);
const contents = this.producedContentsCache.get(blockHash);
if (!contents) {
throw Error(`No contents for executionPayload.blockHash ${blockHash}`);
Expand Down Expand Up @@ -926,7 +926,7 @@ export class BeaconChain implements IBeaconChain {
checkpointRoot: checkpoint.rootHex,
stateId,
stateSlot: state.slot,
stateRoot: toHex(state.hashTreeRoot()),
stateRoot: toRootHex(state.hashTreeRoot()),
});
}

Expand Down Expand Up @@ -997,7 +997,7 @@ export class BeaconChain implements IBeaconChain {

// by default store to lodestar_archive of current dir
const dirpath = path.join(this.opts.persistInvalidSszObjectsDir ?? "invalid_ssz_objects", dateStr);
const filepath = path.join(dirpath, `${typeName}_${toHex(root)}.ssz`);
const filepath = path.join(dirpath, `${typeName}_${toRootHex(root)}.ssz`);

await ensureDir(dirpath);

Expand Down
3 changes: 1 addition & 2 deletions packages/beacon-node/src/chain/forkChoice/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {toHexString} from "@chainsafe/ssz";
import {Slot} from "@lodestar/types";
import {ChainForkConfig} from "@lodestar/config";
import {
Expand Down Expand Up @@ -91,7 +90,7 @@ export function initializeForkChoice(

...(isExecutionStateType(state) && isMergeTransitionComplete(state)
? {
executionPayloadBlockHash: toHexString(state.latestExecutionPayloadHeader.blockHash),
executionPayloadBlockHash: toRootHex(state.latestExecutionPayloadHeader.blockHash),
executionPayloadNumber: state.latestExecutionPayloadHeader.blockNumber,
executionStatus: blockHeader.slot === GENESIS_SLOT ? ExecutionStatus.Valid : ExecutionStatus.Syncing,
}
Expand Down
Loading

0 comments on commit 20c18ad

Please sign in to comment.