Skip to content

Commit

Permalink
Create stratum, work, and util packages.
Browse files Browse the repository at this point in the history
This commit moves the stratum code to one package,the work type to
another package, and several general use functions to the util
package.

Closes #11
  • Loading branch information
jcvernaleo committed Aug 1, 2016
1 parent 325db20 commit f7ad5dc
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 219 deletions.
5 changes: 3 additions & 2 deletions calibrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import (
"unsafe"

"github.com/decred/gominer/cl"
"github.com/decred/gominer/work"
)

// getKernelExecutionTime returns the kernel execution time for a device.
func (d *Device) getKernelExecutionTime(globalWorksize uint32) (time.Duration,
error) {
d.work = Work{}
d.work = work.Work{}

minrLog.Tracef("Started GPU #%d: %s for kernel execution time fetch",
d.index, d.deviceName)
Expand Down Expand Up @@ -43,7 +44,7 @@ func (d *Device) getKernelExecutionTime(globalWorksize uint32) (time.Duration,
// args 9..20: lastBlock except nonce
i2 := 0
for i := 0; i < 12; i++ {
if i2 == nonce0Word {
if i2 == work.Nonce0Word {
i2++
}
lb := d.lastBlock[i2]
Expand Down
65 changes: 22 additions & 43 deletions device.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,22 @@ import (
"unsafe"

"github.com/decred/dcrd/blockchain"
"github.com/decred/dcrd/chaincfg"
"github.com/decred/dcrd/chaincfg/chainhash"

"github.com/decred/gominer/blake256"
"github.com/decred/gominer/cl"
"github.com/decred/gominer/work"
)

const (
outputBufferSize = cl.CL_size_t(64)
localWorksize = 64
uint32Size = cl.CL_size_t(unsafe.Sizeof(cl.CL_uint(0)))

timestampWord = 2
nonce0Word = 3
nonce1Word = 4
nonce2Word = 5
)

var chainParams = &chaincfg.MainNetParams

var zeroSlice = []cl.CL_uint{cl.CL_uint(0)}

func loadProgramSource(filename string) ([][]byte, []cl.CL_size_t, error) {
Expand Down Expand Up @@ -63,26 +62,6 @@ func loadProgramSource(filename string) ([][]byte, []cl.CL_size_t, error) {
return program_buffer[:], program_size[:], nil
}

// NewWork is the constructor for work.
func NewWork(data [192]byte, target *big.Int, jobTime uint32, timeReceived uint32,
isGetWork bool) *Work {
return &Work{
Data: data,
Target: target,
JobTime: jobTime,
TimeReceived: timeReceived,
isGetWork: isGetWork,
}
}

type Work struct {
Data [192]byte
Target *big.Int
JobTime uint32
TimeReceived uint32
isGetWork bool
}

type Device struct {
index int
platformID cl.CL_platform_id
Expand All @@ -107,8 +86,8 @@ type Device struct {
midstate [8]uint32
lastBlock [16]uint32

work Work
newWork chan *Work
work work.Work
newWork chan *work.Work
workDone chan []byte
hasWork bool

Expand Down Expand Up @@ -153,7 +132,7 @@ func NewDevice(index int, platformID cl.CL_platform_id, deviceID cl.CL_device_id
deviceID: deviceID,
deviceName: getDeviceInfo(deviceID, cl.CL_DEVICE_NAME, "CL_DEVICE_NAME"),
quit: make(chan struct{}),
newWork: make(chan *Work, 5),
newWork: make(chan *work.Work, 5),
workDone: workDone,
}

Expand Down Expand Up @@ -273,7 +252,7 @@ func (d *Device) Release() {
}

func (d *Device) updateCurrentWork() {
var w *Work
var w *work.Work
if d.hasWork {
// If we already have work, we just need to check if there's new one
// without blocking if there's not.
Expand All @@ -299,7 +278,7 @@ func (d *Device) updateCurrentWork() {

// Bump and set the work ID if the work is new.
d.currentWorkID++
binary.LittleEndian.PutUint32(d.work.Data[128+4*nonce2Word:],
binary.LittleEndian.PutUint32(d.work.Data[128+4*work.Nonce2Word:],
d.currentWorkID)

// Reset the hash state
Expand Down Expand Up @@ -371,7 +350,7 @@ func (d *Device) runDevice() error {
// different work. If the extraNonce has already been
// set for valid work, restore that.
d.extraNonce += uint32(d.index) << 24
d.lastBlock[nonce1Word] = Uint32EndiannessSwap(d.extraNonce)
d.lastBlock[work.Nonce1Word] = Uint32EndiannessSwap(d.extraNonce)

var status cl.CL_int
for {
Expand All @@ -385,16 +364,16 @@ func (d *Device) runDevice() error {

// Increment extraNonce.
rolloverExtraNonce(&d.extraNonce)
d.lastBlock[nonce1Word] = Uint32EndiannessSwap(d.extraNonce)
d.lastBlock[work.Nonce1Word] = Uint32EndiannessSwap(d.extraNonce)

// Update the timestamp. Only solo work allows you to roll
// the timestamp.
ts := d.work.JobTime
if d.work.isGetWork {
if d.work.IsGetWork {
diffSeconds := uint32(time.Now().Unix()) - d.work.TimeReceived
ts = d.work.JobTime + diffSeconds
}
d.lastBlock[timestampWord] = Uint32EndiannessSwap(ts)
d.lastBlock[work.TimestampWord] = Uint32EndiannessSwap(ts)

// arg 0: pointer to the buffer
obuf := d.outputBuffer
Expand All @@ -418,7 +397,7 @@ func (d *Device) runDevice() error {
// args 9..20: lastBlock except nonce
i2 := 0
for i := 0; i < 12; i++ {
if i2 == nonce0Word {
if i2 == work.Nonce0Word {
i2++
}
lb := d.lastBlock[i2]
Expand Down Expand Up @@ -461,15 +440,15 @@ func (d *Device) runDevice() error {
for i := uint32(0); i < outputData[0]; i++ {
minrLog.Debugf("GPU #%d: Found candidate %v nonce %08x, "+
"extraNonce %08x, workID %08x, timestamp %08x",
d.index, i+1, outputData[i+1], d.lastBlock[nonce1Word],
d.index, i+1, outputData[i+1], d.lastBlock[work.Nonce1Word],
Uint32EndiannessSwap(d.currentWorkID),
d.lastBlock[timestampWord])
d.lastBlock[work.TimestampWord])

// Assess the work. If it's below target, it'll be rejected
// here. The mining algorithm currently sends this function any
// difficulty 1 shares.
d.foundCandidate(d.lastBlock[timestampWord], outputData[i+1],
d.lastBlock[nonce1Word])
d.foundCandidate(d.lastBlock[work.TimestampWord], outputData[i+1],
d.lastBlock[work.Nonce1Word])
}

elapsedTime := time.Since(currentTime)
Expand All @@ -483,9 +462,9 @@ func (d *Device) foundCandidate(ts, nonce0, nonce1 uint32) {
data := make([]byte, 192)
copy(data, d.work.Data[:])

binary.BigEndian.PutUint32(data[128+4*timestampWord:], ts)
binary.BigEndian.PutUint32(data[128+4*nonce0Word:], nonce0)
binary.BigEndian.PutUint32(data[128+4*nonce1Word:], nonce1)
binary.BigEndian.PutUint32(data[128+4*work.TimestampWord:], ts)
binary.BigEndian.PutUint32(data[128+4*work.Nonce0Word:], nonce0)
binary.BigEndian.PutUint32(data[128+4*work.Nonce1Word:], nonce1)
hash := chainhash.HashFuncH(data[0:180])

// Hashes that reach this logic and fail the minimal proof of
Expand Down Expand Up @@ -516,7 +495,7 @@ func (d *Device) Stop() {
close(d.quit)
}

func (d *Device) SetWork(w *Work) {
func (d *Device) SetWork(w *work.Work) {
d.newWork <- w
}

Expand Down
18 changes: 11 additions & 7 deletions getwork.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import (
"time"

"github.com/btcsuite/go-socks/socks"

"github.com/decred/gominer/stratum"
"github.com/decred/gominer/util"
"github.com/decred/gominer/work"
)

// newHTTPClient returns a new HTTP client that is configured according to the
Expand Down Expand Up @@ -113,7 +117,7 @@ func createHTTPClient() *http.Client {
}

// GetWork makes a getwork RPC call and returns the result (data and target)
func GetWork() (*Work, error) {
func GetWork() (*work.Work, error) {
// Generate a request to the configured RPC server.
protocol := "http"
if !cfg.NoTLS {
Expand Down Expand Up @@ -183,21 +187,21 @@ func GetWork() (*Work, error) {
}

bigTarget := new(big.Int)
bigTarget.SetBytes(reverse(target))
bigTarget.SetBytes(util.Reverse(target))

var workData [192]byte
copy(workData[:], data)
givenTs := binary.LittleEndian.Uint32(
workData[128+4*timestampWord : 132+4*timestampWord])
w := NewWork(workData, bigTarget, givenTs, uint32(time.Now().Unix()), true)
workData[128+4*work.TimestampWord : 132+4*work.TimestampWord])
w := work.NewWork(workData, bigTarget, givenTs, uint32(time.Now().Unix()), true)

w.Target = bigTarget

return w, nil
}

// GetPoolWork gets work from a stratum enabled pool
func GetPoolWork(pool *Stratum) (*Work, error) {
func GetPoolWork(pool *stratum.Stratum) (*work.Work, error) {
// Get Next work for stratum and mark it as used
if pool.PoolWork.NewWork {
poolLog.Info("Received new work from pool.")
Expand Down Expand Up @@ -287,7 +291,7 @@ func GetWorkSubmit(data []byte) (bool, error) {
}

// GetPoolWorkSubmit sends the result to the stratum enabled pool
func GetPoolWorkSubmit(data []byte, pool *Stratum) (bool, error) {
func GetPoolWorkSubmit(data []byte, pool *stratum.Stratum) (bool, error) {
sub, err := pool.PrepSubmit(data)
if err != nil {
return false, err
Expand All @@ -310,7 +314,7 @@ func GetPoolWorkSubmit(data []byte, pool *Stratum) (bool, error) {
return false, err
}

pool.submitted = true
pool.Submitted = true

return true, nil
}
3 changes: 3 additions & 0 deletions log.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/btcsuite/btclog"
"github.com/btcsuite/seelog"

"github.com/decred/gominer/stratum"
)

var (
Expand Down Expand Up @@ -36,6 +38,7 @@ func useLogger(subsystemID string, logger btclog.Logger) {
minrLog = logger
case "POOL":
poolLog = logger
stratum.UseLogger(logger)
}
}

Expand Down
10 changes: 6 additions & 4 deletions miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"time"

"github.com/decred/gominer/cl"
"github.com/decred/gominer/stratum"
"github.com/decred/gominer/work"
)

func getCLPlatforms() ([]cl.CL_platform_id, error) {
Expand Down Expand Up @@ -49,7 +51,7 @@ type Miner struct {
quit chan struct{}
needsWorkRefresh chan struct{}
wg sync.WaitGroup
pool *Stratum
pool *stratum.Stratum

started uint32
validShares uint64
Expand All @@ -66,7 +68,7 @@ func NewMiner() (*Miner, error) {

// If needed, start pool code.
if cfg.Pool != "" && !cfg.Benchmark {
s, err := StratumConn(cfg.Pool, cfg.PoolUser, cfg.PoolPassword)
s, err := stratum.StratumConn(cfg.Pool, cfg.PoolUser, cfg.PoolPassword, cfg.Proxy, cfg.ProxyUser, cfg.ProxyPass, version())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -156,7 +158,7 @@ func (m *Miner) workSubmitThread() {
accepted, err := GetPoolWorkSubmit(data, m.pool)
if err != nil {
switch err {
case ErrStatumStaleWork:
case stratum.ErrStatumStaleWork:
stale := atomic.LoadUint64(&m.staleShares)
stale++
atomic.StoreUint64(&m.staleShares, stale)
Expand Down Expand Up @@ -278,7 +280,7 @@ func (m *Miner) Run() {

if cfg.Benchmark {
minrLog.Warn("Running in BENCHMARK mode! No real mining taking place!")
work := &Work{}
work := &work.Work{}
for _, d := range m.devices {
d.SetWork(work)
}
Expand Down
26 changes: 26 additions & 0 deletions stratum/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2013-2015 The btcsuite developers
// Copyright (c) 2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package stratum

import "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.Disabled

// 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
}
Loading

0 comments on commit f7ad5dc

Please sign in to comment.