make `Gwei` `distinct` (#6090)

#6087 introduced a subtle change to `nim-web3` resulting in `Gwei` to be
serialized differently than before. Using a `distinct` type for `Gwei`
improves type safety and avoids such problems in the future.
This commit is contained in:
Etan Kissling 2024-03-19 14:22:07 +01:00 committed by GitHub
parent 1dd2c939ac
commit 5d42859176
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 245 additions and 202 deletions

View File

@ -44,13 +44,13 @@ type
# Registry
validators*: HashList[ValidatorStatus, Limit VALIDATOR_REGISTRY_LIMIT]
balances*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT]
balances*: HashList[Gwei, Limit VALIDATOR_REGISTRY_LIMIT]
# Randomness
randao_mixes*: HashArray[Limit EPOCHS_PER_HISTORICAL_VECTOR, Eth2Digest]
# Slashings
slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, uint64]
slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, Gwei]
## Per-epoch sums of slashed effective balances
# Attestations
@ -97,13 +97,13 @@ type
# Registry
validators*: HashList[ValidatorStatus, Limit VALIDATOR_REGISTRY_LIMIT]
balances*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT]
balances*: HashList[Gwei, Limit VALIDATOR_REGISTRY_LIMIT]
# Randomness
randao_mixes*: HashArray[Limit EPOCHS_PER_HISTORICAL_VECTOR, Eth2Digest]
# Slashings
slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, uint64]
slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, Gwei]
## Per-epoch sums of slashed effective balances
# Participation
@ -155,13 +155,13 @@ type
# Registry
validators*: HashList[ValidatorStatus, Limit VALIDATOR_REGISTRY_LIMIT]
balances*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT]
balances*: HashList[Gwei, Limit VALIDATOR_REGISTRY_LIMIT]
# Randomness
randao_mixes*: HashArray[Limit EPOCHS_PER_HISTORICAL_VECTOR, Eth2Digest]
# Slashings
slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, uint64]
slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, Gwei]
## Per-epoch sums of slashed effective balances
# Participation

View File

@ -89,7 +89,7 @@ type
processor*: ref Eth2Processor
blockProcessor*: ref BlockProcessor
consensusManager*: ref ConsensusManager
attachedValidatorBalanceTotal*: uint64
attachedValidatorBalanceTotal*: Gwei
gossipState*: GossipState
blocksGossipState*: GossipState
beaconClock*: BeaconClock

View File

@ -1368,7 +1368,7 @@ func depositEventsToBlocks(depositsList: openArray[JsonString]): seq[Eth1Block]
lastEth1Block.deposits.add DepositData(
pubkey: ValidatorPubKey.init(pubkey.toArray),
withdrawal_credentials: Eth2Digest(data: withdrawalCredentials.toArray),
amount: bytes_to_uint64(amount.toArray),
amount: bytes_to_uint64(amount.toArray).Gwei,
signature: ValidatorSig.init(signature.toArray))
type

View File

