Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use single state tree at startup #7027

Closed
twoeths opened this issue Aug 15, 2024 · 2 comments · Fixed by #7056
Closed

Use single state tree at startup #7027

twoeths opened this issue Aug 15, 2024 · 2 comments · Fixed by #7056
Assignees
Labels
meta-feature-request Issues to track feature requests.

Comments

@twoeths
Copy link
Contributor

twoeths commented Aug 15, 2024

Problem description

Right now if user provides a checkpointState or checkpointSyncUrl we'll deserialize states to 2 separate trees: one with the last state stored in db and the other one downloaded from checkpointState or checkpointSyncUrl. This takes a lot of memory and time of the node unnecessarily

Solution description

Once we load state with the last db value, use loadState() util to load the other state from bytes. This ensures we use same state tree across application

Additional context

this will also gives us more confident on bringing n-historical state flags to production because we use loadState() api at every startup

@twoeths twoeths added the meta-feature-request Issues to track feature requests. label Aug 15, 2024
@twoeths
Copy link
Contributor Author

twoeths commented Aug 26, 2024

tested with finalized state slot 1885504 of holesky

const chainForkConfig = createChainForkConfig(holeskyChainConfig);

const now = Date.now();
const wsState = getStateTypeFromBytes(chainForkConfig, stateBytes).deserializeToViewDU(stateBytes);
console.log("@@@ loaded state", wsState.slot, Date.now() - now, "ms");
const root = wsState.hashTreeRoot();
console.log("@@@ state root", toRootHex(root), Date.now() - now, "ms");

this gives

@@@ loaded state 1885504 2201 ms
@@@ state root 0x72e5a7e32dceb275f4268b28180d95fa40e3767c31040f7471f3a402de8edbfa 45998 ms

the initial full hashTreeRoot() time is almost 44s, if we use the db state to load downloaded ws state, it would save us at least 40s due to a lot of nodes are now shared between 2 merkle trees

note that initially we always have to compute state root

anchorCheckpoint = getCheckpointFromState(store);

export function getCheckpointFromState(state: BeaconStateAllForks): Checkpoint {
  return {
    // the correct checkpoint is based on state's slot, its latestBlockHeader's slot's epoch can be
    // behind the state
    epoch: computeCheckpointEpochAtStateSlot(state.slot),
    root: getLatestBlockRoot(state),
  };
}

export function getLatestBlockRoot(state: BeaconStateAllForks): Root {
  const header = ssz.phase0.BeaconBlockHeader.clone(state.latestBlockHeader);
  if (ssz.Root.equals(header.stateRoot, ZERO_HASH)) {
    header.stateRoot = state.hashTreeRoot();
  }
  return ssz.phase0.BeaconBlockHeader.hashTreeRoot(header);
}

@twoeths
Copy link
Contributor Author

twoeths commented Aug 27, 2024

Aug-26 06:40:22.054[]                 ^[[32minfo^[[39m: Lodestar network=holesky, version=v1.21.0/te/shared_buffer_sync_pubkeys_2/93e2c66, commit=93e2c66c4d93b5a145bcaf183a0f28982508046b
Aug-26 06:40:22.199[]                 ^[[32minfo^[[39m: Connected to LevelDB database path=/home/devops/beacon/chain-db
Aug-26 06:40:46.360[]                 ^[[33mwarn^[[39m: Forced syncing from checkpoint even though db state is within weak subjectivity period
Aug-26 06:40:46.361[]                 ^[[33mwarn^[[39m: Please consider removing --forceCheckpointSync flag unless absolutely necessary
Aug-26 06:40:46.361[]                 ^[[32minfo^[[39m: Fetching checkpoint state checkpointSyncUrl=https://beaconstate-holesky.chainsafe.io
Aug-26 06:40:51.258[]                 ^[[32minfo^[[39m: Download completed stateId=finalized
Aug-26 06:41:15.124[]                 ^[[32minfo^[[39m: Initializing beacon from a valid checkpoint state slot=2395936, epoch=74873, stateRoot=0x0e528419032ef08a1f740ecb3ffb6e62949610dc95242f64d097c8769be816b8, isWithinWeakSubjectivityPeriod=true
Aug-26 06:41:17.650[chain]            ^[[32minfo^[[39m: Historical state worker started
Aug-26 06:41:17.661[eth1]             ^[[32minfo^[[39m: Eth1 provider urls=http://127.0.0.1:8545
Aug-26 06:41:17.664[execution]        ^[[32minfo^[[39m: Execution client urls=http://127.0.0.1:8551
Aug-26 06:41:48.002[chain]         ^[[36mverbose^[[39m: Clock slot slot=2396009

on a common node, when start up we block for 3 times:

  • hashTreeRoot() db state, ~24s
  • hashTreeRoot() downloaded state, ~24s
  • populate pubkey cache, ~30s

the goal is to get rid of the 2nd blocking time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
meta-feature-request Issues to track feature requests.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant