cpuminer: Refactor code to its own package.

This does the minimum work necessary to refactor the CPU miner code into
its own package.  The idea is that separating this code into its own
package will improve its testability and ultimately be useful to other
parts of the codebase such as the various tests which currently
effectively have their own stripped-down versions of this code.

The API will certainly need some additional cleanup and changes to make
it more usable outside of the specific circumstances it was originally
designed to support (namely the generate RPC), however it is better to
do that in future commits in order to keep the changeset as small as
possible during this refactor.

Overview of the major changes:

- Create the new package
- Move cpuminer.go -> cpuminer/cpuminer.go
- Update mining logging to use the new cpuminer package logger
- Rename cpuminerConfig to Config (so it's now cpuminer.Config)
- Rename newCPUMiner to New (so it's now cpuminer.New)
- Update all references to the cpuminer to use the package
- Add a skeleton README.md
This commit is contained in:
Dave Collins 2016-10-28 11:06:11 -05:00
parent a755305a2e
commit 1a69eb0617
No known key found for this signature in database
GPG key ID: B8904D9D9C93D1F2
5 changed files with 117 additions and 31 deletions

2
log.go
View file

@ -15,6 +15,7 @@ import (
"github.com/btcsuite/btcd/database"
"github.com/btcsuite/btcd/mempool"
"github.com/btcsuite/btcd/mining"
"github.com/btcsuite/btcd/mining/cpuminer"
"github.com/btcsuite/btcd/peer"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btclog"
@ -129,6 +130,7 @@ func useLogger(subsystemID string, logger btclog.Logger) {
case "MINR":
minrLog = logger
mining.UseLogger(logger)
cpuminer.UseLogger(logger)
case "PEER":
peerLog = logger

26
mining/cpuminer/README.md Normal file
View file

@ -0,0 +1,26 @@
cpuminer
========
[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)]
(https://travis-ci.org/btcsuite/btcd) [![ISC License]
(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)]
(http://godoc.org/github.com/btcsuite/btcd/mining/cpuminer)
## Overview
This package is currently a work in progress. It works without issue since it
is used in several of the integration tests, but the API is not really ready for
public consumption as it has simply been refactored out of the main codebase for
now.
## Installation and Updating
```bash
$ go get -u github.com/btcsuite/btcd/mining/cpuminer
```
## License
Package cpuminer is licensed under the [copyfree](http://copyfree.org) ISC
License.

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
package cpuminer
import (
"errors"
@ -47,8 +47,8 @@ var (
defaultNumWorkers = uint32(runtime.NumCPU())
)
// cpuminerConfig is a descriptor containing the cpu miner configuration.
type cpuminerConfig struct {
// Config is a descriptor containing the cpu miner configuration.
type Config struct {
// ChainParams identifies which chain parameters the cpu miner is
// associated with.
ChainParams *chaincfg.Params
@ -92,7 +92,7 @@ type cpuminerConfig struct {
type CPUMiner struct {
sync.Mutex
g *mining.BlkTmplGenerator
cfg cpuminerConfig
cfg Config
numWorkers uint32
started bool
discreteMining bool
@ -109,7 +109,7 @@ type CPUMiner struct {
// speedMonitor handles tracking the number of hashes per second the mining
// process is performing. It must be run as a goroutine.
func (m *CPUMiner) speedMonitor() {
minrLog.Tracef("CPU miner speed monitor started")
log.Tracef("CPU miner speed monitor started")
var hashesPerSec float64
var totalHashes uint64
@ -133,7 +133,7 @@ out:
hashesPerSec = (hashesPerSec + curHashesPerSec) / 2
totalHashes = 0
if hashesPerSec != 0 {
minrLog.Debugf("Hash speed: %6.0f kilohashes/s",
log.Debugf("Hash speed: %6.0f kilohashes/s",
hashesPerSec/1000)
}
@ -147,7 +147,7 @@ out:
}
m.wg.Done()
minrLog.Tracef("CPU miner speed monitor done")
log.Tracef("CPU miner speed monitor done")
}
// submitBlock submits the passed block to network after ensuring it passes all
@ -161,10 +161,9 @@ func (m *CPUMiner) submitBlock(block *btcutil.Block) bool {
// detected and all work on the stale block is halted to start work on
// a new block, but the check only happens periodically, so it is
// possible a block was found and submitted in between.
latestHash := m.g.BestSnapshot().Hash
msgBlock := block.MsgBlock()
if !msgBlock.Header.PrevBlock.IsEqual(latestHash) {
minrLog.Debugf("Block submitted via CPU miner with previous "+
if !msgBlock.Header.PrevBlock.IsEqual(m.g.BestSnapshot().Hash) {
log.Debugf("Block submitted via CPU miner with previous "+
"block %s is stale", msgBlock.Header.PrevBlock)
return false
}
@ -176,22 +175,22 @@ func (m *CPUMiner) submitBlock(block *btcutil.Block) bool {
// Anything other than a rule violation is an unexpected error,
// so log that error as an internal error.
if _, ok := err.(blockchain.RuleError); !ok {
minrLog.Errorf("Unexpected error while processing "+
log.Errorf("Unexpected error while processing "+
"block submitted via CPU miner: %v", err)
return false
}
minrLog.Debugf("Block submitted via CPU miner rejected: %v", err)
log.Debugf("Block submitted via CPU miner rejected: %v", err)
return false
}
if isOrphan {
minrLog.Debugf("Block submitted via CPU miner is an orphan")
log.Debugf("Block submitted via CPU miner is an orphan")
return false
}
// The block was accepted.
coinbaseTx := block.MsgBlock().Transactions[0].TxOut[0]
minrLog.Infof("Block submitted via CPU miner accepted (hash %s, "+
log.Infof("Block submitted via CPU miner accepted (hash %s, "+
"amount %v)", block.Hash(), btcutil.Amount(coinbaseTx.Value))
return true
}
@ -212,12 +211,12 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32,
// worker.
enOffset, err := wire.RandomUint64()
if err != nil {
minrLog.Errorf("Unexpected error while generating random "+
log.Errorf("Unexpected error while generating random "+
"extra nonce offset: %v", err)
enOffset = 0
}
// Create a couple of convenience variables.
// Create some convenience variables.
header := &msgBlock.Header
targetDifficulty := blockchain.CompactToBig(header.Bits)
@ -232,7 +231,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32,
for extraNonce := uint64(0); extraNonce < maxExtraNonce; extraNonce++ {
// Update the extra nonce in the block template with the
// new value by regenerating the coinbase script and
// setting the merkle root to the new value. The
// setting the merkle root to the new value.
m.g.UpdateExtraNonce(msgBlock, blockHeight, extraNonce+enOffset)
// Search through the entire nonce range for a solution while
@ -298,7 +297,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32,
//
// It must be run as a goroutine.
func (m *CPUMiner) generateBlocks(quit chan struct{}) {
minrLog.Tracef("Starting generate blocks worker")
log.Tracef("Starting generate blocks worker")
// Start a ticker which is used to signal checks for stale work and
// updates to the speed monitor.
@ -347,7 +346,7 @@ out:
if err != nil {
errStr := fmt.Sprintf("Failed to create new block "+
"template: %v", err)
minrLog.Errorf(errStr)
log.Errorf(errStr)
continue
}
@ -362,7 +361,7 @@ out:
}
m.workerWg.Done()
minrLog.Tracef("Generate blocks worker done")
log.Tracef("Generate blocks worker done")
}
// miningWorkerController launches the worker goroutines that are used to
@ -436,8 +435,8 @@ func (m *CPUMiner) Start() {
m.Lock()
defer m.Unlock()
// Nothing to do if the miner is already running or if running in discrete
// mode (using GenerateNBlocks).
// Nothing to do if the miner is already running or if running in
// discrete mode (using GenerateNBlocks).
if m.started || m.discreteMining {
return
}
@ -449,7 +448,7 @@ func (m *CPUMiner) Start() {
go m.miningWorkerController()
m.started = true
minrLog.Infof("CPU miner started")
log.Infof("CPU miner started")
}
// Stop gracefully stops the mining process by signalling all workers, and the
@ -470,7 +469,7 @@ func (m *CPUMiner) Stop() {
close(m.quit)
m.wg.Wait()
m.started = false
minrLog.Infof("CPU miner stopped")
log.Infof("CPU miner stopped")
}
// IsMining returns whether or not the CPU miner has been started and is
@ -564,7 +563,7 @@ func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) {
m.Unlock()
minrLog.Tracef("Generating %d blocks", n)
log.Tracef("Generating %d blocks", n)
i := uint32(0)
blockHashes := make([]*chainhash.Hash, n, n)
@ -601,7 +600,7 @@ func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) {
if err != nil {
errStr := fmt.Sprintf("Failed to create new block "+
"template: %v", err)
minrLog.Errorf(errStr)
log.Errorf(errStr)
continue
}
@ -615,7 +614,7 @@ func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) {
blockHashes[i] = block.Hash()
i++
if i == n {
minrLog.Tracef("Generated %d blocks", i)
log.Tracef("Generated %d blocks", i)
m.Lock()
close(m.speedMonitorQuit)
m.wg.Wait()
@ -628,10 +627,10 @@ func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) {
}
}
// newCPUMiner returns a new instance of a CPU miner for the provided server.
// New returns a new instance of a CPU miner for the provided configuration.
// Use Start to begin the mining process. See the documentation for CPUMiner
// type for more details.
func newCPUMiner(cfg *cpuminerConfig) *CPUMiner {
func New(cfg *Config) *CPUMiner {
return &CPUMiner{
g: cfg.BlockTemplateGenerator,
cfg: *cfg,

58
mining/cpuminer/log.go Normal file
View file

@ -0,0 +1,58 @@
// Copyright (c) 2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package cpuminer
import (
"errors"
"io"
"github.com/btcsuite/btclog"
)
// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger
// The default amount of logging is none.
func init() {
DisableLog()
}
// DisableLog disables all library log output. Logging output is disabled
// by default until either UseLogger or SetLogWriter are called.
func DisableLog() {
log = btclog.Disabled
}
// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using btclog.
func UseLogger(logger btclog.Logger) {
log = logger
}
// SetLogWriter uses a specified io.Writer to output package logging info.
// This allows a caller to direct package logging output without needing a
// dependency on seelog. If the caller is also using btclog, UseLogger should
// be used instead.
func SetLogWriter(w io.Writer, level string) error {
if w == nil {
return errors.New("nil writer")
}
lvl, ok := btclog.LogLevelFromString(level)
if !ok {
return errors.New("invalid log level")
}
l, err := btclog.NewLoggerFromWriter(w, lvl)
if err != nil {
return err
}
UseLogger(l)
return nil
}

View file

@ -28,6 +28,7 @@ import (
"github.com/btcsuite/btcd/database"
"github.com/btcsuite/btcd/mempool"
"github.com/btcsuite/btcd/mining"
"github.com/btcsuite/btcd/mining/cpuminer"
"github.com/btcsuite/btcd/peer"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
@ -153,7 +154,7 @@ type server struct {
rpcServer *rpcServer
blockManager *blockManager
txMemPool *mempool.TxPool
cpuMiner *CPUMiner
cpuMiner *cpuminer.CPUMiner
modifyRebroadcastInv chan interface{}
newPeers chan *serverPeer
donePeers chan *serverPeer
@ -2378,7 +2379,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
blockTemplateGenerator := mining.NewBlkTmplGenerator(&policy,
s.chainParams, s.txMemPool, s.blockManager.chain, s.timeSource,
s.sigCache)
s.cpuMiner = newCPUMiner(&cpuminerConfig{
s.cpuMiner = cpuminer.New(&cpuminer.Config{
ChainParams: chainParams,
BlockTemplateGenerator: blockTemplateGenerator,
MiningAddrs: cfg.miningAddrs,