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:
tersec 2020-07-15 10:44:18 +00:00 committed by GitHub
parent 4aefd8b021
commit 26e893ffc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 152 additions and 107 deletions

View File

@ -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)

View File

@ -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

View File

@ -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,7 +169,12 @@ func getEpochInfo*(blck: BlockRef, state: BeaconState): EpochRef =
if matching_epochinfo.len == 0:
let cache = populateEpochCache(state, state_epoch)
blck.epochsInfo.add(cache)
# 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
cache
@ -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.shuffled_active_validator_indices[
state.slot.compute_epoch_at_slot] =
epochInfo.shuffled_active_validator_indices
get_empty_per_epoch_cache()
let epochInfo = getEpochInfo(blck, state)
result = StateCache()
result.shuffled_active_validator_indices[
state.slot.compute_epoch_at_slot] =
epochInfo.shuffled_active_validator_indices
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:

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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,10 +218,8 @@ 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)
doAssert stateCache.shuffled_active_validator_indices.hasKey(
state.data.slot.compute_epoch_at_slot)
if not process_slots(state, signedBlock.message.slot, flags):
rollback(state)
@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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
raiseAssert "getEpochCache(...) didn't fill cache"
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)

View File

@ -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: {}

View File

@ -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)

View File

@ -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()

View File

@ -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:

View File

@ -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,

View File

@ -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

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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[])

View File

@ -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

View File

@ -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, {})

View File

@ -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)

View File

@ -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

View File

@ -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(

View File

@ -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: