diff --git a/log.go b/log.go index 440a66b9..ebdddeac 100644 --- a/log.go +++ b/log.go @@ -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 diff --git a/mining/cpuminer/README.md b/mining/cpuminer/README.md new file mode 100644 index 00000000..3724f0ff --- /dev/null +++ b/mining/cpuminer/README.md @@ -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. diff --git a/cpuminer.go b/mining/cpuminer/cpuminer.go similarity index 93% rename from cpuminer.go rename to mining/cpuminer/cpuminer.go index 1e473349..f581fb8f 100644 --- a/cpuminer.go +++ b/mining/cpuminer/cpuminer.go @@ -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, diff --git a/mining/cpuminer/log.go b/mining/cpuminer/log.go new file mode 100644 index 00000000..ff59dbfe --- /dev/null +++ b/mining/cpuminer/log.go @@ -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 +} diff --git a/server.go b/server.go index dc869cc0..771e310f 100644 --- a/server.go +++ b/server.go @@ -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,