Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions packages/state-transition/src/block/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ForkSeq} from "@lodestar/params";
import {allForks, altair, capella} from "@lodestar/types";
import {allForks, altair, capella, eip4844} from "@lodestar/types";
import {getFullOrBlindedPayload, isExecutionEnabled} from "../util/execution.js";
import {CachedBeaconStateAllForks, CachedBeaconStateCapella, CachedBeaconStateBellatrix} from "../types.js";
import {processExecutionPayload} from "./processExecutionPayload.js";
Expand All @@ -8,7 +8,8 @@ import {processBlockHeader} from "./processBlockHeader.js";
import {processEth1Data} from "./processEth1Data.js";
import {processOperations} from "./processOperations.js";
import {processRandao} from "./processRandao.js";
import {BlockExternalData} from "./externalData.js";
import {processBlobKzgCommitments} from "./processBlobKzgCommitments.js";
import {BlockExternalData, DataAvailableStatus} from "./externalData.js";
import {processWithdrawals} from "./processWithdrawals.js";

// Spec tests
Expand Down Expand Up @@ -46,7 +47,9 @@ export function processBlock(
// on the randao_mix computed with the reveal of the previous block.
if (fork >= ForkSeq.bellatrix && isExecutionEnabled(state as CachedBeaconStateBellatrix, block)) {
const fullOrBlindedPayload = getFullOrBlindedPayload(block);
if (fork >= ForkSeq.capella) {
// TODO EIP-4844: Allow to disable withdrawals for interop testing
// https://github.com/ethereum/consensus-specs/blob/b62c9e877990242d63aa17a2a59a49bc649a2f2e/specs/eip4844/beacon-chain.md#disabling-withdrawals
if (fork >= ForkSeq.capella && !opts?.disabledWithdrawals) {
processWithdrawals(
state as CachedBeaconStateCapella,
fullOrBlindedPayload as capella.FullOrBlindedExecutionPayload
Expand All @@ -61,4 +64,21 @@ export function processBlock(
if (fork >= ForkSeq.altair) {
processSyncAggregate(state, block as altair.BeaconBlock, verifySignatures);
}

if (fork >= ForkSeq.eip4844) {
processBlobKzgCommitments(block.body as eip4844.BeaconBlockBody);

// New in EIP-4844, note: Can sync optimistically without this condition, see note on `is_data_available`
// NOTE: Ommitted and should be verified beforehand

// assert is_data_available(block.slot, hash_tree_root(block), block.body.blob_kzg_commitments)
switch (externalData.dataAvailableStatus) {
case DataAvailableStatus.preEIP4844:
throw Error("dataAvailableStatus preEIP4844");
case DataAvailableStatus.notAvailable:
throw Error("dataAvailableStatus notAvailable");
case DataAvailableStatus.available:
break; // ok
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {eip4844} from "@lodestar/types";
import {verifyKzgCommitmentsAgainstTransactions} from "../util/index.js";

/**
* https://github.com/ethereum/consensus-specs/blob/11a037fd9227e29ee809c9397b09f8cc3383a8c0/specs/eip4844/beacon-chain.md#blob-kzg-commitments
*
* def process_blob_kzg_commitments(state: BeaconState, body: BeaconBlockBody):
* assert verify_kzg_commitments_against_transactions(
* body.execution_payload.transactions,
* body.blob_kzg_commitments
* )
*/
export function processBlobKzgCommitments(body: eip4844.BeaconBlockBody): void {
if (!verifyKzgCommitmentsAgainstTransactions(body.executionPayload.transactions, body.blobKzgCommitments)) {
throw Error("Invalid KZG commitments against transactions");
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ssz, allForks, capella} from "@lodestar/types";
import {ssz, allForks, capella, eip4844} from "@lodestar/types";
import {toHexString, byteArrayEquals} from "@chainsafe/ssz";
import {ForkSeq} from "@lodestar/params";
import {CachedBeaconStateBellatrix, CachedBeaconStateCapella} from "../types.js";
Expand Down Expand Up @@ -89,6 +89,13 @@ export function processExecutionPayload(
);
}

if (fork >= ForkSeq.eip4844) {
// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/beacon-chain.md#process_execution_payload
(bellatrixPayloadFields as eip4844.ExecutionPayloadHeader).excessDataGas = (payload as
| eip4844.ExecutionPayloadHeader
| eip4844.ExecutionPayload).excessDataGas;
}

// TODO EIP-4844: Types are not happy by default. Since it's a generic allForks type going through ViewDU
// transformation then into allForks, probably some weird intersection incompatibility happens
state.latestExecutionPayloadHeader = state.config
Expand Down
3 changes: 2 additions & 1 deletion packages/state-transition/src/cache/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ export type BeaconStateEip4844 = CompositeViewDU<typeof ssz.eip4844.BeaconState>
// - Works well as function argument and as generic type for allForks functions
//
// Quasy equivalent to
// CompositeViewDU<typeof ssz.phase0.BeaconState | typeof ssz.altair.BeaconState | typeof ssz.bellatrix.BeaconState>
// CompositeViewDU<typeof ssz.phase0.BeaconState | typeof ssz.altair.BeaconState | ...> // + future forks
export type BeaconStateAllForks =
| BeaconStatePhase0
| BeaconStateAltair
| BeaconStateBellatrix
| BeaconStateCapella
| BeaconStateEip4844;

export type BeaconStateExecutions = BeaconStateBellatrix | BeaconStateCapella | BeaconStateEip4844;
1 change: 1 addition & 0 deletions packages/state-transition/src/slot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {ZERO_HASH} from "../constants/index.js";
export {upgradeStateToAltair} from "./upgradeStateToAltair.js";
export {upgradeStateToBellatrix} from "./upgradeStateToBellatrix.js";
export {upgradeStateToCapella} from "./upgradeStateToCapella.js";
export {upgradeStateTo4844} from "./upgradeStateTo4844.js";

/**
* Dial state to next slot. Common for all forks
Expand Down
33 changes: 33 additions & 0 deletions packages/state-transition/src/slot/upgradeStateTo4844.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {ssz} from "@lodestar/types";
import {CachedBeaconStateEip4844} from "../types.js";
import {getCachedBeaconState} from "../cache/stateCache.js";
import {CachedBeaconStateCapella} from "../types.js";

/**
* Upgrade a state from Capella to 4844.
*/
export function upgradeStateTo4844(stateCapella: CachedBeaconStateCapella): CachedBeaconStateEip4844 {
const {config} = stateCapella;

const stateCapellaNode = ssz.capella.BeaconState.commitViewDU(stateCapella);
const state4844View = ssz.eip4844.BeaconState.getViewDU(stateCapellaNode);

const state4844 = getCachedBeaconState(state4844View, stateCapella);

state4844.fork = ssz.phase0.Fork.toViewDU({
previousVersion: stateCapella.fork.currentVersion,
currentVersion: config.EIP4844_FORK_VERSION,
epoch: stateCapella.epochCtx.epoch,
});

// capella.latestExecutionPayloadHeader has 15 properties, adding only 1 extra will not increase the tree depth.
// The initial value of the new property 'excessDataGas' is zero, so the default tree value is correct.
// Just casting the same tree node to state4844 is sufficient and nothing has to be done.
// ```
// state4844.latestExecutionPayloadHeader.excessDataGas = ssz.UintBn256.defaultValue()
// ```

state4844.commit();

return state4844;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {CachedBeaconStateBellatrix, CachedBeaconStateCapella} from "../types.js"
import {getCachedBeaconState} from "../cache/stateCache.js";

/**
* Upgrade a state from altair to bellatrix.
* Upgrade a state from bellatrix to capella.
*/
export function upgradeStateToCapella(stateBellatrix: CachedBeaconStateBellatrix): CachedBeaconStateCapella {
const {config} = stateBellatrix;
Expand Down
12 changes: 11 additions & 1 deletion packages/state-transition/src/stateTransition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ import {
CachedBeaconStatePhase0,
CachedBeaconStateAltair,
CachedBeaconStateBellatrix,
CachedBeaconStateCapella,
} from "./types.js";
import {computeEpochAtSlot} from "./util/index.js";
import {verifyProposerSignature} from "./signatureSets/index.js";
import {processSlot, upgradeStateToAltair, upgradeStateToBellatrix, upgradeStateToCapella} from "./slot/index.js";
import {
processSlot,
upgradeStateToAltair,
upgradeStateToBellatrix,
upgradeStateToCapella,
upgradeStateTo4844,
} from "./slot/index.js";
import {processBlock} from "./block/index.js";
import {processEpoch} from "./epoch/index.js";
import {BlockExternalData, DataAvailableStatus, ExecutionPayloadStatus} from "./block/externalData.js";
Expand Down Expand Up @@ -168,6 +175,9 @@ function processSlotsWithTransientCache(
if (stateSlot === config.CAPELLA_FORK_EPOCH) {
postState = upgradeStateToCapella(postState as CachedBeaconStateBellatrix) as CachedBeaconStateAllForks;
}
if (stateSlot === config.EIP4844_FORK_EPOCH) {
postState = upgradeStateTo4844(postState as CachedBeaconStateCapella) as CachedBeaconStateAllForks;
}
} else {
postState.slot++;
}
Expand Down
13 changes: 0 additions & 13 deletions packages/state-transition/src/util/executionEngine.ts

This file was deleted.