Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sovereign chain simulator genesis file adaptation #6796

Merged
Merged
85 changes: 85 additions & 0 deletions cmd/sovereignnode/chainSimulator/configs/configs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package configs

import (
"encoding/json"
"math/big"
"os"

"github.com/multiversx/mx-chain-core-go/core"

"github.com/multiversx/mx-chain-go/common/factory"
"github.com/multiversx/mx-chain-go/config"
"github.com/multiversx/mx-chain-go/genesis/data"
"github.com/multiversx/mx-chain-go/integrationTests/chainSimulator"
chainSimulatorConfigs "github.com/multiversx/mx-chain-go/node/chainSimulator/configs"
"github.com/multiversx/mx-chain-go/node/chainSimulator/dtos"
)

var initialStakedEgldPerNode = big.NewInt(0).Mul(chainSimulator.OneEGLD, big.NewInt(2500))
var initialEgldPerNode = big.NewInt(0).Mul(chainSimulator.OneEGLD, big.NewInt(5000))
var initialSupply = big.NewInt(0).Mul(chainSimulator.OneEGLD, big.NewInt(20000000)) // 20 million EGLD

// GenerateSovereignGenesisFile will generate sovereign initial wallet keys
func GenerateSovereignGenesisFile(args chainSimulatorConfigs.ArgsChainSimulatorConfigs, configs *config.Configs) (*dtos.InitialWalletKeys, error) {
addressConverter, err := factory.NewPubkeyConverter(configs.GeneralConfig.AddressPubkeyConverter)
if err != nil {
return nil, err
}

initialWalletKeys := &dtos.InitialWalletKeys{
BalanceWallets: make(map[uint32]*dtos.WalletKey),
StakeWallets: make([]*dtos.WalletKey, 0),
}
addresses := make([]data.InitialAccount, 0)
numOfNodes := int(args.NumNodesWaitingListShard + args.MinNodesPerShard)

totalStakedValue := big.NewInt(0).Set(initialStakedEgldPerNode)
totalStakedValue.Mul(totalStakedValue, big.NewInt(int64(numOfNodes)))

initialBalance := big.NewInt(0).Set(initialSupply)
initialBalance.Sub(initialBalance, totalStakedValue)

for i := 0; i < numOfNodes; i++ {
initialEgld := big.NewInt(0).Set(initialEgldPerNode)

if i == numOfNodes-1 {
remainingSupply := big.NewInt(0).Set(initialBalance)
allBalances := big.NewInt(0).Set(initialEgld)
allBalances.Mul(allBalances, big.NewInt(int64(numOfNodes)))
remainingSupply.Sub(remainingSupply, allBalances)
if remainingSupply.Cmp(big.NewInt(0)) > 0 {
initialEgld.Add(initialEgld, remainingSupply)
}
}

walletKey, errG := chainSimulatorConfigs.GenerateWalletKeyForShard(core.SovereignChainShardId, args.NumOfShards, addressConverter)
if errG != nil {
return nil, errG
}

supply := big.NewInt(0).Set(initialEgld)
supply.Add(supply, big.NewInt(0).Set(initialStakedEgldPerNode))

addresses = append(addresses, data.InitialAccount{
Address: walletKey.Address.Bech32,
Balance: initialEgld,
Supply: supply,
StakingValue: big.NewInt(0).Set(initialStakedEgldPerNode),
})

initialWalletKeys.StakeWallets = append(initialWalletKeys.StakeWallets, walletKey)
initialWalletKeys.BalanceWallets[uint32(i)] = walletKey
}

addressesBytes, errM := json.Marshal(addresses)
if errM != nil {
return nil, errM
}

err = os.WriteFile(configs.ConfigurationPathsHolder.Genesis, addressesBytes, os.ModePerm)
if err != nil {
return nil, err
}

return initialWalletKeys, nil
}
27 changes: 27 additions & 0 deletions cmd/sovereignnode/chainSimulator/configs/configs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package configs

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/multiversx/mx-chain-go/node/chainSimulator/configs"
)