@ -434,7 +434,7 @@ func compute_deltas(
# If the validator was not included in `old_balances` (i.e. did not exist)
# its balance is zero
let old_balance = if val_index < old_balances.len: old_balances[val_index]
else: 0
else: 0.Gwei
# If the validator is not known in the `new_balances` then use balance of zero
#
@ -444,7 +444,7 @@ func compute_deltas(
#
# Note that attesters are not different as they are activated only under finality
let new_balance = if val_index < new_balances.len: new_balances[val_index]
else: 0
else: 0.Gwei
if vote.current_root != vote.next_root or old_balance != new_balance:
# Ignore the current or next vote if it is not known in `indices`.

View File

@ -103,7 +103,7 @@ type
indices*: Table[Eth2Digest, Index]
currentEpochTips*: Table[Index, FinalityCheckpoints]
previousProposerBoostRoot*: Eth2Digest
previousProposerBoostScore*: uint64
previousProposerBoostScore*: Gwei
ProtoNode* = object
bid*: BlockId

View File

@ -1204,16 +1204,17 @@ proc maybeUpdateActionTrackerNextEpoch(
# functions get_flag_index_deltas() and get_inactivity_penalty_deltas().
#
# There are no penalties associated with TIMELY_HEAD_FLAG_INDEX, but a
# reward exists. effective_balance == MAX_EFFECTIVE_BALANCE ensures if
# even so, then the effective balance cannot change as a result.
# reward exists. effective_balance == MAX_EFFECTIVE_BALANCE.Gwei ensures
# if even so, then the effective balance cannot change as a result.
#
# It's not truly necessary to avoid all rewards and penalties, but only
# to bound them to ensure they won't unexpected alter effective balance
# during the upcoming epoch transition.
#
# During genesis epoch, the check for epoch participation is against current,
# not previous, epoch, and therefore there's a possibility of checking for if
# a validator has participated in an epoch before it will happen.
# During genesis epoch, the check for epoch participation is against
# current, not previous, epoch, and therefore there's a possibility of
# checking for if a validator has participated in an epoch before it will
# happen.
#
# Because process_rewards_and_penalties() in epoch processing happens
# before the current/previous participation swap, previous is correct
@ -1234,7 +1235,7 @@ proc maybeUpdateActionTrackerNextEpoch(
if participation_flags.has_flag(TIMELY_SOURCE_FLAG_INDEX) and
participation_flags.has_flag(TIMELY_TARGET_FLAG_INDEX) and
effective_balance == MAX_EFFECTIVE_BALANCE and
effective_balance == MAX_EFFECTIVE_BALANCE.Gwei and
forkyState.data.slot.epoch != GENESIS_EPOCH and
forkyState.data.inactivity_scores.item(
nextEpochFirstProposer) == 0 and
@ -1956,13 +1957,13 @@ proc start*(node: BeaconNode) {.raises: [CatchableError].} =
node.elManager.start()
node.run()
func formatGwei(amount: uint64): string =
func formatGwei(amount: Gwei): string =
# TODO This is implemented in a quite a silly way.
# Better routines for formatting decimal numbers
# should exists somewhere else.
let
eth = amount div 1000000000
remainder = amount mod 1000000000
eth = distinctBase(amount) div 1000000000
remainder = distinctBase(amount) mod 1000000000
result = $eth
if remainder != 0:

View File

@ -100,10 +100,10 @@ proc getStatus(validator: Validator,
ok(ValidatorFilterKind.ExitedSlashed)
elif validator.withdrawable_epoch <= current_epoch:
# withdrawal
if validator.effective_balance != 0:
if validator.effective_balance != 0.Gwei:
ok(ValidatorFilterKind.WithdrawalPossible)
else:
# validator.effective_balance == 0
# validator.effective_balance == 0.Gwei
ok(ValidatorFilterKind.WithdrawalDone)
else:
err("Invalid validator status")

View File

@ -29,14 +29,14 @@ func increase_balance*(balance: var Gwei, delta: Gwei) =
func increase_balance*(
state: var ForkyBeaconState, index: ValidatorIndex, delta: Gwei) =
## Increase the validator balance at index ``index`` by ``delta``.
if delta != 0: # avoid dirtying the balance cache if not needed
if delta != 0.Gwei: # avoid dirtying the balance cache if not needed
increase_balance(state.balances.mitem(index), delta)
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#decrease_balance
func decrease_balance*(balance: var Gwei, delta: Gwei) =
balance =
if delta > balance:
0'u64
0.Gwei
else:
balance - delta
@ -44,7 +44,7 @@ func decrease_balance*(
state: var ForkyBeaconState, index: ValidatorIndex, delta: Gwei) =
## Decrease the validator balance at index ``index`` by ``delta``, with
## underflow protection.
if delta != 0: # avoid dirtying the balance cache if not needed
if delta != 0.Gwei: # avoid dirtying the balance cache if not needed
decrease_balance(state.balances.mitem(index), delta)
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/beacon-chain.md#deposits
@ -54,7 +54,8 @@ func get_validator_from_deposit*(deposit: DepositData):
let
amount = deposit.amount
effective_balance = min(
amount - amount mod EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
amount - amount mod EFFECTIVE_BALANCE_INCREMENT.Gwei,
MAX_EFFECTIVE_BALANCE.Gwei)
Validator(
pubkeyData: HashedValidatorPubKey.init(deposit.pubkey),
@ -349,13 +350,13 @@ template get_total_balance(
var res = 0.Gwei
for validator_index in validator_indices:
res += state.validators[validator_index].effective_balance
max(EFFECTIVE_BALANCE_INCREMENT, res)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, res)
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#is_eligible_for_activation_queue
func is_eligible_for_activation_queue*(validator: Validator): bool =
## Check if ``validator`` is eligible to be placed into the activation queue.
validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH and
validator.effective_balance == MAX_EFFECTIVE_BALANCE
validator.effective_balance == MAX_EFFECTIVE_BALANCE.Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#is_eligible_for_activation
func is_eligible_for_activation*(
@ -619,11 +620,13 @@ func get_total_active_balance*(state: ForkyBeaconState, cache: var StateCache):
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_base_reward_per_increment
func get_base_reward_per_increment_sqrt(
total_active_balance_sqrt: uint64): Gwei =
EFFECTIVE_BALANCE_INCREMENT * BASE_REWARD_FACTOR div total_active_balance_sqrt
EFFECTIVE_BALANCE_INCREMENT.Gwei * BASE_REWARD_FACTOR div
total_active_balance_sqrt
func get_base_reward_per_increment*(
total_active_balance: Gwei): Gwei =
get_base_reward_per_increment_sqrt(integer_squareroot(total_active_balance))
get_base_reward_per_increment_sqrt(
integer_squareroot(distinctBase(total_active_balance)))
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_base_reward
func get_base_reward(
@ -633,7 +636,8 @@ func get_base_reward(
## Return the base reward for the validator defined by ``index`` with respect
## to the current ``state``.
let increments =
state.validators[index].effective_balance div EFFECTIVE_BALANCE_INCREMENT
state.validators[index].effective_balance div
EFFECTIVE_BALANCE_INCREMENT.Gwei
increments * base_reward_per_increment
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#attestations
@ -701,11 +705,12 @@ proc check_bls_to_execution_change*(
ok()
func get_proposer_reward*(state: ForkyBeaconState,
attestation: SomeAttestation,
base_reward_per_increment: Gwei,
cache: var StateCache,
epoch_participation: var EpochParticipationFlags): uint64 =
func get_proposer_reward*(
state: ForkyBeaconState,
attestation: SomeAttestation,
base_reward_per_increment: Gwei,
cache: var StateCache,
epoch_participation: var EpochParticipationFlags): Gwei =
let participation_flag_indices = get_attestation_participation_flag_indices(
state, attestation.data, state.slot - attestation.data.slot)
for index in get_attesting_indices_iter(
@ -724,7 +729,7 @@ func get_proposer_reward*(state: ForkyBeaconState,
(WEIGHT_DENOMINATOR.uint64 - PROPOSER_WEIGHT.uint64) *
WEIGHT_DENOMINATOR.uint64 div PROPOSER_WEIGHT.uint64
return result div proposer_reward_denominator
result div proposer_reward_denominator
proc process_attestation*(
state: var ForkyBeaconState, attestation: SomeAttestation, flags: UpdateFlags,
@ -811,7 +816,8 @@ func get_next_sync_committee_keys(
candidate_index = active_validator_indices[shuffled_index]
random_byte = eth2digest(hash_buffer).data[i mod 32]
effective_balance = state.validators[candidate_index].effective_balance
if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
if effective_balance * MAX_RANDOM_BYTE >=
MAX_EFFECTIVE_BALANCE.Gwei * random_byte:
res[index] = state.validators[candidate_index].pubkey
inc index
i += 1'u64
@ -827,7 +833,7 @@ func is_fully_withdrawable_validator(
validator: Validator, balance: Gwei, epoch: Epoch): bool =
## Check if ``validator`` is fully withdrawable.
has_eth1_withdrawal_credential(validator) and
validator.withdrawable_epoch <= epoch and balance > 0
validator.withdrawable_epoch <= epoch and balance > 0.Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#is_partially_withdrawable_validator
func is_partially_withdrawable_validator(
@ -835,8 +841,8 @@ func is_partially_withdrawable_validator(
## Check if ``validator`` is partially withdrawable.
let
has_max_effective_balance =
validator.effective_balance == MAX_EFFECTIVE_BALANCE
has_excess_balance = balance > MAX_EFFECTIVE_BALANCE
validator.effective_balance == MAX_EFFECTIVE_BALANCE.Gwei
has_excess_balance = balance > MAX_EFFECTIVE_BALANCE.Gwei
has_eth1_withdrawal_credential(validator) and
has_max_effective_balance and has_excess_balance
@ -868,7 +874,7 @@ func get_expected_withdrawals*(
var w = Withdrawal(
index: withdrawal_index,
validator_index: validator_index,
amount: balance - MAX_EFFECTIVE_BALANCE)
amount: balance - MAX_EFFECTIVE_BALANCE.Gwei)
w.address.data[0..19] = validator.withdrawal_credentials.data[12..^1]
withdrawals.add w
withdrawal_index = WithdrawalIndex(withdrawal_index + 1)
@ -974,9 +980,10 @@ proc initialize_beacon_state_from_eth1(
validator = addr state.validators.mitem(vidx)
validator.effective_balance = min(
balance - balance mod EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
balance - balance mod EFFECTIVE_BALANCE_INCREMENT.Gwei,
MAX_EFFECTIVE_BALANCE.Gwei)
if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
if validator.effective_balance == MAX_EFFECTIVE_BALANCE.Gwei:
validator.activation_eligibility_epoch = GENESIS_EPOCH
validator.activation_epoch = GENESIS_EPOCH
@ -1091,9 +1098,10 @@ proc initialize_beacon_state_from_eth1*(
validator = addr state.validators.mitem(vidx)
validator.effective_balance = min(
balance - balance mod EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
balance - balance mod EFFECTIVE_BALANCE_INCREMENT.Gwei,
MAX_EFFECTIVE_BALANCE.Gwei)
if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
if validator.effective_balance == MAX_EFFECTIVE_BALANCE.Gwei:
validator.activation_eligibility_epoch = GENESIS_EPOCH
validator.activation_epoch = GENESIS_EPOCH

View File

@ -63,7 +63,7 @@
import
std/[macros, hashes, sets, strutils, tables, typetraits],
results,
stew/[assign2, byteutils, endians2],
stew/[assign2, base10, byteutils, endians2],
chronicles,
json_serialization,
ssz_serialization/types as sszTypes,
@ -122,22 +122,39 @@ template maxSize*(n: int) {.pragma.}
type
Wei* = UInt256
Gwei* = uint64
Gwei* = distinct uint64
Ether* = distinct uint64
template ethAmountUnit*(typ: type) {.dirty.} =
# Arithmetic
func `+`*(x, y: typ): typ {.borrow.}
func `-`*(x, y: typ): typ {.borrow.}
func `*`*(x: typ, y: distinctBase(typ)): typ {.borrow.}
func `*`*(x: distinctBase(typ), y: typ): typ {.borrow.}
# Arithmetic, changing type
func `div`*(x, y: typ): distinctBase(typ) {.borrow.}
func `div`*(x: typ, y: distinctBase(typ)): typ {.borrow.}
func `mod`*(x, y: typ): typ {.borrow.}
func `+=`*(x: var typ, y: typ) {.borrow.}
# Comparison
func `<`*(x, y: typ): bool {.borrow.}
func `<=`*(x, y: typ): bool {.borrow.}
func `==`*(x, y: typ): bool {.borrow.}
func `$`*(x: typ): string {.borrow.}
func u256*(n: typ): UInt256 {.borrow.}
proc toString*(B: typedesc[Base10], value: typ): string {.borrow.}
proc writeValue*(writer: var JsonWriter, value: typ) {.raises: [IOError].} =
writer.writeValue(distinctBase(value))
proc readValue*(
reader: var JsonReader,
value: var typ) {.raises: [IOError, SerializationError].} =
reader.readValue(distinctBase(value))
ethAmountUnit Gwei
ethAmountUnit Ether
type
@ -758,8 +775,8 @@ template lenu64*(x: untyped): untyped =
func `$`*(v: ForkDigest | Version | DomainType): string =
toHex(distinctBase(v))
func toGaugeValue*(x: uint64 | Epoch | Slot): int64 =
if x > uint64(int64.high):
func toGaugeValue*[T: uint64 | Gwei | Slot | Epoch](x: T): int64 =
if x > uint64(int64.high).T:
int64.high
else:
int64(x)

View File

@ -557,7 +557,7 @@ type
# Mod-increment
randao_mix*: Eth2Digest
slashing*: uint64
slashing*: Gwei
# Represent in full; for the next epoch, current_epoch_participation in
# epoch n is previous_epoch_participation in epoch n+1 but this doesn't

View File

@ -1008,6 +1008,16 @@ proc readValue*(reader: var JsonReader[RestJson], value: var UInt256) {.
raiseUnexpectedValue(reader,
"UInt256 value should be a valid decimal string")
## Gwei
proc writeValue*(
writer: var JsonWriter[RestJson], value: Gwei) {.raises: [IOError].} =
writer.writeValue(distinctBase(value))
proc readValue*(
reader: var JsonReader[RestJson],
value: var Gwei) {.raises: [IOError, SerializationError].} =
reader.readValue(distinctBase(value))
## Slot
proc writeValue*(
writer: var JsonWriter[RestJson], value: Slot) {.raises: [IOError].} =

View File

@ -719,13 +719,13 @@ func init*(t: typedesc[RestBlockInfo],
RestBlockInfo(slot: forkyBlck.message.slot, blck: forkyBlck.root)
func init*(t: typedesc[RestValidator], index: ValidatorIndex,
balance: uint64, status: string,
balance: Gwei, status: string,
validator: Validator): RestValidator =
RestValidator(index: index, balance: Base10.toString(balance),
status: status, validator: validator)
func init*(t: typedesc[RestValidatorBalance], index: ValidatorIndex,
balance: uint64): RestValidatorBalance =
balance: Gwei): RestValidatorBalance =
RestValidatorBalance(index: index, balance: Base10.toString(balance))
func init*(t: typedesc[Web3SignerRequest], fork: Fork,

View File

@ -25,11 +25,15 @@ import
export
eth2_merkleization, forks, rlp, ssz_codec
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/weak-subjectivity.md#constants
const ETH_TO_GWEI = 1_000_000_000.Gwei
func toEther*(gwei: Gwei): Ether =
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/weak-subjectivity.md#constants
const ETH_TO_GWEI = 1_000_000_000
(gwei div ETH_TO_GWEI).Ether
func toGwei*(eth: Ether): Gwei =
distinctBase(eth) * ETH_TO_GWEI
type
ExecutionHash256* = eth_types.Hash256
ExecutionTransaction* = eth_types.Transaction
@ -452,7 +456,7 @@ func toExecutionWithdrawal*(
index: withdrawal.index,
validatorIndex: withdrawal.validator_index,
address: EthAddress withdrawal.address.data,
amount: withdrawal.amount)
amount: distinctBase(withdrawal.amount))
# https://eips.ethereum.org/EIPS/eip-4895
proc computeWithdrawalsTrieRoot*(

View File

@ -10,7 +10,7 @@
import ".."/datatypes/[altair, capella]
from stew/byteutils import to0xHex
from ../eth2_merkleization import hash_tree_root
from ../eth2_merkleization import fromSszBytes, hash_tree_root, toSszType
type
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/capella/builder.md#blindedbeaconblockbody

View File

@ -19,6 +19,7 @@ export codec, base, typetraits, EpochParticipationFlags
# Coding and decoding of SSZ to spec-specific types
template toSszType*(v: Gwei): auto = uint64(v)
template toSszType*(v: Slot|Epoch|SyncCommitteePeriod): auto = uint64(v)
template toSszType*(v: BlsCurveType): auto = toRaw(v)
template toSszType*(v: ForkDigest|GraffitiBytes): auto = distinctBase(v)
@ -32,6 +33,9 @@ func fromSszBytes*(
raiseIncorrectSize T
copyMem(result.addr, unsafeAddr data[0], sizeof(result))
template fromSszBytes*(T: type Gwei, bytes: openArray[byte]): T =
T fromSszBytes(uint64, bytes)
template fromSszBytes*(T: type Slot, bytes: openArray[byte]): T =
T fromSszBytes(uint64, bytes)

View File

@ -489,7 +489,7 @@ proc process_operations(cfg: RuntimeConfig,
func get_participant_reward*(total_active_balance: Gwei): Gwei =
let
total_active_increments =
total_active_balance div EFFECTIVE_BALANCE_INCREMENT
total_active_balance div EFFECTIVE_BALANCE_INCREMENT.Gwei
total_base_rewards =
get_base_reward_per_increment(total_active_balance) *
total_active_increments

View File

@ -42,19 +42,19 @@ logScope: topics = "consens"
# Accessors that implement the max condition in `get_total_balance`:
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#get_total_balance
template current_epoch*(v: TotalBalances): Gwei =
max(EFFECTIVE_BALANCE_INCREMENT, v.current_epoch_raw)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, v.current_epoch_raw)
template previous_epoch*(v: TotalBalances): Gwei =
max(EFFECTIVE_BALANCE_INCREMENT, v.previous_epoch_raw)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, v.previous_epoch_raw)
template current_epoch_attesters*(v: TotalBalances): Gwei =
max(EFFECTIVE_BALANCE_INCREMENT, v.current_epoch_attesters_raw)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, v.current_epoch_attesters_raw)
template current_epoch_target_attesters*(v: TotalBalances): Gwei =
max(EFFECTIVE_BALANCE_INCREMENT, v.current_epoch_target_attesters_raw)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, v.current_epoch_target_attesters_raw)
template previous_epoch_attesters*(v: TotalBalances): Gwei =
max(EFFECTIVE_BALANCE_INCREMENT, v.previous_epoch_attesters_raw)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, v.previous_epoch_attesters_raw)
template previous_epoch_target_attesters*(v: TotalBalances): Gwei =
max(EFFECTIVE_BALANCE_INCREMENT, v.previous_epoch_target_attesters_raw)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, v.previous_epoch_target_attesters_raw)
template previous_epoch_head_attesters*(v: TotalBalances): Gwei =
max(EFFECTIVE_BALANCE_INCREMENT, v.previous_epoch_head_attesters_raw)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, v.previous_epoch_head_attesters_raw)
func init*(info: var phase0.EpochInfo, state: phase0.BeaconState) =
info.balances = TotalBalances()
@ -218,12 +218,12 @@ func get_unslashed_participating_balances*(
for flag_index in TimelyFlag:
res.previous_epoch[flag_index] =
max(EFFECTIVE_BALANCE_INCREMENT, res.previous_epoch[flag_index])
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, res.previous_epoch[flag_index])
res.current_epoch_TIMELY_TARGET =
max(EFFECTIVE_BALANCE_INCREMENT, res.current_epoch_TIMELY_TARGET)
max(EFFECTIVE_BALANCE_INCREMENT.Gwei, res.current_epoch_TIMELY_TARGET)
res.current_epoch = max(EFFECTIVE_BALANCE_INCREMENT, res.current_epoch)
res.current_epoch = max(EFFECTIVE_BALANCE_INCREMENT.Gwei, res.current_epoch)
res
@ -504,24 +504,26 @@ func is_in_inactivity_leak(finality_delay: uint64): bool =
func get_finality_delay*(state: ForkyBeaconState): uint64 =
get_previous_epoch(state) - state.finalized_checkpoint.epoch
func get_attestation_component_reward*(attesting_balance: Gwei,
total_balance: Gwei,
base_reward: uint64,
finality_delay: uint64): Gwei =
func get_attestation_component_reward*(
attesting_balance: Gwei,
total_balance: Gwei,
base_reward: Gwei,
finality_delay: uint64): Gwei =
if is_in_inactivity_leak(finality_delay):
# Since full base reward will be canceled out by inactivity penalty deltas,
# optimal participation receives full base reward compensation here.
base_reward
else:
let reward_numerator =
base_reward * (attesting_balance div EFFECTIVE_BALANCE_INCREMENT)
reward_numerator div (total_balance div EFFECTIVE_BALANCE_INCREMENT)
base_reward * (attesting_balance div EFFECTIVE_BALANCE_INCREMENT.Gwei)
reward_numerator div (total_balance div EFFECTIVE_BALANCE_INCREMENT.Gwei)
func get_attestation_component_delta(is_unslashed_attester: bool,
attesting_balance: Gwei,
total_balance: Gwei,
base_reward: uint64,
finality_delay: uint64): RewardDelta =
func get_attestation_component_delta(
is_unslashed_attester: bool,
attesting_balance: Gwei,
total_balance: Gwei,
base_reward: Gwei,
finality_delay: uint64): RewardDelta =
# Helper with shared logic for use by get source, target, and head deltas
# functions
if is_unslashed_attester:
@ -534,10 +536,11 @@ func get_attestation_component_delta(is_unslashed_attester: bool,
RewardDelta(penalties: base_reward)
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#components-of-attestation-deltas
func get_source_delta*(validator: RewardStatus,
base_reward: uint64,
balances: TotalBalances,
finality_delay: uint64): RewardDelta =
func get_source_delta*(
validator: RewardStatus,
base_reward: Gwei,
balances: TotalBalances,
finality_delay: uint64): RewardDelta =
## Return attester micro-rewards/penalties for source-vote for each validator.
get_attestation_component_delta(
validator.is_previous_epoch_attester.isSome() and
@ -547,10 +550,11 @@ func get_source_delta*(validator: RewardStatus,
base_reward,
finality_delay)
func get_target_delta*(validator: RewardStatus,
base_reward: uint64,
balances: TotalBalances,
finality_delay: uint64): RewardDelta =
func get_target_delta*(
validator: RewardStatus,
base_reward: Gwei,
balances: TotalBalances,
finality_delay: uint64): RewardDelta =
## Return attester micro-rewards/penalties for target-vote for each validator.
get_attestation_component_delta(
validator.flags.contains(RewardFlags.isPreviousEpochTargetAttester) and
@ -560,10 +564,11 @@ func get_target_delta*(validator: RewardStatus,
base_reward,
finality_delay)
func get_head_delta*(validator: RewardStatus,
base_reward: uint64,
balances: TotalBalances,
finality_delay: uint64): RewardDelta =
func get_head_delta*(
validator: RewardStatus,
base_reward: Gwei,
balances: TotalBalances,
finality_delay: uint64): RewardDelta =
## Return attester micro-rewards/penalties for head-vote for each validator.
get_attestation_component_delta(
validator.flags.contains(RewardFlags.isPreviousEpochHeadAttester) and
@ -573,9 +578,9 @@ func get_head_delta*(validator: RewardStatus,
base_reward,
finality_delay)
func get_inclusion_delay_delta*(validator: RewardStatus,
base_reward: uint64):
(RewardDelta, Opt[(uint64, RewardDelta)]) =
func get_inclusion_delay_delta*(
validator: RewardStatus,
base_reward: Gwei): (RewardDelta, Opt[(uint64, RewardDelta)]) =
## Return proposer and inclusion delay micro-rewards/penalties for each validator.
if validator.is_previous_epoch_attester.isSome() and ((not validator.flags.contains(RewardFlags.isSlashed))):
let
@ -589,9 +594,10 @@ func get_inclusion_delay_delta*(validator: RewardStatus,
proposer_index = inclusion_info.proposer_index;
return (delta, Opt.some((proposer_index, proposer_delta)))
func get_inactivity_penalty_delta*(validator: RewardStatus,
base_reward: Gwei,
finality_delay: uint64): RewardDelta =
func get_inactivity_penalty_delta*(
validator: RewardStatus,
base_reward: Gwei,
finality_delay: uint64): RewardDelta =
## Return inactivity reward/penalty deltas for each validator.
var delta: RewardDelta
@ -615,11 +621,10 @@ func get_inactivity_penalty_delta*(validator: RewardStatus,
func get_attestation_deltas(
state: phase0.BeaconState, info: var phase0.EpochInfo) =
## Update rewards with attestation reward/penalty deltas for each validator.
let
finality_delay = get_finality_delay(state)
total_balance = info.balances.current_epoch
total_balance_sqrt = integer_squareroot(total_balance)
total_balance_sqrt = integer_squareroot(distinctBase(total_balance))
# Filter out ineligible validators. All sub-functions of the spec do this
# except for `get_inclusion_delay_deltas`. It's safe to do so here because
# any validator that is in the unslashed indices of the matching source
@ -664,15 +669,17 @@ func get_base_reward_increment*(
## Return the base reward for the validator defined by ``index`` with respect
## to the current ``state``.
let increments =
state.validators[index].effective_balance div EFFECTIVE_BALANCE_INCREMENT
state.validators[index].effective_balance div
EFFECTIVE_BALANCE_INCREMENT.Gwei
increments * base_reward_per_increment
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_flag_index_deltas
func get_flag_index_reward*(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState | electra.BeaconState,
base_reward: Gwei, active_increments: Gwei,
unslashed_participating_increments: Gwei,
base_reward: Gwei,
active_increments: uint64,
unslashed_participating_increments: uint64,
weight, finality_delay: uint64): Gwei =
if not is_in_inactivity_leak(finality_delay):
let reward_numerator =
@ -683,13 +690,14 @@ func get_flag_index_reward*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_flag_index_deltas
func get_unslashed_participating_increment*(
info: altair.EpochInfo | bellatrix.BeaconState, flag_index: TimelyFlag): Gwei =
info.balances.previous_epoch[flag_index] div EFFECTIVE_BALANCE_INCREMENT
info: altair.EpochInfo | bellatrix.BeaconState,
flag_index: TimelyFlag): uint64 =
info.balances.previous_epoch[flag_index] div EFFECTIVE_BALANCE_INCREMENT.Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_flag_index_deltas
func get_active_increments*(
info: altair.EpochInfo | bellatrix.BeaconState): Gwei =
info.balances.current_epoch div EFFECTIVE_BALANCE_INCREMENT
info: altair.EpochInfo | bellatrix.BeaconState): uint64 =
info.balances.current_epoch div EFFECTIVE_BALANCE_INCREMENT.Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_flag_index_deltas
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#modified-get_inactivity_penalty_deltas
@ -699,12 +707,14 @@ template get_flag_and_inactivity_delta(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState | electra.BeaconState,
base_reward_per_increment: Gwei, finality_delay: uint64,
previous_epoch: Epoch, active_increments: Gwei,
previous_epoch: Epoch,
active_increments: uint64,
penalty_denominator: uint64,
epoch_participation: ptr EpochParticipationFlags,
participating_increments: array[3, Gwei], info: var altair.EpochInfo,
vidx: ValidatorIndex):
(ValidatorIndex, Gwei, Gwei, Gwei, Gwei, Gwei, Gwei) =
participating_increments: array[3, uint64],
info: var altair.EpochInfo,
vidx: ValidatorIndex
): (ValidatorIndex, Gwei, Gwei, Gwei, Gwei, Gwei, Gwei) =
let
base_reward = get_base_reward_increment(state, vidx, base_reward_per_increment)
pflags =
@ -728,13 +738,13 @@ template get_flag_and_inactivity_delta(
participating_increments[ord(flag)],
PARTICIPATION_FLAG_WEIGHTS[flag], finality_delay)
else:
0
0.Gwei
template penalty(flag: untyped): untyped =
if not has_flag(pflags, flag):
base_reward * PARTICIPATION_FLAG_WEIGHTS[flag] div WEIGHT_DENOMINATOR
else:
0
0.Gwei
let inactivity_penalty =
if has_flag(pflags, TIMELY_TARGET_FLAG_INDEX):
@ -893,7 +903,7 @@ func process_registry_updates*(
get_current_epoch(state) + 1
if is_active_validator(state.validators.item(vidx), get_current_epoch(state)) and
state.validators.item(vidx).effective_balance <= cfg.EJECTION_BALANCE:
state.validators.item(vidx).effective_balance <= cfg.EJECTION_BALANCE.Gwei:
? initiate_validator_exit(cfg, state, vidx, cache)
let validator = unsafeAddr state.validators.item(vidx)
@ -950,7 +960,7 @@ func get_slashing_penalty*(validator: Validator,
adjusted_total_slashing_balance,
total_balance: Gwei): Gwei =
# Factored out from penalty numerator to avoid uint64 overflow
const increment = EFFECTIVE_BALANCE_INCREMENT
const increment = EFFECTIVE_BALANCE_INCREMENT.Gwei
let penalty_numerator = validator.effective_balance div increment *
adjusted_total_slashing_balance
penalty_numerator div total_balance * increment
@ -983,7 +993,8 @@ func process_eth1_data_reset*(state: var ForkyBeaconState) =
template effective_balance_might_update*(
balance: Gwei, effective_balance: Gwei): bool =
const
HYSTERESIS_INCREMENT = EFFECTIVE_BALANCE_INCREMENT div HYSTERESIS_QUOTIENT
HYSTERESIS_INCREMENT =
EFFECTIVE_BALANCE_INCREMENT.Gwei div HYSTERESIS_QUOTIENT
DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
balance + DOWNWARD_THRESHOLD < effective_balance or
@ -999,8 +1010,8 @@ func process_effective_balance_updates*(state: var ForkyBeaconState) =
if effective_balance_might_update(balance, effective_balance):
let new_effective_balance =
min(
balance - balance mod EFFECTIVE_BALANCE_INCREMENT,
MAX_EFFECTIVE_BALANCE)
balance - balance mod EFFECTIVE_BALANCE_INCREMENT.Gwei,
MAX_EFFECTIVE_BALANCE.Gwei)
# Protect against unnecessary cache invalidation
if new_effective_balance != effective_balance:
state.validators.mitem(vidx).effective_balance = new_effective_balance
@ -1081,7 +1092,7 @@ template compute_inactivity_update(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState | electra.BeaconState,
info: altair.EpochInfo,
pre_inactivity_score: Gwei): Gwei =
pre_inactivity_score: uint64): uint64 =
let previous_epoch = get_previous_epoch(state) # get_eligible_validator_indices()
# Increase the inactivity score of inactive validators

View File

@ -372,7 +372,7 @@ template compute_proposer_index(state: ForkyBeaconState,
random_byte = (eth2digest(buffer).data)[i mod 32]
effective_balance = state.validators[candidate_index].effective_balance
if effective_balance * MAX_RANDOM_BYTE >=
MAX_EFFECTIVE_BALANCE * random_byte:
MAX_EFFECTIVE_BALANCE.Gwei * random_byte:
res = Opt.some(candidate_index)
break
i += 1

View File

@ -29,8 +29,8 @@ func compute_weak_subjectivity_period(
ws_period = cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
let
N = get_active_validator_indices_len(state, get_current_epoch(state))
t = (get_total_active_balance(state, cache) div N).toEther
const T = MAX_EFFECTIVE_BALANCE.toEther
t = (get_total_active_balance(state, cache) div N).toEther()
const T = MAX_EFFECTIVE_BALANCE.Gwei.toEther()
let delta = cfg.get_validator_churn_limit(state, cache)
const
Delta = MAX_DEPOSITS * SLOTS_PER_EPOCH

View File

@ -585,8 +585,8 @@ proc registerState*(self: var ValidatorMonitor, state: ForkyBeaconState) =
if self.totals:
var
balance: uint64
effective_balance: uint64
balance: Gwei
effective_balance: Gwei
slashed: int64
active: int64
exited: int64

View File

@ -224,7 +224,7 @@ proc collectEpochRewardsAndPenalties*(
let
finality_delay = get_finality_delay(state)
total_balance = info.balances.current_epoch
total_balance_sqrt = integer_squareroot(total_balance)
total_balance_sqrt = integer_squareroot(distinctBase(total_balance))
for index, validator in info.validators:
if not is_eligible_validator(validator):
@ -233,9 +233,10 @@ proc collectEpochRewardsAndPenalties*(
let base_reward = get_base_reward_sqrt(
state, index.ValidatorIndex, total_balance_sqrt)
template get_attestation_component_reward_helper(attesting_balance: Gwei): Gwei =
template get_attestation_component_reward_helper(
attesting_balance: Gwei): Gwei =
get_attestation_component_reward(attesting_balance,
info.balances.current_epoch, base_reward.uint64, finality_delay)
info.balances.current_epoch, base_reward, finality_delay)
template rp: untyped = rewardsAndPenalties[index]
@ -374,7 +375,7 @@ func collectFromAttestations(
when consensusFork > ConsensusFork.Phase0:
let base_reward_per_increment = get_base_reward_per_increment(
get_total_active_balance(forkyState.data, cache))
doAssert base_reward_per_increment > 0
doAssert base_reward_per_increment > 0.Gwei
for attestation in forkyBlck.message.body.attestations:
doAssert check_attestation(
forkyState.data, attestation, {}, cache).isOk

View File

@ -192,19 +192,19 @@ when isMainModule:
func parseRow(csvRow: CsvRow): RewardsAndPenalties {.raises: [ValueError].} =
result = RewardsAndPenalties(
source_outcome: parseBiggestInt(csvRow[0]),
max_source_reward: parseBiggestUInt(csvRow[1]),
max_source_reward: parseBiggestUInt(csvRow[1]).Gwei,
target_outcome: parseBiggestInt(csvRow[2]),
max_target_reward: parseBiggestUInt(csvRow[3]),
max_target_reward: parseBiggestUInt(csvRow[3]).Gwei,
head_outcome: parseBiggestInt(csvRow[4]),
max_head_reward: parseBiggestUInt(csvRow[5]),
max_head_reward: parseBiggestUInt(csvRow[5]).Gwei,
inclusion_delay_outcome: parseBiggestInt(csvRow[6]),
max_inclusion_delay_reward: parseBiggestUInt(csvRow[7]),
max_inclusion_delay_reward: parseBiggestUInt(csvRow[7]).Gwei,
sync_committee_outcome: parseBiggestInt(csvRow[8]),
max_sync_committee_reward: parseBiggestUInt(csvRow[9]),
max_sync_committee_reward: parseBiggestUInt(csvRow[9]).Gwei,
proposer_outcome: parseBiggestInt(csvRow[10]),
inactivity_penalty: parseBiggestUInt(csvRow[11]),
inactivity_penalty: parseBiggestUInt(csvRow[11]).Gwei,
slashing_outcome: parseBiggestInt(csvRow[12]),
deposits: parseBiggestUInt(csvRow[13]))
deposits: parseBiggestUInt(csvRow[13]).Gwei)
if csvRow[14].len > 0:
result.inclusion_delay = some(parseBiggestUInt(csvRow[14]))

View File

@ -120,7 +120,7 @@ cli do(validatorsDir: string, secretsDir: string,
active = withState(state[]):
get_active_validator_indices_len(forkyState.data, slot.epoch)
balance = block:
var b: uint64
var b: Gwei
for k, _ in validators:
if is_active_validator(getStateField(state[], validators).asSeq[k], slot.epoch):
b += getStateField(state[], balances).asSeq[k]

View File

@ -95,7 +95,7 @@ suite baseDescription & "Attester Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_attester_slashing(
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpAttSlashingDir):
@ -134,7 +134,7 @@ suite baseDescription & "Proposer Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_proposer_slashing(
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpProposerSlashingDir):
@ -149,7 +149,7 @@ suite baseDescription & "Sync Aggregate " & preset():
var cache: StateCache
doAssert (? process_sync_aggregate(
preState, syncAggregate, get_total_active_balance(preState, cache),
{}, cache)) > 0
{}, cache)) > 0.Gwei
ok()
for path in walkTests(OpSyncAggregateDir):

View File

@ -74,7 +74,7 @@ proc runTest(rewardsDir, identifier: string) =
flagDeltas2[TimelyFlag.TIMELY_TARGET_FLAG_INDEX].penalties[validator_index] =
penalty1
flagDeltas2[TimelyFlag.TIMELY_HEAD_FLAG_INDEX].penalties[validator_index] =
0
0.Gwei
inactivityPenaltyDeltas2.penalties[validator_index] = penalty2
check:

View File

@ -100,7 +100,7 @@ suite baseDescription & "Attester Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_attester_slashing(
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpAttSlashingDir):
@ -158,7 +158,7 @@ suite baseDescription & "Proposer Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_proposer_slashing(
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpProposerSlashingDir):
@ -173,7 +173,7 @@ suite baseDescription & "Sync Aggregate " & preset():
var cache: StateCache
doAssert (? process_sync_aggregate(
preState, syncAggregate, get_total_active_balance(preState, cache),
{}, cache)) > 0
{}, cache)) > 0.Gwei
ok()
for path in walkTests(OpSyncAggregateDir):

View File

@ -74,7 +74,7 @@ proc runTest(rewardsDir, identifier: string) =
flagDeltas2[TimelyFlag.TIMELY_TARGET_FLAG_INDEX].penalties[validator_index] =
penalty1
flagDeltas2[TimelyFlag.TIMELY_HEAD_FLAG_INDEX].penalties[validator_index] =
0
0.Gwei
inactivityPenaltyDeltas2.penalties[validator_index] = penalty2
check:

View File

@ -104,7 +104,7 @@ suite baseDescription & "Attester Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_attester_slashing(
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpAttSlashingDir):
@ -175,7 +175,7 @@ suite baseDescription & "Proposer Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_proposer_slashing(
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpProposerSlashingDir):
@ -190,7 +190,7 @@ suite baseDescription & "Sync Aggregate " & preset():
var cache: StateCache
doAssert (? process_sync_aggregate(
preState, syncAggregate, get_total_active_balance(preState, cache),
{}, cache)) > 0
{}, cache)) > 0.Gwei
ok()
for path in walkTests(OpSyncAggregateDir):

View File

@ -5,6 +5,7 @@
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].}
{.used.}
import
@ -73,7 +74,7 @@ proc runTest(rewardsDir, identifier: string) =
flagDeltas2[TimelyFlag.TIMELY_TARGET_FLAG_INDEX].penalties[validator_index] =
penalty1
flagDeltas2[TimelyFlag.TIMELY_HEAD_FLAG_INDEX].penalties[validator_index] =
0
0.Gwei
inactivityPenaltyDeltas2.penalties[validator_index] = penalty2
check:

View File

@ -104,7 +104,7 @@ suite baseDescription & "Attester Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_attester_slashing(
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpAttSlashingDir):
@ -177,7 +177,7 @@ suite baseDescription & "Proposer Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_proposer_slashing(
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpProposerSlashingDir):
@ -192,7 +192,7 @@ suite baseDescription & "Sync Aggregate " & preset():
var cache: StateCache
doAssert (? process_sync_aggregate(
preState, syncAggregate, get_total_active_balance(preState, cache),
{}, cache)) > 0
{}, cache)) > 0.Gwei
ok()
for path in walkTests(OpSyncAggregateDir):

View File

@ -74,7 +74,7 @@ proc runTest(rewardsDir, identifier: string) =
flagDeltas2[TimelyFlag.TIMELY_TARGET_FLAG_INDEX].penalties[validator_index] =
penalty1
flagDeltas2[TimelyFlag.TIMELY_HEAD_FLAG_INDEX].penalties[validator_index] =
0
0.Gwei
inactivityPenaltyDeltas2.penalties[validator_index] = penalty2
check:

View File

@ -74,8 +74,8 @@ type
# https://github.com/ethereum/consensus-specs/tree/v1.3.0/tests/formats/rewards#rewards-tests
Deltas* = object
rewards*: List[uint64, Limit VALIDATOR_REGISTRY_LIMIT]
penalties*: List[uint64, Limit VALIDATOR_REGISTRY_LIMIT]
rewards*: List[Gwei, Limit VALIDATOR_REGISTRY_LIMIT]
penalties*: List[Gwei, Limit VALIDATOR_REGISTRY_LIMIT]
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/validator.md#eth1block
Eth1Block* = object

View File

@ -72,7 +72,7 @@ suite baseDescription & "Attestation " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_attestation(
preState, attestation, {}, 0.Gwei, cache)) == 0
preState, attestation, {}, 0.Gwei, cache)) == 0.Gwei
ok()
for path in walkTests(OpAttestationsDir):
@ -86,7 +86,7 @@ suite baseDescription & "Attester Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_attester_slashing(
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpAttSlashingDir):
@ -126,7 +126,7 @@ suite baseDescription & "Proposer Slashing " & preset():
Result[void, cstring] =
var cache: StateCache
doAssert (? process_proposer_slashing(
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)) > 0.Gwei
ok()
for path in walkTests(OpProposerSlashingDir):

