762 lines
26 KiB
Go
762 lines
26 KiB
Go
|
// 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_SHA3X_VERSION string = "sha3x v0.1a"
|
||
|
|
||
|
type Sha3xBlockHeader struct {
|
||
|
Nonce [8]byte
|
||
|
Header [32]byte
|
||
|
Algo byte
|
||
|
}
|
||
|
|
||
|
func Sha3xBlockHeaderToBytes(h Sha3xBlockHeader) []byte {
|
||
|
out := make([]byte, 8+32+1)
|
||
|
for i := 0; i < 8; i++ {
|
||
|
out[i] = h.Nonce[i]
|
||
|
}
|
||
|
for i := 0; i < 32; i++ {
|
||
|
out[8+i] = h.Header[i]
|
||
|
}
|
||
|
out[8+32] = h.Algo
|
||
|
|
||
|
return out
|
||
|
}
|
||
|
|
||
|
type ServerSha3xContext struct {
|
||
|
ServerCtx *coin.ServerContext
|
||
|
logg *zap.Logger
|
||
|
|
||
|
Sha3xJob msg.Sha3xStratumJob
|
||
|
}
|
||
|
|
||
|
var logg *zap.Logger
|
||
|
var ServerSha3xCtx ServerSha3xContext
|
||
|
|
||
|
type Sha3xNotify_params_msg struct {
|
||
|
Algo string `json:"algo"`
|
||
|
Blob string `json:"blob"`
|
||
|
Height uint32 `json:"height"`
|
||
|
Job_id string `json:"job_id"`
|
||
|
Target string `json:"target"`
|
||
|
}
|
||
|
|
||
|
type Sha3xNotify_msg struct {
|
||
|
Jsonrpc string `json:"jsonrpc"`
|
||
|
Method string `json:"method"`
|
||
|
Params Sha3xNotify_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.Sha3xStratumJob)
|
||
|
|
||
|
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 Sha3xBlockHeader
|
||
|
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
|
||
|
submit_item.Header = hex.EncodeToString(Sha3xBlockHeaderToBytes(header))
|
||
|
calc_hash = BuildPowHash(header)
|
||
|
|
||
|
//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.Sha3xStratumJob, 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("blksha3x"), []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 sha3x_parse_miner_notify(miner *coin.MinerObj, msg msg.Sha3xStratumJob) int {
|
||
|
if miner.Sha3xJob.Height != msg.Height {
|
||
|
miner.Job.IsClean = true
|
||
|
}
|
||
|
miner.Sha3xJob = msg
|
||
|
miner.Sha3xJob.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_sha3x_version", SERVER_SHA3X_VERSION))
|
||
|
coin.Init_diff_db()
|
||
|
}
|
||
|
|
||
|
func Start() {
|
||
|
|
||
|
}
|
||
|
|
||
|
func Stop() {
|
||
|
coin.DiffStop()
|
||
|
}
|
||
|
|
||
|
func InitMiner(miner *coin.MinerObj) {
|
||
|
miner.Sha3xJob = miner.Server.Sha3xJob
|
||
|
miner.Sha3xJob.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 Sha3xNotify_msg
|
||
|
|
||
|
idb := make([]byte, 4)
|
||
|
binary.BigEndian.PutUint32(idb, miner.JobId)
|
||
|
miner.Job.Job_id = hex.EncodeToString(idb)
|
||
|
|
||
|
msg.Params.Algo = "sha3x"
|
||
|
msg.Params.Job_id = miner.Job.Job_id
|
||
|
msg.Params.Blob = miner.Sha3xJob.Header
|
||
|
msg.Params.Height = miner.Sha3xJob.Height
|
||
|
//target_s, _ := stratum.ReverseHexStringByByte(miner.Sha3xJob.Target)
|
||
|
//msg.Params.Target = target_s[48:]
|
||
|
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.Sha3xJob.Height
|
||
|
|
||
|
miner.Sha3xJob.JobDifficulty = miner.Difficulty
|
||
|
|
||
|
miner.Jobs.LoadOrStore(miner.Job.Job_id, miner.Sha3xJob)
|
||
|
|
||
|
/*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
|
||
|
}
|
||
|
|
||
|
func HandleJobMsg(server *coin.ServerContext, Msg []byte) {
|
||
|
var result msg.Sha3xStratumJob
|
||
|
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)
|
||
|
|
||
|
//target_new, _ := utility.DiffToTarget((float64)(result.U64target))
|
||
|
//target_str := fmt.Sprintf("%064x", target_new.Bytes())
|
||
|
//result.Target = target_str
|
||
|
|
||
|
server.Sha3xJob = msg.Sha3xStratumJob(result)
|
||
|
logg.Debug("[gbt]", zap.String("Target", server.Sha3xJob.Target))
|
||
|
|
||
|
server.Sha3xJob.Extranonce2_size = 8
|
||
|
server.SJob.Extranonce2_size = 8
|
||
|
logg.Debug("[gbt]", zap.Uint32("Height", server.Sha3xJob.Height), zap.String("Target", server.Sha3xJob.Target), zap.String("Header", server.Sha3xJob.Header) /*, zap.Uint64("Timastamp", server.Sha3xJob.CurTime)*/)
|
||
|
targetb, _ := hex.DecodeString(server.Sha3xJob.Target)
|
||
|
logg.Debug("[gbt]", zap.Uint64("Id", server.Sha3xJob.Id), zap.Float64("network diff", utility.Target2Diff(utility.Reverse(targetb))))
|
||
|
|
||
|
server.NetHight = uint64(server.Sha3xJob.Height)
|
||
|
server.NetTarget = server.Sha3xJob.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 := sha3x_parse_miner_notify(m, server.Sha3xJob)
|
||
|
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
|
||
|
}
|