Added new testdata system using p2pool vectors

This commit is contained in:
DataHoarder 2023-05-10 03:46:33 +02:00
parent e3f50dd515
commit edbb610533
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
14 changed files with 351 additions and 167 deletions

View file

@ -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 {

View file

@ -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 {

View file

@ -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

View file

@ -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
}

View file

@ -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
}

View file

@ -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())
}

View file

@ -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())
}
}

View 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() {
}

View file

@ -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
View 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
View 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

View file

@ -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 {

View file

@ -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 {