import {expect} from "chai"; import {ForkName, ForkSeq} from "@lodestar/params"; import {IBeaconConfig, IForkInfo} from "@lodestar/config"; import {getCurrentAndNextFork, getActiveForks} from "../../../src/network/forks.js"; function getForkConfig({ phase0, altair, bellatrix, capella, eip4844, }: { phase0: number; altair: number; bellatrix: number; capella: number; eip4844: number; }): IBeaconConfig { const forks: Record = { phase0: { name: ForkName.phase0, seq: ForkSeq.phase0, epoch: phase0, version: Buffer.from([0, 0, 0, 0]), prevVersion: Buffer.from([0, 0, 0, 0]), prevForkName: ForkName.phase0, }, altair: { name: ForkName.altair, seq: ForkSeq.altair, epoch: altair, version: Buffer.from([0, 0, 0, 1]), prevVersion: Buffer.from([0, 0, 0, 0]), prevForkName: ForkName.phase0, }, bellatrix: { name: ForkName.bellatrix, seq: ForkSeq.bellatrix, epoch: bellatrix, version: Buffer.from([0, 0, 0, 2]), prevVersion: Buffer.from([0, 0, 0, 1]), prevForkName: ForkName.altair, }, capella: { name: ForkName.capella, seq: ForkSeq.capella, epoch: capella, version: Buffer.from([0, 0, 0, 3]), prevVersion: Buffer.from([0, 0, 0, 2]), prevForkName: ForkName.bellatrix, }, eip4844: { name: ForkName.eip4844, seq: ForkSeq.eip4844, epoch: eip4844, version: Buffer.from([0, 0, 0, 4]), prevVersion: Buffer.from([0, 0, 0, 3]), prevForkName: ForkName.capella, }, }; const forksAscendingEpochOrder = Object.values(forks); const forksDescendingEpochOrder = Object.values(forks).reverse(); return {forks, forksAscendingEpochOrder, forksDescendingEpochOrder} as IBeaconConfig; } const testScenarios = [ { phase0: 0, altair: 0, bellatrix: Infinity, capella: Infinity, testCases: [ {epoch: -1, currentFork: "altair", nextFork: undefined, activeForks: ["altair"]}, {epoch: 0, currentFork: "altair", nextFork: undefined, activeForks: ["altair"]}, {epoch: 1, currentFork: "altair", nextFork: undefined, activeForks: ["altair"]}, ], }, { phase0: 0, altair: 0, bellatrix: 0, capella: Infinity, testCases: [ {epoch: -1, currentFork: "bellatrix", nextFork: undefined, activeForks: ["bellatrix"]}, {epoch: 0, currentFork: "bellatrix", nextFork: undefined, activeForks: ["bellatrix"]}, {epoch: 1, currentFork: "bellatrix", nextFork: undefined, activeForks: ["bellatrix"]}, ], }, { phase0: 0, altair: 1, bellatrix: 1, capella: Infinity, testCases: [ {epoch: -1, currentFork: "phase0", nextFork: "bellatrix", activeForks: ["phase0", "bellatrix"]}, {epoch: 2, currentFork: "bellatrix", nextFork: undefined, activeForks: ["phase0", "bellatrix"]}, {epoch: 3, currentFork: "bellatrix", nextFork: undefined, activeForks: ["phase0", "bellatrix"]}, {epoch: 4, currentFork: "bellatrix", nextFork: undefined, activeForks: ["bellatrix"]}, ], }, { phase0: 0, altair: 1, bellatrix: 2, capella: Infinity, testCases: [ {epoch: -1, currentFork: "phase0", nextFork: "altair", activeForks: ["phase0", "altair"]}, {epoch: 0, currentFork: "phase0", nextFork: "altair", activeForks: ["phase0", "altair", "bellatrix"]}, {epoch: 1, currentFork: "altair", nextFork: "bellatrix", activeForks: ["phase0", "altair", "bellatrix"]}, {epoch: 2, currentFork: "bellatrix", nextFork: undefined, activeForks: ["phase0", "altair", "bellatrix"]}, {epoch: 3, currentFork: "bellatrix", nextFork: undefined, activeForks: ["phase0", "altair", "bellatrix"]}, {epoch: 4, currentFork: "bellatrix", nextFork: undefined, activeForks: ["altair", "bellatrix"]}, {epoch: 5, currentFork: "bellatrix", nextFork: undefined, activeForks: ["bellatrix"]}, ], }, { phase0: 0, altair: 5, bellatrix: 10, capella: Infinity, testCases: [ {epoch: -1, currentFork: "phase0", nextFork: "altair", activeForks: ["phase0"]}, {epoch: 3, currentFork: "phase0", nextFork: "altair", activeForks: ["phase0", "altair"]}, {epoch: 7, currentFork: "altair", nextFork: "bellatrix", activeForks: ["phase0", "altair"]}, {epoch: 8, currentFork: "altair", nextFork: "bellatrix", activeForks: ["altair", "bellatrix"]}, {epoch: 11, currentFork: "bellatrix", nextFork: undefined, activeForks: ["altair", "bellatrix"]}, {epoch: 12, currentFork: "bellatrix", nextFork: undefined, activeForks: ["altair", "bellatrix"]}, {epoch: 13, currentFork: "bellatrix", nextFork: undefined, activeForks: ["bellatrix"]}, ], }, ]; for (const testScenario of testScenarios) { const {phase0, altair, bellatrix, capella, testCases} = testScenario; // TODO EIP-4844: Is it necessary to test? const eip4844 = Infinity; describe(`network / fork: phase0: ${phase0}, altair: ${altair}, bellatrix: ${bellatrix} capella: ${capella}`, () => { const forkConfig = getForkConfig({phase0, altair, bellatrix, capella, eip4844}); const forks = forkConfig.forks; for (const testCase of testCases) { const {epoch, currentFork, nextFork, activeForks} = testCase; it(` on epoch ${epoch} should return ${JSON.stringify({ currentFork, nextFork, })}, getActiveForks: ${activeForks}`, () => { expect(getCurrentAndNextFork(forkConfig, epoch)).to.deep.equal({ currentFork: forks[currentFork as ForkName], nextFork: (nextFork && forks[nextFork as ForkName]) ?? undefined, }); expect(getActiveForks(forkConfig, epoch)).to.deep.equal(activeForks); }); } }); }