m2pool_core/internal/server/enx/enx.go

273 lines
7.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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秒没获取到任务发送退出信号
}