m2pool-core/internal/server/randomxT/randomxT.go

794 lines
27 KiB
Go
Raw Permalink 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.

// sha3x.go
package randomxT
import (
"strconv"
//"database/sql"
"encoding/binary"
"encoding/hex"
"encoding/json"
//"log"
//"math"
"math/big"
//"strings"
"fmt"
"pool/internal/msg"
"pool/internal/server/coin"
"pool/internal/server/dbif"
"pool/internal/stratum"
"pool/internal/utility"
"time"
_ "github.com/mattn/go-sqlite3"
"go.uber.org/zap"
)
const SERVER_RANDOMXT_VERSION string = "randomxt v0.1a"
type RandomxTBlockHeader struct {
Zero [3]byte
Nonce [8]byte
Header [32]byte
Algo byte
PowData [32]byte
}
func RandomxTBlockHeaderToBytes(miningHash string) []byte {
miningHashBytes, err := hex.DecodeString(miningHash)
if err != nil || len(miningHashBytes) != 32 {
return nil
}
out := make([]byte, 76)
copy(out[0:3], []byte{0x00, 0x00, 0x00})
copy(out[3:35], miningHashBytes)
// nonce 8 字节默认全 0无需手动赋值
out[43] = 0x02
// 最后 32 字节也默认全 0无需赋值
return out
}
type ServerRandomxContext struct {
ServerCtx *coin.ServerContext
logg *zap.Logger
RandomxTJob msg.RandomxTStratumJob
}
var logg *zap.Logger
var ServerSha3xCtx ServerRandomxContext
var vm *RandomXValidator
type RandomxTNotify_params_msg struct {
Algo string `json:"algo"` // "rx/0"
Blob string `json:"blob"`
Height uint32 `json:"height"`
Job_id string `json:"job_id"`
Target string `json:"target"`
SeedHash string `json:"seed_hash"`
Variant string `json:"variant"` // "rx/0"
}
type RandomxTNotify_msg struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params RandomxTNotify_params_msg `json:"params"`
}
func handle_submit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 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.RandomxTStratumJob)
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
}
//logg.Debug("[server]", zap.Uint64("ntime", nt), zap.Uint64("mintime", uint64(job.Mintime)), zap.Uint64("jobtime", jt_reverse))
/*if nt < uint64(job.Mintime) {
ack.Result = false
util.Handle_exception(miner, id, util.MINER_ERR_TIME_TOO_OLD)
} else if nt > jt_reverse+uint64(600) {
ack.Result = false
util.Handle_exception(miner, id, util.MINER_ERR_TIME_TOO_NEW)
} else */{
if (miner.LastNonce != nonce) || (miner.LastHeader != job.Header) {
miner.LastHeader = job.Header
miner.LastNonce = nonce
job.Nonce = nonce
job.Extranonce2 = nonce2
//logg.Debug("[server]", zap.Uint32("height", job.Height), zap.String("target", job.Target))
if miner.ZlogInit {
miner.Zlog.Info().Msg("height " + string(job.Height) + " target " + job.Target + " " + miner.User + "." + miner.Miner)
}
phb, _ := hex.DecodeString(job.Header)
nb, _ := hex.DecodeString(nonce)
// var calc_hash []byte
// var header RandomxTBlockHeader
// for i := 0; i < 8; i++ {
// header.Nonce[i] = nb[i]
// }
// for i := 0; i < 32; i++ {
// header.Header[i] = phb[i]
// }
// header.Algo = 1
// header := miner.Server.RandomxTJob.Header
submit_item.Header = hex.EncodeToString(phb)
calc_hash, _, err := vm.BuildPowHash(phb, nb)
if err != nil {
ack.Result = false
stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNKNOWN)
miner.ErrOthers = miner.ErrOthers + 1
return false, false, false
}
//logg.Debug("[server]", zap.String("hash in", submit_item.Header))
//calc_hash, header := util.BuildBlockHash(&(job), true, Build_PowHash)
//logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)) /*, zap.String("merkle root", hex.EncodeToString(merkle_root))*/)
if miner.ZlogInit {
miner.Zlog.Info().Msg("hash in " + submit_item.Header + " calc_hash " + hex.EncodeToString(calc_hash) + " " + miner.User + "." + miner.Miner)
}
submit_target := new(big.Int)
//submit_target.SetBytes(common.Reverse(calc_hash))
//hashs, _ := utility.ReverseS(hex.EncodeToString(calc_hash))
//hashb, _ := hex.DecodeString(hashs)
//submit_target.SetBytes(hashb)
submit_target.SetBytes(calc_hash)
/*logg.Debug("[server]", zap.String("pow", hex.EncodeToString(submit_target.Bytes())), zap.String("target", hex.EncodeToString(miner.Target.Bytes())))
if submit_target.Cmp(miner.Target) > 0 {*/
calc_diff := utility.Target2Diff(utility.Reverse(calc_hash))
//calc_diff := utility.Target2Diff(calc_hash)
//log.Printf("diff,calc_diff:%f difficulty:%f ", calc_diff, miner.Difficulty)
//logg.Warn("[server]", zap.String("user", miner.User+"."+miner.Miner), zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff))
if miner.ZlogInit {
miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " target diff " + fmt.Sprintf("%f", (miner.Difficulty)) + " submit diff " + fmt.Sprintf("%f", (calc_diff)))
}
//logg.Debug("[server]", zap.String("target", miner.Target.String()), zap.Any("bytes", miner.Target.Bytes()))
//logg.Info("[server]", zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff), zap.String("target", hex.EncodeToString(miner.Target.Bytes())))
//if calc_diff < miner.Difficulty {
if calc_diff < job.JobDifficulty {
//gpu protocol handler
/*for i := 0; i < 8; i++ {
temp_nonce := header.Nonce[8+i]
header.Nonce[8+i] = header.Nonce[i]
header.Nonce[i] = temp_nonce
}
submit_item.Header = hex.EncodeToString(Sha3xBlockHeaderToBytes(header))
calc_hash = BuildPowHash(header)
logg.Debug("[server]", zap.String("hash in", hex.EncodeToString(Sha3xBlockHeaderToBytes(header))))*/
//logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)) /*, zap.String("merkle root", hex.EncodeToString(merkle_root))*/)
//submit_target = new(big.Int)
/*submit_target.SetBytes(calc_hash)
calc_diff = utility.Target2Diff(calc_hash)
logg.Warn("[server]", zap.String("user", miner.User+"."+miner.Miner), zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff))
if calc_diff < miner.Difficulty {
*/
ack.Result = false
miner.ErrLowDiffs = miner.ErrLowDiffs + 1
stratum.Handle_exception(miner, id, stratum.MINER_ERR_LOW_DIF_SHARE)
return false, false, false
//}
}
//logg.Warn("[server]", zap.String("pow", hex.EncodeToString(submit_target.Bytes())), zap.String("target", hex.EncodeToString(miner.ServerTarget.Bytes())))
//submit_target.Text(16)
/*if submit_target.Cmp(miner.ServerTarget) <= 0 {*/
//log.Println("[server]server_target", miner.ServerTargetS)
//stb, _ := hex.DecodeString(miner.ServerTargetS)
stb, _ := hex.DecodeString(job.Target)
//logg.Info("[server]", zap.String("target", job.Target))
//server_diff := Target2Diff(common.Reverse(stb))
server_diff := utility.Target2Diff(utility.Reverse(stb))
//log.Printf("[server]server_diff %f", server_diff)
//logg.Info("[server]", zap.Float64("calc_diff", calc_diff), zap.Float64("miner.Difficulty", miner.Difficulty), zap.Float64("server_diff", server_diff))
//logg.Debug("[server]", zap.String("ServerTargetS", miner.ServerTargetS))
network_target := new(big.Int)
network_target.SetBytes(stb)
//logg.Info("[server]", zap.Float64("calc_diff", calc_diff), zap.Float64("miner.Difficulty", miner.Difficulty), zap.Float64("server_diff", server_diff))
//logg.Debug("[server]", zap.String("submit_target", hex.EncodeToString(submit_target.Bytes())), zap.String("network_target", hex.EncodeToString(network_target.Bytes())), zap.String("target", hex.EncodeToString(miner.ServerTarget.Bytes())), zap.Int("cmp", network_target.Cmp(submit_target)))
if miner.ZlogInit {
miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " calc_diff " + fmt.Sprintf("%f", (calc_diff)) + " miner.Difficulty " + fmt.Sprintf("%f", (miner.Difficulty)) + " server_diff " + fmt.Sprintf("%f", (server_diff)))
miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " submit_target " + hex.EncodeToString(submit_target.Bytes()) + " network_target " + hex.EncodeToString(network_target.Bytes()) + " target " + hex.EncodeToString(miner.ServerTarget.Bytes()) + " cmp " + fmt.Sprintf("%d", (network_target.Cmp(submit_target))))
}
submit_item.Hash = hex.EncodeToString(calc_hash)
submit_item.Target = hex.EncodeToString(miner.Target.Bytes())
submit_item.Submit_target = hex.EncodeToString(calc_hash)
submit_item.Height = int64(job.Height)
submit_item.Pow = hex.EncodeToString(calc_hash)
submit_item.Net_target = hex.EncodeToString(network_target.Bytes())
/*user_blk_item.Height = int64(job.Height)
user_blk_item.Hash = hex.EncodeToString(calc_hash)
user_blk_item.Pow = hex.EncodeToString(calc_hash)
user_blk_item.Net_target = hex.EncodeToString(network_target.Bytes())*/
pool_blk_item.Height = int64(job.Height)
pool_blk_item.Hash = hex.EncodeToString(calc_hash)
pool_blk_item.Pow = hex.EncodeToString(calc_hash)
pool_blk_item.Net_target = hex.EncodeToString(network_target.Bytes())
blk_detail_height = int64(job.Height)
blk_detail_hash = hex.EncodeToString(calc_hash)
blk_detail_success = false
//blk_detail_miner_diff = miner.Difficulty
blk_detail_miner_diff = job.JobDifficulty
blk_detail_pool_diff = miner.Server.RefDifficulty
if ack.Result == true {
/*if miner.CurHeight != 0 && miner.CurHeight == job.Height {
return
}*/
//if true {
if (calc_diff >= server_diff) || (network_target.Cmp(submit_target) >= 0) {
//if true {
miner.Server.SubIdx++
Produce_block_submit(miner /*header,*/, &job, submit_item.Hash, miner.Server.SubIdx)
miner.SubmitIndex++
miner.Submits = miner.Submits + 1
//miner.CurHeight = job.Height
new_found = true
}
if new_found && float64(miner.Server.Sha3xJob.U64target) <= calc_diff {
pool_blk_item.Submit = "y"
pool_blk_item.Success = false
pool_blk_item.Accepts = miner.Accepts
pool_blk_item.Rejects = miner.Rejects
pool_blk_item.Reward = 0
pool_blk_item.Fee = 0
pool_blk_item.Nonce = nonce
pool_blk_item.SubIdx = miner.Server.SubIdx
dbif.NotifyPoolBlkStatsDb2(miner.Server, &pool_blk_item)
}
}
} else {
miner.LastHeader = job.Header
miner.LastNonce = nonce
ack.Result = false
stratum.Handle_exception(miner, id, stratum.MINER_ERR_DUP_SHARE)
miner.ErrDuplicates = miner.ErrDuplicates + 1
return false, false, false
}
}
} else {
ack.Result = false
stratum.Handle_exception(miner, id, stratum.MINER_ERR_NOT_FOUND_JOB)
miner.ErrStaleds = miner.ErrStaleds + 1
return false, false, false
}
miner.LastJobId = job_id
ack.Error = nil
body, err := json.Marshal(ack)
if err != nil {
//logg.Error("[server]", zap.String("Marshal", err.Error()))
if miner.ZlogInit {
miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit Marshal " + err.Error())
}
miner.ErrOthers = miner.ErrOthers + 1
stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNKNOWN)
return false, false, false
}
var body_string = string(body) + "\n"
err = stratum.Conn_tx(miner.Conn, []byte(body_string))
if err != nil {
//miner.Server.Miners.Delete(miner.MinerId)
}
if miner.ZlogInit {
miner.Zlog.Info().Msg(body_string)
}
//logg.Debug("[server]", zap.String("tx", body_string))
miner.TxLock.Lock()
miner.Status = coin.MINER_STATUS_RUNNING
miner.TxLock.Unlock()
if ack.Result {
miner.Accepts += miner.Difficulty
miner.M5Accepts += miner.Difficulty
miner.VarDiffOpt.SubmitShares += miner.Difficulty
} else {
miner.Rejects += miner.Difficulty
}
now := time.Now()
if miner.Server.Config.Diff.Filter == "kalman" {
if ack.Result {
share_interval := now.Sub(miner.LastSubmitime).Seconds()
mhs := miner.Difficulty * share_interval
diff_next, kalman_p := miner.DiffHandler.Handler(miner.Difficulty, share_interval)
mhs_est := diff_next * miner.Server.Config.Diff.DiffAdjustInterval
ratio := diff_next / miner.Difficulty
if ratio > 0 {
if now.Sub(miner.StartSubmitTime).Seconds() > 180 {
if ratio >= 2 {
//miner.DifficultyNext = math.Ceil(diff_next*100) / 100
miner.DifficultyNext = diff_next * 10000000 / 10000000
} else if ratio <= 0.5 {
//miner.DifficultyNext = math.Ceil(diff_next*100) / 100
miner.DifficultyNext = diff_next * 10000000 / 10000000
} else {
}
} else {
//miner.DifficultyNext = math.Ceil(diff_next*100) / 100
miner.DifficultyNext = diff_next * 10000000 / 10000000
/*if ratio >= 1.1 {
miner.DifficultyNext = math.Ceil(diff_next*100) / 100
} else if ratio <= 0.8 {
miner.DifficultyNext = math.Ceil(diff_next*100) / 100
} else {
}*/
}
}
if miner.DifficultyNext > 0.0 {
if miner.DifficultyNext < miner.VarDiffOpt.MinDiff {
miner.DifficultyNext = miner.VarDiffOpt.MinDiff
} else if miner.DifficultyNext > miner.VarDiffOpt.MaxDiff {
miner.DifficultyNext = miner.VarDiffOpt.MaxDiff
}
}
//miner.VarDiffOpt.LastCalcTime = now
if miner.Server.Config.Diff.Dbg {
coin.New_diff_into_db(miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.Difficulty, diff_next, kalman_p, share_interval, mhs, mhs_est)
}
//log.Println("diff adjust", ratio, diff_next, miner.Difficulty, miner.DifficultyNext)
}
} else {
// submit time < DiffAdjustInterval,then up adjust diff
if now.Sub(miner.LastSubmitime).Seconds() < miner.Server.Config.Diff.DiffAdjustInterval {
if ack.Result {
if miner.VarDiffOpt.Uptimes++; miner.VarDiffOpt.Uptimes >= coin.DIFFICULTY_WAIT_TIMES {
coin.VarAdjustDifficulty(miner, coin.UP_DIFF)
miner.VarDiffOpt.LastCalcTime = now
}
}
} else {
miner.VarDiffOpt.Uptimes = 0
}
// submit time > 2 * DiffAdjustInterval,then down adjust diff
if now.Sub(miner.LastSubmitime).Seconds() > miner.Server.Config.Diff.DiffAdjustInterval*2 {
if ack.Result {
if miner.VarDiffOpt.Downtimes++; miner.VarDiffOpt.Downtimes >= coin.DIFFICULTY_WAIT_TIMES {
coin.VarAdjustDifficulty(miner, coin.DOWN_DIFF)
miner.VarDiffOpt.LastCalcTime = now
}
}
} else {
miner.VarDiffOpt.Downtimes = 0
}
}
if ack.Result {
miner.LastSubmitime = now
miner.VarDiffOpt.LastSubmitTime = now
}
var duration float64 = float64(now.Sub(miner.StartSubmitTime)) / 1000000000
if duration < 1 {
duration = 1
}
//diffOneShareHashesAvg := uint64(0x00000000FFFFFFFF)
diffOneShareHashesAvg := uint64(0xFFFFFFFFFFFFFFFF)
miner.AverageHashrate = miner.Accepts * float64(diffOneShareHashesAvg) / duration / 1000000
var m5_duration float64 = float64(now.Sub(miner.M5SubmitTime)) / 1000000000
if m5_duration >= float64(time.Minute*5)/1000000000 {
miner.M5SubmitTime = now
miner.M5Hashrate = miner.M5Accepts * float64(diffOneShareHashesAvg) / m5_duration / 1000000
//logg.Info("[server]", zap.Float64("Accepts", miner.Accepts), zap.Float64("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate))
miner.M5Accepts = 0
}
//logg.Warn("[server]", zap.Float64("Accepts", miner.Accepts), zap.Float64("Rejects", miner.Rejects))
//logg.Info("[server]", zap.Float64("TargetShares", miner.VarDiffOpt.TargetShares), zap.Float64("MinShares", miner.VarDiffOpt.MinShares), zap.Float64("MaxShares", miner.VarDiffOpt.MaxShares), zap.Float64("SubmitShares", miner.VarDiffOpt.SubmitShares))
//logg.Warn("[server]", zap.Float64("reject rate", miner.Rejects/(miner.Accepts+miner.Rejects)), zap.Float64("Hashrate(MH/S)", miner.AverageHashrate))
//logg.Warn("[server]", zap.Float64("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate))
if miner.ZlogInit {
miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit M5Accepts " + fmt.Sprintf("%f", (miner.M5Accepts)) + " M5Hashrate(MH/S) " + fmt.Sprintf("%f", (miner.M5Hashrate)))
}
//logg.Info("[server]", zap.Float64("LastCalcTime", float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000))
//calc acutal submit shares period of time, then compare with target shares and adjust diff
if miner.Server.Config.Diff.Filter == "kalman" {
} else {
if float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000 >= miner.VarDiffOpt.AdjustTime {
coin.VarAdjustDifficulty(miner, coin.UPDATE_DIFF)
miner.VarDiffOpt.LastCalcTime = now
}
}
if ack.Result {
submit_item.Success = false
if new_found {
submit_item.Submit = "y"
submit_item.SubIdx = miner.Server.SubIdx
} else {
submit_item.Submit = "n"
submit_item.SubIdx = -1
}
submit_item.Accepts = miner.Accepts
submit_item.Total_accepts = miner.Accepts
submit_item.Rejects = miner.Rejects
submit_item.Total_rejects = miner.Rejects
submit_item.Reward = 0
submit_item.Fee = 0
submit_item.Nonce = nonce
//dbif.NotifyMinerDb2(miner, &submit_item)
dbif.NotifyBlkDetailDb(miner, blk_detail_height, blk_detail_hash, blk_detail_success, blk_detail_miner_diff, blk_detail_pool_diff, nonce, submit_item.SubIdx)
return true, new_found, true
}
return false, false, true
}
func Produce_block_submit(miner *coin.MinerObj /*header Sha3xBlockHeader,*/, job *msg.RandomxTStratumJob, PowHash string, SubIdx int64) {
var nm msg.BlockSha3xMsg
nm.Id = job.Id
nm.Header = job.Header
//nm.Nonce = job.Nonce
noncer, _ := stratum.ReverseHexStringByByte(job.Nonce)
nonce, err := strconv.ParseUint(noncer, 16, 64)
nm.Nonce = nonce
nm.Pow = PowHash
nm.SubIdx = SubIdx
nm.User = miner.User
nm.Miner = miner.Miner
nm.Index = fmt.Sprint(miner.MinerIndex)
body, err := json.Marshal(nm)
if err != nil {
logg.Error("[server]", zap.String("failed to Marshal job", err.Error()))
return
}
blk := string(body)
//Add Height
/*heightb := utility.Uint32ToByte(job.Height)
heights := hex.EncodeToString(heightb)
blk += heights
var Height uint32 = utility.ByteToUint32(heightb)*/
nm.Height = (uint64)(job.Height)
logg.Warn("[server]", zap.Uint32("Height", job.Height))
//Add SubmitIndex
/*indexb := utility.Uint32ToByte(miner.SubmitIndex)
indexs := hex.EncodeToString(indexb)
blk += indexs
var SubmitIndex uint32 = utility.ByteToUint32(indexb)*/
nm.SubmitIdx = (uint64)(miner.SubmitIndex)
logg.Info("[server]", zap.Uint32("SubmitIndex", miner.SubmitIndex))
logg.Info("[server]", zap.String("blk", blk))
if miner.Server.PubCh == nil {
miner.Server.PubCh = utility.InitZmqPub(miner.Server.Config.Zmq.Pub)
}
if miner.Server.PubCh != nil {
//miner.Server.PubCh.SendChan <- [][]byte{[]byte("blksha3x"), []byte(blk)}
err := miner.Server.PubCh.SendMessage([][]byte{[]byte("blkrandomxt"), []byte(blk)})
if err != nil {
miner.Server.PubCh.Destroy()
miner.Server.PubCh = nil
logg.Info("[server]", zap.String("blk", err.Error()))
} else {
logg.Info("[server]", zap.String("blk", "sent"))
}
}
}
// server-->miner
func randomxT_parse_miner_notify(miner *coin.MinerObj, msg msg.RandomxTStratumJob) int {
if miner.Sha3xJob.Height != msg.Height {
miner.Job.IsClean = true
}
miner.RandomxTJob = msg
miner.RandomxTJob.Extranonce1 = miner.Job.Extranonce1
miner.Job.Extranonce2_size = msg.Extranonce2_size
//miner.Server.Logg.Info("[server]", zap.Int32("miner.Version", miner.Version), zap.Int32("msg.Version", msg.Version))
return 1
}
func Init(server *coin.ServerContext) {
ServerSha3xCtx.ServerCtx = server
logg = server.Logg
logg.Info("[server]", zap.String("server_version", SERVER_RANDOMXT_VERSION))
coin.Init_diff_db()
}
func Start() {
}
func Stop() {
coin.DiffStop()
}
func InitMiner(miner *coin.MinerObj) {
miner.RandomxTJob = miner.Server.RandomxTJob
miner.RandomxTJob.Extranonce1 = miner.Job.Extranonce1
server_target := new(big.Int)
t_bytes, err := hex.DecodeString(miner.NexaJob.Target)
if err != nil {
logg.Error("[server]", zap.String("DecodeString", err.Error()))
return
}
//server_target.SetBytes(common.Reverse(t_bytes))
server_target.SetBytes(t_bytes)
miner.ServerTarget = server_target
miner.ServerTargetS = miner.Server.SJob.Target
}
func Handle_subscribe_sha3x(miner *coin.MinerObj, id float64, extranonce1 string) {
}
func HandleMinerSubscribe(miner *coin.MinerObj, id float64, extranonce1 string, msg string) {
}
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) {
//nonce_str, _ := stratum.ReverseHexStringByByte(nonce)
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 SetDifficulty(miner *coin.MinerObj) {
stratum.Set_difficulty(miner)
}
func Sha3xNotify(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
stratum.Set_difficulty(miner)
//logg.Info("[gbt]", zap.Float64("update Diff", miner.Difficulty))
} else {
miner.DifficultyNext = -1
}
}
miner.TxLock.Lock()
//log.Println("[server]extra1, id", miner.Job.Extranonce1, miner.Job.Job_id, miner.MinerId)
var msg RandomxTNotify_msg
idb := make([]byte, 4)
binary.BigEndian.PutUint32(idb, miner.JobId)
miner.Job.Job_id = hex.EncodeToString(idb)
msg.Params.Algo = "rx/0"
msg.Params.Variant = "rx/0"
msg.Params.SeedHash = miner.Server.RandomxTJob.SeedHash
msg.Params.Job_id = miner.Job.Job_id
msg.Params.Blob = miner.RandomxTJob.Header
msg.Params.Height = miner.RandomxTJob.Height
target_new, _ := utility.DiffToTarget(miner.Difficulty)
target_str := fmt.Sprintf("%064x", target_new.Bytes())
target_strr, strerr := stratum.ReverseHexStringByByte(target_str)
if strerr != nil {
println("ReverseHexStringByByte", strerr.Error())
}
//println("target=", target_str, "r=", target_strr)
msg.Params.Target = target_strr[48:]
miner.CurHeight = miner.RandomxTJob.Height
miner.RandomxTJob.JobDifficulty = miner.Difficulty
miner.Jobs.LoadOrStore(miner.Job.Job_id, miner.RandomxTJob)
/*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 body []byte
var err error
msg.Jsonrpc = "2.0"
msg.Method = "job"
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) {
Sha3xNotify(miner)
}
func formatUint64ToHexWithPadding(val uint64) string {
hexStr := fmt.Sprintf("%016x", val)
if len(hexStr) < 64 {
paddingLen := 64 - len(hexStr)
hexStr += string(make([]byte, paddingLen))
for i := len(hexStr) - paddingLen; i < 64; i++ {
hexStr = hexStr[:i] + "0" + hexStr[i+1:]
}
}
return hexStr
}
var last_seed_hash string = ""
func HandleJobMsg(server *coin.ServerContext, Msg []byte) {
vm = &RandomXValidator{} // 初始化vm虚拟机指针防止出现空指针报错
var result msg.RandomxTStratumJob
server.Logg.Warn("[server]", zap.String("receive", "job"))
if err := json.Unmarshal(Msg, &result); err != nil {
server.Logg.Error("[server]", zap.String("Unmarshal", err.Error()))
return
}
result.Target = formatUint64ToHexWithPadding(result.U64target)
if last_seed_hash != result.SeedHash {
seed_hash_byte, err := hex.DecodeString(result.SeedHash)
if err != nil {
server.Logg.Error("[server]", zap.String("DecodeString", err.Error()))
return
}
vm, err = NewRandomXValidator(seed_hash_byte)
if err != nil {
server.Logg.Error("[server]", zap.String("NewRandomXValidator", err.Error()))
return
}
last_seed_hash = result.SeedHash
}
//target_new, _ := utility.DiffToTarget((float64)(result.U64target))
//target_str := fmt.Sprintf("%064x", target_new.Bytes())
//result.Target = target_str
server.RandomxTJob = msg.RandomxTStratumJob(result)
blobByte := RandomxTBlockHeaderToBytes(server.RandomxTJob.Header)
server.RandomxTJob.Header = hex.EncodeToString(blobByte)
logg.Debug("[gbt]", zap.String("Target", server.RandomxTJob.Target))
server.RandomxTJob.Extranonce2_size = 8
server.SJob.Extranonce2_size = 8
logg.Debug("[gbt]", zap.Uint32("Height", server.RandomxTJob.Height), zap.String("Target", server.RandomxTJob.Target), zap.String("Header", server.RandomxTJob.Header) /*, zap.Uint64("Timastamp", server.Sha3xJob.CurTime)*/)
targetb, _ := hex.DecodeString(server.RandomxTJob.Target)
logg.Debug("[gbt]", zap.Uint64("Id", server.RandomxTJob.Id), zap.Float64("network diff", utility.Target2Diff(utility.Reverse(targetb))))
server.NetHight = uint64(server.RandomxTJob.Height)
server.NetTarget = server.RandomxTJob.Target
server.Miners.Range(func(k, v interface{}) bool {
if v != nil {
m, ok := v.(*(coin.MinerObj))
if ok {
if m != nil {
server.Logg.Info("[server]", zap.String("lock", "start"))
m.TxLock.Lock()
status := m.Status
cmd := randomxT_parse_miner_notify(m, server.RandomxTJob)
m.TxLock.Unlock()
server.Logg.Info("[server]", zap.String("lock", "end"))
var need_notify bool = true
if time.Now().Sub(m.ConnSetupTime) >= time.Duration(coin.CONN_EXPIRED_TIME)*time.Second {
if (status != coin.MINER_STATUS_RUNNING) && (status != coin.MINER_STATUS_AUTHORIZED) {
//m.Conn.Close()
need_notify = false
}
}
if need_notify {
switch cmd {
case 0: //extranonce 1 and extranonce2 size
//TODO
case 1: //notify
Sha3xNotify(m)
}
}
}
}
}
return true
})
}
func IsMhsLow(miner *coin.MinerObj) bool {
if miner.Mhs5M < 1 {
return true
}
return false
}
func GetBlockInterval() int {
return 3600
}