generalize `commonAncestor` function to `BlockId` (#5192)
To enable additional use cases, e.g., `/states/###/randao` beacon API, `ShufflingRef` acceleration logic needs to be able to operate on parts of the DAG that do not have `BlockRef`. Changing `commonAncestor` to act on `BlockId` instead of `BlockRef` is a step toward that and also simplifies the logic some more.
This commit is contained in:
parent
3a818ecb93
commit
f98c33ad03
|
@ -1,5 +1,10 @@
|
|||
AllTests-mainnet
|
||||
===
|
||||
## Ancestry
|
||||
```diff
|
||||
+ ancestorSlot OK
|
||||
```
|
||||
OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||
## Attestation pool processing [Preset: mainnet]
|
||||
```diff
|
||||
+ Attestation from different branch [Preset: mainnet] OK
|
||||
|
@ -100,11 +105,10 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
|||
OK: 2/2 Fail: 0/2 Skip: 0/2
|
||||
## BlockRef and helpers
|
||||
```diff
|
||||
+ commonAncestor sanity OK
|
||||
+ get_ancestor sanity OK
|
||||
+ isAncestorOf sanity OK
|
||||
```
|
||||
OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||
OK: 2/2 Fail: 0/2 Skip: 0/2
|
||||
## BlockSlot and helpers
|
||||
```diff
|
||||
+ atSlot sanity OK
|
||||
|
|
|
@ -155,34 +155,6 @@ func get_ancestor*(blck: BlockRef, slot: Slot,
|
|||
|
||||
blck = blck.parent
|
||||
|
||||
func commonAncestor*(a, b: BlockRef, lowSlot: Slot): Opt[BlockRef] =
|
||||
## Return the common ancestor with highest slot of two non-nil `BlockRef`,
|
||||
## limited by `lowSlot` (`err` if exceeded).
|
||||
doAssert a != nil
|
||||
doAssert b != nil
|
||||
if a.slot < lowSlot or b.slot < lowSlot:
|
||||
return err()
|
||||
if a.parent == nil:
|
||||
return ok a # All `BlockRef` lead to `finalizedHead`
|
||||
if b.parent == nil:
|
||||
return ok b # All `BlockRef` lead to `finalizedHead`
|
||||
|
||||
var
|
||||
aa = a
|
||||
bb = b
|
||||
while aa != bb:
|
||||
if aa.slot >= bb.slot:
|
||||
aa = aa.parent
|
||||
doAssert aa != nil, "All `BlockRef` lead to `finalizedHead`"
|
||||
if aa.slot < lowSlot:
|
||||
return err()
|
||||
else:
|
||||
bb = bb.parent
|
||||
doAssert bb != nil, "All `BlockRef` lead to `finalizedHead`"
|
||||
if bb.slot < lowSlot:
|
||||
return err()
|
||||
ok aa
|
||||
|
||||
func atSlot*(blck: BlockRef, slot: Slot): BlockSlot =
|
||||
## Return a BlockSlot at a given slot, with the block set to the closest block
|
||||
## available. If slot comes from before the block, a suitable block ancestor
|
||||
|
|
|
@ -1330,7 +1330,45 @@ proc getFinalizedEpochRef*(dag: ChainDAGRef): EpochRef =
|
|||
dag.finalizedHead.blck, dag.finalizedHead.slot.epoch, false).expect(
|
||||
"getEpochRef for finalized head should always succeed")
|
||||
|
||||
func ancestorSlotForAttesterShuffling*(
|
||||
proc getBlockIdAtSlot(
|
||||
dag: ChainDAGRef, state: ForkyHashedBeaconState, slot: Slot): Opt[BlockId] =
|
||||
if slot >= state.data.slot:
|
||||
Opt.some state.latest_block_id
|
||||
elif state.data.slot <= slot + SLOTS_PER_HISTORICAL_ROOT:
|
||||
dag.getBlockId(state.data.get_block_root_at_slot(slot))
|
||||
else:
|
||||
Opt.none(BlockId)
|
||||
|
||||
proc ancestorSlot*(
|
||||
dag: ChainDAGRef, state: ForkyHashedBeaconState, bid: BlockId,
|
||||
lowSlot: Slot): Opt[Slot] =
|
||||
## Return common ancestor slot of `bid` and `state`, if at least `lowSlot`.
|
||||
## Return `none` if no common ancestor is found with slot >= `lowSlot`.
|
||||
if state.data.slot < lowSlot or bid.slot < lowSlot:
|
||||
return Opt.none(Slot)
|
||||
|
||||
var stateBid = ? dag.getBlockIdAtSlot(state, bid.slot)
|
||||
if stateBid.slot < lowSlot:
|
||||
return Opt.none(Slot)
|
||||
|
||||
var blockBid = (? dag.atSlot(bid, stateBid.slot)).bid
|
||||
if blockBid.slot < lowSlot:
|
||||
return Opt.none(Slot)
|
||||
|
||||
while stateBid != blockBid:
|
||||
if stateBid.slot >= blockBid.slot:
|
||||
stateBid = ? dag.getBlockIdAtSlot(
|
||||
state, min(blockBid.slot, stateBid.slot - 1))
|
||||
if stateBid.slot < lowSlot:
|
||||
return Opt.none(Slot)
|
||||
else:
|
||||
blockBid = ? dag.parent(blockBid)
|
||||
if blockBid.slot < lowSlot:
|
||||
return Opt.none(Slot)
|
||||
|
||||
Opt.some stateBid.slot
|
||||
|
||||
proc ancestorSlotForAttesterShuffling*(
|
||||
dag: ChainDAGRef, state: ForkyHashedBeaconState,
|
||||
blck: BlockRef, epoch: Epoch): Opt[Slot] =
|
||||
## Return slot of `blck` ancestor to which `state` can be rewinded
|
||||
|
@ -1342,48 +1380,8 @@ func ancestorSlotForAttesterShuffling*(
|
|||
const numDelayEpochs = compute_activation_exit_epoch(GENESIS_EPOCH).uint64
|
||||
let
|
||||
lowEpoch = max(epoch, (numDelayEpochs - 1).Epoch) - (numDelayEpochs - 1)
|
||||
lowSlot = lowEpoch.start_slot
|
||||
if state.data.slot < lowSlot or blck.slot < lowSlot:
|
||||
return err()
|
||||
|
||||
# Check that state is related to the information stored in the DAG,
|
||||
# and determine the corresponding `BlockRef`, or `finalizedHead` if finalized
|
||||
let
|
||||
stateBid = state.latest_block_id
|
||||
stateBlck =
|
||||
if dag.finalizedHead.blck == nil:
|
||||
return err()
|
||||
elif stateBid.slot > dag.finalizedHead.blck.slot:
|
||||
? dag.getBlockRef(stateBid.root)
|
||||
elif stateBid.slot == dag.finalizedHead.blck.slot:
|
||||
if stateBid.root != dag.finalizedHead.blck.root:
|
||||
return err()
|
||||
dag.finalizedHead.blck
|
||||
else:
|
||||
let bsi = ? dag.getBlockIdAtSlot(stateBid.slot)
|
||||
if bsi.bid != stateBid:
|
||||
return err()
|
||||
dag.finalizedHead.blck
|
||||
|
||||
# Check that history up to `lowSlot` is included in `state`,
|
||||
# otherwise `get_active_validator_indices` may still change
|
||||
if lowSlot <= dag.finalizedHead.blck.slot:
|
||||
let
|
||||
bsi = ? dag.getBlockIdAtSlot(lowSlot)
|
||||
stateLowBlockRoot =
|
||||
if state.data.slot == lowSlot:
|
||||
stateBid.root
|
||||
else:
|
||||
state.data.get_block_root_at_slot(lowSlot)
|
||||
if stateLowBlockRoot != bsi.bid.root:
|
||||
return err()
|
||||
|
||||
# Compute ancestor slot for starting RANDAO recovery
|
||||
let
|
||||
ancestorBlck = ? commonAncestor(blck, stateBlck, lowSlot)
|
||||
dependentSlot = epoch.attester_dependent_slot
|
||||
doAssert dependentSlot >= lowSlot
|
||||
ok min(min(stateBid.slot, ancestorBlck.slot), dependentSlot)
|
||||
ancestorSlot = ? dag.ancestorSlot(state, blck.bid, lowEpoch.start_slot)
|
||||
Opt.some min(ancestorSlot, epoch.attester_dependent_slot)
|
||||
|
||||
type AttesterRandaoMix = tuple[dependentBid: BlockId, mix: Eth2Digest]
|
||||
|
||||
|
|
|
@ -51,260 +51,6 @@ suite "BlockRef and helpers":
|
|||
s4.get_ancestor(Slot(3)) == s2
|
||||
s4.get_ancestor(Slot(4)) == s4
|
||||
|
||||
test "commonAncestor sanity":
|
||||
# s0
|
||||
# / \
|
||||
# s1 s3
|
||||
# / \
|
||||
# s2 s6
|
||||
# / \ \
|
||||
# s4 s5 s7
|
||||
# \
|
||||
# s8
|
||||
# \
|
||||
# s9
|
||||
let
|
||||
s0 = BlockRef(bid: BlockId(slot: Slot(0)))
|
||||
s1 = BlockRef(bid: BlockId(slot: Slot(1)), parent: s0)
|
||||
s2 = BlockRef(bid: BlockId(slot: Slot(2)), parent: s1)
|
||||
s3 = BlockRef(bid: BlockId(slot: Slot(3)), parent: s0)
|
||||
s4 = BlockRef(bid: BlockId(slot: Slot(4)), parent: s2)
|
||||
s5 = BlockRef(bid: BlockId(slot: Slot(5)), parent: s2)
|
||||
s6 = BlockRef(bid: BlockId(slot: Slot(6)), parent: s3)
|
||||
s7 = BlockRef(bid: BlockId(slot: Slot(7)), parent: s6)
|
||||
s8 = BlockRef(bid: BlockId(slot: Slot(8)), parent: s4)
|
||||
s9 = BlockRef(bid: BlockId(slot: Slot(9)), parent: s8)
|
||||
|
||||
check:
|
||||
commonAncestor(s0, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s1, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s2, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s3, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s4, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s5, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s6, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s7, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s8, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s0, s9, Slot(0)) == Opt.some(s0)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s0, b, Slot(1)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s1, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s1, s1, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s1, s2, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s1, s3, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s1, s4, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s1, s5, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s1, s6, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s1, s7, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s1, s8, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s1, s9, Slot(0)) == Opt.some(s1)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check commonAncestor(s1, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s1, b, Slot(2)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s2, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s2, s1, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s2, s2, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s2, s3, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s2, s4, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s2, s5, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s2, s6, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s2, s7, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s2, s8, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s2, s9, Slot(0)) == Opt.some(s2)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check commonAncestor(s2, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check commonAncestor(s2, b, Slot(2)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s2, b, Slot(3)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s3, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s3, s1, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s3, s2, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s3, s3, Slot(0)) == Opt.some(s3)
|
||||
commonAncestor(s3, s4, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s3, s5, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s3, s6, Slot(0)) == Opt.some(s3)
|
||||
commonAncestor(s3, s7, Slot(0)) == Opt.some(s3)
|
||||
commonAncestor(s3, s8, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s3, s9, Slot(0)) == Opt.some(s0)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s3, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s3, b, Slot(2)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s3, b, Slot(3)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s3, b, Slot(4)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s4, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s4, s1, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s4, s2, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s4, s3, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s4, s4, Slot(0)) == Opt.some(s4)
|
||||
commonAncestor(s4, s5, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s4, s6, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s4, s7, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s4, s8, Slot(0)) == Opt.some(s4)
|
||||
commonAncestor(s4, s9, Slot(0)) == Opt.some(s4)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check commonAncestor(s4, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check commonAncestor(s4, b, Slot(2)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check commonAncestor(s4, b, Slot(3)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check commonAncestor(s4, b, Slot(4)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s4, b, Slot(5)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s5, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s5, s1, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s5, s2, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s5, s3, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s5, s4, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s5, s5, Slot(0)) == Opt.some(s5)
|
||||
commonAncestor(s5, s6, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s5, s7, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s5, s8, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s5, s9, Slot(0)) == Opt.some(s2)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check commonAncestor(s5, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check commonAncestor(s5, b, Slot(2)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s6, s7, s8, s9]:
|
||||
check commonAncestor(s5, b, Slot(3)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s6, s7, s8, s9]:
|
||||
check commonAncestor(s5, b, Slot(4)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s6, s7, s8, s9]:
|
||||
check commonAncestor(s5, b, Slot(5)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s5, b, Slot(6)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s6, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s6, s1, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s6, s2, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s6, s3, Slot(0)) == Opt.some(s3)
|
||||
commonAncestor(s6, s4, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s6, s5, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s6, s6, Slot(0)) == Opt.some(s6)
|
||||
commonAncestor(s6, s7, Slot(0)) == Opt.some(s6)
|
||||
commonAncestor(s6, s8, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s6, s9, Slot(0)) == Opt.some(s0)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s6, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s6, b, Slot(2)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s6, b, Slot(3)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check commonAncestor(s6, b, Slot(4)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check commonAncestor(s6, b, Slot(5)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check commonAncestor(s6, b, Slot(6)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s6, b, Slot(7)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s7, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s7, s1, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s7, s2, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s7, s3, Slot(0)) == Opt.some(s3)
|
||||
commonAncestor(s7, s4, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s7, s5, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s7, s6, Slot(0)) == Opt.some(s6)
|
||||
commonAncestor(s7, s7, Slot(0)) == Opt.some(s7)
|
||||
commonAncestor(s7, s8, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s7, s9, Slot(0)) == Opt.some(s0)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s7, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s7, b, Slot(2)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check commonAncestor(s7, b, Slot(3)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check commonAncestor(s7, b, Slot(4)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check commonAncestor(s7, b, Slot(5)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check commonAncestor(s7, b, Slot(6)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s8, s9]:
|
||||
check commonAncestor(s7, b, Slot(7)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s7, b, Slot(8)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s8, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s8, s1, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s8, s2, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s8, s3, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s8, s4, Slot(0)) == Opt.some(s4)
|
||||
commonAncestor(s8, s5, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s8, s6, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s8, s7, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s8, s8, Slot(0)) == Opt.some(s8)
|
||||
commonAncestor(s8, s9, Slot(0)) == Opt.some(s8)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check commonAncestor(s8, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check commonAncestor(s8, b, Slot(2)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check commonAncestor(s8, b, Slot(3)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check commonAncestor(s8, b, Slot(4)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check commonAncestor(s8, b, Slot(5)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check commonAncestor(s8, b, Slot(6)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check commonAncestor(s8, b, Slot(7)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check commonAncestor(s8, b, Slot(8)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s8, b, Slot(9)) == Opt.none(BlockRef)
|
||||
|
||||
check:
|
||||
commonAncestor(s9, s0, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s9, s1, Slot(0)) == Opt.some(s1)
|
||||
commonAncestor(s9, s2, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s9, s3, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s9, s4, Slot(0)) == Opt.some(s4)
|
||||
commonAncestor(s9, s5, Slot(0)) == Opt.some(s2)
|
||||
commonAncestor(s9, s6, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s9, s7, Slot(0)) == Opt.some(s0)
|
||||
commonAncestor(s9, s8, Slot(0)) == Opt.some(s8)
|
||||
commonAncestor(s9, s9, Slot(0)) == Opt.some(s9)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check commonAncestor(s9, b, Slot(1)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check commonAncestor(s9, b, Slot(2)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check commonAncestor(s9, b, Slot(3)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check commonAncestor(s9, b, Slot(4)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check commonAncestor(s9, b, Slot(5)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check commonAncestor(s9, b, Slot(6)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check commonAncestor(s9, b, Slot(7)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check commonAncestor(s9, b, Slot(8)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8]:
|
||||
check commonAncestor(s9, b, Slot(9)) == Opt.none(BlockRef)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check commonAncestor(s9, b, Slot(10)) == Opt.none(BlockRef)
|
||||
|
||||
suite "BlockSlot and helpers":
|
||||
test "atSlot sanity":
|
||||
let
|
||||
|
|
|
@ -1180,6 +1180,295 @@ suite "Pruning":
|
|||
dag.tail.slot == Epoch(EPOCHS_PER_STATE_SNAPSHOT).start_slot - 1
|
||||
not db.containsBlock(blocks[1].root)
|
||||
|
||||
suite "Ancestry":
|
||||
test "ancestorSlot":
|
||||
const numValidators = SLOTS_PER_EPOCH
|
||||
let
|
||||
cfg = defaultRuntimeConfig
|
||||
validatorMonitor = newClone(ValidatorMonitor.init())
|
||||
dag = ChainDAGRef.init(
|
||||
cfg, makeTestDB(numValidators, cfg = cfg),
|
||||
validatorMonitor, {})
|
||||
quarantine = newClone(Quarantine.init())
|
||||
rng = HmacDrbgContext.new()
|
||||
taskpool = Taskpool.new()
|
||||
|
||||
type Node = tuple[blck: BlockRef, state: ref phase0.HashedBeaconState]
|
||||
template bid(n: Node): BlockId = n.blck.bid
|
||||
|
||||
var verifier = BatchVerifier(rng: rng, taskpool: taskpool)
|
||||
proc addBlock(parent: Node, slot: Slot): Node =
|
||||
dag.updateHead(parent.blck, quarantine[], [])
|
||||
|
||||
var
|
||||
cache: StateCache
|
||||
info: ForkedEpochInfo
|
||||
let res = process_slots(cfg, dag.headState, slot, cache, info, flags = {})
|
||||
check res.isOk
|
||||
|
||||
let
|
||||
blck = dag.headState.addTestBlock(cache, nextSlot = false, cfg = cfg)
|
||||
added = block:
|
||||
const nilCallback = OnPhase0BlockAdded(nil)
|
||||
dag.addHeadBlock(verifier, blck.phase0Data, nilCallback)
|
||||
check added.isOk()
|
||||
dag.updateHead(added[], quarantine[], [])
|
||||
(blck: dag.head, state: newClone(dag.headState.phase0Data))
|
||||
|
||||
# s0
|
||||
# / \
|
||||
# s1 s3
|
||||
# / \
|
||||
# s2 s6
|
||||
# / \ \
|
||||
# s4 s5 s7
|
||||
# \
|
||||
# s8
|
||||
# \
|
||||
# s9
|
||||
let
|
||||
sg = (blck: dag.head, state: newClone(dag.headState.phase0Data))
|
||||
s0 = sg.addBlock(Slot(10))
|
||||
s1 = s0.addBlock(Slot(11))
|
||||
s2 = s1.addBlock(Slot(12))
|
||||
s3 = s0.addBlock(Slot(13))
|
||||
s4 = s2.addBlock(Slot(14))
|
||||
s5 = s2.addBlock(Slot(15))
|
||||
s6 = s3.addBlock(Slot(16))
|
||||
s7 = s6.addBlock(Slot(17))
|
||||
s8 = s4.addBlock(Slot(18))
|
||||
s9 = s8.addBlock(Slot(19))
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s0.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s1.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s2.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s3.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s4.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s5.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s6.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s7.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s8.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s0.state[], s9.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s0.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s1.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s1.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s2.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s3.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s4.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s5.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s6.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s7.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s8.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s1.state[], s9.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s1.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s1.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s2.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s1.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s2.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s3.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s4.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s5.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s6.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s7.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s8.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s2.state[], s9.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s2.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s2.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s2.state[], b.bid, Slot(13)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s3.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s1.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s2.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s3.bid, Slot(10)) == Opt.some(s3.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s4.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s5.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s6.bid, Slot(10)) == Opt.some(s3.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s7.bid, Slot(10)) == Opt.some(s3.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s8.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s3.state[], s9.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s3.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s3.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s3.state[], b.bid, Slot(13)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s3.state[], b.bid, Slot(14)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s4.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s1.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s2.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s3.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s4.bid, Slot(10)) == Opt.some(s4.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s5.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s6.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s7.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s8.bid, Slot(10)) == Opt.some(s4.bid.slot)
|
||||
dag.ancestorSlot(s4.state[], s9.bid, Slot(10)) == Opt.some(s4.bid.slot)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s4.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s4.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s4.state[], b.bid, Slot(13)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s4.state[], b.bid, Slot(14)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s4.state[], b.bid, Slot(15)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s5.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s1.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s2.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s3.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s4.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s5.bid, Slot(10)) == Opt.some(s5.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s6.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s7.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s8.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s5.state[], s9.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s5.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s5.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s5.state[], b.bid, Slot(13)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s5.state[], b.bid, Slot(14)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s5.state[], b.bid, Slot(15)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s5.state[], b.bid, Slot(16)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s6.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s1.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s2.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s3.bid, Slot(10)) == Opt.some(s3.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s4.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s5.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s6.bid, Slot(10)) == Opt.some(s6.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s7.bid, Slot(10)) == Opt.some(s6.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s8.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s6.state[], s9.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s6.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s6.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s6.state[], b.bid, Slot(13)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s6.state[], b.bid, Slot(14)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s6.state[], b.bid, Slot(15)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s6.state[], b.bid, Slot(16)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s6.state[], b.bid, Slot(17)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s7.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s1.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s2.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s3.bid, Slot(10)) == Opt.some(s3.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s4.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s5.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s6.bid, Slot(10)) == Opt.some(s6.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s7.bid, Slot(10)) == Opt.some(s7.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s8.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s7.state[], s9.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s7.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s7.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s7.state[], b.bid, Slot(13)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s7.state[], b.bid, Slot(14)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s7.state[], b.bid, Slot(15)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s8, s9]:
|
||||
check dag.ancestorSlot(s7.state[], b.bid, Slot(16)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s8, s9]:
|
||||
check dag.ancestorSlot(s7.state[], b.bid, Slot(17)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s7.state[], b.bid, Slot(18)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s8.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s1.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s2.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s3.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s4.bid, Slot(10)) == Opt.some(s4.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s5.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s6.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s7.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s8.bid, Slot(10)) == Opt.some(s8.bid.slot)
|
||||
dag.ancestorSlot(s8.state[], s9.bid, Slot(10)) == Opt.some(s8.bid.slot)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(13)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(14)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(15)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(16)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(17)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(18)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s8.state[], b.bid, Slot(19)) == Opt.none(Slot)
|
||||
|
||||
check:
|
||||
dag.ancestorSlot(s9.state[], s0.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s1.bid, Slot(10)) == Opt.some(s1.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s2.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s3.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s4.bid, Slot(10)) == Opt.some(s4.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s5.bid, Slot(10)) == Opt.some(s2.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s6.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s7.bid, Slot(10)) == Opt.some(s0.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s8.bid, Slot(10)) == Opt.some(s8.bid.slot)
|
||||
dag.ancestorSlot(s9.state[], s9.bid, Slot(10)) == Opt.some(s9.bid.slot)
|
||||
for b in [s0, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(11)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s3, s6, s7]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(12)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(13)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(14)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(15)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(16)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(17)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(18)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(19)) == Opt.none(Slot)
|
||||
for b in [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9]:
|
||||
check dag.ancestorSlot(s9.state[], b.bid, Slot(20)) == Opt.none(Slot)
|
||||
|
||||
template runShufflingTests(cfg: RuntimeConfig, numRandomTests: int) =
|
||||
const
|
||||
numValidators = SLOTS_PER_EPOCH
|
||||
|
|
Loading…
Reference in New Issue