View File

@ -58,7 +58,7 @@ proc runTest(rewardsDir, identifier: string) =
info.process_attestations(state[], cache)
let
total_balance = info.balances.current_epoch
total_balance_sqrt = integer_squareroot(total_balance)
total_balance_sqrt = integer_squareroot(distinctBase(total_balance))
var
sourceDeltas2 = Deltas.init(state[].validators.len)

View File

@ -1,12 +0,0 @@
# beacon_chain
# Copyright (c) 2018-2024 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].}
func round_multiple_down*(x: uint64, n: uint64): uint64 =
## Round the input to the previous multiple of "n"
x - x mod n

View File

@ -11,11 +11,9 @@
# ---------------------------------------------------------------
import
# Standard library
std/math,
# Specs
../../beacon_chain/spec/[eth2_merkleization, keystore, forks, signatures],
../../beacon_chain/spec/[
eth2_merkleization, keystore, forks, helpers, signatures],
../../beacon_chain/spec/datatypes/base,
# Internals
@ -25,10 +23,7 @@ import
# Test utilities
../testblockutil
func mockDepositData(
pubkey: ValidatorPubKey,
amount: uint64,
): DepositData =
func mockDepositData(pubkey: ValidatorPubKey, amount: Gwei): DepositData =
# Insecurely use pubkey as withdrawal key
DepositData(
pubkey: pubkey,
@ -37,12 +32,12 @@ func mockDepositData(
)
func mockDepositData(
pubkey: ValidatorPubKey,
privkey: ValidatorPrivKey,
amount: uint64,
# withdrawal_credentials: Eth2Digest,
flags: UpdateFlags = {}
): DepositData =
pubkey: ValidatorPubKey,
privkey: ValidatorPrivKey,
amount: Gwei,
# withdrawal_credentials: Eth2Digest,
flags: UpdateFlags = {}
): DepositData =
var ret = mockDepositData(pubkey, amount)
if skipBlsValidation notin flags:
ret.signature = defaultRuntimeConfig.get_deposit_signature(ret, privkey).toValidatorSig()
@ -92,10 +87,10 @@ template mockGenesisDepositsImpl(
depositsDataHash.add hash_tree_root(result[valIdx])
proc mockGenesisBalancedDeposits*(
validatorCount: uint64,
amountInEth: Positive,
flags: UpdateFlags = {}
): seq[DepositData] =
validatorCount: uint64,
amountInEth: Ether,
flags: UpdateFlags = {}
): seq[DepositData] =
## The amount should be strictly positive
## - 1 is the minimum deposit amount (MIN_DEPOSIT_AMOUNT)
## - 16 is the ejection balance (EJECTION_BALANCE)
@ -104,19 +99,17 @@ proc mockGenesisBalancedDeposits*(
##
## Only validators with 32 ETH will be active at genesis
let amount = amountInEth.uint64 * 10'u64^9
let amount = amountInEth.toGwei()
mockGenesisDepositsImpl(result, validatorCount,amount,flags):
discard
proc mockUpdateStateForNewDeposit*(
state: var ForkyBeaconState,
validator_index: uint64,
amount: uint64,
amount: Gwei,
# withdrawal_credentials: Eth2Digest
flags: UpdateFlags
): Deposit =
# TODO withdrawal credentials
result.data = mockDepositData(

View File

@ -24,7 +24,7 @@ proc initGenesisState*(
cfg = defaultRuntimeConfig): ref ForkedHashedBeaconState =
let deposits = mockGenesisBalancedDeposits(
validatorCount = num_validators,
amountInEth = 32, # We create canonical validators with 32 Eth
amountInEth = 32.Ether, # We create canonical validators with 32 Eth
flags = {}
)

View File

@ -62,7 +62,7 @@ proc makeDeposit*(
result = DepositData(
pubkey: pubkey,
withdrawal_credentials: withdrawal_credentials,
amount: MAX_EFFECTIVE_BALANCE)
amount: MAX_EFFECTIVE_BALANCE.Gwei)
if skipBlsValidation notin flags:
result.signature = get_deposit_signature(cfg, result, privkey).toValidatorSig()

View File

@ -13,11 +13,14 @@ import
../beacon_chain/spec/[
forks, state_transition, state_transition_block]
from "."/helpers/math_helpers import round_multiple_down
from ".."/beacon_chain/bloomfilter import constructBloomFilter
func round_multiple_down(x: Gwei, n: Gwei): Gwei =
## Round the input to the previous multiple of "n"
x - x mod n
proc valid_deposit(state: var ForkyHashedBeaconState) =
const deposit_amount = MAX_EFFECTIVE_BALANCE
const deposit_amount = MAX_EFFECTIVE_BALANCE.Gwei
let validator_index = state.data.validators.len
let deposit = mockUpdateStateForNewDeposit(
state.data,
@ -30,7 +33,7 @@ proc valid_deposit(state: var ForkyHashedBeaconState) =
let pre_balance = if validator_index < pre_val_count:
state.data.balances.item(validator_index)
else:
0
0.Gwei
doAssert process_deposit(
defaultRuntimeConfig, state.data,
constructBloomFilter(state.data.validators.asSeq)[], deposit, {}).isOk
@ -39,8 +42,10 @@ proc valid_deposit(state: var ForkyHashedBeaconState) =
doAssert state.data.balances.item(validator_index) == pre_balance + deposit.data.amount
doAssert state.data.validators.item(validator_index).effective_balance ==
round_multiple_down(
min(MAX_EFFECTIVE_BALANCE, state.data.balances.item(validator_index)),
EFFECTIVE_BALANCE_INCREMENT
min(
MAX_EFFECTIVE_BALANCE.Gwei,
state.data.balances.item(validator_index)),
EFFECTIVE_BALANCE_INCREMENT.Gwei
)
state.root = hash_tree_root(state.data)