273 lines
7.6 KiB
Go
273 lines
7.6 KiB
Go
|
package enx
|
|||
|
|
|||
|
import (
|
|||
|
"bytes"
|
|||
|
"encoding/binary"
|
|||
|
"encoding/hex"
|
|||
|
"encoding/json"
|
|||
|
"fmt"
|
|||
|
"pool/internal/msg"
|
|||
|
"pool/internal/server/coin"
|
|||
|
"pool/internal/stratum"
|
|||
|
"pool/internal/utility"
|
|||
|
|
|||
|
"github.com/btcsuite/btcd/wire"
|
|||
|
"go.uber.org/zap"
|
|||
|
)
|
|||
|
|
|||
|
const SERVER_ENX_VERSION string = "enx v1.15.2"
|
|||
|
|
|||
|
type ServerEnxContext struct {
|
|||
|
ServerCtx *coin.ServerContext
|
|||
|
logg *zap.Logger
|
|||
|
Job msg.StratumJob
|
|||
|
}
|
|||
|
|
|||
|
var logg *zap.Logger
|
|||
|
var ServerEnxCtx ServerEnxContext
|
|||
|
|
|||
|
// headerHash:本身的pow计算结果,收到后根据nonce和timestamp重新计算该值,确保该值正确
|
|||
|
// headerHash本身可以通过计算得出难度
|
|||
|
func handle_submit(miner *coin.MinerObj, id float64, miner_user string, job_id string, headerHash string, ntime string, nonce string) (bool, bool, bool) {
|
|||
|
var submit_item coin.BlockMsg
|
|||
|
/*var user_blk_item coin.UserBlockMsg*/
|
|||
|
var pool_blk_item coin.PoolBlkMsg
|
|||
|
|
|||
|
var blk_detail_height int64
|
|||
|
var blk_detail_hash string
|
|||
|
var blk_detail_success bool
|
|||
|
var blk_detail_miner_diff float64
|
|||
|
var blk_detail_pool_diff float64
|
|||
|
|
|||
|
if miner.Authorized != true {
|
|||
|
miner.ErrOthers = miner.ErrOthers + 1
|
|||
|
stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNAUTH_WORKER)
|
|||
|
stratum.Send_reconnect_msg(miner)
|
|||
|
return false, false, false
|
|||
|
}
|
|||
|
var new_found bool = false
|
|||
|
var ack stratum.Submit_ack
|
|||
|
ack.ID = id
|
|||
|
ack.Result = true
|
|||
|
//logg.Warn("[server]", zap.String("user", miner.User), zap.String("miner", miner.Miner))
|
|||
|
//logg.Debug("[server]", zap.Float64("id", id), zap.String("job_id", job_id))
|
|||
|
//logg.Debug("[server]", zap.String("nonce2", nonce2), zap.String("ntime", ntime), zap.String("nonce", nonce))
|
|||
|
//stratum.UpdateJobs(miner)
|
|||
|
v, ok := miner.Jobs.Load(job_id)
|
|||
|
if ok {
|
|||
|
job := v.(msg.StratumJob)
|
|||
|
if job.Height < miner.CurHeight-1 {
|
|||
|
ack.Result = false
|
|||
|
stratum.Handle_exception(miner, id, stratum.MINER_ERR_STALED_JOB)
|
|||
|
miner.ErrStaleds = miner.ErrStaleds + 1
|
|||
|
return false, false, false
|
|||
|
}
|
|||
|
|
|||
|
if miner.LastNonce != nonce {
|
|||
|
miner.LastNonce = nonce
|
|||
|
if miner.ZlogInit {
|
|||
|
miner.Zlog.Info().Msg("height " + fmt.Sprintf("%d", job.Height) + " target " + job.Target + " extra1 " + job.Extranonce1 + " size " + fmt.Sprintf("%d", job.Extranonce2_size) + " " + miner.User + "." + miner.Miner)
|
|||
|
}
|
|||
|
}
|
|||
|
vb := make([]byte, 4)
|
|||
|
binary.LittleEndian.PutUint32(vb, uint32(job.Version))
|
|||
|
vBuffer := bytes.NewBuffer(vb)
|
|||
|
binary.Read(vBuffer, binary.BigEndian, &(miner.Version))
|
|||
|
|
|||
|
job.Nonce = nonce
|
|||
|
job.Extranonce2 = headerHash
|
|||
|
|
|||
|
var calc_hash []byte
|
|||
|
var header wire.BlockHeader
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 构造提交至节点的区块
|
|||
|
func Produce_block_submit(miner *coin.MinerObj, header wire.BlockHeader, job *msg.StratumJob, PowHash string, SubIdx int64) {
|
|||
|
}
|
|||
|
|
|||
|
// server-->miner
|
|||
|
func enx_parse_miner_notify(miner *coin.MinerObj, msg msg.StratumJob) int {}
|
|||
|
|
|||
|
func Init(server *coin.ServerContext) {
|
|||
|
ServerEnxCtx.ServerCtx = server
|
|||
|
logg = server.Logg
|
|||
|
logg.Info("[server]", zap.String("server_mona_version", SERVER_ENX_VERSION))
|
|||
|
coin.Init_diff_db()
|
|||
|
}
|
|||
|
|
|||
|
func Start() {
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
func Stop() {
|
|||
|
coin.DiffStop()
|
|||
|
}
|
|||
|
|
|||
|
func InitMiner(miner *coin.MinerObj) {}
|
|||
|
|
|||
|
func Handle_subscribe_enx(miner *coin.MinerObj, id float64, extranonce1 string) {
|
|||
|
stratum.Handle_subscribe(miner, id, extranonce1)
|
|||
|
}
|
|||
|
|
|||
|
func HandleMinerSubscribe(miner *coin.MinerObj, id float64, extranonce1 string, msg string) {
|
|||
|
Handle_subscribe_enx(miner, id, extranonce1)
|
|||
|
}
|
|||
|
|
|||
|
func HandleMinerAuth(miner *coin.MinerObj) {
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
func HandleMinerSubmit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) {
|
|||
|
|
|||
|
accept_ok, submit_ok, handle_ok := handle_submit(miner, id, miner_user, job_id, nonce2, ntime, nonce)
|
|||
|
return accept_ok, submit_ok, handle_ok
|
|||
|
}
|
|||
|
|
|||
|
func set_difficulty(miner *coin.MinerObj) {}
|
|||
|
|
|||
|
func SetDifficulty(miner *coin.MinerObj) {
|
|||
|
set_difficulty(miner)
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
id: int, method: string, params:[string(jobid), string(headerHash, 32 byte serialized header, 8 bytes timestamp)]
|
|||
|
*/
|
|||
|
func EnxNotify(miner *coin.MinerObj) {
|
|||
|
miner.TxLock.Lock()
|
|||
|
if !((miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING)) {
|
|||
|
miner.TxLock.Unlock()
|
|||
|
return
|
|||
|
}
|
|||
|
miner.TxLock.Unlock()
|
|||
|
if miner.DifficultyNext > -1 {
|
|||
|
ratio := miner.DifficultyNext / miner.Difficulty
|
|||
|
if ratio > 1.1 || ratio < 0.9 {
|
|||
|
miner.Difficulty = miner.DifficultyNext
|
|||
|
miner.DifficultyNext = -1
|
|||
|
//Set_difficulty(miner)
|
|||
|
miner.Server.CoinCtx.SetDifficulty(miner)
|
|||
|
} else {
|
|||
|
miner.DifficultyNext = -1
|
|||
|
}
|
|||
|
}
|
|||
|
miner.TxLock.Lock()
|
|||
|
//log.Println("[server]extra1, id", miner.Job.Extranonce1, miner.Job.Job_id, miner.MinerId)
|
|||
|
var params [9]interface{}
|
|||
|
var tlist []string = make([]string, 0)
|
|||
|
idb := make([]byte, 4)
|
|||
|
binary.BigEndian.PutUint32(idb, miner.JobId)
|
|||
|
miner.Job.Job_id = hex.EncodeToString(idb)
|
|||
|
params[0] = miner.Job.Job_id
|
|||
|
if len(miner.Job.PrevblockS) > 0 {
|
|||
|
params[1] = miner.Job.PrevblockBig
|
|||
|
} else {
|
|||
|
p_big := utility.Convert_big_endian(miner.Job.Prevblock.CloneBytes())
|
|||
|
params[1] = hex.EncodeToString(p_big)
|
|||
|
}
|
|||
|
params[2] = miner.Job.Coinbase1
|
|||
|
params[3] = miner.Job.Coinbase2
|
|||
|
params[4] = tlist
|
|||
|
|
|||
|
miner.CurHeight = miner.Job.Height
|
|||
|
|
|||
|
if miner.Job.Transactions != nil {
|
|||
|
if len(*miner.Job.Transactions) > 0 {
|
|||
|
params[4] = miner.Job.Transactions
|
|||
|
|
|||
|
/*miner.Server.Logg.Error("[notify]", zap.String("coinbase1", miner.Job.Coinbase1), zap.String("coinbase2", miner.Job.Coinbase2), zap.Uint32("height", miner.Job.Height))
|
|||
|
for i := 0; i < len(*miner.Job.Transactions); i++ {
|
|||
|
miner.Server.Logg.Error("[notify]", zap.String("trans", (*miner.Job.Transactions)[i]))
|
|||
|
}*/
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
vb := make([]byte, 4)
|
|||
|
binary.LittleEndian.PutUint32(vb, uint32(miner.Job.Version))
|
|||
|
params[5] = hex.EncodeToString(vb)
|
|||
|
bb := make([]byte, 4)
|
|||
|
binary.LittleEndian.PutUint32(bb, miner.Job.Bits)
|
|||
|
params[6] = hex.EncodeToString(bb)
|
|||
|
t := miner.Job.Timestamp.Unix()
|
|||
|
if t > int64(^uint32(0)) {
|
|||
|
tb := make([]byte, 8)
|
|||
|
binary.LittleEndian.PutUint64(tb, uint64(t))
|
|||
|
params[7] = hex.EncodeToString(tb)
|
|||
|
} else {
|
|||
|
tb := make([]byte, 4)
|
|||
|
binary.LittleEndian.PutUint32(tb, uint32(t))
|
|||
|
params[7] = hex.EncodeToString(tb)
|
|||
|
}
|
|||
|
if miner.Reconnect {
|
|||
|
params[8] = true
|
|||
|
miner.Reconnect = false
|
|||
|
} else {
|
|||
|
params[8] = miner.Job.IsClean
|
|||
|
}
|
|||
|
miner.Job.JobDifficulty = miner.Difficulty
|
|||
|
|
|||
|
//miner.Jobs[miner.Job.Job_id] = miner.Job
|
|||
|
miner.Jobs.LoadOrStore(miner.Job.Job_id, miner.Job)
|
|||
|
|
|||
|
/*var entry coin.JobListEntry
|
|||
|
entry.Job_id = miner.Job.Job_id
|
|||
|
entry.Ts = time.Now()
|
|||
|
|
|||
|
miner.LockForJobs.Lock()
|
|||
|
miner.JobList.PushFront(entry)
|
|||
|
var removes string = ""
|
|||
|
if miner.JobList.Len() > int(coin.LOCAL_JOBS_TOTAL_SIZE) {
|
|||
|
e := miner.JobList.Back()
|
|||
|
entry := e.Value.(coin.JobListEntry)
|
|||
|
removes = entry.Job_id
|
|||
|
miner.JobList.Remove(e)
|
|||
|
}
|
|||
|
miner.LockForJobs.Unlock()
|
|||
|
if len(removes) > 0 {
|
|||
|
miner.Jobs.Delete(removes)
|
|||
|
}*/
|
|||
|
stratum.AddAndUpdateJob(miner)
|
|||
|
stratum.UpdateJobs(miner)
|
|||
|
|
|||
|
//miner.LastJobId = miner.Job.Job_id
|
|||
|
miner.JobId++
|
|||
|
|
|||
|
var msg stratum.Notify_msg
|
|||
|
msg.ID = nil
|
|||
|
msg.Method = "mining.notify"
|
|||
|
msg.Params = params
|
|||
|
body, err := json.Marshal(msg)
|
|||
|
if err != nil {
|
|||
|
miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error()))
|
|||
|
miner.TxLock.Unlock()
|
|||
|
return
|
|||
|
}
|
|||
|
var body_string = string(body) + "\n"
|
|||
|
err = stratum.Conn_tx(miner.Conn, []byte(body_string))
|
|||
|
if err != nil {
|
|||
|
//delete(miner.Server.Miners, miner.MinerId)
|
|||
|
//miner.Server.Miners.Delete(miner.MinerId)
|
|||
|
}
|
|||
|
//miner.Server.Logg.Debug("[server]", zap.String("tx", body_string))
|
|||
|
miner.TxLock.Unlock()
|
|||
|
|
|||
|
if miner.ZlogInit {
|
|||
|
miner.Zlog.Info().Msg(body_string)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func Notify(miner *coin.MinerObj) {
|
|||
|
EnxNotify(miner)
|
|||
|
}
|
|||
|
|
|||
|
func HandleJobMsg(server *coin.ServerContext, Msg []byte) {}
|
|||
|
|
|||
|
func IsMhsLow(miner *coin.MinerObj) bool {
|
|||
|
return miner.Mhs5M < 1
|
|||
|
}
|
|||
|
|
|||
|
func GetBlockInterval() int {
|
|||
|
return 30 // 30秒没获取到任务发送退出信号
|
|||
|
}
|