Fixed miner output calculations
This commit is contained in:
parent
f818b06cd6
commit
84b8b99040
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
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)
|
||||
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))
|
||||
|
||||
if mainchainDiff == types.ZeroDifficulty {
|
||||
return nil
|
||||
}
|
||||
|
||||
shares[block.MinerId] = shares[block.MinerId].Add(block.Difficulty)
|
||||
//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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue