diff --git a/cmd/sovereignnode/chainSimulator/sovereignChainSimulator_test.go b/cmd/sovereignnode/chainSimulator/sovereignChainSimulator_test.go index b5f68cff53..d36dc27e49 100644 --- a/cmd/sovereignnode/chainSimulator/sovereignChainSimulator_test.go +++ b/cmd/sovereignnode/chainSimulator/sovereignChainSimulator_test.go @@ -76,6 +76,65 @@ func TestChainSimulator_GenerateBlocksShouldWork(t *testing.T) { require.Nil(t, err) } +func TestSovereignChainSimulator_GenerateBlocksAndEpochChangeShouldWork(t *testing.T) { + if testing.Short() { + t.Skip("this is not a short test") + } + + chainSimulator, err := NewSovereignChainSimulator(ArgsSovereignChainSimulator{ + SovereignConfigPath: sovereignConfigPath, + ArgsChainSimulator: &chainSim.ArgsChainSimulator{ + BypassTxSignatureCheck: false, + TempDir: t.TempDir(), + PathToInitialConfig: defaultPathToInitialConfig, + GenesisTimestamp: time.Now().Unix(), + RoundDurationInMillis: uint64(6000), + RoundsPerEpoch: core.OptionalUint64{ + HasValue: true, + Value: 20, + }, + ApiInterface: api.NewNoApiInterface(), + MinNodesPerShard: 2, + }, + }) + require.Nil(t, err) + require.NotNil(t, chainSimulator) + + defer chainSimulator.Close() + + chainSimulatorCommon.GenerateBlocksAndEpochChange(t, chainSimulator) +} + +func TestSovereignSimulator_TriggerChangeOfEpoch(t *testing.T) { + if testing.Short() { + t.Skip("this is not a short test") + } + + chainSimulator, err := NewSovereignChainSimulator(ArgsSovereignChainSimulator{ + SovereignConfigPath: sovereignConfigPath, + ArgsChainSimulator: &chainSim.ArgsChainSimulator{ + BypassTxSignatureCheck: false, + TempDir: t.TempDir(), + PathToInitialConfig: defaultPathToInitialConfig, + GenesisTimestamp: time.Now().Unix(), + RoundDurationInMillis: uint64(6000), + RoundsPerEpoch: core.OptionalUint64{ + HasValue: true, + Value: 20, + }, + ApiInterface: api.NewNoApiInterface(), + MinNodesPerShard: 1, + }, + }) + require.Nil(t, err) + require.NotNil(t, chainSimulator) + + defer chainSimulator.Close() + + nodeHandler := chainSimulator.GetNodeHandler(core.SovereignChainShardId) + chainSimulatorCommon.TriggerChangeOfEpoch(t, chainSimulator, nodeHandler) +} + func TestChainSimulator_SetState(t *testing.T) { if testing.Short() { t.Skip("this is not a short test") diff --git a/integrationTests/chainSimulator/interface.go b/integrationTests/chainSimulator/interface.go index 7aba83c510..ad6d041595 100644 --- a/integrationTests/chainSimulator/interface.go +++ b/integrationTests/chainSimulator/interface.go @@ -27,5 +27,8 @@ type ChainSimulator interface { ForceResetValidatorStatisticsCache() error GetValidatorPrivateKeys() []crypto.PrivateKey SetKeyValueForAddress(address string, keyValueMap map[string]string) error + GetRestAPIInterfaces() map[uint32]string + ForceChangeOfEpoch() error + IsInterfaceNil() bool Close() } diff --git a/integrationTests/chainSimulator/testing.go b/integrationTests/chainSimulator/testing.go index 212021a8fb..52b7bd962b 100644 --- a/integrationTests/chainSimulator/testing.go +++ b/integrationTests/chainSimulator/testing.go @@ -6,18 +6,70 @@ import ( "testing" "time" - "github.com/multiversx/mx-chain-go/node/chainSimulator/dtos" - "github.com/multiversx/mx-chain-go/node/chainSimulator/errors" - chainSimulatorProcess "github.com/multiversx/mx-chain-go/node/chainSimulator/process" - "github.com/multiversx/mx-chain-go/process" - "github.com/multiversx/mx-chain-core-go/core" coreAPI "github.com/multiversx/mx-chain-core-go/data/api" "github.com/multiversx/mx-chain-core-go/data/transaction" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/multiversx/mx-chain-go/node/chainSimulator/dtos" + "github.com/multiversx/mx-chain-go/node/chainSimulator/errors" + chainSimulatorProcess "github.com/multiversx/mx-chain-go/node/chainSimulator/process" + "github.com/multiversx/mx-chain-go/process" ) +// GenerateBlocksAndEpochChange - +func GenerateBlocksAndEpochChange(t *testing.T, chainSimulator ChainSimulator) { + genesisBalances := make(map[string]*big.Int) + for _, stakeWallet := range chainSimulator.GetInitialWalletKeys().StakeWallets { + initialAccount, errGet := getAccount(chainSimulator, stakeWallet.Address) + require.Nil(t, errGet) + + genesisBalances[stakeWallet.Address.Bech32] = initialAccount.GetBalance() + } + + time.Sleep(time.Second) + + err := chainSimulator.GenerateBlocksUntilEpochIsReached(4) + require.Nil(t, err) + + numAccountsWithIncreasedBalances := 0 + for _, stakeWallet := range chainSimulator.GetInitialWalletKeys().StakeWallets { + account, errGet := getAccount(chainSimulator, stakeWallet.Address) + require.Nil(t, errGet) + + if account.GetBalance().Cmp(genesisBalances[stakeWallet.Address.Bech32]) > 0 { + numAccountsWithIncreasedBalances++ + } + } + + require.True(t, numAccountsWithIncreasedBalances > 0) +} + +func getAccount(chainSimulator ChainSimulator, address dtos.WalletAddress) (vmcommon.UserAccountHandler, error) { + shardID := GetShardForAddress(chainSimulator, address.Bech32) + account, err := chainSimulator.GetNodeHandler(shardID).GetStateComponents().AccountsAdapter().GetExistingAccount(address.Bytes) + if err != nil { + return nil, err + } + + return account.(vmcommon.UserAccountHandler), nil +} + +// TriggerChangeOfEpoch - +func TriggerChangeOfEpoch(t *testing.T, chainSimulator ChainSimulator, nodeHandler chainSimulatorProcess.NodeHandler) { + startEpoch := nodeHandler.GetProcessComponents().EpochStartTrigger().Epoch() + + for i := startEpoch; i < startEpoch+4; i++ { + err := chainSimulator.ForceChangeOfEpoch() + require.Nil(t, err) + + currentEpoch := nodeHandler.GetProcessComponents().EpochStartTrigger().Epoch() + require.Equal(t, i+1, currentEpoch) + } +} + // CheckSetState - func CheckSetState(t *testing.T, chainSimulator ChainSimulator, nodeHandler chainSimulatorProcess.NodeHandler) { keyValueMap := map[string]string{ diff --git a/node/chainSimulator/chainSimulator_test.go b/node/chainSimulator/chainSimulator_test.go index 18f54ccbfe..942b75a868 100644 --- a/node/chainSimulator/chainSimulator_test.go +++ b/node/chainSimulator/chainSimulator_test.go @@ -1,7 +1,6 @@ package chainSimulator import ( - "github.com/multiversx/mx-chain-go/errors" "math/big" "strings" "testing" @@ -9,13 +8,14 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/config" + "github.com/multiversx/mx-chain-go/errors" chainSimulatorCommon "github.com/multiversx/mx-chain-go/integrationTests/chainSimulator" "github.com/multiversx/mx-chain-go/node/chainSimulator/components/api" "github.com/multiversx/mx-chain-go/node/chainSimulator/configs" "github.com/multiversx/mx-chain-go/node/chainSimulator/dtos" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) const ( @@ -119,33 +119,7 @@ func TestChainSimulator_GenerateBlocksAndEpochChangeShouldWork(t *testing.T) { defer chainSimulator.Close() - facade, err := NewChainSimulatorFacade(chainSimulator) - require.Nil(t, err) - - genesisBalances := make(map[string]*big.Int) - for _, stakeWallet := range chainSimulator.initialWalletKeys.StakeWallets { - initialAccount, errGet := facade.GetExistingAccountFromBech32AddressString(stakeWallet.Address.Bech32) - require.Nil(t, errGet) - - genesisBalances[stakeWallet.Address.Bech32] = initialAccount.GetBalance() - } - - time.Sleep(time.Second) - - err = chainSimulator.GenerateBlocks(80) - require.Nil(t, err) - - numAccountsWithIncreasedBalances := 0 - for _, stakeWallet := range chainSimulator.initialWalletKeys.StakeWallets { - account, errGet := facade.GetExistingAccountFromBech32AddressString(stakeWallet.Address.Bech32) - require.Nil(t, errGet) - - if account.GetBalance().Cmp(genesisBalances[stakeWallet.Address.Bech32]) > 0 { - numAccountsWithIncreasedBalances++ - } - } - - assert.True(t, numAccountsWithIncreasedBalances > 0) + chainSimulatorCommon.GenerateBlocksAndEpochChange(t, chainSimulator) } func TestSimulator_TriggerChangeOfEpoch(t *testing.T) { @@ -176,21 +150,8 @@ func TestSimulator_TriggerChangeOfEpoch(t *testing.T) { defer chainSimulator.Close() - err = chainSimulator.ForceChangeOfEpoch() - require.Nil(t, err) - - err = chainSimulator.ForceChangeOfEpoch() - require.Nil(t, err) - - err = chainSimulator.ForceChangeOfEpoch() - require.Nil(t, err) - - err = chainSimulator.ForceChangeOfEpoch() - require.Nil(t, err) - - metaNode := chainSimulator.GetNodeHandler(core.MetachainShardId) - currentEpoch := metaNode.GetProcessComponents().EpochStartTrigger().Epoch() - require.Equal(t, uint32(4), currentEpoch) + nodeHandler := chainSimulator.GetNodeHandler(core.MetachainShardId) + chainSimulatorCommon.TriggerChangeOfEpoch(t, chainSimulator, nodeHandler) } func TestChainSimulator_SetState(t *testing.T) { diff --git a/node/chainSimulator/sovereignChainSimulator.go b/node/chainSimulator/sovereignChainSimulator.go index dc6e3917f6..22fb11ceb2 100644 --- a/node/chainSimulator/sovereignChainSimulator.go +++ b/node/chainSimulator/sovereignChainSimulator.go @@ -2,6 +2,8 @@ package chainSimulator import ( "fmt" + + "github.com/multiversx/mx-chain-core-go/core" ) type sovereignChainSimulator struct { @@ -53,3 +55,28 @@ func (ss *sovereignChainSimulator) isSovereignTargetEpochReached(targetEpoch int return true } + +// ForceResetValidatorStatisticsCache will force the reset of the cache used for the validators statistics endpoint +func (ss *sovereignChainSimulator) ForceResetValidatorStatisticsCache() error { + return ss.GetNodeHandler(core.SovereignChainShardId).GetProcessComponents().ValidatorsProvider().ForceUpdate() +} + +// ForceChangeOfEpoch will force the change of current epoch +// This method will call the epoch change trigger and generate block till a new epoch is reached +func (ss *sovereignChainSimulator) ForceChangeOfEpoch() error { + log.Info("force change of epoch") + + ss.mutex.Lock() + + node := ss.nodes[core.SovereignChainShardId] + err := node.ForceChangeOfEpoch() + if err != nil { + ss.mutex.Unlock() + return fmt.Errorf("force change of epoch error-%w", err) + } + + epoch := node.GetProcessComponents().EpochStartTrigger().Epoch() + ss.mutex.Unlock() + + return ss.GenerateBlocksUntilEpochIsReached(int32(epoch + 1)) +}