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
2 changes: 2 additions & 0 deletions packages/beacon-node/src/api/impl/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
BUILDER_PAYMENT_THRESHOLD_DENOMINATOR,
BUILDER_PAYMENT_THRESHOLD_NUMERATOR,
BUILDER_WITHDRAWAL_PREFIX,
BYTES_PER_FIELD_ELEMENT,
COMPOUNDING_WITHDRAWAL_PREFIX,
CONSOLIDATION_REQUEST_TYPE,
DEPOSIT_CONTRACT_TREE_DEPTH,
Expand Down Expand Up @@ -131,6 +132,7 @@ export const specConstants = {
// Deneb types
BLOB_TX_TYPE: toHexByte(BLOB_TX_TYPE),
VERSIONED_HASH_VERSION_KZG: toHexByte(VERSIONED_HASH_VERSION_KZG),
BYTES_PER_FIELD_ELEMENT,

// electra
UNSET_DEPOSIT_REQUESTS_START_INDEX,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ export class AggregatedAttestationPool {
const stateEpoch = state.epoch;
const statePrevEpoch = stateEpoch - 1;
const rootCache = new RootCache(state);
const gloasState = isStatePostGloas(state) ? state : null;

const notSeenValidatorsFn = getNotSeenValidatorsFn(this.config, shufflingCache, state);
const validateAttestationDataFn = getValidateAttestationDataFn(forkChoice, state);
Expand Down Expand Up @@ -361,7 +362,8 @@ export class AggregatedAttestationPool {
inclusionDistance,
stateEpoch,
rootCache,
isStatePostGloas(state) ? state.executionPayloadAvailability : null
gloasState?.executionPayloadAvailability ?? null,
gloasState?.latestExecutionPayloadBid.slot ?? null
);

const weight =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,13 @@ const fastConfirmationTest =
// is_one_confirmed cases (new in v1.7.0-alpha.12, present in electra + fulu) currently
// fail. Unskip once the FCR is reworked.
name.includes("is_one_confirmed_fails_large_validator_slashed") ||
name.includes("is_one_confirmed_fails_recently_activated_validator_voting_in_empty_slot"),
name.includes("is_one_confirmed_fails_recently_activated_validator_voting_in_empty_slot") ||
// This case (new in v1.7.0-alpha.13, consensus-specs #5449) deposits a validator, but the
// vectors are generated with bls_setting=2 so the deposit carries a stub signature that
// only the pyspec BLS stub accepts. Lodestar verifies the deposit proof of possession
// inside processPendingDeposits, so the validator is never onboarded and the state root
// diverges once the pending deposit is applied.
name.includes("is_one_confirmed_passes_with_new_validator_activated_in_head_state"),

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nazarhussain this might be an issue with the test harness? in any case, I would like to keep this out of this PR, so skipping for now

},
};
};
Expand Down
9 changes: 7 additions & 2 deletions packages/beacon-node/test/spec/presets/operations.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import path from "node:path";
import {getConfig} from "@lodestar/config/test-utils";
import {ACTIVE_PRESET, ForkName} from "@lodestar/params";
import {ACTIVE_PRESET, ForkName, ForkSeq} from "@lodestar/params";
import {InputType} from "@lodestar/spec-test-util";
import {
BeaconStateAllForks,
Expand Down Expand Up @@ -38,7 +38,12 @@ const syncAggregate: BlockProcessFn<CachedBeaconStateAllForks> = (
const operationFns: Record<string, BlockProcessFn<CachedBeaconStateAllForks>> = {
attestation: (state, testCase: {attestation: phase0.Attestation}) => {
const fork = state.config.getForkSeq(state.slot);
blockFns.processAttestations(fork, state, [testCase.attestation]);
blockFns.processAttestations(
fork,
state,
[testCase.attestation],
fork >= ForkSeq.gloas ? (state as CachedBeaconStateGloas).latestExecutionPayloadBid.slot : null
);
},

attester_slashing: (state, testCase: BaseSpecTest & {attester_slashing: AttesterSlashing}) => {
Expand Down
7 changes: 6 additions & 1 deletion packages/beacon-node/test/spec/utils/specTestIterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ export const defaultSkipOpts: SkipOpts = {
// New test suite added in v1.7.0-alpha.8 (consensus-specs #5206); gloas PTC fork choice
// handling is not yet implemented in Lodestar.
/^gloas\/fork_choice\/on_payload_attestation_message\/.*$/,
// TODO-GLOAS: re-enable after the gloas should_apply_proposer_boost rule is implemented.
// New test suite added in v1.7.0-alpha.13 (consensus-specs #5441); Lodestar still applies
// the pre-gloas proposer boost, so the head weight differs by the boost amount.
/^gloas\/fork_choice\/should_apply_proposer_boost\/.*$/,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ensi321 looks like we are failing the new tests you added in ethereum/consensus-specs#5441

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional. Supposed to pass with #9233

// TODO GLOAS: enable this after gloas fork choice is ready
/^gloas\/fork_choice_compliance\/.*/,
],
Expand All @@ -93,7 +97,8 @@ export const defaultSkipOpts: SkipOpts = {
// TODO GLOAS: Proposer-boost dependent-root gate uses stale cached head across epoch-boundary ticks;
// boost wrongly denied. Fails identically on every pre-gloas fork.
// Enable this after https://github.com/ChainSafe/lodestar/issues/9666 is resolved
/fork_choice_compliance\/block_tree_test\/pyspec_tests\/block_tree_test_16_201284350_1$/,
// The case name embeds the generation seed, so it changes whenever comptests are regenerated.
/fork_choice_compliance\/block_tree_test\/pyspec_tests\/block_tree_test_17_381675768_1$/,
],
// TODO GLOAS: Investigate why networking tests are failing since alpha.5
skippedRunners: ["networking"],
Expand Down
1 change: 1 addition & 0 deletions packages/config/test/e2e/ensure-config-is-synced.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const ignoredRemoteConfigFields: (keyof ChainConfig)[] = [
"PROPOSER_INCLUSION_LIST_CUTOFF_BPS" as keyof ChainConfig,
"MAX_REQUEST_INCLUSION_LIST" as keyof ChainConfig,
"MAX_BYTES_PER_INCLUSION_LIST" as keyof ChainConfig,
"MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS" as keyof ChainConfig,
// Networking params that may be in presets instead of chainConfig
"ATTESTATION_SUBNET_COUNT" as keyof ChainConfig,
"ATTESTATION_SUBNET_EXTRA_BITS" as keyof ChainConfig,
Expand Down
7 changes: 4 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 {ForkPostGloas, ForkSeq} from "@lodestar/params";
import {BeaconBlock, BlindedBeaconBlock, altair, capella} from "@lodestar/types";
import {BeaconBlock, BlindedBeaconBlock, Slot, altair, capella} from "@lodestar/types";
import {BeaconStateTransitionMetrics} from "../metrics.js";
import {
CachedBeaconStateAllForks,
Expand Down Expand Up @@ -86,16 +86,17 @@ export function processBlock(
processExecutionPayload(fork, state as CachedBeaconStateBellatrix, block.body, externalData);
}

let parentSlot: Slot | null = null;
if (fork >= ForkSeq.gloas) {
processExecutionPayloadBid(
parentSlot = processExecutionPayloadBid(
state as CachedBeaconStateGloas,
(block as BeaconBlock<ForkPostGloas>).body.signedExecutionPayloadBid
);
}

processRandao(state, block, verifySignatures);
processEth1Data(state, block.body.eth1Data);
processOperations(fork, state, block.body, opts, metrics);
processOperations(fork, state, block.body, parentSlot, opts, metrics);
if (fork >= ForkSeq.altair) {
processSyncAggregate(state, block as altair.BeaconBlock, verifySignatures);
}
Expand Down
12 changes: 10 additions & 2 deletions packages/state-transition/src/block/processAttestations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ForkSeq} from "@lodestar/params";
import {Attestation} from "@lodestar/types";
import {Attestation, Slot} from "@lodestar/types";
import {BeaconStateTransitionMetrics} from "../metrics.js";
import {CachedBeaconStateAllForks, CachedBeaconStateAltair, CachedBeaconStatePhase0} from "../types.js";
import {processAttestationPhase0} from "./processAttestationPhase0.js";
Expand All @@ -12,6 +12,7 @@ export function processAttestations(
fork: ForkSeq,
state: CachedBeaconStateAllForks,
attestations: Attestation[],
parentSlot: Slot | null,
verifySignatures = true,
metrics?: BeaconStateTransitionMetrics | null
): void {
Expand All @@ -20,6 +21,13 @@ export function processAttestations(
processAttestationPhase0(state as CachedBeaconStatePhase0, attestation, verifySignatures);
}
} else {
processAttestationsAltair(fork, state as CachedBeaconStateAltair, attestations, verifySignatures, metrics);
processAttestationsAltair(
fork,
state as CachedBeaconStateAltair,
attestations,
parentSlot,
verifySignatures,
metrics
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
TIMELY_TARGET_WEIGHT,
WEIGHT_DENOMINATOR,
} from "@lodestar/params";
import {Attestation, Epoch, phase0} from "@lodestar/types";
import {Attestation, Epoch, Slot, phase0} from "@lodestar/types";
import {byteArrayEquals, intSqrt} from "@lodestar/utils";
import {BeaconStateTransitionMetrics} from "../metrics.js";
import {getAttestationWithIndicesSignatureSet} from "../signatureSets/indexedAttestation.js";
Expand All @@ -37,6 +37,7 @@ export function processAttestationsAltair(
fork: ForkSeq,
state: CachedBeaconStateAltair | CachedBeaconStateGloas,
attestations: Attestation[],
parentSlot: Slot | null,
verifySignature = true,
metrics?: BeaconStateTransitionMetrics | null
): void {
Expand Down Expand Up @@ -82,7 +83,8 @@ export function processAttestationsAltair(
stateSlot - data.slot,
epochCtx.epoch,
rootCache,
fork >= ForkSeq.gloas ? (state as CachedBeaconStateGloas).executionPayloadAvailability : null
fork >= ForkSeq.gloas ? (state as CachedBeaconStateGloas).executionPayloadAvailability : null,
parentSlot
);

// For each participant, update their participation
Expand Down Expand Up @@ -179,7 +181,8 @@ export function getAttestationParticipationStatus(
inclusionDelay: number,
currentEpoch: Epoch,
rootCache: RootCache,
executionPayloadAvailability: BitArray | null
executionPayloadAvailability: BitArray | null,
parentSlot: Slot | null
): {flags: number; isSameSlotAttestation: boolean} {
const justifiedCheckpoint =
data.target.epoch === currentEpoch ? rootCache.currentJustifiedCheckpoint : rootCache.previousJustifiedCheckpoint;
Expand Down Expand Up @@ -221,13 +224,16 @@ export function getAttestationParticipationStatus(
if (executionPayloadAvailability === null) {
throw new Error("Must supply executionPayloadAvailability post-gloas");
}
if (parentSlot === null) {
throw new Error("Must supply parentSlot post-gloas");
}

if (data.index !== 0 && data.index !== 1) {
throw new Error(`data index must be 0 or 1 index=${data.index}`);
}

isMatchingPayload =
Boolean(data.index) === executionPayloadAvailability.get(data.slot % SLOTS_PER_HISTORICAL_ROOT);
Boolean(data.index) === executionPayloadAvailability.get(parentSlot % SLOTS_PER_HISTORICAL_ROOT);
}

isMatchingHead = isMatchingHead && isMatchingPayload;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {PublicKey, Signature, verify} from "@chainsafe/blst";
import {BUILDER_INDEX_SELF_BUILD, GENESIS_SLOT, PAYLOAD_BUILDER_VERSION, SLOTS_PER_EPOCH} from "@lodestar/params";
import {gloas, ssz} from "@lodestar/types";
import {Slot, gloas, ssz} from "@lodestar/types";
import {byteArrayEquals, toHex, toRootHex} from "@lodestar/utils";
import {G2_POINT_AT_INFINITY} from "../constants/constants.js";
import {getExecutionPayloadBidSigningRoot} from "../signatureSets/executionPayloadBid.js";
Expand All @@ -11,7 +11,7 @@ import {getBlockRootAtSlot, getCurrentEpoch, getRandaoMix} from "../util/index.j
export function processExecutionPayloadBid(
state: CachedBeaconStateGloas,
signedBid: gloas.SignedExecutionPayloadBid
): void {
): Slot {
const bid = signedBid.message;
const {builderIndex, value: amount} = bid;

Expand Down Expand Up @@ -99,7 +99,10 @@ export function processExecutionPayloadBid(
state.builderPendingPayments.set(SLOTS_PER_EPOCH + (bid.slot % SLOTS_PER_EPOCH), pendingPaymentView);
}

const parentSlot = state.latestExecutionPayloadBid.slot;
state.latestExecutionPayloadBid = ssz.gloas.ExecutionPayloadBid.toViewDU(bid);

return parentSlot;
}

function verifyExecutionPayloadBidSignature(
Expand Down
5 changes: 3 additions & 2 deletions packages/state-transition/src/block/processOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
MAX_PROPOSER_SLASHINGS,
MAX_VOLUNTARY_EXITS,
} from "@lodestar/params";
import {BeaconBlockBody, capella, electra, gloas} from "@lodestar/types";
import {BeaconBlockBody, Slot, capella, electra, gloas} from "@lodestar/types";
import {BeaconStateTransitionMetrics} from "../metrics.js";
import {
CachedBeaconStateAllForks,
Expand Down Expand Up @@ -44,6 +44,7 @@ export function processOperations(
fork: ForkSeq,
state: CachedBeaconStateAllForks,
body: BeaconBlockBody,
parentSlot: Slot | null,
opts: ProcessBlockOpts = {verifySignatures: true},
metrics?: BeaconStateTransitionMetrics | null
): void {
Expand All @@ -67,7 +68,7 @@ export function processOperations(
processAttesterSlashing(fork, state, attesterSlashing, opts.verifySignatures);
}

processAttestations(fork, state, body.attestations, opts.verifySignatures, metrics);
processAttestations(fork, state, body.attestations, parentSlot, opts.verifySignatures, metrics);

for (const deposit of body.deposits) {
processDeposit(fork, state, deposit);
Expand Down
25 changes: 20 additions & 5 deletions packages/state-transition/src/rewards/blockRewards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ import {
WHISTLEBLOWER_REWARD_QUOTIENT,
WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA,
isForkPostElectra,
isForkPostGloas,
} from "@lodestar/params";
import {BeaconBlock, altair, phase0, rewards} from "@lodestar/types";
import {BeaconBlock, Slot, altair, phase0, rewards} from "@lodestar/types";
import {processAttestationsAltair} from "../block/processAttestationsAltair.js";
import {RewardCache} from "../cache/rewardCache.js";
import {CachedBeaconStateAllForks, CachedBeaconStateAltair, CachedBeaconStatePhase0} from "../cache/stateCache.js";
import {
CachedBeaconStateAllForks,
CachedBeaconStateAltair,
CachedBeaconStateGloas,
CachedBeaconStatePhase0,
} from "../cache/stateCache.js";
import {getAttesterSlashableIndices} from "../util/attestation.js";

type SubRewardValue = number; // All reward values should be integer
Expand Down Expand Up @@ -36,10 +42,18 @@ export async function computeBlockRewards(
let syncAggregateReward = cachedSyncAggregateReward;

if (blockAttestationReward === 0) {
const parentSlot = isForkPostGloas(fork)
? (preState as CachedBeaconStateGloas).latestExecutionPayloadBid.slot
: null;
blockAttestationReward =
fork === ForkName.phase0
? computeBlockAttestationRewardPhase0(block as phase0.BeaconBlock, preState as CachedBeaconStatePhase0)
: computeBlockAttestationRewardAltair(config, block as altair.BeaconBlock, preState as CachedBeaconStateAltair);
: computeBlockAttestationRewardAltair(
config,
block as altair.BeaconBlock,
preState as CachedBeaconStateAltair,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't apply parent execution payload for preState so executionPayloadAvailability passed in is not correct
but I'd resolve it in a different PR

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I follow correctly, maybe you can make a proposal for that, if you are looking into that right now, can target my branch, I am not sure how to merge this unless we skip a lot of spec tests

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in #9736

parentSlot
);
}

if (syncAggregateReward === 0) {
Expand Down Expand Up @@ -79,12 +93,13 @@ function computeBlockAttestationRewardPhase0(
function computeBlockAttestationRewardAltair(
config: BeaconConfig,
block: altair.BeaconBlock,
preState: CachedBeaconStateAltair
preState: CachedBeaconStateAltair,
parentSlot: Slot | null
): SubRewardValue {
const fork = config.getForkSeq(block.slot);
const {attestations} = block.body;

processAttestationsAltair(fork, preState, attestations, false);
processAttestationsAltair(fork, preState, attestations, parentSlot, false);

return preState.proposerRewards.attestations;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ function translateParticipation(
attestation.inclusionDelay,
epochCtx.epoch,
rootCache,
null,
null
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe("altair processAttestation", () => {
state.config.getForkSeq(state.slot),
state as CachedBeaconStateAltair,
attestations,
null,
false
);
state.commit();
Expand Down
2 changes: 1 addition & 1 deletion spec-tests-version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"ethereumConsensusSpecsTests": {
"specVersion": "v1.7.0-alpha.12",
"specVersion": "v1.7.0-alpha.13",
"specTestsRepoUrl": "https://github.com/ethereum/consensus-specs",
"outputDirBase": "spec-tests",
"testsToDownload": [
Expand Down
Loading
Loading