func (oc *OrderCache) get(height int32) (*OrderCacheEntry, bool) {
	if height < minOrderCacheDistance {
		return nil, false
	}
	target := height - minOrderCacheDistance
	entry, exists := oc.cache[target]
	if exists {
		return entry, true
	}
	cacheHeights := oc.heights()
	sort.Sort(sort.Reverse(byHeight(cacheHeights)))
	for _, h := range cacheHeights {
		if h > target {
			continue
		}
		entry, exists := oc.cache[h]
		if !exists {
			continue
		}
		return entry, true
	}
	return nil, false
}
get returns a cache entry appropriate for the height, and whether a matching cache entry was found
package phantom
import (
	"fmt"
	"sort"
	"sync"
)
const (
	minOrderCacheDistance = int32(200)
	maxOrderCacheSize = int(minOrderCacheDistance) * 20
)
type OrderCacheEntry struct {
	Tips []*Node
	Order []*Node
}
type OrderCache struct {
	cache map[int32]*OrderCacheEntry
	addsSinceLastExpire int
	sync.RWMutex
}
type byHeight []int32
func (h byHeight) Len() int { return len(h) }
func (h byHeight) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h byHeight) Less(i, j int) bool { return h[i] < h[j] }
func NewOrderCache() *OrderCache {
	oc := OrderCache{
		cache: make(map[int32]*OrderCacheEntry),
	}
	return &oc
}
func (oc *OrderCache) add(height int32, tips, order []*Node) error {
	reason, ok := oc.canAdd(height)
	if !ok {
		return fmt.Errorf("failed to add to OrderCache, %s", reason)
	}
	size := oc.size()
	if size >= maxOrderCacheSize && oc.addsSinceLastExpire >= cacheFullExpireInterval {
		n := (size - maxOrderCacheSize) + 1
		log.Debugf("Expiring %d lowest orderCache items", n)
		oc.expire(n)
		oc.addsSinceLastExpire = 0
	}
	oc.cache[height] = &OrderCacheEntry{
		Tips: tips,
		Order: order,
	}
	oc.addsSinceLastExpire += 1
	return nil
}
func (oc *OrderCache) Add(height int32, tips, order []*Node) error {
	oc.Lock()
	defer oc.Unlock()
	return oc.add(height, tips, order)
}
func (oc *OrderCache) canAdd(height int32) (string, bool) {
	if height < minOrderCacheDistance {
		reason := fmt.Sprintf("height is too low; got %d, want >= %d", height, minOrderCacheDistance)
		return reason, false
	}
	if _, ok := oc.cache[height]; ok {
		reason := fmt.Sprintf("existing cache entry at height %d", height)
		return reason, false
	}
	return "", true
}
func (oc *OrderCache) CanAdd(height int32) (string, bool) {
	oc.Lock()
	defer oc.Unlock()
	return oc.canAdd(height)
}
func (oc *OrderCache) expire(amt int) {
	if amt <= 0 {
		return
	}
	heights := oc.heights()
	size := len(heights)
	if size < amt {
		amt = size
	}
	for i := 0; i < amt; i++ {
		delete(oc.cache, heights[i])
	}
}
func (oc *OrderCache) Expire(amt int) {
	oc.Lock()
	defer oc.Unlock()
	oc.expire(amt)
}