small perf fixes
* don't sort shuffled_validator_indices, just get them directly with iteration * grab full epoch of proposer indices while we have the data available - they'll get cached and reused * avoid computing active validator set when not used for logging
This commit is contained in:
parent
2c19e3f8cd
commit
7de05efaaf
|
@ -658,7 +658,8 @@ proc updateStateData*(
|
||||||
slots = state.data.data.slot - startSlot,
|
slots = state.data.data.slot - startSlot,
|
||||||
stateRoot = shortLog(state.data.root),
|
stateRoot = shortLog(state.data.root),
|
||||||
stateSlot = state.data.data.slot,
|
stateSlot = state.data.data.slot,
|
||||||
stateRoot = shortLog(startRoot),
|
startRoot = shortLog(startRoot),
|
||||||
|
startSlot,
|
||||||
blck = shortLog(bs)
|
blck = shortLog(bs)
|
||||||
|
|
||||||
proc loadTailState*(dag: ChainDAGRef): StateData =
|
proc loadTailState*(dag: ChainDAGRef): StateData =
|
||||||
|
|
|
@ -101,7 +101,7 @@ func get_attesting_balance(
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/beacon-chain.md#justification-and-finalization
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/beacon-chain.md#justification-and-finalization
|
||||||
proc process_justification_and_finalization*(state: var BeaconState,
|
proc process_justification_and_finalization*(state: var BeaconState,
|
||||||
stateCache: var StateCache, updateFlags: UpdateFlags = {}) {.nbench.} =
|
cache: var StateCache, updateFlags: UpdateFlags = {}) {.nbench.} =
|
||||||
|
|
||||||
logScope: pcs = "process_justification_and_finalization"
|
logScope: pcs = "process_justification_and_finalization"
|
||||||
|
|
||||||
|
@ -126,20 +126,19 @@ proc process_justification_and_finalization*(state: var BeaconState,
|
||||||
state.justification_bits = (state.justification_bits shl 1) and
|
state.justification_bits = (state.justification_bits shl 1) and
|
||||||
cast[uint8]((2^JUSTIFICATION_BITS_LENGTH) - 1)
|
cast[uint8]((2^JUSTIFICATION_BITS_LENGTH) - 1)
|
||||||
|
|
||||||
# This is a somewhat expensive approach
|
|
||||||
let active_validator_indices {.used.} =
|
|
||||||
toHashSet(mapIt(
|
|
||||||
get_active_validator_indices(state, get_current_epoch(state)), it.uint32))
|
|
||||||
|
|
||||||
let matching_target_attestations_previous =
|
let matching_target_attestations_previous =
|
||||||
get_matching_target_attestations(state, previous_epoch) # Previous epoch
|
get_matching_target_attestations(state, previous_epoch) # Previous epoch
|
||||||
|
|
||||||
if verifyFinalization in updateFlags:
|
if verifyFinalization in updateFlags:
|
||||||
|
let active_validator_indices =
|
||||||
|
toHashSet(cache.get_shuffled_active_validator_indices(
|
||||||
|
state, get_current_epoch(state)))
|
||||||
|
|
||||||
# Non-attesting indices in previous epoch
|
# Non-attesting indices in previous epoch
|
||||||
let missing_all_validators =
|
let missing_all_validators =
|
||||||
difference(active_validator_indices,
|
difference(active_validator_indices,
|
||||||
toHashSet(mapIt(get_attesting_indices(state,
|
get_attesting_indices(
|
||||||
matching_target_attestations_previous, stateCache), it.uint32)))
|
state, matching_target_attestations_previous, cache))
|
||||||
|
|
||||||
# testnet0 and testnet1 have 8 non-attesting validators each, by default
|
# testnet0 and testnet1 have 8 non-attesting validators each, by default
|
||||||
if missing_all_validators.len > 15:
|
if missing_all_validators.len > 15:
|
||||||
|
@ -157,42 +156,48 @@ proc process_justification_and_finalization*(state: var BeaconState,
|
||||||
# and
|
# and
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/beacon-chain.md#final-updates
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/beacon-chain.md#final-updates
|
||||||
# after which the state.previous_epoch_attestations is replaced.
|
# after which the state.previous_epoch_attestations is replaced.
|
||||||
let total_active_balance = get_total_active_balance(state, stateCache)
|
let total_active_balance = get_total_active_balance(state, cache)
|
||||||
|
when chronicles.enabledLogLevel == LogLevel.TRACE:
|
||||||
|
let active_validator_indices =
|
||||||
|
toHashSet(cache.get_shuffled_active_validator_indices(
|
||||||
|
state, get_current_epoch(state)))
|
||||||
|
|
||||||
trace "Non-attesting indices in previous epoch",
|
trace "Non-attesting indices in previous epoch",
|
||||||
missing_all_validators=
|
missing_all_validators =
|
||||||
|
difference(active_validator_indices, get_attesting_indices(
|
||||||
|
state, matching_target_attestations_previous, cache)),
|
||||||
|
missing_unslashed_validators =
|
||||||
difference(active_validator_indices,
|
difference(active_validator_indices,
|
||||||
toHashSet(mapIt(get_attesting_indices(state,
|
get_unslashed_attesting_indices(
|
||||||
matching_target_attestations_previous, stateCache), it.uint32))),
|
state, matching_target_attestations_previous, cache)),
|
||||||
missing_unslashed_validators=
|
prev_attestations_len = len(state.previous_epoch_attestations),
|
||||||
difference(active_validator_indices,
|
cur_attestations_len = len(state.current_epoch_attestations),
|
||||||
toHashSet(mapIt(get_unslashed_attesting_indices(state,
|
num_active_validators = len(active_validator_indices),
|
||||||
matching_target_attestations_previous, stateCache), it.uint32))),
|
total_active_balance,
|
||||||
prev_attestations_len=len(state.previous_epoch_attestations),
|
attesting_balance_prev = get_attesting_balance(
|
||||||
cur_attestations_len=len(state.current_epoch_attestations),
|
state, matching_target_attestations_previous, cache)
|
||||||
num_active_validators=len(active_validator_indices),
|
|
||||||
required_balance = total_active_balance * 2,
|
|
||||||
attesting_balance_prev = get_attesting_balance(state, matching_target_attestations_previous, stateCache)
|
|
||||||
if get_attesting_balance(state, matching_target_attestations_previous,
|
if get_attesting_balance(state, matching_target_attestations_previous,
|
||||||
stateCache) * 3 >= total_active_balance * 2:
|
cache) * 3 >= total_active_balance * 2:
|
||||||
state.current_justified_checkpoint =
|
state.current_justified_checkpoint =
|
||||||
Checkpoint(epoch: previous_epoch,
|
Checkpoint(epoch: previous_epoch,
|
||||||
root: get_block_root(state, previous_epoch))
|
root: get_block_root(state, previous_epoch))
|
||||||
state.justification_bits.setBit 1
|
state.justification_bits.setBit 1
|
||||||
|
|
||||||
debug "Justified with previous epoch",
|
trace "Justified with previous epoch",
|
||||||
current_epoch = current_epoch,
|
current_epoch = current_epoch,
|
||||||
checkpoint = shortLog(state.current_justified_checkpoint)
|
checkpoint = shortLog(state.current_justified_checkpoint)
|
||||||
|
|
||||||
let matching_target_attestations_current =
|
let matching_target_attestations_current =
|
||||||
get_matching_target_attestations(state, current_epoch) # Current epoch
|
get_matching_target_attestations(state, current_epoch) # Current epoch
|
||||||
if get_attesting_balance(state, matching_target_attestations_current,
|
if get_attesting_balance(state, matching_target_attestations_current,
|
||||||
stateCache) * 3 >= total_active_balance * 2:
|
cache) * 3 >= total_active_balance * 2:
|
||||||
state.current_justified_checkpoint =
|
state.current_justified_checkpoint =
|
||||||
Checkpoint(epoch: current_epoch,
|
Checkpoint(epoch: current_epoch,
|
||||||
root: get_block_root(state, current_epoch))
|
root: get_block_root(state, current_epoch))
|
||||||
state.justification_bits.setBit 0
|
state.justification_bits.setBit 0
|
||||||
|
|
||||||
debug "Justified with current epoch",
|
trace "Justified with current epoch",
|
||||||
current_epoch = current_epoch,
|
current_epoch = current_epoch,
|
||||||
checkpoint = shortLog(state.current_justified_checkpoint)
|
checkpoint = shortLog(state.current_justified_checkpoint)
|
||||||
|
|
||||||
|
@ -205,7 +210,7 @@ proc process_justification_and_finalization*(state: var BeaconState,
|
||||||
old_previous_justified_checkpoint.epoch + 3 == current_epoch:
|
old_previous_justified_checkpoint.epoch + 3 == current_epoch:
|
||||||
state.finalized_checkpoint = old_previous_justified_checkpoint
|
state.finalized_checkpoint = old_previous_justified_checkpoint
|
||||||
|
|
||||||
debug "Finalized with rule 234",
|
trace "Finalized with rule 234",
|
||||||
current_epoch = current_epoch,
|
current_epoch = current_epoch,
|
||||||
checkpoint = shortLog(state.finalized_checkpoint)
|
checkpoint = shortLog(state.finalized_checkpoint)
|
||||||
|
|
||||||
|
@ -215,7 +220,7 @@ proc process_justification_and_finalization*(state: var BeaconState,
|
||||||
old_previous_justified_checkpoint.epoch + 2 == current_epoch:
|
old_previous_justified_checkpoint.epoch + 2 == current_epoch:
|
||||||
state.finalized_checkpoint = old_previous_justified_checkpoint
|
state.finalized_checkpoint = old_previous_justified_checkpoint
|
||||||
|
|
||||||
debug "Finalized with rule 23",
|
trace "Finalized with rule 23",
|
||||||
current_epoch = current_epoch,
|
current_epoch = current_epoch,
|
||||||
checkpoint = shortLog(state.finalized_checkpoint)
|
checkpoint = shortLog(state.finalized_checkpoint)
|
||||||
|
|
||||||
|
@ -225,7 +230,7 @@ proc process_justification_and_finalization*(state: var BeaconState,
|
||||||
old_current_justified_checkpoint.epoch + 2 == current_epoch:
|
old_current_justified_checkpoint.epoch + 2 == current_epoch:
|
||||||
state.finalized_checkpoint = old_current_justified_checkpoint
|
state.finalized_checkpoint = old_current_justified_checkpoint
|
||||||
|
|
||||||
debug "Finalized with rule 123",
|
trace "Finalized with rule 123",
|
||||||
current_epoch = current_epoch,
|
current_epoch = current_epoch,
|
||||||
checkpoint = shortLog(state.finalized_checkpoint)
|
checkpoint = shortLog(state.finalized_checkpoint)
|
||||||
|
|
||||||
|
@ -235,7 +240,7 @@ proc process_justification_and_finalization*(state: var BeaconState,
|
||||||
old_current_justified_checkpoint.epoch + 1 == current_epoch:
|
old_current_justified_checkpoint.epoch + 1 == current_epoch:
|
||||||
state.finalized_checkpoint = old_current_justified_checkpoint
|
state.finalized_checkpoint = old_current_justified_checkpoint
|
||||||
|
|
||||||
debug "Finalized with rule 12",
|
trace "Finalized with rule 12",
|
||||||
current_epoch = current_epoch,
|
current_epoch = current_epoch,
|
||||||
checkpoint = shortLog(state.finalized_checkpoint)
|
checkpoint = shortLog(state.finalized_checkpoint)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
algorithm, options, sequtils, math, tables,
|
options, sequtils, math, tables,
|
||||||
./datatypes, ./digest, ./helpers
|
./datatypes, ./digest, ./helpers
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/beacon-chain.md#compute_shuffled_index
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/beacon-chain.md#compute_shuffled_index
|
||||||
|
@ -296,17 +296,25 @@ func get_beacon_proposer_index*(state: BeaconState, cache: var StateCache, slot:
|
||||||
|
|
||||||
var buffer: array[32 + 8, byte]
|
var buffer: array[32 + 8, byte]
|
||||||
buffer[0..31] = get_seed(state, epoch, DOMAIN_BEACON_PROPOSER).data
|
buffer[0..31] = get_seed(state, epoch, DOMAIN_BEACON_PROPOSER).data
|
||||||
buffer[32..39] = uint_to_bytes8(slot.uint64)
|
|
||||||
|
|
||||||
# There's exactly one beacon proposer per slot.
|
# There's exactly one beacon proposer per slot.
|
||||||
|
|
||||||
let
|
let
|
||||||
seed = eth2digest(buffer)
|
# active validator indices are kept in cache but sorting them takes
|
||||||
indices =
|
# quite a while
|
||||||
sorted(cache.get_shuffled_active_validator_indices(state, epoch), system.cmp)
|
indices = get_active_validator_indices(state, epoch)
|
||||||
|
start = slot.epoch().compute_start_slot_at_epoch()
|
||||||
|
|
||||||
return cache.beacon_proposer_indices.mgetOrPut(
|
var res: Option[ValidatorIndex]
|
||||||
slot, compute_proposer_index(state, indices, seed))
|
for i in 0..<SLOTS_PER_EPOCH:
|
||||||
|
buffer[32..39] = uint_to_bytes8((start + i).uint64)
|
||||||
|
let seed = eth2digest(buffer)
|
||||||
|
let pi = compute_proposer_index(state, indices, seed)
|
||||||
|
if start + i == slot:
|
||||||
|
res = pi
|
||||||
|
cache.beacon_proposer_indices[start + i] = pi
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/beacon-chain.md#get_beacon_proposer_index
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/beacon-chain.md#get_beacon_proposer_index
|
||||||
func get_beacon_proposer_index*(state: BeaconState, cache: var StateCache):
|
func get_beacon_proposer_index*(state: BeaconState, cache: var StateCache):
|
||||||
|
|
Loading…
Reference in New Issue