Browse Source

Update redis.go

master
yuriy0803 5 years ago
parent
commit
893a29859c
  1. 465
      storage/redis.go

465
storage/redis.go

@ -4,15 +4,14 @@ import (
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"log"
"gopkg.in/redis.v3" "gopkg.in/redis.v3"
"github.com/feeleep75/open-ethereum-pool/util" "github.com/yuriy0803/open-etc-pool-friends/util"
) )
type Config struct { type Config struct {
@ -26,13 +25,12 @@ type RedisClient struct {
client *redis.Client client *redis.Client
prefix string prefix string
pplns int64 pplns int64
CoinName string
} }
type PoolCharts struct { type PoolCharts struct {
Timestamp int64 `json:"x"` Timestamp int64 `json:"x"`
PoolHash int64 `json:"y"` TimeFormat string `json:"timeFormat"`
Diff int64 `json:"d"` PoolHash int64 `json:"y"`
} }
type MinerCharts struct { type MinerCharts struct {
@ -59,29 +57,24 @@ type LuckCharts struct {
} }
type SumRewardData struct { type SumRewardData struct {
Interval int64 `json:"inverval"` Interval int64 `json:"inverval"`
Reward int64 `json:"reward"` Reward int64 `json:"reward"`
Name string `json:"name"` Name string `json:"name"`
Offset int64 `json:"offset"` Offset int64 `json:"offset"`
Blocks int64 `json:"blocks"` Blocks int64 `json:"blocks"`
Effort float64 `json:"personalEffort"`
Count float64 `json:"_"`
ESum float64 `json:"_"`
} }
type RewardData struct { type RewardData struct {
Height int64 `json:"blockheight"` Height int64 `json:"blockheight"`
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
BlockHash string `json:"blockhash"` BlockHash string `json:"blockhash"`
Reward int64 `json:"reward"` Reward int64 `json:"reward"`
Percent float64 `json:"percent"` Percent float64 `json:"percent"`
Immature bool `json:"immature"` Immature bool `json:"immature"`
Difficulty int64 `json:"-"`
PersonalShares int64 `json:"-"`
PersonalEffort float64 `json:"personalEffort"`
} }
type BlockData struct { type BlockData struct {
Finder string `json:"finder"` Login string `json:"login"`
ActualDiff int64 `json:"shareDiff"`
Height int64 `json:"height"` Height int64 `json:"height"`
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
Difficulty int64 `json:"difficulty"` Difficulty int64 `json:"difficulty"`
@ -100,7 +93,6 @@ type BlockData struct {
RoundHeight int64 `json:"-"` RoundHeight int64 `json:"-"`
candidateKey string candidateKey string
immatureKey string immatureKey string
PersonalShares int64 `json:"-"`
} }
func (b *BlockData) RewardInShannon() int64 { func (b *BlockData) RewardInShannon() int64 {
@ -121,7 +113,7 @@ func (b *BlockData) RoundKey() string {
} }
func (b *BlockData) key() string { func (b *BlockData) key() string {
return join(b.UncleHeight, b.Orphan, b.Nonce, b.serializeHash(), b.Timestamp, b.Difficulty, b.TotalShares, b.Reward, b.Finder, b.ActualDiff, b.PersonalShares) return join(b.UncleHeight, b.Orphan, b.Nonce, b.serializeHash(), b.Timestamp, b.Difficulty, b.TotalShares, b.Reward, b.Login)
} }
type Miner struct { type Miner struct {
@ -134,20 +126,25 @@ type Miner struct {
type Worker struct { type Worker struct {
Miner Miner
TotalHR int64 `json:"hr2"` TotalHR int64 `json:"hr2"`
PortDiff string `json:"portDiff"` ValidShares int64 `json:"valid"`
WorkerDiff int64 `json:"difficulty"` StaleShares int64 `json:"stale"`
WorkerHostname string `json:"hostname"` InvalidShares int64 `json:"invalid"`
} ValidPercent float64 `json:"v_per"`
StalePercent float64 `json:"s_per"`
func NewRedisClient(cfg *Config, prefix string, pplns int64, CoinName string) *RedisClient { InvalidPercent float64 `json:"i_per"`
WorkerStatus int64 `json:"w_stat"`
WorkerStatushas int64 `json:"w_stat_s"`
}
func NewRedisClient(cfg *Config, prefix string, pplns int64) *RedisClient {
client := redis.NewClient(&redis.Options{ client := redis.NewClient(&redis.Options{
Addr: cfg.Endpoint, Addr: cfg.Endpoint,
Password: cfg.Password, Password: cfg.Password,
DB: cfg.Database, DB: cfg.Database,
PoolSize: cfg.PoolSize, PoolSize: cfg.PoolSize,
}) })
return &RedisClient{client: client, prefix: prefix, pplns: pplns, CoinName: CoinName} return &RedisClient{client: client, prefix: prefix, pplns: pplns}
} }
func (r *RedisClient) Client() *redis.Client { func (r *RedisClient) Client() *redis.Client {
@ -180,9 +177,9 @@ func (r *RedisClient) GetWhitelist() ([]string, error) {
return cmd.Val(), nil return cmd.Val(), nil
} }
func (r *RedisClient) WritePoolCharts(time int64, poolHash string, diff string) error { func (r *RedisClient) WritePoolCharts(time1 int64, time2 string, poolHash string) error {
s := join(time, poolHash, diff) s := join(time1, time2, poolHash)
cmd := r.client.ZAdd(r.formatKey("charts", "pool"), redis.Z{Score: float64(time), Member: s}) cmd := r.client.ZAdd(r.formatKey("charts", "pool"), redis.Z{Score: float64(time1), Member: s})
return cmd.Err() return cmd.Err()
} }
@ -193,17 +190,22 @@ func (r *RedisClient) WriteMinerCharts(time1 int64, time2, k string, hash, large
} }
func (r *RedisClient) GetPoolCharts(poolHashLen int64) (stats []*PoolCharts, err error) { func (r *RedisClient) GetPoolCharts(poolHashLen int64) (stats []*PoolCharts, err error) {
tx := r.client.Multi() tx := r.client.Multi()
defer tx.Close() defer tx.Close()
now := util.MakeTimestamp() / 1000 now := util.MakeTimestamp() / 1000
cmds, err := tx.Exec(func() error { cmds, err := tx.Exec(func() error {
tx.ZRemRangeByScore(r.formatKey("charts", "pool"), "-inf", fmt.Sprint("(", now-172800)) tx.ZRemRangeByScore(r.formatKey("charts", "pool"), "-inf", fmt.Sprint("(", now-172800))
tx.ZRevRangeWithScores(r.formatKey("charts", "pool"), 0, poolHashLen) tx.ZRevRangeWithScores(r.formatKey("charts", "pool"), 0, poolHashLen)
return nil return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
stats = convertPoolChartsResults(cmds[1].(*redis.ZSliceCmd)) stats = convertPoolChartsResults(cmds[1].(*redis.ZSliceCmd))
return stats, nil return stats, nil
} }
@ -211,11 +213,12 @@ func (r *RedisClient) GetPoolCharts(poolHashLen int64) (stats []*PoolCharts, err
func convertPoolChartsResults(raw *redis.ZSliceCmd) []*PoolCharts { func convertPoolChartsResults(raw *redis.ZSliceCmd) []*PoolCharts {
var result []*PoolCharts var result []*PoolCharts
for _, v := range raw.Val() { for _, v := range raw.Val() {
// "Timestamp:TimeFormat:Hash"
pc := PoolCharts{} pc := PoolCharts{}
pc.Timestamp = int64(v.Score) pc.Timestamp = int64(v.Score)
fields := strings.Split(v.Member.(string), ":") str := v.Member.(string)
pc.PoolHash, _ = strconv.ParseInt(fields[1], 10, 64) pc.TimeFormat = str[strings.Index(str, ":")+1 : strings.LastIndex(str, ":")]
pc.Diff, _ = strconv.ParseInt(fields[2], 10, 64) pc.PoolHash, _ = strconv.ParseInt(str[strings.LastIndex(str, ":")+1:], 10, 64)
result = append(result, &pc) result = append(result, &pc)
} }
var reverse []*PoolCharts var reverse []*PoolCharts
@ -225,7 +228,6 @@ func convertPoolChartsResults(raw *redis.ZSliceCmd) []*PoolCharts {
return reverse return reverse
} }
func convertMinerChartsResults(raw *redis.ZSliceCmd) []*MinerCharts { func convertMinerChartsResults(raw *redis.ZSliceCmd) []*MinerCharts {
var result []*MinerCharts var result []*MinerCharts
for _, v := range raw.Val() { for _, v := range raw.Val() {
@ -241,7 +243,7 @@ func convertMinerChartsResults(raw *redis.ZSliceCmd) []*MinerCharts {
} }
var reverse []*MinerCharts var reverse []*MinerCharts
for i := len(result) - 1; i >= 0; i-- { for i := len(result) - 1; i >= 0; i-- {
reverse = append(reverse, result[i]); reverse = append(reverse, result[i])
} }
return reverse return reverse
} }
@ -302,7 +304,7 @@ func (r *RedisClient) GetPaymentCharts(login string) (stats []*PaymentCharts, er
return stats, nil return stats, nil
} }
func (r *RedisClient) WriteNodeState(id string, height uint64, diff *big.Int, blocktime float64) error { func (r *RedisClient) WriteNodeState(id string, height uint64, diff *big.Int) error {
tx := r.client.Multi() tx := r.client.Multi()
defer tx.Close() defer tx.Close()
@ -313,7 +315,6 @@ func (r *RedisClient) WriteNodeState(id string, height uint64, diff *big.Int, bl
tx.HSet(r.formatKey("nodes"), join(id, "height"), strconv.FormatUint(height, 10)) tx.HSet(r.formatKey("nodes"), join(id, "height"), strconv.FormatUint(height, 10))
tx.HSet(r.formatKey("nodes"), join(id, "difficulty"), diff.String()) tx.HSet(r.formatKey("nodes"), join(id, "difficulty"), diff.String())
tx.HSet(r.formatKey("nodes"), join(id, "lastBeat"), strconv.FormatInt(now, 10)) tx.HSet(r.formatKey("nodes"), join(id, "lastBeat"), strconv.FormatInt(now, 10))
tx.HSet(r.formatKey("nodes"), join(id, "blocktime"), strconv.FormatFloat(blocktime, 'f', 4, 64))
return nil return nil
}) })
return err return err
@ -351,7 +352,7 @@ func (r *RedisClient) checkPoWExist(height uint64, params []string) (bool, error
return val == 0, err return val == 0, err
} }
func (r *RedisClient) WriteShare(login, id string, params []string, diff int64, actualDiff int64, netDiff int64, height, topHeight uint64, window time.Duration, hostname string) (bool, error) { func (r *RedisClient) WriteShare(login, id string, params []string, diff int64, height uint64, window time.Duration) (bool, error) {
exist, err := r.checkPoWExist(height, params) exist, err := r.checkPoWExist(height, params)
if err != nil { if err != nil {
return false, err return false, err
@ -367,14 +368,14 @@ func (r *RedisClient) WriteShare(login, id string, params []string, diff int64,
ts := ms / 1000 ts := ms / 1000
_, err = tx.Exec(func() error { _, err = tx.Exec(func() error {
r.writeShare(tx, ms, ts, login, id, diff, actualDiff, height, topHeight, netDiff, window, hostname) r.writeShare(tx, ms, ts, login, id, diff, window)
tx.HIncrBy(r.formatKey("stats"), "roundShares", diff) tx.HIncrBy(r.formatKey("stats"), "roundShares", diff)
return nil return nil
}) })
return false, err return false, err
} }
func (r *RedisClient) WriteBlock(login, id string, params []string, diff, actualDiff int64, roundDiff int64, height, topHeight uint64, window time.Duration, hostname string) (bool, error) { func (r *RedisClient) WriteBlock(login, id string, params []string, diff, roundDiff int64, height uint64, window time.Duration) (bool, error) {
exist, err := r.checkPoWExist(height, params) exist, err := r.checkPoWExist(height, params)
if err != nil { if err != nil {
return false, err return false, err
@ -390,10 +391,9 @@ func (r *RedisClient) WriteBlock(login, id string, params []string, diff, actual
ts := ms / 1000 ts := ms / 1000
cmds, err := tx.Exec(func() error { cmds, err := tx.Exec(func() error {
r.writeShare(tx, ms, ts, login, id, diff, actualDiff, height, topHeight, roundDiff, window, hostname) r.writeShare(tx, ms, ts, login, id, diff, window)
tx.HSet(r.formatKey("stats"), "lastBlockFound", strconv.FormatInt(ts, 10)) tx.HSet(r.formatKey("stats"), "lastBlockFound", strconv.FormatInt(ts, 10))
tx.HDel(r.formatKey("stats"), "roundShares") tx.HDel(r.formatKey("stats"), "roundShares")
tx.HSet(r.formatKey("miners", login), "roundShares", strconv.FormatInt(0, 10))
tx.ZIncrBy(r.formatKey("finders"), 1, login) tx.ZIncrBy(r.formatKey("finders"), 1, login)
tx.HIncrBy(r.formatKey("miners", login), "blocksFound", 1) tx.HIncrBy(r.formatKey("miners", login), "blocksFound", 1)
tx.HGetAllMap(r.formatKey("shares", "roundCurrent")) tx.HGetAllMap(r.formatKey("shares", "roundCurrent"))
@ -432,35 +432,24 @@ func (r *RedisClient) WriteBlock(login, id string, params []string, diff, actual
n, _ := strconv.ParseInt(v, 10, 64) n, _ := strconv.ParseInt(v, 10, 64)
totalShares += n totalShares += n
} }
personalShares := int64(0)
personalShares = cmds[len(cmds)-14].(*redis.IntCmd).Val()
hashHex := strings.Join(params, ":") hashHex := strings.Join(params, ":")
s := join(hashHex, ts, roundDiff, totalShares, login, actualDiff, personalShares) s := join(hashHex, ts, roundDiff, totalShares, login)
cmd := r.client.ZAdd(r.formatKey("blocks", "candidates"), redis.Z{Score: float64(height), Member: s}) cmd := r.client.ZAdd(r.formatKey("blocks", "candidates"), redis.Z{Score: float64(height), Member: s})
return false, cmd.Err() return false, cmd.Err()
} }
} }
func (r *RedisClient) writeShare(tx *redis.Multi, ms, ts int64, login, id string, diff int64, actualDiff int64, height, topHeight uint64, netDiff int64, expire time.Duration, hostname string) { func (r *RedisClient) writeShare(tx *redis.Multi, ms, ts int64, login, id string, diff int64, expire time.Duration) {
/* # Note To Me: times := int(diff / 1000000000)
Will have to write to get from redis the current value for round for i := 0; i < times; i++ {
shares and increase by 1, then include the new number to be added to redis tx.LPush(r.formatKey("lastshares"), login)
*/ }
// Moved get hostname to stratums
tx.LPush(r.formatKey("lastshares"), login)
tx.LTrim(r.formatKey("lastshares"), 0, r.pplns) tx.LTrim(r.formatKey("lastshares"), 0, r.pplns)
tx.HIncrBy(r.formatKey("miners", login), "roundShares", diff)
tx.HIncrBy(r.formatKey("shares", "roundCurrent"), login, diff) tx.HIncrBy(r.formatKey("shares", "roundCurrent"), login, diff)
tx.ZAdd(r.formatKey("hashrate"), redis.Z{Score: float64(ts), Member: join(diff, login, id, ms, hostname)}) tx.ZAdd(r.formatKey("hashrate"), redis.Z{Score: float64(ts), Member: join(diff, login, id, ms)})
tx.ZAdd(r.formatKey("hashrate", login), redis.Z{Score: float64(ts), Member: join(diff, id, ms, hostname)}) tx.ZAdd(r.formatKey("hashrate", login), redis.Z{Score: float64(ts), Member: join(diff, id, ms)})
tx.Expire(r.formatKey("hashrate", login), expire) // Will delete hashrates for miners that gone tx.Expire(r.formatKey("hashrate", login), expire) // Will delete hashrates for miners that gone
tx.HSet(r.formatKey("miners", login), "lastShare", strconv.FormatInt(ts, 10)) tx.HSet(r.formatKey("miners", login), "lastShare", strconv.FormatInt(ts, 10))
tx.HSet(r.formatKey("miners", login), "lastShareDiff", strconv.FormatInt(actualDiff, 10))
} }
func (r *RedisClient) WriteBlocksFound(ms, ts int64, login, id, share string, diff int64) { func (r *RedisClient) WriteBlocksFound(ms, ts int64, login, id, share string, diff int64) {
@ -493,13 +482,6 @@ func join(args ...interface{}) string {
} else { } else {
s[i] = "0" s[i] = "0"
} }
case *big.Int:
n := v.(*big.Int)
if n != nil {
s[i] = n.String()
} else {
s[i] = "0"
}
case *big.Rat: case *big.Rat:
x := v.(*big.Rat) x := v.(*big.Rat)
if x != nil { if x != nil {
@ -507,6 +489,13 @@ func join(args ...interface{}) string {
} else { } else {
s[i] = "0" s[i] = "0"
} }
case *big.Int:
n := v.(*big.Int)
if n != nil {
s[i] = n.String()
} else {
s[i] = "0"
}
default: default:
panic("Invalid type specified for conversion") panic("Invalid type specified for conversion")
} }
@ -531,6 +520,7 @@ func (r *RedisClient) GetImmatureBlocks(maxHeight int64) ([]*BlockData, error) {
} }
return convertBlockResults(cmd), nil return convertBlockResults(cmd), nil
} }
func (r *RedisClient) GetRewards(login string) ([]*RewardData, error) { func (r *RedisClient) GetRewards(login string) ([]*RewardData, error) {
option := redis.ZRangeByScore{Min: "0", Max: strconv.FormatInt(10, 10)} option := redis.ZRangeByScore{Min: "0", Max: strconv.FormatInt(10, 10)}
cmd := r.client.ZRangeByScoreWithScores(r.formatKey("rewards", login), option) cmd := r.client.ZRangeByScoreWithScores(r.formatKey("rewards", login), option)
@ -599,15 +589,6 @@ func (r *RedisClient) GetBalance(login string) (int64, error) {
} }
return cmd.Int64() return cmd.Int64()
} }
func (r *RedisClient) GetTreshold(login string) (int64, error) {
cmd := r.client.HGet(r.formatKey("miners", login), "payouttreshold")
if cmd.Err() == redis.Nil {
return 0, nil
} else if cmd.Err() != nil {
return 0, cmd.Err()
}
return cmd.Int64()
}
func (r *RedisClient) LockPayouts(login string, amount int64) error { func (r *RedisClient) LockPayouts(login string, amount int64) error {
key := r.formatKey("payments", "lock") key := r.formatKey("payments", "lock")
@ -701,13 +682,18 @@ func (r *RedisClient) WritePayment(login, txHash string, amount int64) error {
tx.HIncrBy(r.formatKey("finances"), "pending", (amount * -1)) tx.HIncrBy(r.formatKey("finances"), "pending", (amount * -1))
tx.HIncrBy(r.formatKey("finances"), "paid", amount) tx.HIncrBy(r.formatKey("finances"), "paid", amount)
tx.ZAdd(r.formatKey("payments", "all"), redis.Z{Score: float64(ts), Member: join(txHash, login, amount)}) tx.ZAdd(r.formatKey("payments", "all"), redis.Z{Score: float64(ts), Member: join(txHash, login, amount)})
tx.ZRemRangeByRank(r.formatKey("payments", "all"), 0, -10000)
tx.ZAdd(r.formatKey("payments", login), redis.Z{Score: float64(ts), Member: join(txHash, amount)}) tx.ZAdd(r.formatKey("payments", login), redis.Z{Score: float64(ts), Member: join(txHash, amount)})
tx.ZRemRangeByRank(r.formatKey("payments", login), 0, -100)
tx.ZRem(r.formatKey("payments", "pending"), join(login, amount)) tx.ZRem(r.formatKey("payments", "pending"), join(login, amount))
tx.Del(r.formatKey("payments", "lock")) tx.Del(r.formatKey("payments", "lock"))
tx.HIncrBy(r.formatKey("paymentsTotal"), "all", 1)
tx.HIncrBy(r.formatKey("paymentsTotal"), login, 1)
return nil return nil
}) })
return err return err
} }
func (r *RedisClient) WriteReward(login string, amount int64, percent *big.Rat, immature bool, block *BlockData) error { func (r *RedisClient) WriteReward(login string, amount int64, percent *big.Rat, immature bool, block *BlockData) error {
if amount <= 0 { if amount <= 0 {
return nil return nil
@ -715,15 +701,15 @@ func (r *RedisClient) WriteReward(login string, amount int64, percent *big.Rat,
tx := r.client.Multi() tx := r.client.Multi()
defer tx.Close() defer tx.Close()
addStr := join(amount, percent, immature, block.Hash, block.Height, block.Timestamp, block.Difficulty, block.PersonalShares) addStr := join(amount, percent, immature, block.Hash, block.Height, block.Timestamp)
remStr := join(amount, percent, !immature, block.Hash, block.Height, block.Timestamp, block.Difficulty, block.PersonalShares) remStr := join(amount, percent, !immature, block.Hash, block.Height, block.Timestamp)
remscore := block.Timestamp - 3600*24*40 // Store the last 40 Days remscore := block.Timestamp - 3600*24*40 // Store the last 40 Days
_, err := tx.Exec(func() error { _, err := tx.Exec(func() error {
tx.ZAdd(r.formatKey("rewards", login), redis.Z{Score: float64(block.Timestamp), Member: addStr}) tx.ZAdd(r.formatKey("rewards", login), redis.Z{Score: float64(block.Timestamp), Member: addStr})
tx.ZRem(r.formatKey("rewards", login), remStr) tx.ZRem(r.formatKey("rewards", login), remStr)
tx.ZRemRangeByScore(r.formatKey("rewards", login), "-inf", "("+strconv.FormatInt(remscore, 10)) tx.ZRemRangeByScore(r.formatKey("rewards", login), "-inf", "("+strconv.FormatInt(remscore, 10))
return nil return nil
}) })
return err return err
@ -786,6 +772,7 @@ func (r *RedisClient) WriteMaturedBlock(block *BlockData, roundRewards map[strin
tx.HSet(r.formatKey("finances"), "lastCreditHeight", strconv.FormatInt(block.Height, 10)) tx.HSet(r.formatKey("finances"), "lastCreditHeight", strconv.FormatInt(block.Height, 10))
tx.HSet(r.formatKey("finances"), "lastCreditHash", block.Hash) tx.HSet(r.formatKey("finances"), "lastCreditHash", block.Hash)
tx.HIncrBy(r.formatKey("finances"), "totalMined", block.RewardInShannon()) tx.HIncrBy(r.formatKey("finances"), "totalMined", block.RewardInShannon())
tx.Expire(r.formatKey("credits", block.Height, block.Hash), 604800*time.Second)
return nil return nil
}) })
return err return err
@ -859,9 +846,11 @@ func (r *RedisClient) GetMinerStats(login string, maxPayments int64) (map[string
cmds, err := tx.Exec(func() error { cmds, err := tx.Exec(func() error {
tx.HGetAllMap(r.formatKey("miners", login)) tx.HGetAllMap(r.formatKey("miners", login))
tx.ZRevRangeWithScores(r.formatKey("payments", login), 0, maxPayments-1) tx.ZRevRangeWithScores(r.formatKey("payments", login), 0, maxPayments-1)
tx.ZCard(r.formatKey("payments", login)) tx.HGet(r.formatKey("paymentsTotal"), login)
tx.HGet(r.formatKey("shares", "currentShares"), login) tx.HGet(r.formatKey("shares", "currentShares"), login)
tx.LRange(r.formatKey("lastshares"), 0, r.pplns) tx.LRange(r.formatKey("lastshares"), 0, r.pplns)
tx.ZRevRangeWithScores(r.formatKey("rewards", login), 0, 39)
tx.ZRevRangeWithScores(r.formatKey("rewards", login), 0, -1)
return nil return nil
}) })
@ -872,7 +861,7 @@ func (r *RedisClient) GetMinerStats(login string, maxPayments int64) (map[string
stats["stats"] = convertStringMap(result) stats["stats"] = convertStringMap(result)
payments := convertPaymentsResults(cmds[1].(*redis.ZSliceCmd)) payments := convertPaymentsResults(cmds[1].(*redis.ZSliceCmd))
stats["payments"] = payments stats["payments"] = payments
stats["paymentsTotal"] = cmds[2].(*redis.IntCmd).Val() stats["paymentsTotal"], _ = cmds[2].(*redis.StringCmd).Int64()
shares := cmds[4].(*redis.StringSliceCmd).Val() shares := cmds[4].(*redis.StringSliceCmd).Val()
csh := 0 csh := 0
for _, val := range shares { for _, val := range shares {
@ -956,15 +945,14 @@ func (r *RedisClient) CollectStats(smallWindow time.Duration, maxBlocks, maxPaym
tx.ZCard(r.formatKey("blocks", "candidates")) tx.ZCard(r.formatKey("blocks", "candidates"))
tx.ZCard(r.formatKey("blocks", "immature")) tx.ZCard(r.formatKey("blocks", "immature"))
tx.ZCard(r.formatKey("blocks", "matured")) tx.ZCard(r.formatKey("blocks", "matured"))
tx.ZCard(r.formatKey("payments", "all")) tx.HGet(r.formatKey("paymentsTotal"), "all")
tx.ZRevRangeWithScores(r.formatKey("payments", "all"), 0, maxPayments-1) tx.ZRevRangeWithScores(r.formatKey("payments", "all"), 0, maxPayments-1)
tx.LLen(r.formatKey("lastshares")) tx.LLen(r.formatKey("lastshares"))
tx.HGetAllMap(r.formatKey("exchange", r.CoinName)) tx.ZRevRangeWithScores(r.formatKey("finders"), 0, -1)
tx.ZRevRangeWithScores(r.formatKey("finders"), 0, -1)
return nil return nil
}) })
if err != nil { if (err != nil) && (err != redis.Nil) {
return nil, err return nil, err
} }
@ -985,21 +973,15 @@ func (r *RedisClient) CollectStats(smallWindow time.Duration, maxBlocks, maxPaym
payments := convertPaymentsResults(cmds[10].(*redis.ZSliceCmd)) payments := convertPaymentsResults(cmds[10].(*redis.ZSliceCmd))
stats["payments"] = payments stats["payments"] = payments
stats["paymentsTotal"] = cmds[9].(*redis.IntCmd).Val() stats["paymentsTotal"], _ = cmds[9].(*redis.StringCmd).Int64()
finders := convertFindersResults(cmds[12].(*redis.ZSliceCmd))
stats["finders"] = finders
totalHashrate, miners := convertMinersStats(window, cmds[1].(*redis.ZSliceCmd)) totalHashrate, miners := convertMinersStats(window, cmds[1].(*redis.ZSliceCmd))
stats["miners"] = miners stats["miners"] = miners
stats["minersTotal"] = len(miners) stats["minersTotal"] = len(miners)
stats["hashrate"] = totalHashrate stats["hashrate"] = totalHashrate
exchangedata, _ := cmds[12].(*redis.StringStringMapCmd).Result()
stats["exchangedata"] = exchangedata
finders := convertFindersResults(cmds[13].(*redis.ZSliceCmd))
stats["finders"] = finders
return stats, nil return stats, nil
} }
@ -1016,7 +998,6 @@ func (r *RedisClient) CollectWorkersStats(sWindow, lWindow time.Duration, login
cmds, err := tx.Exec(func() error { cmds, err := tx.Exec(func() error {
tx.ZRemRangeByScore(r.formatKey("hashrate", login), "-inf", fmt.Sprint("(", now-largeWindow)) tx.ZRemRangeByScore(r.formatKey("hashrate", login), "-inf", fmt.Sprint("(", now-largeWindow))
tx.ZRangeWithScores(r.formatKey("hashrate", login), 0, -1) tx.ZRangeWithScores(r.formatKey("hashrate", login), 0, -1)
tx.LRange(r.formatKey("lastshares"), 0, r.pplns)
tx.ZRevRangeWithScores(r.formatKey("rewards", login), 0, 39) tx.ZRevRangeWithScores(r.formatKey("rewards", login), 0, 39)
tx.ZRevRangeWithScores(r.formatKey("rewards", login), 0, -1) tx.ZRevRangeWithScores(r.formatKey("rewards", login), 0, -1)
tx.ZRangeWithScores(r.formatKey("worker", "blocks", login), 0, -1) tx.ZRangeWithScores(r.formatKey("worker", "blocks", login), 0, -1)
@ -1031,7 +1012,7 @@ func (r *RedisClient) CollectWorkersStats(sWindow, lWindow time.Duration, login
currentHashrate := int64(0) currentHashrate := int64(0)
online := int64(0) online := int64(0)
offline := int64(0) offline := int64(0)
workers := convertWorkersStats(smallWindow, cmds[1].(*redis.ZSliceCmd), cmds[5].(*redis.ZSliceCmd)) workers := convertWorkersStats(smallWindow, cmds[1].(*redis.ZSliceCmd), cmds[4].(*redis.ZSliceCmd), login, r)
for id, worker := range workers { for id, worker := range workers {
timeOnline := now - worker.startedAt timeOnline := now - worker.startedAt
@ -1058,7 +1039,7 @@ func (r *RedisClient) CollectWorkersStats(sWindow, lWindow time.Duration, login
online++ online++
} }
blocks := cmds[5].(*redis.ZSliceCmd).Val() blocks := cmds[4].(*redis.ZSliceCmd).Val()
for _, val := range blocks { for _, val := range blocks {
parts := strings.Split(val.Member.(string), ":") parts := strings.Split(val.Member.(string), ":")
@ -1073,25 +1054,68 @@ func (r *RedisClient) CollectWorkersStats(sWindow, lWindow time.Duration, login
currentHashrate += worker.HR currentHashrate += worker.HR
totalHashrate += worker.TotalHR totalHashrate += worker.TotalHR
workers[id] = worker valid_share, stale_share, invalid_share, _ := r.getSharesStatus(login, id)
} worker.ValidShares = int64(5)
worker.StaleShares = int64(5)
shares := cmds[2].(*redis.StringSliceCmd).Val() worker.InvalidShares = int64(5)
worker.ValidShares = valid_share
csh := 0 worker.StaleShares = stale_share
//var myshares []string worker.InvalidShares = invalid_share
for _, val := range shares { //test percentage
//text := "█" worker.ValidPercent = float64(0)
if val != login { worker.StalePercent = float64(0)
//text = "▁" worker.InvalidPercent = float64(0)
tot_share := int64(0)
tot_share += valid_share
tot_share += stale_share
tot_share += invalid_share
if tot_share > 0 {
d := float64(100)
//tot_share += ////error
cost_per := float64(tot_share) / d
v_per := float64(valid_share) / cost_per
worker.ValidPercent = toFixed(v_per, 1)
s_per := float64(stale_share) / cost_per
worker.StalePercent = toFixed(s_per, 1)
i_per := float64(invalid_share) / cost_per
worker.InvalidPercent = toFixed(i_per, 1)
} else { } else {
csh++ worker.ValidPercent = toFixed(0, 1)
worker.StalePercent = toFixed(0, 1)
worker.InvalidPercent = toFixed(0, 1)
}
w_stat := int64(0) //test worker large hashrate indicator
if worker.HR >= worker.TotalHR {
w_stat = 1
worker.WorkerStatus = w_stat
} else if worker.HR < worker.TotalHR {
w_stat = 0
worker.WorkerStatus = w_stat
} }
//myshares = append(myshares, strconv.FormatInt(int64(ind) 10)) ///test small hr
//myshares = append(myshares, text) tot_w := r.client.HGet(r.formatKey("minerShare", login, id), "hashrate")
if tot_w.Err() == redis.Nil {
tx.HSet(r.formatKey("minerShare", login, id), "hashrate", strconv.FormatInt(0, 10))
//return nil, nil
} else if tot_w.Err() != nil {
tx.HSet(r.formatKey("minerShare", login, id), "hashrate", strconv.FormatInt(0, 10))
//return nil, tot_w.Err()
}
last_hr, _ := tot_w.Int64()
w_stat_s := int64(0) //test worker hashrate indicator
if worker.HR > last_hr {
w_stat_s = 1
worker.WorkerStatushas = w_stat_s
} else if worker.HR <= last_hr {
w_stat_s = 0
worker.WorkerStatushas = w_stat_s
}
tx.HSet(r.formatKey("minerShare", login, id), "hashrate", strconv.FormatInt(worker.HR, 10))
workers[id] = worker
} }
stats["roundShares"] = csh
//stats["shares"] = myshares
stats["workers"] = workers stats["workers"] = workers
stats["workersTotal"] = len(workers) stats["workersTotal"] = len(workers)
stats["workersOnline"] = online stats["workersOnline"] = online
@ -1099,8 +1123,8 @@ func (r *RedisClient) CollectWorkersStats(sWindow, lWindow time.Duration, login
stats["hashrate"] = totalHashrate stats["hashrate"] = totalHashrate
stats["currentHashrate"] = currentHashrate stats["currentHashrate"] = currentHashrate
stats["rewards"] = convertRewardResults(cmds[3].(*redis.ZSliceCmd)) // last 40 stats["rewards"] = convertRewardResults(cmds[2].(*redis.ZSliceCmd)) // last 40
rewards := convertRewardResults(cmds[4].(*redis.ZSliceCmd)) // all rewards := convertRewardResults(cmds[3].(*redis.ZSliceCmd)) // all
var dorew []*SumRewardData var dorew []*SumRewardData
dorew = append(dorew, &SumRewardData{Name: "Last 60 minutes", Interval: 3600, Offset: 0}) dorew = append(dorew, &SumRewardData{Name: "Last 60 minutes", Interval: 3600, Offset: 0})
@ -1110,27 +1134,30 @@ func (r *RedisClient) CollectWorkersStats(sWindow, lWindow time.Duration, login
dorew = append(dorew, &SumRewardData{Name: "Last 30 days", Interval: 3600 * 24 * 30, Offset: 0}) dorew = append(dorew, &SumRewardData{Name: "Last 30 days", Interval: 3600 * 24 * 30, Offset: 0})
for _, reward := range rewards { for _, reward := range rewards {
for _, dore := range dorew { for _, dore := range dorew {
dore.Count += 0
dore.ESum += 0
dore.Reward += 0 dore.Reward += 0
dore.Blocks += 0 dore.Blocks += 0
dore.Effort += 0
if reward.Timestamp > now-dore.Interval { if reward.Timestamp > now-dore.Interval {
dore.Reward += reward.Reward dore.Reward += reward.Reward
dore.Blocks++ dore.Blocks++
dore.ESum += reward.PersonalEffort
dore.Count++
dore.Effort = dore.ESum / dore.Count
} }
} }
} }
stats["sumrewards"] = dorew stats["sumrewards"] = dorew
stats["24hreward"] = dorew[2].Reward stats["24hreward"] = dorew[2].Reward
return stats, nil return stats, nil
} }
func round(num float64) int {
return int(num + math.Copysign(0.5, num))
}
func toFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(round(num*output)) / output
}
func (r *RedisClient) CollectLuckStats(windows []int) (map[string]interface{}, error) { func (r *RedisClient) CollectLuckStats(windows []int) (map[string]interface{}, error) {
stats := make(map[string]interface{}) stats := make(map[string]interface{})
@ -1237,9 +1264,7 @@ func convertCandidateResults(raw *redis.ZSliceCmd) []*BlockData {
block.Timestamp, _ = strconv.ParseInt(fields[3], 10, 64) block.Timestamp, _ = strconv.ParseInt(fields[3], 10, 64)
block.Difficulty, _ = strconv.ParseInt(fields[4], 10, 64) block.Difficulty, _ = strconv.ParseInt(fields[4], 10, 64)
block.TotalShares, _ = strconv.ParseInt(fields[5], 10, 64) block.TotalShares, _ = strconv.ParseInt(fields[5], 10, 64)
block.Finder = fields[6] block.Login = fields[6]
block.ActualDiff, _ = strconv.ParseInt(fields[7], 10, 64)
block.PersonalShares, _ = strconv.ParseInt(fields[8], 10, 64)
block.candidateKey = v.Member.(string) block.candidateKey = v.Member.(string)
result = append(result, &block) result = append(result, &block)
} }
@ -1260,11 +1285,6 @@ func convertRewardResults(rows ...*redis.ZSliceCmd) []*RewardData {
reward.Percent, _ = strconv.ParseFloat(fields[1], 64) reward.Percent, _ = strconv.ParseFloat(fields[1], 64)
reward.Immature, _ = strconv.ParseBool(fields[2]) reward.Immature, _ = strconv.ParseBool(fields[2])
reward.Height, _ = strconv.ParseInt(fields[4], 10, 64) reward.Height, _ = strconv.ParseInt(fields[4], 10, 64)
reward.Difficulty, _ = strconv.ParseInt(fields[6], 10, 64)
reward.PersonalShares, _ = strconv.ParseInt(fields[7], 10, 64)
Difficulty, _ := strconv.ParseFloat(fields[6], 64)
PersonalShares, _ := strconv.ParseFloat(fields[7], 64)
reward.PersonalEffort = float64(PersonalShares / Difficulty)
result = append(result, &reward) result = append(result, &reward)
} }
} }
@ -1290,9 +1310,7 @@ func convertBlockResults(rows ...*redis.ZSliceCmd) []*BlockData {
block.TotalShares, _ = strconv.ParseInt(fields[6], 10, 64) block.TotalShares, _ = strconv.ParseInt(fields[6], 10, 64)
block.RewardString = fields[7] block.RewardString = fields[7]
block.ImmatureReward = fields[7] block.ImmatureReward = fields[7]
block.Finder = fields[8] block.Login = fields[8]
block.ActualDiff, _ = strconv.ParseInt(fields[9], 10, 64)
block.PersonalShares, _ = strconv.ParseInt(fields[10], 10, 64)
block.immatureKey = v.Member.(string) block.immatureKey = v.Member.(string)
result = append(result, &block) result = append(result, &block)
} }
@ -1302,7 +1320,7 @@ func convertBlockResults(rows ...*redis.ZSliceCmd) []*BlockData {
// Build per login workers's total shares map {'rig-1': 12345, 'rig-2': 6789, ...} // Build per login workers's total shares map {'rig-1': 12345, 'rig-2': 6789, ...}
// TS => diff, id, ms // TS => diff, id, ms
func convertWorkersStats(window int64, raw *redis.ZSliceCmd, blocks *redis.ZSliceCmd) map[string]Worker { func convertWorkersStats(window int64, raw *redis.ZSliceCmd, blocks *redis.ZSliceCmd, login string, r *RedisClient) map[string]Worker {
now := util.MakeTimestamp() / 1000 now := util.MakeTimestamp() / 1000
workers := make(map[string]Worker) workers := make(map[string]Worker)
@ -1317,34 +1335,26 @@ func convertWorkersStats(window int64, raw *redis.ZSliceCmd, blocks *redis.ZSlic
for _, v := range raw.Val() { for _, v := range raw.Val() {
parts := strings.Split(v.Member.(string), ":") parts := strings.Split(v.Member.(string), ":")
share, _ := strconv.ParseInt(parts[0], 10, 64) share, _ := strconv.ParseInt(parts[0], 10, 64)
//By Mohannad
var hostname string
if len(parts)>3 {
hostname = parts[3]
}else{
hostname = "unknown"
}
id := parts[1] id := parts[1]
score := int64(v.Score) score := int64(v.Score)
worker := workers[id] worker := workers[id]
// Add for large window // Add for large window
worker.TotalHR += share worker.TotalHR += share
worker.ValidShares = int64(4)
// Addition from Mohannad Otaibi to report Difficulty worker.ValidPercent = float64(0)
worker.WorkerDiff = share worker.StalePercent = float64(0)
worker.WorkerHostname = hostname worker.InvalidPercent = float64(0)
// End Mohannad Adjustments worker.WorkerStatus = int64(0)
worker.WorkerStatushas = int64(0)
//worker.StatleShares = int64(4)
//worker.InvalidShares = int64(4)
// Add for small window if matches // Add for small window if matches
if score >= now-window { if score >= now-window {
worker.HR += share worker.HR += share
} }
if worker.LastBeat < score { if worker.LastBeat < score {
worker.LastBeat = score worker.LastBeat = score
} }
@ -1417,7 +1427,7 @@ func convertPaymentsResults(raw *redis.ZSliceCmd) []map[string]interface{} {
} }
var reverse []map[string]interface{} var reverse []map[string]interface{}
for i := len(result) - 1; i >= 0; i-- { for i := len(result) - 1; i >= 0; i-- {
reverse = append(reverse, result[i]); reverse = append(reverse, result[i])
} }
return result return result
} }
@ -1433,41 +1443,6 @@ func convertFindersResults(raw *redis.ZSliceCmd) []map[string]interface{} {
return result return result
} }
func (r *RedisClient) StoreExchangeData(ExchangeData []map[string]interface{}) {
tx := r.client.Multi()
defer tx.Close()
log.Printf("ExchangeData: %s", ExchangeData)
for _, coindata := range ExchangeData {
for key, value := range coindata {
cmd := tx.HSet(r.formatKey("exchange", coindata["symbol"]), fmt.Sprintf("%v", key), fmt.Sprintf("%v", value))
err := cmd.Err()
if err != nil {
log.Printf("Error while Storing %s : Key-%s , value-%s , Error : %v", coindata["symbol"], key, value, err)
}
}
}
log.Printf("Writing Exchange Data ")
return
}
func (r *RedisClient) GetExchangeData(coinsymbol string) (map[string]string, error) {
cmd := r.client.HGetAllMap(r.formatKey("exchange", coinsymbol))
result, err := cmd.Result()
if err != nil {
return nil, err
}
return result, err
}
/* /*
Timestamp int64 `json:"x"` Timestamp int64 `json:"x"`
TimeFormat string `json:"timeFormat"` TimeFormat string `json:"timeFormat"`
@ -1498,7 +1473,7 @@ func convertPaymentChartsResults(raw *redis.ZSliceCmd) []*PaymentCharts {
} }
var reverse []*PaymentCharts var reverse []*PaymentCharts
for i := len(result) - 1; i >= 0; i-- { for i := len(result) - 1; i >= 0; i-- {
reverse = append(reverse, result[i]); reverse = append(reverse, result[i])
} }
return reverse return reverse
} }
@ -1512,3 +1487,99 @@ func (r *RedisClient) GetCurrentHashrate(login string) (int64, error) {
} }
return hashrate.Int64() return hashrate.Int64()
} }
// Need a function to delete on round end or whatever, and another function to get.
func (r *RedisClient) ResetWorkerShareStatus() {
tx := r.client.Multi()
defer tx.Close()
tx.Exec(func() error {
tx.HDel(r.formatKey("minerShare"))
return nil
})
// THis should do it ay ?
// fuck it
}
// Don't know if this will work, returning three values, but let's see
func (r *RedisClient) getSharesStatus(login string, id string) (int64, int64, int64, error) {
valid_shares := r.client.HGet(r.formatKey("minerShare", login, id), "valid")
stale_shares := r.client.HGet(r.formatKey("minerShare", login, id), "stale")
invalid_shares := r.client.HGet(r.formatKey("minerShare", login, id), "invalid")
if valid_shares.Err() == redis.Nil || stale_shares.Err() == redis.Nil || invalid_shares.Err() == redis.Nil {
return 0, 0, 0, nil
} else if valid_shares.Err() != nil || stale_shares.Err() != nil || invalid_shares.Err() != nil {
return 0, 0, 0, valid_shares.Err()
}
v_c, _ := valid_shares.Int64()
s_c, _ := stale_shares.Int64()
i_c, _ := invalid_shares.Int64()
return v_c, s_c, i_c, nil
}
//lets try to fuck without understanding and see if it works
func (r *RedisClient) WriteWorkerShareStatus(login string, id string, valid bool, stale bool, invalid bool) {
valid_int := 0
stale_int := 0
invalid_int := 0
if valid {
valid_int = 1
}
if stale {
stale_int = 1
}
if invalid {
invalid_int = 1
}
// var after = time.Now().AddDate(0, 0, -1).Unix()
// var now = time.Now().Unix()
// if(now >= after){
// tx.HDel(r.formatKey("minerShare", login, id))
// }
t := time.Now().Local()
if t.Format("15:04:05") >= "23:59:00" {
tx := r.client.Multi()
defer tx.Close()
tx.Exec(func() error {
//tx.Del(r.formatKey("minerShare", login, id))
tx.HSet(r.formatKey("minerShare", login, id), "valid", strconv.FormatInt(0, 10))
tx.HSet(r.formatKey("minerShare", login, id), "stale", strconv.FormatInt(0, 10))
tx.HSet(r.formatKey("minerShare", login, id), "invalid", strconv.FormatInt(0, 10))
return nil
})
} else {
// So, we need to initiate the tx object
tx := r.client.Multi()
defer tx.Close()
tx.Exec(func() error {
// OK, good, no need to read reset and add if i use Hset and HGet shit
tx.HIncrBy(r.formatKey("minerShare", login, id), "valid", int64(valid_int))
tx.HIncrBy(r.formatKey("minerShare", login, id), "stale", int64(stale_int))
tx.HIncrBy(r.formatKey("minerShare", login, id), "invalid", int64(invalid_int))
tx.HIncrBy(r.formatKey("chartsNum", "share", login), "valid", int64(valid_int))
tx.HIncrBy(r.formatKey("chartsNum", "share", login), "stale", int64(stale_int)) // Would that work?
return nil
})
} //end else
}
func (r *RedisClient) NumberStratumWorker(count int) {
tx := r.client.Multi()
defer tx.Close()
tx.Exec(func() error {
tx.Del(r.formatKey("WorkersTot"))
tx.HIncrBy(r.formatKey("WorkersTot"), "workers", int64(count))
//tx.HSet(r.formatKey("WorkersTotal"), "workers", int64(count))
return nil
})
}

Loading…
Cancel
Save