diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index 29ac446d6390..a2235354d18a 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -5,7 +5,7 @@ import {gnosisPreset} from "./presets/gnosis.js"; import {presetStatus} from "./presetStatus.js"; import {userSelectedPreset, userOverrides} from "./setPreset.js"; -export {BeaconPreset} from "./interface.js"; +export {BeaconPreset} from "./types.js"; export { ForkName, ForkSeq, @@ -39,7 +39,7 @@ presetStatus.frozen = true; */ export const ACTIVE_PRESET = userSelectedPreset ?? PresetName[process?.env?.LODESTAR_PRESET as PresetName] ?? PresetName.mainnet; -export const activePreset = presets[ACTIVE_PRESET]; +export const activePreset = {...presets[ACTIVE_PRESET], ...userOverrides}; // These variables must be exported individually and explicitly // in order to be accessible as top-level exports @@ -99,7 +99,7 @@ export const { FIELD_ELEMENTS_PER_BLOB, MAX_BLOBS_PER_BLOCK, -} = {...presets[ACTIVE_PRESET], ...userOverrides}; +} = activePreset; //////////// // Constants diff --git a/packages/params/src/interface.ts b/packages/params/src/interface.ts deleted file mode 100644 index 41628fd2cf72..000000000000 --- a/packages/params/src/interface.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -export interface BeaconPreset { - // Misc - MAX_COMMITTEES_PER_SLOT: number; - TARGET_COMMITTEE_SIZE: number; - MAX_VALIDATORS_PER_COMMITTEE: number; - - SHUFFLE_ROUND_COUNT: number; - - HYSTERESIS_QUOTIENT: number; - HYSTERESIS_DOWNWARD_MULTIPLIER: number; - HYSTERESIS_UPWARD_MULTIPLIER: number; - - // Gwei Values - MIN_DEPOSIT_AMOUNT: number; - MAX_EFFECTIVE_BALANCE: number; - EFFECTIVE_BALANCE_INCREMENT: number; - - // Time parameters - MIN_ATTESTATION_INCLUSION_DELAY: number; - SLOTS_PER_EPOCH: number; - MIN_SEED_LOOKAHEAD: number; - MAX_SEED_LOOKAHEAD: number; - EPOCHS_PER_ETH1_VOTING_PERIOD: number; - SLOTS_PER_HISTORICAL_ROOT: number; - MIN_EPOCHS_TO_INACTIVITY_PENALTY: number; - - // State vector lengths - EPOCHS_PER_HISTORICAL_VECTOR: number; - EPOCHS_PER_SLASHINGS_VECTOR: number; - HISTORICAL_ROOTS_LIMIT: number; - VALIDATOR_REGISTRY_LIMIT: number; - - // Reward and penalty quotients - BASE_REWARD_FACTOR: number; - WHISTLEBLOWER_REWARD_QUOTIENT: number; - PROPOSER_REWARD_QUOTIENT: number; - INACTIVITY_PENALTY_QUOTIENT: number; - MIN_SLASHING_PENALTY_QUOTIENT: number; - PROPORTIONAL_SLASHING_MULTIPLIER: number; - - // Max operations per block - MAX_PROPOSER_SLASHINGS: number; - MAX_ATTESTER_SLASHINGS: number; - MAX_ATTESTATIONS: number; - MAX_DEPOSITS: number; - MAX_VOLUNTARY_EXITS: number; - - // ALTAIR - ///////// - SYNC_COMMITTEE_SIZE: number; - EPOCHS_PER_SYNC_COMMITTEE_PERIOD: number; - INACTIVITY_PENALTY_QUOTIENT_ALTAIR: number; - MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: number; - PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: number; - MIN_SYNC_COMMITTEE_PARTICIPANTS: number; - UPDATE_TIMEOUT: number; - - // BELLATRIX - //////////// - INACTIVITY_PENALTY_QUOTIENT_BELLATRIX: number; - MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX: number; - PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX: number; - MAX_BYTES_PER_TRANSACTION: number; - MAX_TRANSACTIONS_PER_PAYLOAD: number; - BYTES_PER_LOGS_BLOOM: number; - MAX_EXTRA_DATA_BYTES: number; - - // CAPELLA - ////////// - MAX_BLS_TO_EXECUTION_CHANGES: number; - MAX_WITHDRAWALS_PER_PAYLOAD: number; - MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: number; - - // EIP-4844 - /////////// - FIELD_ELEMENTS_PER_BLOB: number; - MAX_BLOBS_PER_BLOCK: number; -} diff --git a/packages/params/src/json.ts b/packages/params/src/json.ts index 390550f409a6..ffb041cbb63d 100644 --- a/packages/params/src/json.ts +++ b/packages/params/src/json.ts @@ -1,4 +1,4 @@ -import {BeaconPreset} from "./interface.js"; +import {BeaconPreset, beaconPresetTypes} from "./types.js"; /** * Render BeaconPreset to JSON strings @@ -25,14 +25,15 @@ function serializePresetValue(value: number): string { /** * Parse JSON strings of BeaconPreset * - Numbers: Convert quoted decimal string to number - * - * Note: extraneous keys are not filtered out and will be validated */ export function presetFromJson(json: Record): Partial { const beaconPreset = {} as BeaconPreset; - for (const key of Object.keys(json) as (keyof BeaconPreset)[]) { - beaconPreset[key] = deserializePresetValue(json[key], key); + for (const key of Object.keys(beaconPresetTypes) as (keyof BeaconPreset)[]) { + const value = json[key]; + if (value !== undefined) { + beaconPreset[key] = deserializePresetValue(value, key); + } } return beaconPreset; diff --git a/packages/params/src/presets/gnosis.ts b/packages/params/src/presets/gnosis.ts index 4ca9fc897831..284d098b67b4 100644 --- a/packages/params/src/presets/gnosis.ts +++ b/packages/params/src/presets/gnosis.ts @@ -1,4 +1,4 @@ -import {BeaconPreset} from "../interface.js"; +import {BeaconPreset} from "../types.js"; import {mainnetPreset} from "./mainnet.js"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/packages/params/src/presets/mainnet.ts b/packages/params/src/presets/mainnet.ts index 5026858bd934..a53c3912c96b 100644 --- a/packages/params/src/presets/mainnet.ts +++ b/packages/params/src/presets/mainnet.ts @@ -1,4 +1,4 @@ -import {BeaconPreset} from "../interface.js"; +import {BeaconPreset} from "../types.js"; /* eslint-disable @typescript-eslint/naming-convention */ export const mainnetPreset: BeaconPreset = { diff --git a/packages/params/src/presets/minimal.ts b/packages/params/src/presets/minimal.ts index ce2e66b23f99..b04ed6773987 100644 --- a/packages/params/src/presets/minimal.ts +++ b/packages/params/src/presets/minimal.ts @@ -1,4 +1,4 @@ -import {BeaconPreset} from "../interface.js"; +import {BeaconPreset} from "../types.js"; /* eslint-disable @typescript-eslint/naming-convention */ export const minimalPreset: BeaconPreset = { diff --git a/packages/params/src/setPreset.ts b/packages/params/src/setPreset.ts index b8d5b5ded653..61836d86a241 100644 --- a/packages/params/src/setPreset.ts +++ b/packages/params/src/setPreset.ts @@ -1,6 +1,6 @@ import {PresetName} from "./presetName.js"; import {presetStatus} from "./presetStatus.js"; -import {BeaconPreset} from "./interface.js"; +import {BeaconPreset} from "./types.js"; import {presetFromJson} from "./json.js"; export {PresetName, presetFromJson}; diff --git a/packages/params/src/types.ts b/packages/params/src/types.ts new file mode 100644 index 000000000000..c7a47b45107c --- /dev/null +++ b/packages/params/src/types.ts @@ -0,0 +1,170 @@ +/* eslint-disable @typescript-eslint/naming-convention */ + +/** + * Compile-time chain configuration + */ +export type BeaconPreset = { + // Misc + MAX_COMMITTEES_PER_SLOT: number; + TARGET_COMMITTEE_SIZE: number; + MAX_VALIDATORS_PER_COMMITTEE: number; + + SHUFFLE_ROUND_COUNT: number; + + HYSTERESIS_QUOTIENT: number; + HYSTERESIS_DOWNWARD_MULTIPLIER: number; + HYSTERESIS_UPWARD_MULTIPLIER: number; + + // Gwei Values + MIN_DEPOSIT_AMOUNT: number; + MAX_EFFECTIVE_BALANCE: number; + EFFECTIVE_BALANCE_INCREMENT: number; + + // Time parameters + MIN_ATTESTATION_INCLUSION_DELAY: number; + SLOTS_PER_EPOCH: number; + MIN_SEED_LOOKAHEAD: number; + MAX_SEED_LOOKAHEAD: number; + EPOCHS_PER_ETH1_VOTING_PERIOD: number; + SLOTS_PER_HISTORICAL_ROOT: number; + MIN_EPOCHS_TO_INACTIVITY_PENALTY: number; + + // State vector lengths + EPOCHS_PER_HISTORICAL_VECTOR: number; + EPOCHS_PER_SLASHINGS_VECTOR: number; + HISTORICAL_ROOTS_LIMIT: number; + VALIDATOR_REGISTRY_LIMIT: number; + + // Reward and penalty quotients + BASE_REWARD_FACTOR: number; + WHISTLEBLOWER_REWARD_QUOTIENT: number; + PROPOSER_REWARD_QUOTIENT: number; + INACTIVITY_PENALTY_QUOTIENT: number; + MIN_SLASHING_PENALTY_QUOTIENT: number; + PROPORTIONAL_SLASHING_MULTIPLIER: number; + + // Max operations per block + MAX_PROPOSER_SLASHINGS: number; + MAX_ATTESTER_SLASHINGS: number; + MAX_ATTESTATIONS: number; + MAX_DEPOSITS: number; + MAX_VOLUNTARY_EXITS: number; + + // ALTAIR + ///////// + SYNC_COMMITTEE_SIZE: number; + EPOCHS_PER_SYNC_COMMITTEE_PERIOD: number; + INACTIVITY_PENALTY_QUOTIENT_ALTAIR: number; + MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: number; + PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: number; + MIN_SYNC_COMMITTEE_PARTICIPANTS: number; + UPDATE_TIMEOUT: number; + + // BELLATRIX + //////////// + INACTIVITY_PENALTY_QUOTIENT_BELLATRIX: number; + MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX: number; + PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX: number; + MAX_BYTES_PER_TRANSACTION: number; + MAX_TRANSACTIONS_PER_PAYLOAD: number; + BYTES_PER_LOGS_BLOOM: number; + MAX_EXTRA_DATA_BYTES: number; + + // CAPELLA + ////////// + MAX_BLS_TO_EXECUTION_CHANGES: number; + MAX_WITHDRAWALS_PER_PAYLOAD: number; + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: number; + + // EIP-4844 + /////////// + FIELD_ELEMENTS_PER_BLOB: number; + MAX_BLOBS_PER_BLOCK: number; +}; + +/** + * Presets only contain numbers, just used to filter out extraneous keys + * when overriding the active preset with custom values from file + */ +export const beaconPresetTypes: BeaconPresetTypes = { + // Misc + MAX_COMMITTEES_PER_SLOT: "number", + TARGET_COMMITTEE_SIZE: "number", + MAX_VALIDATORS_PER_COMMITTEE: "number", + + SHUFFLE_ROUND_COUNT: "number", + + HYSTERESIS_QUOTIENT: "number", + HYSTERESIS_DOWNWARD_MULTIPLIER: "number", + HYSTERESIS_UPWARD_MULTIPLIER: "number", + + // Gwei Values + MIN_DEPOSIT_AMOUNT: "number", + MAX_EFFECTIVE_BALANCE: "number", + EFFECTIVE_BALANCE_INCREMENT: "number", + + // Time parameters + MIN_ATTESTATION_INCLUSION_DELAY: "number", + SLOTS_PER_EPOCH: "number", + MIN_SEED_LOOKAHEAD: "number", + MAX_SEED_LOOKAHEAD: "number", + EPOCHS_PER_ETH1_VOTING_PERIOD: "number", + SLOTS_PER_HISTORICAL_ROOT: "number", + MIN_EPOCHS_TO_INACTIVITY_PENALTY: "number", + + // State vector lengths + EPOCHS_PER_HISTORICAL_VECTOR: "number", + EPOCHS_PER_SLASHINGS_VECTOR: "number", + HISTORICAL_ROOTS_LIMIT: "number", + VALIDATOR_REGISTRY_LIMIT: "number", + + // Reward and penalty quotients + BASE_REWARD_FACTOR: "number", + WHISTLEBLOWER_REWARD_QUOTIENT: "number", + PROPOSER_REWARD_QUOTIENT: "number", + INACTIVITY_PENALTY_QUOTIENT: "number", + MIN_SLASHING_PENALTY_QUOTIENT: "number", + PROPORTIONAL_SLASHING_MULTIPLIER: "number", + + // Max operations per block + MAX_PROPOSER_SLASHINGS: "number", + MAX_ATTESTER_SLASHINGS: "number", + MAX_ATTESTATIONS: "number", + MAX_DEPOSITS: "number", + MAX_VOLUNTARY_EXITS: "number", + + // ALTAIR + ///////// + SYNC_COMMITTEE_SIZE: "number", + EPOCHS_PER_SYNC_COMMITTEE_PERIOD: "number", + INACTIVITY_PENALTY_QUOTIENT_ALTAIR: "number", + MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: "number", + PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: "number", + MIN_SYNC_COMMITTEE_PARTICIPANTS: "number", + UPDATE_TIMEOUT: "number", + + // BELLATRIX + //////////// + INACTIVITY_PENALTY_QUOTIENT_BELLATRIX: "number", + MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX: "number", + PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX: "number", + MAX_BYTES_PER_TRANSACTION: "number", + MAX_TRANSACTIONS_PER_PAYLOAD: "number", + BYTES_PER_LOGS_BLOOM: "number", + MAX_EXTRA_DATA_BYTES: "number", + + // CAPELLA + ////////// + MAX_BLS_TO_EXECUTION_CHANGES: "number", + MAX_WITHDRAWALS_PER_PAYLOAD: "number", + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: "number", + + // EIP-4844 + /////////// + FIELD_ELEMENTS_PER_BLOB: "number", + MAX_BLOBS_PER_BLOCK: "number", +}; + +type BeaconPresetTypes = { + [K in keyof BeaconPreset]: "number"; +}; diff --git a/packages/params/test/e2e/overridePresetOk.ts b/packages/params/test/e2e/overridePresetOk.ts index 25879c81212a..7373ecee7fff 100644 --- a/packages/params/test/e2e/overridePresetOk.ts +++ b/packages/params/test/e2e/overridePresetOk.ts @@ -2,7 +2,7 @@ import assert from "node:assert"; /* eslint import/order: "off" */ // This script is should be run in an e2e !! -// It demostrates how to properly change the Lodestar preset safely +// It demonstrates how to properly change the Lodestar preset safely // 1. Import from @lodestar/params/setPreset only import {setActivePreset, PresetName} from "../../src/setPreset.js"; @@ -11,8 +11,10 @@ setActivePreset(PresetName.minimal, {SLOTS_PER_EPOCH: 2}); // 2. Import from any other @lodestar/params paths -const {SLOTS_PER_EPOCH, BASE_REWARD_FACTOR} = await import("../../src/index.js"); +const {activePreset, SLOTS_PER_EPOCH, BASE_REWARD_FACTOR} = await import("../../src/index.js"); -assert.equal(SLOTS_PER_EPOCH, 2, "SLOTS_PER_EPOCH should have overriden preset value"); +assert.equal(SLOTS_PER_EPOCH, 2, "SLOTS_PER_EPOCH should have overridden preset value"); +assert.equal(activePreset.SLOTS_PER_EPOCH, 2, "activePreset.SLOTS_PER_EPOCH should have overridden preset value"); assert.equal(BASE_REWARD_FACTOR, 64, "BASE_REWARD_FACTOR should have preset value"); +assert.equal(activePreset.BASE_REWARD_FACTOR, 64, "activePreset.BASE_REWARD_FACTOR should have preset value"); assert.equal(process.env.LODESTAR_PRESET, undefined, "LODESTAR_PRESET ENV must not be set");