fix stack overflow in isAncestor recursion

This commit is contained in:
Jacek Sieka 2019-11-28 09:51:12 +01:00 committed by zah
parent c98a0d28ae
commit 2a728d9468
4 changed files with 39 additions and 11 deletions

View File

@ -2,6 +2,7 @@ import
deques, tables, options,
stew/[endians2], chronicles,
spec/[datatypes, crypto, digest],
nimcrypto/utils,
beacon_chain_db
type
@ -214,8 +215,9 @@ type
proc shortLog*(v: AttachedValidator): string = shortLog(v.pubKey)
chronicles.formatIt BlockSlot:
($it.blck.root)[0..7] & ":" & $it.slot
mixin toHex
it.blck.root.data[0..3].toHex(true) & ":" & $it.slot
chronicles.formatIt BlockRef:
($it.root)[0..7] & ":" & $it.slot
mixin toHex
it.root.data[0..3].toHex(true) & ":" & $it.slot

View File

@ -615,12 +615,22 @@ proc loadTailState*(pool: BlockPool): StateData =
)
func isAncestorOf*(a, b: BlockRef): bool =
if a == b:
true
elif a.slot >= b.slot or b.parent.isNil:
false
else:
a.isAncestorOf(b.parent)
var b = b
var depth = 0
const maxDepth = (100'i64 * 365 * 24 * 60 * 60 div SECONDS_PER_SLOT.int)
while true:
if a == b: return true
# for now, use an assert for block chain length since a chain this long
# indicates a circular reference here..
doAssert depth < maxDepth
depth += 1
if a.slot >= b.slot or b.parent.isNil:
return false
doAssert b.slot > b.parent.slot
b = b.parent
proc delBlockAndState(pool: BlockPool, blockRoot: Eth2Digest) =
if (let blk = pool.db.getBlock(blockRoot); blk.isSome):

View File

@ -33,10 +33,10 @@ type
chronicles.formatIt Eth2Digest:
mixin toHex
it.data.toHex(true)[0..7]
it.data[0..3].toHex(true)
func shortLog*(x: Eth2Digest): string =
x.data.toHex(true)[0..7]
x.data[0..3].toHex(true)
# TODO: expose an in-place digest function
# when hashing in loop or into a buffer

View File

@ -94,3 +94,19 @@ suite "Block pool processing" & preset():
hash_tree_root(state.data.data) == state.data.root
pool2.get(b1Root).isSome()
pool2.get(b2Root).isSome()
test "isAncestorOf sanity" & preset():
let
a = BlockRef(slot: Slot(1))
b = BlockRef(slot: Slot(2), parent: a)
c = BlockRef(slot: Slot(3), parent: b)
check:
a.isAncestorOf(a)
a.isAncestorOf(b)
a.isAncestorOf(c)
b.isAncestorOf(c)
not c.isAncestorOf(a)
not c.isAncestorOf(b)
not b.isAncestorOf(a)