func TestCreateChainSimulatorConfigsWithSovereignGenesisFile(t *testing.T) {
if testing.Short() {
t.Skip("this is not a short test")
}

outputConfig, err := configs.CreateChainSimulatorConfigs(configs.ArgsChainSimulatorConfigs{
mariusmihaic marked this conversation as resolved.
Show resolved Hide resolved
NumOfShards: 1,
OriginalConfigsPath: "../../../../cmd/node/config",
RoundDurationInMillis: 6000,
GenesisTimeStamp: 0,
TempDir: t.TempDir(),
MinNodesPerShard: 1,
GenerateGenesisFile: GenerateSovereignGenesisFile,
})
require.Nil(t, err)
require.NotNil(t, outputConfig)
}
6 changes: 6 additions & 0 deletions cmd/sovereignnode/chainSimulator/sovereignChainSimulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import (
chainSimulatorIntegrationTests "github.com/multiversx/mx-chain-go/integrationTests/chainSimulator"
"github.com/multiversx/mx-chain-go/node"
"github.com/multiversx/mx-chain-go/node/chainSimulator"
chainSimulatorConfigs "github.com/multiversx/mx-chain-go/node/chainSimulator/configs"
"github.com/multiversx/mx-chain-go/node/chainSimulator/dtos"
"github.com/multiversx/mx-chain-go/process"
"github.com/multiversx/mx-chain-go/process/block/sovereign/incomingHeader"
sovCommon "github.com/multiversx/mx-chain-go/sovereignnode/chainSimulator/common"
sovChainSimConfig "github.com/multiversx/mx-chain-go/sovereignnode/chainSimulator/configs"
sovereignConfig "github.com/multiversx/mx-chain-go/sovereignnode/config"
)

Expand Down Expand Up @@ -65,6 +68,9 @@ func NewSovereignChainSimulator(args ArgsSovereignChainSimulator) (chainSimulato
}
args.NodeFactory = node.NewSovereignNodeFactory(configs.SovereignExtraConfig.GenesisConfig.NativeESDT)
args.ChainProcessorFactory = NewSovereignChainHandlerFactory()
args.GenerateGenesisFile = func(args chainSimulatorConfigs.ArgsChainSimulatorConfigs, configs *config.Configs) (*dtos.InitialWalletKeys, error) {
return sovChainSimConfig.GenerateSovereignGenesisFile(args, configs)
}

return chainSimulator.NewSovereignChainSimulator(*args.ArgsChainSimulator)
}
Expand Down
7 changes: 7 additions & 0 deletions node/chainSimulator/chainSimulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type ArgsChainSimulator struct {
CreateRunTypeComponents func(args runType.ArgsRunTypeComponents) (factory.RunTypeComponentsHolder, error)
NodeFactory node.NodeFactory
ChainProcessorFactory ChainHandlerFactory
GenerateGenesisFile func(args configs.ArgsChainSimulatorConfigs, configs *config.Configs) (*dtos.InitialWalletKeys, error)
}

// ArgsBaseChainSimulator holds the arguments needed to create a new instance of simulator
Expand Down Expand Up @@ -144,6 +145,11 @@ func setSimulatorRunTypeArguments(args *ArgsChainSimulator) {
if args.ChainProcessorFactory == nil {
args.ChainProcessorFactory = NewChainHandlerFactory()
}
if args.GenerateGenesisFile == nil {
mariusmihaic marked this conversation as resolved.
Show resolved Hide resolved
args.GenerateGenesisFile = func(args configs.ArgsChainSimulatorConfigs, config *config.Configs) (*dtos.InitialWalletKeys, error) {
return configs.GenerateGenesisFile(args, config)
}
}
}

