nimbus-eth2/beacon_chain/fork_choice.nim

62 lines
2.2 KiB
Nim
Raw Normal View History

2018-11-26 13:33:06 +00:00
import
deques, math, options, sequtils, tables,
chronicles,
./spec/[beaconstate, datatypes, crypto, digest, helpers, validator], extras,
./attestation_pool, ./beacon_node_types, ./beacon_chain_db, ./ssz
proc get_ancestor(blck: BlockRef, slot: Slot): BlockRef =
if blck.slot == slot:
2019-01-14 12:19:44 +00:00
blck
elif blck.slot < slot:
nil
2019-01-08 17:28:21 +00:00
else:
get_ancestor(blck.parent, slot)
2019-01-08 17:28:21 +00:00
# https://github.com/ethereum/eth2.0-specs/blob/v0.4.0/specs/core/0_beacon-chain.md#beacon-chain-fork-choice-rule
2019-01-14 12:19:44 +00:00
proc lmdGhost*(
pool: AttestationPool, start_state: BeaconState,
start_block: BlockRef): BlockRef =
2019-01-08 17:28:21 +00:00
# TODO: a Fenwick Tree datastructure to keep track of cumulated votes
# in O(log N) complexity
# https://en.wikipedia.org/wiki/Fenwick_tree
# Nim implementation for cumulative frequencies at
# https://github.com/numforge/laser/blob/990e59fffe50779cdef33aa0b8f22da19e1eb328/benchmarks/random_sampling/fenwicktree.nim
const FORK_CHOICE_BALANCE_INCREMENT = 2'u64^0 * 10'u64^9
let
active_validator_indices =
get_active_validator_indices(
start_state, compute_epoch_of_slot(start_state.slot))
var attestation_targets: seq[tuple[validator: ValidatorIndex, blck: BlockRef]]
for i in active_validator_indices:
let pubKey = start_state.validators[i].pubkey
if (let vote = pool.latestAttestation(pubKey); not vote.isNil):
attestation_targets.add((i, vote))
template get_vote_count(blck: BlockRef): uint64 =
var res: uint64
for validator_index, target in attestation_targets.items():
if get_ancestor(target, blck.slot) == blck:
# The div on the balance is to chop off the insignification bits that
# fluctuate a lot epoch to epoch to have a more stable fork choice
0.6.2 updates (#275) * update process_justification_and_finalization to 0.6.2; mark AttesterSlashing as 0.6.2 * replace get_effective_balance(...) with state.validator_registry[idx].effective_balance; rm get_effective_balance, process_ejections, should_update_validator_registry, update_validator_registry, and update_registry_and_shuffling_data; update get_total_balance to 0.6.2; implement process_registry_updates * rm exit_validator; implement is_slashable_attestation_data; partly update processAttesterSlashings * mark HistoricalBatch and Eth1Data as 0.6.2; implement get_shard_delta(...); replace 0.5 finish_epoch_update with 0.6 process_final_updates * mark increase_balance, decrease_balance, get_delayed_activation_exit_epoch, bls_aggregate_pubkeys, bls_verify_multiple, Attestation, Transfer, slot_to_epoch, Crosslink, get_current_epoch, int_to_bytes*, various constants, processEth1Data, processTransfers, and verifyStateRoot as 0.6.2; rm is_double_vote and is_surround_vote * mark get_bitfield_bit, verify_bitfield, ProposerSlashing, DepositData, VoluntaryExit, PendingAttestation, Fork, integer_squareroot, get_epoch_start_slot, is_active_validator, generate_seed, some constants to 0.6.2; rename MIN_PENALTY_QUOTIENT to MIN_SLASHING_PENALTY_QUOTIENT * rm get_previous_total_balance, get_current_epoch_boundary_attestations, get_previous_epoch_boundary_attestations, and get_previous_epoch_matching_head_attestations * update BeaconState to 0.6.2; simplify legacy get_crosslink_committees_at_slot infrastructure a bit by noting that registry_change is always false; reimplment 0.5 get_crosslink_committees_at_slot in terms of 0.6 get_crosslink_committee * mark process_deposit(...), get_block_root_at_slot(...), get_block_root(...), Deposit, BeaconBlockHeader, BeaconBlockBody, hash(...), get_active_index_root(...), various constants, get_shard_delta(...), get_epoch_start_shard(...), get_crosslink_committee(...), processRandao(...), processVoluntaryExits(...), cacheState(...) as 0.6.2 * rm removed-since-0.5 split(...), is_power_of_2(...), get_shuffling(...); rm 0.5 versions of get_active_validator_indices and get_epoch_committee_count; add a few tests for integer_squareroot * mark bytes_to_int(...) and advanceState(...) as 0.6.2 * rm 0.5 get_attesting_indices; update get_attesting_balance to 0.6.2 * another tiny commit to poke AppVeyor to maybe not timeout at connecting to GitHub partway through CI: mark get_churn_limit(...), initiate_validator_exit(...), and Validator as 0.6.2 * mark get_attestation_slot(...), AttestationDataAndCustodyBit, and BeaconBlock as 0.6.2
2019-06-03 10:31:04 +00:00
res +=
start_state.validators[validator_index].effective_balance div
FORK_CHOICE_BALANCE_INCREMENT
res
var head = start_block
while true:
if head.children.len() == 0:
return head
head = head.children[0]
var
headCount = get_vote_count(head)
for i in 1..<head.children.len:
if (let hc = get_vote_count(head.children[i]); hc > headCount):
head = head.children[i]
headCount = hc