99 lines
2.9 KiB
Go
99 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/client"
|
|
"git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/cache/archive"
|
|
"git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/sidechain"
|
|
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
|
"github.com/floatdrop/lru"
|
|
"log"
|
|
"math"
|
|
"os"
|
|
)
|
|
|
|
func main() {
|
|
inputConsensus := flag.String("consensus", "config.json", "Input config.json consensus file")
|
|
inputArchive := flag.String("input", "", "Input path for archive database")
|
|
outputArchive := flag.String("output", "", "Output path for archive database")
|
|
moneroHost := flag.String("host", "127.0.0.1", "IP address of your Monero node")
|
|
moneroRpcPort := flag.Uint("rpc-port", 18081, "monerod RPC API port number")
|
|
|
|
flag.Parse()
|
|
|
|
client.SetDefaultClientSettings(fmt.Sprintf("http://%s:%d", *moneroHost, *moneroRpcPort))
|
|
|
|
cf, err := os.ReadFile(*inputConsensus)
|
|
|
|
consensus, err := sidechain.NewConsensusFromJSON(cf)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
difficultyCache := lru.New[uint64, types.Difficulty](1024)
|
|
|
|
getDifficultyByHeight := func(height uint64) types.Difficulty {
|
|
if v := difficultyCache.Get(height); v == nil {
|
|
if r, err := client.GetDefaultClient().GetBlockHeaderByHeight(height, context.Background()); err == nil {
|
|
d := types.DifficultyFrom64(r.BlockHeader.Difficulty)
|
|
difficultyCache.Set(height, d)
|
|
return d
|
|
}
|
|
return types.ZeroDifficulty
|
|
} else {
|
|
return *v
|
|
}
|
|
}
|
|
|
|
inputCache, err := archive.NewCache(*inputArchive, consensus, getDifficultyByHeight)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
defer inputCache.Close()
|
|
|
|
outputCache, err := archive.NewCache(*outputArchive, consensus, getDifficultyByHeight)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
defer outputCache.Close()
|
|
|
|
derivationCache := sidechain.NewDerivationCache()
|
|
|
|
blockCache := lru.New[types.Hash, *sidechain.PoolBlock](int(consensus.ChainWindowSize * 2))
|
|
|
|
getByTemplateId := func(h types.Hash) *sidechain.PoolBlock {
|
|
if v := blockCache.Get(h); v == nil {
|
|
if bs := inputCache.LoadByTemplateId(h); len(bs) != 0 {
|
|
blockCache.Set(h, bs[0])
|
|
return bs[0]
|
|
} else if bs = outputCache.LoadByTemplateId(h); len(bs) != 0 {
|
|
blockCache.Set(h, bs[0])
|
|
return bs[0]
|
|
} else {
|
|
return nil
|
|
}
|
|
} else {
|
|
return *v
|
|
}
|
|
}
|
|
|
|
preAllocatedShares := make(sidechain.Shares, consensus.ChainWindowSize*2)
|
|
for i := range preAllocatedShares {
|
|
preAllocatedShares[i] = &sidechain.Share{}
|
|
}
|
|
for blocksAtHeight := range inputCache.ScanHeights(0, math.MaxUint64) {
|
|
for i, b := range blocksAtHeight {
|
|
if _, err := b.PreProcessBlock(consensus, derivationCache, preAllocatedShares, getDifficultyByHeight, getByTemplateId); err != nil {
|
|
log.Printf("error processing block %s at %d, %s", types.HashFromBytes(b.CoinbaseExtra(sidechain.SideTemplateId)), b.Side.Height, err)
|
|
} else {
|
|
outputCache.Store(b)
|
|
if i == 0 {
|
|
blockCache.Set(types.HashFromBytes(b.CoinbaseExtra(sidechain.SideTemplateId)), b)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|