added more sync objects to avoid accidential data races (#345)

* Added more sync objects to avoid accidental data races
* made lib.config.Config variables are private, so they cannot be tampered with (multithreading).
Please introduce Get-methods to retrieve the varialbes outside of the package if you need it.
This way, the race conditions and unexpected change of the global object state can be protected
* added reverse takedown of the validators to avoid the following error
 [app] PoP broadcast tx failed: node0.info: key not found
* moved util.TerminationWaitGroup.Wait()
to the central network cleanup method
* removed mappings for private variables


Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
This commit is contained in:
Jürgen Eckel 2024-03-11 11:11:56 +01:00 committed by GitHub
parent d5d86997f3
commit 1e1e19bb19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 57 additions and 45 deletions

View File

@ -10,13 +10,13 @@ import (
// Config defines library top level configuration.
type Config struct {
ChainID string `json:"chain-id" mapstructure:"chain-id"`
ClientCtx client.Context `json:"client-ctx" mapstructure:"client-ctx"`
EncodingConfig params.EncodingConfig `json:"encoding-config" mapstructure:"encoding-config"`
FeeDenom string `json:"fee-denom" mapstructure:"fee-denom"`
RootDir string `json:"root-dir" mapstructure:"root-dir"`
RPCEndpoint string `json:"rpc-endpoint" mapstructure:"rpc-endpoint"`
TxGas uint64 `json:"tx-gas" mapstructure:"tx-gas"`
chainID string
clientCtx client.Context
encodingConfig params.EncodingConfig
feeDenom string
rootDir string
rpcEndpoint string
txGas uint64
}
// lib wide global singleton
@ -24,18 +24,19 @@ var (
libConfig *Config
sdkConfig *sdk.Config
initConfig sync.Once
changeLock sync.Mutex
)
// DefaultConfig returns library default configuration.
func DefaultConfig() *Config {
return &Config{
ChainID: "planetmint-testnet-1",
ClientCtx: client.Context{},
EncodingConfig: params.EncodingConfig{},
FeeDenom: "plmnt",
RootDir: "~/.planetmint-go/",
RPCEndpoint: "http://127.0.0.1:26657",
TxGas: 200000,
chainID: "planetmint-testnet-1",
clientCtx: client.Context{},
encodingConfig: params.EncodingConfig{},
feeDenom: "plmnt",
rootDir: "~/.planetmint-go/",
rpcEndpoint: "http://127.0.0.1:26657",
txGas: 200000,
}
}
@ -54,48 +55,64 @@ func GetConfig() *Config {
// SetBech32PrefixForAccount sets the bech32 account prefix.
func (config *Config) SetBech32PrefixForAccount(bech32Prefix string) *Config {
changeLock.Lock()
defer changeLock.Unlock()
sdkConfig.SetBech32PrefixForAccount(bech32Prefix, "pub")
return config
}
// SetEncodingConfig sets the encoding config and must not be nil.
func (config *Config) SetEncodingConfig(encodingConfig params.EncodingConfig) *Config {
config.EncodingConfig = encodingConfig
changeLock.Lock()
defer changeLock.Unlock()
config.encodingConfig = encodingConfig
return config
}
// SetChainID sets the chain ID parameter.
func (config *Config) SetChainID(chainID string) *Config {
config.ChainID = chainID
changeLock.Lock()
defer changeLock.Unlock()
config.chainID = chainID
return config
}
// SetClientCtx sets the client context parameter.
func (config *Config) SetClientCtx(clientCtx client.Context) *Config {
config.ClientCtx = clientCtx
changeLock.Lock()
defer changeLock.Unlock()
config.clientCtx = clientCtx
return config
}
// SetFeeDenom sets the fee denominator parameter.
func (config *Config) SetFeeDenom(feeDenom string) *Config {
config.FeeDenom = feeDenom
changeLock.Lock()
defer changeLock.Unlock()
config.feeDenom = feeDenom
return config
}
// SetRoot sets the root directory where to find the keyring.
func (config *Config) SetRoot(root string) *Config {
config.RootDir = root
changeLock.Lock()
defer changeLock.Unlock()
config.rootDir = root
return config
}
// SetRPCEndpoint sets the RPC endpoint to send requests to.
func (config *Config) SetRPCEndpoint(rpcEndpoint string) *Config {
config.RPCEndpoint = rpcEndpoint
changeLock.Lock()
defer changeLock.Unlock()
config.rpcEndpoint = rpcEndpoint
return config
}
// SetTxGas sets the amount of Gas for the TX that is send to the network
func (config *Config) SetTxGas(txGas uint64) *Config {
config.TxGas = txGas
changeLock.Lock()
defer changeLock.Unlock()
config.txGas = txGas
return config
}

View File

@ -61,7 +61,7 @@ func (s *E2ETestSuite) TestBankSendBroadcastTxWithFileLock() {
assert.Equal(s.T(), "received wrong fee denom; got: plmnt required: stake: invalid coins", txResponse.RawLog)
libConfig := lib.GetConfig()
libConfig.FeeDenom = "stake"
libConfig.SetFeeDenom("stake")
// incorrect coin
out, err = lib.BroadcastTxWithFileLock(val.Address, msg)

View File

@ -38,7 +38,7 @@ func getAccountNumberAndSequence(clientCtx client.Context) (accountNumber, seque
}
func getClientContextAndTxFactory(fromAddress sdk.AccAddress) (clientCtx client.Context, txf tx.Factory, err error) {
clientCtx = GetConfig().ClientCtx
clientCtx = GetConfig().clientCtx
// at least we need an account retriever
// it would be better to check for an empty client context, but that does not work at the moment
if clientCtx.AccountRetriever == nil {
@ -70,17 +70,17 @@ func getTxFactoryWithAccountNumberAndSequence(clientCtx client.Context, accountN
WithAccountRetriever(clientCtx.AccountRetriever).
WithChainID(clientCtx.ChainID).
WithFeeGranter(clientCtx.FeeGranter).
WithGas(GetConfig().TxGas).
WithGasPrices("0.000005" + GetConfig().FeeDenom).
WithGas(GetConfig().txGas).
WithGasPrices("0.000005" + GetConfig().feeDenom).
WithKeybase(clientCtx.Keyring).
WithSequence(sequence).
WithTxConfig(clientCtx.TxConfig)
}
func getClientContext(fromAddress sdk.AccAddress) (clientCtx client.Context, err error) {
encodingConfig := GetConfig().EncodingConfig
encodingConfig := GetConfig().encodingConfig
rootDir := GetConfig().RootDir
rootDir := GetConfig().rootDir
input := os.Stdin
codec := encodingConfig.Marshaler
keyringOptions := []keyring.Option{}
@ -95,7 +95,7 @@ func getClientContext(fromAddress sdk.AccAddress) (clientCtx client.Context, err
return
}
remote := GetConfig().RPCEndpoint
remote := GetConfig().rpcEndpoint
wsClient, err := comethttp.New(remote, "/websocket")
if err != nil {
return
@ -106,7 +106,7 @@ func getClientContext(fromAddress sdk.AccAddress) (clientCtx client.Context, err
clientCtx = client.Context{
AccountRetriever: authtypes.AccountRetriever{},
BroadcastMode: "sync",
ChainID: GetConfig().ChainID,
ChainID: GetConfig().chainID,
Client: wsClient,
Codec: codec,
From: fromAddress.String(),

View File

@ -60,7 +60,7 @@ func createSequenceDirectory() (path string, err error) {
return
}
homeDir := usr.HomeDir
path = filepath.Join(GetConfig().RootDir, "sequence")
path = filepath.Join(GetConfig().rootDir, "sequence")
// expand tilde to user's home directory
if strings.HasPrefix(path, "~/") {
path = filepath.Join(homeDir, path[2:])

View File

@ -4,7 +4,6 @@ import (
"github.com/planetmint/planetmint-go/lib"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/testutil/sample"
"github.com/planetmint/planetmint-go/util"
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
@ -39,7 +38,6 @@ func (s *E2ETestSuite) SetupSuite() {
// TearDownSuite clean up after testing
func (s *E2ETestSuite) TearDownSuite() {
util.TerminationWaitGroup.Wait()
s.T().Log("tearing down e2e asset test suite")
}

View File

@ -14,7 +14,6 @@ import (
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/testutil/sample"
"github.com/planetmint/planetmint-go/util"
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
@ -110,7 +109,6 @@ func (s *E2ETestSuite) SetupSuite() {
// TearDownSuite clean up after testing
func (s *E2ETestSuite) TearDownSuite() {
util.TerminationWaitGroup.Wait()
s.T().Log("tearing down e2e dao test suite")
}

View File

@ -6,7 +6,6 @@ import (
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/util"
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
"github.com/stretchr/testify/suite"
@ -42,7 +41,6 @@ func (s *AssetDistributionE2ETestSuite) SetupSuite() {
}
func (s *AssetDistributionE2ETestSuite) TearDownSuite() {
util.TerminationWaitGroup.Wait()
s.T().Log("tearing down e2e dao distribution test suites")
}

View File

@ -15,7 +15,6 @@ import (
"github.com/planetmint/planetmint-go/testutil/moduleobject"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/testutil/sample"
"github.com/planetmint/planetmint-go/util"
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
@ -94,7 +93,6 @@ func (s *ConsumptionE2ETestSuite) SetupSuite() {
}
func (s *ConsumptionE2ETestSuite) TearDownSuite() {
util.TerminationWaitGroup.Wait()
s.T().Log("tearing down e2e dao gas consumption test suites")
}

View File

@ -6,7 +6,6 @@ import (
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/testutil/sample"
"github.com/planetmint/planetmint-go/util"
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
"github.com/stretchr/testify/suite"
@ -45,7 +44,6 @@ func (s *RestrictedMsgsE2ESuite) SetupSuite() {
}
func (s *RestrictedMsgsE2ESuite) TearDownSuite() {
util.TerminationWaitGroup.Wait()
s.T().Log("tearing down e2e dao restricted msg test suite")
}

View File

@ -17,7 +17,6 @@ import (
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/testutil/sample"
"github.com/planetmint/planetmint-go/util"
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
"github.com/stretchr/testify/assert"
@ -87,7 +86,6 @@ func (s *SelectionE2ETestSuite) SetupSuite() {
// TearDownSuite clean up after testing
func (s *SelectionE2ETestSuite) TearDownSuite() {
util.TerminationWaitGroup.Wait()
s.T().Log("tearing down e2e dao pop selection test suite")
}

View File

@ -5,7 +5,6 @@ import (
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/testutil/sample"
"github.com/planetmint/planetmint-go/util"
machinecli "github.com/planetmint/planetmint-go/x/machine/client/cli"
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
@ -50,7 +49,6 @@ func (s *E2ETestSuite) SetupSuite() {
// TearDownSuite clean up after testing
func (s *E2ETestSuite) TearDownSuite() {
util.TerminationWaitGroup.Wait()
s.T().Log("tearing down e2e machine test suite")
}

View File

@ -24,6 +24,7 @@ import (
"github.com/planetmint/planetmint-go/config"
"github.com/planetmint/planetmint-go/lib"
"github.com/planetmint/planetmint-go/testutil/sample"
"github.com/planetmint/planetmint-go/util"
"github.com/spf13/cobra"
"google.golang.org/grpc"
@ -749,7 +750,8 @@ func (n *Network) Cleanup() {
n.Logger.Log("cleaning up test network...")
for _, v := range n.Validators {
for i := len(n.Validators) - 1; i >= 0; i-- {
v := n.Validators[i]
if v.tmNode != nil && v.tmNode.IsRunning() {
_ = v.tmNode.Stop()
}
@ -765,6 +767,8 @@ func (n *Network) Cleanup() {
}
}
}
// waiting for all threads to be terminated
util.TerminationWaitGroup.Wait()
// Give a brief pause for things to finish closing in other processes. Hopefully this helps with the address-in-use errors.
// 100ms chosen randomly.

View File

@ -16,6 +16,7 @@ var (
globalApplicationLoggerTag string
appLogger *AppLogger
initAppLogger sync.Once
syncTestingLog sync.Mutex
)
func init() {
@ -33,7 +34,9 @@ func GetAppLogger() *AppLogger {
}
func (logger *AppLogger) SetTestingLogger(testingLogger *testing.T) *AppLogger {
syncTestingLog.Lock()
logger.testingLogger = testingLogger
syncTestingLog.Unlock()
return logger
}
@ -49,7 +52,9 @@ func (logger *AppLogger) testingLog(msg string, keyvals ...interface{}) {
return
}
msg = format(msg, keyvals...)
syncTestingLog.Lock()
logger.testingLogger.Logf(msg)
syncTestingLog.Unlock()
}
func (logger *AppLogger) Info(ctx sdk.Context, msg string, keyvals ...interface{}) {