Kevacoin stratum server for solo-mining
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
1.9 KiB

10 years ago
package stratum
import (
"bytes"
"encoding/binary"
"encoding/hex"
"log"
"sync/atomic"
"../../cnutil"
)
type BlockTemplate struct {
Blob string
Difficulty int64
Height int64
ReservedOffset int
PrevHash string
Buffer []byte
ExtraNonce uint32
}
func (b *BlockTemplate) nextBlob() (string, uint32) {
// Preventing race by using atomic op here
// No need for using locks, because this is only one write to BT and it's atomic
extraNonce := atomic.AddUint32(&b.ExtraNonce, 1)
extraBuff := new(bytes.Buffer)
binary.Write(extraBuff, binary.BigEndian, extraNonce)
blobBuff := make([]byte, len(b.Buffer))
copy(blobBuff, b.Buffer) // We never write to this buffer to prevent race
copy(blobBuff[b.ReservedOffset:], extraBuff.Bytes())
blob := cnutil.ConvertBlob(blobBuff)
return hex.EncodeToString(blob), extraNonce
}
func (s *StratumServer) fetchBlockTemplate() bool {
reply, err := s.rpc.GetBlockTemplate(8, s.config.Address)
if err != nil {
log.Printf("Error while refreshing block template: %s", err)
return false
}
t := s.currentBlockTemplate()
if t.PrevHash == reply.PrevHash {
// Fallback to height comparison
if len(reply.PrevHash) == 0 && reply.Height > t.Height {
log.Printf("New block to mine at height %v, diff: %v", reply.Height, reply.Difficulty)
} else {
return false
}
} else {
log.Printf("New block to mine at height %v, diff: %v, prev_hash: %s", reply.Height, reply.Difficulty, reply.PrevHash)
}
newTemplate := BlockTemplate{
Blob: reply.Blob,
Difficulty: reply.Difficulty,
Height: reply.Height,
PrevHash: reply.PrevHash,
ReservedOffset: reply.ReservedOffset,
}
newTemplate.Buffer, _ = hex.DecodeString(reply.Blob)
copy(newTemplate.Buffer[reply.ReservedOffset+4:reply.ReservedOffset+7], s.instanceId)
newTemplate.ExtraNonce = 0
s.blockTemplate.Store(&newTemplate)
return true
}