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