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