m2pool_core/internal/server/enx/enx.go

273 lines
7.6 KiB
Go
Raw Normal View History

2025-04-10 07:27:24 +00:00
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秒没获取到任务发送退出信号
}