diff --git a/beacon_chain/beacon_clock.nim b/beacon_chain/beacon_clock.nim index 138f5fe557..cdda0323fd 100644 --- a/beacon_chain/beacon_clock.nim +++ b/beacon_chain/beacon_clock.nim @@ -41,6 +41,9 @@ proc init*( T: type BeaconClock, timeParams: TimeParams, genesis_time: uint64): Opt[T] = + if not timeParams.isValid: + return Opt.none(BeaconClock) + let MIN_GENESIS_TIME = GENESIS_SLOT * timeParams.SLOT_DURATION.seconds.uint64 MAX_GENESIS_TIME = @@ -48,20 +51,18 @@ proc init*( # the time can't be outrageously far from now getTime().toUnix().uint64 + 100'u64 * 365'u64 * 24'u64 * 60'u64 * 60'u64 - if timeParams.SLOT_DURATION notin MIN_SLOT_DURATION .. MAX_SLOT_DURATION or - genesis_time notin MIN_GENESIS_TIME .. MAX_GENESIS_TIME: - Opt.none(BeaconClock) - else: - let - unixGenesis = fromUnix(genesis_time.int64) - # GENESIS_SLOT offsets slot time, but to simplify calculations, we apply - # that offset to genesis instead of applying it at every time conversion - unixGenesisOffset = fromUnix( - (GENESIS_SLOT.int64 * timeParams.SLOT_DURATION).seconds) - - Opt.some T( - timeParams: timeParams, - genesis: (unixGenesis - unixGenesisOffset).inSeconds.fromUnix) + if genesis_time notin MIN_GENESIS_TIME .. MAX_GENESIS_TIME: + return Opt.none(BeaconClock) + + let + unixGenesis = fromUnix(genesis_time.int64) + # GENESIS_SLOT offsets slot time, but to simplify calculations, we apply + # that offset to genesis instead of applying it at every time conversion + unixGenesisOffset = fromUnix( + (GENESIS_SLOT.int64 * timeParams.SLOT_DURATION).seconds) + Opt.some T( + timeParams: timeParams, + genesis: (unixGenesis - unixGenesisOffset).inSeconds.fromUnix) func timeParams*(c: BeaconClock): TimeParams = c.timeParams # Readonly diff --git a/beacon_chain/rpc/rest_config_api.nim b/beacon_chain/rpc/rest_config_api.nim index ced0a6f6df..e82c4a8e07 100644 --- a/beacon_chain/rpc/rest_config_api.nim +++ b/beacon_chain/rpc/rest_config_api.nim @@ -223,6 +223,17 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = Base10.toString(cfg.SHARD_COMMITTEE_PERIOD), ETH1_FOLLOW_DISTANCE: Base10.toString(cfg.ETH1_FOLLOW_DISTANCE), + PROPOSER_REORG_CUTOFF_BPS: + Base10.toString(cfg.timeParams.PROPOSER_REORG_CUTOFF_BPS), + ATTESTATION_DUE_BPS: + Base10.toString(cfg.timeParams.ATTESTATION_DUE_BPS), + AGGREGATE_DUE_BPS: + Base10.toString(cfg.timeParams.AGGREGATE_DUE_BPS), + + SYNC_MESSAGE_DUE_BPS: + Base10.toString(cfg.timeParams.SYNC_MESSAGE_DUE_BPS), + CONTRIBUTION_DUE_BPS: + Base10.toString(cfg.timeParams.CONTRIBUTION_DUE_BPS), INACTIVITY_SCORE_BIAS: Base10.toString(cfg.INACTIVITY_SCORE_BIAS), diff --git a/beacon_chain/spec/beacon_time.nim b/beacon_chain/spec/beacon_time.nim index 8393422772..cd7c16323c 100644 --- a/beacon_chain/spec/beacon_time.nim +++ b/beacon_chain/spec/beacon_time.nim @@ -43,9 +43,6 @@ const GENESIS_SLOT* = Slot(0) GENESIS_EPOCH* = Epoch(0) # compute_epoch_at_slot(GENESIS_SLOT) - # https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.0/specs/phase0/fork-choice.md#constant - INTERVALS_PER_SLOT* = 3 - func FAR_FUTURE_BEACON_TIME(timeParams: TimeParams): BeaconTime = # Ensure all representable slots are complete BeaconTime(ns_since_genesis: @@ -141,35 +138,33 @@ template `+`*(a: TimeDiff, b: Duration): TimeDiff = # Offsets from the start of the slot to when the corresponding message should # be sent +func slotOffset(timeParams: TimeParams, bps: uint16): TimeDiff = + let oneBps = timeParams.SLOT_DURATION.nanoseconds div MAX_BPS.int64 + TimeDiff(nanoseconds: bps.int64 * oneBps) + # https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.2/specs/phase0/validator.md#attesting func attestationSlotOffset*(timeParams: TimeParams): TimeDiff = - TimeDiff(nanoseconds: - timeParams.SLOT_DURATION.nanoseconds.int64 div INTERVALS_PER_SLOT) + timeParams.slotOffset(timeParams.ATTESTATION_DUE_BPS) # https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.2/specs/phase0/validator.md#broadcast-aggregate func aggregateSlotOffset*(timeParams: TimeParams): TimeDiff = - TimeDiff(nanoseconds: - timeParams.SLOT_DURATION.nanoseconds.int64 * 2 div INTERVALS_PER_SLOT) + timeParams.slotOffset(timeParams.AGGREGATE_DUE_BPS) # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.10/specs/altair/validator.md#prepare-sync-committee-message func syncCommitteeMessageSlotOffset*(timeParams: TimeParams): TimeDiff = - TimeDiff(nanoseconds: - timeParams.SLOT_DURATION.nanoseconds.int64 div INTERVALS_PER_SLOT) + timeParams.slotOffset(timeParams.SYNC_MESSAGE_DUE_BPS) # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.10/specs/altair/validator.md#broadcast-sync-committee-contribution func syncContributionSlotOffset*(timeParams: TimeParams): TimeDiff = - TimeDiff(nanoseconds: - timeParams.SLOT_DURATION.nanoseconds.int64 * 2 div INTERVALS_PER_SLOT) + timeParams.slotOffset(timeParams.CONTRIBUTION_DUE_BPS) # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/specs/altair/light-client/p2p-interface.md#sync-committee func lightClientFinalityUpdateSlotOffset*(timeParams: TimeParams): TimeDiff = - TimeDiff(nanoseconds: - timeParams.SLOT_DURATION.nanoseconds.int64 div INTERVALS_PER_SLOT) + timeParams.syncCommitteeMessageSlotOffset # https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.3/specs/altair/light-client/p2p-interface.md#sync-committee func lightClientOptimisticUpdateSlotOffset*(timeParams: TimeParams): TimeDiff = - TimeDiff(nanoseconds: - timeParams.SLOT_DURATION.nanoseconds.int64 div INTERVALS_PER_SLOT) + timeParams.syncCommitteeMessageSlotOffset func toFloatSeconds*(t: TimeDiff): float = float(t.nanoseconds) / 1_000_000_000.0 diff --git a/beacon_chain/spec/presets.nim b/beacon_chain/spec/presets.nim index 4f87975b5c..b56d6eff43 100644 --- a/beacon_chain/spec/presets.nim +++ b/beacon_chain/spec/presets.nim @@ -36,21 +36,34 @@ const MAX_SUPPORTED_BLOBS_PER_BLOCK*: uint64 = 9 # revisit getShortMap(Blobs) if >9 MAX_SUPPORTED_REQUEST_BLOB_SIDECARS*: uint64 = 1152 - # https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.0/specs/phase0/validator.md#time-parameters - ATTESTATION_DUE_BPS: uint64 = 3333 - AGGREGATE_DUE_BPS: uint64 = 6667 - - # https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.0/specs/altair/validator.md#time-parameters - SYNC_MESSAGE_DUE_BPS: uint64 = 3333 - CONTRIBUTION_DUE_BPS: uint64 = 6667 - - # https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.0/specs/phase0/fork-choice.md#time-parameters - PROPOSER_REORG_CUTOFF_BPS: uint64 = 1667 +type TimeParams* = object + SLOT_DURATION*: Duration + PROPOSER_REORG_CUTOFF_BPS*: uint16 + ATTESTATION_DUE_BPS*: uint16 + AGGREGATE_DUE_BPS*: uint16 + SYNC_MESSAGE_DUE_BPS*: uint16 + CONTRIBUTION_DUE_BPS*: uint16 +const + MIN_SLOT_DURATION* = seconds(1) + MAX_SLOT_DURATION* = seconds(Duration.high.seconds) + MAX_BPS* = 10_000'u16 + +func isValid*(timeParams: TimeParams): bool = + # /!\ Keep in sync with `readRuntimeConfig` + timeParams.SLOT_DURATION in + MIN_SLOT_DURATION .. MAX_SLOT_DURATION and + timeParams.PROPOSER_REORG_CUTOFF_BPS in + 0'u16 ..< MAX_BPS and + timeParams.ATTESTATION_DUE_BPS in + timeParams.PROPOSER_REORG_CUTOFF_BPS ..< MAX_BPS and + timeParams.AGGREGATE_DUE_BPS in + timeParams.ATTESTATION_DUE_BPS ..< MAX_BPS and + timeParams.SYNC_MESSAGE_DUE_BPS == + timeParams.ATTESTATION_DUE_BPS and + timeParams.CONTRIBUTION_DUE_BPS == + timeParams.AGGREGATE_DUE_BPS type - TimeParams* = object - SLOT_DURATION*: Duration - Version* = distinct array[4, byte] Eth1Address* = eth.Address @@ -253,7 +266,21 @@ when const_preset == "mainnet": # --------------------------------------------------------------- timeParams: TimeParams( # 12000 milliseconds - SLOT_DURATION: milliseconds(12000)), + SLOT_DURATION: milliseconds(12000), + + # 1667 basis points, ~17% of SLOT_DURATION_MS + PROPOSER_REORG_CUTOFF_BPS: 1667, + # 3333 basis points, ~33% of SLOT_DURATION_MS + ATTESTATION_DUE_BPS: 3333, + # 6667 basis points, ~67% of SLOT_DURATION_MS + AGGREGATE_DUE_BPS: 6667, + + # Altair + # 3333 basis points, ~33% of SLOT_DURATION_MS + SYNC_MESSAGE_DUE_BPS: 3333, + # 6667 basis points, ~67% of SLOT_DURATION_MS + CONTRIBUTION_DUE_BPS: 6667), + # 14 (estimate from Eth1 mainnet) SECONDS_PER_ETH1_BLOCK: 14, # 2**8 (= 256) epochs ~27 hours @@ -421,7 +448,21 @@ elif const_preset == "gnosis": # --------------------------------------------------------------- timeParams: TimeParams( # 5 seconds - SLOT_DURATION: milliseconds(5000)), + SLOT_DURATION: milliseconds(5000), + + # 1667 basis points, ~17% of SLOT_DURATION_MS + PROPOSER_REORG_CUTOFF_BPS: 1667, + # 3333 basis points, ~33% of SLOT_DURATION_MS + ATTESTATION_DUE_BPS: 3333, + # 6667 basis points, ~67% of SLOT_DURATION_MS + AGGREGATE_DUE_BPS: 6667, + + # Altair + # 3333 basis points, ~33% of SLOT_DURATION_MS + SYNC_MESSAGE_DUE_BPS: 3333, + # 6667 basis points, ~67% of SLOT_DURATION_MS + CONTRIBUTION_DUE_BPS: 6667), + # 14 (estimate from Eth1 mainnet) SECONDS_PER_ETH1_BLOCK: 5, # 2**8 (= 256) epochs ~27 hours @@ -588,7 +629,21 @@ elif const_preset == "minimal": # --------------------------------------------------------------- timeParams: TimeParams( # [customized] 6000 milliseconds - SLOT_DURATION: milliseconds(6000)), + SLOT_DURATION: milliseconds(6000), + + # 1667 basis points, ~17% of SLOT_DURATION_MS + PROPOSER_REORG_CUTOFF_BPS: 1667, + # 3333 basis points, ~33% of SLOT_DURATION_MS + ATTESTATION_DUE_BPS: 3333, + # 6667 basis points, ~67% of SLOT_DURATION_MS + AGGREGATE_DUE_BPS: 6667, + + # Altair + # 3333 basis points, ~33% of SLOT_DURATION_MS + SYNC_MESSAGE_DUE_BPS: 3333, + # 6667 basis points, ~67% of SLOT_DURATION_MS + CONTRIBUTION_DUE_BPS: 6667), + # 14 (estimate from Eth1 mainnet) SECONDS_PER_ETH1_BLOCK: 14, # 2**8 (= 256) epochs @@ -694,10 +749,6 @@ const IsMainnetSupported*: bool = const IsGnosisSupported*: bool = const_preset == "gnosis" -const - MIN_SLOT_DURATION* = seconds(1) - MAX_SLOT_DURATION* = seconds(Duration.high.seconds) - const SLOTS_PER_SYNC_COMMITTEE_PERIOD* = SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD @@ -705,16 +756,21 @@ const SLOTS_PER_SYNC_COMMITTEE_PERIOD* = func safeMinEpochsForBlockRequests*(cfg: RuntimeConfig): uint64 = cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY + cfg.CHURN_LIMIT_QUOTIENT div 2 -func parse(T: type uint64, input: string): T {.raises: [ValueError].} = +func parse[T: uint16 | uint64]( + _: typedesc[T], input: string): T {.raises: [ValueError].} = var res: BiggestUInt if input.len > 2 and input[0] == '0' and input[1] == 'x': if parseHex(input, res) != input.len: - raise newException(ValueError, "The constant value should be a valid hex integer") + raise newException( + ValueError, "The constant value should be a valid hex integer") else: if parseBiggestUInt(input, res) != input.len: - raise newException(ValueError, "The constant value should be a valid unsigned integer") - - uint64(res) + raise newException( + ValueError, "The constant value should be a valid unsigned integer") + when T.high < BiggestUInt.high: + if res > T.high.BiggestUInt: + raise newException(ValueError, "The constant value is too large") + res.T template parse(T: type byte, input: string): T = byte parse(uint64, input) @@ -963,12 +1019,6 @@ proc readRuntimeConfig*( checkCompatibility PROPOSER_SCORE_BOOST checkCompatibility REORG_PARENT_WEIGHT_THRESHOLD - checkCompatibility ATTESTATION_DUE_BPS - checkCompatibility AGGREGATE_DUE_BPS - checkCompatibility SYNC_MESSAGE_DUE_BPS - checkCompatibility CONTRIBUTION_DUE_BPS - checkCompatibility PROPOSER_REORG_CUTOFF_BPS - template assignValue(name: static string, field: untyped): untyped = when name == "SLOT_DURATION": if values.hasKey("SLOT_DURATION_MS"): @@ -1037,9 +1087,28 @@ proc readRuntimeConfig*( except ValueError: raise (ref PresetFileError)(msg: "Unable to parse " & name) - checkParsedValue( - "SLOT_DURATION_MS", cfg.timeParams.SLOT_DURATION.milliseconds, - MIN_SLOT_DURATION.milliseconds .. MAX_SLOT_DURATION.milliseconds, `in`) + block: # /!\ Keep in sync with `isValid` + checkParsedValue( + "SLOT_DURATION_MS", cfg.timeParams.SLOT_DURATION.milliseconds, + MIN_SLOT_DURATION.milliseconds .. MAX_SLOT_DURATION.milliseconds, `in`) + + checkParsedValue( + "PROPOSER_REORG_CUTOFF_BPS", cfg.timeParams.PROPOSER_REORG_CUTOFF_BPS, + 0'u16 ..< MAX_BPS, `in`) + checkParsedValue( + "ATTESTATION_DUE_BPS", cfg.timeParams.ATTESTATION_DUE_BPS, + cfg.timeParams.PROPOSER_REORG_CUTOFF_BPS ..< MAX_BPS, `in`) + checkParsedValue( + "AGGREGATE_DUE_BPS", cfg.timeParams.AGGREGATE_DUE_BPS, + cfg.timeParams.ATTESTATION_DUE_BPS ..< MAX_BPS, `in`) + + checkParsedValue( + "SYNC_MESSAGE_DUE_BPS", cfg.timeParams.SYNC_MESSAGE_DUE_BPS, + cfg.timeParams.ATTESTATION_DUE_BPS) + checkParsedValue( + "CONTRIBUTION_DUE_BPS", cfg.timeParams.CONTRIBUTION_DUE_BPS, + cfg.timeParams.AGGREGATE_DUE_BPS) + doAssert cfg.timeParams.isValid # Requires initialized `cfg` checkCompatibility cfg.timeParams.SLOT_DURATION.seconds.uint64, diff --git a/beacon_chain/validator_client/api.nim b/beacon_chain/validator_client/api.nim index 956b842170..7f6a3c5c54 100644 --- a/beacon_chain/validator_client/api.nim +++ b/beacon_chain/validator_client/api.nim @@ -1495,7 +1495,7 @@ proc produceAttestationData*( let res = vc.firstSuccessParallel( RestPlainResponse, ProduceAttestationDataResponse, - vc.OneThirdDuration, + vc.AttestationToAggregationDuration, ViableNodeStatus, {BeaconNodeRole.AttestationData}, produceAttestationDataPlain(it, slot, committee_index)): @@ -1537,8 +1537,8 @@ proc produceAttestationData*( RestPlainResponse, ProduceAttestationDataResponse, float64, - vc.OneThirdDurationSoft, - vc.OneThirdDuration, + vc.AttestationToAggregationDurationSoft, + vc.AttestationToAggregationDuration, ViableNodeStatus, {BeaconNodeRole.AttestationData}, produceAttestationDataPlain(it, slot, committee_index), @@ -1578,7 +1578,7 @@ proc produceAttestationData*( of ApiStrategyKind.Priority: vc.firstSuccessSequential( RestPlainResponse, - vc.OneThirdDuration, + vc.AttestationToAggregationDuration, ViableNodeStatus, {BeaconNodeRole.AttestationData}, produceAttestationDataPlain(it, slot, committee_index)): @@ -1774,7 +1774,7 @@ proc getAggregatedAttestationV2*( let res = vc.firstSuccessParallel( RestPlainResponse, GetAggregatedAttestationV2Response, - vc.OneThirdDuration, + vc.AggregationToSlotEndDuration, ViableNodeStatus, {BeaconNodeRole.AggregatedData}, getAggregatedAttestationPlainV2(it, root, slot, committee_index)): @@ -1818,8 +1818,8 @@ proc getAggregatedAttestationV2*( RestPlainResponse, GetAggregatedAttestationV2Response, float64, - vc.OneThirdDurationSoft, - vc.OneThirdDuration, + vc.AggregationToSlotEndDurationSoft, + vc.AggregationToSlotEndDuration, ViableNodeStatus, {BeaconNodeRole.AggregatedData}, getAggregatedAttestationPlainV2(it, root, slot, committee_index), @@ -1864,7 +1864,7 @@ proc getAggregatedAttestationV2*( of ApiStrategyKind.Priority: vc.firstSuccessSequential( RestPlainResponse, - vc.OneThirdDuration, + vc.AggregationToSlotEndDuration, ViableNodeStatus, {BeaconNodeRole.AggregatedData}, getAggregatedAttestationPlainV2(it, root, slot, committee_index)): @@ -1914,7 +1914,7 @@ proc produceSyncCommitteeContribution*( let res = vc.firstSuccessParallel( RestPlainResponse, ProduceSyncCommitteeContributionResponse, - vc.OneThirdDuration, + vc.SyncContributionToSlotEndDuration, ViableNodeStatus, {BeaconNodeRole.SyncCommitteeData}, produceSyncCommitteeContributionPlain(it, slot, subcommitteeIndex, root)): @@ -1956,8 +1956,8 @@ proc produceSyncCommitteeContribution*( RestPlainResponse, ProduceSyncCommitteeContributionResponse, float64, - vc.OneThirdDurationSoft, - vc.OneThirdDuration, + vc.SyncContributionToSlotEndDurationSoft, + vc.SyncContributionToSlotEndDuration, ViableNodeStatus, {BeaconNodeRole.SyncCommitteeData}, produceSyncCommitteeContributionPlain(it, slot, subcommitteeIndex, root), @@ -1998,7 +1998,7 @@ proc produceSyncCommitteeContribution*( of ApiStrategyKind.Priority: vc.firstSuccessSequential( RestPlainResponse, - vc.OneThirdDuration, + vc.SyncContributionToSlotEndDuration, ViableNodeStatus, {BeaconNodeRole.SyncCommitteeData}, produceSyncCommitteeContributionPlain(it, slot, subcommitteeIndex, root)): diff --git a/beacon_chain/validator_client/common.nim b/beacon_chain/validator_client/common.nim index e9d2a95c40..bf1264c8da 100644 --- a/beacon_chain/validator_client/common.nim +++ b/beacon_chain/validator_client/common.nim @@ -8,7 +8,7 @@ {.push raises: [].} import - std/[tables, os, sets, sequtils, strutils, uri, algorithm], + std/[macros, tables, os, sets, sequtils, strutils, uri, algorithm], results, stew/[base10, byteutils], bearssl/rand, chronos, presto, presto/client as presto_client, @@ -316,13 +316,28 @@ func SlotDuration*(vc: ValidatorClientRef): Duration = vc.timeParams.SLOT_DURATION func SlotDurationSoft*(vc: ValidatorClientRef): Duration = - vc.timeParams.SLOT_DURATION div 2 + vc.SlotDuration div 2 -func OneThirdDuration*(vc: ValidatorClientRef): Duration = - vc.timeParams.SLOT_DURATION div INTERVALS_PER_SLOT +func AttestationToAggregationDuration*(vc: ValidatorClientRef): Duration = + nanoseconds(vc.timeParams.aggregateSlotOffset.nanoseconds) - + nanoseconds(vc.timeParams.attestationSlotOffset.nanoseconds) -func OneThirdDurationSoft*(vc: ValidatorClientRef): Duration = - (vc.timeParams.SLOT_DURATION div INTERVALS_PER_SLOT) div 2 +func AttestationToAggregationDurationSoft*(vc: ValidatorClientRef): Duration = + vc.AttestationToAggregationDuration div 2 + +func AggregationToSlotEndDuration*(vc: ValidatorClientRef): Duration = + vc.timeParams.SLOT_DURATION - + nanoseconds(vc.timeParams.aggregateSlotOffset.nanoseconds) + +func AggregationToSlotEndDurationSoft*(vc: ValidatorClientRef): Duration = + vc.AggregationToSlotEndDuration div 2 + +func SyncContributionToSlotEndDuration*(vc: ValidatorClientRef): Duration = + vc.timeParams.SLOT_DURATION - + nanoseconds(vc.timeParams.syncContributionSlotOffset.nanoseconds) + +func SyncContributionToSlotEndDurationSoft*(vc: ValidatorClientRef): Duration = + vc.SyncContributionToSlotEndDuration div 2 proc `$`*(to: TimeOffset): string = if to.value < 0: @@ -514,8 +529,8 @@ chronicles.expandIt(SyncCommitteeDuty): validator_index = it.validator_index validator_sync_committee_indices = it.validator_sync_committee_indices -func parseConfigValue[T: uint64](_: typedesc[T], str: string): Opt[T] = - let res = Base10.decode(uint64, str).valueOr: +func parseConfigValue[T: uint16 | uint64](_: typedesc[T], str: string): Opt[T] = + let res = Base10.decode(T, str).valueOr: return Opt.none T Opt.some res @@ -592,9 +607,24 @@ func getTimeParams*(c: VCRuntimeConfig): Opt[TimeParams] = seconds(rawValue.int64) else: defaultRuntimeConfig.timeParams.SLOT_DURATION - if SLOT_DURATION notin MIN_SLOT_DURATION .. MAX_SLOT_DURATION: + + macro parseBps(key: static[string]): uint16 = + let keyId = ident key + quote do: + const defaultStr = Base10.toString( + defaultRuntimeConfig.timeParams.`keyId`) + ? uint16.parseConfigValue(c.getOrDefault(`key`, defaultStr)) + + let res = Opt.some TimeParams( + SLOT_DURATION: SLOT_DURATION, + PROPOSER_REORG_CUTOFF_BPS: parseBps "PROPOSER_REORG_CUTOFF_BPS", + ATTESTATION_DUE_BPS: parseBps "ATTESTATION_DUE_BPS", + AGGREGATE_DUE_BPS: parseBps "AGGREGATE_DUE_BPS", + SYNC_MESSAGE_DUE_BPS: parseBps "SYNC_MESSAGE_DUE_BPS", + CONTRIBUTION_DUE_BPS: parseBps "CONTRIBUTION_DUE_BPS") + if not res.get.isValid: return Opt.none TimeParams - Opt.some TimeParams(SLOT_DURATION: SLOT_DURATION) + res proc updateStatus*(node: BeaconNodeServerRef, status: RestBeaconNodeStatus, diff --git a/ncli/resttest-rules.json b/ncli/resttest-rules.json index 49e93e40e5..badb469c56 100644 --- a/ncli/resttest-rules.json +++ b/ncli/resttest-rules.json @@ -3926,7 +3926,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmps", "start": ["data"], "value": {"MAX_COMMITTEES_PER_SLOT":"","TARGET_COMMITTEE_SIZE":"","MAX_VALIDATORS_PER_COMMITTEE":"","SHUFFLE_ROUND_COUNT":"","HYSTERESIS_QUOTIENT":"","HYSTERESIS_DOWNWARD_MULTIPLIER":"","HYSTERESIS_UPWARD_MULTIPLIER":"","MIN_DEPOSIT_AMOUNT":"","MAX_EFFECTIVE_BALANCE":"","EFFECTIVE_BALANCE_INCREMENT":"","MIN_ATTESTATION_INCLUSION_DELAY":"","SLOTS_PER_EPOCH":"","MIN_SEED_LOOKAHEAD":"","MAX_SEED_LOOKAHEAD":"","EPOCHS_PER_ETH1_VOTING_PERIOD":"","SLOTS_PER_HISTORICAL_ROOT":"","MIN_EPOCHS_TO_INACTIVITY_PENALTY":"","EPOCHS_PER_HISTORICAL_VECTOR":"","EPOCHS_PER_SLASHINGS_VECTOR":"","HISTORICAL_ROOTS_LIMIT":"","VALIDATOR_REGISTRY_LIMIT":"","BASE_REWARD_FACTOR":"","WHISTLEBLOWER_REWARD_QUOTIENT":"","PROPOSER_REWARD_QUOTIENT":"","INACTIVITY_PENALTY_QUOTIENT":"","MIN_SLASHING_PENALTY_QUOTIENT":"","PROPORTIONAL_SLASHING_MULTIPLIER":"","MAX_PROPOSER_SLASHINGS":"","MAX_ATTESTER_SLASHINGS":"","MAX_ATTESTATIONS":"","MAX_DEPOSITS":"","MAX_VOLUNTARY_EXITS":"","INACTIVITY_PENALTY_QUOTIENT_ALTAIR":"","MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR":"","PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR":"","SYNC_COMMITTEE_SIZE":"","EPOCHS_PER_SYNC_COMMITTEE_PERIOD":"","MIN_SYNC_COMMITTEE_PARTICIPANTS":"","UPDATE_TIMEOUT":"","INACTIVITY_PENALTY_QUOTIENT_BELLATRIX":"","MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX":"","PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX":"","MAX_BYTES_PER_TRANSACTION":"","MAX_TRANSACTIONS_PER_PAYLOAD":"","BYTES_PER_LOGS_BLOOM":"","MAX_EXTRA_DATA_BYTES":"","MAX_BLS_TO_EXECUTION_CHANGES":"","MAX_WITHDRAWALS_PER_PAYLOAD":"","MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP":"","FIELD_ELEMENTS_PER_BLOB":"","MAX_BLOB_COMMITMENTS_PER_BLOCK":"","KZG_COMMITMENT_INCLUSION_PROOF_DEPTH":"","PRESET_BASE":"","CONFIG_NAME":"","TERMINAL_TOTAL_DIFFICULTY":"","TERMINAL_BLOCK_HASH":"","TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH":"","MIN_GENESIS_ACTIVE_VALIDATOR_COUNT":"","MIN_GENESIS_TIME":"","GENESIS_FORK_VERSION":"","GENESIS_DELAY":"","ALTAIR_FORK_VERSION":"","ALTAIR_FORK_EPOCH":"","BELLATRIX_FORK_VERSION":"","BELLATRIX_FORK_EPOCH":"","CAPELLA_FORK_VERSION":"","CAPELLA_FORK_EPOCH":"","DENEB_FORK_VERSION":"","DENEB_FORK_EPOCH":"","ELECTRA_FORK_VERSION":"","ELECTRA_FORK_EPOCH":"","FULU_FORK_VERSION":"","FULU_FORK_EPOCH":"","SECONDS_PER_SLOT":"","SLOT_DURATION_MS":"","SECONDS_PER_ETH1_BLOCK":"","MIN_VALIDATOR_WITHDRAWABILITY_DELAY":"","SHARD_COMMITTEE_PERIOD":"","ETH1_FOLLOW_DISTANCE":"","INACTIVITY_SCORE_BIAS":"","INACTIVITY_SCORE_RECOVERY_RATE":"","EJECTION_BALANCE":"","MIN_PER_EPOCH_CHURN_LIMIT":"","CHURN_LIMIT_QUOTIENT":"","MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT":"","PROPOSER_SCORE_BOOST":"","REORG_HEAD_WEIGHT_THRESHOLD":"","REORG_PARENT_WEIGHT_THRESHOLD":"","REORG_MAX_EPOCHS_SINCE_FINALIZATION":"","DEPOSIT_CHAIN_ID":"","DEPOSIT_NETWORK_ID":"","DEPOSIT_CONTRACT_ADDRESS":"","MAX_PAYLOAD_SIZE":"","MAX_REQUEST_BLOCKS":"","EPOCHS_PER_SUBNET_SUBSCRIPTION":"","MIN_EPOCHS_FOR_BLOCK_REQUESTS":"","ATTESTATION_PROPAGATION_SLOT_RANGE":"","MAXIMUM_GOSSIP_CLOCK_DISPARITY":"","MESSAGE_DOMAIN_INVALID_SNAPPY":"","MESSAGE_DOMAIN_VALID_SNAPPY":"","SUBNETS_PER_NODE":"","ATTESTATION_SUBNET_COUNT":"","ATTESTATION_SUBNET_EXTRA_BITS":"","ATTESTATION_SUBNET_PREFIX_BITS":"","MAX_REQUEST_BLOCKS_DENEB":"","MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS":"","BLOB_SIDECAR_SUBNET_COUNT":"","MAX_BLOBS_PER_BLOCK":"","MAX_REQUEST_BLOB_SIDECARS":"","MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA":"","MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT":"","BLOB_SIDECAR_SUBNET_COUNT_ELECTRA":"","MAX_BLOBS_PER_BLOCK_ELECTRA":"","MAX_REQUEST_BLOB_SIDECARS_ELECTRA":"","NUMBER_OF_COLUMNS":"","NUMBER_OF_CUSTODY_GROUPS":"","DATA_COLUMN_SIDECAR_SUBNET_COUNT":"","MAX_REQUEST_DATA_COLUMN_SIDECARS":"","SAMPLES_PER_SLOT":"","CUSTODY_REQUIREMENT":"","VALIDATOR_CUSTODY_REQUIREMENT":"","BALANCE_PER_ADDITIONAL_CUSTODY_GROUP":"","BLOB_SCHEDULE": [{"EPOCH": "*", "MAX_BLOBS_PER_BLOCK": "*"}],"MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS":"","BLS_WITHDRAWAL_PREFIX":"","ETH1_ADDRESS_WITHDRAWAL_PREFIX":"","DOMAIN_BEACON_PROPOSER":"","DOMAIN_BEACON_ATTESTER":"","DOMAIN_RANDAO":"","DOMAIN_DEPOSIT":"","DOMAIN_VOLUNTARY_EXIT":"","DOMAIN_SELECTION_PROOF":"","DOMAIN_AGGREGATE_AND_PROOF":"","TIMELY_SOURCE_FLAG_INDEX":"","TIMELY_TARGET_FLAG_INDEX":"","TIMELY_HEAD_FLAG_INDEX":"","TIMELY_SOURCE_WEIGHT":"","TIMELY_TARGET_WEIGHT":"","TIMELY_HEAD_WEIGHT":"","SYNC_REWARD_WEIGHT":"","PROPOSER_WEIGHT":"","WEIGHT_DENOMINATOR":"","DOMAIN_SYNC_COMMITTEE":"","DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF":"","DOMAIN_CONTRIBUTION_AND_PROOF":"","DOMAIN_BLS_TO_EXECUTION_CHANGE":"","TARGET_AGGREGATORS_PER_COMMITTEE":"","TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE":"","SYNC_COMMITTEE_SUBNET_COUNT":"","UNSET_DEPOSIT_REQUESTS_START_INDEX":"","FULL_EXIT_REQUEST_AMOUNT":"","COMPOUNDING_WITHDRAWAL_PREFIX":"","DEPOSIT_REQUEST_TYPE":"","WITHDRAWAL_REQUEST_TYPE":"","CONSOLIDATION_REQUEST_TYPE":"","MIN_ACTIVATION_BALANCE":"","MAX_EFFECTIVE_BALANCE_ELECTRA":"","MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA":"","WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA":"","PENDING_DEPOSITS_LIMIT":"","PENDING_PARTIAL_WITHDRAWALS_LIMIT":"","PENDING_CONSOLIDATIONS_LIMIT":"","MAX_ATTESTER_SLASHINGS_ELECTRA":"","MAX_ATTESTATIONS_ELECTRA":"","MAX_DEPOSIT_REQUESTS_PER_PAYLOAD":"","MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD":"","MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD":"","MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP":"","MAX_PENDING_DEPOSITS_PER_EPOCH":""}}] + "body": [{"operator": "jstructcmps", "start": ["data"], "value": {"MAX_COMMITTEES_PER_SLOT":"","TARGET_COMMITTEE_SIZE":"","MAX_VALIDATORS_PER_COMMITTEE":"","SHUFFLE_ROUND_COUNT":"","HYSTERESIS_QUOTIENT":"","HYSTERESIS_DOWNWARD_MULTIPLIER":"","HYSTERESIS_UPWARD_MULTIPLIER":"","MIN_DEPOSIT_AMOUNT":"","MAX_EFFECTIVE_BALANCE":"","EFFECTIVE_BALANCE_INCREMENT":"","MIN_ATTESTATION_INCLUSION_DELAY":"","SLOTS_PER_EPOCH":"","MIN_SEED_LOOKAHEAD":"","MAX_SEED_LOOKAHEAD":"","EPOCHS_PER_ETH1_VOTING_PERIOD":"","SLOTS_PER_HISTORICAL_ROOT":"","MIN_EPOCHS_TO_INACTIVITY_PENALTY":"","EPOCHS_PER_HISTORICAL_VECTOR":"","EPOCHS_PER_SLASHINGS_VECTOR":"","HISTORICAL_ROOTS_LIMIT":"","VALIDATOR_REGISTRY_LIMIT":"","BASE_REWARD_FACTOR":"","WHISTLEBLOWER_REWARD_QUOTIENT":"","PROPOSER_REWARD_QUOTIENT":"","INACTIVITY_PENALTY_QUOTIENT":"","MIN_SLASHING_PENALTY_QUOTIENT":"","PROPORTIONAL_SLASHING_MULTIPLIER":"","MAX_PROPOSER_SLASHINGS":"","MAX_ATTESTER_SLASHINGS":"","MAX_ATTESTATIONS":"","MAX_DEPOSITS":"","MAX_VOLUNTARY_EXITS":"","INACTIVITY_PENALTY_QUOTIENT_ALTAIR":"","MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR":"","PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR":"","SYNC_COMMITTEE_SIZE":"","EPOCHS_PER_SYNC_COMMITTEE_PERIOD":"","MIN_SYNC_COMMITTEE_PARTICIPANTS":"","UPDATE_TIMEOUT":"","INACTIVITY_PENALTY_QUOTIENT_BELLATRIX":"","MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX":"","PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX":"","MAX_BYTES_PER_TRANSACTION":"","MAX_TRANSACTIONS_PER_PAYLOAD":"","BYTES_PER_LOGS_BLOOM":"","MAX_EXTRA_DATA_BYTES":"","MAX_BLS_TO_EXECUTION_CHANGES":"","MAX_WITHDRAWALS_PER_PAYLOAD":"","MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP":"","FIELD_ELEMENTS_PER_BLOB":"","MAX_BLOB_COMMITMENTS_PER_BLOCK":"","KZG_COMMITMENT_INCLUSION_PROOF_DEPTH":"","PRESET_BASE":"","CONFIG_NAME":"","TERMINAL_TOTAL_DIFFICULTY":"","TERMINAL_BLOCK_HASH":"","TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH":"","MIN_GENESIS_ACTIVE_VALIDATOR_COUNT":"","MIN_GENESIS_TIME":"","GENESIS_FORK_VERSION":"","GENESIS_DELAY":"","ALTAIR_FORK_VERSION":"","ALTAIR_FORK_EPOCH":"","BELLATRIX_FORK_VERSION":"","BELLATRIX_FORK_EPOCH":"","CAPELLA_FORK_VERSION":"","CAPELLA_FORK_EPOCH":"","DENEB_FORK_VERSION":"","DENEB_FORK_EPOCH":"","ELECTRA_FORK_VERSION":"","ELECTRA_FORK_EPOCH":"","FULU_FORK_VERSION":"","FULU_FORK_EPOCH":"","SECONDS_PER_SLOT":"","SLOT_DURATION_MS":"","SECONDS_PER_ETH1_BLOCK":"","MIN_VALIDATOR_WITHDRAWABILITY_DELAY":"","SHARD_COMMITTEE_PERIOD":"","ETH1_FOLLOW_DISTANCE":"","PROPOSER_REORG_CUTOFF_BPS":"","ATTESTATION_DUE_BPS":"","AGGREGATE_DUE_BPS":"","SYNC_MESSAGE_DUE_BPS":"","CONTRIBUTION_DUE_BPS":"","INACTIVITY_SCORE_BIAS":"","INACTIVITY_SCORE_RECOVERY_RATE":"","EJECTION_BALANCE":"","MIN_PER_EPOCH_CHURN_LIMIT":"","CHURN_LIMIT_QUOTIENT":"","MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT":"","PROPOSER_SCORE_BOOST":"","REORG_HEAD_WEIGHT_THRESHOLD":"","REORG_PARENT_WEIGHT_THRESHOLD":"","REORG_MAX_EPOCHS_SINCE_FINALIZATION":"","DEPOSIT_CHAIN_ID":"","DEPOSIT_NETWORK_ID":"","DEPOSIT_CONTRACT_ADDRESS":"","MAX_PAYLOAD_SIZE":"","MAX_REQUEST_BLOCKS":"","EPOCHS_PER_SUBNET_SUBSCRIPTION":"","MIN_EPOCHS_FOR_BLOCK_REQUESTS":"","ATTESTATION_PROPAGATION_SLOT_RANGE":"","MAXIMUM_GOSSIP_CLOCK_DISPARITY":"","MESSAGE_DOMAIN_INVALID_SNAPPY":"","MESSAGE_DOMAIN_VALID_SNAPPY":"","SUBNETS_PER_NODE":"","ATTESTATION_SUBNET_COUNT":"","ATTESTATION_SUBNET_EXTRA_BITS":"","ATTESTATION_SUBNET_PREFIX_BITS":"","MAX_REQUEST_BLOCKS_DENEB":"","MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS":"","BLOB_SIDECAR_SUBNET_COUNT":"","MAX_BLOBS_PER_BLOCK":"","MAX_REQUEST_BLOB_SIDECARS":"","MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA":"","MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT":"","BLOB_SIDECAR_SUBNET_COUNT_ELECTRA":"","MAX_BLOBS_PER_BLOCK_ELECTRA":"","MAX_REQUEST_BLOB_SIDECARS_ELECTRA":"","NUMBER_OF_COLUMNS":"","NUMBER_OF_CUSTODY_GROUPS":"","DATA_COLUMN_SIDECAR_SUBNET_COUNT":"","MAX_REQUEST_DATA_COLUMN_SIDECARS":"","SAMPLES_PER_SLOT":"","CUSTODY_REQUIREMENT":"","VALIDATOR_CUSTODY_REQUIREMENT":"","BALANCE_PER_ADDITIONAL_CUSTODY_GROUP":"","BLOB_SCHEDULE": [{"EPOCH": "*", "MAX_BLOBS_PER_BLOCK": "*"}],"MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS":"","BLS_WITHDRAWAL_PREFIX":"","ETH1_ADDRESS_WITHDRAWAL_PREFIX":"","DOMAIN_BEACON_PROPOSER":"","DOMAIN_BEACON_ATTESTER":"","DOMAIN_RANDAO":"","DOMAIN_DEPOSIT":"","DOMAIN_VOLUNTARY_EXIT":"","DOMAIN_SELECTION_PROOF":"","DOMAIN_AGGREGATE_AND_PROOF":"","TIMELY_SOURCE_FLAG_INDEX":"","TIMELY_TARGET_FLAG_INDEX":"","TIMELY_HEAD_FLAG_INDEX":"","TIMELY_SOURCE_WEIGHT":"","TIMELY_TARGET_WEIGHT":"","TIMELY_HEAD_WEIGHT":"","SYNC_REWARD_WEIGHT":"","PROPOSER_WEIGHT":"","WEIGHT_DENOMINATOR":"","DOMAIN_SYNC_COMMITTEE":"","DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF":"","DOMAIN_CONTRIBUTION_AND_PROOF":"","DOMAIN_BLS_TO_EXECUTION_CHANGE":"","TARGET_AGGREGATORS_PER_COMMITTEE":"","TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE":"","SYNC_COMMITTEE_SUBNET_COUNT":"","UNSET_DEPOSIT_REQUESTS_START_INDEX":"","FULL_EXIT_REQUEST_AMOUNT":"","COMPOUNDING_WITHDRAWAL_PREFIX":"","DEPOSIT_REQUEST_TYPE":"","WITHDRAWAL_REQUEST_TYPE":"","CONSOLIDATION_REQUEST_TYPE":"","MIN_ACTIVATION_BALANCE":"","MAX_EFFECTIVE_BALANCE_ELECTRA":"","MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA":"","WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA":"","PENDING_DEPOSITS_LIMIT":"","PENDING_PARTIAL_WITHDRAWALS_LIMIT":"","PENDING_CONSOLIDATIONS_LIMIT":"","MAX_ATTESTER_SLASHINGS_ELECTRA":"","MAX_ATTESTATIONS_ELECTRA":"","MAX_DEPOSIT_REQUESTS_PER_PAYLOAD":"","MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD":"","MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD":"","MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP":"","MAX_PENDING_DEPOSITS_PER_EPOCH":""}}] } }, {