From ef78c58f05b9a3047d48a4a2fcc7464918ffc9e2 Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Fri, 2 Aug 2024 09:12:01 +0700 Subject: [PATCH 1/3] chore: more log on updateHeadState() --- packages/beacon-node/src/chain/blocks/importBlock.ts | 2 +- packages/beacon-node/src/chain/regen/interface.ts | 2 +- packages/beacon-node/src/chain/regen/queued.ts | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index 906be51434c2..e402f14e1da1 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -241,7 +241,7 @@ export async function importBlock( if (newHead.blockRoot !== oldHead.blockRoot) { // Set head state as strong reference - this.regen.updateHeadState(newHead.stateRoot, postState); + this.regen.updateHeadState(newHead, postState); this.emitter.emit(routes.events.EventType.head, { block: newHead.blockRoot, diff --git a/packages/beacon-node/src/chain/regen/interface.ts b/packages/beacon-node/src/chain/regen/interface.ts index 341625c9ff1d..031d19860789 100644 --- a/packages/beacon-node/src/chain/regen/interface.ts +++ b/packages/beacon-node/src/chain/regen/interface.ts @@ -44,7 +44,7 @@ export interface IStateRegenerator extends IStateRegeneratorInternal { pruneOnFinalized(finalizedEpoch: Epoch): void; processState(blockRootHex: RootHex, postState: CachedBeaconStateAllForks): void; addCheckpointState(cp: phase0.Checkpoint, item: CachedBeaconStateAllForks): void; - updateHeadState(newHeadStateRoot: RootHex, maybeHeadState: CachedBeaconStateAllForks): void; + updateHeadState(newHead: ProtoBlock, maybeHeadState: CachedBeaconStateAllForks): void; updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null; } diff --git a/packages/beacon-node/src/chain/regen/queued.ts b/packages/beacon-node/src/chain/regen/queued.ts index 358a37e6e638..89f1c50b6b48 100644 --- a/packages/beacon-node/src/chain/regen/queued.ts +++ b/packages/beacon-node/src/chain/regen/queued.ts @@ -165,9 +165,11 @@ export class QueuedStateRegenerator implements IStateRegenerator { this.checkpointStateCache.add(cp, item); } - updateHeadState(newHeadStateRoot: RootHex, maybeHeadState: CachedBeaconStateAllForks): void { + updateHeadState(newHead: ProtoBlock, maybeHeadState: CachedBeaconStateAllForks): void { // the resulting state will be added to block state cache so we transfer the cache in this flow const cloneOpts = {dontTransferCache: true}; + const {stateRoot: newHeadStateRoot, blockRoot: newHeadBlockRoot, slot: newHeadSlot} = newHead; + const logCtx = {newHeadSlot, newHeadBlockRoot, newHeadStateRoot, maybeHeadSlot: maybeHeadState.slot}; const headState = newHeadStateRoot === toHexString(maybeHeadState.hashTreeRoot()) ? maybeHeadState @@ -177,7 +179,7 @@ export class QueuedStateRegenerator implements IStateRegenerator { this.blockStateCache.setHeadState(headState); } else { // Trigger regen on head change if necessary - this.logger.warn("Head state not available, triggering regen", {stateRoot: newHeadStateRoot}); + this.logger.warn("Head state not available, triggering regen", logCtx); // it's important to reload state to regen head state here const allowDiskReload = true; // head has changed, so the existing cached head state is no longer useful. Set strong reference to null to free @@ -186,7 +188,7 @@ export class QueuedStateRegenerator implements IStateRegenerator { this.blockStateCache.setHeadState(null); this.regen.getState(newHeadStateRoot, RegenCaller.processBlock, cloneOpts, allowDiskReload).then( (headStateRegen) => this.blockStateCache.setHeadState(headStateRegen), - (e) => this.logger.error("Error on head state regen", {}, e) + (e) => this.logger.error("Error on head state regen", logCtx, e) ); } } From e84d7f3bedc96a024aacde21037ada8a88599190 Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Fri, 2 Aug 2024 09:51:41 +0700 Subject: [PATCH 2/3] chore: also log maybeHeadStateRoot --- packages/beacon-node/src/chain/regen/queued.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/beacon-node/src/chain/regen/queued.ts b/packages/beacon-node/src/chain/regen/queued.ts index 89f1c50b6b48..702775da726f 100644 --- a/packages/beacon-node/src/chain/regen/queued.ts +++ b/packages/beacon-node/src/chain/regen/queued.ts @@ -169,11 +169,16 @@ export class QueuedStateRegenerator implements IStateRegenerator { // the resulting state will be added to block state cache so we transfer the cache in this flow const cloneOpts = {dontTransferCache: true}; const {stateRoot: newHeadStateRoot, blockRoot: newHeadBlockRoot, slot: newHeadSlot} = newHead; - const logCtx = {newHeadSlot, newHeadBlockRoot, newHeadStateRoot, maybeHeadSlot: maybeHeadState.slot}; + const maybeHeadStateRoot = toHexString(maybeHeadState.hashTreeRoot()); + const logCtx = { + newHeadSlot, + newHeadBlockRoot, + newHeadStateRoot, + maybeHeadSlot: maybeHeadState.slot, + maybeHeadStateRoot, + }; const headState = - newHeadStateRoot === toHexString(maybeHeadState.hashTreeRoot()) - ? maybeHeadState - : this.blockStateCache.get(newHeadStateRoot, cloneOpts); + newHeadStateRoot === maybeHeadStateRoot ? maybeHeadState : this.blockStateCache.get(newHeadStateRoot, cloneOpts); if (headState) { this.blockStateCache.setHeadState(headState); From 21875365448548ace65c8ee9fb59f2e9c41c0238 Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Fri, 2 Aug 2024 10:27:33 +0700 Subject: [PATCH 3/3] fix: dontTransferCache option when regen head state --- .../beacon-node/src/chain/regen/queued.ts | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/beacon-node/src/chain/regen/queued.ts b/packages/beacon-node/src/chain/regen/queued.ts index 702775da726f..ad673b334bd1 100644 --- a/packages/beacon-node/src/chain/regen/queued.ts +++ b/packages/beacon-node/src/chain/regen/queued.ts @@ -166,8 +166,6 @@ export class QueuedStateRegenerator implements IStateRegenerator { } updateHeadState(newHead: ProtoBlock, maybeHeadState: CachedBeaconStateAllForks): void { - // the resulting state will be added to block state cache so we transfer the cache in this flow - const cloneOpts = {dontTransferCache: true}; const {stateRoot: newHeadStateRoot, blockRoot: newHeadBlockRoot, slot: newHeadSlot} = newHead; const maybeHeadStateRoot = toHexString(maybeHeadState.hashTreeRoot()); const logCtx = { @@ -178,19 +176,26 @@ export class QueuedStateRegenerator implements IStateRegenerator { maybeHeadStateRoot, }; const headState = - newHeadStateRoot === maybeHeadStateRoot ? maybeHeadState : this.blockStateCache.get(newHeadStateRoot, cloneOpts); + newHeadStateRoot === maybeHeadStateRoot + ? maybeHeadState + : // maybeHeadState was already in block state cache so we don't transfer the cache + this.blockStateCache.get(newHeadStateRoot, {dontTransferCache: true}); if (headState) { this.blockStateCache.setHeadState(headState); } else { // Trigger regen on head change if necessary this.logger.warn("Head state not available, triggering regen", logCtx); - // it's important to reload state to regen head state here - const allowDiskReload = true; - // head has changed, so the existing cached head state is no longer useful. Set strong reference to null to free - // up memory for regen step below. During regen, node won't be functional but eventually head will be available - // for legacy StateContextCache only + // for the old BlockStateCacheImpl only + // - head has changed, so the existing cached head state is no longer useful. Set strong reference to null to free + // up memory for regen step below. During regen, node won't be functional but eventually head will be available + // for the new FIFOBlockStateCache, this has no affect this.blockStateCache.setHeadState(null); + + // for the new FIFOBlockStateCache, it's important to reload state to regen head state here if needed + const allowDiskReload = true; + // transfer cache here because we want to regen state asap + const cloneOpts = {dontTransferCache: false}; this.regen.getState(newHeadStateRoot, RegenCaller.processBlock, cloneOpts, allowDiskReload).then( (headStateRegen) => this.blockStateCache.setHeadState(headStateRegen), (e) => this.logger.error("Error on head state regen", logCtx, e)