Skip to content

Commit

Permalink
feat: update deneb types and spec to 1.4.0-alpha.1 (#5605)
Browse files Browse the repository at this point in the history
* feat:  update deneb types and spec to 1.4.0-alpha.1

update config commit

* fix e2e
  • Loading branch information
g11tech authored Jun 5, 2023
1 parent dd11c95 commit e9e5bc5
Show file tree
Hide file tree
Showing 19 changed files with 136 additions and 31 deletions.
2 changes: 2 additions & 0 deletions packages/beacon-node/test/e2e/api/impl/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const CONSTANT_NAMES_SKIP_LIST = new Set([
// TODO DENEB: This constant was added then removed on a spec re-write.
// When developing DENEB branch the tracked version still doesn't have released the removal
"DOMAIN_BLOB_SIDECAR",
// TODO DENEB: Configure the blob subnets in a followup PR
"BLOB_SIDECAR_SUBNET_COUNT",
]);

describe("api / impl / config", function () {
Expand Down
1 change: 1 addition & 0 deletions packages/beacon-node/test/spec/presets/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {transition} from "./transition.js";
// ],
// ```
const skipOpts: SkipOpts = {
skippedForks: ["eip6110"],
// TODO: capella
// BeaconBlockBody proof in lightclient is the new addition in v1.3.0-rc.2-hotfix
// Skip them for now to enable subsequently
Expand Down
8 changes: 3 additions & 5 deletions packages/beacon-node/test/spec/presets/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,12 @@ const operationFns: Record<string, BlockProcessFn<CachedBeaconStateAllForks>> =
blockFns.processVoluntaryExit(state, testCase.voluntary_exit);
},

execution_payload: (
state,
testCase: {execution_payload: bellatrix.ExecutionPayload; execution: {execution_valid: boolean}}
) => {
execution_payload: (state, testCase: {body: bellatrix.BeaconBlockBody; execution: {execution_valid: boolean}}) => {
const fork = state.config.getForkSeq(state.slot);
blockFns.processExecutionPayload(
fork,
state as CachedBeaconStateAllForks as CachedBeaconStateBellatrix,
testCase.execution_payload,
testCase.body,
{
executionPayloadStatus: testCase.execution.execution_valid
? ExecutionPayloadStatus.valid
Expand Down Expand Up @@ -127,6 +124,7 @@ export const operations: TestRunnerFn<OperationsTestCase, BeaconStateAllForks> =
attestation: ssz.phase0.Attestation,
attester_slashing: ssz.phase0.AttesterSlashing,
block: ssz[fork].BeaconBlock,
body: ssz[fork].BeaconBlockBody,
deposit: ssz.phase0.Deposit,
proposer_slashing: ssz.phase0.ProposerSlashing,
voluntary_exit: ssz.phase0.SignedVoluntaryExit,
Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-node/test/spec/specTestVersioning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {DownloadTestsOptions} from "@lodestar/spec-test-util";
const __dirname = path.dirname(fileURLToPath(import.meta.url));

export const ethereumConsensusSpecsTests: DownloadTestsOptions = {
specVersion: "v1.3.0",
specVersion: "v1.4.0-alpha.1",
// Target directory is the host package root: 'packages/*/spec-tests'
outputDir: path.join(__dirname, "../../spec-tests"),
specTestsRepoUrl: "https://github.com/ethereum/consensus-spec-tests",
Expand Down
8 changes: 6 additions & 2 deletions packages/light-client/src/spec/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ export function upgradeLightClientHeader(

// eslint-disable-next-line no-fallthrough
case ForkName.deneb:
(upgradedHeader as deneb.LightClientHeader).execution.dataGasUsed =
ssz.deneb.LightClientHeader.fields.execution.fields.dataGasUsed.defaultValue();
(upgradedHeader as deneb.LightClientHeader).execution.excessDataGas =
ssz.deneb.LightClientHeader.fields.execution.fields.excessDataGas.defaultValue();

Expand Down Expand Up @@ -127,8 +129,10 @@ export function isValidLightClientHeader(config: ChainForkConfig, header: allFor

if (epoch < config.DENEB_FORK_EPOCH) {
if (
(header as deneb.LightClientHeader).execution.excessDataGas &&
(header as deneb.LightClientHeader).execution.excessDataGas !== BigInt(0)
((header as deneb.LightClientHeader).execution.dataGasUsed &&
(header as deneb.LightClientHeader).execution.dataGasUsed !== BigInt(0)) ||
((header as deneb.LightClientHeader).execution.excessDataGas &&
(header as deneb.LightClientHeader).execution.excessDataGas !== BigInt(0))
) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe("isValidLightClientHeader", function () {

const capellaUpgradedDenebHeader = {
beacon: capellaLCHeader.beacon,
execution: {...capellaLCHeader.execution, excessDataGas: 0},
execution: {...capellaLCHeader.execution, dataGasUsed: 0, excessDataGas: 0},
executionBranch: capellaLCHeader.executionBranch,
};

Expand Down
1 change: 1 addition & 0 deletions packages/params/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export const {
MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP,

FIELD_ELEMENTS_PER_BLOB,
MAX_BLOB_COMMITMENTS_PER_BLOCK,
MAX_BLOBS_PER_BLOCK,
} = activePreset;

Expand Down
1 change: 1 addition & 0 deletions packages/params/src/presets/mainnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,6 @@ export const mainnetPreset: BeaconPreset = {
///////////
// https://github.com/ethereum/consensus-specs/blob/dev/presets/mainnet/eip4844.yaml
FIELD_ELEMENTS_PER_BLOB: 4096,
MAX_BLOB_COMMITMENTS_PER_BLOCK: 4096,
MAX_BLOBS_PER_BLOCK: 4,
};
1 change: 1 addition & 0 deletions packages/params/src/presets/minimal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,6 @@ export const minimalPreset: BeaconPreset = {
///////////
// https://github.com/ethereum/consensus-specs/blob/dev/presets/minimal/eip4844.yaml
FIELD_ELEMENTS_PER_BLOB: 4,
MAX_BLOB_COMMITMENTS_PER_BLOCK: 16,
MAX_BLOBS_PER_BLOCK: 4,
};
2 changes: 2 additions & 0 deletions packages/params/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export type BeaconPreset = {
// DENEB
///////////
FIELD_ELEMENTS_PER_BLOB: number;
MAX_BLOB_COMMITMENTS_PER_BLOCK: number;
MAX_BLOBS_PER_BLOCK: number;
};

Expand Down Expand Up @@ -162,6 +163,7 @@ export const beaconPresetTypes: BeaconPresetTypes = {
// DENEB
///////////
FIELD_ELEMENTS_PER_BLOB: "number",
MAX_BLOB_COMMITMENTS_PER_BLOCK: "number",
MAX_BLOBS_PER_BLOCK: "number",
};

Expand Down
2 changes: 1 addition & 1 deletion packages/params/test/e2e/ensure-config-is-synced.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {loadConfigYaml} from "../yaml.js";
// Not e2e, but slow. Run with e2e tests

/** https://github.com/ethereum/consensus-specs/releases */
const specConfigCommit = "v1.3.0";
const specConfigCommit = "v1.4.0-alpha.1";

describe("Ensure config is synced", function () {
this.timeout(60 * 1000);
Expand Down
2 changes: 1 addition & 1 deletion packages/state-transition/src/block/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function processBlock(
fullOrBlindedPayload as capella.FullOrBlindedExecutionPayload
);
}
processExecutionPayload(fork, state as CachedBeaconStateBellatrix, fullOrBlindedPayload, externalData);
processExecutionPayload(fork, state as CachedBeaconStateBellatrix, block.body, externalData);
}

processRandao(state, block, verifySignatures);
Expand Down
17 changes: 14 additions & 3 deletions packages/state-transition/src/block/processExecutionPayload.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import {ssz, allForks, capella, deneb} from "@lodestar/types";
import {toHexString, byteArrayEquals} from "@chainsafe/ssz";
import {ForkSeq} from "@lodestar/params";
import {ForkSeq, MAX_BLOBS_PER_BLOCK} from "@lodestar/params";
import {CachedBeaconStateBellatrix, CachedBeaconStateCapella} from "../types.js";
import {getRandaoMix} from "../util/index.js";
import {isExecutionPayload, isMergeTransitionComplete} from "../util/execution.js";
import {isExecutionPayload, isMergeTransitionComplete, getFullOrBlindedPayloadFromBody} from "../util/execution.js";
import {BlockExternalData, ExecutionPayloadStatus} from "./externalData.js";

export function processExecutionPayload(
fork: ForkSeq,
state: CachedBeaconStateBellatrix | CachedBeaconStateCapella,
payload: allForks.FullOrBlindedExecutionPayload,
body: allForks.FullOrBlindedBeaconBlockBody,
externalData: BlockExternalData
): void {
const payload = getFullOrBlindedPayloadFromBody(body);
// Verify consistency of the parent hash, block number, base fee per gas and gas limit
// with respect to the previous execution payload header
if (isMergeTransitionComplete(state)) {
Expand Down Expand Up @@ -43,6 +44,13 @@ export function processExecutionPayload(
throw Error(`Invalid timestamp ${payload.timestamp} genesisTime=${state.genesisTime} slot=${state.slot}`);
}

if (fork >= ForkSeq.deneb) {
const blobKzgCommitmentsLen = (body as deneb.BeaconBlockBody).blobKzgCommitments?.length ?? 0;
if (blobKzgCommitmentsLen > MAX_BLOBS_PER_BLOCK) {
throw Error(`blobKzgCommitmentsLen exceeds limit=${MAX_BLOBS_PER_BLOCK}`);
}
}

// Verify the execution payload is valid
//
// if executionEngine is null, executionEngine.onPayload MUST be called after running processBlock to get the
Expand Down Expand Up @@ -101,6 +109,9 @@ export function executionPayloadToPayloadHeader(

if (fork >= ForkSeq.deneb) {
// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/beacon-chain.md#process_execution_payload
(bellatrixPayloadFields as deneb.ExecutionPayloadHeader).dataGasUsed = (
payload as deneb.ExecutionPayloadHeader | deneb.ExecutionPayload
).dataGasUsed;
(bellatrixPayloadFields as deneb.ExecutionPayloadHeader).excessDataGas = (
payload as deneb.ExecutionPayloadHeader | deneb.ExecutionPayload
).excessDataGas;
Expand Down
19 changes: 13 additions & 6 deletions packages/state-transition/src/slot/upgradeStateToDeneb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,21 @@ export function upgradeStateToDeneb(stateCapella: CachedBeaconStateCapella): Cac
epoch: stateCapella.epochCtx.epoch,
});

// The field order of deneb latestExecutionPayloadHeader is not the same to capella
// all fields after excessDataGas need to explicitly set
stateDeneb.latestExecutionPayloadHeader.excessDataGas = ssz.UintBn256.defaultValue();
stateDeneb.latestExecutionPayloadHeader.blockHash = stateCapella.latestExecutionPayloadHeader.blockHash;
stateDeneb.latestExecutionPayloadHeader.transactionsRoot = stateCapella.latestExecutionPayloadHeader.transactionsRoot;
stateDeneb.latestExecutionPayloadHeader.withdrawalsRoot = stateCapella.latestExecutionPayloadHeader.withdrawalsRoot;
// Since excessDataGas and dataGasUsed are appened in the end to latestExecutionPayloadHeader so they should
// be set to defaults and need no assigning, but right now any access to latestExecutionPayloadHeader fails
// with LeafNode has no left node. Weirdly its beacuse of addition of the second field as with one field
// it seems to work.
//
// TODO DENEB: Debug and remove the following cloning
stateDeneb.latestExecutionPayloadHeader = ssz.deneb.BeaconState.fields.latestExecutionPayloadHeader.toViewDU({
...stateCapella.latestExecutionPayloadHeader.toValue(),
excessDataGas: BigInt(0),
dataGasUsed: BigInt(0),
});

stateDeneb.commit();
// Clear cache to ensure the cache of capella fields is not used by new deneb fields
stateDeneb["clearCache"]();

return stateDeneb;
}
16 changes: 11 additions & 5 deletions packages/state-transition/src/util/execution.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {allForks, bellatrix, capella, isBlindedBeaconBlock, ssz} from "@lodestar/types";
import {allForks, bellatrix, capella, isBlindedBeaconBlockBody, ssz} from "@lodestar/types";
import {
BeaconStateBellatrix,
BeaconStateCapella,
Expand Down Expand Up @@ -93,10 +93,16 @@ export function isExecutionBlockBodyType(
export function getFullOrBlindedPayload(
block: allForks.FullOrBlindedBeaconBlock
): allForks.FullOrBlindedExecutionPayload {
if (isBlindedBeaconBlock(block)) {
return block.body.executionPayloadHeader;
} else if ((block as bellatrix.BeaconBlock).body.executionPayload !== undefined) {
return (block as bellatrix.BeaconBlock).body.executionPayload;
return getFullOrBlindedPayloadFromBody(block.body);
}

export function getFullOrBlindedPayloadFromBody(
body: allForks.FullOrBlindedBeaconBlockBody
): allForks.FullOrBlindedExecutionPayload {
if (isBlindedBeaconBlockBody(body)) {
return body.executionPayloadHeader;
} else if ((body as bellatrix.BeaconBlockBody).executionPayload !== undefined) {
return (body as bellatrix.BeaconBlockBody).executionPayload;
} else {
throw Error("Ǹot allForks.FullOrBlindedBeaconBlock");
}
Expand Down
58 changes: 58 additions & 0 deletions packages/state-transition/test/unit/upgradeState.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {expect} from "chai";
import {ssz} from "@lodestar/types";
import {ForkName} from "@lodestar/params";
import {createCachedBeaconState, PubkeyIndexMap} from "@lodestar/state-transition";
import {createBeaconConfig, ChainForkConfig, createChainForkConfig} from "@lodestar/config";
import {config as chainConfig} from "@lodestar/config/default";

import {upgradeStateToDeneb} from "../../src/slot/upgradeStateToDeneb.js";

describe("upgradeState", () => {
it("upgradeStateToDeneb", () => {
const capellaState = ssz.capella.BeaconState.defaultViewDU();
const config = getConfig(ForkName.capella);
const stateView = createCachedBeaconState(
capellaState,
{
config: createBeaconConfig(config, capellaState.genesisValidatorsRoot),
pubkey2index: new PubkeyIndexMap(),
index2pubkey: [],
},
{skipSyncCommitteeCache: true}
);
const newState = upgradeStateToDeneb(stateView);
expect(() => newState.toValue()).to.not.throw();
});
});

const ZERO_HASH = Buffer.alloc(32, 0);
/** default config with ZERO_HASH as genesisValidatorsRoot */
const config = createBeaconConfig(chainConfig, ZERO_HASH);

/* eslint-disable @typescript-eslint/naming-convention */
function getConfig(fork: ForkName, forkEpoch = 0): ChainForkConfig {
switch (fork) {
case ForkName.phase0:
return config;
case ForkName.altair:
return createChainForkConfig({ALTAIR_FORK_EPOCH: forkEpoch});
case ForkName.bellatrix:
return createChainForkConfig({
ALTAIR_FORK_EPOCH: 0,
BELLATRIX_FORK_EPOCH: forkEpoch,
});
case ForkName.capella:
return createChainForkConfig({
ALTAIR_FORK_EPOCH: 0,
BELLATRIX_FORK_EPOCH: 0,
CAPELLA_FORK_EPOCH: forkEpoch,
});
case ForkName.deneb:
return createChainForkConfig({
ALTAIR_FORK_EPOCH: 0,
BELLATRIX_FORK_EPOCH: 0,
CAPELLA_FORK_EPOCH: 0,
DENEB_FORK_EPOCH: forkEpoch,
});
}
}
13 changes: 9 additions & 4 deletions packages/types/src/deneb/sszTypes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {ContainerType, ListCompositeType, ByteVectorType, VectorCompositeType} from "@chainsafe/ssz";
import {
HISTORICAL_ROOTS_LIMIT,
MAX_BLOB_COMMITMENTS_PER_BLOCK,
FIELD_ELEMENTS_PER_BLOB,
MAX_BLOBS_PER_BLOCK,
MAX_REQUEST_BLOCKS,
Expand All @@ -20,6 +21,7 @@ const {
Slot,
Root,
BLSSignature,
UintBn64,
UintBn256,
Bytes32,
Bytes48,
Expand Down Expand Up @@ -50,7 +52,7 @@ export const Blobs = new ListCompositeType(Blob, MAX_BLOBS_PER_BLOCK);
export const BlindedBlob = Bytes32;
export const BlindedBlobs = new ListCompositeType(BlindedBlob, MAX_BLOBS_PER_BLOCK);
export const VersionedHash = Bytes32;
export const BlobKzgCommitments = new ListCompositeType(KZGCommitment, MAX_BLOBS_PER_BLOCK);
export const BlobKzgCommitments = new ListCompositeType(KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK);

// Constants

Expand Down Expand Up @@ -121,15 +123,17 @@ export const BeaconBlockAndBlobsSidecarByRootRequest = new ListCompositeType(Roo
export const ExecutionPayload = new ContainerType(
{
...capellaSsz.ExecutionPayload.fields,
excessDataGas: UintBn256, // New in DENEB
dataGasUsed: UintBn64, // New in DENEB
excessDataGas: UintBn64, // New in DENEB
},
{typeName: "ExecutionPayload", jsonCase: "eth2"}
);

export const ExecutionPayloadHeader = new ContainerType(
{
...capellaSsz.ExecutionPayloadHeader.fields,
excessDataGas: UintBn256, // New in DENEB
dataGasUsed: UintBn64, // New in DENEB
excessDataGas: UintBn64, // New in DENEB
},
{typeName: "ExecutionPayloadHeader", jsonCase: "eth2"}
);
Expand Down Expand Up @@ -233,8 +237,9 @@ export const SignedBeaconBlockAndBlobsSidecar = new ContainerType(

export const BlindedBeaconBlockBody = new ContainerType(
{
...BeaconBlockBody.fields,
...altairSsz.BeaconBlockBody.fields,
executionPayloadHeader: ExecutionPayloadHeader, // Modified in DENEB
blsToExecutionChanges: capellaSsz.BeaconBlockBody.fields.blsToExecutionChanges,
blobKzgCommitments: BlobKzgCommitments, // New in DENEB
},
{typeName: "BlindedBeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true}
Expand Down
11 changes: 9 additions & 2 deletions packages/types/src/utils/typeguards.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import {
FullOrBlindedBeaconBlock,
FullOrBlindedSignedBeaconBlock,
FullOrBlindedBeaconBlockBody,
FullOrBlindedExecutionPayload,
ExecutionPayloadHeader,
FullOrBlindedBlobSidecar,
FullOrBlindedSignedBlobSidecar,
BlindedBeaconBlockBody,
BlindedBeaconBlock,
} from "../allForks/types.js";
import {ts as bellatrix} from "../bellatrix/index.js";
import {ts as deneb} from "../deneb/index.js";
Expand All @@ -15,8 +18,12 @@ export function isBlindedExecution(payload: FullOrBlindedExecutionPayload): payl
return (payload as ExecutionPayloadHeader).transactionsRoot !== undefined;
}

export function isBlindedBeaconBlock(block: FullOrBlindedBeaconBlock): block is bellatrix.BlindedBeaconBlock {
return (block as bellatrix.BlindedBeaconBlock).body.executionPayloadHeader !== undefined;
export function isBlindedBeaconBlock(block: FullOrBlindedBeaconBlock): block is BlindedBeaconBlock {
return isBlindedBeaconBlockBody(block.body);
}

export function isBlindedBeaconBlockBody(body: FullOrBlindedBeaconBlockBody): body is BlindedBeaconBlockBody {
return (body as BlindedBeaconBlockBody).executionPayloadHeader !== undefined;
}

export function isBlindedSignedBeaconBlock(
Expand Down
1 change: 1 addition & 0 deletions packages/validator/src/util/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,5 +208,6 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record<keyof ConfigWit
/////////////////
FIELD_ELEMENTS_PER_BLOB: denebForkRelevant,
MAX_BLOBS_PER_BLOCK: denebForkRelevant,
MAX_BLOB_COMMITMENTS_PER_BLOCK: denebForkRelevant,
};
}

0 comments on commit e9e5bc5

Please sign in to comment.