788 lines
19 KiB
Go
788 lines
19 KiB
Go
|
// coin.go
|
||
|
package coin
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"container/list"
|
||
|
"crypto/md5"
|
||
|
"crypto/rand"
|
||
|
"encoding/base64"
|
||
|
|
||
|
"database/sql"
|
||
|
"encoding/binary"
|
||
|
"encoding/hex"
|
||
|
"strconv"
|
||
|
|
||
|
"io"
|
||
|
"log"
|
||
|
"math"
|
||
|
"math/big"
|
||
|
"net"
|
||
|
|
||
|
"fmt"
|
||
|
"pool/internal/db"
|
||
|
"pool/internal/msg"
|
||
|
"pool/internal/server/diff"
|
||
|
"pool/internal/utility"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||
|
"github.com/btcsuite/btcd/wire"
|
||
|
|
||
|
"github.com/rs/zerolog"
|
||
|
|
||
|
"github.com/redis/go-redis/v9"
|
||
|
"github.com/zeromq/goczmq"
|
||
|
"go.uber.org/zap"
|
||
|
"gopkg.in/natefinch/lumberjack.v2"
|
||
|
|
||
|
_ "github.com/mattn/go-sqlite3"
|
||
|
)
|
||
|
|
||
|
const JOB_EXPIRED_TIME uint32 = 60 //job expired time (second)
|
||
|
const LOCAL_JOBS_EXPIRED_TIME uint32 = 300 //300 //local jobs expired time (second)
|
||
|
const LOCAL_JOBS_TOTAL_SIZE uint32 = 300 //300 //total local jobs
|
||
|
const CONN_EXPIRED_TIME uint32 = 600 //connection expired time
|
||
|
|
||
|
// miner status
|
||
|
// const MINER_STATUS_OFFLINE string = "offline"
|
||
|
const MINER_STATUS_CONNECTED string = "connected"
|
||
|
const MINER_STATUS_SUBSCRIBED string = "subscribed"
|
||
|
const MINER_STATUS_AUTHORIZED string = "authorized"
|
||
|
const MINER_STATUS_RUNNING string = "online"
|
||
|
const MINER_STATUS_DISCONNECTED string = "offline"
|
||
|
const MINER_STATUS_DISABLED string = "disabled"
|
||
|
|
||
|
const MINER_DURATION_TIME time.Duration = 1
|
||
|
const MINER_DIFFICULTY_ADJUST_DURATION time.Duration = 5
|
||
|
|
||
|
// vardiff
|
||
|
const UP_DIFF int = 0
|
||
|
const DOWN_DIFF int = 1
|
||
|
const UPDATE_DIFF int = 2
|
||
|
const DIFFICULTY_WAIT_TIMES int = 6
|
||
|
|
||
|
const (
|
||
|
Low = 0
|
||
|
Mid = 1
|
||
|
Hign = 2
|
||
|
)
|
||
|
|
||
|
type BindConfig struct {
|
||
|
Listen string `json:"listen"`
|
||
|
Auth bool `json:"auth"`
|
||
|
}
|
||
|
|
||
|
type DiffConfig struct {
|
||
|
StartDifficulty float64 `json:"start_diff"`
|
||
|
DiffMin float64 `json:"diff_min"`
|
||
|
DiffMax float64 `json:"diff_max"`
|
||
|
DiffAdjustInterval float64 `json:"diff_adjust_interval"`
|
||
|
DiffAdjustPercentage float64 `json:"diff_adjust_percentage"`
|
||
|
DiffAdjustTime float64 `json:"diff_adjust_time"`
|
||
|
Filter string `json:"filter"`
|
||
|
Dbg bool `json:"dbg"`
|
||
|
}
|
||
|
|
||
|
type ServerConfig struct {
|
||
|
Coin string `json:"coin"`
|
||
|
Host BindConfig `json:"host"`
|
||
|
Diff DiffConfig `json:"diff"`
|
||
|
Zmq utility.ZmqConfig `json:"zmq"`
|
||
|
Redis utility.RedisConfig `json:"redis"`
|
||
|
Zaplog zap.Config `json:"zap"`
|
||
|
Logrotae utility.LogRotateConfig `json:"logrotate"`
|
||
|
}
|
||
|
|
||
|
type CoinObj struct {
|
||
|
Coin string
|
||
|
Init func(server *ServerContext)
|
||
|
Start func()
|
||
|
Stop func()
|
||
|
InitMiner func(miner *MinerObj)
|
||
|
HandleMinerSubscribe func(miner *MinerObj, id float64, extranonce1 string, msg string)
|
||
|
HandleMinerAuth func(miner *MinerObj)
|
||
|
HandleMinerSubmit func(miner *MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool)
|
||
|
SetDifficulty func(miner *MinerObj)
|
||
|
Notify func(miner *MinerObj)
|
||
|
HandleJobMsg func(server *ServerContext, Msg []byte)
|
||
|
IsMhsLow func(miner *MinerObj) bool
|
||
|
GetBlockInterval func() int
|
||
|
}
|
||
|
|
||
|
type PoolBlkMsg struct {
|
||
|
Height int64
|
||
|
Hash string
|
||
|
Pow string
|
||
|
Net_target string
|
||
|
Submit string
|
||
|
Success bool
|
||
|
Accepts float64
|
||
|
Rejects float64
|
||
|
Reward float64
|
||
|
Fee float64
|
||
|
Nonce string
|
||
|
SubIdx int64
|
||
|
}
|
||
|
|
||
|
type ServerContext struct {
|
||
|
CoinCtx CoinObj
|
||
|
DbCtx *db.DbContext
|
||
|
|
||
|
Config *ServerConfig
|
||
|
|
||
|
PubCh *goczmq.Sock
|
||
|
SubCh *goczmq.Sock
|
||
|
|
||
|
Listener net.Listener
|
||
|
|
||
|
MinerType string
|
||
|
|
||
|
Extranonce1 uint64
|
||
|
|
||
|
Difficulty float64
|
||
|
|
||
|
RefDifficulty float64
|
||
|
|
||
|
Accepts float64
|
||
|
Rejects float64
|
||
|
AverageHashrate float64
|
||
|
|
||
|
Miners sync.Map
|
||
|
|
||
|
MMhs sync.Map
|
||
|
|
||
|
Started bool
|
||
|
|
||
|
SLock sync.Mutex
|
||
|
ExitFlag bool
|
||
|
|
||
|
//AlivingChan chan bool
|
||
|
//LiveingExpired bool
|
||
|
FlagAliving int32
|
||
|
FlagAlivingExit int32
|
||
|
|
||
|
ExitPingChan chan bool
|
||
|
ExitJobChan chan bool
|
||
|
|
||
|
Logg *zap.Logger
|
||
|
LogR *lumberjack.Logger
|
||
|
|
||
|
SJob msg.StratumJob
|
||
|
|
||
|
//UpdateMap sync.Map
|
||
|
|
||
|
SyncJobChan chan bool
|
||
|
Synced bool
|
||
|
|
||
|
ExitDbMiners chan bool
|
||
|
ExitDbMinersStats chan bool
|
||
|
|
||
|
ExitDbUser chan bool
|
||
|
ExitDbUserStats chan bool
|
||
|
|
||
|
ExitDbPoolStats chan bool
|
||
|
|
||
|
NexaJob msg.NexaStratumJob
|
||
|
AlphJob msg.AlphStratumJob
|
||
|
|
||
|
ExitDiffVar chan bool
|
||
|
|
||
|
RedisClient *redis.Client
|
||
|
|
||
|
Accepts5M float64
|
||
|
Accepts15M float64
|
||
|
Accepts30M float64
|
||
|
Accepts1h float64
|
||
|
Accepts3h float64
|
||
|
Accepts6h float64
|
||
|
Accepts12h float64
|
||
|
Accepts24h float64
|
||
|
Accepts48h float64
|
||
|
|
||
|
Rejects5M float64
|
||
|
Rejects15M float64
|
||
|
Rejects30M float64
|
||
|
Rejects1h float64
|
||
|
Rejects3h float64
|
||
|
Rejects6h float64
|
||
|
Rejects12h float64
|
||
|
Rejects24h float64
|
||
|
Rejects48h float64
|
||
|
|
||
|
Mhs5M float64
|
||
|
Mhs15M float64
|
||
|
Mhs30M float64
|
||
|
Mhs1h float64
|
||
|
Mhs3h float64
|
||
|
Mhs6h float64
|
||
|
Mhs12h float64
|
||
|
Mhs24h float64
|
||
|
Mhs48h float64
|
||
|
|
||
|
RejectRatio5M float64
|
||
|
RejectRatio15M float64
|
||
|
RejectRatio30M float64
|
||
|
RejectRatio1h float64
|
||
|
RejectRatio3h float64
|
||
|
RejectRatio6h float64
|
||
|
RejectRatio12h float64
|
||
|
RejectRatio24h float64
|
||
|
RejectRatio48h float64
|
||
|
|
||
|
TotalMiners int64
|
||
|
Normal int64
|
||
|
Abnormal int64
|
||
|
Offline int64
|
||
|
MhsZero int64
|
||
|
MhsLow int64
|
||
|
HighRejects int64
|
||
|
Unstable int64
|
||
|
|
||
|
NetTarget string
|
||
|
NetHight uint64
|
||
|
|
||
|
Submits int64
|
||
|
Blocks int64
|
||
|
Orphans int64
|
||
|
|
||
|
Reward float64
|
||
|
Fee float64
|
||
|
|
||
|
/*Users sync.Map
|
||
|
UsersSLock sync.Mutex*/
|
||
|
|
||
|
/*PoolSLock sync.Mutex*/
|
||
|
|
||
|
SubIdx int64
|
||
|
|
||
|
MinerIndex int64
|
||
|
|
||
|
//NotifyBlkDetailIdx int32
|
||
|
}
|
||
|
|
||
|
type JobListEntry struct {
|
||
|
Job_id string
|
||
|
Ts time.Time
|
||
|
}
|
||
|
|
||
|
type MhsItem struct {
|
||
|
Tt time.Time
|
||
|
Diff float64
|
||
|
}
|
||
|
|
||
|
type MhsObj struct {
|
||
|
MinerId string
|
||
|
Name string
|
||
|
Accepts []MhsItem
|
||
|
Rejects []MhsItem
|
||
|
StartSubmitTime time.Time
|
||
|
|
||
|
StartDayTime time.Time
|
||
|
|
||
|
User string
|
||
|
Miner string
|
||
|
Index string
|
||
|
Status string
|
||
|
Algo int
|
||
|
}
|
||
|
|
||
|
type VarDiffOptions struct {
|
||
|
VariancePercent float64
|
||
|
AdjustTime float64
|
||
|
AdjustInterval float64
|
||
|
MinDiff float64
|
||
|
MaxDiff float64
|
||
|
MinShares float64
|
||
|
MaxShares float64
|
||
|
TargetShares float64
|
||
|
SubmitShares float64
|
||
|
SilenceCount float64
|
||
|
LastCalcTime time.Time
|
||
|
Uptimes int
|
||
|
Downtimes int
|
||
|
Level int
|
||
|
LastSubmitTime time.Time
|
||
|
}
|
||
|
|
||
|
type BlockMsg struct {
|
||
|
Target string
|
||
|
Submit_target string
|
||
|
Height int64
|
||
|
Success bool
|
||
|
Pow string
|
||
|
Net_target string
|
||
|
Submit string
|
||
|
Hash string
|
||
|
Header string
|
||
|
Accepts float64
|
||
|
Total_accepts float64
|
||
|
Rejects float64
|
||
|
Total_rejects float64
|
||
|
Reward float64
|
||
|
Fee float64
|
||
|
Nonce string
|
||
|
SubIdx int64
|
||
|
}
|
||
|
|
||
|
type MinerObj struct {
|
||
|
Server *ServerContext
|
||
|
Conn net.Conn
|
||
|
Authorized bool
|
||
|
|
||
|
MinerId string
|
||
|
JobId uint32
|
||
|
Name string
|
||
|
|
||
|
Jobs sync.Map
|
||
|
LockForJobs sync.Mutex
|
||
|
JobList *list.List
|
||
|
|
||
|
Target *big.Int
|
||
|
Difficulty float64
|
||
|
DifficultyNext float64
|
||
|
ServerDifficulty float64
|
||
|
ServerTarget *big.Int
|
||
|
ServerTargetS string
|
||
|
Accepts float64
|
||
|
Rejects float64
|
||
|
StartSubmitTime time.Time
|
||
|
LastSubmitime time.Time
|
||
|
SubmitIndex uint32
|
||
|
AverageHashrate float64
|
||
|
M5Accepts float64
|
||
|
M5Hashrate float64
|
||
|
M5SubmitTime time.Time
|
||
|
LastJobId string
|
||
|
LastNonce string
|
||
|
CurHeight uint32
|
||
|
CurHeight64 uint64
|
||
|
Reconnect bool
|
||
|
|
||
|
LastHeader string
|
||
|
|
||
|
VarDiffOpt VarDiffOptions
|
||
|
|
||
|
Version int32
|
||
|
Job msg.StratumJob
|
||
|
|
||
|
User string
|
||
|
PassWord string
|
||
|
Miner string
|
||
|
|
||
|
Duration float64
|
||
|
|
||
|
Status string
|
||
|
ConnSetupTime time.Time
|
||
|
TxLock sync.Mutex
|
||
|
|
||
|
KeepliveCnt float64
|
||
|
RecvedLiveAck bool
|
||
|
PongFailCnt int
|
||
|
PingCnt int
|
||
|
|
||
|
NexaJob msg.NexaStratumJob
|
||
|
AlphJob msg.AlphStratumJob
|
||
|
|
||
|
//EndCh chan bool
|
||
|
FromIP string
|
||
|
|
||
|
OnlineTime time.Time
|
||
|
OfflineTime time.Time
|
||
|
Retry int64
|
||
|
DurationTime float64
|
||
|
MinerIndex int64
|
||
|
|
||
|
Protocol string
|
||
|
|
||
|
ErrStaleds int64
|
||
|
ErrLowDiffs int64
|
||
|
ErrDuplicates int64
|
||
|
ErrFormats int64
|
||
|
ErrOthers int64
|
||
|
|
||
|
IsDisabled bool
|
||
|
|
||
|
Submits int64
|
||
|
Blocks int64
|
||
|
Orphans int64
|
||
|
|
||
|
Accepts5M float64
|
||
|
Accepts15M float64
|
||
|
Accepts30M float64
|
||
|
Accepts1h float64
|
||
|
Accepts3h float64
|
||
|
Accepts6h float64
|
||
|
Accepts12h float64
|
||
|
Accepts24h float64
|
||
|
Accepts48h float64
|
||
|
|
||
|
Rejects5M float64
|
||
|
Rejects15M float64
|
||
|
Rejects30M float64
|
||
|
Rejects1h float64
|
||
|
Rejects3h float64
|
||
|
Rejects6h float64
|
||
|
Rejects12h float64
|
||
|
Rejects24h float64
|
||
|
Rejects48h float64
|
||
|
|
||
|
Mhs5M float64
|
||
|
Mhs15M float64
|
||
|
Mhs30M float64
|
||
|
Mhs1h float64
|
||
|
Mhs3h float64
|
||
|
Mhs6h float64
|
||
|
Mhs12h float64
|
||
|
Mhs24h float64
|
||
|
Mhs48h float64
|
||
|
|
||
|
RejectRatio5M float64
|
||
|
RejectRatio15M float64
|
||
|
RejectRatio30M float64
|
||
|
RejectRatio1h float64
|
||
|
RejectRatio3h float64
|
||
|
RejectRatio6h float64
|
||
|
RejectRatio12h float64
|
||
|
RejectRatio24h float64
|
||
|
RejectRatio48h float64
|
||
|
|
||
|
Reward float64
|
||
|
Fee float64
|
||
|
|
||
|
Zlog zerolog.Logger
|
||
|
LogR *lumberjack.Logger
|
||
|
ZlogInit bool
|
||
|
|
||
|
//EndCh chan bool
|
||
|
|
||
|
DiffHandler diff.KalmanVarDiff
|
||
|
|
||
|
NeedExit int32
|
||
|
}
|
||
|
|
||
|
/*type UserBlockMsg struct {
|
||
|
User string
|
||
|
Miner string
|
||
|
Index string
|
||
|
Height int64
|
||
|
Hash string
|
||
|
Pow string
|
||
|
Net_target string
|
||
|
Submit string
|
||
|
Success bool
|
||
|
Accepts float64
|
||
|
Rejects float64
|
||
|
Reward float64
|
||
|
Fee float64
|
||
|
Nonce string
|
||
|
SubIdx int64
|
||
|
}*/
|
||
|
/*
|
||
|
type UserMinerContainer struct {
|
||
|
Data map[string]string
|
||
|
}*/
|
||
|
|
||
|
/*
|
||
|
type UserObj struct {
|
||
|
Server *ServerContext
|
||
|
User string
|
||
|
Name string
|
||
|
|
||
|
Normal int64
|
||
|
Abnormal int64
|
||
|
|
||
|
Offline int64
|
||
|
MhsZero int64
|
||
|
MhsLow int64
|
||
|
HighRejects int64
|
||
|
Unstable int64
|
||
|
|
||
|
Submits int64
|
||
|
Blocks int64
|
||
|
Orphans int64
|
||
|
|
||
|
Reward float64
|
||
|
Fee float64
|
||
|
|
||
|
Accepts5M float64
|
||
|
Accepts15M float64
|
||
|
Accepts30M float64
|
||
|
Accepts1h float64
|
||
|
Accepts3h float64
|
||
|
Accepts6h float64
|
||
|
Accepts12h float64
|
||
|
Accepts24h float64
|
||
|
Accepts48h float64
|
||
|
|
||
|
Rejects5M float64
|
||
|
Rejects15M float64
|
||
|
Rejects30M float64
|
||
|
Rejects1h float64
|
||
|
Rejects3h float64
|
||
|
Rejects6h float64
|
||
|
Rejects12h float64
|
||
|
Rejects24h float64
|
||
|
Rejects48h float64
|
||
|
|
||
|
Mhs5M float64
|
||
|
Mhs15M float64
|
||
|
Mhs30M float64
|
||
|
Mhs1h float64
|
||
|
Mhs3h float64
|
||
|
Mhs6h float64
|
||
|
Mhs12h float64
|
||
|
Mhs24h float64
|
||
|
Mhs48h float64
|
||
|
|
||
|
RejectRatio5M float64
|
||
|
RejectRatio15M float64
|
||
|
RejectRatio30M float64
|
||
|
RejectRatio1h float64
|
||
|
RejectRatio3h float64
|
||
|
RejectRatio6h float64
|
||
|
RejectRatio12h float64
|
||
|
RejectRatio24h float64
|
||
|
RejectRatio48h float64
|
||
|
}*/
|
||
|
|
||
|
func md5md5(v string) string {
|
||
|
md5Obj := md5.New()
|
||
|
md5Obj.Write([]byte(v))
|
||
|
char := md5Obj.Sum(nil)
|
||
|
return hex.EncodeToString(char)
|
||
|
}
|
||
|
|
||
|
func Guid() string {
|
||
|
c := make([]byte, 32)
|
||
|
if _, err := io.ReadFull(rand.Reader, c); err != nil {
|
||
|
return ""
|
||
|
}
|
||
|
return md5md5(base64.URLEncoding.EncodeToString(c))
|
||
|
}
|
||
|
|
||
|
func VarAdjustDifficulty(miner *MinerObj, adjust int) {
|
||
|
if adjust != UP_DIFF && adjust != DOWN_DIFF && adjust != UPDATE_DIFF {
|
||
|
miner.Server.Logg.Error("[server]", zap.Int("Not support adjust ", adjust))
|
||
|
return
|
||
|
}
|
||
|
if adjust == UP_DIFF {
|
||
|
miner.DifficultyNext = miner.Difficulty
|
||
|
if miner.VarDiffOpt.Level == Mid {
|
||
|
miner.DifficultyNext *= math.Pow(2, 1)
|
||
|
miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000
|
||
|
} else if miner.VarDiffOpt.Level == Hign {
|
||
|
miner.DifficultyNext *= math.Pow(2, 2)
|
||
|
miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000
|
||
|
}
|
||
|
} else if adjust == DOWN_DIFF {
|
||
|
miner.DifficultyNext = miner.Difficulty
|
||
|
if miner.VarDiffOpt.Level == Mid {
|
||
|
miner.DifficultyNext /= math.Pow(2, 1)
|
||
|
miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000
|
||
|
} else if miner.VarDiffOpt.Level == Hign {
|
||
|
miner.DifficultyNext /= math.Pow(2, 2)
|
||
|
miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000
|
||
|
}
|
||
|
} else if adjust == UPDATE_DIFF {
|
||
|
if miner.VarDiffOpt.SubmitShares > 0 {
|
||
|
// re-target if outside bounds
|
||
|
if miner.VarDiffOpt.SubmitShares < miner.VarDiffOpt.MinShares || miner.VarDiffOpt.SubmitShares > miner.VarDiffOpt.MaxShares {
|
||
|
var change float64 = miner.VarDiffOpt.SubmitShares / miner.VarDiffOpt.TargetShares
|
||
|
miner.DifficultyNext = miner.Difficulty
|
||
|
miner.DifficultyNext *= change
|
||
|
miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000
|
||
|
}
|
||
|
miner.VarDiffOpt.SilenceCount = 0
|
||
|
} else {
|
||
|
// radical measures if there were no shares submitted
|
||
|
miner.VarDiffOpt.SilenceCount++
|
||
|
miner.DifficultyNext = miner.Difficulty / math.Pow(2, miner.VarDiffOpt.SilenceCount)
|
||
|
miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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.TargetShares = miner.VarDiffOpt.AdjustTime / miner.VarDiffOpt.AdjustInterval * miner.DifficultyNext
|
||
|
miner.VarDiffOpt.MinShares = miner.VarDiffOpt.AdjustTime / miner.VarDiffOpt.AdjustInterval * miner.DifficultyNext * (1 - miner.VarDiffOpt.VariancePercent)
|
||
|
miner.VarDiffOpt.MaxShares = miner.VarDiffOpt.AdjustTime / miner.VarDiffOpt.AdjustInterval * miner.DifficultyNext * (1 + miner.VarDiffOpt.VariancePercent)
|
||
|
miner.VarDiffOpt.SubmitShares = 0
|
||
|
miner.VarDiffOpt.Uptimes = 0
|
||
|
miner.VarDiffOpt.Downtimes = 0
|
||
|
miner.Server.Logg.Info("[server]", zap.Float64("DifficultyNext", miner.DifficultyNext))
|
||
|
miner.Server.Logg.Info("[server]", zap.Float64("TargetShares", miner.VarDiffOpt.TargetShares), zap.Float64("MinShares", miner.VarDiffOpt.MinShares), zap.Float64("MaxShares", miner.VarDiffOpt.MaxShares))
|
||
|
|
||
|
now := time.Now()
|
||
|
share_interval := now.Sub(miner.LastSubmitime).Seconds()
|
||
|
New_diff_into_db(miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.Difficulty, miner.DifficultyNext, miner.VarDiffOpt.SubmitShares, share_interval, miner.VarDiffOpt.MinShares, miner.VarDiffOpt.MaxShares)
|
||
|
}
|
||
|
|
||
|
var gdiff_db *sql.DB
|
||
|
|
||
|
func Init_diff_db() {
|
||
|
db, err := sql.Open("sqlite3", "./diffs.db")
|
||
|
if err != nil {
|
||
|
log.Printf("Error opening database: %v", err)
|
||
|
return
|
||
|
}
|
||
|
//defer db.Close()
|
||
|
|
||
|
gdiff_db = db
|
||
|
|
||
|
createTableSQL := `
|
||
|
CREATE TABLE IF NOT EXISTS diffs (
|
||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
ts TEXT NOT NULL,
|
||
|
user TEXT NOT NULL,
|
||
|
miner TEXT NOT NULL,
|
||
|
minerid TEXT NOT NULL,
|
||
|
diff REAL NOT NULL,
|
||
|
next REAL NOT NULL,
|
||
|
kp REAL NOT NULL,
|
||
|
interval REAL NOT NULL,
|
||
|
mhs REAL NOT NULL,
|
||
|
mhs_est REAL NOT NULL
|
||
|
);`
|
||
|
_, err = gdiff_db.Exec(createTableSQL)
|
||
|
if err != nil {
|
||
|
log.Printf("Error creating table: %v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func New_diff_into_db(user string, miner string, minerid string, diff float64, diff_next float64, kp float64, interval float64, mhs float64, mhs_est float64) {
|
||
|
if gdiff_db != nil {
|
||
|
insertSQL := `INSERT INTO diffs (ts, user, miner, minerid, diff, next, kp, interval, mhs, mhs_est) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||
|
_, err := gdiff_db.Exec(insertSQL, time.Now().Format("2006-01-02 15:04:05"), user, miner, minerid, diff, diff_next, kp, interval, mhs, mhs_est)
|
||
|
if err != nil {
|
||
|
log.Printf("Error inserting data from diffs %s: %v", user+"."+miner+"_"+minerid, err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func DiffStop() {
|
||
|
if gdiff_db != nil {
|
||
|
defer gdiff_db.Close()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Build_coinbase(coinbase1 string, extranonce1 string, extranonce2, coinbase2 string, doublehash bool) ([]byte, error) {
|
||
|
var coinbase_string string = coinbase1 + extranonce1 + extranonce2 + coinbase2
|
||
|
coinbase_bytes, err := hex.DecodeString(coinbase_string)
|
||
|
if err != nil {
|
||
|
//log.Println("[dash]failed to Build_coinbase", err)
|
||
|
return nil, err
|
||
|
}
|
||
|
//fmt.Println("coinbase", coinbase_string, hex.EncodeToString(coinbase_bytes))
|
||
|
var coinbase []byte
|
||
|
if doublehash {
|
||
|
coinbase = chainhash.DoubleHashB(coinbase_bytes)
|
||
|
} else {
|
||
|
coinbase = chainhash.HashB(coinbase_bytes)
|
||
|
}
|
||
|
//fmt.Println("coinbase_hash", hex.EncodeToString(coinbase))
|
||
|
//fmt.Println("coinbase_hash", coinbase)
|
||
|
return coinbase, nil
|
||
|
}
|
||
|
|
||
|
// build merkel root hash value
|
||
|
func Build_merkle_root(coinbase []byte, transaction_list *[]string) ([]byte, error) {
|
||
|
var merkle_root []byte
|
||
|
merkle_root = coinbase
|
||
|
count := len(*transaction_list)
|
||
|
var i int
|
||
|
for i = 0; i < count; i++ {
|
||
|
//fmt.Println("merkle_hash start", i, hex.EncodeToString(merkle_root))
|
||
|
t_bytes, err := hex.DecodeString((*transaction_list)[i])
|
||
|
if err != nil {
|
||
|
//log.Println("[dash]failed to Build_merkle_root", err)
|
||
|
return nil, err
|
||
|
}
|
||
|
for j := 0; j < len(t_bytes); j++ {
|
||
|
merkle_root = append(merkle_root, t_bytes[j])
|
||
|
}
|
||
|
//fmt.Println("merkle_hash append", i, hex.EncodeToString(merkle_root))
|
||
|
merkle := chainhash.DoubleHashB(merkle_root)
|
||
|
//fmt.Println("merkle_hash", i, hex.EncodeToString(merkle))
|
||
|
merkle_root = merkle
|
||
|
}
|
||
|
return merkle_root, nil
|
||
|
}
|
||
|
|
||
|
func BuildBlockHash(job *msg.StratumJob, doublehash bool, pow func(h wire.BlockHeader) chainhash.Hash) ([]byte, wire.BlockHeader) {
|
||
|
var bh wire.BlockHeader
|
||
|
//log.Printf("[dash]c1 %s,e1 %s,e2 %s,c2 %s\n", job.Coinbase1, job.Extranonce1, job.Extranonce2, job.Coinbase2)
|
||
|
coinbase, err := Build_coinbase(job.Coinbase1, job.Extranonce1, job.Extranonce2, job.Coinbase2, doublehash)
|
||
|
if err != nil {
|
||
|
return nil, bh
|
||
|
}
|
||
|
//log.Println("[dash]trans", job.Transactions)
|
||
|
merkle_root, err := Build_merkle_root(coinbase, job.Transactions)
|
||
|
if err != nil {
|
||
|
return nil, bh
|
||
|
}
|
||
|
vb := make([]byte, 4)
|
||
|
binary.LittleEndian.PutUint32(vb, uint32(job.Version))
|
||
|
tb := make([]byte, 4)
|
||
|
binary.LittleEndian.PutUint32(tb, uint32(job.Timestamp.Unix()))
|
||
|
bh, err = Build_block_hash(hex.EncodeToString(vb), job.PrevblockBig, merkle_root, hex.EncodeToString(tb), job.BitsS, job.Nonce)
|
||
|
if err != nil {
|
||
|
return nil, bh
|
||
|
}
|
||
|
powhash := pow(bh)
|
||
|
//log.Printf("POW hash:%s", powhash.String())
|
||
|
return powhash.CloneBytes(), bh
|
||
|
}
|
||
|
|
||
|
func Build_block_hash(block_version string, prev_hash string, merkle_root []byte, ntime string, nbits string, nonce string) (wire.BlockHeader, error) {
|
||
|
var header wire.BlockHeader
|
||
|
b, err := strconv.ParseUint(nbits, 16, 32)
|
||
|
if err != nil {
|
||
|
//log.Println("[dash]failed to Build_block_hash", err)
|
||
|
return header, err
|
||
|
}
|
||
|
header.Bits = uint32(b)
|
||
|
//log.Printf("Bits:%x", header.Bits)
|
||
|
p_bytes, err := hex.DecodeString(prev_hash)
|
||
|
if err != nil {
|
||
|
log.Println("[dash]failed to Build_block_hash", err)
|
||
|
return header, err
|
||
|
}
|
||
|
p, err := chainhash.NewHash(utility.Convert_big_endian(p_bytes))
|
||
|
header.PrevBlock = *p
|
||
|
//log.Printf("Prev Block:%s", hex.EncodeToString(header.PrevBlock.CloneBytes()))
|
||
|
m, err := chainhash.NewHash(merkle_root)
|
||
|
header.MerkleRoot = *m
|
||
|
//log.Printf("MerkleRoot:%s", hex.EncodeToString(header.MerkleRoot.CloneBytes()))
|
||
|
n, err := strconv.ParseUint(nonce, 16, 32)
|
||
|
if err != nil {
|
||
|
//log.Println("[dash]failed to Build_block_hash", err)
|
||
|
return header, err
|
||
|
}
|
||
|
header.Nonce = uint32(n)
|
||
|
//log.Printf("Nonce:%x", header.Nonce)
|
||
|
v, err := hex.DecodeString(block_version)
|
||
|
if err != nil {
|
||
|
//log.Println("[dash]failed to Build_block_hash", err)
|
||
|
return header, err
|
||
|
}
|
||
|
vBuffer := bytes.NewBuffer(v)
|
||
|
binary.Read(vBuffer, binary.BigEndian, &(header.Version))
|
||
|
//log.Printf("Version:%x", header.Version)
|
||
|
t, err := strconv.ParseInt(ntime, 16, 64)
|
||
|
if err != nil {
|
||
|
//log.Println("[dash]failed to Build_block_hash", err)
|
||
|
return header, err
|
||
|
}
|
||
|
header.Timestamp = time.Unix(t, 0)
|
||
|
//log.Printf("nTime %v", header.Timestamp)
|
||
|
|
||
|
return header, nil
|
||
|
}
|