func (f *SidechainForest) Prune(mainChainHeight int32, params *chaincfg.Params) {
	pruneDepth := int32(params.CoinbaseMaturity)
	for i := 0; i < len(f.trees); {
		if int32(f.trees[i].root.Header.Height)+pruneDepth < mainChainHeight {
			f.trees[i] = f.trees[len(f.trees)-1]
			f.trees[len(f.trees)-1] = nil
			f.trees = f.trees[:len(f.trees)-1]
		} else {
			i++
		}
	}
}
Prune removes any sidechain trees which contain a root that is significantly
behind the current main chain tip block.
package wallet
import (
	"context"
	"math/big"
	"sort"
	"decred.org/dcrwallet/v2/errors"
	"decred.org/dcrwallet/v2/wallet/walletdb"
	blockchain "github.com/decred/dcrd/blockchain/standalone/v2"
	"github.com/decred/dcrd/chaincfg/chainhash"
	"github.com/decred/dcrd/chaincfg/v3"
	"github.com/decred/dcrd/gcs/v3"
	"github.com/decred/dcrd/wire"
)
type SidechainForest struct {
	trees []*sidechainRootedTree
}
type BlockNode struct {
	Header   *wire.BlockHeader
	Hash     *chainhash.Hash
	FilterV2 *gcs.FilterV2
	parent   *BlockNode
	workSum  *big.Int
}
type sidechainRootedTree struct {
	root      *BlockNode
	children  map[chainhash.Hash]*BlockNode
	tips      map[chainhash.Hash]*BlockNode
	bestChain []*BlockNode  
}
func newSideChainRootedTree(root *BlockNode) *sidechainRootedTree {
	root.workSum = blockchain.CalcWork(root.Header.Bits)
	return &sidechainRootedTree{
		root:     root,
		children: make(map[chainhash.Hash]*BlockNode),
		tips:     make(map[chainhash.Hash]*BlockNode),
	}
}
func NewBlockNode(header *wire.BlockHeader, hash *chainhash.Hash, filter *gcs.FilterV2) *BlockNode {
	return &BlockNode{
		Header:   header,
		Hash:     hash,
		FilterV2: filter,
	}
}
func (t *sidechainRootedTree) duplicateNode(n *BlockNode) bool {
	if *t.root.Hash == *n.Hash {
		return true
	}
	old, ok := t.children[*n.Hash]
	if ok && n.FilterV2 != nil && old.FilterV2 == nil {
		old.FilterV2 = n.FilterV2
	}
	return ok
}
func (t *sidechainRootedTree) maybeAttachNode(n *BlockNode) bool {
	if *t.root.Hash == n.Header.PrevBlock && n.Header.Height == t.root.Header.Height+1 {
		n.parent = t.root
		t.children[*n.Hash] = n
		t.tips[*n.Hash] = n
		n.workSum = new(big.Int).Add(n.parent.workSum, blockchain.CalcWork(n.Header.Bits))
		t.bestChain = nil
		return true
	}
	if parent, ok := t.children[n.Header.PrevBlock]; ok && n.Header.Height == parent.Header.Height+1 {
		n.parent = parent
		t.children[*n.Hash] = n
		t.tips[*n.Hash] = n
		delete(t.tips, *parent.Hash)
		n.workSum = new(big.Int).Add(n.parent.workSum, blockchain.CalcWork(n.Header.Bits))
		t.bestChain = nil
		return true
	}
	return false
}
func (t *sidechainRootedTree) best() ([]*BlockNode, *big.Int) {
	if len(t.bestChain) != 0 {
		return t.bestChain, t.bestChain[len(t.bestChain)-1].workSum
	}
	var best *BlockNode
	for _, n := range t.tips {
		if best == nil || best.workSum.Cmp(n.workSum) == -1 {
			best = n
		}
	}
	if best == nil {
		t.bestChain = []*BlockNode{t.root}
		return t.bestChain, t.root.workSum
	}
	chain := make([]*BlockNode, best.Header.Height-t.root.Header.Height+1)
	n := best
	for i, j := 0, len(chain)-1; i < len(chain); i, j = i+1, j-1 {
		chain[j] = n
		n = n.parent
	}
	t.bestChain = chain
	return chain, best.workSum
}
func (f *SidechainForest) AddBlockNode(n *BlockNode) bool {
	var nodeTree *sidechainRootedTree
	for _, t := range f.trees {
		if t.duplicateNode(n) {
			return false
		}
		if t.maybeAttachNode(n) {
			nodeTree = t
			break
		}
	}
	if nodeTree == nil {
		nodeTree = newSideChainRootedTree(n)
		f.trees = append(f.trees, nodeTree)
	}
	for i := 0; i < len(f.trees); {
		orphanTree := f.trees[i]
		if orphanTree.root.Header.PrevBlock != *n.Hash {
			i++
			continue
		}
		var nodes []*BlockNode
		nodes = append(nodes, orphanTree.root)
		for _, node := range orphanTree.children {
			nodes = append(nodes, node)
		}
		sort.Slice(nodes, func(i, j int) bool {
			return nodes[i].Header.Height < nodes[j].Header.Height
		})
		for _, n := range nodes {
			if nodeTree.duplicateNode(n) || !nodeTree.maybeAttachNode(n) {
				panic("sidechain forest internal consistency error")
			}
		}
		f.trees[i] = f.trees[len(f.trees)-1]
		f.trees[len(f.trees)-1] = nil
		f.trees = f.trees[:len(f.trees)-1]
	}
	return true
}