635 lines
21 KiB
Go
635 lines
21 KiB
Go
package alph
|
||
|
||
import (
|
||
//"database/sql"
|
||
|
||
"encoding/binary"
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"strings"
|
||
|
||
//"log"
|
||
//"math"
|
||
"math/big"
|
||
|
||
"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_ALPH_VERSION = "alph v1.0"
|
||
|
||
type ServerAlphContext struct {
|
||
ServerCtx *coin.ServerContext
|
||
logg *zap.Logger
|
||
|
||
AlphJob msg.AlphStratumJob
|
||
}
|
||
|
||
var logg *zap.Logger
|
||
var ServerAlphCtx ServerAlphContext
|
||
|
||
type Notify_msg_alph struct {
|
||
ID interface{} `json:"id"`
|
||
Method string `json:"method"`
|
||
Params []msg.AlphStratumJob `json:"params"`
|
||
}
|
||
|
||
func handle_submit(miner *coin.MinerObj, id float64, miner_user string, job_id 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
|
||
v, ok := miner.Jobs.Load(job_id)
|
||
|
||
if ok {
|
||
job := v.(msg.AlphStratumJob)
|
||
|
||
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.LastHeader != job.HeaderBlob) {
|
||
miner.LastHeader = job.HeaderBlob
|
||
miner.LastNonce = nonce
|
||
job.Nonce = nonce
|
||
logg.Debug("[server]", zap.Uint32("height", job.Height), zap.String("target", job.TargetBlob))
|
||
|
||
// ============== 对nonce+区块头进行double blake3 hash ==============
|
||
phb, _ := hex.DecodeString(job.HeaderBlob) // 区块头 []byte
|
||
nb, _ := hex.DecodeString(nonce) // nonce []byte
|
||
|
||
// Blake3 Hash Test Code
|
||
// headerStr := "00070000000208dd35a4511b86c67d4559b94a09a64f7b35ad8d821b5bb0fb4e8c05000000008e7b7b385b727d6bedfc7b9fa8b76f39a2ef318b406a522007b56faa000000020901b382ec2b14149902d5e825d5785b41794f6dfe7a767fe5488e5f00000003178d4a043a964da8afea94bb315711a29ab70532e69f0a51c77501200000000030d339eadb0ce263f5ee49a356dd967a7f23152b6453ab57671d550100000001632ef4dab01759432e37b50d818d39f15cabab11ae0ad9949b2ca742000000000be91faa2a5b6c68762856350092244146fa5d03899ed8aecd8ef0d3446b0d40f1f22eb47dc4df7c9f2a849fa2c2f5ed5c50d626360be988b92244aa0c5dfbc04f756fc5de7f962edf62996f08ed373c51112bcb09637f9a64e6640e00000194f909ea901dff0b28"
|
||
// nonceStr := "cd1359f22f500001cd1359f22f50000151956b6400000000"
|
||
// _header, _ := hex.DecodeString(headerStr)
|
||
// _nonce, _ := hex.DecodeString(nonceStr)
|
||
// _hash := Hash(append(_nonce, _header...))
|
||
// fmt.Println("测试用hash:", _hash)
|
||
|
||
// Hash Diff Test Code
|
||
// _hash, _ := hex.DecodeString("0000000044b373be04ff72d317ec7f1e63b7d8eb8babbc6f33ab29bf640feee7")
|
||
// diff := utility.AlphShareDiff(_hash)
|
||
// fmt.Println("测试用diff:", diff)
|
||
|
||
// 计算hash, nonce + header
|
||
var calc_hash []byte
|
||
calc_hash = append(nb, phb...)
|
||
calc_hash = Hash(calc_hash)
|
||
logg.Debug("[server]", zap.String("hash in", submit_item.Header))
|
||
logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)))
|
||
// ==================================================================
|
||
|
||
submit_target := new(big.Int)
|
||
submit_target.SetBytes(calc_hash) // bignum.fromBuffer(hash);
|
||
calc_diff := utility.AlphShareDiff(calc_hash) // 根据hash计算难度,shareDiff
|
||
// fmt.Println("提交shares难度:", calc_diff)
|
||
// fmt.Println("任务难度:", job.JobDifficulty)
|
||
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 < job.JobDifficulty {
|
||
ack.Result = false
|
||
miner.ErrLowDiffs = miner.ErrLowDiffs + 1
|
||
stratum.Handle_exception(miner, id, stratum.MINER_ERR_LOW_DIF_SHARE)
|
||
return false, false, false
|
||
}
|
||
|
||
var addZero string = ""
|
||
if len(job.TargetBlob) < 64 {
|
||
addZero = strings.Repeat("0", 64-len(job.TargetBlob))
|
||
}
|
||
stb, _ := hex.DecodeString(addZero + job.TargetBlob)
|
||
// server_diff := utility.Target2Diff(utility.Reverse(stb))
|
||
server_diff := utility.AlphShareDiff(utility.Reverse(stb))
|
||
network_target := new(big.Int)
|
||
network_target.SetBytes(stb)
|
||
Net_target := hex.EncodeToString(network_target.Bytes()) // jobTarget
|
||
|
||
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)))
|
||
|
||
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 = strings.Repeat("0", 64-len(Net_target)) + Net_target
|
||
|
||
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 = strings.Repeat("0", 64-len(Net_target)) + Net_target
|
||
|
||
blk_detail_height = int64(job.Height)
|
||
blk_detail_hash = hex.EncodeToString(calc_hash)
|
||
blk_detail_success = false
|
||
// blk_detail_miner_diff = job.JobDifficulty
|
||
blk_detail_miner_diff = miner.Difficulty
|
||
blk_detail_pool_diff = miner.Server.RefDifficulty
|
||
// fmt.Println("mienr.Diff:", miner.Difficulty)
|
||
// fmt.Println("job.Diff:", job.JobDifficulty)
|
||
// fmt.Println("提交任务:", "Hash:", submit_item.Hash, "\tTarget:", submit_item.Target, "\tNet_target:", submit_item.Net_target)
|
||
// fmt.Println("submit_item:", submit_item)
|
||
// fmt.Println("pool_blk_item:", pool_blk_item)
|
||
// fmt.Println("blk_detail_height:", blk_detail_height)
|
||
if ack.Result == true {
|
||
if (calc_diff >= server_diff) || (network_target.Cmp(submit_target) >= 0) {
|
||
miner.Server.SubIdx++
|
||
Produce_block_submit(miner, &job, submit_item.Hash, miner.Server.SubIdx)
|
||
miner.SubmitIndex++
|
||
miner.Submits = miner.Submits + 1
|
||
new_found = true
|
||
}
|
||
}
|
||
} else {
|
||
miner.LastHeader = job.HeaderBlob
|
||
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()))
|
||
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 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)
|
||
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("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate))
|
||
|
||
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 new_found {
|
||
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)
|
||
|
||
}
|
||
|
||
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.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
|
||
}
|
||
|
||
// 该方法和alph-gbt的768行代码相对应
|
||
func Produce_block_submit(miner *coin.MinerObj, job *msg.AlphStratumJob, PowHash string, SubIdx int64) {
|
||
var nm msg.BlockAlphMsg
|
||
nm.Id = job.JobId
|
||
nm.Header = job.HeaderBlob
|
||
nm.Nonce = job.Nonce
|
||
nm.FromGroup = job.FromGroup
|
||
nm.ToGroup = job.ToGroup
|
||
nm.SubIdx = SubIdx
|
||
nm.User = miner.User
|
||
nm.Miner = miner.Miner
|
||
nm.Hash = PowHash
|
||
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)
|
||
logg.Warn("[server]", zap.Uint32("Height", Height))
|
||
|
||
//Add SubmitIndex
|
||
indexb := utility.Uint32ToByte(miner.SubmitIndex)
|
||
indexs := hex.EncodeToString(indexb)
|
||
blk += indexs
|
||
var SubmitIndex uint32 = utility.ByteToUint32(indexb)
|
||
logg.Info("[server]", zap.Uint32("SubmitIndex", 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("blknexa"), []byte(blk)}
|
||
err := miner.Server.PubCh.SendMessage([][]byte{[]byte("blkalph"), []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"))
|
||
}
|
||
}
|
||
}
|
||
|
||
func alph_parse_miner_notify(miner *coin.MinerObj, msg msg.AlphStratumJob) int {
|
||
if miner.AlphJob.Height != msg.Height {
|
||
miner.Job.IsClean = true
|
||
}
|
||
miner.AlphJob = msg
|
||
miner.AlphJob.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) {
|
||
ServerAlphCtx.ServerCtx = server
|
||
logg = server.Logg
|
||
logg.Info("[server]", zap.String("server_alph_version", SERVER_ALPH_VERSION))
|
||
coin.Init_diff_db()
|
||
}
|
||
|
||
func Start() {
|
||
|
||
}
|
||
|
||
func Stop() {
|
||
coin.DiffStop()
|
||
}
|
||
|
||
func InitMiner(miner *coin.MinerObj) {
|
||
be1 := make([]byte, 8)
|
||
binary.LittleEndian.PutUint64(be1, (miner.Server.Extranonce1 /* + 0x81000000*/))
|
||
miner.Job.Extranonce1 = hex.EncodeToString(be1)
|
||
miner.AlphJob.Extranonce1 = miner.Job.Extranonce1
|
||
miner.Server.Extranonce1++
|
||
// fmt.Println("miner.Server.Extranonce1:", miner.Server.Extranonce1)
|
||
|
||
target, err := utility.DiffToTarget(miner.Difficulty)
|
||
if err != nil {
|
||
logg.Error("[server]", zap.String("DiffToTarget", err.Error()))
|
||
return
|
||
}
|
||
|
||
miner.Target = target
|
||
logg.Debug("[target]", zap.String("target", hex.EncodeToString(target.Bytes())), zap.Float64("diff", miner.Difficulty))
|
||
|
||
server_target := new(big.Int)
|
||
t_bytes, err := hex.DecodeString(miner.AlphJob.TargetBlob)
|
||
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
|
||
|
||
miner.AlphJob = miner.Server.AlphJob
|
||
}
|
||
func HandleMinerSubscribe(miner *coin.MinerObj, id float64, extranonce1 string, msg string) {
|
||
|
||
}
|
||
|
||
func HandleMinerAuth(miner *coin.MinerObj) {
|
||
// randomNumber := rand.Intn(65536)
|
||
// hexString := fmt.Sprintf("%04x", randomNumber)
|
||
// method := "mining.set_extranonce"
|
||
// params := []string{hexString}
|
||
// setExtranonce_msg := stratum.AlphSetExtranonce{Method: method, ID: nil, Params: params}
|
||
// fmt.Println("extranonce:", setExtranonce_msg)
|
||
// ex_msg, err := json.Marshal(setExtranonce_msg)
|
||
// if err != nil {
|
||
// logg.Error("[server]", zap.String("Marshal", err.Error()))
|
||
// return
|
||
// }
|
||
// stratum.Conn_tx(miner.Conn, ex_msg)
|
||
}
|
||
|
||
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, nonce)
|
||
return accept_ok, submit_ok, handle_ok
|
||
}
|
||
|
||
func SetDifficulty(miner *coin.MinerObj) {
|
||
extra_msg := stratum.AlphSetExtranonce()
|
||
err := stratum.Conn_tx(miner.Conn, extra_msg)
|
||
if err != nil {
|
||
fmt.Println("alph.set_extranonce发送消息失败:", err)
|
||
}
|
||
stratum.Set_difficulty(miner)
|
||
}
|
||
|
||
func AlphNotify(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()
|
||
|
||
var params msg.AlphStratumJob
|
||
|
||
target := utility.AlphDiffToTarget2(miner.Difficulty)
|
||
|
||
params.JobId = miner.AlphJob.JobId
|
||
params.HeaderBlob = miner.AlphJob.HeaderBlob
|
||
params.TargetBlob = target
|
||
|
||
params.Height = miner.AlphJob.Height
|
||
params.FromGroup = miner.AlphJob.FromGroup
|
||
params.ToGroup = miner.AlphJob.ToGroup
|
||
params.TxsBlob = miner.AlphJob.TxsBlob
|
||
miner.CurHeight = miner.AlphJob.Height
|
||
miner.AlphJob.JobDifficulty = miner.Difficulty
|
||
|
||
miner.Jobs.LoadOrStore(miner.AlphJob.JobId, miner.AlphJob)
|
||
|
||
stratum.AddAndUpdateJob(miner)
|
||
|
||
stratum.UpdateJobs(miner)
|
||
|
||
miner.JobId++
|
||
// 发送mining.notify消息
|
||
var body []byte
|
||
var err error
|
||
var msg Notify_msg_alph
|
||
msg.ID = nil
|
||
msg.Method = "mining.notify"
|
||
msg.Params = append(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) {
|
||
AlphNotify(miner)
|
||
}
|
||
|
||
func HandleJobMsg(server *coin.ServerContext, Msg []byte) {
|
||
var result msg.AlphStratumJob
|
||
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
|
||
}
|
||
|
||
server.AlphJob = msg.AlphStratumJob(result)
|
||
|
||
logg.Debug("[gbt]", zap.String("Target", server.AlphJob.TargetBlob))
|
||
|
||
// server.NexaJob.Extranonce2_size = 8
|
||
// server.SJob.Extranonce2_size = 8
|
||
logg.Debug("[gbt]", zap.Uint32("Height", server.AlphJob.Height), zap.String("Target", server.AlphJob.TargetBlob), zap.String("Header", server.AlphJob.HeaderBlob) /*, zap.Uint64("Timastamp", server.NexaJob.CurTime)*/)
|
||
// targetb, _ := hex.DecodeString(server.AlphJob.TargetBlob)
|
||
|
||
// jobIdInt, err := strconv.ParseInt(server.AlphJob.JobId, 16, 64)
|
||
// if err != nil {
|
||
// logg.Error("[server]", zap.String("Atoi", err.Error()))
|
||
// return
|
||
// }
|
||
// uint64Id := uint64(jobIdInt)
|
||
// logg.Debug("[gbt]", zap.Uint64("Id", uint64Id), zap.Float64("network diff", utility.Target2Diff(utility.Reverse(targetb))))
|
||
|
||
server.NetHight = uint64(server.AlphJob.Height)
|
||
server.NetTarget = server.AlphJob.TargetBlob // 任务的target就是全网target
|
||
server.Miners.Range(func(k, v interface{}) bool {
|
||
m, ok := v.(*(coin.MinerObj))
|
||
if ok {
|
||
server.Logg.Info("[server]", zap.String("lock", "start"))
|
||
m.TxLock.Lock()
|
||
status := m.Status
|
||
cmd := alph_parse_miner_notify(m, server.AlphJob)
|
||
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
|
||
AlphNotify(m)
|
||
}
|
||
}
|
||
}
|
||
return true
|
||
})
|
||
}
|
||
|
||
func IsMhsLow(miner *coin.MinerObj) bool {
|
||
if miner.Mhs5M < 1 {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
func GetBlockInterval() int {
|
||
return 180
|
||
}
|