Browse Source

Update redis.go

master
yuriy0803 5 years ago
parent
commit
159b730eeb
  1. 452
      storage/redis.go

452
storage/redis.go

@ -4,14 +4,15 @@ 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/yuriy0803/open-etc-pool-friends/util" "github.com/feeleep75/open-ethereum-pool/util"
) )
type Config struct { type Config struct {
@ -25,12 +26,13 @@ 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"`
TimeFormat string `json:"timeFormat"` PoolHash int64 `json:"y"`
PoolHash int64 `json:"y"` Diff int64 `json:"d"`
} }
type MinerCharts struct { type MinerCharts struct {
@ -57,24 +59,29 @@ 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 {
Login string `json:"login"` Finder string `json:"finder"`
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"`
@ -93,6 +100,7 @@ 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 {
@ -113,7 +121,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.Login) return join(b.UncleHeight, b.Orphan, b.Nonce, b.serializeHash(), b.Timestamp, b.Difficulty, b.TotalShares, b.Reward, b.Finder, b.ActualDiff, b.PersonalShares)
} }
type Miner struct { type Miner struct {
@ -126,25 +134,20 @@ type Miner struct {
type Worker struct { type Worker struct {
Miner Miner
TotalHR int64 `json:"hr2"` TotalHR int64 `json:"hr2"`
ValidShares int64 `json:"valid"` PortDiff string `json:"portDiff"`
StaleShares int64 `json:"stale"` WorkerDiff int64 `json:"difficulty"`
InvalidShares int64 `json:"invalid"` WorkerHostname string `json:"hostname"`
ValidPercent float64 `json:"v_per"` }
StalePercent float64 `json:"s_per"`
InvalidPercent float64 `json:"i_per"` func NewRedisClient(cfg *Config, prefix string, pplns int64, CoinName string) *RedisClient {
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} return &RedisClient{client: client, prefix: prefix, pplns: pplns, CoinName: CoinName}
} }
func (r *RedisClient) Client() *redis.Client { func (r *RedisClient) Client() *redis.Client {
@ -177,9 +180,9 @@ func (r *RedisClient) GetWhitelist() ([]string, error) {
return cmd.Val(), nil return cmd.Val(), nil
} }
func (r *RedisClient) WritePoolCharts(time1 int64, time2 string, poolHash string) error { func (r *RedisClient) WritePoolCharts(time int64, poolHash string, diff string) error {
s := join(time1, time2, poolHash) s := join(time, poolHash, diff)
cmd := r.client.ZAdd(r.formatKey("charts", "pool"), redis.Z{Score: float64(time1), Member: s}) cmd := r.client.ZAdd(r.formatKey("charts", "pool"), redis.Z{Score: float64(time), Member: s})
return cmd.Err() return cmd.Err()
} }
@ -190,22 +193,17 @@ 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
} }
@ -213,12 +211,11 @@ 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)
str := v.Member.(string) fields := strings.Split(v.Member.(string), ":")
pc.TimeFormat = str[strings.Index(str, ":")+1 : strings.LastIndex(str, ":")] pc.PoolHash, _ = strconv.ParseInt(fields[1], 10, 64)
pc.PoolHash, _ = strconv.ParseInt(str[strings.LastIndex(str, ":")+1:], 10, 64) pc.Diff, _ = strconv.ParseInt(fields[2], 10, 64)
result = append(result, &pc) result = append(result, &pc)
} }
var reverse []*PoolCharts var reverse []*PoolCharts
@ -228,6 +225,7 @@ 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() {
@ -243,7 +241,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
} }
@ -304,7 +302,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) error { func (r *RedisClient) WriteNodeState(id string, height uint64, diff *big.Int, blocktime float64) error {
tx := r.client.Multi() tx := r.client.Multi()
defer tx.Close() defer tx.Close()
@ -315,6 +313,7 @@ func (r *RedisClient) WriteNodeState(id string, height uint64, diff *big.Int) er
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
@ -352,7 +351,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, height uint64, window time.Duration) (bool, error) { 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) {
exist, err := r.checkPoWExist(height, params) exist, err := r.checkPoWExist(height, params)
if err != nil { if err != nil {
return false, err return false, err
@ -368,14 +367,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, window) r.writeShare(tx, ms, ts, login, id, diff, actualDiff, height, topHeight, netDiff, window, hostname)
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, roundDiff int64, height uint64, window time.Duration) (bool, error) { func (r *RedisClient) WriteBlock(login, id string, params []string, diff, actualDiff int64, roundDiff int64, height, topHeight uint64, window time.Duration, hostname string) (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
@ -391,9 +390,10 @@ func (r *RedisClient) WriteBlock(login, id string, params []string, diff, roundD
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, window) r.writeShare(tx, ms, ts, login, id, diff, actualDiff, height, topHeight, roundDiff, window, hostname)
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,14 +432,18 @@ func (r *RedisClient) WriteBlock(login, id string, params []string, diff, roundD
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) s := join(hashHex, ts, roundDiff, totalShares, login, actualDiff, personalShares)
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, expire time.Duration) { 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) {
/* # Note To Me: /* # Note To Me:
Will have to write to get from redis the current value for round Will have to write to get from redis the current value for round
shares and increase by 1, then include the new number to be added to redis shares and increase by 1, then include the new number to be added to redis
@ -450,11 +454,13 @@ func (r *RedisClient) writeShare(tx *redis.Multi, ms, ts int64, login, id string
tx.LPush(r.formatKey("lastshares"), login) 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)}) tx.ZAdd(r.formatKey("hashrate"), redis.Z{Score: float64(ts), Member: join(diff, login, id, ms, hostname)})
tx.ZAdd(r.formatKey("hashrate", login), redis.Z{Score: float64(ts), Member: join(diff, id, ms)}) tx.ZAdd(r.formatKey("hashrate", login), redis.Z{Score: float64(ts), Member: join(diff, id, ms, hostname)})
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) {
@ -487,13 +493,6 @@ func join(args ...interface{}) string {
} else { } else {
s[i] = "0" s[i] = "0"
} }
case *big.Rat:
x := v.(*big.Rat)
if x != nil {
s[i] = x.FloatString(9)
} else {
s[i] = "0"
}
case *big.Int: case *big.Int:
n := v.(*big.Int) n := v.(*big.Int)
if n != nil { if n != nil {
@ -501,6 +500,13 @@ func join(args ...interface{}) string {
} else { } else {
s[i] = "0" s[i] = "0"
} }
case *big.Rat:
x := v.(*big.Rat)
if x != nil {
s[i] = x.FloatString(9)
} else {
s[i] = "0"
}
default: default:
panic("Invalid type specified for conversion") panic("Invalid type specified for conversion")
} }
@ -525,7 +531,6 @@ 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)
@ -594,6 +599,15 @@ 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")
@ -687,18 +701,13 @@ 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
@ -706,15 +715,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) addStr := 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) remStr := join(amount, percent, !immature, block.Hash, block.Height, block.Timestamp, block.Difficulty, block.PersonalShares)
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
@ -777,7 +786,6 @@ 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
@ -851,11 +859,9 @@ 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.HGet(r.formatKey("paymentsTotal"), login) tx.ZCard(r.formatKey("payments", 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
}) })
@ -866,7 +872,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.StringCmd).Int64() stats["paymentsTotal"] = cmds[2].(*redis.IntCmd).Val()
shares := cmds[4].(*redis.StringSliceCmd).Val() shares := cmds[4].(*redis.StringSliceCmd).Val()
csh := 0 csh := 0
for _, val := range shares { for _, val := range shares {
@ -950,14 +956,15 @@ 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.HGet(r.formatKey("paymentsTotal"), "all") tx.ZCard(r.formatKey("payments", "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.ZRevRangeWithScores(r.formatKey("finders"), 0, -1) tx.HGetAllMap(r.formatKey("exchange", r.CoinName))
tx.ZRevRangeWithScores(r.formatKey("finders"), 0, -1)
return nil return nil
}) })
if (err != nil) && (err != redis.Nil) { if err != nil {
return nil, err return nil, err
} }
@ -978,15 +985,21 @@ 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.StringCmd).Int64() stats["paymentsTotal"] = cmds[9].(*redis.IntCmd).Val()
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
} }
@ -1003,6 +1016,7 @@ 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)
@ -1017,7 +1031,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[4].(*redis.ZSliceCmd), login, r) workers := convertWorkersStats(smallWindow, cmds[1].(*redis.ZSliceCmd), cmds[5].(*redis.ZSliceCmd))
for id, worker := range workers { for id, worker := range workers {
timeOnline := now - worker.startedAt timeOnline := now - worker.startedAt
@ -1044,7 +1058,7 @@ func (r *RedisClient) CollectWorkersStats(sWindow, lWindow time.Duration, login
online++ online++
} }
blocks := cmds[4].(*redis.ZSliceCmd).Val() blocks := cmds[5].(*redis.ZSliceCmd).Val()
for _, val := range blocks { for _, val := range blocks {
parts := strings.Split(val.Member.(string), ":") parts := strings.Split(val.Member.(string), ":")
@ -1059,68 +1073,25 @@ func (r *RedisClient) CollectWorkersStats(sWindow, lWindow time.Duration, login
currentHashrate += worker.HR currentHashrate += worker.HR
totalHashrate += worker.TotalHR totalHashrate += worker.TotalHR
valid_share, stale_share, invalid_share, _ := r.getSharesStatus(login, id)
worker.ValidShares = int64(5)
worker.StaleShares = int64(5)
worker.InvalidShares = int64(5)
worker.ValidShares = valid_share
worker.StaleShares = stale_share
worker.InvalidShares = invalid_share
//test percentage
worker.ValidPercent = float64(0)
worker.StalePercent = float64(0)
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 {
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
}
///test small hr
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 workers[id] = worker
} }
shares := cmds[2].(*redis.StringSliceCmd).Val()
csh := 0
//var myshares []string
for _, val := range shares {
//text := "█"
if val != login {
//text = "▁"
} else {
csh++
}
//myshares = append(myshares, strconv.FormatInt(int64(ind) 10))
//myshares = append(myshares, text)
}
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
@ -1128,8 +1099,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[2].(*redis.ZSliceCmd)) // last 40 stats["rewards"] = convertRewardResults(cmds[3].(*redis.ZSliceCmd)) // last 40
rewards := convertRewardResults(cmds[3].(*redis.ZSliceCmd)) // all rewards := convertRewardResults(cmds[4].(*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})
@ -1139,30 +1110,27 @@ 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{})
@ -1269,7 +1237,9 @@ 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.Login = fields[6] block.Finder = 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)
} }
@ -1290,6 +1260,11 @@ 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)
} }
} }
@ -1315,7 +1290,9 @@ 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.Login = fields[8] block.Finder = 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)
} }
@ -1325,7 +1302,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, login string, r *RedisClient) map[string]Worker { func convertWorkersStats(window int64, raw *redis.ZSliceCmd, blocks *redis.ZSliceCmd) map[string]Worker {
now := util.MakeTimestamp() / 1000 now := util.MakeTimestamp() / 1000
workers := make(map[string]Worker) workers := make(map[string]Worker)
@ -1340,26 +1317,34 @@ 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)
worker.ValidPercent = float64(0) // Addition from Mohannad Otaibi to report Difficulty
worker.StalePercent = float64(0) worker.WorkerDiff = share
worker.InvalidPercent = float64(0) worker.WorkerHostname = hostname
worker.WorkerStatus = int64(0) // End Mohannad Adjustments
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
} }
@ -1432,7 +1417,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
} }
@ -1448,6 +1433,41 @@ 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"`
@ -1478,7 +1498,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
} }
@ -1492,99 +1512,3 @@ 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