Michael Sutton c81506220b
Send pruning point anticone in batches (#1973)
* add p2p v5 which is currently identical to v4

* set all internal imports to v5

* set default version to 5

* Send pruning point and its anticone in batches

* go lint

* Fix jsom format

* Use DequeueWithTimeout

* Assert that batch size < route capacity

* oops, this is a flow handler, by definition it needs to be w/o a timeout

* here however, a timeout is required

* Keep IDs of prev messages unmodified

* previous merge operation accidentally erased an important part of this pr

* Extend timeout of simple sync

Co-authored-by: Ori Newman <orinewman1@gmail.com>
2022-03-13 16:31:34 +02:00

145 lines
4.2 KiB
Go

package main
import (
"time"
"github.com/kaspanet/go-secp256k1"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/stability-tests/common"
"github.com/kaspanet/kaspad/stability-tests/common/rpc"
"github.com/kaspanet/kaspad/util"
"github.com/pkg/errors"
)
func mineLoop(syncerRPCClient, syncedRPCClient *rpc.Client) error {
miningAddr, err := generateAddress()
if err != nil {
return err
}
syncerBlockCountBefore, err := syncerRPCClient.GetBlockCount()
if err != nil {
return err
}
syncedBlockCountBefore, err := syncedRPCClient.GetBlockCount()
if err != nil {
return err
}
log.Infof("Starting to mine")
totalTime := time.Duration(0)
for i := uint64(0); i < activeConfig().NumberOfBlocks; i++ {
log.Infof("Mining block %d...", i+1)
err = mineBlock(syncerRPCClient.Address(), miningAddr)
if err != nil {
// Ignore error and instead check that the block count changed correctly.
// TODO: Fix the race condition in kaspaminer so it won't panic (proper shutdown handler)
log.Warnf("mineBlock returned an err: %s", err)
}
start := time.Now()
const timeToPropagate = 60 * time.Second
select {
case <-syncedRPCClient.OnBlockAdded:
case <-time.After(timeToPropagate):
return errors.Errorf("block %d took more than %s to propagate", i+1, timeToPropagate)
}
totalTime += time.Since(start)
syncerResult, err := syncerRPCClient.GetBlockDAGInfo()
if err != nil {
return err
}
syncedResult, err := syncedRPCClient.GetBlockDAGInfo()
if err != nil {
return err
}
if !areTipsAreEqual(syncedResult, syncerResult) {
return errors.Errorf("syncer node has tips %s but synced node has tips %s", syncerResult.TipHashes, syncedResult.TipHashes)
}
}
const expectedAveragePropagationTime = time.Second
averagePropagationTime := totalTime / time.Duration(activeConfig().NumberOfBlocks)
if averagePropagationTime > expectedAveragePropagationTime {
return errors.Errorf("average block propagation time %s is higher than expected (%s)", averagePropagationTime, expectedAveragePropagationTime)
}
log.Infof("Finished to mine")
log.Infof("Getting syncer block count")
syncerBlockCountAfter, err := syncerRPCClient.GetBlockCount()
if err != nil {
return err
}
log.Infof("Getting syncee block count")
syncedBlockCountAfter, err := syncedRPCClient.GetBlockCount()
if err != nil {
return err
}
if syncerBlockCountAfter.BlockCount-syncerBlockCountBefore.BlockCount != activeConfig().NumberOfBlocks {
return errors.Errorf("Expected to mine %d blocks, instead mined: %d", activeConfig().NumberOfBlocks, syncerBlockCountAfter.BlockCount-syncerBlockCountBefore.BlockCount)
}
if syncedBlockCountAfter.BlockCount-syncedBlockCountBefore.BlockCount != activeConfig().NumberOfBlocks {
return errors.Errorf("Expected syncer to have %d new blocks, instead have: %d", activeConfig().NumberOfBlocks, syncedBlockCountAfter.BlockCount-syncedBlockCountBefore.BlockCount)
}
log.Infof("Finished the mine loop successfully")
return nil
}
func generateAddress() (util.Address, error) {
privateKey, err := secp256k1.GenerateSchnorrKeyPair()
if err != nil {
return nil, err
}
pubKey, err := privateKey.SchnorrPublicKey()
if err != nil {
return nil, err
}
pubKeySerialized, err := pubKey.Serialize()
if err != nil {
return nil, err
}
return util.NewAddressPublicKey(pubKeySerialized[:], activeConfig().ActiveNetParams.Prefix)
}
func areTipsAreEqual(resultA, resultB *appmessage.GetBlockDAGInfoResponseMessage) bool {
if len(resultA.TipHashes) != len(resultB.TipHashes) {
return false
}
tipsASet := make(map[string]struct{})
for _, tip := range resultA.TipHashes {
tipsASet[tip] = struct{}{}
}
for _, tip := range resultB.TipHashes {
if _, ok := tipsASet[tip]; !ok {
return false
}
}
return true
}
func mineBlock(syncerRPCAddress string, miningAddress util.Address) error {
kaspaMinerCmd, err := common.StartCmd("MINER",
"kaspaminer",
common.NetworkCliArgumentFromNetParams(activeConfig().NetParams()),
"-s", syncerRPCAddress,
"--mine-when-not-synced",
"--miningaddr", miningAddress.EncodeAddress(),
"--numblocks", "1",
)
if err != nil {
return err
}
return errors.Wrapf(kaspaMinerCmd.Wait(), "error with command '%s'", kaspaMinerCmd)
}