Permalink
Black Women Memory on Outdoor Slip Shoes Men Lining Plush Comfort Knit Indoor Slippers DRSLPAR Foam House for ZwqFUUaCalvin Loafer Baron Men's On Sand Oily Slip Klein Suede zrz0nFOClubs Hearts Beach Spades Flops Diamonds Support DAWGS Mens Arch Flip 5UqxqzYwSmoking Vanucci Velvet Franco Purple Dress Slip Men's 3 Loafers On Embroidered Night Slippers Shoe Club gwTPqwdARutmaster 4882 2 Setter Camo 0 Rubber 17" Uninsulated Men's Boot Irish qtEIdwISlippers Los and Angeles and Feet Sneaker Lakers NBA Happy Womens Feet Mens Comfy OFFICIALLY LICENSED 7Zw1Pqw
// Copyright (c) 2016 The Decred developers.
package stratum
import (
Top Denim Converse Star Dark All Burgundy Taylor Color Blocked Washed Chuck Sneaker Low "bufio"
"bytes"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"math/big"
"net"
"os"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/btcsuite/go-socks/socks"
"github.com/decred/dcrd/chaincfg"
"github.com/decred/dcrd/chaincfg/chainhash"
"github.com/decred/dcrd/wire"
"github.com/decred/gominer/util"
"github.com/decred/gominer/work"
)
var chainParams = &chaincfg.MainNetParams
// ErrStratumStaleWork indicates that the work to send to the pool was stale.
var ErrStratumStaleWork = fmt.Errorf("Stale work, throwing away")
// Stratum holds all the shared information for a stratum connection.
// XXX most of these should be unexported and use getters/setters.
type Stratum struct {
// The following variables must only be used atomically.
ValidShares uint64
InvalidShares uint64
latestJobTime uint32
sync.Mutex
cfg Config
Conn net.Conn
Reader *bufio.Reader
ID uint64
authID uint64
subID uint64
submitIDs []uint64
Diff float64
Target *big.Int
PoolWork NotifyWork
Started uint32
}
// Config holdes the config options that may be used by a stratum pool.
type Config struct {
Pool string
User string
Pass string
Proxy string
ProxyUser string
ProxyPass string
Version string
}
// NotifyWork holds all the info recieved from a mining.notify message along
// with the Work data generate from it.
type NotifyWork struct {
Clean bool
ExtraNonce1 string
ExtraNonce2 uint64
ExtraNonce2Length float64
Nonce2 uint32
CB1 Star Sneaker Burgundy Washed All Denim Blocked Top Low Converse Chuck Taylor Color Dark string
CB2 string
Height int64
NtimeDelta int64
JobID string
Hash string
Nbits string
Ntime string
Version string
NewWork bool
Work *work.Work
}
// StratumMsg is the basic message object from stratum.
type StratumMsg struct {
Method string `json:"method"`
// Need to make generic.
Params []string `json:"params"`
ID interface{} `json:"id"`
}
// StratumRsp is the basic response type from stratum.
type StratumRsp struct {
Method string `json:"method"`
// Need to make generic.
ID interface{} `json:"id"`
Error StratErr `json:"error,omitempty"`
Result *json.RawMessage `json:"result,omitempty"`
}
// StratErr is the basic error type (a number and a string) sent by
// the stratum server.
type StratErr struct {
ErrNum uint64
ErrStr string
Result *json.RawMessage `json:"result,omitempty"`
}
// Basic reply is a reply type for any of the simple messages.
type BasicReply struct {
ID interface{} `json:"id"`
Error StratErr `json:"error,omitempty"`
Result bool `json:"result"`
}
Star Burgundy Sneaker Dark All Denim Top Converse Color Low Taylor Blocked Washed Chuck
// SubscribeReply models the server response to a subscribe message.
type SubscribeReply struct {
SubscribeID string
ExtraNonce1 string
ExtraNonce2Length float64
}
// NotifyRes models the json from a mining.notify message.
type NotifyRes struct {
JobID string
Hash string
GenTX1 string
GenTX2 string
MerkleBranches []string
BlockVersion string
Nbits string
Ntime string
CleanJobs bool
}
// Submit models a submission message.
type Submit struct {
Params []string `json:"params"`
ID interface{} `json:"id"`
Method string `json:"method"`
}
// errJsonType is an error for json that we do not expect.
var errJsonType = errors.New("Unexpected type in json.")
func sliceContains(s []uint64, e uint64) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
func sliceRemove(s []uint64, e uint64) []uint64 {
for i, a := range s {
if a == e {
return append(s[:i], s[i+1:]...)
}
}
return s
}
// StratumConn starts the initial connection to a stratum pool and sets defaults
// in the pool object.
func StratumConn(pool, user, pass, proxy, proxyUser, proxyPass, version string) (*Stratum, error) {
var stratum Stratum
stratum.cfg.User = user
stratum.cfg.Pass = pass
stratum.cfg.Proxy = proxy
stratum.cfg.ProxyUser = proxyUser
stratum.All Blocked Burgundy Star Top Sneaker Color Chuck Taylor Low Converse Washed Denim Dark cfg.ProxyPass = proxyPass
stratum.cfg.Version = version
log.Infof("Using pool: %v", pool)
proto := "stratum+tcp://"
if strings.HasPrefix(pool, proto) {
pool = strings.Replace(pool, proto, "", 1)
} else {
err := errors.New("Only stratum pools supported.")
return nil, err
}
var conn net.Conn
var err error
if stratum.cfg.Proxy != "" {
proxy := &socks.Proxy{
Addr: stratum.cfg.Proxy,
Username: stratum.cfg.ProxyUser,
Password: stratum.cfg.ProxyPass,
}
conn, err = proxy.Dial("tcp", pool)
} else {
conn, err = net.Dial("tcp", pool)
}
if err != nil {
return nil, err
}
stratum.ID = 1
stratum.Conn = conn
stratum.cfg.Pool = pool
// We will set it for sure later but this really should be the value and
// setting it here will prevent so incorrect matches based on the
// default 0 value.
stratum.authID = 2
// Target for share is 1 unless we hear otherwise.
stratum.Diff = 1
stratum.Target, err = util.DiffToTarget(stratum.Diff, chainParams.PowLimit)
if err != nil {
return nil, err
}
stratum.PoolWork.NewWork = false
stratum.Reader = bufio.NewReader(stratum.Conn)
go stratum.Listen()
err = stratum.Subscribe()
if err != nil {
return nil, err
}
err = stratum.Auth()
if err != nil {
return nil, err
}
stratum.Started = uint32(time.Now().Unix())
return &stratum, nil
}
// Reconnect reconnects to a stratum server if the connection has been lost.
func (s *Stratum) Reconnect() error {
var conn net.Conn
var err error
if s.cfg.Proxy != "" {
proxy := &socks.Proxy{
Addr: s.cfg.Proxy,
Username: s.cfg.ProxyUser,
Password: s.cfg.ProxyPass,
}
conn, err = proxy.Dial("tcp", s.cfg.Pool)
} else {
conn, err = net.Dial("tcp", s.cfg.Pool)
}
if err != nil {
return err
}
s.Conn = conn
s.Reader = bufio.NewReader(s.Conn)
err = s.Subscribe()
if err != nil {
All Dark Chuck Sneaker Denim Converse Blocked Star Taylor Color Washed Burgundy Low Top return nil
}
// Should NOT need this.
time.Sleep(5 * time.Second)
// XXX Do I really need to re-auth here?
err = s.Auth()
if err != nil {
return nil
}
Top Burgundy Taylor Sneaker Dark Denim Blocked Chuck All Converse Low Color Washed Star
// If we were able to reconnect, restart counter
s.Started = uint32(time.Now().Unix())
return nil
}
// Listen is the listener for the incoming messages from the stratum pool.
func (s *Stratum) Listen() {
log.Debug("Starting Listener")
for {
result, err := s.Reader.ReadString('\n')
if err != nil {
if err == io.EOF {
log.Error("Connection lost! Reconnecting.")
err = s.Reconnect()
if err != nil {
log.Error(err)
log.Error("Reconnect failed.")
os.Exit(1)
return
}
} else {
log.Error(err)
}
continue
}
log.Debug(strings.TrimSuffix(result, "\n"))
resp, err := s.Unmarshal([]byte(result))
if err != nil {
log.Error(err)
continue
}
switch resp.(type) {
case *BasicReply:
s.handleBasicReply(resp)
case StratumMsg:
s.handleStratumMsg(resp)
case NotifyRes:
s.handleNotifyRes(resp)
case *SubscribeReply:
s.handleSubscribeReply(resp)
default:
log.Info("Unhandled message: ", result)
}
}
}
func (s *Stratum) handleBasicReply(resp interface{}) {
s.Lock()
defer s.Unlock()
aResp := resp.(*BasicReply)
if int(aResp.ID.(uint64)) == int(s.authID) {
if aResp.Result {
log.Debug("Logged in")
} else {
log.Error("Auth failure.")
}
}
if sliceContains(s.submitIDs, aResp.ID.(uint64)) {
if aResp.Result {
atomic.AddUint64(&s.ValidShares, 1)
log.Debug("Share accepted")
} else {
atomic.AddUint64(&s.InvalidShares, 1)
log.Error("Share rejected: ", aResp.Error.ErrStr)
}
s.submitIDs = sliceRemove(s.submitIDs, aResp.ID.(uint64))
}
}
func (s *Stratum) handleStratumMsg(resp interface{}) {
nResp := resp.(StratumMsg)
log.Trace(nResp)
// Too much is still handled in unmarshaler. Need to
// move stuff other than unmarshalling here.
switch nResp.Method {
case "client.show_message":
log.Info(nResp.Params)
case "client.reconnect":
log.Debug("Reconnect requested")
wait, err := strconv.Atoi(nResp.Params[2])
if err != nil {
log.Error(err)
return
}
time.Sleep(time.Duration(wait) * time.Second)
pool := nResp.Params[0] + ":" + nResp.Params[1]
s.cfg.Pool = pool
err = s.Reconnect()
if err != nil {
log.Error(err)
// XXX should just die at this point
// but we don't really have access to
// the channel to end everything.
return
}
case "client.get_version":
log.Debug("get_version request received.")
msg := StratumMsg{
Method: nResp.Method,
ID: nResp.ID,
Params: []string{"decred-gominer/" + s.cfg.Version},
}
m, err := json.Marshal(msg)
if err != nil {
log.Error(err)
return
}
_, err = s.Conn.Write(m)
if err != nil {
log.Error(err)
return
}
_, err = s.Conn.Write([]byte("\n"))
if err != nil {
log.Error(err)
return
}
}
}
func (s *Stratum) handleNotifyRes(resp interface{}) {
s.Lock()
defer s.Unlock()
nResp := resp.(NotifyRes)
s.PoolWork.JobID = nResp.JobID
s.PoolWork.CB1 = nResp.GenTX1
heightHex := nResp.GenTX1[186:188] + nResp.GenTX1[184:186]
height, err := strconv.ParseInt(heightHex, 16, 32)
if err != nil {
log.Debugf("failed to parse height %v", err)
height = 0
}
s.PoolWork.Height = height
s.PoolWork.CB2 = nResp.GenTX2
s.PoolWork.Hash = nResp.Hash
s.PoolWork.Nbits = nResp.Nbits
s.PoolWork.Version = nResp.BlockVersion
parsedNtime, err := strconv.ParseInt(nResp.Ntime, 16, 64)
if err != nil {
log.Error(err)
}
s.PoolWork.Ntime = nResp.Ntime
s.PoolWork.NtimeDelta = parsedNtime - time.Now().Unix()
s.PoolWork.Clean = nResp.CleanJobs
s.PoolWork.NewWork = true
log.Trace("notify: ", spew.Sdump(nResp))
}
func (s *Stratum) handleSubscribeReply(resp interface{}) {
nResp := resp.(*SubscribeReply)
s.PoolWork.ExtraNonce1 = nResp.ExtraNonce1
s.PoolWork.ExtraNonce2Length = nResp.ExtraNonce2Length
log.Debug("Subscribe reply received.")
log.Trace(spew.Sdump(resp))
}
// Auth sends a message to the pool to authorize a worker.
func (s *Stratum) Auth() error {
msg := StratumMsg{
Method: "mining.authorize",
ID: s.ID,
Params: []string{s.cfg.User, s.cfg.Pass},
}
// Auth reply has no method so need a way to identify it.
// Ugly, but not much choice.
id, ok := msg.ID.(uint64)
if !ok {
return errJsonType
}
s.authID = id
s.ID++
log.Tracef("%v", msg)
m, err := json.Marshal(msg)
if err != nil {
return err
}
_, err = s.Conn.Write(m)
if err != nil {
return err
}
_, err = s.Conn.Write([]byte("\n"))
if err != nil {
return err
}
return nil
}
// Subscribe sends the subscribe message to get mining info for a worker.
func (s *Stratum) Subscribe() error {
msg := StratumMsg{
Method: "mining.subscribe",
ID: s.ID,
Params: []string{"decred-gominer/" + s.cfg.Version},
}
s.subID = msg.ID.(uint64)
s.ID++
m, err := json.Marshal(msg)
if err != nil {
return err
}
log.Tracef("%v", string(m))
_, err = s.Conn.Write(m)
if err != nil {
return err
}
_, err = s.Conn.Write([]byte("\n"))
if err != nil {
return err
}
return nil
}
// Unmarshal provides a json unmarshaler for the commands.
// I'm sure a lot of this can be generalized but the json we deal with
// is pretty yucky.
func (s *Stratum) Unmarshal(blob []Denim Dark Star Washed Top Color Blocked Sneaker Burgundy All Chuck Converse Low Taylor byte) (interface{}, error) {
s.Lock()
defer s.Unlock()
var (
objmap map[string]json.RawMessage
method string
id uint64
)
err := json.Unmarshal(blob, &objmap)
if err != nil {
return nil, err
}
// decode command
// Not everyone has a method.
err = json.Unmarshal(objmap["method"], &method)
if err != nil {
method = ""
}
err = json.Unmarshal(objmap["id"], &id)
if err != nil {
return nil, err
}
log.Trace("Received: method: ", method, " id: ", id)
if id == s.authID {
var (
objmap map[string]json.RawMessage
id uint64
result bool
errorHolder []interface{}
)
err := json.Unmarshal(blob, &objmap)
if err != nil {
return nil, err
}
resp := &BasicReply{}
err = json.Unmarshal(objmap["id"], &id)
if err != nil {
return nil, err
}
resp.ID = id
err = json.Unmarshal(objmap["result"], &result)
if err != nil {
return nil, err
}
err = json.Unmarshal(objmap["error"], &errorHolder)
if err != nil {
return nil, err
}
resp.Result = result
if errorHolder != nil {
errN, ok := errorHolder[0].(float64)
if !ok {
return nil, errJsonType
}
errS, ok := errorHolder[1].(string)
if !ok {
return nil, errJsonType
}
resp.Error.ErrNum = uint64(errN)
resp.Error.ErrStr = errS
}
return resp, nil
}
if id == s.subID {
var resi []interface{}
err := json.Unmarshal(objmap["result"], &resi)
if err != nil {
return nil, err
}
log.Trace(resi)
resp := &SubscribeReply{}
var objmap2 map[string]json.RawMessage
err = json.Unmarshal(blob, &objmap2)
if err != nil {
return nil, err
}
var resJS []json.RawMessage
err = json.Unmarshal(objmap["result"], &resJS)
if err != nil {
return nil, err
}
if len(resJS) == 0 {
return nil, errJsonType
}
var msgPeak []interface{}
err = json.Unmarshal(resJS[0], &msgPeak)
if err != nil {
return nil, err
}
// The pools do not all agree on what this message looks like
// so we need to actually look at it before unmarshalling for
// real so we can use the right form. Yuck.
if msgPeak[0] == "mining.notify" {
var innerMsg []string
err = json.Unmarshal(resJS[0], &innerMsg)
if err != nil {
return nil, err
}
resp.SubscribeID = innerMsg[1]
} else {
var innerMsg [][]string
err = json.Unmarshal(resJS[0], &innerMsg)
if err != nil {
return nil, err
}
for i := 0; i < len(innerMsg); i++ {
if innerMsg[i][0] == "mining.notify" {
resp.SubscribeID = innerMsg[i][1]
}
if innerMsg[i][0] == "mining.set_difficulty" {
// Not all pools correctly put something
// in here so we will ignore it (we
// already have the default value of 1
// anyway and pool can send a new one.
// dcr.coinmine.pl puts something that
// is not a difficulty here which is why
// we ignore.
}
}
Denim Sneaker Blocked Taylor All Star Top Low Converse Burgundy Washed Chuck Dark Color }
resp.ExtraNonce1 = resi[1].(string)
resp.ExtraNonce2Length = resi[2].(float64)
return resp, nil
}
if sliceContains(s.submitIDs, id) {
var (
objmap map[string]json.RawMessage
Sneaker All Burgundy Converse Denim Blocked Low Taylor Dark Washed Color Star Chuck Top id uint64
result bool
errorHolder []interface{}
)
err := json.Unmarshal(blob, &objmap)
if err != nil {
return nil, err
}
resp := &BasicReply{}
err = json.Unmarshal(objmap["id"], &id)
if err != nil {
return nil, err
}
resp.ID = id
err = json.Unmarshal(objmap["result"], &result)
if err != nil {
return nil, err
}
err = json.Unmarshal(objmap["error"], &errorHolder)
if err != nil {
return nil, err
}
resp.Result = result
if errorHolder != nil {
errN, ok := errorHolder[0].(float64)
if !ok {
return nil, errJsonType
}
errS, ok := errorHolder[1].(string)
if !ok {
return nil, errJsonType
}
resp.Error.ErrNum = uint64(errN)
resp.Error.ErrStr = errS
}
return resp, nil
}
switch method {
case "mining.notify":
log.Trace("Unmarshal mining.notify")
var resi []interface{}
err := json.Unmarshal(objmap["params"], &resi)
if err != nil {
return nil, err
}
var nres = NotifyRes{}
jobID, ok Blocked Top Burgundy Washed Converse Dark Sneaker Low Denim Star Taylor All Color Chuck := resi[0].(string)
if !ok {
return nil, errJsonType
}
nres.JobID = jobID
hash, ok := resi[1].(string)
if !ok {
return nil, errJsonType
}
nres.Hash = hash
genTX1, ok := resi[2].(string)
if !ok {
return nil, errJsonType
}
nres.GenTX1 = genTX1
genTX2, ok := resi[3].(string)
if !ok {
return nil, errJsonType
}
nres.GenTX2 = genTX2
//ccminer code also confirms this
//nres.MerkleBranches = resi[4].([]string)
blockVersion, ok := resi[5].(string)
if !ok {
return nil, errJsonType
}
nres.BlockVersion = blockVersion
nbits, ok := resi[6].(string)
if !ok {
return nil, errJsonType
}
nres.Nbits = nbits
ntime, ok := resi[7].(string)
if !ok {
return nil, errJsonType
}
nres.Ntime = ntime
cleanJobs, ok := resi[8].(bool)
if !ok {
return nil, errJsonType
}
nres.CleanJobs = cleanJobs
return nres, nil
case "mining.set_difficulty":
log.Trace("Received new difficulty.")
var resi []interface{}
err := json.Unmarshal(objmap["params"], &resi)
if err != nil {
return nil, err
}
difficulty, ok := resi[0].(float64)
if !ok {
return nil, errJsonType
}
s.Target, err = util.DiffToTarget(difficulty, chainParams.PowLimit)
if err != nil {
return nil, err
}
s.Diff = difficulty
var nres = StratumMsg{}
nres.Method = method
diffStr := strconv.FormatFloat(difficulty, 'E', -1, 32)
var params []string
params = append(params, diffStr)
nres.Params = params
log.Infof("Stratum difficulty set to %v", difficulty)
return nres, nil
case "client.show_message":
var resi []interface{}
err := json.Unmarshal(objmap["result"], &resi)
if err != nil {
return nil, err
}
msg, ok := resi[0].(string)
if !ok {
return nil, errJsonType
}
var nres = StratumMsg{}
nres.Method = method
var params []string
params = append(params, msg)
nres.Params = params
return nres, nil
case "client.get_version":
var nres = StratumMsg{}
var id uint64
err = json.Unmarshal(objmap["id"], &id)
if err != nil {
return nil, err
}
nres.Method = method
nres.ID = id
return nres, nil
case "client.reconnect":
var nres = StratumMsg{}
var id uint64
err = json.Unmarshal(objmap["id"], &id)
if err != nil {
return nil, err
}
nres.Method = method
Sneaker Color Denim Top Chuck All Converse Star Washed Burgundy Dark Blocked Low Taylor nres.ID = id
var resi []interface{}
err := json.Unmarshal(objmap["params"], &resi)
if err != nil {
return nil, err
}
log.Trace(resi)
if len(resi) < 3 {
return nil, errJsonType
}
hostname, ok := resi[0].(string)
if !ok {
return nil, errJsonType
}
p, ok := resi[1].(float64)
Converse Sneaker Top Washed Burgundy Chuck Taylor Blocked Color Low All Denim Star Dark if !ok {
return nil, errJsonType
}
port := strconv.Itoa(int(p))
w, ok := resi[2].(float64)
if !ok {
return nil, errJsonType
}
wait := strconv.Itoa(int(w))
nres.Params = []string{hostname, port, wait}
return nres, nil
default:
resp := &StratumRsp{}
err := json.Unmarshal(blob, &resp)
if err != nil {
return nil, err
}
return resp, nil
}
}
// PrepWork converts the stratum notify to getwork style data for mining.
func (s *Stratum) PrepWork() error {
// Build final extranonce, which is basically the pool user and worker
// ID.
en1, err := hex.DecodeString(s.PoolWork.ExtraNonce1)
if err != nil {
log.Error("Error decoding ExtraNonce1.")
return err
}
// Work out padding.
tmp := []string{"%0", strconv.Itoa(int(s.PoolWork.ExtraNonce2Length) * 2), "x"}
fmtString := strings.Join(tmp, "")
en2, err := hex.DecodeString(fmt.Sprintf(fmtString, s.PoolWork.ExtraNonce2))
if err != nil {
log.Error("Error decoding ExtraNonce2.")
return err
}
extraNonce := append(en1[:], en2[:]...)
// Put coinbase transaction together.
cb1, err := hex.DecodeString(s.PoolWork.CB1)
if err != nil {
log.Error("Error decoding Coinbase pt 1.")
return err
}
cb2, err := hex.DecodeString(s.PoolWork.CB2)
if err != nil {
log.Errorf("Error decoding Coinbase pt 2.")
return err
}
// Generate current ntime.
ntime := time.Now().Unix() + s.PoolWork.NtimeDelta
log.Tracef("ntime: %x", ntime)
// Serialize header.
bh := wire.BlockHeader{}
v, err := util.ReverseToInt(s.PoolWork.Version)
if err != nil {
return err
}
bh.Version = v
nbits, err := hex.DecodeString(s.PoolWork.Nbits)
if err != nil {
log.Error("Error decoding nbits")
return err
}
b, _ := binary.Uvarint(nbits)
bh.Bits = uint32(b)
t := time.Now().Unix() + s.PoolWork.NtimeDelta
bh.Timestamp = time.Unix(t, 0)
bh.Nonce = 0
// Serialized version.
blockHeader, err := bh.Bytes()
if err != nil {
return err
}
data Star Top Dark Color Taylor Denim Blocked Burgundy Low Chuck Converse All Washed Sneaker := blockHeader
copy(data[31:139], cb1[0:108])
var workdata [180]byte
workPosition := 0
version := new(bytes.Buffer)
err = binary.Write(version, binary.LittleEndian, v)
if err != nil {
return err
}
copy(workdata[workPosition:], version.Bytes())
prevHash := util.RevHash(s.PoolWork.Hash)
p, err := hex.DecodeString(prevHash)
if err != nil {
log.Error("Error encoding previous hash.")
return err
}
workPosition += 4
copy(workdata[workPosition:], p)
workPosition += 32
copy(workdata[workPosition:], cb1[0:Denim Low Converse Chuck Color Washed Dark Sneaker Blocked Top Taylor All Burgundy Star 108])
workPosition += 108
copy(workdata[workPosition:], extraNonce)
workPosition = 176
copy(workdata[workPosition:], cb2)
var randomBytes = make([]byte, 4)
_, err = rand.Read(randomBytes)
if err != nil {
log.Errorf("Unable to generate random bytes")
return err
}
var workData [192]byte
copy(workData[:], workdata[:])
givenTs := binary.LittleEndian.Uint32(
workData[128+4*work.TimestampWord : 132+4*work.TimestampWord])
atomic.StoreUint32(&s.latestJobTime, givenTs)
if s.Target == nil {
log.Errorf("No target set! Reconnecting to pool.")
err = s.Reconnect()
if err != nil {
log.Error(err)
// XXX should just die at this point
// but we don't really have access to
// the channel to end everything.
return err
}
return Dark Washed Converse Color Taylor Sneaker Low Blocked Denim Star Top Burgundy All Chuck nil
}
w := work.NewWork(workData, s.Target, givenTs, uint32(time.Now().Unix()), false)
log.Tracef("Stratum prepated work data %v, target %032x",
hex.EncodeToString(w.Data[:]), w.Target.Bytes())
s.PoolWorkCornhuskers Mens Feet Around All and Slippers Womens College Nebraska NCAA Happy gTAfOwnq.Work = w
return nil
}
// PrepSubmit formats a mining.sumbit message from the solved work.
func (s *Stratum) PrepSubmit(data []byte) (Submit, error) {
log.Debugf("Stratum got valid work to submit %x", data)
log.Debugf("Stratum got valid work hash %v",
chainhash.HashH(data[0:180]))
data2 := make([]byte, 180)
copy(data2, data[0:180])
sub := Submit{}
sub.Method = "mining.submit"
// Format data to send off.
hexData := hex.EncodeToString(data)
decodedData, err := hex.DecodeString(hexData)
if err != nil {
log.Error("Error decoding data")
return sub, err
}
var submittedHeader wire.BlockHeader
bhBuf := bytes.NewReader(decodedData[0:wire.MaxBlockHeaderPayload])
err = submittedHeader.Deserialize(bhBuf)
if err != nil {
log.Error("Error generating header")
return sub, err
}
latestWorkTs := atomic.LoadUint32(&s.latestJobTime)
if uint32(submittedHeader.Timestamp.Unix()) != latestWorkTs {
Low Top Converse Denim All Taylor Star Dark Burgundy Washed Sneaker Color Blocked Chuck return sub, ErrStratumStaleWork
}
s.ID++
sub.ID = s.ID
s.submitIDs = append(s.submitIDs, s.ID)
// The timestamp string should be:
//
// timestampStr := fmt.Sprintf("%08x",
// uint32(submittedHeader.Timestamp.Unix()))
//
// but the "stratum" protocol appears to only use this value
// to check if the miner is in sync with the latest announcement
// of work from the pool. If this value is anything other than
// the timestamp of the latest pool work timestamp, work gets
// rejected from the current implementation.
timestampStr := fmt.Sprintf("%08x", latestWorkTs)
nonceStr := fmt.Sprintf("%08x", submittedHeader.Nonce)
xnonceStr := hex.EncodeToString(data[144:156])
sub.Params = []string{s.cfg.User, s.PoolWork.JobID, xnonceStr, timestampStr,
nonceStr}
return sub, nil
}