DataHoarder
019375e929
Some checks are pending
continuous-integration/drone/push Build is running
Specify wallet address on login user in xmrig or similar
262 lines
6.3 KiB
Go
262 lines
6.3 KiB
Go
package stratum
|
|
|
|
import (
|
|
"compress/gzip"
|
|
"fmt"
|
|
"git.gammaspectra.live/P2Pool/consensus/v3/monero/address"
|
|
"git.gammaspectra.live/P2Pool/consensus/v3/monero/client"
|
|
"git.gammaspectra.live/P2Pool/consensus/v3/monero/crypto"
|
|
"git.gammaspectra.live/P2Pool/consensus/v3/p2pool/sidechain"
|
|
p2pooltypes "git.gammaspectra.live/P2Pool/consensus/v3/p2pool/types"
|
|
"git.gammaspectra.live/P2Pool/consensus/v3/types"
|
|
"git.gammaspectra.live/P2Pool/consensus/v3/utils"
|
|
unsafeRandom "math/rand/v2"
|
|
"os"
|
|
"path"
|
|
"runtime"
|
|
"slices"
|
|
"testing"
|
|
"time"
|
|
_ "unsafe"
|
|
)
|
|
|
|
var preLoadedMiniSideChain *sidechain.SideChain
|
|
|
|
var preLoadedPoolBlock *sidechain.PoolBlock
|
|
|
|
func init() {
|
|
utils.GlobalLogLevel = 0
|
|
|
|
_, filename, _, _ := runtime.Caller(0)
|
|
// The ".." may change depending on you folder structure
|
|
dir := path.Join(path.Dir(filename), "../..")
|
|
err := os.Chdir(dir)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_ = sidechain.ConsensusDefault.InitHasher(2)
|
|
_ = sidechain.ConsensusMini.InitHasher(2)
|
|
client.SetDefaultClientSettings(os.Getenv("MONEROD_RPC_URL"))
|
|
}
|
|
|
|
func getMinerData() *p2pooltypes.MinerData {
|
|
if d, err := client.GetDefaultClient().GetMinerData(); err != nil {
|
|
return nil
|
|
} else {
|
|
return &p2pooltypes.MinerData{
|
|
MajorVersion: d.MajorVersion,
|
|
Height: d.Height,
|
|
PrevId: types.MustHashFromString(d.PrevId),
|
|
SeedHash: types.MustHashFromString(d.SeedHash),
|
|
Difficulty: types.MustDifficultyFromString(d.Difficulty),
|
|
MedianWeight: d.MedianWeight,
|
|
AlreadyGeneratedCoins: d.AlreadyGeneratedCoins,
|
|
MedianTimestamp: d.MedianTimestamp,
|
|
TimeReceived: time.Now(),
|
|
TxBacklog: nil,
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
if buf, err := os.ReadFile("testdata/block.dat"); err != nil {
|
|
panic(err)
|
|
} else {
|
|
preLoadedPoolBlock = &sidechain.PoolBlock{}
|
|
if err = preLoadedPoolBlock.UnmarshalBinary(sidechain.ConsensusDefault, &sidechain.NilDerivationCache{}, buf); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
_ = sidechain.ConsensusMini.InitHasher(2)
|
|
client.SetDefaultClientSettings(os.Getenv("MONEROD_RPC_URL"))
|
|
|
|
preLoadedMiniSideChain = sidechain.NewSideChain(sidechain.GetFakeTestServer(sidechain.ConsensusMini))
|
|
|
|
f, err := os.Open("testdata/sidechain_dump_mini.dat.gz")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer f.Close()
|
|
|
|
r, err := gzip.NewReader(f)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer r.Close()
|
|
|
|
if err = sidechain.LoadSideChainTestData(preLoadedMiniSideChain, r); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
code := m.Run()
|
|
|
|
os.Exit(code)
|
|
}
|
|
|
|
func TestStratumServer(t *testing.T) {
|
|
stratumServer := NewServer(preLoadedMiniSideChain, func(block *sidechain.PoolBlock) error {
|
|
return nil
|
|
})
|
|
minerData := getMinerData()
|
|
tip := preLoadedMiniSideChain.GetChainTip()
|
|
stratumServer.HandleMinerData(minerData)
|
|
stratumServer.HandleTip(tip)
|
|
|
|
func() {
|
|
//Process all incoming changes first
|
|
for {
|
|
select {
|
|
case f := <-stratumServer.incomingChanges:
|
|
if f() {
|
|
stratumServer.Update()
|
|
}
|
|
default:
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
|
|
tpl, _, _, seedHash, err := stratumServer.BuildTemplate(address.FromBase58(types.DonationAddress).ToPackedAddress(), false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if seedHash != minerData.SeedHash {
|
|
t.Fatal()
|
|
}
|
|
|
|
if tpl.MainHeight != minerData.Height {
|
|
t.Fatal()
|
|
}
|
|
|
|
if tpl.MainParent != minerData.PrevId {
|
|
t.Fatal()
|
|
}
|
|
|
|
if tpl.SideHeight != (tip.Side.Height + 1) {
|
|
t.Fatal()
|
|
}
|
|
|
|
if tpl.SideParent != tip.SideTemplateId(preLoadedMiniSideChain.Consensus()) {
|
|
t.Fatal()
|
|
}
|
|
}
|
|
|
|
func TestShuffleMapping(t *testing.T) {
|
|
const n = 16
|
|
const shareVersion = sidechain.ShareVersion_V2
|
|
var seed = zeroExtraBaseRCTHash
|
|
mappings := BuildShuffleMapping(n, shareVersion, seed)
|
|
|
|
seq := make([]int, n)
|
|
for i := range seq {
|
|
seq[i] = i
|
|
}
|
|
|
|
seq1 := slices.Clone(seq)
|
|
|
|
sidechain.ShuffleShares(seq1, shareVersion, seed)
|
|
seq2 := ApplyShuffleMapping(seq, mappings)
|
|
|
|
if slices.Compare(seq1, seq2) != 0 {
|
|
for i := range seq1 {
|
|
if seq1[i] != seq2[i] {
|
|
t.Logf("%d %d *** @ %d", seq1[i], seq2[i], i)
|
|
} else {
|
|
t.Logf("%d %d @ %d", seq1[i], seq2[i], i)
|
|
}
|
|
}
|
|
|
|
t.Fatal()
|
|
}
|
|
|
|
}
|
|
|
|
func BenchmarkServer_FillTemplate(b *testing.B) {
|
|
stratumServer := NewServer(preLoadedMiniSideChain, func(block *sidechain.PoolBlock) error {
|
|
return nil
|
|
})
|
|
minerData := getMinerData()
|
|
tip := preLoadedMiniSideChain.GetChainTip()
|
|
stratumServer.minerData = minerData
|
|
stratumServer.tip = tip
|
|
|
|
b.ResetTimer()
|
|
|
|
b.Run("New", func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
if err := stratumServer.fillNewTemplateData(minerData.Difficulty); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
b.ReportAllocs()
|
|
})
|
|
|
|
b.Run("Cached", func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
if err := stratumServer.fillNewTemplateData(types.ZeroDifficulty); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
b.ReportAllocs()
|
|
})
|
|
|
|
}
|
|
|
|
func BenchmarkServer_BuildTemplate(b *testing.B) {
|
|
stratumServer := NewServer(preLoadedMiniSideChain, func(block *sidechain.PoolBlock) error {
|
|
return nil
|
|
})
|
|
minerData := getMinerData()
|
|
tip := preLoadedMiniSideChain.GetChainTip()
|
|
stratumServer.minerData = minerData
|
|
stratumServer.tip = tip
|
|
|
|
if err := stratumServer.fillNewTemplateData(minerData.Difficulty); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
const randomPoolSize = 512
|
|
var randomKeys [randomPoolSize]address.PackedAddress
|
|
|
|
//generate random keys deterministically
|
|
for i := range randomKeys {
|
|
spendPriv, viewPriv := crypto.DeterministicScalar([]byte(fmt.Sprintf("BenchmarkBuildTemplate_%d_spend", i))), crypto.DeterministicScalar([]byte(fmt.Sprintf("BenchmarkBuildTemplate_%d_spend", i)))
|
|
randomKeys[i][0] = (*crypto.PrivateKeyScalar)(spendPriv).PublicKey().AsBytes()
|
|
randomKeys[i][1] = (*crypto.PrivateKeyScalar)(viewPriv).PublicKey().AsBytes()
|
|
}
|
|
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
|
|
b.Run("Cached", func(b *testing.B) {
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
counter := unsafeRandom.IntN(randomPoolSize)
|
|
for pb.Next() {
|
|
a := randomKeys[counter%randomPoolSize]
|
|
if _, _, _, _, err := stratumServer.BuildTemplate(a, false); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
counter++
|
|
}
|
|
})
|
|
b.ReportAllocs()
|
|
})
|
|
|
|
b.Run("Forced", func(b *testing.B) {
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
counter := unsafeRandom.IntN(randomPoolSize)
|
|
for pb.Next() {
|
|
a := randomKeys[counter%randomPoolSize]
|
|
if _, _, _, _, err := stratumServer.BuildTemplate(a, true); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
counter++
|
|
}
|
|
})
|
|
b.ReportAllocs()
|
|
})
|
|
}
|