From 84b8b99040288c400314e623736e479a441801e9 Mon Sep 17 00:00:00 2001 From: WeebDataHoarder <57538841+WeebDataHoarder@users.noreply.github.com> Date: Mon, 20 Mar 2023 11:47:09 +0100 Subject: [PATCH] Fixed miner output calculations --- cmd/api/api.go | 6 +- cmd/daemon/daemon.go | 13 +-- database/miner.go | 6 +- p2pool/api/api.go | 218 ++++++++++++++----------------------------- 4 files changed, 79 insertions(+), 164 deletions(-) diff --git a/cmd/api/api.go b/cmd/api/api.go index 3da0078..a54a478 100644 --- a/cmd/api/api.go +++ b/cmd/api/api.go @@ -47,13 +47,13 @@ func main() { log.Panic(err) } defer db.Close() - api, err := p2poolapi.New(db, os.Getenv("API_FOLDER")) + + p2api := p2poolapi.NewP2PoolApi(*p2poolApiHost) + api, err := p2poolapi.New(db, p2api) if err != nil { log.Panic(err) } - p2api := p2poolapi.NewP2PoolApi(*p2poolApiHost) - for status := p2api.Status(); !p2api.Status().Synchronized; status = p2api.Status() { log.Printf("[API] Not synchronized (height %d, id %s), waiting five seconds", status.Height, status.Id) time.Sleep(time.Second * 5) diff --git a/cmd/daemon/daemon.go b/cmd/daemon/daemon.go index c6d326a..175d93a 100644 --- a/cmd/daemon/daemon.go +++ b/cmd/daemon/daemon.go @@ -29,24 +29,17 @@ func main() { log.Panic(err) } defer db.Close() - api, err := p2poolapi.New(db, os.Getenv("API_FOLDER")) + + p2api := p2poolapi.NewP2PoolApi(*p2poolApiHost) + api, err := p2poolapi.New(db, p2api) if err != nil { log.Panic(err) } - p2api := p2poolapi.NewP2PoolApi(*p2poolApiHost) - //TODO: force-insert section tip := db.GetChainTip() - /*bId, _ := types.HashFromString("f36ae9e2ed3e1e2ab7b79c9ac2767692f02c41b2aaf78e16fcc123730354ce86") - b := db.GetBlockById(bId) - if tx, _ := client.GetDefaultClient().GetCoinbaseTransaction(b.Coinbase.Id); tx != nil { - _ = db.SetBlockFound(b.Id, true) - processFoundBlockWithTransaction(api, b, tx) - }*/ - isFresh := tip == nil var tipHeight uint64 diff --git a/database/miner.go b/database/miner.go index 55a6b61..d875650 100644 --- a/database/miner.go +++ b/database/miner.go @@ -52,8 +52,8 @@ func MatchOutputs(c *transaction.CoinbaseTransaction, miners []*Miner, privateKe addresses := make(map[address.PackedAddress]*Miner, len(miners)) outputs := make([]*transaction.Output, len(c.Outputs)) - for i, o := range c.Outputs { - outputs[i] = &o + for i := range c.Outputs { + outputs[i] = &c.Outputs[i] } //TODO: this sorting will be inefficient come the hard fork @@ -89,7 +89,7 @@ func MatchOutputs(c *transaction.CoinbaseTransaction, miners []*Miner, privateKe Output: o, }) outputs[i] = nil - //outputs = slices.Compact(outputs) + outputs = slices.Compact(outputs) break } } diff --git a/p2pool/api/api.go b/p2pool/api/api.go index fbe20d6..47d9eb1 100644 --- a/p2pool/api/api.go +++ b/p2pool/api/api.go @@ -1,31 +1,21 @@ package api import ( - "encoding/json" - "fmt" "git.gammaspectra.live/P2Pool/p2pool-observer/database" - "git.gammaspectra.live/P2Pool/p2pool-observer/p2pool" + "git.gammaspectra.live/P2Pool/p2pool-observer/monero/randomx" + "git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/sidechain" "git.gammaspectra.live/P2Pool/p2pool-observer/types" - "io" - "os" - "path" ) type Api struct { - db *database.Database - path string + db *database.Database + p2api *P2PoolApi } -func New(db *database.Database, p string) (*Api, error) { +func New(db *database.Database, p2api *P2PoolApi) (*Api, error) { api := &Api{ - db: db, - path: path.Clean(p), - } - - if info, err := os.Stat(api.path); err != nil { - return nil, err - } else if !info.IsDir() { - return nil, fmt.Errorf("directory path does not exist %s %s", p, api.path) + db: db, + p2api: p2api, } return api, nil @@ -36,48 +26,91 @@ func (a *Api) GetDatabase() *database.Database { } func (a *Api) GetBlockWindowPayouts(tip *database.Block) (shares map[uint64]types.Difficulty) { + if tip == nil { + return nil + } //TODO: adjust for fork shares = make(map[uint64]types.Difficulty) - blockCount := 0 + var blockDepth uint64 block := tip - blockCache := make(map[uint64]*database.Block, p2pool.PPLNSWindow) - for b := range a.db.GetBlocksInWindow(&tip.Height, p2pool.PPLNSWindow) { + blockCache := make(map[uint64]*database.Block, a.p2api.Consensus().ChainWindowSize) + for b := range a.db.GetBlocksInWindow(&tip.Height, a.p2api.Consensus().ChainWindowSize) { blockCache[b.Height] = b } - for { - if _, ok := shares[block.MinerId]; !ok { - shares[block.MinerId] = types.DifficultyFrom64(0) - } + mainchainDiff := a.p2api.MainDifficultyByHeight(randomx.SeedHeight(tip.Main.Height)) - shares[block.MinerId] = shares[block.MinerId].Add(block.Difficulty) + if mainchainDiff == types.ZeroDifficulty { + return nil + } + + //TODO: remove this hack + sidechainVersion := sidechain.ShareVersion_V1 + if tip.Timestamp >= sidechain.ShareVersion_V2MainNetTimestamp { + sidechainVersion = sidechain.ShareVersion_V2 + } + maxPplnsWeight := types.MaxDifficulty + + if sidechainVersion > sidechain.ShareVersion_V1 { + maxPplnsWeight = mainchainDiff.Mul64(2) + } + var pplnsWeight types.Difficulty + + for { + + curWeight := block.Difficulty for uncle := range a.db.GetUnclesByParentId(block.Id) { - if (tip.Height - uncle.Block.Height) >= p2pool.PPLNSWindow { + if (tip.Height - uncle.Block.Height) >= a.p2api.Consensus().ChainWindowSize { continue } + unclePenalty := uncle.Block.Difficulty.Mul64(a.p2api.Consensus().UnclePenalty).Div64(100) + uncleWeight := uncle.Block.Difficulty.Sub(unclePenalty) + newPplnsWeight := pplnsWeight.Add(uncleWeight) + + if newPplnsWeight.Cmp(maxPplnsWeight) > 0 { + continue + } + + curWeight = curWeight.Add(uncleWeight) + if _, ok := shares[uncle.Block.MinerId]; !ok { shares[uncle.Block.MinerId] = types.DifficultyFrom64(0) } - - product := uncle.Block.Difficulty.Mul64(p2pool.UnclePenalty) - unclePenalty := product.Div64(100) - - shares[block.MinerId] = shares[block.MinerId].Add(unclePenalty) - shares[uncle.Block.MinerId] = shares[uncle.Block.MinerId].Add(uncle.Block.Difficulty.Sub(unclePenalty)) + shares[uncle.Block.MinerId] = shares[uncle.Block.MinerId].Add(uncleWeight) + } + + if _, ok := shares[block.MinerId]; !ok { + shares[block.MinerId] = types.DifficultyFrom64(0) + } + shares[block.MinerId] = shares[block.MinerId].Add(curWeight) + + pplnsWeight = pplnsWeight.Add(curWeight) + + if pplnsWeight.Cmp(maxPplnsWeight) > 0 { + break + } + + blockDepth++ + + if blockDepth >= a.p2api.Consensus().ChainWindowSize { + break + } + + if block.Height == 0 { + break } - blockCount++ if b, ok := blockCache[block.Height-1]; ok && b.Id == block.PreviousId { block = b } else { block = a.db.GetBlockById(block.PreviousId) } - if block == nil || blockCount >= p2pool.PPLNSWindow { + if block == nil { break } } @@ -101,122 +134,11 @@ func (a *Api) GetBlockWindowPayouts(tip *database.Block) (shares map[uint64]type } } - if blockCount != p2pool.PPLNSWindow { + if (block == nil || block.Height != 0) && + ((sidechainVersion == sidechain.ShareVersion_V1 && blockDepth != a.p2api.Consensus().ChainWindowSize) || + (sidechainVersion > sidechain.ShareVersion_V1 && (blockDepth != a.p2api.Consensus().ChainWindowSize) && pplnsWeight.Cmp(maxPplnsWeight) <= 0)) { return nil } return shares } - -func (a *Api) GetWindowPayouts(height, totalReward *uint64) (shares map[uint64]types.Difficulty) { - shares = make(map[uint64]types.Difficulty) - - var tip uint64 - if height != nil { - tip = *height - } else { - tip = a.db.GetChainTip().Height - } - - blockCount := 0 - - for block := range a.db.GetBlocksInWindow(&tip, p2pool.PPLNSWindow) { - if _, ok := shares[block.MinerId]; !ok { - shares[block.MinerId] = types.DifficultyFrom64(0) - } - - shares[block.MinerId] = shares[block.MinerId].Add(block.Difficulty) - - for uncle := range a.db.GetUnclesByParentId(block.Id) { - if (tip - uncle.Block.Height) >= p2pool.PPLNSWindow { - continue - } - - if _, ok := shares[uncle.Block.MinerId]; !ok { - shares[uncle.Block.MinerId] = types.DifficultyFrom64(0) - } - - product := uncle.Block.Difficulty.Mul64(p2pool.UnclePenalty) - unclePenalty := product.Div64(100) - - shares[block.MinerId] = shares[block.MinerId].Add(unclePenalty) - shares[uncle.Block.MinerId] = shares[uncle.Block.MinerId].Add(uncle.Block.Difficulty.Sub(unclePenalty)) - } - - blockCount++ - } - - if totalReward != nil && *totalReward > 0 { - totalWeight := types.DifficultyFrom64(0) - for _, w := range shares { - totalWeight = totalWeight.Add(w) - } - - w := types.DifficultyFrom64(0) - rewardGiven := types.DifficultyFrom64(0) - - for miner, weight := range shares { - w = w.Add(weight) - nextValue := w.Mul64(*totalReward).Div(totalWeight) - shares[miner] = nextValue.Sub(rewardGiven) - rewardGiven = nextValue - } - } - - if blockCount != p2pool.PPLNSWindow { - return nil - } - - return shares -} - -// GetPoolBlocks -// Deprecated -func (a *Api) GetPoolBlocks() (result []struct { - Height uint64 `json:"height"` - Hash types.Hash `json:"hash"` - Difficulty uint64 `json:"difficulty"` - TotalHashes uint64 `json:"totalHashes"` - Ts uint64 `json:"ts"` -}, err error) { - f, err := os.Open(fmt.Sprintf("%s/pool/blocks", a.path)) - if err != nil { - return result, err - } - defer f.Close() - if buf, err := io.ReadAll(f); err != nil { - return result, err - } else { - err = json.Unmarshal(buf, &result) - return result, err - } -} - -// GetPoolStats -// Deprecated -func (a *Api) GetPoolStats() (result struct { - PoolList []string `json:"pool_list"` - PoolStatistics struct { - HashRate uint64 `json:"hashRate"` - Difficulty uint64 `json:"difficulty"` - Hash types.Hash `json:"hash"` - Height uint64 `json:"height"` - Miners uint64 `json:"miners"` - TotalHashes uint64 `json:"totalHashes"` - LastBlockFoundTime uint64 `json:"lastBlockFoundTime"` - LastBlockFound uint64 `json:"lastBlockFound"` - TotalBlocksFound uint64 `json:"totalBlocksFound"` - } `json:"pool_statistics"` -}, err error) { - f, err := os.Open(fmt.Sprintf("%s/pool/stats", a.path)) - if err != nil { - return result, err - } - defer f.Close() - if buf, err := io.ReadAll(f); err != nil { - return result, err - } else { - err = json.Unmarshal(buf, &result) - return result, err - } -}