func (b *BlockDAG) HaveBlock(hash *chainhash.Hash) (bool, error) {
	exists, err := b.blockExists(hash)
	if err != nil {
		return false, err
	}
	return exists || b.IsKnownOrphan(hash), nil
}
HaveBlock returns whether or not the chain instance has the block represented
by the passed hash.  This includes checking the various places a block can
be like part of the main chain, on a side chain, or in the orphan pool.

This function is safe for concurrent access.
package blockdag
import (
	"container/list"
	"fmt"
	"github.com/soteria-dag/soterd/mining/cuckoo"
	"math"
	"sort"
	"sync"
	"time"
	"github.com/soteria-dag/soterd/blockdag/phantom"
	"github.com/soteria-dag/soterd/chaincfg"
	"github.com/soteria-dag/soterd/chaincfg/chainhash"
	"github.com/soteria-dag/soterd/database"
	"github.com/soteria-dag/soterd/soterutil"
	"github.com/soteria-dag/soterd/txscript"
	"github.com/soteria-dag/soterd/wire"
)
const (
	maxOrphanBlocks = 700
	maxGenerationDifference = 70
	coloringK = 3
)
type BlockLocator []*int32
type orphanBlock struct {
	block      *soterutil.Block
	expiration time.Time
}
type BestState struct {
	Hash        chainhash.Hash  
	Height      int32           
	Bits        uint32          
	BlockSize   uint64          
	BlockWeight uint64          
	NumTxns     uint64          
	TotalTxns   uint64          
	MedianTime  time.Time       
}
func newBestState(node *blockNode, blockSize, blockWeight, numTxns,
	totalTxns uint64, medianTime time.Time) *BestState {
	return &BestState{
		Hash:        node.hash,
		Height:      node.height,
		Bits:        node.bits,
		BlockSize:   blockSize,
		BlockWeight: blockWeight,
		NumTxns:     numTxns,
		TotalTxns:   totalTxns,
		MedianTime:  medianTime,
	}
}
type DAGState struct {
	Tips      []chainhash.Hash  
	Hash      chainhash.Hash  
	MinHeight int32
	MaxHeight int32
	BlkCount  uint32
}
func newDAGState(tips []*blockNode, blkCount uint32) *DAGState {
	tipHashes := make([]chainhash.Hash, len(tips))
	i := 0
	var maxHeight int32 = math.MinInt32
	var minHeight int32 = math.MaxInt32
	for _, tip := range tips {
		tipHashes[i] = tip.hash
		i++
		if tip.height > maxHeight {
			maxHeight = tip.height
		}
		if tip.height < minHeight {
			minHeight = tip.height
		}
	}
	hash := generateTipsHash(tips)
	return &DAGState{
		Tips: tipHashes,
		Hash: *hash,
		MinHeight: minHeight,
		MaxHeight: maxHeight,
		BlkCount: blkCount,
	}
}
type BlockDAG struct {
	db           database.DB
	chainParams  *chaincfg.Params
	timeSource   MedianTimeSource
	sigCache     *txscript.SigCache
	indexManager IndexManager
	hashCache    *txscript.HashCache
	Solver cuckoo.Solver
	minRetargetTimespan int64  
	maxRetargetTimespan int64  
	blocksPerRetarget   int64  
	chainLock sync.RWMutex
	index             *blockIndex
	dView             *dagView
	graph             *phantom.Graph
	blueSet           *phantom.BlueSetCache
	nodeOrder         []*chainhash.Hash
	orderCache        *phantom.OrderCache
	orphanLock   sync.RWMutex
	orphans      map[chainhash.Hash]*orphanBlock
	prevOrphans  map[chainhash.Hash][]*orphanBlock
	oldestOrphan *orphanBlock
	stateLock     sync.RWMutex
	stateSnapshot *BestState
	dagSnapshot   *DAGState
	warningCaches    []thresholdStateCache
	deploymentCaches []thresholdStateCache
	unknownRulesWarned    bool
	unknownVersionsWarned bool
	notificationsLock sync.RWMutex
	notifications     []NotificationCallback
}
func (b *BlockDAG) visitOrphan(hash *chainhash.Hash, order *[]chainhash.Hash, tempMark, done *map[chainhash.Hash]int) error {
	_, isDone := (*done)[*hash]
	if isDone {
		return nil
	}
	_, inProgress := (*tempMark)[*hash]
	if inProgress {
		return fmt.Errorf("Non-DAG block connectivity detected!")
	}
	(*tempMark)[*hash] = 0
	parents, hasParents := b.prevOrphans[*hash]
	if hasParents {
		for _, parent := range parents {
			err := b.visitOrphan(parent.block.Hash(), order, tempMark, done)
			if err != nil {
				return err
			}
		}
	}
	(*done)[*hash] = 0
	*order = append(*order, *hash)
	return nil
}