another ~2x speedup in epoch processing

This commit is contained in:
Dustin Brody 2019-03-27 18:20:11 -07:00 committed by zah
parent e1ba820486
commit 6f481f8812
1 changed files with 35 additions and 14 deletions

View File

@ -630,7 +630,9 @@ func get_winning_root_and_participants(
winning_root_balance = root_balance winning_root_balance = root_balance
(winning_root, (winning_root,
get_attesting_indices(state, attestations_for.getOrDefault(winning_root))) get_attesting_indices_cached(
state,
attestations_for.getOrDefault(winning_root), crosslink_committees_cache))
# Combination of earliest_attestation and inclusion_slot avoiding O(n^2) # Combination of earliest_attestation and inclusion_slot avoiding O(n^2)
# TODO merge/refactor these two functions, which differ only very slightly. # TODO merge/refactor these two functions, which differ only very slightly.
@ -728,7 +730,8 @@ func update_justification_and_finalization(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#crosslinks # https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#crosslinks
func process_crosslinks( func process_crosslinks(
state: var BeaconState, crosslink_committee_cache: var auto) = state: var BeaconState, crosslink_committee_cache: var auto,
winning_root_participants_cache: var auto) =
let let
current_epoch = get_current_epoch(state) current_epoch = get_current_epoch(state)
previous_epoch = current_epoch - 1 previous_epoch = current_epoch - 1
@ -747,11 +750,20 @@ func process_crosslinks(
state, slot, false, crosslink_committee_cache): state, slot, false, crosslink_committee_cache):
let let
(crosslink_committee, shard) = cas (crosslink_committee, shard) = cas
(winning_root, participants) = get_winning_root_and_participants( # In general, it'll loop over the same shards twice, and
# get_winning_root_and_participants is defined to return
# the same results from the previous epoch as current.
(winning_root, participants) =
if shard notin winning_root_participants_cache:
get_winning_root_and_participants(
state, shard, crosslink_committee_cache) state, shard, crosslink_committee_cache)
else:
(ZERO_HASH, winning_root_participants_cache[shard])
participating_balance = get_total_balance(state, participants) participating_balance = get_total_balance(state, participants)
total_balance = get_total_balance(state, crosslink_committee) total_balance = get_total_balance(state, crosslink_committee)
winning_root_participants_cache[shard] = participants
if 3'u64 * participating_balance >= 2'u64 * total_balance: if 3'u64 * participating_balance >= 2'u64 * total_balance:
# Check not from spec; seems kludgy # Check not from spec; seems kludgy
doAssert slot >= GENESIS_SLOT doAssert slot >= GENESIS_SLOT
@ -844,7 +856,7 @@ func compute_normal_justification_and_finalization_deltas(state: BeaconState):
else: else:
deltas[1][index] += get_base_reward(state, index) deltas[1][index] += get_base_reward(state, index)
# Expected head # Expected head
if index in get_attesting_indices(state, matching_head_attestations): if index in matching_head_attestation_indices:
deltas[0][index] += deltas[0][index] +=
get_base_reward(state, index) * get_base_reward(state, index) *
matching_head_balance div total_balance matching_head_balance div total_balance
@ -929,7 +941,9 @@ func get_justification_and_finalization_deltas(state: BeaconState):
compute_inactivity_leak_deltas(state) compute_inactivity_leak_deltas(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslinks-1 # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslinks-1
func get_crosslink_deltas(state: BeaconState, crosslink_committees_cache: var auto): func get_crosslink_deltas(
state: BeaconState, crosslink_committees_cache: var auto,
winning_root_participants_cache: var auto):
tuple[a: seq[Gwei], b: seq[Gwei]] = tuple[a: seq[Gwei], b: seq[Gwei]] =
# deltas[0] for rewards # deltas[0] for rewards
# deltas[1] for penalties # deltas[1] for penalties
@ -949,11 +963,11 @@ func get_crosslink_deltas(state: BeaconState, crosslink_committees_cache: var au
(crosslink_committee, shard) = cas (crosslink_committee, shard) = cas
(winning_root, participants) = get_winning_root_and_participants( (winning_root, participants) = get_winning_root_and_participants(
state, shard, crosslink_committees_cache) state, shard, crosslink_committees_cache)
nonquadraticParticipants = toSet(participants)
participating_balance = get_total_balance(state, participants) participating_balance = get_total_balance(state, participants)
total_balance = get_total_balance(state, crosslink_committee) total_balance = get_total_balance(state, crosslink_committee)
# In principle quadratic, but should be small.
for index in crosslink_committee: for index in crosslink_committee:
if index in participants: if index in nonquadraticParticipants:
deltas[0][index] += deltas[0][index] +=
get_base_reward(state, index) * participating_balance div get_base_reward(state, index) * participating_balance div
total_balance total_balance
@ -964,10 +978,12 @@ func get_crosslink_deltas(state: BeaconState, crosslink_committees_cache: var au
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#apply-rewards # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#apply-rewards
func apply_rewards( func apply_rewards(
state: var BeaconState, crosslink_committees_cache: var auto) = state: var BeaconState, crosslink_committees_cache: var auto,
winning_root_participants_cache: var auto) =
let let
deltas1 = get_justification_and_finalization_deltas(state) deltas1 = get_justification_and_finalization_deltas(state)
deltas2 = get_crosslink_deltas(state, crosslink_committees_cache) deltas2 = get_crosslink_deltas(
state, crosslink_committees_cache, winning_root_participants_cache)
for i in 0 ..< len(state.validator_registry): for i in 0 ..< len(state.validator_registry):
state.validator_balances[i] = state.validator_balances[i] =
max( max(
@ -1081,16 +1097,21 @@ func processEpoch(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#justification # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#justification
update_justification_and_finalization(state) update_justification_and_finalization(state)
var crosslink_committee_cache = var
crosslink_committee_cache =
initTable[tuple[a: uint64, b: bool], seq[CrosslinkCommittee]]() initTable[tuple[a: uint64, b: bool], seq[CrosslinkCommittee]]()
winning_root_participants_cache =
initTable[Shard, seq[ValidatorIndex]]()
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslinks # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslinks
process_crosslinks(state, crosslink_committee_cache) process_crosslinks(
state, crosslink_committee_cache, winning_root_participants_cache)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1-data # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1-data
maybe_reset_eth1_period(state) maybe_reset_eth1_period(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#apply-rewards # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#apply-rewards
apply_rewards(state, crosslink_committee_cache) apply_rewards(
state, crosslink_committee_cache, winning_root_participants_cache)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#ejections # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#ejections
process_ejections(state) process_ejections(state)