From b52cc8cd54154f87057e7007933b4069ca88a416 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 14 Sep 2023 17:10:02 +0200 Subject: [PATCH 1/7] Add max activation churn limit --- packages/config/src/chainConfig/presets/mainnet.ts | 1 + packages/config/src/chainConfig/presets/minimal.ts | 1 + packages/config/src/chainConfig/types.ts | 1 + packages/state-transition/src/cache/epochCache.ts | 5 +++++ .../state-transition/src/epoch/processRegistryUpdates.ts | 2 +- packages/state-transition/src/util/validator.ts | 9 +++++++++ 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/config/src/chainConfig/presets/mainnet.ts b/packages/config/src/chainConfig/presets/mainnet.ts index dcce1d82cf9b..72cbaef39a3a 100644 --- a/packages/config/src/chainConfig/presets/mainnet.ts +++ b/packages/config/src/chainConfig/presets/mainnet.ts @@ -68,6 +68,7 @@ export const chainConfig: ChainConfig = { EJECTION_BALANCE: 16000000000, // 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4, + MAX_PER_EPOCH_CHURN_LIMIT: 8, // 2**16 (= 65,536) CHURN_LIMIT_QUOTIENT: 65536, PROPOSER_SCORE_BOOST: 40, diff --git a/packages/config/src/chainConfig/presets/minimal.ts b/packages/config/src/chainConfig/presets/minimal.ts index fc72cbff72de..ae64befc7665 100644 --- a/packages/config/src/chainConfig/presets/minimal.ts +++ b/packages/config/src/chainConfig/presets/minimal.ts @@ -66,6 +66,7 @@ export const chainConfig: ChainConfig = { EJECTION_BALANCE: 16000000000, // 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4, + MAX_PER_EPOCH_CHURN_LIMIT: 8, // [customized] scale queue churn at much lower validator counts for testing CHURN_LIMIT_QUOTIENT: 32, PROPOSER_SCORE_BOOST: 40, diff --git a/packages/config/src/chainConfig/types.ts b/packages/config/src/chainConfig/types.ts index b2568d6fba57..5a1c9487bef0 100644 --- a/packages/config/src/chainConfig/types.ts +++ b/packages/config/src/chainConfig/types.ts @@ -53,6 +53,7 @@ export type ChainConfig = { INACTIVITY_SCORE_RECOVERY_RATE: number; EJECTION_BALANCE: number; MIN_PER_EPOCH_CHURN_LIMIT: number; + MAX_PER_EPOCH_CHURN_LIMIT: number; CHURN_LIMIT_QUOTIENT: number; // Proposer boost diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index aeefc4769aca..94cd24acefc9 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -24,6 +24,7 @@ import { computeSyncPeriodAtEpoch, getSeed, computeProposers, + getActivationChurnLimit, } from "../util/index.js"; import {computeEpochShuffling, EpochShuffling} from "../util/epochShuffling.js"; import {computeBaseRewardPerIncrement, computeSyncParticipantReward} from "../util/syncCommittee.js"; @@ -204,6 +205,7 @@ export class EpochCache { baseRewardPerIncrement: number; totalActiveBalanceIncrements: number; churnLimit: number; + activationChurnLimit: number; exitQueueEpoch: Epoch; exitQueueChurn: number; currentTargetUnslashedBalanceIncrements: number; @@ -405,6 +407,7 @@ export class EpochCache { baseRewardPerIncrement, totalActiveBalanceIncrements, churnLimit, + activationChurnLimit, exitQueueEpoch, exitQueueChurn, previousTargetUnslashedBalanceIncrements, @@ -444,6 +447,7 @@ export class EpochCache { baseRewardPerIncrement: this.baseRewardPerIncrement, totalActiveBalanceIncrements: this.totalActiveBalanceIncrements, churnLimit: this.churnLimit, + activationChurnLimit: this.activationChurnLimit, exitQueueEpoch: this.exitQueueEpoch, exitQueueChurn: this.exitQueueChurn, previousTargetUnslashedBalanceIncrements: this.previousTargetUnslashedBalanceIncrements, @@ -503,6 +507,7 @@ export class EpochCache { // the first block of the epoch process_block() call. So churnLimit must be computed at the end of the before epoch // transition and the result is valid until the end of the next epoch transition this.churnLimit = getChurnLimit(this.config, this.currentShuffling.activeIndices.length); + this.activationChurnLimit = getActivationChurnLimit(this.config, this.config.getForkSeq(state.slot), this.currentShuffling.activeIndices.length); // Maybe advance exitQueueEpoch at the end of the epoch if there haven't been any exists for a while const exitQueueEpoch = computeActivationExitEpoch(currEpoch); diff --git a/packages/state-transition/src/epoch/processRegistryUpdates.ts b/packages/state-transition/src/epoch/processRegistryUpdates.ts index 831b3cd80550..0591f982d1d5 100644 --- a/packages/state-transition/src/epoch/processRegistryUpdates.ts +++ b/packages/state-transition/src/epoch/processRegistryUpdates.ts @@ -38,7 +38,7 @@ export function processRegistryUpdates(state: CachedBeaconStateAllForks, cache: const finalityEpoch = state.finalizedCheckpoint.epoch; // dequeue validators for activation up to churn limit - for (const index of cache.indicesEligibleForActivation.slice(0, epochCtx.churnLimit)) { + for (const index of cache.indicesEligibleForActivation.slice(0, epochCtx.activationChurnLimit)) { const validator = validators.get(index); // placement in queue is finalized if (validator.activationEligibilityEpoch > finalityEpoch) { diff --git a/packages/state-transition/src/util/validator.ts b/packages/state-transition/src/util/validator.ts index 958fa0a157af..8f101eb9f23b 100644 --- a/packages/state-transition/src/util/validator.ts +++ b/packages/state-transition/src/util/validator.ts @@ -2,6 +2,7 @@ import {Epoch, phase0, ValidatorIndex} from "@lodestar/types"; import {intDiv} from "@lodestar/utils"; import {ChainForkConfig} from "@lodestar/config"; import {BeaconStateAllForks} from "../types.js"; +import { ForkSeq } from "@lodestar/params"; /** * Check if [[validator]] is active @@ -35,6 +36,14 @@ export function getActiveValidatorIndices(state: BeaconStateAllForks, epoch: Epo return indices; } +export function getActivationChurnLimit(config: ChainForkConfig, fork: ForkSeq, activeValidatorCount: number): number { + if (fork >= ForkSeq.deneb) { + return Math.min(config.MAX_PER_EPOCH_CHURN_LIMIT, getChurnLimit(config, activeValidatorCount)); + } else { + return getChurnLimit(config, activeValidatorCount); + } +} + export function getChurnLimit(config: ChainForkConfig, activeValidatorCount: number): number { return Math.max(config.MIN_PER_EPOCH_CHURN_LIMIT, intDiv(activeValidatorCount, config.CHURN_LIMIT_QUOTIENT)); } From 5bc30172e4d91e827eabdc2f9d7eccbff60a9337 Mon Sep 17 00:00:00 2001 From: harkamal Date: Tue, 26 Sep 2023 22:24:40 +0530 Subject: [PATCH 2/7] fixes for branch and update spec version --- .../beacon-node/test/spec/specTestVersioning.ts | 2 +- packages/config/src/chainConfig/types.ts | 1 + .../test/e2e/ensure-config-is-synced.test.ts | 2 +- .../state-transition/src/cache/epochCache.ts | 17 ++++++++++++++++- packages/state-transition/src/util/validator.ts | 2 +- packages/validator/src/util/params.ts | 1 + 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/beacon-node/test/spec/specTestVersioning.ts b/packages/beacon-node/test/spec/specTestVersioning.ts index ff24be32ee34..3f1aad878e65 100644 --- a/packages/beacon-node/test/spec/specTestVersioning.ts +++ b/packages/beacon-node/test/spec/specTestVersioning.ts @@ -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.4.0-beta.1", + specVersion: "v1.4.0-beta.2-hotfix", // Target directory is the host package root: 'packages/*/spec-tests' outputDir: path.join(__dirname, "../../spec-tests"), specTestsRepoUrl: "https://github.com/ethereum/consensus-spec-tests", diff --git a/packages/config/src/chainConfig/types.ts b/packages/config/src/chainConfig/types.ts index 5a1c9487bef0..adb85f12afae 100644 --- a/packages/config/src/chainConfig/types.ts +++ b/packages/config/src/chainConfig/types.ts @@ -106,6 +106,7 @@ export const chainConfigTypes: SpecTypes = { INACTIVITY_SCORE_RECOVERY_RATE: "number", EJECTION_BALANCE: "number", MIN_PER_EPOCH_CHURN_LIMIT: "number", + MAX_PER_EPOCH_CHURN_LIMIT: "number", CHURN_LIMIT_QUOTIENT: "number", // Proposer boost diff --git a/packages/params/test/e2e/ensure-config-is-synced.test.ts b/packages/params/test/e2e/ensure-config-is-synced.test.ts index 774e06fad8be..6be3e6e15db1 100644 --- a/packages/params/test/e2e/ensure-config-is-synced.test.ts +++ b/packages/params/test/e2e/ensure-config-is-synced.test.ts @@ -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.4.0-beta.1"; +const specConfigCommit = "v1.4.0-beta.2"; describe("Ensure config is synced", function () { this.timeout(60 * 1000); diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index 94cd24acefc9..9892de37a569 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -146,6 +146,11 @@ export class EpochCache { * change through the epoch. It's used in initiateValidatorExit(). Must be update after changing active indexes. */ churnLimit: number; + + /** + * Fork limited actual activationChurnLimit + */ + activationChurnLimit: number; /** * Closest epoch with available churn for validators to exit at. May be updated every block as validators are * initiateValidatorExit(). This value may vary on each fork of the state. @@ -230,6 +235,7 @@ export class EpochCache { this.baseRewardPerIncrement = data.baseRewardPerIncrement; this.totalActiveBalanceIncrements = data.totalActiveBalanceIncrements; this.churnLimit = data.churnLimit; + this.activationChurnLimit = data.activationChurnLimit; this.exitQueueEpoch = data.exitQueueEpoch; this.exitQueueChurn = data.exitQueueChurn; this.currentTargetUnslashedBalanceIncrements = data.currentTargetUnslashedBalanceIncrements; @@ -366,6 +372,11 @@ export class EpochCache { // the first block of the epoch process_block() call. So churnLimit must be computed at the end of the before epoch // transition and the result is valid until the end of the next epoch transition const churnLimit = getChurnLimit(config, currentShuffling.activeIndices.length); + const activationChurnLimit = getActivationChurnLimit( + config, + config.getForkSeq(state.slot), + currentShuffling.activeIndices.length + ); if (exitQueueChurn >= churnLimit) { exitQueueEpoch += 1; exitQueueChurn = 0; @@ -507,7 +518,11 @@ export class EpochCache { // the first block of the epoch process_block() call. So churnLimit must be computed at the end of the before epoch // transition and the result is valid until the end of the next epoch transition this.churnLimit = getChurnLimit(this.config, this.currentShuffling.activeIndices.length); - this.activationChurnLimit = getActivationChurnLimit(this.config, this.config.getForkSeq(state.slot), this.currentShuffling.activeIndices.length); + this.activationChurnLimit = getActivationChurnLimit( + this.config, + this.config.getForkSeq(state.slot), + this.currentShuffling.activeIndices.length + ); // Maybe advance exitQueueEpoch at the end of the epoch if there haven't been any exists for a while const exitQueueEpoch = computeActivationExitEpoch(currEpoch); diff --git a/packages/state-transition/src/util/validator.ts b/packages/state-transition/src/util/validator.ts index 8f101eb9f23b..b6ae9c976ff2 100644 --- a/packages/state-transition/src/util/validator.ts +++ b/packages/state-transition/src/util/validator.ts @@ -1,8 +1,8 @@ import {Epoch, phase0, ValidatorIndex} from "@lodestar/types"; import {intDiv} from "@lodestar/utils"; import {ChainForkConfig} from "@lodestar/config"; +import {ForkSeq} from "@lodestar/params"; import {BeaconStateAllForks} from "../types.js"; -import { ForkSeq } from "@lodestar/params"; /** * Check if [[validator]] is active diff --git a/packages/validator/src/util/params.ts b/packages/validator/src/util/params.ts index 61034c133028..775a71ae1d1d 100644 --- a/packages/validator/src/util/params.ts +++ b/packages/validator/src/util/params.ts @@ -118,6 +118,7 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record Date: Tue, 26 Sep 2023 22:52:23 +0530 Subject: [PATCH 3/7] only proposerboost the first block we see --- packages/fork-choice/src/forkChoice/forkChoice.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/fork-choice/src/forkChoice/forkChoice.ts b/packages/fork-choice/src/forkChoice/forkChoice.ts index 04beeef02585..ef859a239dc5 100644 --- a/packages/fork-choice/src/forkChoice/forkChoice.ts +++ b/packages/fork-choice/src/forkChoice/forkChoice.ts @@ -357,7 +357,9 @@ export class ForkChoice implements IForkChoice { if ( this.opts?.proposerBoostEnabled && this.fcStore.currentSlot === slot && - blockDelaySec < this.config.SECONDS_PER_SLOT / INTERVALS_PER_SLOT + blockDelaySec < this.config.SECONDS_PER_SLOT / INTERVALS_PER_SLOT && + // only boost the first block we see + this.proposerBoostRoot === null ) { this.proposerBoostRoot = blockRootHex; } From 6e3347f7fdc1d33ed7c2d57c982766b2ccce2b42 Mon Sep 17 00:00:00 2001 From: harkamal Date: Wed, 27 Sep 2023 19:27:16 +0530 Subject: [PATCH 4/7] update the forkchoice tests to handle blob spec data --- .../test/spec/presets/fork_choice.test.ts | 50 +++++++++++++++---- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/packages/beacon-node/test/spec/presets/fork_choice.test.ts b/packages/beacon-node/test/spec/presets/fork_choice.test.ts index 7212745c3ff1..e34095911ee8 100644 --- a/packages/beacon-node/test/spec/presets/fork_choice.test.ts +++ b/packages/beacon-node/test/spec/presets/fork_choice.test.ts @@ -4,8 +4,8 @@ import {toHexString} from "@chainsafe/ssz"; import {BeaconStateAllForks, isExecutionStateType} from "@lodestar/state-transition"; import {InputType} from "@lodestar/spec-test-util"; import {CheckpointWithHex, ForkChoice} from "@lodestar/fork-choice"; -import {phase0, allForks, bellatrix, ssz, RootHex} from "@lodestar/types"; -import {bnToNum} from "@lodestar/utils"; +import {phase0, allForks, bellatrix, ssz, RootHex, deneb} from "@lodestar/types"; +import {bnToNum, fromHex} from "@lodestar/utils"; import {createBeaconConfig} from "@lodestar/config"; import {ACTIVE_PRESET, ForkSeq, isForkBlobs} from "@lodestar/params"; import {BeaconChain} from "../../../src/chain/index.js"; @@ -34,6 +34,7 @@ import {specTestIterator} from "../utils/specTestIterator.js"; const ANCHOR_STATE_FILE_NAME = "anchor_state"; const ANCHOR_BLOCK_FILE_NAME = "anchor_block"; const BLOCK_FILE_NAME = "^(block)_([0-9a-zA-Z]+)$"; +const BLOBS_FILE_NAME = "^(blobs)_([0-9a-zA-Z]+)$"; const POW_BLOCK_FILE_NAME = "^(pow_block)_([0-9a-zA-Z]+)$"; const ATTESTATION_FILE_NAME = "^(attestation)_([0-9a-zA-Z])+$"; const ATTESTER_SLASHING_FILE_NAME = "^(attester_slashing)_([0-9a-zA-Z])+$"; @@ -147,6 +148,16 @@ const forkChoiceTest = throw Error(`No block ${step.block}`); } + let blobs: deneb.Blobs = []; + let proofs: deneb.KZGProofs = []; + if (step.blobs !== undefined) { + blobs = testcase.blobs.get(step.blobs); + if (blobs === undefined) { + throw Error(`Blobs not loaded ${step.blobs}`); + } + proofs = step.proofs.map((proof) => ssz.deneb.KZGProof.deserialize(fromHex(proof))); + } + const {slot} = signedBlock.message; // Log the BeaconBlock root instead of the SignedBeaconBlock root, forkchoice references BeaconBlock roots const blockRoot = config @@ -163,16 +174,18 @@ const forkChoiceTest = const blockImport = config.getForkSeq(slot) < ForkSeq.deneb ? getBlockInput.preDeneb(config, signedBlock, BlockSource.gossip, null) - : getBlockInput.postDeneb( - config, - signedBlock, - BlockSource.gossip, - ssz.deneb.BlobSidecars.defaultValue(), - null, - [null] - ); + : getBlockInput.postDeneb(config, signedBlock, BlockSource.gossip, blobs, null, [null]); try { + if (config.getForkSeq(slot) >= ForkSeq.deneb) { + // the kzg lib for validation of minimal setup is not yet integrated, lets just verify lengths + // post integration use validateBlobsAndProofs + const commitments = (signedBlock as deneb.SignedBeaconBlock).message.body.blobKzgCommitments; + if (blobs.length !== commitments.length || proofs.length !== commitments.length) { + throw Error("Invalid blobs or proofs lengths"); + } + } + await chain.processBlock(blockImport, { seenTimestampSec: tickTime, validBlobSidecars: true, @@ -276,6 +289,7 @@ const forkChoiceTest = [ANCHOR_STATE_FILE_NAME]: ssz[fork].BeaconState, [ANCHOR_BLOCK_FILE_NAME]: ssz[fork].BeaconBlock, [BLOCK_FILE_NAME]: ssz[fork].SignedBeaconBlock, + [BLOBS_FILE_NAME]: ssz.deneb.Blobs, [POW_BLOCK_FILE_NAME]: ssz.bellatrix.PowBlock, [ATTESTATION_FILE_NAME]: ssz.phase0.Attestation, [ATTESTER_SLASHING_FILE_NAME]: ssz.phase0.AttesterSlashing, @@ -283,6 +297,7 @@ const forkChoiceTest = mapToTestCase: (t: Record) => { // t has input file name as key const blocks = new Map(); + const blobs = new Map(); const powBlocks = new Map(); const attestations = new Map(); const attesterSlashings = new Map(); @@ -291,6 +306,10 @@ const forkChoiceTest = if (blockMatch) { blocks.set(key, t[key]); } + const blobsMatch = key.match(BLOBS_FILE_NAME); + if (blobsMatch) { + blobs.set(key, t[key]); + } const powBlockMatch = key.match(POW_BLOCK_FILE_NAME); if (powBlockMatch) { powBlocks.set(key, t[key]); @@ -310,6 +329,7 @@ const forkChoiceTest = anchorBlock: t[ANCHOR_BLOCK_FILE_NAME] as ForkChoiceTestCase["anchorBlock"], steps: t["steps"] as ForkChoiceTestCase["steps"], blocks, + blobs, powBlocks, attestations, attesterSlashings, @@ -319,6 +339,13 @@ const forkChoiceTest = // eslint-disable-next-line @typescript-eslint/no-empty-function expectFunc: () => {}, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts + // EXCEPTION : this test skipped here because prefix match can't be don't for this particular test + // as testId for the entire directory is same : `deneb/fork_choice/on_block/pyspec_tests` and + // we just want to skip this one particular test because we don't have minimal kzg lib integrated + // + // This skip can be removed once c-kzg lib with run-time minimal blob size setup is released and + // integrated + shouldSkip: (_testcase, name, _index) => name.includes("invalid_incorrect_proof"), }, }; }; @@ -364,6 +391,8 @@ type OnAttesterSlashing = { type OnBlock = { /** the name of the `block_<32-byte-root>.ssz_snappy` file. To execute `on_block(store, block)` */ block: string; + blobs?: string; + proofs?: string[]; /** optional, default to `true`. */ valid?: number; }; @@ -412,6 +441,7 @@ type ForkChoiceTestCase = { anchorBlock: allForks.BeaconBlock; steps: Step[]; blocks: Map; + blobs: Map; powBlocks: Map; attestations: Map; attesterSlashings: Map; From 1c303fc0b74c5df82d9ec1a80e3740e17f8786d9 Mon Sep 17 00:00:00 2001 From: harkamal Date: Wed, 27 Sep 2023 21:44:28 +0530 Subject: [PATCH 5/7] update minimal param --- packages/config/src/chainConfig/presets/minimal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/config/src/chainConfig/presets/minimal.ts b/packages/config/src/chainConfig/presets/minimal.ts index ae64befc7665..8fc8c7715648 100644 --- a/packages/config/src/chainConfig/presets/minimal.ts +++ b/packages/config/src/chainConfig/presets/minimal.ts @@ -65,7 +65,7 @@ export const chainConfig: ChainConfig = { // 2**4 * 10**9 (= 16,000,000,000) Gwei EJECTION_BALANCE: 16000000000, // 2**2 (= 4) - MIN_PER_EPOCH_CHURN_LIMIT: 4, + MIN_PER_EPOCH_CHURN_LIMIT: 2, MAX_PER_EPOCH_CHURN_LIMIT: 8, // [customized] scale queue churn at much lower validator counts for testing CHURN_LIMIT_QUOTIENT: 32, From 1d55b82a8bd486196f94b0b778fda115644a75ff Mon Sep 17 00:00:00 2001 From: harkamal Date: Wed, 27 Sep 2023 22:07:14 +0530 Subject: [PATCH 6/7] update the churn limit name and the minimal params --- packages/config/src/chainConfig/presets/mainnet.ts | 2 +- packages/config/src/chainConfig/presets/minimal.ts | 2 +- packages/config/src/chainConfig/types.ts | 4 ++-- packages/state-transition/src/util/validator.ts | 2 +- packages/validator/src/util/params.ts | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/config/src/chainConfig/presets/mainnet.ts b/packages/config/src/chainConfig/presets/mainnet.ts index 72cbaef39a3a..2c02643a032c 100644 --- a/packages/config/src/chainConfig/presets/mainnet.ts +++ b/packages/config/src/chainConfig/presets/mainnet.ts @@ -68,7 +68,7 @@ export const chainConfig: ChainConfig = { EJECTION_BALANCE: 16000000000, // 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4, - MAX_PER_EPOCH_CHURN_LIMIT: 8, + MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8, // 2**16 (= 65,536) CHURN_LIMIT_QUOTIENT: 65536, PROPOSER_SCORE_BOOST: 40, diff --git a/packages/config/src/chainConfig/presets/minimal.ts b/packages/config/src/chainConfig/presets/minimal.ts index 8fc8c7715648..d790032bcee1 100644 --- a/packages/config/src/chainConfig/presets/minimal.ts +++ b/packages/config/src/chainConfig/presets/minimal.ts @@ -66,7 +66,7 @@ export const chainConfig: ChainConfig = { EJECTION_BALANCE: 16000000000, // 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 2, - MAX_PER_EPOCH_CHURN_LIMIT: 8, + MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 4, // [customized] scale queue churn at much lower validator counts for testing CHURN_LIMIT_QUOTIENT: 32, PROPOSER_SCORE_BOOST: 40, diff --git a/packages/config/src/chainConfig/types.ts b/packages/config/src/chainConfig/types.ts index adb85f12afae..4818ef9ee0aa 100644 --- a/packages/config/src/chainConfig/types.ts +++ b/packages/config/src/chainConfig/types.ts @@ -53,7 +53,7 @@ export type ChainConfig = { INACTIVITY_SCORE_RECOVERY_RATE: number; EJECTION_BALANCE: number; MIN_PER_EPOCH_CHURN_LIMIT: number; - MAX_PER_EPOCH_CHURN_LIMIT: number; + MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: number; CHURN_LIMIT_QUOTIENT: number; // Proposer boost @@ -106,7 +106,7 @@ export const chainConfigTypes: SpecTypes = { INACTIVITY_SCORE_RECOVERY_RATE: "number", EJECTION_BALANCE: "number", MIN_PER_EPOCH_CHURN_LIMIT: "number", - MAX_PER_EPOCH_CHURN_LIMIT: "number", + MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: "number", CHURN_LIMIT_QUOTIENT: "number", // Proposer boost diff --git a/packages/state-transition/src/util/validator.ts b/packages/state-transition/src/util/validator.ts index b6ae9c976ff2..99f1e6fa0b19 100644 --- a/packages/state-transition/src/util/validator.ts +++ b/packages/state-transition/src/util/validator.ts @@ -38,7 +38,7 @@ export function getActiveValidatorIndices(state: BeaconStateAllForks, epoch: Epo export function getActivationChurnLimit(config: ChainForkConfig, fork: ForkSeq, activeValidatorCount: number): number { if (fork >= ForkSeq.deneb) { - return Math.min(config.MAX_PER_EPOCH_CHURN_LIMIT, getChurnLimit(config, activeValidatorCount)); + return Math.min(config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, getChurnLimit(config, activeValidatorCount)); } else { return getChurnLimit(config, activeValidatorCount); } diff --git a/packages/validator/src/util/params.ts b/packages/validator/src/util/params.ts index 775a71ae1d1d..37908afaf86c 100644 --- a/packages/validator/src/util/params.ts +++ b/packages/validator/src/util/params.ts @@ -118,7 +118,7 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record Date: Thu, 28 Sep 2023 21:24:35 +0530 Subject: [PATCH 7/7] fix issue with spec types --- .../test/spec/presets/fork_choice.test.ts | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/packages/beacon-node/test/spec/presets/fork_choice.test.ts b/packages/beacon-node/test/spec/presets/fork_choice.test.ts index e34095911ee8..7f7548a6fc16 100644 --- a/packages/beacon-node/test/spec/presets/fork_choice.test.ts +++ b/packages/beacon-node/test/spec/presets/fork_choice.test.ts @@ -148,13 +148,12 @@ const forkChoiceTest = throw Error(`No block ${step.block}`); } - let blobs: deneb.Blobs = []; - let proofs: deneb.KZGProofs = []; + let blobs: deneb.Blob[] | undefined; + let proofs: deneb.KZGProof[] | undefined; if (step.blobs !== undefined) { blobs = testcase.blobs.get(step.blobs); - if (blobs === undefined) { - throw Error(`Blobs not loaded ${step.blobs}`); - } + } + if (step.proofs !== undefined) { proofs = step.proofs.map((proof) => ssz.deneb.KZGProof.deserialize(fromHex(proof))); } @@ -171,19 +170,48 @@ const forkChoiceTest = isValid, }); - const blockImport = - config.getForkSeq(slot) < ForkSeq.deneb - ? getBlockInput.preDeneb(config, signedBlock, BlockSource.gossip, null) - : getBlockInput.postDeneb(config, signedBlock, BlockSource.gossip, blobs, null, [null]); - try { + let blockImport; if (config.getForkSeq(slot) >= ForkSeq.deneb) { + if (blobs === undefined) { + // seems like some deneb tests don't have this and we are supposed to assume empty + // throw Error("Missing blobs for the deneb+ block"); + blobs = []; + } + if (proofs === undefined) { + // seems like some deneb tests don't have this and we are supposed to assume empty + // throw Error("proofs for the deneb+ block"); + proofs = []; + } // the kzg lib for validation of minimal setup is not yet integrated, lets just verify lengths // post integration use validateBlobsAndProofs const commitments = (signedBlock as deneb.SignedBeaconBlock).message.body.blobKzgCommitments; if (blobs.length !== commitments.length || proofs.length !== commitments.length) { throw Error("Invalid blobs or proofs lengths"); } + + const blockRoot = config + .getForkTypes(signedBlock.message.slot) + .BeaconBlock.hashTreeRoot(signedBlock.message); + const blobSidecars: deneb.BlobSidecars = blobs.map((blob, index) => { + return { + blockRoot, + index, + slot, + blob, + // proofs isn't undefined here but typescript(check types) can't figure it out + kzgProof: (proofs ?? [])[index], + kzgCommitment: commitments[index], + blockParentRoot: signedBlock.message.parentRoot, + proposerIndex: signedBlock.message.proposerIndex, + }; + }); + + blockImport = getBlockInput.postDeneb(config, signedBlock, BlockSource.gossip, blobSidecars, null, [ + null, + ]); + } else { + blockImport = getBlockInput.preDeneb(config, signedBlock, BlockSource.gossip, null); } await chain.processBlock(blockImport, {