Michael Sutton 0e1d247915
Fix stability test mining (allow submission of non DAA blocks too) (#1917)
* Fix stability test mining (allow submission of non DAA blocks too)

* Comments for go fmt

* Use SubmitBlockAlsoIfNonDAA for all tests

Co-authored-by: Elichai Turkel <elichai.turkel@gmail.com>
2021-12-30 11:04:56 +02:00

204 lines
5.2 KiB
Go

package main
import (
"fmt"
"github.com/kaspanet/kaspad/domain/consensus"
"os/exec"
"strings"
"sync/atomic"
"syscall"
"time"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/stability-tests/common"
"github.com/kaspanet/kaspad/stability-tests/common/mine"
"github.com/kaspanet/kaspad/stability-tests/common/rpc"
"github.com/kaspanet/kaspad/util"
"github.com/kaspanet/kaspad/util/panics"
"github.com/pkg/errors"
)
const (
syncerRPCAddress = "localhost:9000"
syncedRPCAddress = "localhost:9100"
syncerListen = "localhost:9001"
syncedListen = "localhost:9101"
)
func startNode(name string, rpcAddress, listen, connect, profilePort, dataDir string) (*exec.Cmd, func(), error) {
log.Infof("Data directory for %s is %s", name, dataDir)
args := []string{
"kaspad",
common.NetworkCliArgumentFromNetParams(activeConfig().NetParams()),
"--appdir", dataDir,
"--logdir", dataDir,
"--rpclisten", rpcAddress,
"--listen", listen,
"--profile", profilePort,
"--loglevel", "debug",
"--allow-submit-block-when-not-synced",
}
if connect != "" {
args = append(args, "--connect", connect)
}
if activeConfig().OverrideDAGParamsFile != "" {
args = append(args, "--override-dag-params-file", activeConfig().OverrideDAGParamsFile)
}
cmd, err := common.StartCmd(name,
args...,
)
if err != nil {
return nil, nil, err
}
var shutdown uint32
stopped := make(chan struct{})
spawn("startNode-cmd.Wait", func() {
err := cmd.Wait()
if err != nil {
if atomic.LoadUint32(&shutdown) == 0 {
panics.Exit(log, fmt.Sprintf("%s ( %s ) closed unexpectedly: %s", name, cmd, err))
}
if !strings.Contains(err.Error(), "signal: killed") {
panics.Exit(log, fmt.Sprintf("%s ( %s ) closed with an error: %s", name, cmd, err))
}
}
stopped <- struct{}{}
})
return cmd, func() {
atomic.StoreUint32(&shutdown, 1)
killWithSigkill(cmd, name)
const timeout = time.Second
select {
case <-stopped:
case <-time.After(timeout):
panics.Exit(log, fmt.Sprintf("%s couldn't be closed after %s", name, timeout))
}
}, nil
}
func killWithSigkill(cmd *exec.Cmd, commandName string) {
log.Error("SIGKILLED")
err := cmd.Process.Signal(syscall.SIGKILL)
if err != nil {
log.Criticalf("error sending SIGKILL to %s", commandName)
}
}
func setupNodeWithRPC(name, listen, rpcListen, connect, profilePort, dataDir string) (*rpc.Client, func(), error) {
_, teardown, err := startNode(name, rpcListen, listen, connect, profilePort, dataDir)
if err != nil {
return nil, nil, errors.Wrap(err, "error in startNode")
}
defer func() {
if r := recover(); r != nil {
teardown()
panic(r)
}
}()
log.Infof("Waiting for node %s to start...", name)
const initTime = 2 * time.Second
time.Sleep(initTime)
rpcClient, err := rpc.ConnectToRPC(&rpc.Config{
RPCServer: rpcListen,
}, activeConfig().NetParams())
if err != nil {
return nil, nil, errors.Wrap(err, "error connecting to JSON-RPC server")
}
return rpcClient, teardown, nil
}
func setupSyncee() (*rpc.Client, func(), error) {
const syncedProfilePort = "6061"
synceeDataDir, err := useDirOrCreateTemp(activeConfig().SynceeDataDirectory, "syncee-kaspad-data-dir")
if err != nil {
return nil, nil, err
}
return setupNodeWithRPC("SYNCEE", syncedListen, syncedRPCAddress, syncerListen, syncedProfilePort,
synceeDataDir)
}
func setupSyncer() (*rpc.Client, func(), error) {
const syncerProfilePort = "6062"
syncerDataDir, err := useDirOrCreateTemp(activeConfig().SyncerDataDirectory, "syncer-kaspad-data-dir")
if err != nil {
return nil, nil, err
}
rpcClient, teardown, err := setupNodeWithRPC("SYNCER", syncerListen, syncerRPCAddress, "",
syncerProfilePort, syncerDataDir)
if err != nil {
return nil, nil, err
}
defer func() {
if r := recover(); r != nil {
teardown()
panic(r)
}
}()
miningDataDir, err := useDirOrCreateTemp(activeConfig().MiningDataDirectory, "syncer-mining-data-dir")
if err != nil {
return nil, nil, err
}
err = mine.FromFile(cfg.DAGFile, &consensus.Config{Params: *activeConfig().NetParams()}, rpcClient, miningDataDir)
if err != nil {
return nil, nil, errors.Wrap(err, "error in mine.FromFile")
}
log.Info("Mining on top of syncer tips")
rejectReason, err := mineOnTips(rpcClient)
if err != nil {
panic(err)
}
if rejectReason != appmessage.RejectReasonNone {
panic(fmt.Sprintf("mined block rejected: %s", rejectReason))
}
return rpcClient, teardown, nil
}
func useDirOrCreateTemp(dataDir, tempName string) (string, error) {
if dataDir != "" {
return dataDir, nil
}
return common.TempDir(tempName)
}
func mineOnTips(client *rpc.Client) (appmessage.RejectReason, error) {
fakePublicKey := make([]byte, util.PublicKeySize)
addr, err := util.NewAddressPublicKey(fakePublicKey, activeConfig().NetParams().Prefix)
if err != nil {
return appmessage.RejectReasonNone, err
}
template, err := client.GetBlockTemplate(addr.String())
if err != nil {
return appmessage.RejectReasonNone, err
}
domainBlock, err := appmessage.RPCBlockToDomainBlock(template.Block)
if err != nil {
return appmessage.RejectReasonNone, err
}
if !activeConfig().NetParams().SkipProofOfWork {
mine.SolveBlock(domainBlock)
}
return client.SubmitBlockAlsoIfNonDAA(domainBlock)
}