Fork choice EF consensus tests (#3041)
* add EF fork choice tests to CI * checkpoints * compilation fixes and add test to preset dependent suite * support longpaths on Windows CI * skip minimal tests (long paths issue + impl detals tested) * fix stackoverflow on some platforms * rebase on top of https://github.com/status-im/nimbus-eth2/pull/3054 * fix stack usage
This commit is contained in:
parent
a223d62b07
commit
97da6e1365
|
@ -102,6 +102,10 @@ jobs:
|
|||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Support longpaths (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: git config --system core.longpaths true
|
||||
|
||||
- name: Checkout nimbus-eth2
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
|
|
|
@ -766,6 +766,17 @@ OK: 36/36 Fail: 0/36 Skip: 0/36
|
|||
+ process_light_client_update_timeout OK
|
||||
```
|
||||
OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||
## Ethereum Foundation - ForkChoice [Preset: mainnet]
|
||||
```diff
|
||||
+ ForkChoice - mainnet/phase0/fork_choice/get_head/pyspec_tests/chain_no_attestations OK
|
||||
+ ForkChoice - mainnet/phase0/fork_choice/get_head/pyspec_tests/genesis OK
|
||||
+ ForkChoice - mainnet/phase0/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_we OK
|
||||
+ ForkChoice - mainnet/phase0/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attesta OK
|
||||
+ ForkChoice - mainnet/phase0/fork_choice/on_block/pyspec_tests/basic OK
|
||||
+ ForkChoice - mainnet/phase0/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK
|
||||
ForkChoice - mainnet/phase0/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
|
||||
```
|
||||
OK: 6/7 Fail: 0/7 Skip: 1/7
|
||||
## Ethereum Foundation - Merge - Epoch Processing - Effective balance updates [Preset: mainnet]
|
||||
```diff
|
||||
+ Effective balance updates - effective_balance_hysteresis [Preset: mainnet] OK
|
||||
|
@ -1154,4 +1165,4 @@ OK: 44/44 Fail: 0/44 Skip: 0/44
|
|||
OK: 27/27 Fail: 0/27 Skip: 0/27
|
||||
|
||||
---TOTAL---
|
||||
OK: 984/984 Fail: 0/984 Skip: 0/984
|
||||
OK: 990/991 Fail: 0/991 Skip: 1/991
|
||||
|
|
|
@ -784,6 +784,27 @@ OK: 36/36 Fail: 0/36 Skip: 0/36
|
|||
+ process_light_client_update_timeout OK
|
||||
```
|
||||
OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||
## Ethereum Foundation - ForkChoice [Preset: minimal]
|
||||
```diff
|
||||
ForkChoice - minimal/phase0/fork_choice/get_head/pyspec_tests/chain_no_attestations Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/get_head/pyspec_tests/filtered_block_tree Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/get_head/pyspec_tests/genesis Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_we Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attesta Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/basic Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/new_finalized_slot_is_justif Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/new_finalized_slot_is_not_ju Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/new_justified_is_later_than_ Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/on_block_before_finalized Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/on_block_checkpoints Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slot Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slot Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/on_block_future_block Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/on_block_outside_safe_slots_ Skip
|
||||
ForkChoice - minimal/phase0/fork_choice/on_block/pyspec_tests/on_block_update_justified_ch Skip
|
||||
```
|
||||
OK: 0/17 Fail: 0/17 Skip: 17/17
|
||||
## Ethereum Foundation - Merge - Epoch Processing - Effective balance updates [Preset: minimal]
|
||||
```diff
|
||||
+ Effective balance updates - effective_balance_hysteresis [Preset: minimal] OK
|
||||
|
@ -1198,4 +1219,4 @@ OK: 48/48 Fail: 0/48 Skip: 0/48
|
|||
OK: 30/30 Fail: 0/30 Skip: 0/30
|
||||
|
||||
---TOTAL---
|
||||
OK: 1020/1020 Fail: 0/1020 Skip: 0/1020
|
||||
OK: 1020/1037 Fail: 0/1037 Skip: 17/1037
|
||||
|
|
|
@ -131,8 +131,8 @@ proc init*(T: type AttestationPool, dag: ChainDAGRef,
|
|||
# too big - getting an EpochRef can be expensive.
|
||||
forkChoice.backend.process_block(
|
||||
blckRef.root, blckRef.parent.root,
|
||||
epochRef.current_justified_checkpoint.epoch,
|
||||
epochRef.finalized_checkpoint.epoch)
|
||||
epochRef.current_justified_checkpoint,
|
||||
epochRef.finalized_checkpoint)
|
||||
else:
|
||||
epochRef = dag.getEpochRef(blckRef, blckRef.slot.epoch)
|
||||
withBlck(dag.get(blckRef).data):
|
||||
|
|
|
@ -47,22 +47,20 @@ func compute_deltas(
|
|||
logScope:
|
||||
topics = "fork_choice"
|
||||
|
||||
func init*(T: type ForkChoiceBackend,
|
||||
justified_epoch: Epoch,
|
||||
finalized_root: Eth2Digest,
|
||||
finalized_epoch: Epoch): T =
|
||||
proc init*(T: type ForkChoiceBackend,
|
||||
justifiedCheckpoint: Checkpoint,
|
||||
finalizedCheckpoint: Checkpoint): T =
|
||||
T(
|
||||
proto_array: ProtoArray.init(
|
||||
justified_epoch,
|
||||
finalized_root,
|
||||
finalized_epoch
|
||||
justifiedCheckpoint,
|
||||
finalizedCheckpoint
|
||||
)
|
||||
)
|
||||
|
||||
proc init*(T: type ForkChoice,
|
||||
epochRef: EpochRef,
|
||||
blck: BlockRef): T =
|
||||
## Initialize a fork choice context for a genesis state - in the genesis
|
||||
## Initialize a fork choice context for a finalized state - in the finalized
|
||||
## state, the justified and finalized checkpoints are the same, so only one
|
||||
## is used here
|
||||
debug "Initializing fork choice",
|
||||
|
@ -70,14 +68,14 @@ proc init*(T: type ForkChoice,
|
|||
|
||||
let
|
||||
justified = BalanceCheckpoint(
|
||||
blck: blck, epoch: epochRef.epoch, balances: epochRef.effective_balances)
|
||||
checkpoint: Checkpoint(root: blck.root, epoch: epochRef.epoch),
|
||||
balances: epochRef.effective_balances)
|
||||
finalized = Checkpoint(root: blck.root, epoch: epochRef.epoch)
|
||||
best_justified = Checkpoint(
|
||||
root: justified.blck.root, epoch: justified.epoch)
|
||||
root: blck.root, epoch: epochRef.epoch)
|
||||
|
||||
ForkChoice(
|
||||
backend: ForkChoiceBackend.init(
|
||||
epochRef.epoch, blck.root, epochRef.epoch),
|
||||
backend: ForkChoiceBackend.init(best_justified, finalized),
|
||||
checkpoints: Checkpoints(
|
||||
justified: justified,
|
||||
finalized: finalized,
|
||||
|
@ -102,18 +100,19 @@ proc on_tick(self: var Checkpoints, dag: ChainDAGRef, time: Slot): FcResult[void
|
|||
self.time = time
|
||||
|
||||
if newEpoch and
|
||||
self.best_justified.epoch > self.justified.epoch:
|
||||
self.best_justified.epoch > self.justified.checkpoint.epoch:
|
||||
let blck = dag.getRef(self.best_justified.root)
|
||||
if blck.isNil:
|
||||
return err ForkChoiceError(
|
||||
kind: fcJustifiedNodeUnknown,
|
||||
blockRoot: self.best_justified.root)
|
||||
|
||||
let epochRef = dag.getEpochRef(blck, self.best_justified.epoch)
|
||||
self.justified = BalanceCheckpoint(
|
||||
blck: blck,
|
||||
epoch: epochRef.epoch,
|
||||
balances: epochRef.effective_balances)
|
||||
|
||||
let ancestor = blck.atEpochStart(self.finalized.epoch)
|
||||
if ancestor.blck.root == self.finalized.root:
|
||||
let epochRef = dag.getEpochRef(blck, self.best_justified.epoch)
|
||||
self.justified = BalanceCheckpoint(
|
||||
checkpoint: Checkpoint(root: blck.root, epoch: epochRef.epoch),
|
||||
balances: epochRef.effective_balances)
|
||||
ok()
|
||||
|
||||
func process_attestation_queue(self: var ForkChoice) {.gcsafe.}
|
||||
|
@ -207,7 +206,7 @@ func should_update_justified_checkpoint(
|
|||
return ok(true)
|
||||
|
||||
let
|
||||
justified_slot = compute_start_slot_at_epoch(self.justified.epoch)
|
||||
justified_slot = compute_start_slot_at_epoch(self.justified.checkpoint.epoch)
|
||||
new_justified_checkpoint = epochRef.current_justified_checkpoint
|
||||
justified_blck = dag.getRef(new_justified_checkpoint.root)
|
||||
|
||||
|
@ -218,7 +217,7 @@ func should_update_justified_checkpoint(
|
|||
|
||||
let justified_ancestor = justified_blck.atSlot(justified_slot)
|
||||
|
||||
if justified_ancestor.blck.root != self.justified.blck.root:
|
||||
if justified_ancestor.blck.root != self.justified.checkpoint.root:
|
||||
return ok(false)
|
||||
|
||||
ok(true)
|
||||
|
@ -234,53 +233,57 @@ proc process_state(self: var Checkpoints,
|
|||
trace "Processing epoch",
|
||||
epoch = epochRef.epoch,
|
||||
state_justified_epoch = state_justified_epoch,
|
||||
current_justified = self.justified.epoch,
|
||||
current_justified = self.justified.checkpoint.epoch,
|
||||
state_finalized_epoch = state_finalized_epoch,
|
||||
current_finalized = self.finalized.epoch
|
||||
|
||||
if state_justified_epoch > self.justified.epoch:
|
||||
if state_justified_epoch > self.justified.checkpoint.epoch:
|
||||
if state_justified_epoch > self.best_justified.epoch:
|
||||
self.best_justified = epochRef.current_justified_checkpoint
|
||||
|
||||
if ? should_update_justified_checkpoint(self, dag, epochRef):
|
||||
let
|
||||
justifiedBlck = blck.atEpochStart(state_justified_epoch)
|
||||
justifiedEpoch = dag.getEpochRef(justifiedBlck.blck, state_justified_epoch)
|
||||
justifiedEpochRef = dag.getEpochRef(justifiedBlck.blck, state_justified_epoch)
|
||||
|
||||
self.justified =
|
||||
BalanceCheckpoint(
|
||||
blck: justifiedBlck.blck,
|
||||
epoch: justifiedEpoch.epoch,
|
||||
balances: justifiedEpoch.effective_balances)
|
||||
checkpoint: Checkpoint(
|
||||
root: justifiedBlck.blck.root,
|
||||
epoch: justifiedEpochRef.epoch
|
||||
),
|
||||
balances: justifiedEpochRef.effective_balances)
|
||||
|
||||
if state_finalized_epoch > self.finalized.epoch:
|
||||
self.finalized = epochRef.finalized_checkpoint
|
||||
|
||||
if self.justified.epoch != state_justified_epoch or
|
||||
self.justified.blck.root != epochRef.current_justified_checkpoint.root:
|
||||
if self.justified.checkpoint.epoch != state_justified_epoch or
|
||||
self.justified.checkpoint.root != epochRef.current_justified_checkpoint.root:
|
||||
|
||||
if (state_justified_epoch > self.justified.epoch) or
|
||||
(self.justified.blck.atEpochStart(self.finalized.epoch).blck.root !=
|
||||
if (state_justified_epoch > self.justified.checkpoint.epoch) or
|
||||
(dag.getRef(self.justified.checkpoint.root).atEpochStart(self.finalized.epoch).blck.root !=
|
||||
self.finalized.root):
|
||||
|
||||
let
|
||||
justifiedBlck = blck.atEpochStart(state_justified_epoch)
|
||||
justifiedEpoch = dag.getEpochRef(justifiedBlck.blck, state_justified_epoch)
|
||||
justifiedEpochRef = dag.getEpochRef(justifiedBlck.blck, state_justified_epoch)
|
||||
|
||||
self.justified =
|
||||
BalanceCheckpoint(
|
||||
blck: justifiedBlck.blck,
|
||||
epoch: justifiedEpoch.epoch,
|
||||
balances: justifiedEpoch.effective_balances)
|
||||
checkpoint: Checkpoint(
|
||||
root: justifiedBlck.blck.root,
|
||||
epoch: justifiedEpochRef.epoch
|
||||
),
|
||||
balances: justifiedEpochRef.effective_balances)
|
||||
ok()
|
||||
|
||||
func process_block*(self: var ForkChoiceBackend,
|
||||
block_root: Eth2Digest,
|
||||
parent_root: Eth2Digest,
|
||||
justified_epoch: Epoch,
|
||||
finalized_epoch: Epoch): FcResult[void] =
|
||||
justified_checkpoint: Checkpoint,
|
||||
finalized_checkpoint: Checkpoint): FcResult[void] =
|
||||
self.proto_array.onBlock(
|
||||
block_root, parent_root, justified_epoch, finalized_epoch)
|
||||
block_root, parent_root, justified_checkpoint, finalized_checkpoint)
|
||||
|
||||
# TODO workaround for https://github.com/nim-lang/Nim/issues/18095
|
||||
# it expresses as much of:
|
||||
|
@ -320,8 +323,8 @@ proc process_block*(self: var ForkChoice,
|
|||
|
||||
? process_block(
|
||||
self.backend, blckRef.root, blck.parent_root,
|
||||
epochRef.current_justified_checkpoint.epoch,
|
||||
epochRef.finalized_checkpoint.epoch
|
||||
epochRef.current_justified_checkpoint,
|
||||
epochRef.finalized_checkpoint
|
||||
)
|
||||
|
||||
trace "Integrating block in fork choice",
|
||||
|
@ -331,9 +334,8 @@ proc process_block*(self: var ForkChoice,
|
|||
|
||||
func find_head*(
|
||||
self: var ForkChoiceBackend,
|
||||
justified_epoch: Epoch,
|
||||
justified_root: Eth2Digest,
|
||||
finalized_epoch: Epoch,
|
||||
justifiedCheckpoint: Checkpoint,
|
||||
finalizedCheckpoint: Checkpoint,
|
||||
justified_state_balances: seq[Gwei]
|
||||
): FcResult[Eth2Digest] =
|
||||
## Returns the new blockchain head
|
||||
|
@ -351,20 +353,19 @@ func find_head*(
|
|||
|
||||
# Apply score changes
|
||||
? self.proto_array.applyScoreChanges(
|
||||
deltas, justified_epoch, finalized_epoch
|
||||
deltas, justifiedCheckpoint, finalizedCheckpoint
|
||||
)
|
||||
|
||||
self.balances = justified_state_balances
|
||||
|
||||
# Find the best block
|
||||
var new_head{.noInit.}: Eth2Digest
|
||||
? self.proto_array.findHead(new_head, justified_root)
|
||||
? self.proto_array.findHead(new_head, justifiedCheckpoint.root)
|
||||
|
||||
{.noSideEffect.}:
|
||||
trace "Fork choice requested",
|
||||
justified_epoch = justified_epoch,
|
||||
justified_root = shortLog(justified_root),
|
||||
finalized_epoch = finalized_epoch,
|
||||
justifiedCheckpoint = shortLog(justifiedCheckpoint),
|
||||
finalizedCheckpoint = shortLog(finalizedCheckpoint),
|
||||
fork_choice_head = shortLog(new_head)
|
||||
|
||||
return ok(new_head)
|
||||
|
@ -376,9 +377,8 @@ proc get_head*(self: var ForkChoice,
|
|||
? self.update_time(dag, wallSlot)
|
||||
|
||||
self.backend.find_head(
|
||||
self.checkpoints.justified.epoch,
|
||||
self.checkpoints.justified.blck.root,
|
||||
self.checkpoints.finalized.epoch,
|
||||
self.checkpoints.justified.checkpoint,
|
||||
self.checkpoints.finalized,
|
||||
self.checkpoints.justified.balances,
|
||||
)
|
||||
|
||||
|
|
|
@ -69,11 +69,11 @@ type
|
|||
indicesLen*: int
|
||||
of fcInvalidBestNode:
|
||||
startRoot*: Eth2Digest
|
||||
justifiedEpoch*: Epoch
|
||||
finalizedEpoch*: Epoch
|
||||
fkChoiceJustifiedCheckpoint*: Checkpoint
|
||||
fkChoiceFinalizedCheckpoint*: Checkpoint
|
||||
headRoot*: Eth2Digest
|
||||
headJustifiedEpoch*: Epoch
|
||||
headFinalizedEpoch*: Epoch
|
||||
headJustifiedCheckpoint*: Checkpoint
|
||||
headFinalizedCheckpoint*: Checkpoint
|
||||
of fcUnknownParent:
|
||||
childRoot*: Eth2Digest
|
||||
parentRoot*: Eth2Digest
|
||||
|
@ -89,23 +89,22 @@ type
|
|||
## to get the physical index
|
||||
|
||||
ProtoArray* = object
|
||||
justifiedEpoch*: Epoch
|
||||
finalizedEpoch*: Epoch
|
||||
nodes*: Protonodes
|
||||
justifiedCheckpoint*: Checkpoint
|
||||
finalizedCheckpoint*: Checkpoint
|
||||
nodes*: ProtoNodes
|
||||
indices*: Table[Eth2Digest, Index]
|
||||
|
||||
ProtoNode* = object
|
||||
root*: Eth2Digest
|
||||
parent*: Option[Index]
|
||||
justifiedEpoch*: Epoch
|
||||
finalizedEpoch*: Epoch
|
||||
justifiedCheckpoint*: Checkpoint
|
||||
finalizedCheckpoint*: Checkpoint
|
||||
weight*: int64
|
||||
bestChild*: Option[Index]
|
||||
bestDescendant*: Option[Index]
|
||||
|
||||
BalanceCheckpoint* = object
|
||||
blck*: BlockRef
|
||||
epoch*: Epoch
|
||||
checkpoint*: Checkpoint
|
||||
balances*: seq[Gwei]
|
||||
|
||||
Checkpoints* = object
|
||||
|
@ -137,7 +136,6 @@ type
|
|||
ForkChoice* = object
|
||||
backend*: ForkChoiceBackend
|
||||
checkpoints*: Checkpoints
|
||||
finalizedBlock*: BlockRef ## Any finalized block used at startup
|
||||
queuedAttestations*: seq[QueuedAttestation]
|
||||
|
||||
func shortlog*(vote: VoteTracker): auto =
|
||||
|
|
|
@ -84,30 +84,29 @@ func nodeLeadsToViableHead(self: ProtoArray, node: ProtoNode): FcResult[bool]
|
|||
# ----------------------------------------------------------------------
|
||||
|
||||
func init*(T: type ProtoArray,
|
||||
justifiedEpoch: Epoch,
|
||||
finalizedRoot: Eth2Digest,
|
||||
finalizedEpoch: Epoch): T =
|
||||
justifiedCheckpoint: Checkpoint,
|
||||
finalizedCheckpoint: Checkpoint): T =
|
||||
let node = ProtoNode(
|
||||
root: finalizedRoot,
|
||||
root: finalizedCheckpoint.root,
|
||||
parent: none(int),
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
justifiedCheckpoint: justifiedCheckpoint,
|
||||
finalizedCheckpoint: finalizedCheckpoint,
|
||||
weight: 0,
|
||||
bestChild: none(int),
|
||||
bestDescendant: none(int)
|
||||
)
|
||||
|
||||
T(
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
justifiedCheckpoint: justifiedCheckpoint,
|
||||
finalizedCheckpoint: finalizedCheckpoint,
|
||||
nodes: ProtoNodes(buf: @[node], offset: 0),
|
||||
indices: {node.root: 0}.toTable()
|
||||
)
|
||||
|
||||
func applyScoreChanges*(self: var ProtoArray,
|
||||
deltas: var openArray[Delta],
|
||||
justifiedEpoch: Epoch,
|
||||
finalizedEpoch: Epoch): FcResult[void] =
|
||||
justifiedCheckpoint: Checkpoint,
|
||||
finalizedCheckpoint: Checkpoint): FcResult[void] =
|
||||
## Iterate backwards through the array, touching all nodes and their parents
|
||||
## and potentially the best-child of each parent.
|
||||
##
|
||||
|
@ -128,8 +127,8 @@ func applyScoreChanges*(self: var ProtoArray,
|
|||
deltasLen: deltas.len,
|
||||
indicesLen: self.indices.len)
|
||||
|
||||
self.justifiedEpoch = justifiedEpoch
|
||||
self.finalizedEpoch = finalizedEpoch
|
||||
self.justifiedCheckpoint = justifiedCheckpoint
|
||||
self.finalizedCheckpoint = finalizedCheckpoint
|
||||
|
||||
## Alias
|
||||
# This cannot raise the IndexError exception, how to tell compiler?
|
||||
|
@ -206,8 +205,8 @@ func applyScoreChanges*(self: var ProtoArray,
|
|||
func onBlock*(self: var ProtoArray,
|
||||
root: Eth2Digest,
|
||||
parent: Eth2Digest,
|
||||
justifiedEpoch: Epoch,
|
||||
finalizedEpoch: Epoch): FcResult[void] =
|
||||
justifiedCheckpoint: Checkpoint,
|
||||
finalizedCheckpoint: Checkpoint): FcResult[void] =
|
||||
## Register a block with the fork choice
|
||||
## A block `hasParentInForkChoice` may be false
|
||||
## on fork choice initialization:
|
||||
|
@ -234,8 +233,8 @@ func onBlock*(self: var ProtoArray,
|
|||
let node = ProtoNode(
|
||||
root: root,
|
||||
parent: some(parentIdx),
|
||||
justifiedEpoch: justifiedEpoch,
|
||||
finalizedEpoch: finalizedEpoch,
|
||||
justifiedCheckpoint: justifiedCheckpoint,
|
||||
finalizedCheckpoint: finalizedCheckpoint,
|
||||
weight: 0,
|
||||
bestChild: none(int),
|
||||
bestDescendant: none(int)
|
||||
|
@ -283,11 +282,11 @@ func findHead*(self: var ProtoArray,
|
|||
return err ForkChoiceError(
|
||||
kind: fcInvalidBestNode,
|
||||
startRoot: justifiedRoot,
|
||||
justifiedEpoch: self.justifiedEpoch,
|
||||
finalizedEpoch: self.finalizedEpoch,
|
||||
fkChoiceJustifiedCheckpoint: self.justifiedCheckpoint,
|
||||
fkChoiceFinalizedCheckpoint: self.finalizedCheckpoint,
|
||||
headRoot: justifiedNode.get().root,
|
||||
headJustifiedEpoch: justifiedNode.get().justifiedEpoch,
|
||||
headFinalizedEpoch: justifiedNode.get().finalizedEpoch)
|
||||
headJustifiedCheckpoint: justifiedNode.get().justifiedCheckpoint,
|
||||
headFinalizedCheckpoint: justifiedNode.get().finalizedCheckpoint)
|
||||
|
||||
head = bestNode.get().root
|
||||
ok()
|
||||
|
@ -456,11 +455,11 @@ func nodeIsViableForHead(self: ProtoArray, node: ProtoNode): bool =
|
|||
## Any node that has a different finalized or justified epoch
|
||||
## should not be viable for the head.
|
||||
(
|
||||
(node.justifiedEpoch == self.justifiedEpoch) or
|
||||
(self.justifiedEpoch == Epoch(0))
|
||||
(node.justifiedCheckpoint == self.justifiedCheckpoint) or
|
||||
(self.justifiedCheckpoint.epoch == Epoch(0))
|
||||
) and (
|
||||
(node.finalizedEpoch == self.finalizedEpoch) or
|
||||
(self.finalizedEpoch == Epoch(0))
|
||||
(node.finalizedCheckpoint == self.finalizedCheckpoint) or
|
||||
(self.finalizedCheckpoint.epoch == Epoch(0))
|
||||
)
|
||||
|
||||
# Sanity checks
|
||||
|
|
|
@ -14,6 +14,7 @@ import
|
|||
import
|
||||
./phase0/all_phase0_fixtures,
|
||||
./altair/all_altair_fixtures,
|
||||
./merge/all_merge_fixtures
|
||||
./merge/all_merge_fixtures,
|
||||
./test_fixture_fork_choice
|
||||
|
||||
summarizeLongTests("ConsensusSpecPreset")
|
||||
|
|
|
@ -0,0 +1,346 @@
|
|||
# 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
|
||||
# Standard library
|
||||
std/[strformat, tables, options, json, os, strutils],
|
||||
# Status libraries
|
||||
stew/[results, endians2], snappy, chronicles,
|
||||
eth/keys, taskpools,
|
||||
# Internals
|
||||
../../beacon_chain/spec/[helpers, forks],
|
||||
../../beacon_chain/spec/datatypes/[
|
||||
base,
|
||||
phase0, altair, merge],
|
||||
../../beacon_chain/fork_choice/[fork_choice, fork_choice_types],
|
||||
../../beacon_chain/beacon_chain_db,
|
||||
../../beacon_chain/consensus_object_pools/[
|
||||
blockchain_dag, block_quarantine, block_clearance, spec_cache],
|
||||
# Third-party
|
||||
yaml,
|
||||
# Test
|
||||
../testutil,
|
||||
./fixtures_utils
|
||||
|
||||
# Test format described at https://github.com/ethereum/consensus-specs/tree/v1.1.0/tests/formats/fork_choice
|
||||
# Note that our implementation has been optimized with "ProtoArray"
|
||||
# instead of following the spec (in particular the "store").
|
||||
|
||||
type
|
||||
OpKind = enum
|
||||
opOnTick
|
||||
opOnAttestation
|
||||
opOnBlock
|
||||
opOnMergeBlock
|
||||
opChecks
|
||||
|
||||
Operation = object
|
||||
valid: bool
|
||||
# variant specific fields
|
||||
case kind*: OpKind
|
||||
of opOnTick:
|
||||
tick: int
|
||||
of opOnAttestation:
|
||||
att: Attestation
|
||||
of opOnBlock:
|
||||
blk: ForkedSignedBeaconBlock
|
||||
of opOnMergeBlock:
|
||||
powBlock: PowBlock
|
||||
of opChecks:
|
||||
checks: JsonNode
|
||||
|
||||
proc initialLoad(
|
||||
path: string, db: BeaconChainDB,
|
||||
StateType, BlockType: typedesc): tuple[
|
||||
dag: ChainDagRef, fkChoice: ref ForkChoice
|
||||
] =
|
||||
|
||||
# TODO: support more than phase 0 genesis
|
||||
|
||||
let state = newClone(parseTest(
|
||||
path/"anchor_state.ssz_snappy",
|
||||
SSZ, StateType
|
||||
))
|
||||
|
||||
# TODO stack usage. newClone and assignClone do not seem to
|
||||
# prevent temporaries created by case objects
|
||||
let forkedState = new ForkedHashedBeaconState
|
||||
forkedState.kind = BeaconStateFork.Phase0
|
||||
forkedState.phase0Data.data = state[]
|
||||
forkedState.phase0Data.root = hash_tree_root(state[])
|
||||
|
||||
let blk = parseTest(
|
||||
path/"anchor_block.ssz_snappy",
|
||||
SSZ, BlockType
|
||||
)
|
||||
|
||||
|
||||
let signedBlock = ForkedSignedBeaconBlock.init(phase0.SignedBeaconBlock(
|
||||
message: blk,
|
||||
# signature: - unused as it's trusted
|
||||
root: hashTreeRoot(blk)
|
||||
))
|
||||
|
||||
ChainDagRef.preInit(
|
||||
db,
|
||||
forkedState[], forkedState[],
|
||||
asTrusted(signedBlock)
|
||||
)
|
||||
let dag = ChainDAGRef.init(
|
||||
defaultRuntimeConfig,
|
||||
db,
|
||||
updateFlags = {}
|
||||
)
|
||||
let fkChoice = newClone(ForkChoice.init(
|
||||
dag.getFinalizedEpochRef(),
|
||||
dag.finalizedHead.blck
|
||||
))
|
||||
|
||||
(dag, fkChoice)
|
||||
|
||||
proc loadOps(path: string, fork: BeaconBlockFork): seq[Operation] =
|
||||
let stepsYAML = readFile(path/"steps.yaml")
|
||||
let steps = yaml.loadToJson(stepsYAML)
|
||||
|
||||
result = @[]
|
||||
for step in steps[0]:
|
||||
if step.hasKey"tick":
|
||||
result.add Operation(kind: opOnTick, tick: step["tick"].getInt())
|
||||
elif step.hasKey"block":
|
||||
let filename = step["block"].getStr()
|
||||
case fork
|
||||
of BeaconBlockFork.Phase0:
|
||||
let blk = parseTest(
|
||||
path/filename & ".ssz_snappy",
|
||||
SSZ, phase0.SignedBeaconBlock
|
||||
)
|
||||
result.add Operation(kind: opOnBlock,
|
||||
blk: ForkedSignedBeaconBlock.init(blk))
|
||||
of BeaconBlockFork.Altair:
|
||||
let blk = parseTest(
|
||||
path/filename & ".ssz_snappy",
|
||||
SSZ, altair.SignedBeaconBlock
|
||||
)
|
||||
result.add Operation(kind: opOnBlock,
|
||||
blk: ForkedSignedBeaconBlock.init(blk))
|
||||
of BeaconBlockFork.Merge:
|
||||
let blk = parseTest(
|
||||
path/filename & ".ssz_snappy",
|
||||
SSZ, merge.SignedBeaconBlock
|
||||
)
|
||||
result.add Operation(kind: opOnBlock,
|
||||
blk: ForkedSignedBeaconBlock.init(blk))
|
||||
elif step.hasKey"attestation":
|
||||
let filename = step["attestation"].getStr()
|
||||
let att = parseTest(
|
||||
path/filename & ".ssz_snappy",
|
||||
SSZ, Attestation
|
||||
)
|
||||
result.add Operation(kind: opOnAttestation,
|
||||
att: att)
|
||||
elif step.hasKey"checks":
|
||||
result.add Operation(kind: opChecks,
|
||||
checks: step["checks"])
|
||||
else:
|
||||
doAssert false, "Unreachable: " & $step
|
||||
|
||||
if step.hasKey"valid":
|
||||
doAssert step.len == 2
|
||||
result[^1].valid = step["valid"].getBool()
|
||||
elif not step.hasKey"checks":
|
||||
doAssert step.len == 1
|
||||
result[^1].valid = true
|
||||
|
||||
proc stepOnBlock(
|
||||
dag: ChainDagRef,
|
||||
fkChoice: ref ForkChoice,
|
||||
quarantine: QuarantineRef,
|
||||
state: var StateData,
|
||||
stateCache: var StateCache,
|
||||
signedBlock: phase0.SignedBeaconBlock | altair.SignedBeaconBlock | merge.SignedBeaconBlock,
|
||||
time: Slot): Result[BlockRef, (ValidationResult, BlockError)] =
|
||||
# 1. Move state to proper slot.
|
||||
dag.updateStateData(
|
||||
state,
|
||||
dag.head.atSlot(time),
|
||||
save = false,
|
||||
stateCache
|
||||
)
|
||||
|
||||
# 2. Add block to DAG
|
||||
when signedBlock is phase0.SignedBeaconBlock:
|
||||
type TrustedBlock = phase0.TrustedSignedBeaconBlock
|
||||
elif signedBlock is altair.SignedBeaconBlock:
|
||||
type TrustedBlock = altair.TrustedSignedBeaconBlock
|
||||
else:
|
||||
type TrustedBlock = merge.TrustedSignedBeaconBlock
|
||||
|
||||
let blockAdded = dag.addRawBlock(quarantine, signedBlock) do (
|
||||
blckRef: BlockRef, signedBlock: TrustedBlock, epochRef: EpochRef
|
||||
):
|
||||
|
||||
# 3. Update fork choice if valid
|
||||
let status = fkChoice[].process_block(
|
||||
dag,
|
||||
epochRef,
|
||||
blckRef,
|
||||
signedBlock.message,
|
||||
time
|
||||
)
|
||||
doAssert status.isOk()
|
||||
|
||||
return blockAdded
|
||||
|
||||
proc stepOnAttestation(
|
||||
dag: ChainDagRef,
|
||||
fkChoice: ref ForkChoice,
|
||||
att: Attestation,
|
||||
time: Slot): FcResult[void] =
|
||||
|
||||
let epochRef = dag.getEpochRef(dag.head, time.compute_epoch_at_slot())
|
||||
let attesters = epochRef.get_attesting_indices(att.data, att.aggregation_bits)
|
||||
|
||||
let status = fkChoice[].on_attestation(
|
||||
dag,
|
||||
att.data.slot, att.data.beacon_block_root, attesters,
|
||||
time
|
||||
)
|
||||
|
||||
status
|
||||
|
||||
proc stepChecks(
|
||||
checks: JsonNode,
|
||||
dag: ChainDagRef,
|
||||
fkChoice: ref ForkChoice,
|
||||
time: Slot
|
||||
) =
|
||||
doAssert checks.len >= 1, "No checks found"
|
||||
for check, val in checks:
|
||||
if check == "time":
|
||||
doAssert time == Slot(val.getInt())
|
||||
doAssert fkChoice.checkpoints.time == time
|
||||
elif check == "head":
|
||||
let headRoot = fkChoice[].get_head(dag, time).get()
|
||||
let headRef = dag.getRef(headRoot)
|
||||
doAssert headRef.slot == Slot(val["slot"].getInt())
|
||||
doAssert headRef.root == Eth2Digest.fromHex(val["root"].getStr())
|
||||
elif check == "justified_checkpoint":
|
||||
let checkpointRoot = fkChoice.checkpoints.justified.checkpoint.root
|
||||
let checkpointEpoch = fkChoice.checkpoints.justified.checkpoint.epoch
|
||||
doAssert checkpointEpoch == Epoch(val["epoch"].getInt())
|
||||
doAssert checkpointRoot == Eth2Digest.fromHex(val["root"].getStr())
|
||||
elif check == "justified_checkpoint_root": # undocumented check
|
||||
let checkpointRoot = fkChoice.checkpoints.justified.checkpoint.root
|
||||
doAssert checkpointRoot == Eth2Digest.fromHex(val.getStr())
|
||||
elif check == "finalized_checkpoint":
|
||||
let checkpointRoot = fkChoice.checkpoints.finalized.root
|
||||
let checkpointEpoch = fkChoice.checkpoints.finalized.epoch
|
||||
doAssert checkpointEpoch == Epoch(val["epoch"].getInt())
|
||||
doAssert checkpointRoot == Eth2Digest.fromHex(val["root"].getStr())
|
||||
elif check == "best_justified_checkpoint":
|
||||
let checkpointRoot = fkChoice.checkpoints.best_justified.root
|
||||
let checkpointEpoch = fkChoice.checkpoints.best_justified.epoch
|
||||
doAssert checkpointEpoch == Epoch(val["epoch"].getInt())
|
||||
doAssert checkpointRoot == Eth2Digest.fromHex(val["root"].getStr())
|
||||
elif check == "genesis_time":
|
||||
# The fork choice is pruned regularly
|
||||
# and does not store the genesis time,
|
||||
# hence we check the DAG
|
||||
doAssert dag.genesis.slot == Slot(val.getInt())
|
||||
else:
|
||||
doAssert false, "Unsupported check '" & $check & "'"
|
||||
|
||||
proc runTest(path: string, fork: BeaconBlockFork) =
|
||||
let db = BeaconChainDB.new("", inMemory = true)
|
||||
defer:
|
||||
db.close()
|
||||
|
||||
var stores = case fork
|
||||
of BeaconBlockFork.Phase0:
|
||||
initialLoad(
|
||||
path, db,
|
||||
phase0.BeaconState, phase0.BeaconBlock
|
||||
)
|
||||
else:
|
||||
doAssert false, "Unsupported fork: " & $fork
|
||||
(ChainDAGRef(), (ref ForkChoice)())
|
||||
# of BeaconBlockFork.Altair:
|
||||
# initialLoad(
|
||||
# path, db,
|
||||
# # The tests always use phase 0 block for anchor - https://github.com/ethereum/eth2.0-specs/pull/2323
|
||||
# # TODO: support altair genesis state
|
||||
# altair.BeaconState, phase0.BeaconBlock
|
||||
# )
|
||||
# of BeaconBlockFork.Merge:
|
||||
# initialLoad(
|
||||
# path, db,
|
||||
# # The tests always use phase 0 block for anchor - https://github.com/ethereum/eth2.0-specs/pull/2323
|
||||
# # TODO: support merge genesis state
|
||||
# merge.BeaconState, phase0.BeaconBlock
|
||||
# )
|
||||
|
||||
let taskpool = Taskpool.new(numThreads = 1)
|
||||
let quarantine = QuarantineRef.init(keys.newRng(), taskpool)
|
||||
|
||||
let steps = loadOps(path, fork)
|
||||
var time = stores.fkChoice.checkpoints.time
|
||||
|
||||
let state = newClone(stores.dag.headState)
|
||||
var stateCache = StateCache()
|
||||
|
||||
for step in steps:
|
||||
case step.kind
|
||||
of opOnTick:
|
||||
time = Slot(step.tick)
|
||||
of opOnBlock:
|
||||
withBlck(step.blk):
|
||||
let status = stepOnBlock(
|
||||
stores.dag, stores.fkChoice,
|
||||
quarantine,
|
||||
state[], stateCache,
|
||||
blck,
|
||||
time)
|
||||
doAssert status.isOk == step.valid
|
||||
of opOnAttestation:
|
||||
let status = stepOnAttestation(
|
||||
stores.dag, stores.fkChoice,
|
||||
step.att, time)
|
||||
doAssert status.isOk == step.valid
|
||||
of opChecks:
|
||||
stepChecks(step.checks, stores.dag, stores.fkChoice, time)
|
||||
else:
|
||||
doAssert false, "Unsupported"
|
||||
|
||||
suite "Ethereum Foundation - ForkChoice" & preset():
|
||||
const SKIP = [
|
||||
# protoArray can handle blocks in the future gracefully
|
||||
# spec: https://github.com/ethereum/consensus-specs/blame/v1.1.3/specs/phase0/fork-choice.md#L349
|
||||
# test: tests/fork_choice/scenarios/no_votes.nim
|
||||
# "Ensure the head is still 4 whilst the justified epoch is 0."
|
||||
"on_block_future_block",
|
||||
]
|
||||
|
||||
for fork in [BeaconBlockFork.Phase0]: # TODO: init ChainDAG from Merge/Altair
|
||||
let forkStr = toLowerAscii($fork)
|
||||
for testKind in ["get_head", "on_block"]:
|
||||
let basePath = SszTestsDir/const_preset/forkStr/"fork_choice"/testKind/"pyspec_tests"
|
||||
for kind, path in walkDir(basePath, relative = true, checkDir = true):
|
||||
test "ForkChoice - " & const_preset/forkStr/"fork_choice"/testKind/"pyspec_tests"/path:
|
||||
if const_preset == "minimal":
|
||||
# TODO: Minimal tests have long paths issues on Windows
|
||||
# and some are testing implementation details:
|
||||
# - assertion that input block is not in the future
|
||||
# - block slot is later than finalized slot
|
||||
# - ...
|
||||
# that ProtoArray handles gracefully
|
||||
skip()
|
||||
elif path in SKIP:
|
||||
skip()
|
||||
else:
|
||||
runTest(basePath/path, fork)
|
||||
|
||||
|
|
@ -41,16 +41,15 @@ type
|
|||
# variant specific fields
|
||||
case kind*: OpKind
|
||||
of FindHead, InvalidFindHead:
|
||||
justified_epoch*: Epoch
|
||||
justified_root*: Eth2Digest
|
||||
finalized_epoch*: Epoch
|
||||
justified_checkpoint*: Checkpoint
|
||||
finalized_checkpoint*: Checkpoint
|
||||
justified_state_balances*: seq[Gwei]
|
||||
expected_head*: Eth2Digest
|
||||
of ProcessBlock:
|
||||
root*: Eth2Digest
|
||||
parent_root*: Eth2Digest
|
||||
blk_justified_epoch*: Epoch
|
||||
blk_finalized_epoch*: Epoch
|
||||
blk_justified_checkpoint*: Checkpoint
|
||||
blk_finalized_checkpoint*: Checkpoint
|
||||
of ProcessAttestation:
|
||||
validator_index*: ValidatorIndex
|
||||
block_root*: Eth2Digest
|
||||
|
@ -67,27 +66,26 @@ func apply(ctx: var ForkChoiceBackend, id: int, op: Operation) =
|
|||
case op.kind
|
||||
of FindHead, InvalidFindHead:
|
||||
let r = ctx.find_head(
|
||||
op.justified_epoch,
|
||||
op.justified_root,
|
||||
op.finalized_epoch,
|
||||
op.justified_checkpoint,
|
||||
op.finalized_checkpoint,
|
||||
op.justified_state_balances
|
||||
)
|
||||
if op.kind == FindHead:
|
||||
doAssert r.isOk(), &"find_head (op #{id}) returned an error: {r.error}"
|
||||
doAssert r.get() == op.expected_head, &"find_head (op #{id}) returned an incorrect result: {r.get()} (expected: {op.expected_head})"
|
||||
debugEcho " Found expected head: 0x", op.expected_head, " from justified checkpoint(epoch: ", op.justified_epoch, ", root: 0x", op.justified_root, ")"
|
||||
doAssert r.get() == op.expected_head, &"find_head (op #{id}) returned an incorrect result: {r.get()} (expected: {op.expected_head}, from justified checkpoint: {op.justified_checkpoint}, finalized checkpoint: {op.finalized_checkpoint})"
|
||||
debugEcho &" Found expected head: 0x{op.expected_head} from justified checkpoint {op.justified_checkpoint}, finalized checkpoint {op.finalized_checkpoint}"
|
||||
else:
|
||||
doAssert r.isErr(), "find_head was unexpectedly successful"
|
||||
debugEcho " Detected an expected invalid head"
|
||||
doAssert r.isErr(), &"invalid_find_head (op #{id}) was unexpectedly successful, head {op.expected_head} from justified checkpoint {op.justified_checkpoint}, finalized checkpoint {op.finalized_checkpoint}"
|
||||
debugEcho &" Detected an expected invalid head from justified checkpoint {op.justified_checkpoint}, finalized checkpoint {op.finalized_checkpoint}"
|
||||
of ProcessBlock:
|
||||
let r = ctx.process_block(
|
||||
block_root = op.root,
|
||||
parent_root = op.parent_root,
|
||||
justified_epoch = op.blk_justified_epoch,
|
||||
finalized_epoch = op.blk_finalized_epoch
|
||||
justified_checkpoint = op.blk_justified_checkpoint,
|
||||
finalized_checkpoint = op.blk_finalized_checkpoint
|
||||
)
|
||||
doAssert r.isOk(), &"process_block (op #{id}) returned an error: {r.error}"
|
||||
debugEcho " Processed block 0x", op.root, " with parent 0x", op.parent_root, " and justified epoch ", op.blk_justified_epoch
|
||||
debugEcho " Processed block 0x", op.root, " with parent 0x", op.parent_root, " and justified checkpoint ", op.blk_justified_checkpoint
|
||||
of ProcessAttestation:
|
||||
ctx.process_attestation(
|
||||
validator_index = op.validator_index,
|
||||
|
|
|
@ -13,9 +13,8 @@ func setup_finality_01(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
|
||||
# Initialize the fork choice context
|
||||
result.fork_choice = ForkChoiceBackend.init(
|
||||
justified_epoch = Epoch(1),
|
||||
finalized_epoch = Epoch(1),
|
||||
finalized_root = GenesisRoot
|
||||
justifiedCheckpoint = Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
finalizedCheckpoint = Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
|
||||
# ----------------------------------
|
||||
|
@ -23,9 +22,8 @@ func setup_finality_01(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Head should be genesis
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: GenesisRoot
|
||||
)
|
||||
|
@ -43,22 +41,22 @@ func setup_finality_01(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(1),
|
||||
parent_root: GenesisRoot,
|
||||
blk_justified_epoch: Epoch(0),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(2),
|
||||
parent_root: fakeHash(1),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(1), epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(3),
|
||||
parent_root: fakeHash(2),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(2), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: fakeHash(1), epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Ensure that with justified epoch 0 we find 3
|
||||
|
@ -72,9 +70,8 @@ func setup_finality_01(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# 3 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(0),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(3)
|
||||
)
|
||||
|
@ -90,9 +87,8 @@ func setup_finality_01(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# 3 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: fakeHash(2),
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakeHash(1), epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -108,9 +104,8 @@ func setup_finality_01(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# 3 <- start + head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(3),
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: fakeHash(2), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(1), epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(3)
|
||||
)
|
||||
|
|
|
@ -13,9 +13,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
|
||||
# Initialize the fork choice context
|
||||
result.fork_choice = ForkChoiceBackend.init(
|
||||
justified_epoch = Epoch(1),
|
||||
finalized_epoch = Epoch(1),
|
||||
finalized_root = GenesisRoot
|
||||
justifiedCheckpoint = Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalizedCheckpoint = Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# ----------------------------------
|
||||
|
@ -23,9 +22,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Head should be genesis
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: GenesisRoot
|
||||
)
|
||||
|
@ -49,36 +47,36 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(1),
|
||||
parent_root: GenesisRoot,
|
||||
blk_justified_epoch: Epoch(0),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(3),
|
||||
parent_root: fakeHash(1),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(1), epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(5),
|
||||
parent_root: fakeHash(3),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(1), epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(7),
|
||||
parent_root: fakeHash(5),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(1), epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(9),
|
||||
parent_root: fakeHash(7),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakehash(3), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
|
||||
# Build the following tree.
|
||||
|
@ -100,36 +98,36 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(2),
|
||||
parent_root: GenesisRoot,
|
||||
blk_justified_epoch: Epoch(0),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(4),
|
||||
parent_root: fakeHash(2),
|
||||
blk_justified_epoch: Epoch(0),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(6),
|
||||
parent_root: fakeHash(4),
|
||||
blk_justified_epoch: Epoch(0),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(8),
|
||||
parent_root: fakeHash(6),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakehash(2), epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(10),
|
||||
parent_root: fakeHash(8),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(0)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakehash(4), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0))
|
||||
)
|
||||
|
||||
# Ensure that if we start at 0 we find 10 (just: 0, fin: 0).
|
||||
|
@ -147,9 +145,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# 9 10 <-- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(0),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(10)
|
||||
)
|
||||
|
@ -157,9 +154,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Same with justified_epoch 2
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(4), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(10)
|
||||
)
|
||||
|
@ -167,9 +163,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Justified epoch 3 is invalid
|
||||
result.ops.add Operation(
|
||||
kind: InvalidFindHead,
|
||||
justified_epoch: Epoch(3), # <--- Wrong epoch
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(4), epoch: Epoch(3)), # <--- Wrong epoch
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances
|
||||
)
|
||||
|
||||
|
@ -208,9 +203,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# head -> 9 10
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(0),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -218,9 +212,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Same with justified_epoch 2
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(3), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -228,9 +221,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Justified epoch 3 is invalid
|
||||
result.ops.add Operation(
|
||||
kind: InvalidFindHead,
|
||||
justified_epoch: Epoch(3), # <--- Wrong epoch
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(3)), # <--- Wrong epoch
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances
|
||||
)
|
||||
|
||||
|
@ -269,9 +261,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# 9 10 <-- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(0),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(10)
|
||||
)
|
||||
|
@ -279,9 +270,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Same with justified_epoch 2
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakeHash(4), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(10)
|
||||
)
|
||||
|
@ -289,9 +279,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Justified epoch 3 is invalid
|
||||
result.ops.add Operation(
|
||||
kind: InvalidFindHead,
|
||||
justified_epoch: Epoch(3), # <--- Wrong epoch
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(3)), # <--- Wrong epoch
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances
|
||||
)
|
||||
|
||||
|
@ -310,9 +299,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# head -> 9 10
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(0),
|
||||
justified_root: fakeHash(1),
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(1), epoch: Epoch(0)), # <- in production the root/epoch mismatch isn't used.
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -320,9 +308,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Same with justified_epoch 2
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(1),
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(3), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -330,9 +317,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Justified epoch 3 is invalid
|
||||
result.ops.add Operation(
|
||||
kind: InvalidFindHead,
|
||||
justified_epoch: Epoch(3), # <--- Wrong epoch
|
||||
justified_root: fakeHash(1),
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(5), epoch: Epoch(3)), # <--- Wrong epoch
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances
|
||||
)
|
||||
|
||||
|
@ -351,9 +337,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# 9 10 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(0),
|
||||
justified_root: fakeHash(2),
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(2), epoch: Epoch(0)), # In production this can't happen
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(10)
|
||||
)
|
||||
|
@ -361,9 +346,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Same with justified_epoch 2
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(2),
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(4), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(10)
|
||||
)
|
||||
|
@ -371,9 +355,8 @@ func setup_finality_02(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operati
|
|||
# Justified epoch 3 is invalid
|
||||
result.ops.add Operation(
|
||||
kind: InvalidFindHead,
|
||||
justified_epoch: Epoch(3), # <--- Wrong epoch
|
||||
justified_root: fakeHash(2),
|
||||
finalized_epoch: Epoch(0),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(4), epoch: Epoch(3)), # <--- Wrong epoch
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(0)),
|
||||
justified_state_balances: balances
|
||||
)
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
let GenesisRoot = fakeHash(0)
|
||||
|
||||
# Initialize the fork choice context
|
||||
# We start with epoch 0 fully finalized to avoid epoch 0 special cases.
|
||||
result.fork_choice = ForkChoiceBackend.init(
|
||||
justified_epoch = Epoch(1),
|
||||
finalized_epoch = Epoch(1),
|
||||
finalized_root = GenesisRoot
|
||||
justifiedCheckpoint = Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalizedCheckpoint = Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# ----------------------------------
|
||||
|
@ -23,9 +23,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# Head should be genesis
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: GenesisRoot
|
||||
)
|
||||
|
@ -39,8 +38,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(2),
|
||||
parent_root: GenesisRoot,
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Head should be 2
|
||||
|
@ -50,9 +49,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# 2 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -66,8 +64,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(1),
|
||||
parent_root: GenesisRoot,
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Head is still 2 due to tiebreaker as fakeHash(2) (0xD8...) > fakeHash(1) (0x7C...)
|
||||
|
@ -77,9 +75,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# head-> 2 1
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -95,8 +92,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(3),
|
||||
parent_root: fakeHash(1),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Head is still 2
|
||||
|
@ -108,9 +105,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# 3
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -126,8 +122,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(4),
|
||||
parent_root: fakeHash(2),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Check that head is 4
|
||||
|
@ -139,9 +135,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# head-> 4 3
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(4)
|
||||
)
|
||||
|
@ -159,8 +154,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(5),
|
||||
parent_root: fakeHash(4),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Ensure the head is still 4 whilst the justified epoch is 0.
|
||||
|
@ -174,9 +169,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# 5
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(4)
|
||||
)
|
||||
|
@ -188,12 +182,11 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# | |
|
||||
# 4 3
|
||||
# |
|
||||
# 5 <- starting from 5 with justified epoch 1 should error.
|
||||
# 5 <- starting from 5 with justified epoch 0 should error.
|
||||
result.ops.add Operation(
|
||||
kind: InvalidFindHead,
|
||||
justified_epoch: Epoch(1), # <--- Wrong epoch
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances
|
||||
)
|
||||
|
||||
|
@ -204,12 +197,11 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# | |
|
||||
# 4 3
|
||||
# |
|
||||
# 5 <- head + justified
|
||||
# 5 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(5)
|
||||
)
|
||||
|
@ -229,8 +221,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(6),
|
||||
parent_root: fakeHash(5),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Ensure 6 is the head
|
||||
|
@ -245,9 +237,8 @@ func setup_no_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]
|
|||
# 6 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(6)
|
||||
)
|
||||
|
|
|
@ -12,10 +12,10 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
let GenesisRoot = fakeHash(0)
|
||||
|
||||
# Initialize the fork choice context
|
||||
# We start with epoch 0 fully finalized to avoid epoch 0 special cases.
|
||||
result.fork_choice = ForkChoiceBackend.init(
|
||||
justified_epoch = Epoch(1),
|
||||
finalized_epoch = Epoch(1),
|
||||
finalized_root = GenesisRoot
|
||||
justifiedCheckpoint = Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalizedCheckpoint = Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# ----------------------------------
|
||||
|
@ -23,9 +23,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# Head should be genesis
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: GenesisRoot
|
||||
)
|
||||
|
@ -39,8 +38,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(2),
|
||||
parent_root: GenesisRoot,
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Head should be 2
|
||||
|
@ -50,9 +49,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# 2 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -66,8 +64,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(1),
|
||||
parent_root: GenesisRoot,
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Head is still 2 due to tiebreaker as fakeHash(2) (0xD8...) > fakeHash(1) (0x7C...)
|
||||
|
@ -77,9 +75,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# head-> 2 1
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -103,9 +100,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# 2 1 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(1)
|
||||
)
|
||||
|
@ -129,9 +125,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# head-> 2 1
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -147,8 +142,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(3),
|
||||
parent_root: fakeHash(1),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Head is still 2
|
||||
|
@ -158,9 +153,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# head-> 2 1
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -186,9 +180,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# head-> 2 1
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(2)
|
||||
)
|
||||
|
@ -217,9 +210,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# 3 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(3)
|
||||
)
|
||||
|
@ -237,8 +229,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(4),
|
||||
parent_root: fakeHash(3),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Head is now 4
|
||||
|
@ -252,9 +244,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# 4 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(4)
|
||||
)
|
||||
|
@ -274,8 +265,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(5),
|
||||
parent_root: fakeHash(4),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(2)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2))
|
||||
)
|
||||
|
||||
# Ensure that 5 is filtered out and the head stays at 4.
|
||||
|
@ -291,9 +282,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# 5
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(4)
|
||||
)
|
||||
|
@ -313,8 +303,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(6),
|
||||
parent_root: fakeHash(4),
|
||||
blk_justified_epoch: Epoch(1),
|
||||
blk_finalized_epoch: Epoch(1)
|
||||
blk_justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Move both votes to 5.
|
||||
|
@ -363,22 +353,24 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(7),
|
||||
parent_root: fakeHash(5),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(2)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(8),
|
||||
parent_root: fakeHash(7),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(2)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1))
|
||||
)
|
||||
|
||||
# Finalizes 5
|
||||
result.ops.add Operation(
|
||||
kind: ProcessBlock,
|
||||
root: fakeHash(9),
|
||||
parent_root: fakeHash(8),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(2)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2))
|
||||
)
|
||||
|
||||
# Ensure that 6 is the head, even though 5 has all the votes. This is testing to ensure
|
||||
|
@ -401,9 +393,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# 9
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(1),
|
||||
justified_root: GenesisRoot,
|
||||
finalized_epoch: Epoch(1),
|
||||
justified_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
finalized_checkpoint: Checkpoint(root: GenesisRoot, epoch: Epoch(1)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(6)
|
||||
)
|
||||
|
@ -430,9 +421,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# head-> 9
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -469,14 +459,13 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# Head should still be 9
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
||||
# Add block 10
|
||||
# Add block 10 (also finalizes 5)
|
||||
# 0
|
||||
# / \
|
||||
# 2 1
|
||||
|
@ -496,16 +485,15 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(10),
|
||||
parent_root: fakeHash(8),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(2)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2))
|
||||
)
|
||||
|
||||
# Head should still be 9
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -561,9 +549,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# 9 10 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(10)
|
||||
)
|
||||
|
@ -579,9 +566,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# head -> 9 10
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -597,9 +583,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# 9 10 <- head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(10)
|
||||
)
|
||||
|
@ -615,9 +600,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# head -> 9 10
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakehash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -652,9 +636,8 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
# Prune shouldn't have changed the head
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(9)
|
||||
)
|
||||
|
@ -674,16 +657,15 @@ func setup_votes(): tuple[fork_choice: ForkChoiceBackend, ops: seq[Operation]] =
|
|||
kind: ProcessBlock,
|
||||
root: fakeHash(11),
|
||||
parent_root: fakeHash(9),
|
||||
blk_justified_epoch: Epoch(2),
|
||||
blk_finalized_epoch: Epoch(2)
|
||||
blk_justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
blk_finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2))
|
||||
)
|
||||
|
||||
# Head is now 11
|
||||
result.ops.add Operation(
|
||||
kind: FindHead,
|
||||
justified_epoch: Epoch(2),
|
||||
justified_root: fakeHash(5),
|
||||
finalized_epoch: Epoch(2),
|
||||
justified_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
finalized_checkpoint: Checkpoint(root: fakeHash(5), epoch: Epoch(2)),
|
||||
justified_state_balances: balances,
|
||||
expected_head: fakeHash(11)
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue