feat: placeholder PR for electra

add types stub and epoch config

fix types
This commit is contained in:
harkamal
2024-01-24 17:38:11 +05:30
parent 5d2e1a7228
commit d87e637291
19 changed files with 323 additions and 6 deletions

View File

@@ -36,7 +36,7 @@ export enum GossipedInputType {
type BlobsCacheMap = Map<number, {blobSidecar: deneb.BlobSidecar; blobBytes: Uint8Array | null}>;
type ForkBlobsInfo = {fork: ForkName.deneb};
type ForkBlobsInfo = {fork: ForkName.deneb | ForkName.electra};
type BlobsData = {blobs: deneb.BlobSidecars; blobsBytes: (Uint8Array | null)[]; blobsSource: BlobsSource};
export type BlockInputDataBlobs = ForkBlobsInfo & BlobsData;
export type BlockInputData = BlockInputDataBlobs;

View File

@@ -35,6 +35,8 @@ const fork: TestRunnerFn<ForkStateCase, BeaconStateAllForks> = (forkNext) => {
return slotFns.upgradeStateToCapella(preState as CachedBeaconStateBellatrix);
case ForkName.deneb:
return slotFns.upgradeStateToDeneb(preState as CachedBeaconStateCapella);
case ForkName.electra:
throw Error("not Implemented");
}
},
options: {

View File

@@ -102,6 +102,14 @@ function getTransitionConfig(fork: ForkName, forkEpoch: number): Partial<ChainCo
return {ALTAIR_FORK_EPOCH: 0, BELLATRIX_FORK_EPOCH: 0, CAPELLA_FORK_EPOCH: forkEpoch};
case ForkName.deneb:
return {ALTAIR_FORK_EPOCH: 0, BELLATRIX_FORK_EPOCH: 0, CAPELLA_FORK_EPOCH: 0, DENEB_FORK_EPOCH: forkEpoch};
case ForkName.electra:
return {
ALTAIR_FORK_EPOCH: 0,
BELLATRIX_FORK_EPOCH: 0,
CAPELLA_FORK_EPOCH: 0,
DENEB_FORK_EPOCH: 0,
ELECTRA_FORK_EPOCH: forkEpoch,
};
}
}

View File

