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
|
AllTests-mainnet
|
||||||
===
|
===
|
||||||
|
## Ancestry
|
||||||
|
```diff
|
||||||
|
+ ancestorSlot OK
|
||||||
|
```
|
||||||
|
OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
## Attestation pool processing [Preset: mainnet]
|
## Attestation pool processing [Preset: mainnet]
|
||||||
```diff
|
```diff
|
||||||
+ Attestation from different branch [Preset: mainnet] OK
|
+ 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
|
OK: 2/2 Fail: 0/2 Skip: 0/2
|
||||||
## BlockRef and helpers
|
## BlockRef and helpers
|
||||||
```diff
|
```diff
|
||||||
+ commonAncestor sanity OK
|
|
||||||
+ get_ancestor sanity OK
|
+ get_ancestor sanity OK
|
||||||
+ isAncestorOf 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
|
## BlockSlot and helpers
|
||||||
```diff
|
```diff
|
||||||
+ atSlot sanity OK
|
+ atSlot sanity OK
|
||||||
|
|
|
@ -155,34 +155,6 @@ func get_ancestor*(blck: BlockRef, slot: Slot,
|
||||||
|
|
||||||
blck = blck.parent
|
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 =
|
func atSlot*(blck: BlockRef, slot: Slot): BlockSlot =
|
||||||
## Return a BlockSlot at a given slot, with the block set to the closest block
|
## 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
|
## 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(
|
dag.finalizedHead.blck, dag.finalizedHead.slot.epoch, false).expect(
|
||||||
"getEpochRef for finalized head should always succeed")
|
"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,
|
dag: ChainDAGRef, state: ForkyHashedBeaconState,
|
||||||
blck: BlockRef, epoch: Epoch): Opt[Slot] =
|
blck: BlockRef, epoch: Epoch): Opt[Slot] =
|
||||||
## Return slot of `blck` ancestor to which `state` can be rewinded
|
## 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
|
const numDelayEpochs = compute_activation_exit_epoch(GENESIS_EPOCH).uint64
|
||||||
let
|
let
|
||||||
lowEpoch = max(epoch, (numDelayEpochs - 1).Epoch) - (numDelayEpochs - 1)
|
lowEpoch = max(epoch, (numDelayEpochs - 1).Epoch) - (numDelayEpochs - 1)
|
||||||
lowSlot = lowEpoch.start_slot
|
ancestorSlot = ? dag.ancestorSlot(state, blck.bid, lowEpoch.start_slot)
|
||||||
if state.data.slot < lowSlot or blck.slot < lowSlot:
|
Opt.some min(ancestorSlot, epoch.attester_dependent_slot)
|
||||||
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)
|
|
||||||
|
|
||||||
type AttesterRandaoMix = tuple[dependentBid: BlockId, mix: Eth2Digest]
|
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(3)) == s2
|
||||||
s4.get_ancestor(Slot(4)) == s4
|
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":
|
suite "BlockSlot and helpers":
|
||||||
test "atSlot sanity":
|
test "atSlot sanity":
|
||||||
let
|
let
|
||||||
|
|
|
@ -1180,6 +1180,295 @@ suite "Pruning":
|
||||||
dag.tail.slot == Epoch(EPOCHS_PER_STATE_SNAPSHOT).start_slot - 1
|
dag.tail.slot == Epoch(EPOCHS_PER_STATE_SNAPSHOT).start_slot - 1
|
||||||
not db.containsBlock(blocks[1].root)
|
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) =
|
template runShufflingTests(cfg: RuntimeConfig, numRandomTests: int) =
|
||||||
const
|
const
|
||||||
numValidators = SLOTS_PER_EPOCH
|
numValidators = SLOTS_PER_EPOCH
|
||||||
|
|
Loading…
Reference in New Issue