174 lines
6.2 KiB
Nim
174 lines
6.2 KiB
Nim
# beacon_chain
|
|
# Copyright (c) 2020-2022 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
{.used.}
|
|
|
|
import
|
|
../beacon_chain/spec/[
|
|
datatypes/base, forks, presets, signatures, state_transition],
|
|
../beacon_chain/consensus_object_pools/[
|
|
block_quarantine, blockchain_dag, exit_pool],
|
|
"."/[testutil, testblockutil, testdbutil]
|
|
|
|
func makeSignedBeaconBlockHeader(
|
|
fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot,
|
|
proposer_index: uint64, parent_root: Eth2Digest): SignedBeaconBlockHeader =
|
|
let tmp = BeaconBlockHeader(
|
|
slot: slot, proposer_index: proposer_index, parent_root: parent_root)
|
|
|
|
SignedBeaconBlockHeader(
|
|
message: tmp,
|
|
signature: get_block_signature(
|
|
fork, genesis_validators_root, slot, hash_tree_root(tmp),
|
|
MockPrivKeys[proposer_index]).toValidatorSig())
|
|
|
|
func makeIndexedAttestation(
|
|
fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot,
|
|
validator_index: uint64, beacon_block_root: Eth2Digest): IndexedAttestation =
|
|
let tmp = AttestationData(slot: slot, beacon_block_root: beacon_block_root)
|
|
|
|
IndexedAttestation(
|
|
data: tmp,
|
|
attesting_indices: List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE](@[validator_index]),
|
|
signature: get_attestation_signature(
|
|
fork, genesis_validators_root, tmp,
|
|
MockPrivKeys[validator_index]).toValidatorSig)
|
|
|
|
func makeSignedVoluntaryExit(
|
|
fork: Fork, genesis_validators_root: Eth2Digest, epoch: Epoch,
|
|
validator_index: uint64): SignedVoluntaryExit =
|
|
let tmp = VoluntaryExit(epoch: epoch, validator_index: validator_index)
|
|
|
|
SignedVoluntaryExit(
|
|
message: tmp,
|
|
signature: get_voluntary_exit_signature(
|
|
fork, genesis_validators_root, tmp,
|
|
MockPrivKeys[validator_index]).toValidatorSig)
|
|
|
|
suite "Exit pool testing suite":
|
|
setup:
|
|
let
|
|
cfg = block:
|
|
var tmp = defaultRuntimeConfig
|
|
tmp.ALTAIR_FORK_EPOCH = Epoch(tmp.SHARD_COMMITTEE_PERIOD)
|
|
tmp.BELLATRIX_FORK_EPOCH = Epoch(tmp.SHARD_COMMITTEE_PERIOD) + 1
|
|
tmp
|
|
|
|
validatorMonitor = newClone(ValidatorMonitor.init())
|
|
dag = init(
|
|
ChainDAGRef, cfg, makeTestDB(SLOTS_PER_EPOCH * 3),
|
|
validatorMonitor, {})
|
|
fork = dag.forkAtEpoch(Epoch(0))
|
|
genesis_validators_root = dag.genesis_validators_root
|
|
pool = newClone(ExitPool.init(dag))
|
|
|
|
test "addExitMessage/getProposerSlashingMessage":
|
|
for i in 0'u64 .. MAX_PROPOSER_SLASHINGS + 5:
|
|
for j in 0'u64 .. i:
|
|
let
|
|
msg = ProposerSlashing(
|
|
signed_header_1:
|
|
makeSignedBeaconBlockHeader(
|
|
fork, genesis_validators_root, Slot(1), j, makeFakeHash(0)),
|
|
signed_header_2:
|
|
makeSignedBeaconBlockHeader(
|
|
fork, genesis_validators_root, Slot(1), j, makeFakeHash(1)))
|
|
|
|
if i == 0:
|
|
check not pool[].isSeen(msg)
|
|
|
|
pool[].addMessage(msg)
|
|
check: pool[].isSeen(msg)
|
|
withState(dag.headState):
|
|
check:
|
|
pool[].getBeaconBlockExits(
|
|
cfg, forkyState.data).proposer_slashings.lenu64 ==
|
|
min(i + 1, MAX_PROPOSER_SLASHINGS)
|
|
pool[].getBeaconBlockExits(
|
|
cfg, forkyState.data).proposer_slashings.len == 0
|
|
|
|
test "addExitMessage/getAttesterSlashingMessage":
|
|
for i in 0'u64 .. MAX_ATTESTER_SLASHINGS + 5:
|
|
for j in 0'u64 .. i:
|
|
let
|
|
msg = AttesterSlashing(
|
|
attestation_1: makeIndexedAttestation(
|
|
fork, genesis_validators_root, Slot(1), j, makeFakeHash(0)),
|
|
attestation_2: makeIndexedAttestation(
|
|
fork, genesis_validators_root, Slot(1), j, makeFakeHash(1)))
|
|
|
|
if i == 0:
|
|
check not pool[].isSeen(msg)
|
|
|
|
pool[].addMessage(msg)
|
|
check: pool[].isSeen(msg)
|
|
withState(dag.headState):
|
|
check:
|
|
pool[].getBeaconBlockExits(
|
|
cfg, forkyState.data).attester_slashings.lenu64 ==
|
|
min(i + 1, MAX_ATTESTER_SLASHINGS)
|
|
pool[].getBeaconBlockExits(
|
|
cfg, forkyState.data).attester_slashings.len == 0
|
|
|
|
test "addExitMessage/getVoluntaryExitMessage":
|
|
# Need to advance state or it will not accept voluntary exits
|
|
var
|
|
cache: StateCache
|
|
info: ForkedEpochInfo
|
|
process_slots(
|
|
dag.cfg, dag.headState,
|
|
Epoch(dag.cfg.SHARD_COMMITTEE_PERIOD).start_slot + 1, cache, info,
|
|
{}).expect("ok")
|
|
let
|
|
fork = dag.forkAtEpoch(dag.headState.get_current_epoch())
|
|
|
|
for i in 0'u64 .. MAX_VOLUNTARY_EXITS + 5:
|
|
for j in 0'u64 .. i:
|
|
# Cannot exit until
|
|
let msg = makeSignedVoluntaryExit(
|
|
fork, genesis_validators_root, dag.headState.get_current_epoch(), j)
|
|
if i == 0:
|
|
check not pool[].isSeen(msg)
|
|
|
|
pool[].addMessage(msg)
|
|
check: pool[].isSeen(msg)
|
|
|
|
withState(dag.headState):
|
|
check:
|
|
pool[].getBeaconBlockExits(
|
|
cfg, forkyState.data).voluntary_exits.lenu64 ==
|
|
min(i + 1, MAX_VOLUNTARY_EXITS)
|
|
pool[].getBeaconBlockExits(
|
|
cfg, forkyState.data).voluntary_exits.len == 0
|
|
|
|
test "pre-pre-fork voluntary exit":
|
|
var
|
|
cache: StateCache
|
|
info: ForkedEpochInfo
|
|
process_slots(
|
|
dag.cfg, dag.headState,
|
|
Epoch(dag.cfg.SHARD_COMMITTEE_PERIOD).start_slot + 1, cache, info,
|
|
{}).expect("ok")
|
|
|
|
let msg = makeSignedVoluntaryExit(
|
|
fork, genesis_validators_root, dag.headState.get_current_epoch(), 0)
|
|
|
|
pool[].addMessage(msg)
|
|
check: pool[].isSeen(msg)
|
|
|
|
process_slots(
|
|
dag.cfg, dag.headState,
|
|
(Epoch(dag.cfg.SHARD_COMMITTEE_PERIOD) + 1).start_slot + 1, cache, info,
|
|
{}).expect("ok")
|
|
|
|
withState(dag.headState):
|
|
check:
|
|
# Message signed with a (fork-2) domain can no longer be added as that
|
|
# fork is not present in the BeaconState and thus fails transition
|
|
pool[].getBeaconBlockExits(
|
|
cfg, forkyState.data).voluntary_exits.lenu64 == 0
|