mirror of
https://github.com/ChainSafe/lodestar.git
synced 2026-01-08 23:28:10 -05:00
**Motivation** Use latest `module` and `moduleResolution` for TS. **Description** - To use [subpath imports](https://nodejs.org/api/packages.html#subpath-imports) in the PR #8320 we need to update the module solution strategy for TS. - That requires to change the `module` for the TS as well. - Earlier tried to stay with `node18` or `node20`, but the `ts-node` does not work with that. - Maintaining different tsconfig for ts-node is more of hassle on wrong run. - So decided to stick with `nodenext` strategy for `moduleResolution` **Steps to test or reproduce** Run all tests --------- Co-authored-by: Cayman <caymannava@gmail.com>
148 lines
4.9 KiB
TypeScript
148 lines
4.9 KiB
TypeScript
import {fromHexString} from "@chainsafe/ssz";
|
|
import {routes} from "@lodestar/api";
|
|
import {ChainConfig} from "@lodestar/config";
|
|
import {TimestampFormatCode} from "@lodestar/logger";
|
|
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
import {phase0} from "@lodestar/types";
|
|
import {afterEach, describe, expect, it, vi} from "vitest";
|
|
import {ChainEvent} from "../../../src/chain/index.js";
|
|
import {waitForEvent} from "../../utils/events/resolver.js";
|
|
import {LogLevel, TestLoggerOpts, testLogger} from "../../utils/logger.js";
|
|
import {connect, onPeerConnect} from "../../utils/network.js";
|
|
import {getDevBeaconNode} from "../../utils/node/beacon.js";
|
|
import {getAndInitDevValidators} from "../../utils/node/validator.js";
|
|
|
|
describe("sync / finalized sync for fulu", () => {
|
|
// chain is finalized at slot 32, plus 4 slots for genesis delay => ~72s it should sync pretty fast
|
|
vi.setConfig({testTimeout: 90_000});
|
|
|
|
const validatorCount = 8;
|
|
const ELECTRA_FORK_EPOCH = 0;
|
|
const FULU_FORK_EPOCH = 1;
|
|
const SECONDS_PER_SLOT = 2;
|
|
const testParams: Partial<ChainConfig> = {
|
|
SECONDS_PER_SLOT,
|
|
ALTAIR_FORK_EPOCH: ELECTRA_FORK_EPOCH,
|
|
BELLATRIX_FORK_EPOCH: ELECTRA_FORK_EPOCH,
|
|
CAPELLA_FORK_EPOCH: ELECTRA_FORK_EPOCH,
|
|
DENEB_FORK_EPOCH: ELECTRA_FORK_EPOCH,
|
|
ELECTRA_FORK_EPOCH: ELECTRA_FORK_EPOCH,
|
|
FULU_FORK_EPOCH: FULU_FORK_EPOCH,
|
|
BLOB_SCHEDULE: [
|
|
{
|
|
EPOCH: 1,
|
|
MAX_BLOBS_PER_BLOCK: 3,
|
|
},
|
|
],
|
|
};
|
|
|
|
const afterEachCallbacks: (() => Promise<unknown> | void)[] = [];
|
|
afterEach(async () => {
|
|
while (afterEachCallbacks.length > 0) {
|
|
const callback = afterEachCallbacks.pop();
|
|
if (callback) await callback();
|
|
}
|
|
});
|
|
|
|
it("should do a finalized sync from another BN", async () => {
|
|
// single node at beginning, use main thread to verify bls
|
|
const genesisSlotsDelay = 4;
|
|
const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * SECONDS_PER_SLOT;
|
|
|
|
const testLoggerOpts: TestLoggerOpts = {
|
|
level: LogLevel.info,
|
|
timestampFormat: {
|
|
format: TimestampFormatCode.EpochSlot,
|
|
genesisTime,
|
|
slotsPerEpoch: SLOTS_PER_EPOCH,
|
|
secondsPerSlot: SECONDS_PER_SLOT,
|
|
},
|
|
};
|
|
|
|
const loggerNodeA = testLogger("FinalizedSync-Node-A", testLoggerOpts);
|
|
const loggerNodeB = testLogger("FinalizedSync-Node-B", testLoggerOpts);
|
|
|
|
const bn = await getDevBeaconNode({
|
|
params: testParams,
|
|
options: {
|
|
sync: {isSingleNode: true},
|
|
network: {allowPublishToZeroPeers: true, useWorker: false},
|
|
chain: {blsVerifyAllMainThread: true},
|
|
},
|
|
validatorCount,
|
|
genesisTime,
|
|
logger: loggerNodeA,
|
|
});
|
|
|
|
afterEachCallbacks.push(() => bn.close());
|
|
|
|
const {validators} = await getAndInitDevValidators({
|
|
node: bn,
|
|
logPrefix: "FinalizedSyncVc",
|
|
validatorsPerClient: validatorCount,
|
|
validatorClientCount: 1,
|
|
startIndex: 0,
|
|
useRestApi: false,
|
|
testLoggerOpts,
|
|
});
|
|
|
|
afterEachCallbacks.push(() => Promise.all(validators.map((validator) => validator.close())));
|
|
|
|
// stop beacon node after validators
|
|
afterEachCallbacks.push(() => bn.close());
|
|
|
|
await Promise.all([
|
|
waitForEvent<phase0.Checkpoint>(
|
|
bn.chain.emitter,
|
|
ChainEvent.forkChoiceFinalized,
|
|
240000,
|
|
(finalized) => finalized.epoch >= FULU_FORK_EPOCH
|
|
),
|
|
waitForEvent<routes.events.EventData[routes.events.EventType.head]>(
|
|
bn.chain.emitter,
|
|
routes.events.EventType.head,
|
|
100000,
|
|
// at block slot 32 imported, finalized checkpoint epoch 2 is processed
|
|
({slot}) => slot === 32
|
|
),
|
|
]);
|
|
loggerNodeA.info("Node A emitted finalized checkpoint event for fulu");
|
|
|
|
const bn2 = await getDevBeaconNode({
|
|
params: testParams,
|
|
options: {
|
|
api: {rest: {enabled: false}},
|
|
network: {useWorker: false},
|
|
chain: {blsVerifyAllMainThread: true},
|
|
},
|
|
validatorCount,
|
|
genesisTime,
|
|
logger: loggerNodeB,
|
|
});
|
|
loggerNodeA.info("Node B created");
|
|
|
|
afterEachCallbacks.push(() => bn2.close());
|
|
afterEachCallbacks.push(() => bn2.close());
|
|
|
|
const headSummary = bn.chain.forkChoice.getHead();
|
|
const head = await bn.db.block.get(fromHexString(headSummary.blockRoot));
|
|
if (!head) throw Error("First beacon node has no head block");
|
|
const waitForSynced = waitForEvent<routes.events.EventData[routes.events.EventType.head]>(
|
|
bn2.chain.emitter,
|
|
routes.events.EventType.head,
|
|
100000,
|
|
({block}) => block === headSummary.blockRoot
|
|
);
|
|
|
|
await Promise.all([connect(bn2.network, bn.network), onPeerConnect(bn2.network), onPeerConnect(bn.network)]);
|
|
loggerNodeA.info("Node A connected to Node B");
|
|
|
|
try {
|
|
await waitForSynced;
|
|
loggerNodeB.info("Node B synced to Node A, received fulu head block", {slot: head.message.slot});
|
|
} catch (_e) {
|
|
expect.fail("Failed to sync to other node in time");
|
|
}
|
|
});
|
|
});
|