@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
67 lines (58 loc) • 2.28 kB
text/typescript
import {sortBy} from "../../../util/sortBy.js";
import {MIN_FINALIZED_CHAIN_VALIDATED_EPOCHS, PARALLEL_HEAD_CHAINS} from "../../constants.js";
import {RangeSyncType} from "../../utils/remoteSyncType.js";
import {SyncChain} from "../chain.js";
/**
* Priotize existing chains based on their target and peer count
* Returns an array of chains toStart and toStop to comply with the priotization
*/
export function updateChains(chains: SyncChain[]): {toStart: SyncChain[]; toStop: SyncChain[]} {
const finalizedChains: SyncChain[] = [];
const headChains: SyncChain[] = [];
for (const chain of chains) {
if (chain.syncType === RangeSyncType.Finalized) {
finalizedChains.push(chain);
} else {
headChains.push(chain);
}
}
const toStart: SyncChain[] = [];
const toStop: SyncChain[] = [];
if (finalizedChains.length > 0) {
// Pick first only
const [newSyncChain] = prioritizeSyncChains(finalizedChains);
// TODO: Should it stop all HEAD chains if going from a head sync to a finalized sync?
const currentSyncChain = finalizedChains.find((syncChain) => syncChain.isSyncing);
// Only switch from currentSyncChain to newSyncChain if necessary
// Avoid unnecesary switchings and try to advance it
if (
!currentSyncChain ||
(newSyncChain !== currentSyncChain &&
newSyncChain.peers > currentSyncChain.peers &&
currentSyncChain.validatedEpochs > MIN_FINALIZED_CHAIN_VALIDATED_EPOCHS)
) {
toStart.push(newSyncChain);
if (currentSyncChain) toStop.push(currentSyncChain);
}
} else {
for (const syncChain of prioritizeSyncChains(headChains)) {
if (toStart.length < PARALLEL_HEAD_CHAINS) {
toStart.push(syncChain);
} else {
toStop.push(syncChain);
}
}
}
return {toStart, toStop};
}
/**
* Order `syncChains` by most peers and already syncing first
* If two chains have the same number of peers, prefer the already syncing to not drop progress
*/
function prioritizeSyncChains(syncChains: SyncChain[]): SyncChain[] {
return sortBy(
syncChains,
(syncChain) => -syncChain.peers, // Sort from high peer count to low: negative to reverse
(syncChain) => (syncChain.isSyncing ? 0 : 1) // Sort by isSyncing first = 0
);
}