mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00

* 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>
204 lines
5.2 KiB
Go
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)
|
|
}
|