Skip to content

(WIP) PPLNS support #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Modern beautiful Ember.js frontend
* Separate stats for workers: can highlight timed-out workers so miners can perform maintenance of rigs
* JSON-API for stats
* PPLNS block reward

#### Proxies

Expand Down
1 change: 1 addition & 0 deletions config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"threads": 2,
"coin": "eth",
"name": "main",
"pplns": 9000,

"proxy": {
"enabled": true,
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func main() {

startNewrelic()

backend = storage.NewRedisClient(&cfg.Redis, cfg.Coin)
backend = storage.NewRedisClient(&cfg.Redis, cfg.Coin, cfg.Pplns)
pong, err := backend.Check()
if err != nil {
log.Printf("Can't establish connection to backend: %v", err)
Expand Down
7 changes: 6 additions & 1 deletion payouts/unlocker.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,12 @@ func (u *BlockUnlocker) calculateRewards(block *storage.BlockData) (*big.Rat, *b
return nil, nil, nil, nil, err
}

rewards := calculateRewardsForShares(shares, block.TotalShares, minersProfit)
totalShares := int64(0)
for _, val := range shares {
totalShares += val
}

rewards := calculateRewardsForShares(shares, totalShares, minersProfit)

if block.ExtraReward != nil {
extraReward := new(big.Rat).SetInt(block.ExtraReward)
Expand Down
1 change: 1 addition & 0 deletions proxy/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Config struct {
Threads int `json:"threads"`

Coin string `json:"coin"`
Pplns int64 `json:"pplns"`
Redis storage.Config `json:"redis"`

BlockUnlocker payouts.UnlockerConfig `json:"unlocker"`
Expand Down
58 changes: 50 additions & 8 deletions storage/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Config struct {
type RedisClient struct {
client *redis.Client
prefix string
pplns int64
}

type BlockData struct {
Expand Down Expand Up @@ -78,14 +79,14 @@ type Worker struct {
TotalHR int64 `json:"hr2"`
}

func NewRedisClient(cfg *Config, prefix string) *RedisClient {
func NewRedisClient(cfg *Config, prefix string, pplns int64) *RedisClient {
client := redis.NewClient(&redis.Options{
Addr: cfg.Endpoint,
Password: cfg.Password,
DB: cfg.Database,
PoolSize: cfg.PoolSize,
})
return &RedisClient{client: client, prefix: prefix}
return &RedisClient{client: client, prefix: prefix, pplns: pplns}
}

func (r *RedisClient) Client() *redis.Client {
Expand Down Expand Up @@ -210,14 +211,36 @@ func (r *RedisClient) WriteBlock(login, id string, params []string, diff, roundD
tx.HDel(r.formatKey("stats"), "roundShares")
tx.ZIncrBy(r.formatKey("finders"), 1, login)
tx.HIncrBy(r.formatKey("miners", login), "blocksFound", 1)
tx.Rename(r.formatKey("shares", "roundCurrent"), r.formatRound(int64(height), params[0]))
tx.HGetAllMap(r.formatRound(int64(height), params[0]))
tx.HGetAllMap(r.formatKey("shares", "roundCurrent"))
tx.Del(r.formatKey("shares", "roundCurrent"))
tx.LRange(r.formatKey("lastshares"), 0, r.pplns)
return nil
})
if err != nil {
return false, err
} else {
sharesMap, _ := cmds[10].(*redis.StringStringMapCmd).Result()

shares := cmds[len(cmds)-1].(*redis.StringSliceCmd).Val()

tx2 := r.client.Multi()
defer tx2.Close()

totalshares := make(map[string]int64)
for _, val := range shares {
totalshares[val] += 1
}

_, err := tx2.Exec(func() error {
for k, v := range totalshares {
tx2.HIncrBy(r.formatRound(int64(height), params[0]), k, v)
}
return nil
})
if err != nil {
return false, err
}

sharesMap, _ := cmds[len(cmds)-3].(*redis.StringStringMapCmd).Result()
totalShares := int64(0)
for _, v := range sharesMap {
n, _ := strconv.ParseInt(v, 10, 64)
Expand All @@ -231,6 +254,9 @@ func (r *RedisClient) WriteBlock(login, id string, params []string, diff, roundD
}

func (r *RedisClient) writeShare(tx *redis.Multi, ms, ts int64, login, id string, diff int64, expire time.Duration) {
tx.LPush(r.formatKey("lastshares"), login)
tx.LTrim(r.formatKey("lastshares"), 0, r.pplns)

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", login), redis.Z{Score: float64(ts), Member: join(diff, id, ms)})
Expand Down Expand Up @@ -271,6 +297,13 @@ func join(args ...interface{}) string {
} else {
s[i] = "0"
}
case *big.Rat:
x := v.(*big.Rat)
if x != nil {
s[i] = x.FloatString(9)
} else {
s[i] = "0"
}
default:
panic("Invalid type specified for conversion")
}
Expand Down Expand Up @@ -577,7 +610,8 @@ func (r *RedisClient) GetMinerStats(login string, maxPayments int64) (map[string
tx.HGetAllMap(r.formatKey("miners", login))
tx.ZRevRangeWithScores(r.formatKey("payments", login), 0, maxPayments-1)
tx.ZCard(r.formatKey("payments", login))
tx.HGet(r.formatKey("shares", "roundCurrent"), login)
tx.HGet(r.formatKey("shares", "currentShares"), login)
tx.LRange(r.formatKey("lastshares"), 0, r.pplns)
return nil
})

Expand All @@ -589,8 +623,14 @@ func (r *RedisClient) GetMinerStats(login string, maxPayments int64) (map[string
payments := convertPaymentsResults(cmds[1].(*redis.ZSliceCmd))
stats["payments"] = payments
stats["paymentsTotal"] = cmds[2].(*redis.IntCmd).Val()
roundShares, _ := cmds[3].(*redis.StringCmd).Int64()
stats["roundShares"] = roundShares
shares := cmds[4].(*redis.StringSliceCmd).Val()
csh := 0
for _, val := range shares {
if val == login {
csh++
}
}
stats["roundShares"] = csh
}

return stats, nil
Expand Down Expand Up @@ -668,6 +708,7 @@ func (r *RedisClient) CollectStats(smallWindow time.Duration, maxBlocks, maxPaym
tx.ZCard(r.formatKey("blocks", "matured"))
tx.ZCard(r.formatKey("payments", "all"))
tx.ZRevRangeWithScores(r.formatKey("payments", "all"), 0, maxPayments-1)
tx.LLen(r.formatKey("lastshares"))
return nil
})

Expand All @@ -676,6 +717,7 @@ func (r *RedisClient) CollectStats(smallWindow time.Duration, maxBlocks, maxPaym
}

result, _ := cmds[2].(*redis.StringStringMapCmd).Result()
result["nShares"] = strconv.FormatInt(cmds[11].(*redis.IntCmd).Val(), 10)
stats["stats"] = convertStringMap(result)
candidates := convertCandidateResults(cmds[3].(*redis.ZSliceCmd))
stats["candidates"] = candidates
Expand Down
2 changes: 1 addition & 1 deletion storage/redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var r *RedisClient
const prefix = "test"

func TestMain(m *testing.M) {
r = NewRedisClient(&Config{Endpoint: "127.0.0.1:6379"}, prefix)
r = NewRedisClient(&Config{Endpoint: "127.0.0.1:6379"}, prefix, 3000)
reset()
c := m.Run()
reset()
Expand Down
2 changes: 1 addition & 1 deletion www/app/controllers/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default Ember.Controller.extend({

roundPercent: Ember.computed('stats', 'model', {
get() {
var percent = this.get('model.roundShares') / this.get('stats.roundShares');
var percent = this.get('model.roundShares') / this.get('stats.nShares');
if (!percent) {
return 0;
}
Expand Down