@@ -15,6 +15,7 @@ describe("UpgradeLightClientHeader", function () {
BELLATRIX_FORK_EPOCH: 2,
CAPELLA_FORK_EPOCH: 3,
DENEB_FORK_EPOCH: 4,
ELECTRA_FORK_EPOCH: Infinity,
});
const genesisValidatorsRoot = Buffer.alloc(32, 0xaa);
@@ -27,6 +28,7 @@ describe("UpgradeLightClientHeader", function () {
capella: ssz.capella.LightClientHeader.defaultValue(),
bellatrix: ssz.altair.LightClientHeader.defaultValue(),
deneb: ssz.deneb.LightClientHeader.defaultValue(),
electra: ssz.electra.LightClientHeader.defaultValue(),
};
testSlots = {
@@ -35,11 +37,18 @@ describe("UpgradeLightClientHeader", function () {
bellatrix: 17,
capella: 25,
deneb: 33,
electra: 0,
};
});
for (let i = ForkSeq.altair; i < Object.values(ForkName).length; i++) {
for (let j = i + 1; j < Object.values(ForkName).length; j++) {
// Since electra is not implemented for loop is till deneb (Object.values(ForkName).length-1)
// Once electra is implemnted run for loop till Object.values(ForkName).length
// for (let i = ForkSeq.altair; i < Object.values(ForkName).length; i++) {
// for (let j = i + 1; j < Object.values(ForkName).length; j++) {
for (let i = ForkSeq.altair; i < Object.values(ForkName).length - 1; i++) {
for (let j = i + 1; j < Object.values(ForkName).length - 1; j++) {
const fromFork = ForkName[ForkSeq[i] as ForkName];
const toFork = ForkName[ForkSeq[j] as ForkName];
@@ -53,7 +62,27 @@ describe("UpgradeLightClientHeader", function () {
}
}
// for electra not implemented
for (let i = ForkSeq.altair; i < Object.values(ForkName).length; i++) {
const fromFork = ForkName[ForkSeq[i] as ForkName];
const toFork = ForkName["electra"];
it(`Throw error ${fromFork}=>${toFork}`, function () {
lcHeaderByFork[fromFork].beacon.slot = testSlots[fromFork];
lcHeaderByFork[toFork].beacon.slot = testSlots[fromFork];
expect(() => {
upgradeLightClientHeader(config, toFork, lcHeaderByFork[fromFork]);
}).toThrow("Not Implemented");
});
}
// Since electra is not implemented for loop is till deneb (Object.values(ForkName).length-1)
// Once electra is implemnted run for loop till Object.values(ForkName).length
// for (let i = ForkSeq.altair; i < Object.values(ForkName).length; i++) {
for (let i = ForkSeq.altair; i < Object.values(ForkName).length - 1; i++) {
for (let j = i; j > 0; j--) {
const fromFork = ForkName[ForkSeq[i] as ForkName];
const toFork = ForkName[ForkSeq[j] as ForkName];

View File

@@ -9,12 +9,14 @@ function getForkConfig({
bellatrix,
capella,
deneb,
electra,
}: {
phase0: number;
altair: number;
bellatrix: number;
capella: number;
deneb: number;
electra: number;
}): BeaconConfig {
const forks: Record<ForkName, ForkInfo> = {
phase0: {
@@ -57,6 +59,14 @@ function getForkConfig({
prevVersion: Buffer.from([0, 0, 0, 3]),
prevForkName: ForkName.capella,
},
electra: {
name: ForkName.electra,
seq: ForkSeq.electra,
epoch: electra,
version: Buffer.from([0, 0, 0, 5]),
prevVersion: Buffer.from([0, 0, 0, 4]),
prevForkName: ForkName.deneb,
},
};
const forksAscendingEpochOrder = Object.values(forks);
const forksDescendingEpochOrder = Object.values(forks).reverse();
@@ -133,9 +143,10 @@ const testScenarios = [
for (const testScenario of testScenarios) {
const {phase0, altair, bellatrix, capella, testCases} = testScenario;
const deneb = Infinity;
const electra = Infinity;
describe(`network / fork: phase0: ${phase0}, altair: ${altair}, bellatrix: ${bellatrix} capella: ${capella}`, () => {
const forkConfig = getForkConfig({phase0, altair, bellatrix, capella, deneb});
const forkConfig = getForkConfig({phase0, altair, bellatrix, capella, deneb, electra});
const forks = forkConfig.forks;
for (const testCase of testCases) {
const {epoch, currentFork, nextFork, activeForks} = testCase;

View File

@@ -31,5 +31,13 @@ export function getConfig(fork: ForkName, forkEpoch = 0): ChainForkConfig {
CAPELLA_FORK_EPOCH: 0,
DENEB_FORK_EPOCH: forkEpoch,
});
case ForkName.electra:
return createChainForkConfig({
ALTAIR_FORK_EPOCH: 0,
BELLATRIX_FORK_EPOCH: 0,
CAPELLA_FORK_EPOCH: 0,
DENEB_FORK_EPOCH: 0,
ELECTRA_FORK_EPOCH: forkEpoch,
});
}
}

View File

@@ -49,6 +49,10 @@ export const chainConfig: ChainConfig = {
DENEB_FORK_VERSION: b("0x04000000"),
DENEB_FORK_EPOCH: 269568, // March 13, 2024, 01:55:35pm UTC
// Electra
ELECTRA_FORK_VERSION: b("0x05000000"),
ELECTRA_FORK_EPOCH: Infinity,
// Time parameters
// ---------------------------------------------------------------
// 12 seconds

View File

@@ -46,6 +46,10 @@ export const chainConfig: ChainConfig = {
DENEB_FORK_VERSION: b("0x04000001"),
DENEB_FORK_EPOCH: Infinity,
// Electra
ELECTRA_FORK_VERSION: b("0x05000001"),
ELECTRA_FORK_EPOCH: Infinity,
// Time parameters
// ---------------------------------------------------------------
// [customized] Faster for testing purposes

View File

@@ -40,6 +40,9 @@ export type ChainConfig = {
// DENEB
DENEB_FORK_VERSION: Uint8Array;
DENEB_FORK_EPOCH: number;
// ELECTRA
ELECTRA_FORK_VERSION: Uint8Array;
ELECTRA_FORK_EPOCH: number;
// Time parameters
SECONDS_PER_SLOT: number;
@@ -99,6 +102,9 @@ export const chainConfigTypes: SpecTypes<ChainConfig> = {
// DENEB
DENEB_FORK_VERSION: "bytes",
DENEB_FORK_EPOCH: "number",
// ELECTRA
ELECTRA_FORK_VERSION: "bytes",
ELECTRA_FORK_EPOCH: "number",
// Time parameters
SECONDS_PER_SLOT: "number",

View File

@@ -59,10 +59,18 @@ export function createForkConfig(config: ChainConfig): ForkConfig {
prevVersion: config.CAPELLA_FORK_VERSION,
prevForkName: ForkName.capella,
};
const electra: ForkInfo = {
name: ForkName.electra,
seq: ForkSeq.electra,
epoch: config.ELECTRA_FORK_EPOCH,
version: config.ELECTRA_FORK_VERSION,
prevVersion: config.DENEB_FORK_VERSION,
prevForkName: ForkName.deneb,
};
/** Forks in order order of occurence, `phase0` first */
// Note: Downstream code relies on proper ordering.
const forks = {phase0, altair, bellatrix, capella, deneb};
const forks = {phase0, altair, bellatrix, capella, deneb, electra};
// Prevents allocating an array on every getForkInfo() call
const forksAscendingEpochOrder = Object.values(forks);

View File

@@ -112,6 +112,10 @@ export function upgradeLightClientHeader(
// Break if no further upgradation is required else fall through
if (ForkSeq[targetFork] <= ForkSeq.deneb) break;
// eslint-disable-next-line no-fallthrough
case ForkName.electra:
throw Error("Not Implemented");
}
return upgradedHeader;
}

View File

@@ -7,6 +7,7 @@ export enum ForkName {
bellatrix = "bellatrix",
capella = "capella",
deneb = "deneb",
electra = "electra",
}
/**
@@ -18,6 +19,7 @@ export enum ForkSeq {
bellatrix = 2,
capella = 3,
deneb = 4,
electra = 5,
}
function exclude<T extends ForkName, U extends T>(coll: T[], val: U[]): Exclude<T, U>[] {

View File

@@ -55,5 +55,13 @@ function getConfig(fork: ForkName, forkEpoch = 0): ChainForkConfig {
CAPELLA_FORK_EPOCH: 0,
DENEB_FORK_EPOCH: forkEpoch,
});
case ForkName.electra:
return createChainForkConfig({
ALTAIR_FORK_EPOCH: 0,
BELLATRIX_FORK_EPOCH: 0,
CAPELLA_FORK_EPOCH: 0,
DENEB_FORK_EPOCH: 0,
ELECTRA_FORK_EPOCH: forkEpoch,
});
}
}

View File

@@ -0,0 +1,3 @@
export * from "./types.js";
export * as ts from "./types.js";
export * as ssz from "./sszTypes.js";

View File

@@ -0,0 +1,148 @@
import {ContainerType} from "@chainsafe/ssz";
import {ssz as primitiveSsz} from "../primitive/index.js";
import {ssz as denebSsz} from "../deneb/index.js";
const {BLSSignature} = primitiveSsz;
export const ExecutionPayload = new ContainerType(
{
...denebSsz.ExecutionPayload.fields,
},
{typeName: "ExecutionPayload", jsonCase: "eth2"}
);
export const ExecutionPayloadHeader = new ContainerType(
{
...denebSsz.ExecutionPayloadHeader.fields,
},
{typeName: "ExecutionPayloadHeader", jsonCase: "eth2"}
);
export const BeaconBlockBody = new ContainerType(
{
...denebSsz.BeaconBlockBody.fields,
},
{typeName: "BeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true}
);
export const BeaconBlock = new ContainerType(
{
...denebSsz.BeaconBlock.fields,
},
{typeName: "BeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true}
);
export const SignedBeaconBlock = new ContainerType(
{
message: BeaconBlock,
signature: BLSSignature,
},
{typeName: "SignedBeaconBlock", jsonCase: "eth2"}
);
export const BlobSidecar = new ContainerType(
{
...denebSsz.BlobSidecar.fields,
},
{typeName: "BlobSidecar", jsonCase: "eth2"}
);
export const BlindedBeaconBlockBody = new ContainerType(
{
...denebSsz.BlindedBeaconBlockBody.fields,
},
{typeName: "BlindedBeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true}
);
export const BlindedBeaconBlock = new ContainerType(
{
...denebSsz.BlindedBeaconBlock.fields,
},
{typeName: "BlindedBeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true}
);
export const SignedBlindedBeaconBlock = new ContainerType(
{
message: BlindedBeaconBlock,
signature: BLSSignature,
},
{typeName: "SignedBlindedBeaconBlock", jsonCase: "eth2"}
);
export const BuilderBid = new ContainerType(
{
...denebSsz.BuilderBid.fields,
},
{typeName: "BuilderBid", jsonCase: "eth2"}
);
export const SignedBuilderBid = new ContainerType(
{
message: BuilderBid,
signature: BLSSignature,
},
{typeName: "SignedBuilderBid", jsonCase: "eth2"}
);
export const ExecutionPayloadAndBlobsBundle = new ContainerType(
{
...denebSsz.ExecutionPayloadAndBlobsBundle.fields,
},
{typeName: "ExecutionPayloadAndBlobsBundle", jsonCase: "eth2"}
);
export const BeaconState = new ContainerType(
{
...denebSsz.BeaconState.fields,
},
{typeName: "BeaconState", jsonCase: "eth2"}
);
export const LightClientHeader = new ContainerType(
{
...denebSsz.LightClientHeader.fields,
},
{typeName: "LightClientHeader", jsonCase: "eth2"}
);
export const LightClientBootstrap = new ContainerType(
{
...denebSsz.LightClientBootstrap.fields,
},
{typeName: "LightClientBootstrap", jsonCase: "eth2"}
);
export const LightClientUpdate = new ContainerType(
{
...denebSsz.LightClientUpdate.fields,
},
{typeName: "LightClientUpdate", jsonCase: "eth2"}
);
export const LightClientFinalityUpdate = new ContainerType(
{
...denebSsz.LightClientFinalityUpdate.fields,
},
{typeName: "LightClientFinalityUpdate", jsonCase: "eth2"}
);
export const LightClientOptimisticUpdate = new ContainerType(
{
...denebSsz.LightClientOptimisticUpdate.fields,
},
{typeName: "LightClientOptimisticUpdate", jsonCase: "eth2"}
);
export const LightClientStore = new ContainerType(
{
...denebSsz.LightClientStore.fields,
},
{typeName: "LightClientStore", jsonCase: "eth2"}
);
export const SSEPayloadAttributes = new ContainerType(
{
...denebSsz.SSEPayloadAttributes.fields,
},
{typeName: "SSEPayloadAttributes", jsonCase: "eth2"}
);

View File

@@ -0,0 +1,29 @@
import {ValueOf} from "@chainsafe/ssz";
import * as ssz from "./sszTypes.js";
export type BlobSidecar = ValueOf<typeof ssz.BlobSidecar>;
export type ExecutionPayloadAndBlobsBundle = ValueOf<typeof ssz.ExecutionPayloadAndBlobsBundle>;
export type ExecutionPayload = ValueOf<typeof ssz.ExecutionPayload>;
export type ExecutionPayloadHeader = ValueOf<typeof ssz.ExecutionPayloadHeader>;
export type BeaconBlockBody = ValueOf<typeof ssz.BeaconBlockBody>;
export type BeaconBlock = ValueOf<typeof ssz.BeaconBlock>;
export type SignedBeaconBlock = ValueOf<typeof ssz.SignedBeaconBlock>;
export type BeaconState = ValueOf<typeof ssz.BeaconState>;
export type BlindedBeaconBlockBody = ValueOf<typeof ssz.BlindedBeaconBlockBody>;
export type BlindedBeaconBlock = ValueOf<typeof ssz.BlindedBeaconBlock>;
export type SignedBlindedBeaconBlock = ValueOf<typeof ssz.SignedBlindedBeaconBlock>;
export type BuilderBid = ValueOf<typeof ssz.BuilderBid>;
export type SignedBuilderBid = ValueOf<typeof ssz.SignedBuilderBid>;
export type SSEPayloadAttributes = ValueOf<typeof ssz.SSEPayloadAttributes>;
export type LightClientHeader = ValueOf<typeof ssz.LightClientHeader>;
export type LightClientBootstrap = ValueOf<typeof ssz.LightClientBootstrap>;
export type LightClientUpdate = ValueOf<typeof ssz.LightClientUpdate>;
export type LightClientFinalityUpdate = ValueOf<typeof ssz.LightClientFinalityUpdate>;
export type LightClientOptimisticUpdate = ValueOf<typeof ssz.LightClientOptimisticUpdate>;
export type LightClientStore = ValueOf<typeof ssz.LightClientStore>;

View File

@@ -5,9 +5,10 @@ import {ssz as altair} from "./altair/index.js";
import {ssz as bellatrix} from "./bellatrix/index.js";
import {ssz as capella} from "./capella/index.js";
import {ssz as deneb} from "./deneb/index.js";
import {ssz as electra} from "./electra/index.js";
export * from "./primitive/sszTypes.js";
export {phase0, altair, bellatrix, capella, deneb};
export {phase0, altair, bellatrix, capella, deneb, electra};
/**
* Index the ssz types that differ by fork
@@ -19,6 +20,7 @@ const typesByFork = {
[ForkName.bellatrix]: {...phase0, ...altair, ...bellatrix},
[ForkName.capella]: {...phase0, ...altair, ...bellatrix, ...capella},
[ForkName.deneb]: {...phase0, ...altair, ...bellatrix, ...capella, ...deneb},
[ForkName.deneb]: {...phase0, ...altair, ...bellatrix, ...capella, ...deneb, ...electra},
};
/**

View File

@@ -4,6 +4,7 @@ import {ts as altair} from "./altair/index.js";
import {ts as bellatrix} from "./bellatrix/index.js";
import {ts as capella} from "./capella/index.js";
import {ts as deneb} from "./deneb/index.js";
import {ts as electra} from "./electra/index.js";
import {Slot} from "./primitive/types.js";
export * from "./primitive/types.js";
@@ -12,6 +13,7 @@ export {ts as altair} from "./altair/index.js";
export {ts as bellatrix} from "./bellatrix/index.js";
export {ts as capella} from "./capella/index.js";
export {ts as deneb} from "./deneb/index.js";
export {ts as electra} from "./electra/index.js";
/** Common non-spec type to represent roots as strings */
export type RootHex = string;
@@ -132,6 +134,40 @@ type TypesByFork = {
SyncCommittee: altair.SyncCommittee;
SyncAggregate: altair.SyncAggregate;
};
[ForkName.electra]: {
BeaconBlockHeader: phase0.BeaconBlockHeader;
SignedBeaconBlockHeader: phase0.SignedBeaconBlockHeader;
BeaconBlock: electra.BeaconBlock;
BeaconBlockBody: electra.BeaconBlockBody;
BeaconState: electra.BeaconState;
SignedBeaconBlock: electra.SignedBeaconBlock;
Metadata: altair.Metadata;
LightClientHeader: electra.LightClientHeader;
LightClientBootstrap: electra.LightClientBootstrap;
LightClientUpdate: electra.LightClientUpdate;
LightClientFinalityUpdate: electra.LightClientFinalityUpdate;
LightClientOptimisticUpdate: electra.LightClientOptimisticUpdate;
LightClientStore: electra.LightClientStore;
BlindedBeaconBlock: electra.BlindedBeaconBlock;
BlindedBeaconBlockBody: electra.BlindedBeaconBlockBody;
SignedBlindedBeaconBlock: electra.SignedBlindedBeaconBlock;
ExecutionPayload: electra.ExecutionPayload;
ExecutionPayloadHeader: electra.ExecutionPayloadHeader;
BuilderBid: electra.BuilderBid;
SignedBuilderBid: electra.SignedBuilderBid;
SSEPayloadAttributes: electra.SSEPayloadAttributes;
BlockContents: {block: BeaconBlock<ForkName.electra>; kzgProofs: deneb.KZGProofs; blobs: deneb.Blobs};
SignedBlockContents: {
signedBlock: SignedBeaconBlock<ForkName.electra>;
kzgProofs: deneb.KZGProofs;
blobs: deneb.Blobs;
};
ExecutionPayloadAndBlobsBundle: deneb.ExecutionPayloadAndBlobsBundle;
BlobsBundle: deneb.BlobsBundle;
Contents: deneb.Contents;
SyncCommittee: altair.SyncCommittee;
SyncAggregate: altair.SyncAggregate;
};
};
export type TypesFor<F extends ForkName, K extends keyof TypesByFork[F] | void = void> = K extends void

View File

@@ -73,6 +73,7 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record<keyof ConfigWit
const bellatrixForkRelevant = localConfig.BELLATRIX_FORK_EPOCH < Infinity;
const capellaForkRelevant = localConfig.CAPELLA_FORK_EPOCH < Infinity;
const denebForkRelevant = localConfig.DENEB_FORK_EPOCH < Infinity;
const electraForkRelevant = localConfig.ELECTRA_FORK_EPOCH < Infinity;
return {
// # Config
@@ -106,6 +107,10 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record<keyof ConfigWit
DENEB_FORK_VERSION: denebForkRelevant,
DENEB_FORK_EPOCH: denebForkRelevant,
// electra
ELECTRA_FORK_VERSION: electraForkRelevant,
ELECTRA_FORK_EPOCH: electraForkRelevant,
// Time parameters
SECONDS_PER_SLOT: true,
SECONDS_PER_ETH1_BLOCK: true,