begin removing plain BeaconState versions of state transition functions (#951)
* remove near-duplicate code paths: process_slot(), process_slots(), and state_transition() for BeaconState are now wrappers around the HashedBeaconState versions * convert tests/test_state_transition.nim to use HashedBeaconState * convert mocking infrastructure and spec_block/epoch_processing tests to use HashedBeaconBlock, and remove thus unused process_slot*(state: var BeaconState)
This commit is contained in:
parent
c74ba5c0c6
commit
3a56ddc5c4
|
@ -268,6 +268,15 @@ proc initialize_beacon_state_from_eth1*(
|
||||||
|
|
||||||
state
|
state
|
||||||
|
|
||||||
|
proc initialize_hashed_beacon_state_from_eth1*(
|
||||||
|
eth1_block_hash: Eth2Digest,
|
||||||
|
eth1_timestamp: uint64,
|
||||||
|
deposits: openArray[Deposit],
|
||||||
|
flags: UpdateFlags = {}): HashedBeaconState =
|
||||||
|
let genesisState = initialize_beacon_state_from_eth1(
|
||||||
|
eth1_block_hash, eth1_timestamp, deposits, flags)
|
||||||
|
HashedBeaconState(data: genesisState[], root: hash_tree_root(genesisState))
|
||||||
|
|
||||||
func is_valid_genesis_state*(state: BeaconState): bool =
|
func is_valid_genesis_state*(state: BeaconState): bool =
|
||||||
if state.genesis_time < MIN_GENESIS_TIME:
|
if state.genesis_time < MIN_GENESIS_TIME:
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -38,24 +38,6 @@ import
|
||||||
declareGauge beacon_current_validators, """Number of status="pending|active|exited|withdrawable" validators in current epoch""" # On epoch transition
|
declareGauge beacon_current_validators, """Number of status="pending|active|exited|withdrawable" validators in current epoch""" # On epoch transition
|
||||||
declareGauge beacon_previous_validators, """Number of status="pending|active|exited|withdrawable" validators in previous epoch""" # On epoch transition
|
declareGauge beacon_previous_validators, """Number of status="pending|active|exited|withdrawable" validators in previous epoch""" # On epoch transition
|
||||||
|
|
||||||
# Canonical state transition functions
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
|
||||||
func process_slot*(state: var BeaconState) {.nbench.}=
|
|
||||||
# Cache state root
|
|
||||||
let previous_state_root = hash_tree_root(state)
|
|
||||||
state.state_roots[state.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
|
||||||
previous_state_root
|
|
||||||
|
|
||||||
# Cache latest block header state root
|
|
||||||
if state.latest_block_header.state_root == ZERO_HASH:
|
|
||||||
state.latest_block_header.state_root = previous_state_root
|
|
||||||
|
|
||||||
# Cache block root
|
|
||||||
state.block_roots[state.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
|
||||||
hash_tree_root(state.latest_block_header)
|
|
||||||
|
|
||||||
func get_epoch_validator_count(state: BeaconState): int64 =
|
func get_epoch_validator_count(state: BeaconState): int64 =
|
||||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#additional-metrics
|
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#additional-metrics
|
||||||
#
|
#
|
||||||
|
@ -78,32 +60,6 @@ func get_epoch_validator_count(state: BeaconState): int64 =
|
||||||
validator.withdrawable_epoch > get_current_epoch(state):
|
validator.withdrawable_epoch > get_current_epoch(state):
|
||||||
result += 1
|
result += 1
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
|
||||||
proc process_slots*(state: var BeaconState, slot: Slot) {.nbench.}=
|
|
||||||
if not (state.slot <= slot):
|
|
||||||
warn("Trying to apply old block",
|
|
||||||
state_slot = state.slot,
|
|
||||||
slot = slot)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Catch up to the target slot
|
|
||||||
while state.slot < slot:
|
|
||||||
process_slot(state)
|
|
||||||
let is_epoch_transition = (state.slot + 1) mod SLOTS_PER_EPOCH == 0
|
|
||||||
if is_epoch_transition:
|
|
||||||
# Note: Genesis epoch = 0, no need to test if before Genesis
|
|
||||||
try:
|
|
||||||
beacon_previous_validators.set(get_epoch_validator_count(state))
|
|
||||||
except Exception as e: # TODO https://github.com/status-im/nim-metrics/pull/22
|
|
||||||
trace "Couldn't update metrics", msg = e.msg
|
|
||||||
process_epoch(state)
|
|
||||||
state.slot += 1
|
|
||||||
if is_epoch_transition:
|
|
||||||
try:
|
|
||||||
beacon_current_validators.set(get_epoch_validator_count(state))
|
|
||||||
except Exception as e: # TODO https://github.com/status-im/nim-metrics/pull/22
|
|
||||||
trace "Couldn't update metrics", msg = e.msg
|
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#verify_block_signature
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#verify_block_signature
|
||||||
proc verify_block_signature*(
|
proc verify_block_signature*(
|
||||||
state: BeaconState, signedBlock: SignedBeaconBlock): bool {.nbench.} =
|
state: BeaconState, signedBlock: SignedBeaconBlock): bool {.nbench.} =
|
||||||
|
@ -144,9 +100,74 @@ type
|
||||||
proc noRollback*(state: var BeaconState) =
|
proc noRollback*(state: var BeaconState) =
|
||||||
trace "Skipping rollback of broken state"
|
trace "Skipping rollback of broken state"
|
||||||
|
|
||||||
|
type
|
||||||
|
RollbackHashedProc* = proc(state: var HashedBeaconState) {.gcsafe.}
|
||||||
|
|
||||||
|
# Hashed-state transition functions
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
|
||||||
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||||
|
func process_slot*(state: var HashedBeaconState) {.nbench.} =
|
||||||
|
# Cache state root
|
||||||
|
let previous_slot_state_root = state.root
|
||||||
|
state.data.state_roots[state.data.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
||||||
|
previous_slot_state_root
|
||||||
|
|
||||||
|
# Cache latest block header state root
|
||||||
|
if state.data.latest_block_header.state_root == ZERO_HASH:
|
||||||
|
state.data.latest_block_header.state_root = previous_slot_state_root
|
||||||
|
|
||||||
|
# Cache block root
|
||||||
|
state.data.block_roots[state.data.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
||||||
|
hash_tree_root(state.data.latest_block_header)
|
||||||
|
|
||||||
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||||
|
proc process_slots*(state: var HashedBeaconState, slot: Slot) {.nbench.} =
|
||||||
|
# TODO: Eth specs strongly assert that state.data.slot <= slot
|
||||||
|
# This prevents receiving attestation in any order
|
||||||
|
# (see tests/test_attestation_pool)
|
||||||
|
# but it maybe an artifact of the test case
|
||||||
|
# as this was not triggered in the testnet1
|
||||||
|
# after a hour
|
||||||
|
if state.data.slot > slot:
|
||||||
|
notice(
|
||||||
|
"Unusual request for a slot in the past",
|
||||||
|
state_root = shortLog(state.root),
|
||||||
|
current_slot = state.data.slot,
|
||||||
|
target_slot = slot
|
||||||
|
)
|
||||||
|
|
||||||
|
# Catch up to the target slot
|
||||||
|
while state.data.slot < slot:
|
||||||
|
process_slot(state)
|
||||||
|
let is_epoch_transition = (state.data.slot + 1) mod SLOTS_PER_EPOCH == 0
|
||||||
|
if is_epoch_transition:
|
||||||
|
# Note: Genesis epoch = 0, no need to test if before Genesis
|
||||||
|
try:
|
||||||
|
beacon_previous_validators.set(get_epoch_validator_count(state.data))
|
||||||
|
except Exception as e: # TODO https://github.com/status-im/nim-metrics/pull/22
|
||||||
|
trace "Couldn't update metrics", msg = e.msg
|
||||||
|
process_epoch(state.data)
|
||||||
|
state.data.slot += 1
|
||||||
|
if is_epoch_transition:
|
||||||
|
try:
|
||||||
|
beacon_current_validators.set(get_epoch_validator_count(state.data))
|
||||||
|
except Exception as e: # TODO https://github.com/status-im/nim-metrics/pull/22
|
||||||
|
trace "Couldn't update metrics", msg = e.msg
|
||||||
|
state.root = hash_tree_root(state.data)
|
||||||
|
|
||||||
|
# TODO remove this once callers gone
|
||||||
|
proc process_slots*(state: var BeaconState, slot: Slot) =
|
||||||
|
var hashedState = HashedBeaconState(data: state, root: hash_tree_root(state))
|
||||||
|
process_slots(hashedState, slot)
|
||||||
|
state = hashedState.data
|
||||||
|
|
||||||
|
proc noRollback*(state: var HashedBeaconState) =
|
||||||
|
trace "Skipping rollback of broken state"
|
||||||
|
|
||||||
proc state_transition*(
|
proc state_transition*(
|
||||||
state: var BeaconState, signedBlock: SignedBeaconBlock, flags: UpdateFlags,
|
state: var HashedBeaconState, signedBlock: SignedBeaconBlock,
|
||||||
rollback: RollbackProc): bool {.nbench.} =
|
flags: UpdateFlags, rollback: RollbackHashedProc): bool =
|
||||||
## Time in the beacon chain moves by slots. Every time (haha.) that happens,
|
## Time in the beacon chain moves by slots. Every time (haha.) that happens,
|
||||||
## we will update the beacon state. Normally, the state updates will be driven
|
## we will update the beacon state. Normally, the state updates will be driven
|
||||||
## by the contents of a new block, but it may happen that the block goes
|
## by the contents of a new block, but it may happen that the block goes
|
||||||
|
@ -190,87 +211,6 @@ proc state_transition*(
|
||||||
# that the block is sane.
|
# that the block is sane.
|
||||||
# TODO what should happen if block processing fails?
|
# TODO what should happen if block processing fails?
|
||||||
# https://github.com/ethereum/eth2.0-specs/issues/293
|
# https://github.com/ethereum/eth2.0-specs/issues/293
|
||||||
if skipBLSValidation in flags or
|
|
||||||
verify_block_signature(state, signedBlock):
|
|
||||||
var per_epoch_cache = get_empty_per_epoch_cache()
|
|
||||||
|
|
||||||
if processBlock(state, signedBlock.message, flags, per_epoch_cache):
|
|
||||||
# This is a bit awkward - at the end of processing we verify that the
|
|
||||||
# state we arrive at is what the block producer thought it would be -
|
|
||||||
# meaning that potentially, it could fail verification
|
|
||||||
if skipStateRootValidation in flags or verifyStateRoot(state, signedBlock.message):
|
|
||||||
# State root is what it should be - we're done!
|
|
||||||
return true
|
|
||||||
|
|
||||||
# Block processing failed, roll back changes
|
|
||||||
rollback(state)
|
|
||||||
false
|
|
||||||
|
|
||||||
# Hashed-state transition functions
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
|
||||||
func process_slot(state: var HashedBeaconState) =
|
|
||||||
# Cache state root
|
|
||||||
let previous_slot_state_root = state.root
|
|
||||||
state.data.state_roots[state.data.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
|
||||||
previous_slot_state_root
|
|
||||||
|
|
||||||
# Cache latest block header state root
|
|
||||||
if state.data.latest_block_header.state_root == ZERO_HASH:
|
|
||||||
state.data.latest_block_header.state_root = previous_slot_state_root
|
|
||||||
|
|
||||||
# Cache block root
|
|
||||||
state.data.block_roots[state.data.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
|
||||||
hash_tree_root(state.data.latest_block_header)
|
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
|
||||||
proc process_slots*(state: var HashedBeaconState, slot: Slot) =
|
|
||||||
# TODO: Eth specs strongly assert that state.data.slot <= slot
|
|
||||||
# This prevents receiving attestation in any order
|
|
||||||
# (see tests/test_attestation_pool)
|
|
||||||
# but it maybe an artifact of the test case
|
|
||||||
# as this was not triggered in the testnet1
|
|
||||||
# after a hour
|
|
||||||
if state.data.slot > slot:
|
|
||||||
notice(
|
|
||||||
"Unusual request for a slot in the past",
|
|
||||||
state_root = shortLog(state.root),
|
|
||||||
current_slot = state.data.slot,
|
|
||||||
target_slot = slot
|
|
||||||
)
|
|
||||||
|
|
||||||
# Catch up to the target slot
|
|
||||||
while state.data.slot < slot:
|
|
||||||
process_slot(state)
|
|
||||||
let is_epoch_transition = (state.data.slot + 1) mod SLOTS_PER_EPOCH == 0
|
|
||||||
if is_epoch_transition:
|
|
||||||
# Note: Genesis epoch = 0, no need to test if before Genesis
|
|
||||||
try:
|
|
||||||
beacon_previous_validators.set(get_epoch_validator_count(state.data))
|
|
||||||
except Exception as e: # TODO https://github.com/status-im/nim-metrics/pull/22
|
|
||||||
trace "Couldn't update metrics", msg = e.msg
|
|
||||||
process_epoch(state.data)
|
|
||||||
state.data.slot += 1
|
|
||||||
if is_epoch_transition:
|
|
||||||
try:
|
|
||||||
beacon_current_validators.set(get_epoch_validator_count(state.data))
|
|
||||||
except Exception as e: # TODO https://github.com/status-im/nim-metrics/pull/22
|
|
||||||
trace "Couldn't update metrics", msg = e.msg
|
|
||||||
state.root = hash_tree_root(state.data)
|
|
||||||
|
|
||||||
type
|
|
||||||
RollbackHashedProc* = proc(state: var HashedBeaconState) {.gcsafe.}
|
|
||||||
|
|
||||||
proc noRollback*(state: var HashedBeaconState) =
|
|
||||||
trace "Skipping rollback of broken state"
|
|
||||||
|
|
||||||
proc state_transition*(
|
|
||||||
state: var HashedBeaconState, signedBlock: SignedBeaconBlock,
|
|
||||||
flags: UpdateFlags, rollback: RollbackHashedProc): bool =
|
|
||||||
doAssert not rollback.isNil, "use noRollback if it's ok to mess up state"
|
|
||||||
process_slots(state, signedBlock.message.slot)
|
|
||||||
|
|
||||||
if skipBLSValidation in flags or
|
if skipBLSValidation in flags or
|
||||||
verify_block_signature(state.data, signedBlock):
|
verify_block_signature(state.data, signedBlock):
|
||||||
|
|
||||||
|
@ -292,3 +232,11 @@ proc state_transition*(
|
||||||
rollback(state)
|
rollback(state)
|
||||||
|
|
||||||
false
|
false
|
||||||
|
|
||||||
|
# TODO remove this once callers gone
|
||||||
|
proc state_transition*(
|
||||||
|
state: var BeaconState, signedBlock: SignedBeaconBlock, flags: UpdateFlags,
|
||||||
|
rollback: RollbackHashedProc): bool {.nbench.} =
|
||||||
|
var hashedState = HashedBeaconState(data: state, root: hash_tree_root(state))
|
||||||
|
result = state_transition(hashedState, signedBlock, flags, rollback)
|
||||||
|
state = hashedState.data
|
||||||
|
|
|
@ -123,12 +123,12 @@ proc fillAggregateAttestation*(state: BeaconState, attestation: var Attestation)
|
||||||
for i in 0 ..< beacon_committee.len:
|
for i in 0 ..< beacon_committee.len:
|
||||||
attestation.aggregation_bits[i] = true
|
attestation.aggregation_bits[i] = true
|
||||||
|
|
||||||
proc add*(state: var BeaconState, attestation: Attestation, slot: Slot) =
|
proc add*(state: var HashedBeaconState, attestation: Attestation, slot: Slot) =
|
||||||
var signedBlock = mockBlockForNextSlot(state)
|
var signedBlock = mockBlockForNextSlot(state.data)
|
||||||
signedBlock.message.slot = slot
|
signedBlock.message.slot = slot
|
||||||
signedBlock.message.body.attestations.add attestation
|
signedBlock.message.body.attestations.add attestation
|
||||||
process_slots(state, slot)
|
process_slots(state, slot)
|
||||||
signMockBlock(state, signedBlock)
|
signMockBlock(state.data, signedBlock)
|
||||||
|
|
||||||
doAssert state_transition(
|
doAssert state_transition(
|
||||||
state, signedBlock, flags = {skipStateRootValidation}, noRollback)
|
state, signedBlock, flags = {skipStateRootValidation}, noRollback)
|
||||||
|
|
|
@ -61,9 +61,9 @@ proc mockBlockForNextSlot*(state: BeaconState, flags: UpdateFlags = {}):
|
||||||
SignedBeaconBlock =
|
SignedBeaconBlock =
|
||||||
mockBlock(state, state.slot + 1, flags)
|
mockBlock(state, state.slot + 1, flags)
|
||||||
|
|
||||||
proc applyEmptyBlock*(state: var BeaconState) =
|
proc applyEmptyBlock*(state: var HashedBeaconState) =
|
||||||
## Do a state transition with an empty signed block
|
## Do a state transition with an empty signed block
|
||||||
## on the current slot
|
## on the current slot
|
||||||
let signedBlock = mockBlock(state, state.slot, flags = {})
|
let signedBlock = mockBlock(state.data, state.data.slot, flags = {})
|
||||||
doAssert state_transition(
|
doAssert state_transition(
|
||||||
state, signedBlock, {skipStateRootValidation}, noRollback)
|
state, signedBlock, {skipStateRootValidation}, noRollback)
|
||||||
|
|
|
@ -17,14 +17,14 @@ import
|
||||||
./mock_deposits
|
./mock_deposits
|
||||||
|
|
||||||
|
|
||||||
proc initGenesisState*(num_validators: uint64, genesis_time: uint64 = 0): BeaconStateRef =
|
proc initGenesisState*(num_validators: uint64, genesis_time: uint64 = 0): HashedBeaconState =
|
||||||
let deposits = mockGenesisBalancedDeposits(
|
let deposits = mockGenesisBalancedDeposits(
|
||||||
validatorCount = num_validators,
|
validatorCount = num_validators,
|
||||||
amountInEth = 32, # We create canonical validators with 32 Eth
|
amountInEth = 32, # We create canonical validators with 32 Eth
|
||||||
flags = {skipBlsValidation}
|
flags = {skipBlsValidation}
|
||||||
)
|
)
|
||||||
|
|
||||||
initialize_beacon_state_from_eth1(
|
initialize_hashed_beacon_state_from_eth1(
|
||||||
eth1BlockHash, 0, deposits, {skipBlsValidation})
|
eth1BlockHash, 0, deposits, {skipBlsValidation})
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# beacon_chain
|
# beacon_chain
|
||||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
# * 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).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
@ -14,11 +14,12 @@ import
|
||||||
# Internals
|
# Internals
|
||||||
../../beacon_chain/state_transition
|
../../beacon_chain/state_transition
|
||||||
|
|
||||||
proc nextEpoch*(state: var BeaconState) =
|
proc nextEpoch*(state: var HashedBeaconState) =
|
||||||
## Transition to the start of the next epoch
|
## Transition to the start of the next epoch
|
||||||
let slot = state.slot + SLOTS_PER_EPOCH - (state.slot mod SLOTS_PER_EPOCH)
|
let slot =
|
||||||
|
state.data.slot + SLOTS_PER_EPOCH - (state.data.slot mod SLOTS_PER_EPOCH)
|
||||||
process_slots(state, slot)
|
process_slots(state, slot)
|
||||||
|
|
||||||
proc nextSlot*(state: var BeaconState) =
|
proc nextSlot*(state: var HashedBeaconState) =
|
||||||
## Transition to the next slot
|
## Transition to the next slot
|
||||||
process_slots(state, state.slot + 1)
|
process_slots(state, state.data.slot + 1)
|
||||||
|
|
|
@ -24,7 +24,7 @@ suiteReport "[Unit - Spec - Block processing] Attestations " & preset():
|
||||||
|
|
||||||
const NumValidators = uint64(8) * SLOTS_PER_EPOCH
|
const NumValidators = uint64(8) * SLOTS_PER_EPOCH
|
||||||
let genesisState = initGenesisState(NumValidators)
|
let genesisState = initGenesisState(NumValidators)
|
||||||
doAssert genesisState.validators.len == int NumValidators
|
doAssert genesisState.data.validators.len == int NumValidators
|
||||||
|
|
||||||
template valid_attestation(name: string, body: untyped): untyped {.dirty.}=
|
template valid_attestation(name: string, body: untyped): untyped {.dirty.}=
|
||||||
# Process a valid attestation
|
# Process a valid attestation
|
||||||
|
@ -42,29 +42,29 @@ suiteReport "[Unit - Spec - Block processing] Attestations " & preset():
|
||||||
# Params for sanity checks
|
# Params for sanity checks
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
let
|
let
|
||||||
current_epoch_count = state.current_epoch_attestations.len
|
current_epoch_count = state.data.current_epoch_attestations.len
|
||||||
previous_epoch_count = state.previous_epoch_attestations.len
|
previous_epoch_count = state.data.previous_epoch_attestations.len
|
||||||
|
|
||||||
# State transition
|
# State transition
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
var cache = get_empty_per_epoch_cache()
|
var cache = get_empty_per_epoch_cache()
|
||||||
check process_attestation(
|
check process_attestation(
|
||||||
state[], attestation, flags = {}, cache
|
state.data, attestation, flags = {}, cache
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check that the attestation was processed
|
# Check that the attestation was processed
|
||||||
if attestation.data.target.epoch == get_current_epoch(state[]):
|
if attestation.data.target.epoch == get_current_epoch(state.data):
|
||||||
check(state.current_epoch_attestations.len == current_epoch_count + 1)
|
check(state.data.current_epoch_attestations.len == current_epoch_count + 1)
|
||||||
else:
|
else:
|
||||||
check(state.previous_epoch_attestations.len == previous_epoch_count + 1)
|
check(state.data.previous_epoch_attestations.len == previous_epoch_count + 1)
|
||||||
|
|
||||||
valid_attestation("Valid attestation"):
|
valid_attestation("Valid attestation"):
|
||||||
let attestation = mockAttestation(state[])
|
let attestation = mockAttestation(state.data)
|
||||||
state.slot += MIN_ATTESTATION_INCLUSION_DELAY
|
state.data.slot += MIN_ATTESTATION_INCLUSION_DELAY
|
||||||
|
|
||||||
valid_attestation("Valid attestation from previous epoch"):
|
valid_attestation("Valid attestation from previous epoch"):
|
||||||
let attestation = mockAttestation(state[])
|
let attestation = mockAttestation(state.data)
|
||||||
state.slot = Slot(SLOTS_PER_EPOCH - 1)
|
state.data.slot = Slot(SLOTS_PER_EPOCH - 1)
|
||||||
nextEpoch(state[])
|
nextEpoch(state[])
|
||||||
applyEmptyBlock(state[])
|
applyEmptyBlock(state[])
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ suiteReport "[Unit - Spec - Block processing] Attestations " & preset():
|
||||||
|
|
||||||
# valid_attestation("Empty aggregation bit"):
|
# valid_attestation("Empty aggregation bit"):
|
||||||
# var attestation = mockAttestation(state)
|
# var attestation = mockAttestation(state)
|
||||||
# state.slot += MIN_ATTESTATION_INCLUSION_DELAY
|
# state.data.slot += MIN_ATTESTATION_INCLUSION_DELAY
|
||||||
|
|
||||||
# # Overwrite committee
|
# # Overwrite committee
|
||||||
# attestation.aggregation_bits = init(CommitteeValidatorsBits, attestation.aggregation_bits.len)
|
# attestation.aggregation_bits = init(CommitteeValidatorsBits, attestation.aggregation_bits.len)
|
||||||
|
|
|
@ -27,7 +27,7 @@ suiteReport "[Unit - Spec - Block processing] Deposits " & preset():
|
||||||
|
|
||||||
const NumValidators = uint64 5 * SLOTS_PER_EPOCH
|
const NumValidators = uint64 5 * SLOTS_PER_EPOCH
|
||||||
let genesisState = initGenesisState(NumValidators)
|
let genesisState = initGenesisState(NumValidators)
|
||||||
doAssert genesisState.validators.len == int NumValidators
|
doAssert genesisState.data.validators.len == int NumValidators
|
||||||
|
|
||||||
template valid_deposit(deposit_amount: uint64, name: string): untyped =
|
template valid_deposit(deposit_amount: uint64, name: string): untyped =
|
||||||
# TODO: BLS signature
|
# TODO: BLS signature
|
||||||
|
@ -37,9 +37,9 @@ suiteReport "[Unit - Spec - Block processing] Deposits " & preset():
|
||||||
|
|
||||||
# Test configuration
|
# Test configuration
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
let validator_index = state.validators.len
|
let validator_index = state.data.validators.len
|
||||||
let deposit = mockUpdateStateForNewDeposit(
|
let deposit = mockUpdateStateForNewDeposit(
|
||||||
state[],
|
state.data,
|
||||||
uint64 validator_index,
|
uint64 validator_index,
|
||||||
deposit_amount,
|
deposit_amount,
|
||||||
flags = {skipBlsValidation}
|
flags = {skipBlsValidation}
|
||||||
|
@ -47,25 +47,25 @@ suiteReport "[Unit - Spec - Block processing] Deposits " & preset():
|
||||||
|
|
||||||
# Params for sanity checks
|
# Params for sanity checks
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
let pre_val_count = state.validators.len
|
let pre_val_count = state.data.validators.len
|
||||||
let pre_balance = if validator_index < pre_val_count:
|
let pre_balance = if validator_index < pre_val_count:
|
||||||
state.balances[validator_index]
|
state.data.balances[validator_index]
|
||||||
else:
|
else:
|
||||||
0
|
0
|
||||||
|
|
||||||
# State transition
|
# State transition
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
check: process_deposit(state[], deposit, {skipBlsValidation})
|
check: process_deposit(state.data, deposit, {skipBlsValidation})
|
||||||
|
|
||||||
# Check invariants
|
# Check invariants
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
check:
|
check:
|
||||||
state.validators.len == pre_val_count + 1
|
state.data.validators.len == pre_val_count + 1
|
||||||
state.balances.len == pre_val_count + 1
|
state.data.balances.len == pre_val_count + 1
|
||||||
state.balances[validator_index] == pre_balance + deposit.data.amount
|
state.data.balances[validator_index] == pre_balance + deposit.data.amount
|
||||||
state.validators[validator_index].effective_balance ==
|
state.data.validators[validator_index].effective_balance ==
|
||||||
round_multiple_down(
|
round_multiple_down(
|
||||||
min(MAX_EFFECTIVE_BALANCE, state.balances[validator_index]),
|
min(MAX_EFFECTIVE_BALANCE, state.data.balances[validator_index]),
|
||||||
EFFECTIVE_BALANCE_INCREMENT
|
EFFECTIVE_BALANCE_INCREMENT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ suiteReport "[Unit - Spec - Block processing] Deposits " & preset():
|
||||||
let validator_index = 0
|
let validator_index = 0
|
||||||
let deposit_amount = MAX_EFFECTIVE_BALANCE div 4
|
let deposit_amount = MAX_EFFECTIVE_BALANCE div 4
|
||||||
let deposit = mockUpdateStateForNewDeposit(
|
let deposit = mockUpdateStateForNewDeposit(
|
||||||
state[],
|
state.data,
|
||||||
uint64 validator_index,
|
uint64 validator_index,
|
||||||
deposit_amount,
|
deposit_amount,
|
||||||
flags = {skipBlsValidation}
|
flags = {skipBlsValidation}
|
||||||
|
@ -89,25 +89,25 @@ suiteReport "[Unit - Spec - Block processing] Deposits " & preset():
|
||||||
|
|
||||||
# Params for sanity checks
|
# Params for sanity checks
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
let pre_val_count = state.validators.len
|
let pre_val_count = state.data.validators.len
|
||||||
let pre_balance = if validator_index < pre_val_count:
|
let pre_balance = if validator_index < pre_val_count:
|
||||||
state.balances[validator_index]
|
state.data.balances[validator_index]
|
||||||
else:
|
else:
|
||||||
0
|
0
|
||||||
|
|
||||||
# State transition
|
# State transition
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
check: process_deposit(state[], deposit, {skipBlsValidation})
|
check: process_deposit(state.data, deposit, {skipBlsValidation})
|
||||||
|
|
||||||
# Check invariants
|
# Check invariants
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
check:
|
check:
|
||||||
state.validators.len == pre_val_count
|
state.data.validators.len == pre_val_count
|
||||||
state.balances.len == pre_val_count
|
state.data.balances.len == pre_val_count
|
||||||
state.balances[validator_index] == pre_balance + deposit.data.amount
|
state.data.balances[validator_index] == pre_balance + deposit.data.amount
|
||||||
state.validators[validator_index].effective_balance ==
|
state.data.validators[validator_index].effective_balance ==
|
||||||
round_multiple_down(
|
round_multiple_down(
|
||||||
min(MAX_EFFECTIVE_BALANCE, state.balances[validator_index]),
|
min(MAX_EFFECTIVE_BALANCE, state.data.balances[validator_index]),
|
||||||
EFFECTIVE_BALANCE_INCREMENT
|
EFFECTIVE_BALANCE_INCREMENT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# beacon_chain
|
# beacon_chain
|
||||||
# Copyright (c) 2018 Status Research & Development GmbH
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
# * 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).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
@ -11,9 +11,10 @@ import
|
||||||
# Internals
|
# Internals
|
||||||
../../beacon_chain/[state_transition]
|
../../beacon_chain/[state_transition]
|
||||||
|
|
||||||
proc processSlotsUntilEndCurrentEpoch(state: var BeaconState) =
|
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
|
||||||
let slot = state.slot + SLOTS_PER_EPOCH - (state.slot mod SLOTS_PER_EPOCH)
|
let slot =
|
||||||
|
state.data.slot + SLOTS_PER_EPOCH - (state.data.slot mod SLOTS_PER_EPOCH)
|
||||||
|
|
||||||
# Transition to slot before the epoch state transition
|
# Transition to slot before the epoch state transition
|
||||||
process_slots(state, slot - 1)
|
process_slots(state, slot - 1)
|
||||||
|
@ -23,11 +24,11 @@ proc processSlotsUntilEndCurrentEpoch(state: var BeaconState) =
|
||||||
# (see process_slots())
|
# (see process_slots())
|
||||||
process_slot(state)
|
process_slot(state)
|
||||||
|
|
||||||
proc transitionEpochUntilJustificationFinalization*(state: var BeaconState) =
|
proc transitionEpochUntilJustificationFinalization*(state: var HashedBeaconState) =
|
||||||
# Process slots and do the epoch transition until crosslinks
|
# Process slots and do the epoch transition until crosslinks
|
||||||
processSlotsUntilEndCurrentEpoch(state)
|
processSlotsUntilEndCurrentEpoch(state)
|
||||||
|
|
||||||
# From process_epoch()
|
# From process_epoch()
|
||||||
var per_epoch_cache = get_empty_per_epoch_cache()
|
var per_epoch_cache = get_empty_per_epoch_cache()
|
||||||
|
|
||||||
process_justification_and_finalization(state, per_epoch_cache)
|
process_justification_and_finalization(state.data, per_epoch_cache)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# beacon_chain
|
# beacon_chain
|
||||||
# Copyright (c) 2018 Status Research & Development GmbH
|
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
# * 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).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
@ -24,10 +24,10 @@ import
|
||||||
# (source) https://github.com/protolambda/eth2-docs#justification-and-finalization
|
# (source) https://github.com/protolambda/eth2-docs#justification-and-finalization
|
||||||
# for a visualization of finalization rules
|
# for a visualization of finalization rules
|
||||||
|
|
||||||
proc finalizeOn234(state: var BeaconState, epoch: Epoch, sufficient_support: bool) =
|
proc finalizeOn234(state: var HashedBeaconState, epoch: Epoch, sufficient_support: bool) =
|
||||||
## Check finalization on rule 1 "234"
|
## Check finalization on rule 1 "234"
|
||||||
doAssert epoch > 4
|
doAssert epoch > 4
|
||||||
state.slot = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
state.data.slot = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
||||||
|
|
||||||
# 43210 -- epochs ago
|
# 43210 -- epochs ago
|
||||||
# 3210x -- justification bitfields indices
|
# 3210x -- justification bitfields indices
|
||||||
|
@ -35,22 +35,22 @@ proc finalizeOn234(state: var BeaconState, epoch: Epoch, sufficient_support: boo
|
||||||
|
|
||||||
# checkpoints for epochs ago
|
# checkpoints for epochs ago
|
||||||
let (c1, c2, c3, c4, _) = getCheckpoints(epoch)
|
let (c1, c2, c3, c4, _) = getCheckpoints(epoch)
|
||||||
putCheckpointsInBlockRoots(state, [c1, c2, c3, c4])
|
putCheckpointsInBlockRoots(state.data, [c1, c2, c3, c4])
|
||||||
|
|
||||||
# Save for final checks
|
# Save for final checks
|
||||||
let old_finalized = state.finalized_checkpoint
|
let old_finalized = state.data.finalized_checkpoint
|
||||||
|
|
||||||
# Mock the state
|
# Mock the state
|
||||||
state.previous_justified_checkpoint = c4
|
state.data.previous_justified_checkpoint = c4
|
||||||
state.current_justified_checkpoint = c3
|
state.data.current_justified_checkpoint = c3
|
||||||
state.justification_bits = 0'u8 # Bitvector of length 4
|
state.data.justification_bits = 0'u8 # Bitvector of length 4
|
||||||
# mock 3rd and 4th latest epochs as justified
|
# mock 3rd and 4th latest epochs as justified
|
||||||
# indices are pre-shift
|
# indices are pre-shift
|
||||||
state.justification_bits.setBit 1
|
state.data.justification_bits.setBit 1
|
||||||
state.justification_bits.setBit 2
|
state.data.justification_bits.setBit 2
|
||||||
# mock the 2nd latest epoch as justifiable, with 4th as the source
|
# mock the 2nd latest epoch as justifiable, with 4th as the source
|
||||||
addMockAttestations(
|
addMockAttestations(
|
||||||
state,
|
state.data,
|
||||||
epoch = epoch - 2,
|
epoch = epoch - 2,
|
||||||
source = c4,
|
source = c4,
|
||||||
target = c2,
|
target = c2,
|
||||||
|
@ -61,18 +61,18 @@ proc finalizeOn234(state: var BeaconState, epoch: Epoch, sufficient_support: boo
|
||||||
transitionEpochUntilJustificationFinalization(state)
|
transitionEpochUntilJustificationFinalization(state)
|
||||||
|
|
||||||
# Checks
|
# Checks
|
||||||
doAssert state.previous_justified_checkpoint == c3 # changed to old current
|
doAssert state.data.previous_justified_checkpoint == c3 # changed to old current
|
||||||
if sufficient_support:
|
if sufficient_support:
|
||||||
doAssert state.current_justified_checkpoint == c2 # changed to second latest
|
doAssert state.data.current_justified_checkpoint == c2 # changed to second latest
|
||||||
doAssert state.finalized_checkpoint == c4 # finalized old previous justified epoch
|
doAssert state.data.finalized_checkpoint == c4 # finalized old previous justified epoch
|
||||||
else:
|
else:
|
||||||
doAssert state.current_justified_checkpoint == c3 # still old current
|
doAssert state.data.current_justified_checkpoint == c3 # still old current
|
||||||
doAssert state.finalized_checkpoint == old_finalized # no new finalized checkpoint
|
doAssert state.data.finalized_checkpoint == old_finalized # no new finalized checkpoint
|
||||||
|
|
||||||
proc finalizeOn23(state: var BeaconState, epoch: Epoch, sufficient_support: bool) =
|
proc finalizeOn23(state: var HashedBeaconState, epoch: Epoch, sufficient_support: bool) =
|
||||||
## Check finalization on rule 2 "23"
|
## Check finalization on rule 2 "23"
|
||||||
doAssert epoch > 3
|
doAssert epoch > 3
|
||||||
state.slot = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
state.data.slot = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
||||||
|
|
||||||
# 43210 -- epochs ago
|
# 43210 -- epochs ago
|
||||||
# 210xx -- justification bitfields indices preshift
|
# 210xx -- justification bitfields indices preshift
|
||||||
|
@ -81,21 +81,21 @@ proc finalizeOn23(state: var BeaconState, epoch: Epoch, sufficient_support: bool
|
||||||
|
|
||||||
# checkpoints for epochs ago
|
# checkpoints for epochs ago
|
||||||
let (c1, c2, c3, _, _) = getCheckpoints(epoch)
|
let (c1, c2, c3, _, _) = getCheckpoints(epoch)
|
||||||
putCheckpointsInBlockRoots(state, [c1, c2, c3])
|
putCheckpointsInBlockRoots(state.data, [c1, c2, c3])
|
||||||
|
|
||||||
# Save for final checks
|
# Save for final checks
|
||||||
let old_finalized = state.finalized_checkpoint
|
let old_finalized = state.data.finalized_checkpoint
|
||||||
|
|
||||||
# Mock the state
|
# Mock the state
|
||||||
state.previous_justified_checkpoint = c3
|
state.data.previous_justified_checkpoint = c3
|
||||||
state.current_justified_checkpoint = c3
|
state.data.current_justified_checkpoint = c3
|
||||||
state.justification_bits = 0'u8 # Bitvector of length 4
|
state.data.justification_bits = 0'u8 # Bitvector of length 4
|
||||||
# mock 3rd as justified
|
# mock 3rd as justified
|
||||||
# indices are pre-shift
|
# indices are pre-shift
|
||||||
state.justification_bits.setBit 1
|
state.data.justification_bits.setBit 1
|
||||||
# mock the 2nd latest epoch as justifiable, with 3rd as the source
|
# mock the 2nd latest epoch as justifiable, with 3rd as the source
|
||||||
addMockAttestations(
|
addMockAttestations(
|
||||||
state,
|
state.data,
|
||||||
epoch = epoch - 2,
|
epoch = epoch - 2,
|
||||||
source = c3,
|
source = c3,
|
||||||
target = c2,
|
target = c2,
|
||||||
|
@ -106,18 +106,18 @@ proc finalizeOn23(state: var BeaconState, epoch: Epoch, sufficient_support: bool
|
||||||
transitionEpochUntilJustificationFinalization(state)
|
transitionEpochUntilJustificationFinalization(state)
|
||||||
|
|
||||||
# Checks
|
# Checks
|
||||||
doAssert state.previous_justified_checkpoint == c3 # changed to old current
|
doAssert state.data.previous_justified_checkpoint == c3 # changed to old current
|
||||||
if sufficient_support:
|
if sufficient_support:
|
||||||
doAssert state.current_justified_checkpoint == c2 # changed to second latest
|
doAssert state.data.current_justified_checkpoint == c2 # changed to second latest
|
||||||
doAssert state.finalized_checkpoint == c3 # finalized old previous justified epoch
|
doAssert state.data.finalized_checkpoint == c3 # finalized old previous justified epoch
|
||||||
else:
|
else:
|
||||||
doAssert state.current_justified_checkpoint == c3 # still old current
|
doAssert state.data.current_justified_checkpoint == c3 # still old current
|
||||||
doAssert state.finalized_checkpoint == old_finalized # no new finalized checkpoint
|
doAssert state.data.finalized_checkpoint == old_finalized # no new finalized checkpoint
|
||||||
|
|
||||||
proc finalizeOn123(state: var BeaconState, epoch: Epoch, sufficient_support: bool) =
|
proc finalizeOn123(state: var HashedBeaconState, epoch: Epoch, sufficient_support: bool) =
|
||||||
## Check finalization on rule 3 "123"
|
## Check finalization on rule 3 "123"
|
||||||
doAssert epoch > 5
|
doAssert epoch > 5
|
||||||
state.slot = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
state.data.slot = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
||||||
|
|
||||||
# 43210 -- epochs ago
|
# 43210 -- epochs ago
|
||||||
# 210xx -- justification bitfields indices preshift
|
# 210xx -- justification bitfields indices preshift
|
||||||
|
@ -126,21 +126,21 @@ proc finalizeOn123(state: var BeaconState, epoch: Epoch, sufficient_support: boo
|
||||||
|
|
||||||
# checkpoints for epochs ago
|
# checkpoints for epochs ago
|
||||||
let (c1, c2, c3, c4, c5) = getCheckpoints(epoch)
|
let (c1, c2, c3, c4, c5) = getCheckpoints(epoch)
|
||||||
putCheckpointsInBlockRoots(state, [c1, c2, c3, c4, c5])
|
putCheckpointsInBlockRoots(state.data, [c1, c2, c3, c4, c5])
|
||||||
|
|
||||||
# Save for final checks
|
# Save for final checks
|
||||||
let old_finalized = state.finalized_checkpoint
|
let old_finalized = state.data.finalized_checkpoint
|
||||||
|
|
||||||
# Mock the state
|
# Mock the state
|
||||||
state.previous_justified_checkpoint = c5
|
state.data.previous_justified_checkpoint = c5
|
||||||
state.current_justified_checkpoint = c3
|
state.data.current_justified_checkpoint = c3
|
||||||
state.justification_bits = 0'u8 # Bitvector of length 4
|
state.data.justification_bits = 0'u8 # Bitvector of length 4
|
||||||
# mock 3rd as justified
|
# mock 3rd as justified
|
||||||
# indices are pre-shift
|
# indices are pre-shift
|
||||||
state.justification_bits.setBit 1
|
state.data.justification_bits.setBit 1
|
||||||
# mock the 2nd latest epoch as justifiable, with 5th as the source
|
# mock the 2nd latest epoch as justifiable, with 5th as the source
|
||||||
addMockAttestations(
|
addMockAttestations(
|
||||||
state,
|
state.data,
|
||||||
epoch = epoch - 2,
|
epoch = epoch - 2,
|
||||||
source = c5,
|
source = c5,
|
||||||
target = c2,
|
target = c2,
|
||||||
|
@ -148,7 +148,7 @@ proc finalizeOn123(state: var BeaconState, epoch: Epoch, sufficient_support: boo
|
||||||
)
|
)
|
||||||
# mock the 1st latest epoch as justifiable with 3rd as source
|
# mock the 1st latest epoch as justifiable with 3rd as source
|
||||||
addMockAttestations(
|
addMockAttestations(
|
||||||
state,
|
state.data,
|
||||||
epoch = epoch - 1,
|
epoch = epoch - 1,
|
||||||
source = c3,
|
source = c3,
|
||||||
target = c1,
|
target = c1,
|
||||||
|
@ -159,18 +159,18 @@ proc finalizeOn123(state: var BeaconState, epoch: Epoch, sufficient_support: boo
|
||||||
transitionEpochUntilJustificationFinalization(state)
|
transitionEpochUntilJustificationFinalization(state)
|
||||||
|
|
||||||
# Checks
|
# Checks
|
||||||
doAssert state.previous_justified_checkpoint == c3 # changed to old current
|
doAssert state.data.previous_justified_checkpoint == c3 # changed to old current
|
||||||
if sufficient_support:
|
if sufficient_support:
|
||||||
doAssert state.current_justified_checkpoint == c1 # changed to second latest
|
doAssert state.data.current_justified_checkpoint == c1 # changed to second latest
|
||||||
doAssert state.finalized_checkpoint == c3 # finalized old previous justified epoch
|
doAssert state.data.finalized_checkpoint == c3 # finalized old previous justified epoch
|
||||||
else:
|
else:
|
||||||
doAssert state.current_justified_checkpoint == c3 # still old current
|
doAssert state.data.current_justified_checkpoint == c3 # still old current
|
||||||
doAssert state.finalized_checkpoint == old_finalized # no new finalized checkpoint
|
doAssert state.data.finalized_checkpoint == old_finalized # no new finalized checkpoint
|
||||||
|
|
||||||
proc finalizeOn12(state: var BeaconState, epoch: Epoch, sufficient_support: bool) =
|
proc finalizeOn12(state: var HashedBeaconState, epoch: Epoch, sufficient_support: bool) =
|
||||||
## Check finalization on rule 4 "12"
|
## Check finalization on rule 4 "12"
|
||||||
doAssert epoch > 2
|
doAssert epoch > 2
|
||||||
state.slot = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
state.data.slot = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
||||||
|
|
||||||
# 43210 -- epochs ago
|
# 43210 -- epochs ago
|
||||||
# 210xx -- justification bitfields indices preshift
|
# 210xx -- justification bitfields indices preshift
|
||||||
|
@ -179,21 +179,21 @@ proc finalizeOn12(state: var BeaconState, epoch: Epoch, sufficient_support: bool
|
||||||
|
|
||||||
# checkpoints for epochs ago
|
# checkpoints for epochs ago
|
||||||
let (c1, c2, _, _, _) = getCheckpoints(epoch)
|
let (c1, c2, _, _, _) = getCheckpoints(epoch)
|
||||||
putCheckpointsInBlockRoots(state, [c1, c2])
|
putCheckpointsInBlockRoots(state.data, [c1, c2])
|
||||||
|
|
||||||
# Save for final checks
|
# Save for final checks
|
||||||
let old_finalized = state.finalized_checkpoint
|
let old_finalized = state.data.finalized_checkpoint
|
||||||
|
|
||||||
# Mock the state
|
# Mock the state
|
||||||
state.previous_justified_checkpoint = c2
|
state.data.previous_justified_checkpoint = c2
|
||||||
state.current_justified_checkpoint = c2
|
state.data.current_justified_checkpoint = c2
|
||||||
state.justification_bits = 0'u8 # Bitvector of length 4
|
state.data.justification_bits = 0'u8 # Bitvector of length 4
|
||||||
# mock 3rd as justified
|
# mock 3rd as justified
|
||||||
# indices are pre-shift
|
# indices are pre-shift
|
||||||
state.justification_bits.setBit 0
|
state.data.justification_bits.setBit 0
|
||||||
# mock the 2nd latest epoch as justifiable, with 3rd as the source
|
# mock the 2nd latest epoch as justifiable, with 3rd as the source
|
||||||
addMockAttestations(
|
addMockAttestations(
|
||||||
state,
|
state.data,
|
||||||
epoch = epoch - 1,
|
epoch = epoch - 1,
|
||||||
source = c2,
|
source = c2,
|
||||||
target = c1,
|
target = c1,
|
||||||
|
@ -204,13 +204,13 @@ proc finalizeOn12(state: var BeaconState, epoch: Epoch, sufficient_support: bool
|
||||||
transitionEpochUntilJustificationFinalization(state)
|
transitionEpochUntilJustificationFinalization(state)
|
||||||
|
|
||||||
# Checks
|
# Checks
|
||||||
doAssert state.previous_justified_checkpoint == c2 # changed to old current
|
doAssert state.data.previous_justified_checkpoint == c2 # changed to old current
|
||||||
if sufficient_support:
|
if sufficient_support:
|
||||||
doAssert state.current_justified_checkpoint == c1 # changed to second latest
|
doAssert state.data.current_justified_checkpoint == c1 # changed to second latest
|
||||||
doAssert state.finalized_checkpoint == c2 # finalized old previous justified epoch
|
doAssert state.data.finalized_checkpoint == c2 # finalized old previous justified epoch
|
||||||
else:
|
else:
|
||||||
doAssert state.current_justified_checkpoint == c2 # still old current
|
doAssert state.data.current_justified_checkpoint == c2 # still old current
|
||||||
doAssert state.finalized_checkpoint == old_finalized # no new finalized checkpoint
|
doAssert state.data.finalized_checkpoint == old_finalized # no new finalized checkpoint
|
||||||
|
|
||||||
proc payload =
|
proc payload =
|
||||||
suiteReport "[Unit - Spec - Epoch processing] Justification and Finalization " & preset():
|
suiteReport "[Unit - Spec - Epoch processing] Justification and Finalization " & preset():
|
||||||
|
@ -218,7 +218,7 @@ proc payload =
|
||||||
|
|
||||||
const NumValidators = uint64(8) * SLOTS_PER_EPOCH
|
const NumValidators = uint64(8) * SLOTS_PER_EPOCH
|
||||||
let genesisState = initGenesisState(NumValidators)
|
let genesisState = initGenesisState(NumValidators)
|
||||||
doAssert genesisState.validators.len == int NumValidators
|
doAssert genesisState.data.validators.len == int NumValidators
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
var state = newClone(genesisState)
|
var state = newClone(genesisState)
|
||||||
|
|
|
@ -20,43 +20,43 @@ suiteReport "Block processing" & preset():
|
||||||
let
|
let
|
||||||
# Genesis state with minimal number of deposits
|
# Genesis state with minimal number of deposits
|
||||||
# TODO bls verification is a bit of a bottleneck here
|
# TODO bls verification is a bit of a bottleneck here
|
||||||
genesisState = initialize_beacon_state_from_eth1(
|
genesisState = initialize_hashed_beacon_state_from_eth1(
|
||||||
Eth2Digest(), 0, makeInitialDeposits(), {})
|
Eth2Digest(), 0, makeInitialDeposits(), {})
|
||||||
genesisBlock = get_initial_beacon_block(genesisState[])
|
genesisBlock = get_initial_beacon_block(genesisState.data)
|
||||||
genesisRoot = hash_tree_root(genesisBlock.message)
|
genesisRoot = hash_tree_root(genesisBlock.message)
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
var state = newClone(genesisState)
|
var state = newClone(genesisState)
|
||||||
|
|
||||||
timedTest "Passes from genesis state, no block" & preset():
|
timedTest "Passes from genesis state, no block" & preset():
|
||||||
process_slots(state[], state.slot + 1)
|
process_slots(state[], state.data.slot + 1)
|
||||||
check:
|
check:
|
||||||
state.slot == genesisState.slot + 1
|
state.data.slot == genesisState.data.slot + 1
|
||||||
|
|
||||||
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)
|
||||||
new_block = makeTestBlock(state[], previous_block_root)
|
new_block = makeTestBlock(state.data, previous_block_root)
|
||||||
|
|
||||||
let block_ok = state_transition(state[], new_block, {}, noRollback)
|
let block_ok = state_transition(state[], new_block, {}, noRollback)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
block_ok
|
block_ok
|
||||||
|
|
||||||
state.slot == genesisState.slot + 1
|
state.data.slot == genesisState.data.slot + 1
|
||||||
|
|
||||||
timedTest "Passes through epoch update, no block" & preset():
|
timedTest "Passes through epoch update, no block" & preset():
|
||||||
process_slots(state[], Slot(SLOTS_PER_EPOCH))
|
process_slots(state[], Slot(SLOTS_PER_EPOCH))
|
||||||
|
|
||||||
check:
|
check:
|
||||||
state.slot == genesisState.slot + SLOTS_PER_EPOCH
|
state.data.slot == genesisState.data.slot + SLOTS_PER_EPOCH
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
for i in 1..SLOTS_PER_EPOCH.int:
|
for i in 1..SLOTS_PER_EPOCH.int:
|
||||||
let new_block = makeTestBlock(state[], previous_block_root)
|
let new_block = makeTestBlock(state.data, previous_block_root)
|
||||||
|
|
||||||
let block_ok = state_transition(state[], new_block, {}, noRollback)
|
let block_ok = state_transition(state[], new_block, {}, noRollback)
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ suiteReport "Block processing" & preset():
|
||||||
previous_block_root = hash_tree_root(new_block.message)
|
previous_block_root = hash_tree_root(new_block.message)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
state.slot == genesisState.slot + SLOTS_PER_EPOCH
|
state.data.slot == genesisState.data.slot + SLOTS_PER_EPOCH
|
||||||
|
|
||||||
timedTest "Attestation gets processed at epoch" & preset():
|
timedTest "Attestation gets processed at epoch" & preset():
|
||||||
var
|
var
|
||||||
|
@ -74,21 +74,21 @@ suiteReport "Block processing" & preset():
|
||||||
cache = get_empty_per_epoch_cache()
|
cache = get_empty_per_epoch_cache()
|
||||||
|
|
||||||
# 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..
|
||||||
process_slots(state[], state.slot + 1)
|
process_slots(state[], state.data.slot + 1)
|
||||||
|
|
||||||
let
|
let
|
||||||
# Create an attestation for slot 1 signed by the only attester we have!
|
# Create an attestation for slot 1 signed by the only attester we have!
|
||||||
beacon_committee =
|
beacon_committee =
|
||||||
get_beacon_committee(state[], state.slot, 0.CommitteeIndex, cache)
|
get_beacon_committee(state.data, state.data.slot, 0.CommitteeIndex, cache)
|
||||||
attestation = makeAttestation(
|
attestation = makeAttestation(
|
||||||
state[], previous_block_root, beacon_committee[0], cache)
|
state.data, previous_block_root, beacon_committee[0], cache)
|
||||||
|
|
||||||
# Some time needs to pass before attestations are included - this is
|
# Some time needs to pass before attestations are included - this is
|
||||||
# to let the attestation propagate properly to interested participants
|
# to let the attestation propagate properly to interested participants
|
||||||
process_slots(state[], GENESIS_SLOT + MIN_ATTESTATION_INCLUSION_DELAY + 1)
|
process_slots(state[], GENESIS_SLOT + MIN_ATTESTATION_INCLUSION_DELAY + 1)
|
||||||
|
|
||||||
let
|
let
|
||||||
new_block = makeTestBlock(state[], previous_block_root,
|
new_block = makeTestBlock(state.data, previous_block_root,
|
||||||
attestations = @[attestation]
|
attestations = @[attestation]
|
||||||
)
|
)
|
||||||
check state_transition(state[], new_block, {}, noRollback)
|
check state_transition(state[], new_block, {}, noRollback)
|
||||||
|
@ -96,7 +96,7 @@ suiteReport "Block processing" & preset():
|
||||||
check:
|
check:
|
||||||
# TODO epoch attestations can get multiplied now; clean up paths to
|
# TODO epoch attestations can get multiplied now; clean up paths to
|
||||||
# enable exact 1-check again and keep finalization.
|
# enable exact 1-check again and keep finalization.
|
||||||
state.current_epoch_attestations.len >= 1
|
state.data.current_epoch_attestations.len >= 1
|
||||||
|
|
||||||
when const_preset=="minimal":
|
when const_preset=="minimal":
|
||||||
# Can take several minutes with mainnet settings
|
# Can take several minutes with mainnet settings
|
||||||
|
|
Loading…
Reference in New Issue