Added new testdata system using p2pool vectors
This commit is contained in:
parent
e3f50dd515
commit
edbb610533
|
@ -196,7 +196,7 @@ func main() {
|
|||
return b
|
||||
}
|
||||
}, func(b *sidechain.PoolBlock, weight types.Difficulty) {
|
||||
miners[indexDb.GetOrCreateMinerPackedAddress(*b.GetAddress()).Id()]++
|
||||
miners[indexDb.GetOrCreateMinerPackedAddress(b.GetAddress()).Id()]++
|
||||
pplnsWeight = pplnsWeight.Add(weight)
|
||||
|
||||
if i := slices.IndexFunc(versions, func(entry sideChainVersionEntry) bool {
|
||||
|
|
|
@ -483,7 +483,7 @@ func main() {
|
|||
if len(args) != 1 {
|
||||
return nil
|
||||
}
|
||||
return args[0].(*sidechain.PoolBlock).GetAddress().ToBase58()
|
||||
return args[0].(*sidechain.PoolBlock).GetAddress().Reference().ToBase58()
|
||||
}
|
||||
|
||||
env.Functions["extra_nonce"] = func(ctx stick.Context, args ...stick.Value) stick.Value {
|
||||
|
|
|
@ -102,7 +102,7 @@ func (b *SideBlock) FromPoolBlock(i *Index, block *sidechain.PoolBlock, getSeedB
|
|||
b.MainHeight = block.Main.Coinbase.GenHeight
|
||||
b.SideHeight = block.Side.Height
|
||||
b.ParentTemplateId = block.Side.Parent
|
||||
b.Miner = i.GetOrCreateMinerPackedAddress(*block.GetAddress()).id
|
||||
b.Miner = i.GetOrCreateMinerPackedAddress(block.GetAddress()).id
|
||||
b.Nonce = block.Main.Nonce
|
||||
b.ExtraNonce = binary.LittleEndian.Uint32(block.CoinbaseExtra(sidechain.SideExtraNonce))
|
||||
b.Timestamp = block.Main.Timestamp
|
||||
|
|
|
@ -119,3 +119,7 @@ func (p *PackedAddress) ToAddress() *Address {
|
|||
func (p *PackedAddress) ToBase58() string {
|
||||
return p.ToAddress().ToBase58()
|
||||
}
|
||||
|
||||
func (p PackedAddress) Reference() *PackedAddress {
|
||||
return &p
|
||||
}
|
||||
|
|
|
@ -118,7 +118,9 @@ func NewShareFromExportedBytes(buf []byte, consensus *Consensus, cacheInterface
|
|||
switch version {
|
||||
case 1:
|
||||
|
||||
if _, err = io.ReadFull(reader, b.cache.mainId[:]); err != nil {
|
||||
var mainId types.Hash
|
||||
|
||||
if _, err = io.ReadFull(reader, mainId[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -126,14 +128,18 @@ func NewShareFromExportedBytes(buf []byte, consensus *Consensus, cacheInterface
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err = binary.Read(reader, binary.BigEndian, &b.cache.mainDifficulty.Hi); err != nil {
|
||||
var mainDifficulty types.Difficulty
|
||||
|
||||
if err = binary.Read(reader, binary.BigEndian, &mainDifficulty.Hi); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = binary.Read(reader, binary.BigEndian, &b.cache.mainDifficulty.Lo); err != nil {
|
||||
if err = binary.Read(reader, binary.BigEndian, &mainDifficulty.Lo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.cache.mainDifficulty.ReverseBytes()
|
||||
mainDifficulty.ReverseBytes()
|
||||
|
||||
_ = mainDifficulty
|
||||
|
||||
if err = binary.Read(reader, binary.BigEndian, &mainDataSize); err != nil {
|
||||
return nil, err
|
||||
|
@ -205,8 +211,6 @@ func NewShareFromExportedBytes(buf []byte, consensus *Consensus, cacheInterface
|
|||
b.FillPrivateKeys(cacheInterface)
|
||||
|
||||
//zero cache as it can be wrong
|
||||
b.cache.mainDifficulty = types.ZeroDifficulty
|
||||
b.cache.mainId = types.ZeroHash
|
||||
b.cache.templateId = types.ZeroHash
|
||||
b.cache.powHash = types.ZeroHash
|
||||
|
||||
|
@ -308,24 +312,7 @@ func (b *PoolBlock) CoinbaseExtra(tag CoinbaseExtraTag) []byte {
|
|||
}
|
||||
|
||||
func (b *PoolBlock) MainId() types.Hash {
|
||||
if hash, ok := func() (types.Hash, bool) {
|
||||
b.cache.lock.RLock()
|
||||
defer b.cache.lock.RUnlock()
|
||||
|
||||
if b.cache.mainId != types.ZeroHash {
|
||||
return b.cache.mainId, true
|
||||
}
|
||||
return types.ZeroHash, false
|
||||
}(); ok {
|
||||
return hash
|
||||
} else {
|
||||
b.cache.lock.Lock()
|
||||
defer b.cache.lock.Unlock()
|
||||
if b.cache.mainId == types.ZeroHash { //check again for race
|
||||
b.cache.mainId = b.Main.Id()
|
||||
}
|
||||
return b.cache.mainId
|
||||
}
|
||||
return b.Main.Id()
|
||||
}
|
||||
|
||||
func (b *PoolBlock) FullId() FullId {
|
||||
|
@ -353,24 +340,7 @@ func (b *PoolBlock) CalculateFullId(consensus *Consensus) FullId {
|
|||
}
|
||||
|
||||
func (b *PoolBlock) MainDifficulty(f mainblock.GetDifficultyByHeightFunc) types.Difficulty {
|
||||
if difficulty, ok := func() (types.Difficulty, bool) {
|
||||
b.cache.lock.RLock()
|
||||
defer b.cache.lock.RUnlock()
|
||||
|
||||
if b.cache.mainDifficulty != types.ZeroDifficulty {
|
||||
return b.cache.mainDifficulty, true
|
||||
}
|
||||
return types.ZeroDifficulty, false
|
||||
}(); ok {
|
||||
return difficulty
|
||||
} else {
|
||||
b.cache.lock.Lock()
|
||||
defer b.cache.lock.Unlock()
|
||||
if b.cache.mainDifficulty == types.ZeroDifficulty { //check again for race
|
||||
b.cache.mainDifficulty = b.Main.Difficulty(f)
|
||||
}
|
||||
return b.cache.mainDifficulty
|
||||
}
|
||||
return b.Main.Difficulty(f)
|
||||
}
|
||||
|
||||
func (b *PoolBlock) SideTemplateId(consensus *Consensus) types.Hash {
|
||||
|
@ -653,9 +623,8 @@ func (b *PoolBlock) CalculateTransactionPrivateKeySeed() types.Hash {
|
|||
return types.Hash(b.Side.PublicSpendKey.AsBytes())
|
||||
}
|
||||
|
||||
func (b *PoolBlock) GetAddress() *address.PackedAddress {
|
||||
a := address.NewPackedAddressFromBytes(b.Side.PublicSpendKey, b.Side.PublicViewKey)
|
||||
return &a
|
||||
func (b *PoolBlock) GetAddress() address.PackedAddress {
|
||||
return address.NewPackedAddressFromBytes(b.Side.PublicSpendKey, b.Side.PublicViewKey)
|
||||
}
|
||||
|
||||
func (b *PoolBlock) GetTransactionOutputType() uint8 {
|
||||
|
@ -670,12 +639,9 @@ func (b *PoolBlock) GetTransactionOutputType() uint8 {
|
|||
}
|
||||
|
||||
type poolBlockCache struct {
|
||||
lock sync.RWMutex
|
||||
mainId types.Hash
|
||||
mainDifficulty types.Difficulty
|
||||
templateId types.Hash
|
||||
powHash types.Hash
|
||||
fullId FullId
|
||||
lock sync.RWMutex
|
||||
templateId types.Hash
|
||||
powHash types.Hash
|
||||
}
|
||||
|
||||
func (c *poolBlockCache) FromReader(reader readerAndByteReader) (err error) {
|
||||
|
@ -690,21 +656,15 @@ func (c *poolBlockCache) UnmarshalBinary(buf []byte) error {
|
|||
if len(buf) < types.HashSize*3+types.DifficultySize+FullIdSize {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
copy(c.mainId[:], buf)
|
||||
c.mainDifficulty = types.DifficultyFromBytes(buf[types.HashSize:])
|
||||
copy(c.templateId[:], buf[types.HashSize+types.DifficultySize:])
|
||||
copy(c.powHash[:], buf[types.HashSize+types.DifficultySize+types.HashSize:])
|
||||
copy(c.fullId[:], buf[types.HashSize+types.DifficultySize+types.HashSize+types.HashSize:])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *poolBlockCache) MarshalBinary() ([]byte, error) {
|
||||
buf := make([]byte, 0, types.HashSize*3+types.DifficultySize+FullIdSize)
|
||||
buf = append(buf, c.mainId[:]...)
|
||||
buf = append(buf, c.mainDifficulty.Bytes()...)
|
||||
buf = append(buf, c.templateId[:]...)
|
||||
buf = append(buf, c.powHash[:]...)
|
||||
buf = append(buf, c.fullId[:]...)
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
|
|
@ -2,114 +2,72 @@ package sidechain
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/address"
|
||||
block2 "git.gammaspectra.live/P2Pool/p2pool-observer/monero/block"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/client"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/randomx"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPoolBlockDecode(t *testing.T) {
|
||||
client.SetDefaultClientSettings(os.Getenv("MONEROD_RPC_URL"))
|
||||
|
||||
f, err := os.Open("testdata/1783223a701d16192ce9ff83c603b48b3e1785e3779b42079ede6e52ea7f0d2d.hex")
|
||||
if err != nil {
|
||||
if buf, err := os.ReadFile("testdata/block.dat"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
buf, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
contents, err := hex.DecodeString(string(buf))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
block, err := NewShareFromExportedBytes(contents, ConsensusDefault, &NilDerivationCache{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
mainId := block.MainId()
|
||||
|
||||
if hex.EncodeToString(mainId[:]) != "05892769e709b6cfebd5d71e5cadf38ba0abde8048a0eea3792d981861ad9a69" {
|
||||
t.Fatalf("expected main id 05892769e709b6cfebd5d71e5cadf38ba0abde8048a0eea3792d981861ad9a69, got %s", mainId.String())
|
||||
}
|
||||
if hex.EncodeToString(block.CoinbaseExtra(SideTemplateId)) != "1783223a701d16192ce9ff83c603b48b3e1785e3779b42079ede6e52ea7f0d2d" {
|
||||
t.Fatalf("expected side id 1783223a701d16192ce9ff83c603b48b3e1785e3779b42079ede6e52ea7f0d2d, got %s", hex.EncodeToString(block.CoinbaseExtra(SideTemplateId)))
|
||||
}
|
||||
|
||||
b1, _ := block.Main.MarshalBinary()
|
||||
main2 := &block2.Block{}
|
||||
if err = main2.UnmarshalBinary(b1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if main2.Id() != block.Main.Id() {
|
||||
t.Fatalf("expected main id %s, got %s", block.Main.Id().String(), main2.Id())
|
||||
}
|
||||
|
||||
b2, _ := block.Main.MarshalBinary()
|
||||
side2 := &SideData{}
|
||||
if err = side2.UnmarshalBinary(b2, block.ShareVersion()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log(block.SideTemplateId(ConsensusDefault).String())
|
||||
|
||||
t.Log(block.Side.CoinbasePrivateKey.String())
|
||||
t.Log(address.GetDeterministicTransactionPrivateKey(block.GetPrivateKeySeed(), block.Main.PreviousId).String())
|
||||
|
||||
txId := block.Main.Coinbase.Id()
|
||||
|
||||
if txId.String() != "41e8976fafbf9263996733b8f857a11ca385a78798c33617af8c77cfd989da60" {
|
||||
t.Fatalf("expected coinbase id 41e8976fafbf9263996733b8f857a11ca385a78798c33617af8c77cfd989da60, got %s", txId.String())
|
||||
}
|
||||
|
||||
proofResult, _ := types.DifficultyFromString("00000000000000000000006ef6334490")
|
||||
|
||||
getSeedByHeight := func(height uint64) (hash types.Hash) {
|
||||
seedHeight := randomx.SeedHeight(height)
|
||||
if h, err := client.GetDefaultClient().GetBlockHeaderByHeight(seedHeight, context.Background()); err != nil {
|
||||
return types.ZeroHash
|
||||
} else {
|
||||
hash, _ := types.HashFromString(h.BlockHeader.Hash)
|
||||
return hash
|
||||
} else {
|
||||
b := &PoolBlock{}
|
||||
if err = b.UnmarshalBinary(ConsensusDefault, &NilDerivationCache{}, buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
getDifficultyByHeight := func(height uint64) types.Difficulty {
|
||||
if h, err := client.GetDefaultClient().GetBlockHeaderByHeight(height, context.Background()); err != nil {
|
||||
return types.ZeroDifficulty
|
||||
} else {
|
||||
return types.DifficultyFrom64(h.BlockHeader.Difficulty)
|
||||
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()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if types.DifficultyFromPoW(block.PowHash(getSeedByHeight)).Cmp(proofResult) != 0 {
|
||||
t.Fatalf("expected PoW difficulty %s, got %s", proofResult.String(), types.DifficultyFromPoW(block.PowHash(getSeedByHeight)).String())
|
||||
}
|
||||
|
||||
t.Log(block.Main.Id().String())
|
||||
//t.Log(block.Main.PowHash().String())
|
||||
//t.Log(block.Main.PowHash().String())
|
||||
|
||||
if !block.IsProofHigherThanMainDifficulty(getDifficultyByHeight, getSeedByHeight) {
|
||||
t.Fatal("expected proof higher than difficulty")
|
||||
}
|
||||
|
||||
block.cache.powHash[31] = 1
|
||||
|
||||
if block.IsProofHigherThanMainDifficulty(getDifficultyByHeight, getSeedByHeight) {
|
||||
t.Fatal("expected proof lower than difficulty")
|
||||
}
|
||||
|
||||
log.Print(types.DifficultyFromPoW(block.PowHash(getSeedByHeight)).String())
|
||||
log.Print(block.MainDifficulty(getDifficultyByHeight).String())
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ func (c *SideChain) AddPoolBlockExternal(block *PoolBlock) (missingBlocks []type
|
|||
}
|
||||
|
||||
if block.Side.Difficulty.Cmp64(c.Consensus().MinimumDifficulty) < 0 {
|
||||
return nil, fmt.Errorf("block mined by %s has invalid difficulty %s, expected >= %d", block.GetAddress().ToBase58(), block.Side.Difficulty.StringNumeric(), c.Consensus().MinimumDifficulty), true
|
||||
return nil, fmt.Errorf("block mined by %s has invalid difficulty %s, expected >= %d", block.GetAddress().Reference().ToBase58(), block.Side.Difficulty.StringNumeric(), c.Consensus().MinimumDifficulty), true
|
||||
}
|
||||
|
||||
//TODO: cache?
|
||||
|
@ -197,7 +197,7 @@ func (c *SideChain) AddPoolBlockExternal(block *PoolBlock) (missingBlocks []type
|
|||
}
|
||||
|
||||
if tooLowDiff {
|
||||
return nil, fmt.Errorf("block mined by %s has too low difficulty %s, expected >= %s", block.GetAddress().ToBase58(), block.Side.Difficulty.StringNumeric(), expectedDifficulty.StringNumeric()), false
|
||||
return nil, fmt.Errorf("block mined by %s has too low difficulty %s, expected >= %s", block.GetAddress().Reference().ToBase58(), block.Side.Difficulty.StringNumeric(), expectedDifficulty.StringNumeric()), false
|
||||
}
|
||||
|
||||
// This check is not always possible to perform because of mainchain reorgs
|
||||
|
@ -307,7 +307,7 @@ func (c *SideChain) verifyLoop(blockToVerify *PoolBlock) (err error) {
|
|||
}
|
||||
|
||||
if verification, invalid := c.verifyBlock(block); invalid != nil {
|
||||
log.Printf("[SideChain] block at height = %d, id = %s, mainchain height = %d, mined by %s is invalid: %s", block.Side.Height, block.SideTemplateId(c.Consensus()), block.Main.Coinbase.GenHeight, block.GetAddress().ToBase58(), invalid.Error())
|
||||
log.Printf("[SideChain] block at height = %d, id = %s, mainchain height = %d, mined by %s is invalid: %s", block.Side.Height, block.SideTemplateId(c.Consensus()), block.Main.Coinbase.GenHeight, block.GetAddress().Reference().ToBase58(), invalid.Error())
|
||||
block.Invalid.Store(true)
|
||||
block.Verified.Store(verification == nil)
|
||||
if block == blockToVerify {
|
||||
|
@ -323,12 +323,12 @@ func (c *SideChain) verifyLoop(blockToVerify *PoolBlock) (err error) {
|
|||
block.Invalid.Store(false)
|
||||
|
||||
if block.ShareVersion() > ShareVersion_V1 {
|
||||
log.Printf("[SideChain] verified block at height = %d, depth = %d, id = %s, mainchain height = %d, mined by %s via %s %s", block.Side.Height, block.Depth.Load(), block.SideTemplateId(c.Consensus()), block.Main.Coinbase.GenHeight, block.GetAddress().ToBase58(), block.Side.ExtraBuffer.SoftwareId, block.Side.ExtraBuffer.SoftwareVersion)
|
||||
log.Printf("[SideChain] verified block at height = %d, depth = %d, id = %s, mainchain height = %d, mined by %s via %s %s", block.Side.Height, block.Depth.Load(), block.SideTemplateId(c.Consensus()), block.Main.Coinbase.GenHeight, block.GetAddress().Reference().ToBase58(), block.Side.ExtraBuffer.SoftwareId, block.Side.ExtraBuffer.SoftwareVersion)
|
||||
} else {
|
||||
if signalingVersion := block.ShareVersionSignaling(); signalingVersion > ShareVersion_None {
|
||||
log.Printf("[SideChain] verified block at height = %d, depth = %d, id = %s, mainchain height = %d, mined by %s, signaling v%d", block.Side.Height, block.Depth.Load(), block.SideTemplateId(c.Consensus()), block.Main.Coinbase.GenHeight, block.GetAddress().ToBase58(), signalingVersion)
|
||||
log.Printf("[SideChain] verified block at height = %d, depth = %d, id = %s, mainchain height = %d, mined by %s, signaling v%d", block.Side.Height, block.Depth.Load(), block.SideTemplateId(c.Consensus()), block.Main.Coinbase.GenHeight, block.GetAddress().Reference().ToBase58(), signalingVersion)
|
||||
} else {
|
||||
log.Printf("[SideChain] verified block at height = %d, depth = %d, id = %s, mainchain height = %d, mined by %s", block.Side.Height, block.Depth.Load(), block.SideTemplateId(c.Consensus()), block.Main.Coinbase.GenHeight, block.GetAddress().ToBase58())
|
||||
log.Printf("[SideChain] verified block at height = %d, depth = %d, id = %s, mainchain height = %d, mined by %s", block.Side.Height, block.Depth.Load(), block.SideTemplateId(c.Consensus()), block.Main.Coinbase.GenHeight, block.GetAddress().Reference().ToBase58())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
215
p2pool/sidechain/sidechain_test.go
Normal file
215
p2pool/sidechain/sidechain_test.go
Normal file
|
@ -0,0 +1,215 @@
|
|||
package sidechain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
mainblock "git.gammaspectra.live/P2Pool/p2pool-observer/monero/block"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/client"
|
||||
p2pooltypes "git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/types"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"io"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = ConsensusDefault.InitHasher(2)
|
||||
_ = ConsensusMini.InitHasher(2)
|
||||
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)
|
||||
}
|
||||
|
||||
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 != 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 {
|
||||
t.Fatal()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type fakeServer struct {
|
||||
consensus *Consensus
|
||||
lastHeader atomic.Pointer[mainblock.Header]
|
||||
}
|
||||
|
||||
func (s *fakeServer) Consensus() *Consensus {
|
||||
return s.consensus
|
||||
}
|
||||
|
||||
func (s *fakeServer) GetBlob(key []byte) (blob []byte, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *fakeServer) SetBlob(key, blob []byte) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *fakeServer) RemoveBlob(key []byte) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *fakeServer) UpdateTip(tip *PoolBlock) {
|
||||
|
||||
}
|
||||
func (s *fakeServer) Broadcast(block *PoolBlock) {
|
||||
|
||||
}
|
||||
func (s *fakeServer) ClientRPC() *client.Client {
|
||||
return client.GetDefaultClient()
|
||||
}
|
||||
func (s *fakeServer) GetChainMainByHeight(height uint64) *ChainMain {
|
||||
return nil
|
||||
}
|
||||
func (s *fakeServer) GetChainMainByHash(hash types.Hash) *ChainMain {
|
||||
return nil
|
||||
}
|
||||
func (s *fakeServer) GetMinimalBlockHeaderByHeight(height uint64) *mainblock.Header {
|
||||
if h := s.lastHeader.Load(); h != nil && h.Height == height {
|
||||
return h
|
||||
}
|
||||
if h, err := s.ClientRPC().GetBlockHeaderByHeight(height, context.Background()); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
header := &mainblock.Header{
|
||||
MajorVersion: uint8(h.BlockHeader.MajorVersion),
|
||||
MinorVersion: uint8(h.BlockHeader.MinorVersion),
|
||||
Timestamp: uint64(h.BlockHeader.Timestamp),
|
||||
PreviousId: types.MustHashFromString(h.BlockHeader.PrevHash),
|
||||
Height: h.BlockHeader.Height,
|
||||
Nonce: uint32(h.BlockHeader.Nonce),
|
||||
Reward: h.BlockHeader.Reward,
|
||||
Difficulty: types.DifficultyFrom64(h.BlockHeader.Difficulty),
|
||||
Id: types.MustHashFromString(h.BlockHeader.Hash),
|
||||
}
|
||||
s.lastHeader.Store(header)
|
||||
return header
|
||||
}
|
||||
}
|
||||
func (s *fakeServer) GetMinimalBlockHeaderByHash(hash types.Hash) *mainblock.Header {
|
||||
return nil
|
||||
}
|
||||
func (s *fakeServer) GetDifficultyByHeight(height uint64) types.Difficulty {
|
||||
return s.GetMinimalBlockHeaderByHeight(height).Difficulty
|
||||
}
|
||||
func (s *fakeServer) UpdateBlockFound(data *ChainMain, block *PoolBlock) {
|
||||
|
||||
}
|
||||
func (s *fakeServer) SubmitBlock(block *mainblock.Block) {
|
||||
|
||||
}
|
||||
func (s *fakeServer) GetChainMainTip() *ChainMain {
|
||||
return nil
|
||||
}
|
||||
func (s *fakeServer) GetMinerDataTip() *p2pooltypes.MinerData {
|
||||
return nil
|
||||
}
|
||||
func (s *fakeServer) Store(block *PoolBlock) {
|
||||
|
||||
}
|
||||
func (s *fakeServer) ClearCachedBlocks() {
|
||||
|
||||
}
|
|
@ -199,14 +199,14 @@ func GetShares(tip *PoolBlock, consensus *Consensus, difficultyByHeight block.Ge
|
|||
return s
|
||||
}
|
||||
|
||||
insertSet := func(weight types.Difficulty, a *address.PackedAddress) {
|
||||
if _, ok := sharesSet[*a]; ok {
|
||||
sharesSet[*a].Weight = sharesSet[*a].Weight.Add(weight)
|
||||
insertSet := func(weight types.Difficulty, a address.PackedAddress) {
|
||||
if _, ok := sharesSet[a]; ok {
|
||||
sharesSet[a].Weight = sharesSet[a].Weight.Add(weight)
|
||||
} else {
|
||||
s := getPreAllocated()
|
||||
s.Weight = weight
|
||||
s.Address = *a
|
||||
sharesSet[*a] = s
|
||||
s.Address = a
|
||||
sharesSet[a] = s
|
||||
}
|
||||
}
|
||||
|
||||
|
|
5
testdata/.gitignore
vendored
Normal file
5
testdata/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
block.dat
|
||||
sidechain_dump.dat.gz
|
||||
sidechain_dump_mini.dat.gz
|
||||
sidechain_dump.dat
|
||||
sidechain_dump_mini.dat
|
File diff suppressed because one or more lines are too long
25
testdata/setup.sh
vendored
Executable file
25
testdata/setup.sh
vendored
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
pushd "${SCRIPT_DIR}"
|
||||
|
||||
TESTS_COMMIT_ID=f455ce398c20137a92a67b062c6311580939abea
|
||||
|
||||
function download_test() {
|
||||
if [ -f "./${1}" ]; then
|
||||
return
|
||||
fi
|
||||
curl --progress-bar --output "./${1}" "https://raw.githubusercontent.com/SChernykh/p2pool/${TESTS_COMMIT_ID}/tests/src/${1}"
|
||||
}
|
||||
|
||||
function download_compressed_test() {
|
||||
if [ -f "./${1}" ]; then
|
||||
return
|
||||
fi
|
||||
curl --progress-bar --output "./${1}.gz" "https://raw.githubusercontent.com/SChernykh/p2pool/${TESTS_COMMIT_ID}/tests/src/${1}.gz" && gzip --decompress "${1}.gz"
|
||||
|
||||
}
|
||||
|
||||
download_test block.dat
|
||||
download_compressed_test sidechain_dump.dat
|
||||
download_compressed_test sidechain_dump_mini.dat
|
|
@ -195,6 +195,15 @@ func (d Difficulty) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(d.String())
|
||||
}
|
||||
|
||||
func MustDifficultyFromString(s string) Difficulty {
|
||||
if d, err := DifficultyFromString(s); err != nil {
|
||||
panic(err)
|
||||
return ZeroDifficulty
|
||||
} else {
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
func DifficultyFromString(s string) (Difficulty, error) {
|
||||
if strings.HasPrefix(s, "0x") {
|
||||
if buf, err := hex.DecodeString(s[2:]); err != nil {
|
||||
|
|
|
@ -20,6 +20,15 @@ func (h Hash) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(h.String())
|
||||
}
|
||||
|
||||
func MustHashFromString(s string) Hash {
|
||||
if h, err := HashFromString(s); err != nil {
|
||||
panic(err)
|
||||
return ZeroHash
|
||||
} else {
|
||||
return h
|
||||
}
|
||||
}
|
||||
|
||||
func HashFromString(s string) (Hash, error) {
|
||||
var h Hash
|
||||
if buf, err := hex.DecodeString(s); err != nil {
|
||||
|
|
Loading…
Reference in a new issue