Added tests for pre-fork p2pool, generalize tests, added patched missing blocks for old mini sidechain test
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
DataHoarder 2023-05-23 21:17:08 +02:00
parent 415cde0759
commit 48915be81b
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
6 changed files with 209 additions and 122 deletions

View file

@ -3,13 +3,75 @@ package sidechain
import (
"context"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/client"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/randomx"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"log"
"os"
"testing"
)
func testPoolBlock(b *PoolBlock, t *testing.T, expectedBufferLength int, majorVersion, minorVersion uint8, sideHeight uint64, nonce uint32, templateId, mainId, expectedPowHash, privateKeySeed, coinbaseId types.Hash, privateKey crypto.PrivateKeyBytes) {
if buf, _ := b.Main.MarshalBinary(); len(buf) != expectedBufferLength {
t.Fatal()
}
powHash := b.PowHash(ConsensusDefault.GetHasher(), func(height uint64) (hash types.Hash) {
seedHeight := randomx.SeedHeight(height)
if h, err := client.GetDefaultClient().GetBlockByHeight(seedHeight, context.Background()); err != nil {
return types.ZeroHash
} else {
return types.MustHashFromString(h.BlockHeader.Hash)
}
})
if b.Main.MajorVersion != majorVersion || b.Main.MinorVersion != minorVersion {
t.Fatal()
}
if b.Side.Height != sideHeight {
t.Fatal()
}
if b.Main.Nonce != nonce {
t.Fatal()
}
if b.SideTemplateId(ConsensusDefault) != templateId {
t.Fatal()
}
if b.MainId() != mainId {
t.Fatal()
}
if powHash != expectedPowHash {
t.Fatal()
}
if !b.IsProofHigherThanDifficulty(ConsensusDefault.GetHasher(), func(height uint64) (hash types.Hash) {
seedHeight := randomx.SeedHeight(height)
if h, err := client.GetDefaultClient().GetBlockByHeight(seedHeight, context.Background()); err != nil {
return types.ZeroHash
} else {
return types.MustHashFromString(h.BlockHeader.Hash)
}
}) {
t.Fatal()
}
if b.Side.CoinbasePrivateKey != privateKey {
t.Fatal()
}
if b.Side.CoinbasePrivateKeySeed != privateKeySeed {
t.Fatal()
}
if b.Main.Coinbase.Id() != coinbaseId {
t.Fatal()
}
}
func TestPoolBlockDecode(t *testing.T) {
if buf, err := os.ReadFile("testdata/block.dat"); err != nil {
@ -20,54 +82,44 @@ func TestPoolBlockDecode(t *testing.T) {
t.Fatal(err)
}
if buf, _ = b.Main.MarshalBinary(); len(buf) != 1757 {
t.Fatal()
}
powHash := b.PowHash(ConsensusDefault.GetHasher(), func(height uint64) (hash types.Hash) {
seedHeight := randomx.SeedHeight(height)
if h, err := client.GetDefaultClient().GetBlockByHeight(seedHeight, context.Background()); err != nil {
return types.ZeroHash
} else {
return types.MustHashFromString(h.BlockHeader.Hash)
}
})
if b.SideTemplateId(ConsensusDefault).String() != "15ecd7e99e78e93bf8bffb1f597046cfa2d604decc32070e36e3caca01597c7d" {
log.Print(b.SideTemplateId(ConsensusDefault))
t.Fatal()
}
if b.MainId().String() != "fc63db007b94b3eba51bbc6e2076b0ac37b49ea554cc310c5e0fa595889960f3" {
t.Fatal()
}
if powHash.String() != "aa7a3c4a2d67cb6a728e244288219bf038024f3b511b0da197a19ec601000000" {
t.Fatal()
}
if !b.IsProofHigherThanDifficulty(ConsensusDefault.GetHasher(), func(height uint64) (hash types.Hash) {
seedHeight := randomx.SeedHeight(height)
if h, err := client.GetDefaultClient().GetBlockByHeight(seedHeight, context.Background()); err != nil {
return types.ZeroHash
} else {
return types.MustHashFromString(h.BlockHeader.Hash)
}
}) {
t.Fatal()
}
if b.Side.CoinbasePrivateKey.String() != "ba757262420e8bfa7c1931c75da051955cd2d4dff35dff7bfff42a1569941405" {
t.Fatal()
}
if b.Side.CoinbasePrivateKeySeed.String() != "fd7b5f77c79e624e26b939028a15f14b250fdb217cd40b4ce524eab9b17082ca" {
t.Fatal()
}
if b.Main.Coinbase.Id().String() != "b52a9222eb2712c43742ed3a598df34c821bfb5d3b5a25d41bb4bdb014505ca9" {
t.Fatal()
}
testPoolBlock(b, t,
1757,
16,
16,
4674483,
1247,
types.MustHashFromString("15ecd7e99e78e93bf8bffb1f597046cfa2d604decc32070e36e3caca01597c7d"),
types.MustHashFromString("fc63db007b94b3eba51bbc6e2076b0ac37b49ea554cc310c5e0fa595889960f3"),
types.MustHashFromString("aa7a3c4a2d67cb6a728e244288219bf038024f3b511b0da197a19ec601000000"),
types.MustHashFromString("fd7b5f77c79e624e26b939028a15f14b250fdb217cd40b4ce524eab9b17082ca"),
types.MustHashFromString("b52a9222eb2712c43742ed3a598df34c821bfb5d3b5a25d41bb4bdb014505ca9"),
crypto.PrivateKeyBytes(types.MustHashFromString("ba757262420e8bfa7c1931c75da051955cd2d4dff35dff7bfff42a1569941405")),
)
}
}
func TestPoolBlockDecodePreFork(t *testing.T) {
if buf, err := os.ReadFile("testdata/old_mainnet_test2_block.dat"); err != nil {
t.Fatal(err)
} else {
b := &PoolBlock{}
if err = b.UnmarshalBinary(ConsensusDefault, &NilDerivationCache{}, buf); err != nil {
t.Fatal(err)
}
testPoolBlock(b, t,
5607,
14,
14,
53450,
2432795907,
types.MustHashFromString("bd39e2870edfd54838fe690f70178bfe4f433198ae0b3c8b0725bdbbddf7ed57"),
types.MustHashFromString("5023d36d54141efae5895eae3d51478fe541c5898ad4d783cef33118b67051f2"),
types.MustHashFromString("f76d731c61c9c9b6c3f46be2e60c9478930b49b4455feecd41ecb9420d000000"),
types.ZeroHash,
types.MustHashFromString("09f4ead399cd8357eff7403562e43fe472f79e47deb39148ff3d681fc8f113ea"),
crypto.PrivateKeyBytes(types.MustHashFromString("fed259c99cb7d21ac94ade82f2909ad1ccabdeafd16eeb60db4ca5eedca86a0a")),
)
}
}

