restore EpochRef and flush statecaches on epoch transitions (#1312)
* restore EpochRef and flush statecaches on epoch transitions * more targeted cache invalidation * remove get_empty_per_epoch_cache(); implement simpler but still faster get_beacon_proposer_index()/compute_proposer_index() approach; add some abstraction layer for accessing the shuffled validator indices cache * reduce integer type conversions * remove most of rest of integer type conversion in compute_proposer_index()
This commit is contained in:
parent
4aefd8b021
commit
26e893ffc2
|
@ -48,7 +48,7 @@ proc aggregate_attestations*(
|
|||
# TODO for testing purposes, refactor this into the condition check
|
||||
# and just calculation
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#aggregation-selection
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
if not is_aggregator(state, slot, index, slot_signature, cache):
|
||||
return none(AggregateAndProof)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import
|
|||
# Status libraries
|
||||
chronicles, stew/[byteutils], json_serialization/std/sets,
|
||||
# Internal
|
||||
./spec/[beaconstate, datatypes, crypto, digest, helpers, validator],
|
||||
./spec/[beaconstate, datatypes, crypto, digest, helpers],
|
||||
./extras, ./block_pool, ./block_pools/candidate_chains, ./beacon_node_types,
|
||||
./fork_choice/fork_choice
|
||||
|
||||
|
@ -464,7 +464,7 @@ proc getAttestationsForBlock*(pool: AttestationPool,
|
|||
if attestations.len == 0:
|
||||
return
|
||||
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
for a in attestations:
|
||||
var
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#construct-attestation
|
||||
|
|
|
@ -14,7 +14,9 @@ import
|
|||
metrics,
|
||||
# Internals
|
||||
../ssz/merkleization, ../beacon_chain_db, ../extras,
|
||||
../spec/[crypto, datatypes, digest, helpers, validator, state_transition],
|
||||
../spec/[
|
||||
crypto, datatypes, digest, helpers, validator, state_transition,
|
||||
beaconstate],
|
||||
block_pools_types
|
||||
|
||||
declareCounter beacon_reorgs_total, "Total occurrences of reorganizations of the chain" # On fork choice
|
||||
|
@ -58,7 +60,7 @@ func parent*(bs: BlockSlot): BlockSlot =
|
|||
)
|
||||
|
||||
func populateEpochCache(state: BeaconState, epoch: Epoch): EpochRef =
|
||||
result = (EpochRef)(
|
||||
(EpochRef)(
|
||||
epoch: state.slot.compute_epoch_at_slot,
|
||||
shuffled_active_validator_indices:
|
||||
get_shuffled_active_validator_indices(state, epoch))
|
||||
|
@ -167,6 +169,11 @@ func getEpochInfo*(blck: BlockRef, state: BeaconState): EpochRef =
|
|||
|
||||
if matching_epochinfo.len == 0:
|
||||
let cache = populateEpochCache(state, state_epoch)
|
||||
|
||||
# Don't use BlockRef caching as far as the epoch where the active
|
||||
# validator indices can diverge.
|
||||
if (compute_activation_exit_epoch(blck.slot.compute_epoch_at_slot) >
|
||||
state_epoch):
|
||||
blck.epochsInfo.add(cache)
|
||||
trace "candidate_chains.getEpochInfo: back-filling parent.epochInfo",
|
||||
state_slot = state.slot
|
||||
|
@ -177,13 +184,11 @@ func getEpochInfo*(blck: BlockRef, state: BeaconState): EpochRef =
|
|||
raiseAssert "multiple EpochRefs per epoch per BlockRef invalid"
|
||||
|
||||
func getEpochCache*(blck: BlockRef, state: BeaconState): StateCache =
|
||||
when false:
|
||||
let epochInfo = getEpochInfo(blck, state)
|
||||
result = get_empty_per_epoch_cache()
|
||||
result = StateCache()
|
||||
result.shuffled_active_validator_indices[
|
||||
state.slot.compute_epoch_at_slot] =
|
||||
epochInfo.shuffled_active_validator_indices
|
||||
get_empty_per_epoch_cache()
|
||||
|
||||
func init(T: type BlockRef, root: Eth2Digest, slot: Slot): BlockRef =
|
||||
BlockRef(
|
||||
|
@ -920,7 +925,7 @@ proc getProposer*(
|
|||
dag: CandidateChains, head: BlockRef, slot: Slot):
|
||||
Option[(ValidatorIndex, ValidatorPubKey)] =
|
||||
dag.withState(dag.tmpState, head.atSlot(slot)):
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
let proposerIdx = get_beacon_proposer_index(state, cache)
|
||||
if proposerIdx.isNone:
|
||||
|
|
|
@ -107,7 +107,7 @@ proc process_deposit*(preset: RuntimePreset,
|
|||
ok()
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#compute_activation_exit_epoch
|
||||
func compute_activation_exit_epoch(epoch: Epoch): Epoch =
|
||||
func compute_activation_exit_epoch*(epoch: Epoch): Epoch =
|
||||
## Return the epoch during which validator activations and exits initiated in
|
||||
## ``epoch`` take effect.
|
||||
epoch + 1 + MAX_SEED_LOOKAHEAD
|
||||
|
@ -592,10 +592,13 @@ proc check_attestation*(
|
|||
trace "process_attestation: beginning",
|
||||
attestation=attestation
|
||||
|
||||
if not (data.index < get_committee_count_at_slot(state, data.slot)):
|
||||
let committee_count_at_slot =
|
||||
get_committee_count_at_slot(get_shuffled_active_validator_indices(
|
||||
state, stateSlot.compute_epoch_at_slot, stateCache).len.uint64).uint64
|
||||
if not (data.index < committee_count_at_slot):
|
||||
warn("Data index exceeds committee count",
|
||||
data_index = data.index,
|
||||
committee_count = get_committee_count_at_slot(state, data.slot))
|
||||
committee_count = committee_count_at_slot)
|
||||
return
|
||||
|
||||
if not isValidAttestationTargetEpoch(state, data):
|
||||
|
|
|
@ -65,7 +65,7 @@ func get_active_validator_indices*(state: BeaconState, epoch: Epoch):
|
|||
result.add idx.ValidatorIndex
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#get_committee_count_at_slot
|
||||
func get_committee_count_at_slot*(num_active_validators: Slot): uint64 =
|
||||
func get_committee_count_at_slot*(num_active_validators: uint64): uint64 =
|
||||
clamp(
|
||||
num_active_validators div SLOTS_PER_EPOCH div TARGET_COMMITTEE_SIZE,
|
||||
1, MAX_COMMITTEES_PER_SLOT).uint64
|
||||
|
@ -77,9 +77,10 @@ func get_committee_count_at_slot*(state: BeaconState, slot: Slot): uint64 =
|
|||
# be converted to CommitteeIndex types for get_beacon_committee(...); replace
|
||||
# with better and more type-safe use pattern, probably beginning with using a
|
||||
# CommitteeIndex return type here.
|
||||
let epoch = compute_epoch_at_slot(slot)
|
||||
let active_validator_indices = get_active_validator_indices(state, epoch)
|
||||
result = get_committee_count_at_slot(len(active_validator_indices).uint64.Slot)
|
||||
let
|
||||
epoch = compute_epoch_at_slot(slot)
|
||||
active_validator_indices = get_active_validator_indices(state, epoch)
|
||||
result = get_committee_count_at_slot(len(active_validator_indices).uint64)
|
||||
|
||||
# Otherwise, get_beacon_committee(...) cannot access some committees.
|
||||
doAssert (SLOTS_PER_EPOCH * MAX_COMMITTEES_PER_SLOT).uint64 >= result
|
||||
|
|
|
@ -70,7 +70,7 @@ func compute_subnet_for_attestation*(
|
|||
let
|
||||
slots_since_epoch_start = attestation.data.slot mod SLOTS_PER_EPOCH
|
||||
committees_since_epoch_start =
|
||||
get_committee_count_at_slot(num_active_validators.Slot) * slots_since_epoch_start
|
||||
get_committee_count_at_slot(num_active_validators) * slots_since_epoch_start
|
||||
|
||||
(committees_since_epoch_start + attestation.data.index) mod ATTESTATION_SUBNET_COUNT
|
||||
|
||||
|
|
|
@ -124,6 +124,15 @@ func process_slot*(state: var HashedBeaconState) {.nbench.} =
|
|||
state.data.block_roots[state.data.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
||||
hash_tree_root(state.data.latest_block_header)
|
||||
|
||||
func clear_epoch_from_cache(cache: var StateCache, epoch: Epoch) =
|
||||
cache.shuffled_active_validator_indices.del epoch
|
||||
let
|
||||
start_slot = epoch.compute_start_slot_at_epoch
|
||||
end_slot = (epoch + 1).compute_start_slot_at_epoch
|
||||
|
||||
for i in start_slot ..< end_slot:
|
||||
cache.beacon_proposer_indices.del i
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||
proc advance_slot*(
|
||||
state: var HashedBeaconState, updateFlags: UpdateFlags,
|
||||
|
@ -137,6 +146,8 @@ proc advance_slot*(
|
|||
# Note: Genesis epoch = 0, no need to test if before Genesis
|
||||
beacon_previous_validators.set(get_epoch_validator_count(state.data))
|
||||
process_epoch(state.data, updateFlags, epochCache)
|
||||
clear_epoch_from_cache(
|
||||
epochCache, (state.data.slot + 1).compute_epoch_at_slot)
|
||||
state.data.slot += 1
|
||||
if is_epoch_transition:
|
||||
beacon_current_validators.set(get_epoch_validator_count(state.data))
|
||||
|
@ -161,7 +172,7 @@ proc process_slots*(state: var HashedBeaconState, slot: Slot,
|
|||
return false
|
||||
|
||||
# Catch up to the target slot
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
while state.data.slot < slot:
|
||||
advance_slot(state, updateFlags, cache)
|
||||
|
||||
|
@ -207,8 +218,6 @@ proc state_transition*(
|
|||
# the changes in case of failure (look out for `var BeaconState` and
|
||||
# bool return values...)
|
||||
doAssert not rollback.isNil, "use noRollback if it's ok to mess up state"
|
||||
when false:
|
||||
# TODO readd this assetion when epochref cache is back
|
||||
doAssert stateCache.shuffled_active_validator_indices.hasKey(
|
||||
state.data.slot.compute_epoch_at_slot)
|
||||
|
||||
|
@ -255,9 +264,7 @@ proc state_transition*(
|
|||
# TODO consider moving this to testutils or similar, since non-testing
|
||||
# and fuzzing code should always be coming from blockpool which should
|
||||
# always be providing cache or equivalent
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
# TODO not here, but in blockpool, should fill in as far ahead towards
|
||||
# block's slot as protocol allows to be known already
|
||||
var cache = StateCache()
|
||||
cache.shuffled_active_validator_indices[state.data.slot.compute_epoch_at_slot] =
|
||||
get_shuffled_active_validator_indices(
|
||||
state.data, state.data.slot.compute_epoch_at_slot)
|
||||
|
|
|
@ -274,7 +274,7 @@ proc process_voluntary_exit*(
|
|||
validator_withdrawable_epoch = validator.withdrawable_epoch,
|
||||
validator_exit_epoch = validator.exit_epoch,
|
||||
validator_effective_balance = validator.effective_balance
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
initiate_validator_exit(
|
||||
state, voluntary_exit.validator_index.ValidatorIndex, cache)
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ func get_shuffled_seq*(seed: Eth2Digest,
|
|||
if bit != 0:
|
||||
shuffled_active_validator_indices[index] = flip.ValidatorIndex
|
||||
|
||||
result = shuffled_active_validator_indices
|
||||
shuffled_active_validator_indices
|
||||
|
||||
func get_shuffled_active_validator_indices*(state: BeaconState, epoch: Epoch):
|
||||
seq[ValidatorIndex] =
|
||||
|
@ -90,6 +90,16 @@ func get_shuffled_active_validator_indices*(state: BeaconState, epoch: Epoch):
|
|||
active_validator_indices.len.uint64),
|
||||
active_validator_indices[it])
|
||||
|
||||
func get_shuffled_active_validator_indices*(
|
||||
state: BeaconState, epoch: Epoch, cache: var StateCache):
|
||||
seq[ValidatorIndex] =
|
||||
try:
|
||||
cache.shuffled_active_validator_indices[epoch]
|
||||
except KeyError:
|
||||
let validator_indices = get_shuffled_active_validator_indices(state, epoch)
|
||||
cache.shuffled_active_validator_indices[epoch] = validator_indices
|
||||
validator_indices
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#get_previous_epoch
|
||||
func get_previous_epoch*(state: BeaconState): Epoch =
|
||||
# Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
|
||||
|
@ -142,7 +152,7 @@ func get_beacon_committee*(
|
|||
|
||||
try:
|
||||
let committee_count = get_committee_count_at_slot(
|
||||
cache.shuffled_active_validator_indices[epoch].len.uint64.Slot)
|
||||
cache.shuffled_active_validator_indices[epoch].len.uint64)
|
||||
compute_committee(
|
||||
cache.shuffled_active_validator_indices[epoch],
|
||||
get_seed(state, epoch, DOMAIN_BEACON_ATTESTER),
|
||||
|
@ -153,10 +163,44 @@ func get_beacon_committee*(
|
|||
except KeyError:
|
||||
raiseAssert "values are added to cache before using them"
|
||||
|
||||
# Not from spec
|
||||
func get_empty_per_epoch_cache*(): StateCache =
|
||||
result.shuffled_active_validator_indices =
|
||||
initTable[Epoch, seq[ValidatorIndex]]()
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#compute_shuffled_index
|
||||
func compute_shuffled_index(
|
||||
index: uint64, index_count: uint64, seed: Eth2Digest): uint64 =
|
||||
# Return the shuffled index corresponding to ``seed`` (and ``index_count``).
|
||||
doAssert index < index_count
|
||||
|
||||
var
|
||||
pivot_buffer: array[(32+1), byte]
|
||||
source_buffer: array[(32+1+4), byte]
|
||||
cur_idx_permuted = index
|
||||
|
||||
pivot_buffer[0..31] = seed.data
|
||||
source_buffer[0..31] = seed.data
|
||||
|
||||
# Swap or not (https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf)
|
||||
# See the 'generalized domain' algorithm on page 3
|
||||
for current_round in 0 ..< SHUFFLE_ROUND_COUNT.int:
|
||||
let round_bytes1 = int_to_bytes1(current_round)[0]
|
||||
pivot_buffer[32] = round_bytes1
|
||||
source_buffer[32] = round_bytes1
|
||||
|
||||
let
|
||||
# If using multiple indices, can amortize this
|
||||
pivot =
|
||||
bytes_to_int(eth2digest(pivot_buffer).data.toOpenArray(0, 7)) mod
|
||||
index_count
|
||||
|
||||
flip = ((index_count + pivot) - cur_idx_permuted) mod index_count
|
||||
position = max(cur_idx_permuted.int, flip.int)
|
||||
source_buffer[33..36] = int_to_bytes4((position div 256).uint64)
|
||||
let
|
||||
source = eth2digest(source_buffer).data
|
||||
byte_value = source[(position mod 256) div 8]
|
||||
bit = (byte_value shr (position mod 8)) mod 2
|
||||
|
||||
cur_idx_permuted = if bit != 0: flip else: cur_idx_permuted
|
||||
|
||||
cur_idx_permuted
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#compute_proposer_index
|
||||
func compute_proposer_index(state: BeaconState, indices: seq[ValidatorIndex],
|
||||
|
@ -167,23 +211,19 @@ func compute_proposer_index(state: BeaconState, indices: seq[ValidatorIndex],
|
|||
if len(indices) == 0:
|
||||
return none(ValidatorIndex)
|
||||
|
||||
let
|
||||
seq_len = indices.len.uint64
|
||||
shuffled_seq = mapIt(get_shuffled_seq(seed, seq_len), indices[it])
|
||||
|
||||
doAssert seq_len == shuffled_seq.len.uint64
|
||||
let seq_len = indices.len.uint64
|
||||
|
||||
var
|
||||
i = 0
|
||||
i = 0'u64
|
||||
buffer: array[32+8, byte]
|
||||
buffer[0..31] = seed.data
|
||||
while true:
|
||||
buffer[32..39] = int_to_bytes8(i.uint64 div 32)
|
||||
buffer[32..39] = int_to_bytes8(i div 32)
|
||||
let
|
||||
candidate_index = shuffled_seq[(i.uint64 mod seq_len).int]
|
||||
candidate_index =
|
||||
indices[compute_shuffled_index(i mod seq_len, seq_len, seed)]
|
||||
random_byte = (eth2digest(buffer).data)[i mod 32]
|
||||
effective_balance =
|
||||
state.validators[candidate_index].effective_balance
|
||||
effective_balance = state.validators[candidate_index].effective_balance
|
||||
if effective_balance * MAX_RANDOM_BYTE >=
|
||||
MAX_EFFECTIVE_BALANCE * random_byte:
|
||||
return some(candidate_index)
|
||||
|
@ -245,7 +285,7 @@ func get_committee_assignment*(
|
|||
let next_epoch = get_current_epoch(state) + 1
|
||||
doAssert epoch <= next_epoch
|
||||
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
let start_slot = compute_start_slot_at_epoch(epoch)
|
||||
for slot in start_slot ..< start_slot + SLOTS_PER_EPOCH:
|
||||
|
@ -259,7 +299,7 @@ func get_committee_assignment*(
|
|||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#validator-assignments
|
||||
func is_proposer(
|
||||
state: BeaconState, validator_index: ValidatorIndex): bool {.used.} =
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let proposer_index = get_beacon_proposer_index(state, cache)
|
||||
proposer_index.isSome and proposer_index.get == validator_index
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
|
|||
stateId: string, epoch: uint64, index: uint64, slot: uint64) ->
|
||||
seq[BeaconStatesCommitteesTuple]:
|
||||
withStateForStateId(stateId):
|
||||
var cache = get_empty_per_epoch_cache() # TODO is this OK?
|
||||
var cache = StateCache() # TODO is this OK?
|
||||
|
||||
proc getCommittee(slot: Slot, index: CommitteeIndex): BeaconStatesCommitteesTuple =
|
||||
let vals = get_beacon_committee(state, slot, index, cache).mapIt(it.uint64)
|
||||
|
|
|
@ -196,7 +196,7 @@ proc makeBeaconBlockForHeadAndSlot*(node: BeaconNode,
|
|||
doAssert v.addr == addr poolPtr.tmpState.data
|
||||
assign(poolPtr.tmpState, poolPtr.headState)
|
||||
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let message = makeBeaconBlock(
|
||||
node.config.runtimePreset,
|
||||
hashedState,
|
||||
|
@ -341,13 +341,7 @@ proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) =
|
|||
cache.shuffled_active_validator_indices[
|
||||
slot.compute_epoch_at_slot].len.uint64
|
||||
except KeyError:
|
||||
when false:
|
||||
# TODO re-enable when getEpochCache() works
|
||||
raiseAssert "getEpochCache(...) didn't fill cache"
|
||||
let epoch = slot.compute_epoch_at_slot
|
||||
cache.shuffled_active_validator_indices[epoch] =
|
||||
get_shuffled_active_validator_indices(state, epoch)
|
||||
cache.shuffled_active_validator_indices[epoch].len.uint64
|
||||
|
||||
for committee_index in 0'u64..<committees_per_slot:
|
||||
let committee = get_beacon_committee(
|
||||
|
@ -407,7 +401,7 @@ proc broadcastAggregatedAttestations(
|
|||
node.blockPool.withState(node.blockPool.tmpState, bs):
|
||||
let
|
||||
committees_per_slot = get_committee_count_at_slot(state, aggregationSlot)
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
for committee_index in 0'u64..<committees_per_slot:
|
||||
let committee = get_beacon_committee(
|
||||
state, aggregationSlot, committee_index.CommitteeIndex, cache)
|
||||
|
|
|
@ -187,7 +187,7 @@ template processEpochScenarioImpl(
|
|||
state.root = hash_tree_root(state.data)
|
||||
|
||||
when needCache:
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let epoch = state.data.slot.compute_epoch_at_slot
|
||||
cache.shuffled_active_validator_indices[epoch] =
|
||||
get_shuffled_active_validator_indices(state.data, epoch)
|
||||
|
@ -223,7 +223,7 @@ template processBlockScenarioImpl(
|
|||
state.root = hash_tree_root(state.data)
|
||||
|
||||
when needCache:
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
when needFlags:
|
||||
let flags = if skipBLS: {skipBlsValidation}
|
||||
else: {}
|
||||
|
|
|
@ -60,7 +60,7 @@ template decodeAndProcess(typ, process: untyped): bool =
|
|||
let flags {.inject.} = if disable_bls: {skipBlsValidation} else: {}
|
||||
|
||||
var
|
||||
cache {.used, inject.} = get_empty_per_epoch_cache()
|
||||
cache {.used, inject.} = StateCache()
|
||||
data {.inject.} = newClone(
|
||||
try:
|
||||
SSZ.decode(input, typ)
|
||||
|
|
|
@ -67,7 +67,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
|||
attestationHead = blockPool.head.blck.atSlot(slot)
|
||||
|
||||
blockPool.withState(blockPool.tmpState, attestationHead):
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let committees_per_slot = get_committee_count_at_slot(state, slot)
|
||||
|
||||
for committee_index in 0'u64..<committees_per_slot:
|
||||
|
@ -100,7 +100,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
|||
head = blockPool.head.blck
|
||||
|
||||
blockPool.withState(blockPool.tmpState, head.atSlot(slot)):
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
let
|
||||
proposerIdx = get_beacon_proposer_index(state, cache).get()
|
||||
|
|
|
@ -54,7 +54,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
|||
attesters: RunningStat
|
||||
r = initRand(1)
|
||||
signedBlock: SignedBeaconBlock
|
||||
cache = get_empty_per_epoch_cache()
|
||||
cache = StateCache()
|
||||
|
||||
proc maybeWrite(last: bool) =
|
||||
if write_last_json:
|
||||
|
|
|
@ -55,7 +55,7 @@ proc mockAttestationData(
|
|||
)
|
||||
|
||||
proc signMockAttestation*(state: BeaconState, attestation: var Attestation) =
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let participants = get_attesting_indices(
|
||||
state,
|
||||
attestation.data,
|
||||
|
@ -80,7 +80,7 @@ proc mockAttestationImpl(
|
|||
slot: Slot,
|
||||
flags: UpdateFlags): Attestation =
|
||||
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
let
|
||||
beacon_committee = get_beacon_committee(
|
||||
|
@ -113,7 +113,7 @@ proc mockAttestation*(
|
|||
mockAttestationImpl(state, slot, flags)
|
||||
|
||||
func fillAggregateAttestation*(state: BeaconState, attestation: var Attestation) =
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let beacon_committee = get_beacon_committee(
|
||||
state,
|
||||
attestation.data.slot,
|
||||
|
|
|
@ -44,7 +44,7 @@ proc mockBlock(
|
|||
## Mock a BeaconBlock for the specific slot
|
||||
## Skip signature creation if block should not be signed (skipBlsValidation present)
|
||||
|
||||
var emptyCache = get_empty_per_epoch_cache()
|
||||
var emptyCache = StateCache()
|
||||
let proposer_index = get_beacon_proposer_index(state, emptyCache)
|
||||
result.message.slot = slot
|
||||
result.message.proposer_index = proposer_index.get.uint64
|
||||
|
|
|
@ -13,7 +13,7 @@ import
|
|||
# Utilities
|
||||
stew/results,
|
||||
# Beacon chain internals
|
||||
../../beacon_chain/spec/[datatypes, beaconstate, validator],
|
||||
../../beacon_chain/spec/[datatypes, beaconstate],
|
||||
../../beacon_chain/ssz,
|
||||
# Test utilities
|
||||
../testutil,
|
||||
|
@ -39,7 +39,7 @@ proc runTest(identifier: string) =
|
|||
prefix = "[Invalid] "
|
||||
|
||||
timedTest prefix & identifier:
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
let attestation = parseTest(testDir/"attestation.ssz", SSZ, Attestation)
|
||||
var preState = newClone(parseTest(testDir/"pre.ssz", SSZ, BeaconState))
|
||||
|
|
|
@ -13,7 +13,7 @@ import
|
|||
# Utilities
|
||||
stew/results,
|
||||
# Beacon chain internals
|
||||
../../beacon_chain/spec/[datatypes, state_transition_block, validator],
|
||||
../../beacon_chain/spec/[datatypes, state_transition_block],
|
||||
../../beacon_chain/ssz,
|
||||
# Test utilities
|
||||
../testutil,
|
||||
|
@ -39,7 +39,7 @@ proc runTest(identifier: string) =
|
|||
prefix = "[Invalid] "
|
||||
|
||||
timedTest prefix & identifier:
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
let attesterSlashing = parseTest(testDir/"attester_slashing.ssz", SSZ, AttesterSlashing)
|
||||
var preState = newClone(parseTest(testDir/"pre.ssz", SSZ, BeaconState))
|
||||
|
|
|
@ -13,7 +13,7 @@ import
|
|||
# Utilities
|
||||
stew/results,
|
||||
# Beacon chain internals
|
||||
../../beacon_chain/spec/[datatypes, state_transition_block, validator],
|
||||
../../beacon_chain/spec/[datatypes, state_transition_block],
|
||||
../../beacon_chain/ssz,
|
||||
# Test utilities
|
||||
../testutil,
|
||||
|
@ -39,7 +39,7 @@ proc runTest(identifier: string) =
|
|||
prefix = "[Invalid] "
|
||||
|
||||
timedTest prefix & identifier:
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
let blck = parseTest(testDir/"block.ssz", SSZ, BeaconBlock)
|
||||
var preState = newClone(parseTest(testDir/"pre.ssz", SSZ, BeaconState))
|
||||
|
|
|
@ -13,7 +13,7 @@ import
|
|||
# Utilities
|
||||
stew/results,
|
||||
# Beacon chain internals
|
||||
../../beacon_chain/spec/[datatypes, state_transition_block, validator],
|
||||
../../beacon_chain/spec/[datatypes, state_transition_block],
|
||||
../../beacon_chain/ssz,
|
||||
# Test utilities
|
||||
../testutil,
|
||||
|
@ -42,7 +42,7 @@ proc runTest(identifier: string) =
|
|||
let proposerSlashing = parseTest(testDir/"proposer_slashing.ssz", SSZ, ProposerSlashing)
|
||||
var preState = newClone(parseTest(testDir/"pre.ssz", SSZ, BeaconState))
|
||||
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
if existsFile(testDir/"post.ssz"):
|
||||
let postState = newClone(parseTest(testDir/"post.ssz", SSZ, BeaconState))
|
||||
|
|
|
@ -11,7 +11,7 @@ import
|
|||
# Standard library
|
||||
os, unittest, strutils,
|
||||
# Beacon chain internals
|
||||
../../beacon_chain/spec/[datatypes, validator, state_transition_epoch],
|
||||
../../beacon_chain/spec/[datatypes, state_transition_epoch],
|
||||
# Test utilities
|
||||
../testutil,
|
||||
./fixtures_utils,
|
||||
|
@ -42,7 +42,7 @@ template runSuite(suiteDir, testName: string, transitionProc: untyped{ident}, us
|
|||
let postState = newClone(parseTest(testDir/"post.ssz", SSZ, BeaconState))
|
||||
|
||||
when useCache:
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
transitionProc(preState[], cache)
|
||||
else:
|
||||
transitionProc(preState[])
|
||||
|
|
|
@ -16,7 +16,7 @@ import
|
|||
unittest,
|
||||
stew/results,
|
||||
# Specs
|
||||
../../beacon_chain/spec/[beaconstate, datatypes, helpers, validator],
|
||||
../../beacon_chain/spec/[beaconstate, datatypes, helpers],
|
||||
# Mock helpers
|
||||
../mocking/[mock_genesis, mock_attestations, mock_state],
|
||||
../testutil
|
||||
|
@ -48,7 +48,7 @@ suiteReport "[Unit - Spec - Block processing] Attestations " & preset():
|
|||
|
||||
# State transition
|
||||
# ----------------------------------------
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
check process_attestation(
|
||||
state.data, attestation, flags = {}, cache
|
||||
).isOk
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import
|
||||
# Specs
|
||||
../../beacon_chain/spec/[
|
||||
datatypes, state_transition_epoch, validator, state_transition]
|
||||
datatypes, state_transition_epoch, state_transition]
|
||||
|
||||
proc processSlotsUntilEndCurrentEpoch(state: var HashedBeaconState) =
|
||||
# Process all slots until the end of the last slot of the current epoch
|
||||
|
@ -28,6 +28,6 @@ proc transitionEpochUntilJustificationFinalization*(state: var HashedBeaconState
|
|||
processSlotsUntilEndCurrentEpoch(state)
|
||||
|
||||
# From process_epoch()
|
||||
var per_epoch_cache = get_empty_per_epoch_cache()
|
||||
var per_epoch_cache = StateCache()
|
||||
|
||||
process_justification_and_finalization(state.data, per_epoch_cache, {})
|
||||
|
|
|
@ -34,7 +34,7 @@ proc addMockAttestations*(
|
|||
raise newException(ValueError, &"Cannot include attestations from epoch {state.get_current_epoch()} in epoch {epoch}")
|
||||
|
||||
# TODO: Working with an unsigned Gwei balance is a recipe for underflows to happen
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
cache.shuffled_active_validator_indices[epoch] =
|
||||
get_shuffled_active_validator_indices(state, epoch)
|
||||
var remaining_balance = state.get_total_active_balance(cache).int64 * 2 div 3
|
||||
|
@ -45,7 +45,7 @@ proc addMockAttestations*(
|
|||
for slot in start_slot.uint64 ..< start_slot.uint64 + SLOTS_PER_EPOCH:
|
||||
for index in 0 ..< get_committee_count_at_slot(state, slot.Slot):
|
||||
# TODO: can we move cache out of the loops
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
let committee = get_beacon_committee(
|
||||
state, slot.Slot, index.CommitteeIndex, cache)
|
||||
|
|
|
@ -44,7 +44,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
process_slots(state.data, state.data.data.slot + 1)
|
||||
|
||||
timedTest "Can add and retrieve simple attestation" & preset():
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let
|
||||
# Create an attestation for slot 1!
|
||||
beacon_committee = get_beacon_committee(
|
||||
|
@ -63,7 +63,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
attestations.len == 1
|
||||
|
||||
timedTest "Attestations may arrive in any order" & preset():
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let
|
||||
# Create an attestation for slot 1!
|
||||
bc0 = get_beacon_committee(
|
||||
|
@ -92,7 +92,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
attestations.len == 1
|
||||
|
||||
timedTest "Attestations should be combined" & preset():
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let
|
||||
# Create an attestation for slot 1!
|
||||
bc0 = get_beacon_committee(
|
||||
|
@ -114,7 +114,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
attestations.len == 1
|
||||
|
||||
timedTest "Attestations may overlap, bigger first" & preset():
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
var
|
||||
# Create an attestation for slot 1!
|
||||
|
@ -139,7 +139,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
attestations.len == 1
|
||||
|
||||
timedTest "Attestations may overlap, smaller first" & preset():
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
var
|
||||
# Create an attestation for slot 1!
|
||||
bc0 = get_beacon_committee(state.data.data,
|
||||
|
@ -163,7 +163,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
attestations.len == 1
|
||||
|
||||
timedTest "Fork choice returns latest block with no attestations":
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let
|
||||
b1 = addTestBlock(state.data, blockPool[].tail.root, cache)
|
||||
b1Root = hash_tree_root(b1.message)
|
||||
|
@ -189,7 +189,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
head2 == b2Add[]
|
||||
|
||||
timedTest "Fork choice returns block with attestation":
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let
|
||||
b10 = makeTestBlock(state.data, blockPool[].tail.root, cache)
|
||||
b10Root = hash_tree_root(b10.message)
|
||||
|
@ -248,7 +248,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
head4 == b11Add[]
|
||||
|
||||
timedTest "Trying to add a block twice tags the second as an error":
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
let
|
||||
b10 = makeTestBlock(state.data, blockPool[].tail.root, cache)
|
||||
b10Root = hash_tree_root(b10.message)
|
||||
|
@ -270,7 +270,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
doAssert: b10Add_clone.error == Duplicate
|
||||
|
||||
wrappedTimedTest "Trying to add a duplicate block from an old pruned epoch is tagged as an error":
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
var cache = StateCache()
|
||||
|
||||
blockpool[].addFlags {skipBLSValidation}
|
||||
pool.forkChoice_v2.proto_array.prune_threshold = 1
|
||||
|
@ -335,7 +335,7 @@ suiteReport "Attestation pool processing" & preset():
|
|||
# signature: ValidatorSig()
|
||||
)
|
||||
|
||||
cache = get_empty_per_epoch_cache()
|
||||
cache = StateCache()
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Prune
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
import
|
||||
options, sequtils, unittest,
|
||||
./testutil, ./testblockutil,
|
||||
../beacon_chain/spec/[datatypes, digest, helpers, validator,
|
||||
state_transition, presets],
|
||||
../beacon_chain/spec/[datatypes, digest, helpers, state_transition, presets],
|
||||
../beacon_chain/[beacon_node_types, block_pool, ssz]
|
||||
|
||||
when isMainModule:
|
||||
|
@ -92,7 +91,7 @@ suiteReport "Block pool processing" & preset():
|
|||
db = makeTestDB(SLOTS_PER_EPOCH)
|
||||
pool = BlockPool.init(defaultRuntimePreset, db)
|
||||
stateData = newClone(pool.loadTailState())
|
||||
cache = get_empty_per_epoch_cache()
|
||||
cache = StateCache()
|
||||
b1 = addTestBlock(stateData.data, pool.tail.root, cache)
|
||||
b1Root = hash_tree_root(b1.message)
|
||||
b2 = addTestBlock(stateData.data, b1Root, cache)
|
||||
|
@ -299,7 +298,7 @@ suiteReport "BlockPool finalization tests" & preset():
|
|||
var
|
||||
db = makeTestDB(SLOTS_PER_EPOCH)
|
||||
pool = BlockPool.init(defaultRuntimePreset, db)
|
||||
cache = get_empty_per_epoch_cache()
|
||||
cache = StateCache()
|
||||
|
||||
timedTest "prune heads on finalization" & preset():
|
||||
# Create a fork that will not be taken
|
||||
|
@ -324,10 +323,6 @@ suiteReport "BlockPool finalization tests" & preset():
|
|||
pool.tail.children.len == 2
|
||||
pool.heads.len == 2
|
||||
|
||||
if i mod SLOTS_PER_EPOCH == 0:
|
||||
# Reset cache at epoch boundaries
|
||||
cache = get_empty_per_epoch_cache()
|
||||
|
||||
blck = makeTestBlock(
|
||||
pool.headState.data, pool.head.blck.root, cache,
|
||||
attestations = makeFullAttestations(
|
||||
|
@ -365,7 +360,7 @@ suiteReport "BlockPool finalization tests" & preset():
|
|||
hash_tree_root(pool.justifiedState.data.data)
|
||||
|
||||
# timedTest "init with gaps" & preset():
|
||||
# var cache = get_empty_per_epoch_cache()
|
||||
# var cache = StateCache()
|
||||
# for i in 0 ..< (SLOTS_PER_EPOCH * 6 - 2):
|
||||
# var
|
||||
# blck = makeTestBlock(
|
||||
|
|
|
@ -37,7 +37,7 @@ suiteReport "Block processing" & preset():
|
|||
timedTest "Passes from genesis state, empty block" & preset():
|
||||
var
|
||||
previous_block_root = hash_tree_root(genesisBlock.message)
|
||||
cache = get_empty_per_epoch_cache()
|
||||
cache = StateCache()
|
||||
new_block = makeTestBlock(state[], previous_block_root, cache)
|
||||
|
||||
let block_ok = state_transition(defaultRuntimePreset, state[], new_block, {}, noRollback)
|
||||
|
@ -55,7 +55,7 @@ suiteReport "Block processing" & preset():
|
|||
timedTest "Passes through epoch update, empty block" & preset():
|
||||
var
|
||||
previous_block_root = genesisRoot
|
||||
cache = get_empty_per_epoch_cache()
|
||||
cache = StateCache()
|
||||
|
||||
for i in 1..SLOTS_PER_EPOCH.int:
|
||||
let new_block = makeTestBlock(state[], previous_block_root, cache)
|
||||
|
@ -73,7 +73,7 @@ suiteReport "Block processing" & preset():
|
|||
timedTest "Attestation gets processed at epoch" & preset():
|
||||
var
|
||||
previous_block_root = genesisRoot
|
||||
cache = get_empty_per_epoch_cache()
|
||||
cache = StateCache()
|
||||
|
||||
# Slot 0 is a finalized slot - won't be making attestations for it..
|
||||
check:
|
||||
|
|
Loading…
Reference in New Issue