func createRunTypeCoreComponents() (factory.RunTypeCoreComponentsHolder, error) {
Expand Down Expand Up @@ -193,6 +199,7 @@ func (s *simulator) createChainHandlers(args ArgsBaseChainSimulator) error {
AlterConfigsFunction: args.AlterConfigsFunction,
NumNodesWaitingListShard: args.NumNodesWaitingListShard,
NumNodesWaitingListMeta: args.NumNodesWaitingListMeta,
GenerateGenesisFile: args.GenerateGenesisFile,
})
if err != nil {
return err
Expand Down
3 changes: 3 additions & 0 deletions node/chainSimulator/components/testOnlyProcessingNode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ func createMockArgsTestOnlyProcessingNode(t *testing.T) ArgsTestOnlyProcessingNo
MetaChainMinNodes: 1,
ConsensusGroupSize: 1,
MetaChainConsensusGroupSize: 1,
GenerateGenesisFile: func(args configs.ArgsChainSimulatorConfigs, config *config.Configs) (*dtos.InitialWalletKeys, error) {
return configs.GenerateGenesisFile(args, config)
},
})
require.Nil(t, err)

Expand Down
69 changes: 40 additions & 29 deletions node/chainSimulator/configs/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (

var oneEgld = big.NewInt(1000000000000000000)
var initialStakedEgldPerNode = big.NewInt(0).Mul(oneEgld, big.NewInt(2500))
var initialEgldPerNode = big.NewInt(0).Mul(oneEgld, big.NewInt(5000))
var initialSupply = big.NewInt(0).Mul(oneEgld, big.NewInt(20000000)) // 20 million EGLD
const (
// ChainID contains the chain id
Expand All @@ -58,6 +57,7 @@ type ArgsChainSimulatorConfigs struct {
NumNodesWaitingListShard uint32
NumNodesWaitingListMeta uint32
AlterConfigsFunction func(cfg *config.Configs)
GenerateGenesisFile func(args ArgsChainSimulatorConfigs, configs *config.Configs) (*dtos.InitialWalletKeys, error)
}

// ArgsConfigsSimulator holds the configs for the chain simulator
Expand All @@ -84,7 +84,7 @@ func CreateChainSimulatorConfigs(args ArgsChainSimulatorConfigs) (*ArgsConfigsSi
}

// update genesis.json
initialWallets, err := generateGenesisFile(args, configs)
initialWallets, err := args.GenerateGenesisFile(args, configs)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -191,7 +191,8 @@ func SetStakingV4ActivationEpochs(cfg *config.Configs, initialEpoch uint32) {
cfg.SystemSCConfig.StakingSystemSCConfig.NodeLimitPercentage = 1
}

func generateGenesisFile(args ArgsChainSimulatorConfigs, configs *config.Configs) (*dtos.InitialWalletKeys, error) {
// GenerateGenesisFile will generate initial wallet keys
func GenerateGenesisFile(args ArgsChainSimulatorConfigs, configs *config.Configs) (*dtos.InitialWalletKeys, error) {
addressConverter, err := factory.NewPubkeyConverter(configs.GeneralConfig.AddressPubkeyConverter)
if err != nil {
return nil, err
Expand All @@ -201,47 +202,56 @@ func generateGenesisFile(args ArgsChainSimulatorConfigs, configs *config.Configs
BalanceWallets: make(map[uint32]*dtos.WalletKey),
StakeWallets: make([]*dtos.WalletKey, 0),
}

addresses := make([]data.InitialAccount, 0)
numOfNodes := int((args.NumNodesWaitingListShard+args.MinNodesPerShard)*args.NumOfShards + args.NumNodesWaitingListMeta + args.MetaChainMinNodes)
for i := 0; i < numOfNodes; i++ {
wallet, errGenerate := generateWalletKey(addressConverter)
if errGenerate != nil {
return nil, errGenerate
}

totalStakedValue := big.NewInt(0).Set(initialStakedEgldPerNode)
totalStakedValue.Mul(totalStakedValue, big.NewInt(int64(numOfNodes)))
stakedValue := big.NewInt(0).Set(initialStakedEgldPerNode)
addresses = append(addresses, data.InitialAccount{
Address: wallet.Address.Bech32,
StakingValue: stakedValue,
Supply: stakedValue,
})

initialWalletKeys.StakeWallets = append(initialWalletKeys.StakeWallets, wallet)
}

// generate an address for every shard
initialBalance := big.NewInt(0).Set(initialSupply)
initialBalance.Sub(initialBalance, totalStakedValue)
totalStakedValue := big.NewInt(int64(numOfNodes))
totalStakedValue = totalStakedValue.Mul(totalStakedValue, big.NewInt(0).Set(initialStakedEgldPerNode))
initialBalance = initialBalance.Sub(initialBalance, totalStakedValue)

for i := 0; i < numOfNodes; i++ {
initialEgld := big.NewInt(0).Set(initialEgldPerNode)

if i == numOfNodes-1 {
remainingSupply := big.NewInt(0).Set(initialBalance)
allBalances := big.NewInt(0).Set(initialEgld)
allBalances.Mul(allBalances, big.NewInt(int64(numOfNodes)))
remainingSupply.Sub(remainingSupply, allBalances)
if remainingSupply.Cmp(big.NewInt(0)) > 0 {
initialEgld.Add(initialEgld, remainingSupply)
}
}
walletBalance := big.NewInt(0).Set(initialBalance)
walletBalance.Div(walletBalance, big.NewInt(int64(args.NumOfShards)))

walletKey, errG := generateWalletKeyForShard(0, args.NumOfShards, addressConverter)
// remainder = balance % numTotalWalletKeys
remainder := big.NewInt(0).Set(initialBalance)
remainder.Mod(remainder, big.NewInt(int64(args.NumOfShards)))

for shardID := uint32(0); shardID < args.NumOfShards; shardID++ {
walletKey, errG := GenerateWalletKeyForShard(shardID, args.NumOfShards, addressConverter)
if errG != nil {
return nil, errG
}

supply := big.NewInt(0).Set(initialEgld)
supply.Add(supply, big.NewInt(0).Set(initialStakedEgldPerNode))

addresses = append(addresses, data.InitialAccount{
Address: walletKey.Address.Bech32,
Balance: initialEgld,
Supply: supply,
StakingValue: big.NewInt(0).Set(initialStakedEgldPerNode),
Address: walletKey.Address.Bech32,
Balance: big.NewInt(0).Set(walletBalance),
Supply: big.NewInt(0).Set(walletBalance),
})

initialWalletKeys.StakeWallets = append(initialWalletKeys.StakeWallets, walletKey)
initialWalletKeys.BalanceWallets[uint32(i)] = walletKey
initialWalletKeys.BalanceWallets[shardID] = walletKey
}

addresses[len(addresses)-1].Balance.Add(walletBalance, remainder)
addresses[len(addresses)-1].Supply.Add(walletBalance, remainder)

addressesBytes, errM := json.Marshal(addresses)
if errM != nil {
return nil, errM
Expand Down Expand Up @@ -410,7 +420,8 @@ func GetLatestGasScheduleFilename(directory string) (string, error) {
return path.Join(directory, filename), nil
}

func generateWalletKeyForShard(shardID, numOfShards uint32, converter core.PubkeyConverter) (*dtos.WalletKey, error) {
// GenerateWalletKeyForShard will generate a wallet key in a specific shard
func GenerateWalletKeyForShard(shardID, numOfShards uint32, converter core.PubkeyConverter) (*dtos.WalletKey, error) {
for {
walletKey, err := generateWalletKey(converter)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions node/chainSimulator/configs/configs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func TestNewProcessorRunnerChainArguments(t *testing.T) {
MinNodesPerShard: 1,
ConsensusGroupSize: 1,
MetaChainConsensusGroupSize: 1,
GenerateGenesisFile: GenerateGenesisFile,
})
require.Nil(t, err)

Expand Down