View file

@ -30,27 +30,18 @@ func init() {
client.SetDefaultClientSettings(os.Getenv("MONEROD_RPC_URL"))
}
func TestSideChainDefault(t *testing.T) {
s := NewSideChain(&fakeServer{
consensus: ConsensusDefault,
})
f, err := os.Open("testdata/sidechain_dump.dat")
if err != nil {
t.Fatal(err)
}
func testSideChain(s *SideChain, t *testing.T, reader io.Reader, sideHeight, mainHeight uint64, patchedBlocks ...[]byte) {
var err error
buf := make([]byte, PoolBlockMaxTemplateSize)
for {
buf = buf[:0]
var blockLen uint32
if err = binary.Read(f, binary.LittleEndian, &blockLen); err == io.EOF {
if err = binary.Read(reader, binary.LittleEndian, &blockLen); err == io.EOF {
break
} else if err != nil {
t.Fatal(err)
}
if _, err = io.ReadFull(f, buf[:blockLen]); err != nil {
if _, err = io.ReadFull(reader, buf[:blockLen]); err != nil {
t.Fatal(err)
}
b := &PoolBlock{}
@ -62,6 +53,16 @@ func TestSideChainDefault(t *testing.T) {
}
}
for _, buf := range patchedBlocks {
b := &PoolBlock{}
if err = b.UnmarshalBinary(s.Consensus(), s.DerivationCache(), buf); err != nil {
t.Fatal(err)
}
if err = s.AddPoolBlock(b); err != nil {
t.Fatal(err)
}
}
tip := s.GetChainTip()
if tip == nil {
@ -76,67 +77,11 @@ func TestSideChainDefault(t *testing.T) {
t.Fatal()
}
if tip.Main.Coinbase.GenHeight != 2870010 {
if tip.Main.Coinbase.GenHeight != mainHeight {
t.Fatal()
}
if tip.Side.Height != 4957203 {
t.Fatal()
}
}
func TestSideChainMini(t *testing.T) {
s := NewSideChain(&fakeServer{
consensus: ConsensusMini,
})
f, err := os.Open("testdata/sidechain_dump_mini.dat")
if err != nil {
t.Fatal(err)
}
buf := make([]byte, PoolBlockMaxTemplateSize)
for {
buf = buf[:0]
var blockLen uint32
if err = binary.Read(f, binary.LittleEndian, &blockLen); err == io.EOF {
break
} else if err != nil {
t.Fatal(err)
}
if _, err = io.ReadFull(f, buf[:blockLen]); err != nil {
t.Fatal(err)
}
b := &PoolBlock{}
if err = b.UnmarshalBinary(s.Consensus(), s.DerivationCache(), buf[:blockLen]); err != nil {
t.Fatal(err)
}
if err = s.AddPoolBlock(b); err != nil {
t.Fatal(err)
}
}
tip := s.GetChainTip()
if tip == nil {
t.Fatal()
}
if !tip.Verified.Load() {
t.Fatal()
}
if tip.Invalid.Load() {
t.Fatal()
}
if tip.Main.Coinbase.GenHeight != 2870010 {
t.Fatal()
}
if tip.Side.Height != 4414446 {
if tip.Side.Height != sideHeight {
t.Fatal()
}
@ -157,6 +102,77 @@ func TestSideChainMini(t *testing.T) {
log.Printf("PubKeyToPoint Key Cache hits = %d (%.02f%%), misses = %d (%.02f%%), total = %d", hits, (float64(hits)/float64(total))*100, misses, (float64(misses)/float64(total))*100, total)
}
func TestSideChainDefault(t *testing.T) {
s := NewSideChain(&fakeServer{
consensus: ConsensusDefault,
})
f, err := os.Open("testdata/sidechain_dump.dat")
if err != nil {
t.Fatal(err)
}
defer f.Close()
testSideChain(s, t, f, 4957203, 2870010)
}
func TestSideChainDefaultPreFork(t *testing.T) {
s := NewSideChain(&fakeServer{
consensus: ConsensusDefault,
})
f, err := os.Open("testdata/old_sidechain_dump.dat")
if err != nil {
t.Fatal(err)
}
defer f.Close()
testSideChain(s, t, f, 522805, 2483901)
}
func TestSideChainMini(t *testing.T) {
s := NewSideChain(&fakeServer{
consensus: ConsensusMini,
})
f, err := os.Open("testdata/sidechain_dump_mini.dat")
if err != nil {
t.Fatal(err)
}
defer f.Close()
testSideChain(s, t, f, 4414446, 2870010)
}
func TestSideChainMiniPreFork(t *testing.T) {
s := NewSideChain(&fakeServer{
consensus: ConsensusMini,
})
f, err := os.Open("testdata/old_sidechain_dump_mini.dat")
if err != nil {
t.Fatal(err)
}
defer f.Close()
//patch in missing blocks that are needed to newer reach sync range
block2420028, err := os.ReadFile("testdata/old_sidechain_dump_mini_2420028.dat")
if err != nil {
t.Fatal(err)
}
block2420027, err := os.ReadFile("testdata/old_sidechain_dump_mini_2420027.dat")
if err != nil {
t.Fatal(err)
}
testSideChain(s, t, f, 2424349, 2696040, block2420028, block2420027)
}
type fakeServer struct {
consensus *Consensus
lastHeader atomic.Pointer[mainblock.Header]

7
testdata/.gitignore vendored
View file

@ -3,4 +3,9 @@ crypto_tests.txt
sidechain_dump.dat.gz
sidechain_dump_mini.dat.gz
sidechain_dump.dat
sidechain_dump_mini.dat
sidechain_dump_mini.dat
# old pre-v2 hardfork testdata
old_mainnet_test2_block.dat
old_sidechain_dump.dat
old_sidechain_dump_mini.dat

Binary file not shown.

Binary file not shown.

14
testdata/setup.sh vendored
View file

@ -3,6 +3,16 @@
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
pushd "${SCRIPT_DIR}"
# Pre-v2 p2pool hardfork
OLD_TESTS_COMMIT_ID=b9eb66e2b3e02a5ec358ff8a0c5169a5606d9fde
function download_old_test() {
if [ -f "./old_${1}" ]; then
return
fi
curl --progress-bar --output "./old_${1}" "https://raw.githubusercontent.com/SChernykh/p2pool/${OLD_TESTS_COMMIT_ID}/tests/src/${1}"
}
TESTS_COMMIT_ID=f455ce398c20137a92a67b062c6311580939abea
function download_test() {
@ -24,3 +34,7 @@ download_test block.dat
download_test crypto_tests.txt
download_compressed_test sidechain_dump.dat
download_compressed_test sidechain_dump_mini.dat
download_old_test mainnet_test2_block.dat
download_old_test sidechain_dump.dat
download_old_test sidechain_dump_mini.dat