func genBlockChain(numBlocks uint32) ([]*chainhash.Hash, map[chainhash.Hash]*wire.MsgBlock) {
	prevHash := chainParams.GenesisHash
	prevHeader := &chainParams.GenesisBlock.Header
	hashes := make([]*chainhash.Hash, numBlocks)
	blocks := make(map[chainhash.Hash]*wire.MsgBlock, numBlocks)
	script := []byte{0x01, 0x01}
	createTx := func(prevOut wire.OutPoint) *wire.MsgTx {
		return &wire.MsgTx{
			TxIn: []*wire.TxIn{{
				PreviousOutPoint: prevOut,
				SignatureScript:  script,
			}},
			TxOut: []*wire.TxOut{{PkScript: script}},
		}
	}
	for i := uint32(0); i < numBlocks; i++ {
		txs := []*wire.MsgTx{
			createTx(wire.OutPoint{Index: wire.MaxPrevOutIndex}),
			createTx(wire.OutPoint{Hash: *prevHash, Index: 0}),
			createTx(wire.OutPoint{Hash: *prevHash, Index: 1}),
		}
		header := &wire.BlockHeader{
			Version:    1,
			PrevBlock:  *prevHash,
			MerkleRoot: calcMerkleRoot(txs),
			Timestamp:  prevHeader.Timestamp.Add(10 * time.Minute),
			Bits:       chainParams.PowLimitBits,
			Nonce:      0,
		}
		if !solveBlock(header) {
			panic(fmt.Sprintf("could not solve block at idx %v", i))
		}
		block := &wire.MsgBlock{
			Header:       *header,
			Transactions: txs,
		}
		blockHash := block.BlockHash()
		hashes[i] = &blockHash
		blocks[blockHash] = block
		prevHash = &blockHash
		prevHeader = header
	}
	return hashes, blocks
}
genBlockChain generates a test chain with the given number of blocks.
package chain
import (
	"fmt"
	"io"
	"math"
	"net"
	"runtime"
	"sync"
	"time"
	"github.com/btcsuite/btcd/blockchain"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
)
type conn struct {
	io.Reader
	io.Writer
	io.Closer
	localAddr  string
	remoteAddr string
}
func (c conn) LocalAddr() net.Addr {
	return &addr{"tcp", c.localAddr}
}
func (c conn) RemoteAddr() net.Addr {
	return &addr{"tcp", c.remoteAddr}
}
func (c conn) SetDeadline(t time.Time) error      { return nil }
func (c conn) SetReadDeadline(t time.Time) error  { return nil }
func (c conn) SetWriteDeadline(t time.Time) error { return nil }
type addr struct {
	net, address string
}
func (m addr) Network() string { return m.net }
func (m addr) String() string  { return m.address }
func pipe(c1, c2 *conn) (*conn, *conn) {
	r1, w1 := io.Pipe()
	r2, w2 := io.Pipe()
	c1.Writer = w1
	c1.Closer = w1
	c2.Reader = r1
	c1.Reader = r2
	c2.Writer = w2
	c2.Closer = w2
	return c1, c2
}
func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash {
	if len(txns) == 0 {
		return chainhash.Hash{}
	}
	utilTxns := make([]*btcutil.Tx, 0, len(txns))
	for _, tx := range txns {
		utilTxns = append(utilTxns, btcutil.NewTx(tx))
	}
	merkles := blockchain.BuildMerkleTreeStore(utilTxns, false)
	return *merkles[len(merkles)-1]
}
func solveBlock(header *wire.BlockHeader) bool {
	type sbResult struct {
		found bool
		nonce uint32
	}
	var wg sync.WaitGroup
	defer func() {
		wg.Wait()
	}()
	targetDifficulty := blockchain.CompactToBig(header.Bits)
	quit := make(chan bool)
	results := make(chan sbResult)
	solver := func(hdr wire.BlockHeader, startNonce, stopNonce uint32) {
		defer wg.Done()
		for i := startNonce; i >= startNonce && i <= stopNonce; i++ {
			select {
			case <-quit:
				return
			default:
				hdr.Nonce = i
				hash := hdr.BlockHash()
				if blockchain.HashToBig(&hash).Cmp(
					targetDifficulty) <= 0 {
					select {
					case results <- sbResult{true, i}:
					case <-quit:
					}
					return
				}
			}
		}
		select {
		case results <- sbResult{false, 0}:
		case <-quit:
		}
	}
	startNonce := uint32(1)
	stopNonce := uint32(math.MaxUint32)
	numCores := uint32(runtime.NumCPU())
	noncesPerCore := (stopNonce - startNonce) / numCores
	wg.Add(int(numCores))
	for i := uint32(0); i < numCores; i++ {
		rangeStart := startNonce + (noncesPerCore * i)
		rangeStop := startNonce + (noncesPerCore * (i + 1)) - 1
		if i == numCores-1 {
			rangeStop = stopNonce
		}
		go solver(*header, rangeStart, rangeStop)
	}
	for i := uint32(0); i < numCores; i++ {
		result := <-results
		if result.found {
			close(quit)
			header.Nonce = result.nonce
			return true
		}
	}
	return false
}