func (b *BlockChain) ProcessBlock(block *types.Block) (bool, bool, error) {
	b.mutex.Lock()
	defer b.mutex.Unlock()
	blockHash := block.Hash()
	log.Debugf("[ProcessBLock] height = %d, hash = %x", block.Header.GetHeight(), blockHash.Bytes())
	exists, err := b.BlockExists(&blockHash)
	if err != nil {
		return false, false, err
	}
	if exists {
		str := fmt.Sprintf("already have block %x\n", blockHash.Bytes())
		return false, false, fmt.Errorf(str)
	}
	if _, exists := b.Orphans[blockHash]; exists {
		str := fmt.Sprintf("already have block (orphan) %v", blockHash)
		return false, false, fmt.Errorf(str)
	}
	err = b.cfg.Validator.CheckBlockSanity(block, b.chainParams.PowLimit, b.TimeSource)
	if err != nil {
		log.Error("powCheckBlockSanity error!", err)
		return false, false, err
	}
	blockHeader := block.Header
	prevHash := blockHeader.GetPrevious()
	if !prevHash.IsEqual(common.EmptyHash) {
		prevHashExists, err := b.BlockExists(&prevHash)
		if err != nil {
			return false, false, err
		}
		if !prevHashExists {
			log.Debugf("Adding orphan block %x with parent %x", blockHash.Bytes(), prevHash.Bytes())
			b.AddOrphanBlock(block)
			return false, true, nil
		}
	}
	inMainChain, err := b.maybeAcceptBlock(block)
	if err != nil {
		return false, true, err
	}
	err = b.ProcessOrphans(&blockHash)
	if err != nil {
		return false, false, err
	}
	if inMainChain {
		log.Info("current height -> ", block.GetHeight())
	}
	return inMainChain, false, nil
}
(bool, bool, error)
1. inMainChain
2. isOphan
3. error
package blockchain
import (
	"container/list"
	"errors"
	"fmt"
	"math/big"
	"sort"
	"sync"
	"time"
	"github.com/elastos/Elastos.ELA.SideChain/config"
	"github.com/elastos/Elastos.ELA.SideChain/events"
	"github.com/elastos/Elastos.ELA.SideChain/types"
	"github.com/elastos/Elastos.ELA.SideChain/interfaces"
	"github.com/elastos/Elastos.ELA/common"
)
const (
	maxOrphanBlocks  = 10000
	minMemoryNodes   = 20160
	maxBlockLocators = 500
	medianTimeBlocks = 11
)
var (
	oneLsh256 = new(big.Int).Lsh(big.NewInt(1), 256)
)
type Config struct {
	ChainStore     *ChainStore
	ChainParams    *config.Params
	Validator      *Validator
	CheckTxSanity  func(*types.Transaction) error
	CheckTxContext func(*types.Transaction) error
	GetTxFee       func(tx *types.Transaction, assetId common.Uint256) (common.Fixed64, error)
	GetHeader      func(hash common.Uint256) (interfaces.Header, error)
	GetBlock       func(hash common.Uint256) (*types.Block, error)
}
type BlockChain struct {
	cfg         *Config
	chainParams *config.Params
	db          *ChainStore
	GenesisHash common.Uint256
	minRetargetTimespan int64   
	maxRetargetTimespan int64   
	blocksPerRetarget   uint32  
	mutex          sync.RWMutex
	BestChain      *BlockNode
	Root           *BlockNode
	Index          map[common.Uint256]*BlockNode
	IndexLock      sync.RWMutex
	DepNodes       map[common.Uint256][]*BlockNode
	Orphans        map[common.Uint256]*OrphanBlock
	PrevOrphans    map[common.Uint256][]*OrphanBlock
	OldestOrphan   *OrphanBlock
	BlockCache     map[common.Uint256]*types.Block
	TimeSource     MedianTimeSource
	MedianTimePast time.Time
	OrphanLock     sync.RWMutex
}
func New(cfg *Config) (*BlockChain, error) {
	genesisHash, err := cfg.ChainStore.GetBlockHash(0)
	if err != nil {
		return nil, fmt.Errorf("query genesis block hash failed, error %s", err)
	}
	chainParams := cfg.ChainParams
	targetTimespan := int64(chainParams.TargetTimespan / time.Second)
	targetTimePerBlock := int64(chainParams.TargetTimePerBlock / time.Second)
	adjustmentFactor := chainParams.AdjustmentFactor
	chain := BlockChain{
		cfg:                 cfg,
		chainParams:         chainParams,
		db:                  cfg.ChainStore,
		GenesisHash:         genesisHash,
		minRetargetTimespan: targetTimespan / adjustmentFactor,
		maxRetargetTimespan: targetTimespan * adjustmentFactor,
		blocksPerRetarget:   uint32(targetTimespan / targetTimePerBlock),
		Root:                nil,
		BestChain:           nil,
		Index:               make(map[common.Uint256]*BlockNode),
		DepNodes:            make(map[common.Uint256][]*BlockNode),
		OldestOrphan:        nil,
		Orphans:             make(map[common.Uint256]*OrphanBlock),
		PrevOrphans:         make(map[common.Uint256][]*OrphanBlock),
		BlockCache:          make(map[common.Uint256]*types.Block),
		TimeSource:          NewMedianTime(),
	}
	endHeight := cfg.ChainStore.GetHeight()
	startHeight := uint32(0)
	if endHeight > minMemoryNodes {
		startHeight = endHeight - minMemoryNodes
	}
	for start := startHeight; start <= endHeight; start++ {
		hash, err := chain.db.GetBlockHash(start)
		if err != nil {
			return nil, err
		}
		var header interfaces.Header
		if cfg.GetHeader != nil {
			header, err = cfg.GetHeader(hash)
		} else {
			header, err = chain.db.GetHeader(hash)
		}
		if err != nil {
			return nil, err
		}
		node, err := chain.LoadBlockNode(header, &hash)
		if err != nil {
			return nil, err
		}
		chain.BestChain = node
	}
	return &chain, nil
}
func (b *BlockChain) GetBestHeight() uint32 {
	return b.db.GetHeight()
}
func (b *BlockChain) IsDoubleSpend(tx *types.Transaction) bool {
	return b.db.IsDoubleSpend(tx)
}
func (b *BlockChain) GetAsset(assetId common.Uint256) (*types.Asset, error) {
	asset, err := b.db.GetAsset(assetId)
	if err != nil {
		return nil, errors.New("[Ledger],GetAsset failed with assetId =" + assetId.String())
	}
	return asset, nil
}
func (b *BlockChain) GetBlockHash(height uint32) (common.Uint256, error) {
	return b.db.GetBlockHash(height)
}
func (b *BlockChain) GetBlockWithHeight(height uint32) (*types.Block, error) {
	temp, err := b.db.GetBlockHash(height)
	if err != nil {
		return nil, errors.New("[Ledger],GetBlockWithHeight failed with height=" + string(height))
	}
	var bk *types.Block
	if b.cfg.GetBlock != nil {
		bk, err = b.cfg.GetBlock(temp)
	} else {
		bk, err = b.db.GetBlock(temp)
	}
	if err != nil {
		return nil, errors.New("[Ledger],GetBlockWithHeight failed with hash=" + temp.String())
	}
	return bk, nil
}
func (b *BlockChain) GetBlockByHash(hash common.Uint256) (*types.Block, error) {
	var bk *types.Block
	var err error
	if b.cfg.GetBlock != nil {
		bk, err = b.cfg.GetBlock(hash)
	} else {
		bk, err = b.db.GetBlock(hash)
	}
	if err != nil {
		return nil, errors.New("[Ledger],GetBlockWithHeight failed with hash=" + hash.String())
	}
	return bk, nil
}
func (b *BlockChain) IsDuplicateTx(txId common.Uint256) bool {
	return b.db.IsDuplicateTx(txId)
}
func (b *BlockChain) IsDuplicateMainchainTx(txId common.Uint256) bool {
	return b.db.IsDuplicateMainchainTx(txId)
}
func (b *BlockChain) GetTransaction(hash common.Uint256) (*types.Transaction, uint32, error) {
	return b.db.GetTransaction(hash)
}
func (b *BlockChain) GetTxReference(tx *types.Transaction) (map[*types.Input]*types.Output, error) {
	return b.db.GetTxReference(tx)
}
func (b *BlockChain) GetAssetUnspents(programHash common.Uint168, assetid common.Uint256) ([]*types.UTXO, error) {
	return b.db.GetAssetUnspents(programHash, assetid)
}
func (b *BlockChain) GetAssets() map[common.Uint256]*types.Asset {
	return b.db.GetAssets()
}
func (b *BlockChain) GetUnspents(programHash common.Uint168) (map[common.Uint256][]*types.UTXO, error) {
	return b.db.GetUnspents(programHash)
}
func (b *BlockChain) GetHeader(hash common.Uint256) (interfaces.Header, error) {
	var header interfaces.Header
	var err error
	if b.cfg.GetHeader != nil {
		header, err = b.db.GetHeader(hash)
	} else {
		header, err = b.db.GetHeader(hash)
	}
	if err != nil {
		return nil, errors.New("[BlockChain], GetHeader failed.")
	}
	return header, nil
}
func (b *BlockChain) ContainsTransaction(hash common.Uint256) bool {
	_, _, err := b.db.GetTransaction(hash)
	if err != nil {
		return false
	}
	return true
}
func (b *BlockChain) CurrentBlockHash() common.Uint256 {
	return b.db.GetCurrentBlockHash()
}
type OrphanBlock struct {
	Block      *types.Block
	Expiration time.Time
}
func (b *BlockChain) ProcessOrphans(hash *common.Uint256) error {
	processHashes := make([]*common.Uint256, 0, 10)
	processHashes = append(processHashes, hash)
	for len(processHashes) > 0 {
		processHash := processHashes[0]
		processHashes[0] = nil  
		processHashes = processHashes[1:]
		for i := 0; i < len(b.PrevOrphans[*processHash]); i++ {
			orphan := b.PrevOrphans[*processHash][i]
			if orphan == nil {
				continue
			}
			orphanHash := orphan.Block.Hash()
			b.RemoveOrphanBlock(orphan)
			i--
			_, err := b.maybeAcceptBlock(orphan.Block)
			if err != nil {
				return err
			}
			processHashes = append(processHashes, &orphanHash)
		}
	}
	return nil
}
func (b *BlockChain) RemoveOrphanBlock(orphan *OrphanBlock) {
	b.OrphanLock.Lock()
	defer b.OrphanLock.Unlock()
	orphanHash := orphan.Block.Hash()
	delete(b.Orphans, orphanHash)
	prevHash := orphan.Block.Header.GetPrevious()
	orphans := b.PrevOrphans[prevHash]
	for i := 0; i < len(orphans); i++ {
		hash := orphans[i].Block.Hash()
		if hash.IsEqual(orphanHash) {
			copy(orphans[i:], orphans[i+1:])
			orphans[len(orphans)-1] = nil
			orphans = orphans[:len(orphans)-1]
			i--
		}
	}
	b.PrevOrphans[prevHash] = orphans
	if len(b.PrevOrphans[prevHash]) == 0 {
		delete(b.PrevOrphans, prevHash)
	}
}
func (b *BlockChain) AddOrphanBlock(block *types.Block) {
	for _, oBlock := range b.Orphans {
		if time.Now().After(oBlock.Expiration) {
			b.RemoveOrphanBlock(oBlock)
			if b.OldestOrphan == oBlock {
				b.OldestOrphan = nil
			}
			continue
		}
	}
	for _, oBlock := range b.Orphans {
		if b.OldestOrphan == nil || oBlock.Expiration.Before(b.OldestOrphan.Expiration) {
			b.OldestOrphan = oBlock
		}
	}
	if len(b.Orphans)+1 > maxOrphanBlocks {
		b.RemoveOrphanBlock(b.OldestOrphan)
		b.OldestOrphan = nil
	}
	b.OrphanLock.Lock()
	defer b.OrphanLock.Unlock()
	expiration := time.Now().Add(time.Hour)
	oBlock := &OrphanBlock{
		Block:      block,
		Expiration: expiration,
	}
	b.Orphans[block.Hash()] = oBlock
	prevHash := block.Header.GetPrevious()
	b.PrevOrphans[prevHash] = append(b.PrevOrphans[prevHash], oBlock)
	return
}
func (b *BlockChain) IsKnownOrphan(hash *common.Uint256) bool {
	b.OrphanLock.RLock()
	_, ok := b.Orphans[*hash]
	b.OrphanLock.RUnlock()
	return ok
}
func (b *BlockChain) GetOrphanRoot(hash *common.Uint256) *common.Uint256 {
	b.OrphanLock.RLock()
	defer b.OrphanLock.RUnlock()
	orphanRoot := hash
	prevHash := hash
	for {
		orphan, ok := b.Orphans[*prevHash]
		if !ok {
			break
		}
		orphanRoot = prevHash
		*prevHash = orphan.Block.Header.GetPrevious()
	}
	return orphanRoot
}
type BlockNode struct {
	Hash        *common.Uint256
	ParentHash  *common.Uint256
	Height      uint32
	Version     uint32
	Bits        uint32
	Timestamp   uint32
	WorkSum     *big.Int
	InMainChain bool
	Parent      *BlockNode
	Children    []*BlockNode
}
func NewBlockNode(header interfaces.Header, hash *common.Uint256) *BlockNode {
	var previous, current common.Uint256
	copy(previous[:], header.GetPrevious().Bytes()[:])
	copy(current[:], hash[:])
	node := BlockNode{
		Hash:       &current,
		ParentHash: &previous,
		Height:     header.GetHeight(),
		Version:    header.GetVersion(),
		Bits:       header.GetBits(),
		Timestamp:  header.GetTimeStamp(),
		WorkSum:    CalcWork(header.GetBits()),
	}
	return &node
}
func CalcWork(bits uint32) *big.Int {
	difficultyNum := CompactToBig(bits)
	if difficultyNum.Sign() <= 0 {
		return big.NewInt(0)
	}
	denominator := new(big.Int).Add(difficultyNum, big.NewInt(1))
	return new(big.Int).Div(oneLsh256, denominator)
}
func AddChildrenWork(node *BlockNode, work *big.Int) {
	for _, childNode := range node.Children {
		childNode.WorkSum.Add(childNode.WorkSum, work)
		AddChildrenWork(childNode, work)
	}
}
func RemoveChildNode(children []*BlockNode, node *BlockNode) []*BlockNode {
	if node == nil {
		return children
	}
	for i := 0; i < len(children); i++ {
		if (*children[i].Hash).IsEqual(*node.Hash) {
			copy(children[i:], children[i+1:])
			children[len(children)-1] = nil
			return children[:len(children)-1]
		}
	}
	return children
}
func (b *BlockChain) LoadBlockNode(blockHeader interfaces.Header, hash *common.Uint256) (*BlockNode, error) {
	node := NewBlockNode(blockHeader, hash)
	node.InMainChain = true
	prevHash := blockHeader.GetPrevious()
	if parentNode, ok := b.LookupNodeInIndex(&prevHash); ok {
		node.WorkSum = node.WorkSum.Add(parentNode.WorkSum, node.WorkSum)
		parentNode.Children = append(parentNode.Children, node)
		node.Parent = parentNode
	} else if childNodes, ok := b.DepNodes[*hash]; ok {
		for _, childNode := range childNodes {
			childNode.Parent = node
			node.Children = append(node.Children, childNode)
			childNode.WorkSum.Add(childNode.WorkSum, node.WorkSum)
			AddChildrenWork(childNode, node.WorkSum)
			b.Root = node
		}
	} else {
		if b.Root != nil {
			str := "LoadBlockNode: attempt to insert orphan block %v"
			return nil, fmt.Errorf(str, hash)
		}
		b.Root = node
	}
	b.AddNodeToIndex(node)
	b.DepNodes[prevHash] = append(b.DepNodes[prevHash], node)
	return node, nil
}
func (b *BlockChain) PruneBlockNodes() error {
	if b.BestChain == nil {
		return nil
	}
	newRootNode := b.BestChain
	for i := uint32(0); i < minMemoryNodes-1 && newRootNode != nil; i++ {
		newRootNode = newRootNode.Parent
	}
	if newRootNode == nil || newRootNode.Parent == nil {
		return nil
	}
	deleteNodes := list.New()
	for node := newRootNode.Parent; node != nil; node = node.Parent {
		deleteNodes.PushFront(node)
	}
	for e := deleteNodes.Front(); e != nil; e = e.Next() {
		node := e.Value.(*BlockNode)
		err := b.RemoveBlockNode(node)
		if err != nil {
			return err
		}
	}
	b.Root = newRootNode
	return nil
}
func (b *BlockChain) RemoveBlockNode(node *BlockNode) error {
	if node.Parent != nil {
		return fmt.Errorf("RemoveBlockNode must be called with a "+
			" node at the front of the chain - node %v", node.Hash)
	}
	b.RemoveNodeFromIndex(node)
	for _, child := range node.Children {
		child.Parent = nil
	}
	node.Children = nil
	prevHash := node.ParentHash
	if children, ok := b.DepNodes[*prevHash]; ok {
		b.DepNodes[*prevHash] = RemoveChildNode(children, node)
		if len(b.DepNodes[*prevHash]) == 0 {
			delete(b.DepNodes, *prevHash)
		}
	}
	return nil
}
func (b *BlockChain) GetPrevNodeFromBlock(block *types.Block) (*BlockNode, error) {
	prevHash := block.Header.GetPrevious()
	if prevHash.IsEqual(common.EmptyHash) {
		return nil, nil
	}
	if bn, ok := b.LookupNodeInIndex(&prevHash); ok {
		return bn, nil
	}
	header, err := b.GetHeader(prevHash)
	if err != nil {
		return nil, err
	}
	prevBlockNode, err := b.LoadBlockNode(header, &prevHash)
	if err != nil {
		return nil, err
	}
	return prevBlockNode, nil
}
func (b *BlockChain) GetPrevNodeFromNode(node *BlockNode) (*BlockNode, error) {
	if node.Parent != nil {
		return node.Parent, nil
	}
	if node.Hash.IsEqual(b.GenesisHash) {
		return nil, nil
	}
	header, err := b.GetHeader(*node.ParentHash)
	if err != nil {
		return nil, err
	}
	prevBlockNode, err := b.LoadBlockNode(header, node.ParentHash)
	if err != nil {
		return nil, err
	}
	return prevBlockNode, nil
}
func (b *BlockChain) getReorganizeNodes(node *BlockNode) (*list.List, *list.List) {
	attachNodes := list.New()
	detachNodes := list.New()
	if node == nil {
		return detachNodes, attachNodes
	}
	ancestor := node
	for ; ancestor.Parent != nil; ancestor = ancestor.Parent {
		if ancestor.InMainChain {
			break
		}
		attachNodes.PushFront(ancestor)
	}
	for n := b.BestChain; n != nil && n.Parent != nil; n = n.Parent {
		if n.Hash.IsEqual(*ancestor.Hash) {
			break
		}
		detachNodes.PushBack(n)
	}
	return detachNodes, attachNodes
}
func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error {
	for e := attachNodes.Front(); e != nil; e = e.Next() {
		n := e.Value.(*BlockNode)
		if _, exists := b.BlockCache[*n.Hash]; !exists {
			return fmt.Errorf("block %x is missing from the side "+
				"chain block cache", n.Hash.Bytes())
		}
	}
	for e := detachNodes.Front(); e != nil; e = e.Next() {
		n := e.Value.(*BlockNode)
		var block *types.Block
		var err error
		if b.cfg.GetBlock != nil {
			block, err = b.cfg.GetBlock(*n.Hash)
		} else {
			block, err = b.db.GetBlock(*n.Hash)
		}
		if err != nil {
			return err
		}
		err = b.disconnectBlock(n, block)
		if err != nil {
			return err
		}
	}
	for e := attachNodes.Front(); e != nil; e = e.Next() {
		n := e.Value.(*BlockNode)
		block := b.BlockCache[*n.Hash]
		err := b.connectBlock(n, block)
		if err != nil {
			return err
		}
		delete(b.BlockCache, *n.Hash)
	}
	return nil
}
func (b *BlockChain) disconnectBlock(node *BlockNode, block *types.Block) error {
	if b.BestChain == nil || !node.Hash.IsEqual(*b.BestChain.Hash) {
		return fmt.Errorf("disconnectBlock must be called with the " +
			"block at the end of the main chain")
	}
	_, err := b.GetPrevNodeFromNode(node)
	if err != nil {
		return err
	}
	err = b.db.RollbackBlock(*node.Hash)
	if err != nil {
		return err
	}
	node.InMainChain = false
	b.BlockCache[*node.Hash] = block
	b.BestChain = node.Parent
	b.MedianTimePast = CalcPastMedianTime(b.BestChain)
	events.Notify(events.ETBlockDisconnected, block)
	return nil
}
func (b *BlockChain) connectBlock(node *BlockNode, block *types.Block) error {
	if err := b.CheckBlockContext(block); err != nil {
		log.Errorf("CheckBlockContext error %s", err.Error())
		return err
	}
	prevHash := block.Header.GetPrevious()
	if b.BestChain != nil && !prevHash.IsEqual(*b.BestChain.Hash) {
		return fmt.Errorf("connectBlock must be called with a block " +
			"that extends the main chain")
	}
	err := b.db.SaveBlock(block)
	if err != nil {
		return err
	}
	node.InMainChain = true
	b.AddNodeToIndex(node)
	b.DepNodes[prevHash] = append(b.DepNodes[prevHash], node)
	b.BestChain = node
	b.MedianTimePast = CalcPastMedianTime(b.BestChain)
	events.Notify(events.ETBlockConnected, block)
	return nil
}
func (b *BlockChain) CheckBlockContext(block *types.Block) error {
	var rewardInCoinbase = common.Fixed64(0)
	var totalTxFee = common.Fixed64(0)
	for index, tx := range block.Transactions {
		if err := b.cfg.CheckTxContext(tx); err != nil {
			return fmt.Errorf("CheckTransactionContext failed when verify block: %s", err)
		}
		if index == 0 {
			for _, output := range tx.Outputs {
				rewardInCoinbase += output.Value
			}
			continue
		}
		fee, err := b.cfg.GetTxFee(tx, b.chainParams.ElaAssetId)
		if err != nil {
			continue
		}
		totalTxFee += fee
	}
	if rewardInCoinbase != totalTxFee {
		return errors.New("reward amount in coinbase not correct")
	}
	return nil
}
func (b *BlockChain) HaveBlock(hash *common.Uint256) (bool, error) {
	exists, err := b.BlockExists(hash)
	if err != nil {
		return false, err
	}
	return exists || b.IsKnownOrphan(hash), nil
}
func (b *BlockChain) BlockExists(hash *common.Uint256) (bool, error) {
	if _, ok := b.LookupNodeInIndex(hash); ok {
		return true, nil
	}
	return b.db.IsBlockInStore(hash), nil
}
func (b *BlockChain) maybeAcceptBlock(block *types.Block) (bool, error) {
	prevNode, err := b.GetPrevNodeFromBlock(block)
	if err != nil {
		log.Errorf("getPrevNodeFromBlock: %v", err)
		return false, err
	}
	blockHeight := uint32(0)
	if prevNode != nil {
		blockHeight = prevNode.Height + 1
	}
	if block.Header.GetHeight() != blockHeight {
		return false, fmt.Errorf("wrong block height!")
	}
	err = b.cfg.Validator.CheckBlockContext(block, prevNode)
	if err != nil {
		log.Error("powCheckBlockContext error!", err)
		return false, err
	}
	err = b.PruneBlockNodes()
	if err != nil {
		return false, err
	}
	blockhash := block.Hash()
	header := block.Header
	newNode := NewBlockNode(header, &blockhash)
	if prevNode != nil {
		newNode.Parent = prevNode
		newNode.Height = blockHeight
		newNode.WorkSum.Add(prevNode.WorkSum, newNode.WorkSum)
	}
	inMainChain, err := b.connectBestChain(newNode, block)
	if err != nil {
		return false, err
	}
	events.Notify(events.ETBlockAccepted, block)
	return inMainChain, nil
}
func (b *BlockChain) connectBestChain(node *BlockNode, block *types.Block) (bool, error) {
	if b.BestChain == nil || node.Parent.Hash.IsEqual(*b.BestChain.Hash) {
		err := b.connectBlock(node, block)
		if err != nil {
			return false, err
		}
		if node.Parent != nil {
			node.Parent.Children = append(node.Parent.Children, node)
		}
		return true, nil
	}
	log.Debugf("Adding block %x to side chain cache", node.Hash.Bytes())
	b.BlockCache[*node.Hash] = block
	b.AddNodeToIndex(node)
	node.InMainChain = false
	node.Parent.Children = append(node.Parent.Children, node)
	if node.WorkSum.Cmp(b.BestChain.WorkSum) <= 0 {
		fork := node
		for ; fork.Parent != nil; fork = fork.Parent {
			if fork.InMainChain {
				break
			}
		}
		if fork.Hash.IsEqual(*node.Parent.Hash) {
			log.Infof("FORK: Block %s forks the chain at height %d"+
				"/block %s, but does not cause a reorganize",
				node.Hash, fork.Height, fork.Hash)
		} else {
			log.Infof("EXTEND FORK: Block %s extends a side chain "+
				"which forks the chain at height %d/block %s",
				node.Hash, fork.Height, fork.Hash)
		}
		return false, nil
	}
	detachNodes, attachNodes := b.getReorganizeNodes(node)
	log.Infof("REORGANIZE: Block %s is causing a reorganize.", node.Hash)
	err := b.reorganizeChain(detachNodes, attachNodes)
	if err != nil {
		return false, err
	}
	return true, nil
}