remove redundant justification and finalization tests (#4412)
This commit is contained in:
parent
e3c062189a
commit
ad8e682f76
|
@ -521,18 +521,6 @@ OK: 7/7 Fail: 0/7 Skip: 0/7
|
||||||
+ default initialization of signatures OK
|
+ default initialization of signatures OK
|
||||||
```
|
```
|
||||||
OK: 3/3 Fail: 0/3 Skip: 0/3
|
OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||||
## [Unit - Spec - Epoch processing] Justification and Finalization [Preset: mainnet]
|
|
||||||
```diff
|
|
||||||
+ Rule I - 234 finalization with enough support OK
|
|
||||||
+ Rule I - 234 finalization without support OK
|
|
||||||
+ Rule II - 23 finalization with enough support OK
|
|
||||||
+ Rule II - 23 finalization without support OK
|
|
||||||
+ Rule III - 123 finalization with enough support OK
|
|
||||||
+ Rule III - 123 finalization without support OK
|
|
||||||
+ Rule IV - 12 finalization with enough support OK
|
|
||||||
+ Rule IV - 12 finalization without support OK
|
|
||||||
```
|
|
||||||
OK: 8/8 Fail: 0/8 Skip: 0/8
|
|
||||||
## chain DAG finalization tests [Preset: mainnet]
|
## chain DAG finalization tests [Preset: mainnet]
|
||||||
```diff
|
```diff
|
||||||
+ init with gaps [Preset: mainnet] OK
|
+ init with gaps [Preset: mainnet] OK
|
||||||
|
@ -620,4 +608,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
|
||||||
OK: 9/9 Fail: 0/9 Skip: 0/9
|
OK: 9/9 Fail: 0/9 Skip: 0/9
|
||||||
|
|
||||||
---TOTAL---
|
---TOTAL---
|
||||||
OK: 345/350 Fail: 0/350 Skip: 5/350
|
OK: 337/342 Fail: 0/342 Skip: 5/342
|
||||||
|
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 201 KiB |
|
@ -50,10 +50,6 @@ import # Unit test
|
||||||
./slashing_protection/test_fixtures,
|
./slashing_protection/test_fixtures,
|
||||||
./slashing_protection/test_slashing_protection_db
|
./slashing_protection/test_slashing_protection_db
|
||||||
|
|
||||||
import # Refactor state transition unit tests
|
|
||||||
# In mainnet these take 2 minutes and are empty TODOs
|
|
||||||
./spec_epoch_processing/test_process_justification_and_finalization
|
|
||||||
|
|
||||||
when not defined(i386):
|
when not defined(i386):
|
||||||
# Avoids "Out of memory" CI failures
|
# Avoids "Out of memory" CI failures
|
||||||
import
|
import
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
# Epoch state transition
|
|
||||||
|
|
||||||
## Finalization and justification
|
|
||||||
|
|
||||||
![](eth2-finalization.png)
|
|
|
@ -1,42 +0,0 @@
|
||||||
# beacon_chain
|
|
||||||
# Copyright (c) 2018-2021 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.
|
|
||||||
|
|
||||||
import
|
|
||||||
# Specs
|
|
||||||
../../beacon_chain/spec/[
|
|
||||||
forks, presets, state_transition, state_transition_epoch],
|
|
||||||
../../beacon_chain/spec/datatypes/phase0
|
|
||||||
|
|
||||||
proc processSlotsUntilEndCurrentEpoch(state: var ForkedHashedBeaconState) =
|
|
||||||
# Process all slots until the end of the last slot of the current epoch
|
|
||||||
var
|
|
||||||
cache = StateCache()
|
|
||||||
info = ForkedEpochInfo()
|
|
||||||
let slot =
|
|
||||||
getStateField(state, slot) + SLOTS_PER_EPOCH -
|
|
||||||
(getStateField(state, slot) mod SLOTS_PER_EPOCH)
|
|
||||||
|
|
||||||
# Transition to slot before the epoch state transition
|
|
||||||
discard process_slots(defaultRuntimeConfig, state, slot - 1, cache, info, {})
|
|
||||||
|
|
||||||
# For the last slot of the epoch,
|
|
||||||
# only process_slot without process_epoch
|
|
||||||
# (see process_slots()) - state.root is invalid after here!
|
|
||||||
process_slot(state.phase0Data.data, getStateRoot(state))
|
|
||||||
|
|
||||||
proc transitionEpochUntilJustificationFinalization*(state: var ForkedHashedBeaconState) =
|
|
||||||
# Process slots and do the epoch transition until crosslinks
|
|
||||||
processSlotsUntilEndCurrentEpoch(state)
|
|
||||||
|
|
||||||
var
|
|
||||||
cache = StateCache()
|
|
||||||
info: phase0.EpochInfo
|
|
||||||
|
|
||||||
info.init(state.phase0Data.data)
|
|
||||||
info.process_attestations(state.phase0Data.data, cache)
|
|
||||||
process_justification_and_finalization(
|
|
||||||
state.phase0Data.data, info.balances)
|
|
|
@ -1,90 +0,0 @@
|
||||||
# beacon_chain
|
|
||||||
# Copyright (c) 2018-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.
|
|
||||||
|
|
||||||
import
|
|
||||||
# Standard library
|
|
||||||
std/strformat,
|
|
||||||
# Specs
|
|
||||||
../../beacon_chain/spec/datatypes/phase0,
|
|
||||||
../../beacon_chain/spec/[beaconstate, validator, helpers],
|
|
||||||
# Test helpers
|
|
||||||
../helpers/digest_helpers
|
|
||||||
|
|
||||||
# Justification and finalization utils
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
|
|
||||||
func addMockAttestations*(
|
|
||||||
state: var phase0.BeaconState, epoch: Epoch,
|
|
||||||
source, target: Checkpoint,
|
|
||||||
sufficient_support = false
|
|
||||||
) =
|
|
||||||
# We must be at the end of the epoch
|
|
||||||
doAssert (state.slot + 1).is_epoch
|
|
||||||
|
|
||||||
# Alias the attestations container
|
|
||||||
var attestations: ptr seq[PendingAttestation]
|
|
||||||
if state.get_current_epoch() == epoch:
|
|
||||||
attestations = state.current_epoch_attestations.asSeq.addr
|
|
||||||
elif state.get_previous_epoch() == epoch:
|
|
||||||
attestations = state.previous_epoch_attestations.asSeq.addr
|
|
||||||
else:
|
|
||||||
raise newException(ValueError, &"Cannot include attestations from epoch {state.get_current_epoch()} in epoch {epoch}")
|
|
||||||
|
|
||||||
# TODO: Working with an unsigned Gwei balance is a recipe for underflows to happen
|
|
||||||
var cache = StateCache()
|
|
||||||
var remaining_balance = state.get_total_active_balance(cache).int64 * 2 div 3
|
|
||||||
|
|
||||||
let
|
|
||||||
committees_per_slot = get_committee_count_per_slot(state, epoch, cache)
|
|
||||||
|
|
||||||
for slot in epoch.slots():
|
|
||||||
for committee_index in get_committee_indices(committees_per_slot):
|
|
||||||
let committee = get_beacon_committee(state, slot, committee_index, cache)
|
|
||||||
|
|
||||||
# Create a bitfield filled with the given count per attestation,
|
|
||||||
# exactly on the right-most part of the committee field.
|
|
||||||
var aggregation_bits = init(CommitteeValidatorsBits, committee.len)
|
|
||||||
for v in 0 ..< committee.len * 2 div 3 + 1:
|
|
||||||
if remaining_balance > 0:
|
|
||||||
# Beware of the underflows, use int
|
|
||||||
remaining_balance -= state.validators.item(v).effective_balance.int64
|
|
||||||
aggregation_bits[v] = true
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
# Remove just one attester to make the marginal support insufficient
|
|
||||||
if not sufficient_support:
|
|
||||||
# Find the first attester if any
|
|
||||||
let idx = aggregation_bits.find(true)
|
|
||||||
if idx != -1:
|
|
||||||
aggregation_bits[idx] = false
|
|
||||||
|
|
||||||
attestations[].add PendingAttestation(
|
|
||||||
aggregation_bits: aggregation_bits,
|
|
||||||
data: AttestationData(
|
|
||||||
slot: slot.Slot,
|
|
||||||
index: committee_index.uint64,
|
|
||||||
beacon_block_root: [byte 0xFF] * 32, # Irrelevant for testing
|
|
||||||
source: source,
|
|
||||||
target: target,
|
|
||||||
),
|
|
||||||
inclusion_delay: 1
|
|
||||||
)
|
|
||||||
|
|
||||||
func getCheckpoints*(epoch: Epoch): tuple[c1, c2, c3, c4, c5: Checkpoint] =
|
|
||||||
if epoch >= 1: result.c1 = Checkpoint(epoch: epoch - 1, root: [byte 0xAA] * 32)
|
|
||||||
if epoch >= 2: result.c2 = Checkpoint(epoch: epoch - 2, root: [byte 0xBB] * 32)
|
|
||||||
if epoch >= 3: result.c3 = Checkpoint(epoch: epoch - 3, root: [byte 0xCC] * 32)
|
|
||||||
if epoch >= 4: result.c4 = Checkpoint(epoch: epoch - 4, root: [byte 0xDD] * 32)
|
|
||||||
if epoch >= 5: result.c5 = Checkpoint(epoch: epoch - 5, root: [byte 0xEE] * 32)
|
|
||||||
|
|
||||||
func putCheckpointsInBlockRoots*(
|
|
||||||
state: var phase0.BeaconState,
|
|
||||||
checkpoints: openArray[Checkpoint]) =
|
|
||||||
for c in checkpoints:
|
|
||||||
let idx = c.epoch.start_slot() mod SLOTS_PER_HISTORICAL_ROOT
|
|
||||||
state.block_roots[idx] = c.root
|
|
|
@ -1,251 +0,0 @@
|
||||||
# beacon_chain
|
|
||||||
# Copyright (c) 2018-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
|
|
||||||
# Standard library
|
|
||||||
# Vendored packages
|
|
||||||
stew/bitops2,
|
|
||||||
# Specs
|
|
||||||
../../beacon_chain/spec/datatypes/base,
|
|
||||||
../../beacon_chain/spec/forks,
|
|
||||||
# Test helpers
|
|
||||||
../mocking/mock_genesis,
|
|
||||||
./epoch_utils,
|
|
||||||
./justification_finalization_helpers,
|
|
||||||
../testutil
|
|
||||||
|
|
||||||
# See diagram: eth2-finalization.png
|
|
||||||
# (source) https://github.com/protolambda/eth2-docs#justification-and-finalization
|
|
||||||
# for a visualization of finalization rules
|
|
||||||
|
|
||||||
proc finalizeOn234(
|
|
||||||
state: var ForkedHashedBeaconState, epoch: Epoch, sufficient_support: bool) =
|
|
||||||
## Check finalization on rule 1 "234"
|
|
||||||
doAssert epoch > 4
|
|
||||||
getStateField(state, slot) = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
|
||||||
|
|
||||||
# 43210 -- epochs ago
|
|
||||||
# 3210x -- justification bitfields indices
|
|
||||||
# 11*0. -- justification bitfield contents. . = this epoch, * is being justified now
|
|
||||||
|
|
||||||
# checkpoints for epochs ago
|
|
||||||
let (c1, c2, c3, c4, _) = getCheckpoints(epoch)
|
|
||||||
putCheckpointsInBlockRoots(state.phase0Data.data, [c1, c2, c3, c4])
|
|
||||||
|
|
||||||
# Save for final checks
|
|
||||||
let old_finalized = getStateField(state, finalized_checkpoint)
|
|
||||||
|
|
||||||
# Mock the state
|
|
||||||
getStateField(state, previous_justified_checkpoint) = c4
|
|
||||||
getStateField(state, current_justified_checkpoint) = c3
|
|
||||||
getStateField(state, justification_bits) = JustificationBits(0'u8) # Bitvector of length 4
|
|
||||||
# mock 3rd and 4th latest epochs as justified
|
|
||||||
# indices are pre-shift
|
|
||||||
uint8(getStateField(state, justification_bits)).setBit 1
|
|
||||||
uint8(getStateField(state, justification_bits)).setBit 2
|
|
||||||
# mock the 2nd latest epoch as justifiable, with 4th as the source
|
|
||||||
addMockAttestations(
|
|
||||||
state.phase0Data.data,
|
|
||||||
epoch = epoch - 2,
|
|
||||||
source = c4,
|
|
||||||
target = c2,
|
|
||||||
sufficient_support = sufficient_support
|
|
||||||
)
|
|
||||||
|
|
||||||
# State transition
|
|
||||||
transitionEpochUntilJustificationFinalization(state)
|
|
||||||
|
|
||||||
# Checks
|
|
||||||
doAssert getStateField(state, previous_justified_checkpoint) == c3 # changed to old current
|
|
||||||
if sufficient_support:
|
|
||||||
doAssert getStateField(state, current_justified_checkpoint) == c2 # changed to second latest
|
|
||||||
doAssert getStateField(state, finalized_checkpoint) == c4 # finalized old previous justified epoch
|
|
||||||
else:
|
|
||||||
doAssert getStateField(state, current_justified_checkpoint) == c3 # still old current
|
|
||||||
doAssert getStateField(state, finalized_checkpoint) == old_finalized # no new finalized checkpoint
|
|
||||||
|
|
||||||
proc finalizeOn23(state: var ForkedHashedBeaconState, epoch: Epoch, sufficient_support: bool) =
|
|
||||||
## Check finalization on rule 2 "23"
|
|
||||||
doAssert epoch > 3
|
|
||||||
getStateField(state, slot) = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
|
||||||
|
|
||||||
# 43210 -- epochs ago
|
|
||||||
# 210xx -- justification bitfields indices preshift
|
|
||||||
# 3210x -- justification bitfield indices postshift
|
|
||||||
# 01*0. -- justification bitfield contents. . = this epoch, * is being justified now
|
|
||||||
|
|
||||||
# checkpoints for epochs ago
|
|
||||||
let (c1, c2, c3, _, _) = getCheckpoints(epoch)
|
|
||||||
putCheckpointsInBlockRoots(state.phase0Data.data, [c1, c2, c3])
|
|
||||||
|
|
||||||
# Save for final checks
|
|
||||||
let old_finalized = getStateField(state, finalized_checkpoint)
|
|
||||||
|
|
||||||
# Mock the state
|
|
||||||
getStateField(state, previous_justified_checkpoint) = c3
|
|
||||||
getStateField(state, current_justified_checkpoint) = c3
|
|
||||||
getStateField(state, justification_bits) = JustificationBits(0'u8) # Bitvector of length 4
|
|
||||||
# mock 3rd as justified
|
|
||||||
# indices are pre-shift
|
|
||||||
uint8(getStateField(state, justification_bits)).setBit 1
|
|
||||||
# mock the 2nd latest epoch as justifiable, with 3rd as the source
|
|
||||||
addMockAttestations(
|
|
||||||
state.phase0Data.data,
|
|
||||||
epoch = epoch - 2,
|
|
||||||
source = c3,
|
|
||||||
target = c2,
|
|
||||||
sufficient_support = sufficient_support
|
|
||||||
)
|
|
||||||
|
|
||||||
# State transition
|
|
||||||
transitionEpochUntilJustificationFinalization(state)
|
|
||||||
|
|
||||||
# Checks
|
|
||||||
doAssert getStateField(state, previous_justified_checkpoint) == c3 # changed to old current
|
|
||||||
if sufficient_support:
|
|
||||||
doAssert getStateField(state, current_justified_checkpoint) == c2 # changed to second latest
|
|
||||||
doAssert getStateField(state, finalized_checkpoint) == c3 # finalized old previous justified epoch
|
|
||||||
else:
|
|
||||||
doAssert getStateField(state, current_justified_checkpoint) == c3 # still old current
|
|
||||||
doAssert getStateField(state, finalized_checkpoint) == old_finalized # no new finalized checkpoint
|
|
||||||
|
|
||||||
proc finalizeOn123(state: var ForkedHashedBeaconState, epoch: Epoch, sufficient_support: bool) =
|
|
||||||
## Check finalization on rule 3 "123"
|
|
||||||
doAssert epoch > 5
|
|
||||||
getStateField(state, slot) = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
|
||||||
|
|
||||||
# 43210 -- epochs ago
|
|
||||||
# 210xx -- justification bitfields indices preshift
|
|
||||||
# 3210x -- justification bitfield indices postshift
|
|
||||||
# 0110*. -- justification bitfield contents. . = this epoch, * is being justified now
|
|
||||||
|
|
||||||
# checkpoints for epochs ago
|
|
||||||
let (c1, c2, c3, c4, c5) = getCheckpoints(epoch)
|
|
||||||
putCheckpointsInBlockRoots(state.phase0Data.data, [c1, c2, c3, c4, c5])
|
|
||||||
|
|
||||||
# Save for final checks
|
|
||||||
let old_finalized = getStateField(state, finalized_checkpoint)
|
|
||||||
|
|
||||||
# Mock the state
|
|
||||||
getStateField(state, previous_justified_checkpoint) = c5
|
|
||||||
getStateField(state, current_justified_checkpoint) = c3
|
|
||||||
getStateField(state, justification_bits) = JustificationBits(0'u8) # Bitvector of length 4
|
|
||||||
# mock 3rd as justified
|
|
||||||
# indices are pre-shift
|
|
||||||
uint8(getStateField(state, justification_bits)).setBit 1
|
|
||||||
# mock the 2nd latest epoch as justifiable, with 5th as the source
|
|
||||||
addMockAttestations(
|
|
||||||
state.phase0Data.data,
|
|
||||||
epoch = epoch - 2,
|
|
||||||
source = c5,
|
|
||||||
target = c2,
|
|
||||||
sufficient_support = sufficient_support
|
|
||||||
)
|
|
||||||
# mock the 1st latest epoch as justifiable with 3rd as source
|
|
||||||
addMockAttestations(
|
|
||||||
state.phase0Data.data,
|
|
||||||
epoch = epoch - 1,
|
|
||||||
source = c3,
|
|
||||||
target = c1,
|
|
||||||
sufficient_support = sufficient_support
|
|
||||||
)
|
|
||||||
|
|
||||||
# State transition
|
|
||||||
transitionEpochUntilJustificationFinalization(state)
|
|
||||||
|
|
||||||
# Checks
|
|
||||||
doAssert getStateField(state, previous_justified_checkpoint) == c3 # changed to old current
|
|
||||||
if sufficient_support:
|
|
||||||
doAssert getStateField(state, current_justified_checkpoint) == c1 # changed to second latest
|
|
||||||
doAssert getStateField(state, finalized_checkpoint) == c3 # finalized old previous justified epoch
|
|
||||||
else:
|
|
||||||
doAssert getStateField(state, current_justified_checkpoint) == c3 # still old current
|
|
||||||
doAssert getStateField(state, finalized_checkpoint) == old_finalized # no new finalized checkpoint
|
|
||||||
|
|
||||||
proc finalizeOn12(state: var ForkedHashedBeaconState, epoch: Epoch, sufficient_support: bool) =
|
|
||||||
## Check finalization on rule 4 "12"
|
|
||||||
doAssert epoch > 2
|
|
||||||
getStateField(state, slot) = Slot((epoch * SLOTS_PER_EPOCH) - 1) # Skip ahead to just before epoch
|
|
||||||
|
|
||||||
# 43210 -- epochs ago
|
|
||||||
# 210xx -- justification bitfields indices preshift
|
|
||||||
# 3210x -- justification bitfield indices postshift
|
|
||||||
# 01*0. -- justification bitfield contents. . = this epoch, * is being justified now
|
|
||||||
|
|
||||||
# checkpoints for epochs ago
|
|
||||||
let (c1, c2, _, _, _) = getCheckpoints(epoch)
|
|
||||||
putCheckpointsInBlockRoots(state.phase0Data.data, [c1, c2])
|
|
||||||
|
|
||||||
# Save for final checks
|
|
||||||
let old_finalized = getStateField(state, finalized_checkpoint)
|
|
||||||
|
|
||||||
# Mock the state
|
|
||||||
getStateField(state, previous_justified_checkpoint) = c2
|
|
||||||
getStateField(state, current_justified_checkpoint) = c2
|
|
||||||
getStateField(state, justification_bits) = JustificationBits(0'u8) # Bitvector of length 4
|
|
||||||
# mock 3rd as justified
|
|
||||||
# indices are pre-shift
|
|
||||||
uint8(getStateField(state, justification_bits)).setBit 0
|
|
||||||
# mock the 2nd latest epoch as justifiable, with 3rd as the source
|
|
||||||
addMockAttestations(
|
|
||||||
state.phase0Data.data,
|
|
||||||
epoch = epoch - 1,
|
|
||||||
source = c2,
|
|
||||||
target = c1,
|
|
||||||
sufficient_support = sufficient_support
|
|
||||||
)
|
|
||||||
|
|
||||||
# State transition
|
|
||||||
transitionEpochUntilJustificationFinalization(state)
|
|
||||||
|
|
||||||
# Checks
|
|
||||||
doAssert getStateField(state, previous_justified_checkpoint) == c2 # changed to old current
|
|
||||||
if sufficient_support:
|
|
||||||
doAssert getStateField(state, current_justified_checkpoint) == c1 # changed to second latest
|
|
||||||
doAssert getStateField(state, finalized_checkpoint) == c2 # finalized old previous justified epoch
|
|
||||||
else:
|
|
||||||
doAssert getStateField(state, current_justified_checkpoint) == c2 # still old current
|
|
||||||
doAssert getStateField(state, finalized_checkpoint) == old_finalized # no new finalized checkpoint
|
|
||||||
|
|
||||||
proc payload =
|
|
||||||
suite "[Unit - Spec - Epoch processing] Justification and Finalization " & preset():
|
|
||||||
echo " Finalization rules are detailed at https://github.com/protolambda/eth2-docs#justification-and-finalization"
|
|
||||||
|
|
||||||
const NumValidators = uint64(8) * SLOTS_PER_EPOCH
|
|
||||||
let genesisState = initGenesisState(NumValidators)
|
|
||||||
doAssert getStateField(genesisState[], validators).lenu64 == NumValidators
|
|
||||||
|
|
||||||
setup:
|
|
||||||
let state = assignClone(genesisState[])
|
|
||||||
|
|
||||||
test " Rule I - 234 finalization with enough support":
|
|
||||||
finalizeOn234(state[], Epoch 5, sufficient_support = true)
|
|
||||||
|
|
||||||
test " Rule I - 234 finalization without support":
|
|
||||||
finalizeOn234(state[], Epoch 5, sufficient_support = false)
|
|
||||||
|
|
||||||
test " Rule II - 23 finalization with enough support":
|
|
||||||
finalizeOn23(state[], Epoch 4, sufficient_support = true)
|
|
||||||
|
|
||||||
test " Rule II - 23 finalization without support":
|
|
||||||
finalizeOn23(state[], Epoch 4, sufficient_support = false)
|
|
||||||
|
|
||||||
test " Rule III - 123 finalization with enough support":
|
|
||||||
finalizeOn123(state[], Epoch 6, sufficient_support = true)
|
|
||||||
|
|
||||||
test " Rule III - 123 finalization without support":
|
|
||||||
finalizeOn123(state[], Epoch 6, sufficient_support = false)
|
|
||||||
|
|
||||||
test " Rule IV - 12 finalization with enough support":
|
|
||||||
finalizeOn12(state[], Epoch 3, sufficient_support = true)
|
|
||||||
|
|
||||||
test " Rule IV - 12 finalization without support":
|
|
||||||
finalizeOn12(state[], Epoch 3, sufficient_support = false)
|
|
||||||
|
|
||||||
payload()
|
|
Loading…
Reference in New Issue