func (gh *CachedLMDGhost) getAncestor(block *dag.DagNode, height uint64) *dag.DagNode {
	if height >= block.Height {
		if height > block.Height {
			return nil
		} else {
			return block
		}
	}
	cacheKey := CacheKey{}
	copy(cacheKey[:32], block.Key[:])
	cacheKey[32] = uint8(height >> 24)
	cacheKey[33] = uint8(height >> 16)
	cacheKey[34] = uint8(height >> 8)
	cacheKey[35] = uint8(height)
	if res, ok := gh.cache[cacheKey]; ok {
		return res
	}
	if x := gh.ancestors[logz[block.Height - height - 1]][block]; x == nil {
		panic("Ancestors data is invalid")
	}
	skipBlock := gh.ancestors[logz[block.Height - height - 1]][block]
	o := gh.getAncestor(skipBlock, height)
	if o.Height != height {
		panic("Found ancestor is at wrong height")
	}
	gh.cache[cacheKey] = o
	return o
}
/ Similar to the spec get_ancestor,
/ but using height instead of slot numbers to enable skipping ahead logarithmically, and with caching.
package cached
import (
	"lmd-ghost/eth2/dag"
)
type CacheKey [32 + 4]uint8
const logzLen = 10000
var logz = [logzLen]uint8{0, 0}
func init() {
	for i := 2; i < logzLen; i++ {
		logz[i] = logz[i / 2] + 1
	}
}
type CachedLMDGhost struct {
	dag *dag.BeaconDag
	latestScores map[*dag.DagNode]int64
	cache map[CacheKey]*dag.DagNode
	ancestors [16]map[*dag.DagNode]*dag.DagNode
}
func NewCachedLMDGhost(d *dag.BeaconDag) dag.ForkChoice {
	res := &CachedLMDGhost{
		dag:          d,
		latestScores: make(map[*dag.DagNode]int64),
		cache: make(map[CacheKey]*dag.DagNode),
		ancestors: [16]map[*dag.DagNode]*dag.DagNode{},
	}
	for i := uint8(0); i < 16; i++ {
		res.ancestors[i] = make(map[*dag.DagNode]*dag.DagNode)
	}
	return res
}