diff --git a/chain/chain.go b/chain/chain.go index 50bf41e1bc..67f216a09d 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -361,13 +361,3 @@ func importChain(content []byte) (*Chain, error) { return chain, nil } - -// GetGenesisAccountBalance returns balance for genesis account based on its address (expressed in weis). -// If not found in provided allocations map, 0 is returned. -func GetGenesisAccountBalance(address types.Address, allocations map[types.Address]*GenesisAccount) (*big.Int, error) { - if genesisAcc, ok := allocations[address]; ok { - return genesisAcc.Balance, nil - } - - return nil, fmt.Errorf("genesis account %s is not found among genesis allocations", address) -} diff --git a/chain/chain_test.go b/chain/chain_test.go index db88298784..88568a019c 100644 --- a/chain/chain_test.go +++ b/chain/chain_test.go @@ -2,13 +2,11 @@ package chain import ( "encoding/json" - "fmt" "math/big" "reflect" "testing" "github.com/0xPolygon/polygon-edge/types" - "github.com/stretchr/testify/require" ) var emptyAddr types.Address @@ -152,48 +150,3 @@ func TestGenesisX(t *testing.T) { }) } } - -func TestGetGenesisAccountBalance(t *testing.T) { - t.Parallel() - - testAddr := types.Address{0x2} - cases := []struct { - name string - address types.Address - allocs map[types.Address]*GenesisAccount - expectedBalance *big.Int - shouldFail bool - }{ - { - name: "Query existing account", - address: testAddr, - allocs: map[types.Address]*GenesisAccount{ - testAddr: {Balance: big.NewInt(50)}, - }, - expectedBalance: big.NewInt(50), - shouldFail: false, - }, - { - name: "Query non-existing account", - address: testAddr, - allocs: nil, - expectedBalance: nil, - shouldFail: true, - }, - } - - for _, c := range cases { - c := c - t.Run(c.name, func(t *testing.T) { - t.Parallel() - - actualBalance, err := GetGenesisAccountBalance(c.address, c.allocs) - if c.shouldFail { - require.Equal(t, err.Error(), fmt.Errorf("genesis account %s is not found among genesis allocations", c.address).Error()) - } else { - require.NoError(t, err) - } - require.Equal(t, c.expectedBalance, actualBalance) - }) - } -} diff --git a/command/bridge/withdraw/withdraw_erc20.go b/command/bridge/withdraw/withdraw_erc20.go index 6e00c63dbb..4716115d2f 100644 --- a/command/bridge/withdraw/withdraw_erc20.go +++ b/command/bridge/withdraw/withdraw_erc20.go @@ -155,13 +155,14 @@ func run(cmd *cobra.Command, _ []string) { receipt, err := txRelayer.SendTransaction(txn, senderAccount) if err != nil { - outputter.SetError(fmt.Errorf("receiver: %s, amount: %s, error: %w", receiver, amount, err)) + outputter.SetError(fmt.Errorf("failed to send withdraw transaction (receiver: %s, amount: %s). error: %w)", + receiver, amount, err)) return } if receipt.Status == uint64(types.ReceiptFailed) { - outputter.SetError(fmt.Errorf("receiver: %s, amount: %s", receiver, amount)) + outputter.SetError(fmt.Errorf("failed to execute withdrawal (receiver: %s, amount: %s)", receiver, amount)) return } diff --git a/command/genesis/genesis.go b/command/genesis/genesis.go index 46a12c8bda..e45b207beb 100644 --- a/command/genesis/genesis.go +++ b/command/genesis/genesis.go @@ -16,7 +16,7 @@ func GetCommand() *cobra.Command { genesisCmd := &cobra.Command{ Use: "genesis", Short: "Generates the genesis configuration file with the passed in parameters", - PreRunE: runPreRun, + PreRunE: preRunCommand, Run: runCommand, } @@ -60,7 +60,7 @@ func setFlags(cmd *cobra.Command) { premineFlag, []string{}, fmt.Sprintf( - "the premined accounts and balances (format:
:). Default premined balance: %d", + "the premined accounts and balances (format:
[:]). Default premined balance: %d", command.DefaultPremineBalance, ), ) @@ -150,12 +150,39 @@ func setFlags(cmd *cobra.Command) { // PolyBFT { cmd.Flags().StringVar( - ¶ms.manifestPath, - manifestPathFlag, - defaultManifestPath, - "the manifest file path, which contains genesis metadata", + ¶ms.validatorsPath, + validatorsPathFlag, + "./", + "root path containing polybft validators secrets", ) + cmd.Flags().StringVar( + ¶ms.validatorsPrefixPath, + validatorsPrefixFlag, + defaultValidatorPrefixPath, + "folder prefix names for polybft validators secrets", + ) + + cmd.Flags().StringArrayVar( + ¶ms.validators, + validatorsFlag, + []string{}, + "validators defined by user (format: :::)", + ) + + cmd.Flags().StringArrayVar( + ¶ms.stakes, + stakeFlag, + []string{}, + fmt.Sprintf( + "validators staked amount (format:
[:]). Default stake amount: %d", + command.DefaultStake, + ), + ) + + cmd.MarkFlagsMutuallyExclusive(validatorsFlag, validatorsPathFlag) + cmd.MarkFlagsMutuallyExclusive(validatorsFlag, validatorsPrefixFlag) + cmd.Flags().Uint64Var( ¶ms.sprintSize, sprintSizeFlag, @@ -170,13 +197,6 @@ func setFlags(cmd *cobra.Command) { "the predefined period which determines block creation frequency", ) - cmd.Flags().StringVar( - ¶ms.bridgeJSONRPCAddr, - bridgeFlag, - "", - "the rootchain JSON RPC endpoint", - ) - cmd.Flags().Uint64Var( ¶ms.epochReward, epochRewardFlag, @@ -184,15 +204,7 @@ func setFlags(cmd *cobra.Command) { "reward size for block sealing", ) - cmd.Flags().StringArrayVar( - ¶ms.eventTrackerStartBlocks, - trackerStartBlocksFlag, - []string{}, - "event tracker starting block configuration, which is specified per contract address "+ - "(format: :)", - ) - - //Regenesis flag that allows to start from non-empty database + // regenesis flag that allows to start from non-empty database cmd.Flags().StringVar( ¶ms.initialStateRoot, trieRootFlag, @@ -255,13 +267,13 @@ func setLegacyFlags(cmd *cobra.Command) { ¶ms.chainID, chainIDFlagLEGACY, command.DefaultChainID, - "the ID of the chain (not-applicable for Polybft consensus protocol as chain id is defined in manifest.json)", + "the ID of the chain", ) _ = cmd.Flags().MarkHidden(chainIDFlagLEGACY) } -func runPreRun(cmd *cobra.Command, _ []string) error { +func preRunCommand(cmd *cobra.Command, _ []string) error { if err := params.validateFlags(); err != nil { return err } diff --git a/command/genesis/params.go b/command/genesis/params.go index edf0ef5f0e..d420251141 100644 --- a/command/genesis/params.go +++ b/command/genesis/params.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math" + "os" "strconv" "strings" "time" @@ -90,12 +91,13 @@ type genesisParams struct { genesisConfig *chain.Chain // PolyBFT - manifestPath string - sprintSize uint64 - blockTime time.Duration - bridgeJSONRPCAddr string - epochReward uint64 - eventTrackerStartBlocks []string + validatorsPath string + validatorsPrefixPath string + stakes []string + validators []string + sprintSize uint64 + blockTime time.Duration + epochReward uint64 initialStateRoot string @@ -142,12 +144,15 @@ func (p *genesisParams) validateFlags() error { return errInvalidEpochSize } - // Validate min and max validators number - if err := command.ValidateMinMaxValidatorsNumber(p.minNumValidators, p.maxNumValidators); err != nil { - return err + // Validate validatorsPath only if validators information were not provided via CLI flag + if len(p.validators) == 0 { + if _, err := os.Stat(p.validatorsPath); err != nil { + return fmt.Errorf("invalid validators path ('%s') provided. Error: %w", p.validatorsPath, err) + } } - return nil + // Validate min and max validators number + return command.ValidateMinMaxValidatorsNumber(p.minNumValidators, p.maxNumValidators) } func (p *genesisParams) isIBFTConsensus() bool { @@ -368,13 +373,13 @@ func (p *genesisParams) initGenesisConfig() error { } for _, premineRaw := range p.premine { - premineInfo, err := ParsePremineInfo(premineRaw) + premineInfo, err := parsePremineInfo(premineRaw) if err != nil { return err } - chainConfig.Genesis.Alloc[premineInfo.Address] = &chain.GenesisAccount{ - Balance: premineInfo.Amount, + chainConfig.Genesis.Alloc[premineInfo.address] = &chain.GenesisAccount{ + Balance: premineInfo.amount, } } diff --git a/command/genesis/polybft_params.go b/command/genesis/polybft_params.go index 4d0852a7a5..ecea9fe195 100644 --- a/command/genesis/polybft_params.go +++ b/command/genesis/polybft_params.go @@ -4,33 +4,37 @@ import ( "errors" "fmt" "math/big" + "path" "strings" "time" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" - "github.com/0xPolygon/polygon-edge/helper/common" + "github.com/multiformats/go-multiaddr" "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/helper" - "github.com/0xPolygon/polygon-edge/consensus/polybft" "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/server" "github.com/0xPolygon/polygon-edge/types" ) const ( - manifestPathFlag = "manifest" - sprintSizeFlag = "sprint-size" - blockTimeFlag = "block-time" - bridgeFlag = "bridge-json-rpc" - trackerStartBlocksFlag = "tracker-start-blocks" - trieRootFlag = "trieroot" - - defaultManifestPath = "./manifest.json" + stakeFlag = "stake" + validatorsFlag = "validators" + validatorsPathFlag = "validators-path" + validatorsPrefixFlag = "validators-prefix" + + defaultValidatorPrefixPath = "test-chain-" + + sprintSizeFlag = "sprint-size" + blockTimeFlag = "block-time" + trieRootFlag = "trieroot" + defaultEpochSize = uint64(10) defaultSprintSize = uint64(5) defaultValidatorSetSize = 100 @@ -44,6 +48,10 @@ const ( transactionsAllowListEnabledFlag = "transactions-allow-list-enabled" bootnodePortStart = 30301 + + ecdsaAddressLength = 40 + blsKeyLength = 256 + blsSignatureLength = 128 ) var ( @@ -52,49 +60,45 @@ var ( // generatePolyBftChainConfig creates and persists polybft chain configuration to the provided file path func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) error { - // load manifest file - manifest, err := polybft.LoadManifest(p.manifestPath) - if err != nil { - return fmt.Errorf("failed to load manifest file from provided path '%s': %w", p.manifestPath, err) - } + // populate premine balance map + premineBalances := make(map[types.Address]*premineInfo, len(p.premine)) - if len(manifest.GenesisValidators) == 0 { - return errNoGenesisValidators + for _, premine := range p.premine { + premineInfo, err := parsePremineInfo(premine) + if err != nil { + return fmt.Errorf("invalid balance amount provided '%s' : %w", premine, err) + } + + premineBalances[premineInfo.address] = premineInfo } - eventTrackerStartBlock, err := parseTrackerStartBlocks(params.eventTrackerStartBlocks) + initialValidators, err := p.getValidatorAccounts(premineBalances) if err != nil { - return err + return fmt.Errorf("failed to retrieve genesis validators: %w", err) } - var bridge *polybft.BridgeConfig - - // populate bridge configuration - if p.bridgeJSONRPCAddr != "" && manifest.RootchainConfig != nil { - bridge = manifest.RootchainConfig.ToBridgeConfig() - bridge.JSONRPCEndpoint = p.bridgeJSONRPCAddr - bridge.EventTrackerStartBlocks = eventTrackerStartBlock + if len(initialValidators) == 0 { + return errNoGenesisValidators } if _, err := o.Write([]byte("[GENESIS VALIDATORS]\n")); err != nil { return err } - for _, v := range manifest.GenesisValidators { + for _, v := range initialValidators { if _, err := o.Write([]byte(fmt.Sprintf("%v\n", v))); err != nil { return err } } polyBftConfig := &polybft.PolyBFTConfig{ - InitialValidatorSet: manifest.GenesisValidators, + InitialValidatorSet: initialValidators, BlockTime: common.Duration{Duration: p.blockTime}, EpochSize: p.epochSize, SprintSize: p.sprintSize, EpochReward: p.epochReward, // use 1st account as governance address - Governance: manifest.GenesisValidators[0].Address, - Bridge: bridge, + Governance: initialValidators[0].Address, InitialTrieRoot: types.StringToHash(p.initialStateRoot), MintableNativeToken: p.mintableNativeToken, NativeTokenConfig: p.nativeTokenConfig, @@ -103,7 +107,7 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er chainConfig := &chain.Chain{ Name: p.name, Params: &chain.Params{ - ChainID: manifest.ChainID, + ChainID: int64(p.chainID), Forks: chain.AllForksEnabled, Engine: map[string]interface{}{ string(server.PolyBFTConsensus): polyBftConfig, @@ -112,13 +116,9 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er Bootnodes: p.bootnodes, } - genesisValidators := make(map[types.Address]struct{}, len(manifest.GenesisValidators)) totalStake := big.NewInt(0) - for _, validator := range manifest.GenesisValidators { - // populate premine info for validator accounts - genesisValidators[validator.Address] = struct{}{} - + for _, validator := range initialValidators { // increment total stake totalStake.Add(totalStake, validator.Stake) } @@ -129,55 +129,28 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er return err } - premineInfos := make([]*PremineInfo, len(p.premine)) - premineValidatorsAddrs := []string{} - // premine non-validator - for i, premine := range p.premine { - premineInfo, err := ParsePremineInfo(premine) - if err != nil { - return err - } - - // collect validators addresses which got premined, as it is an error - // genesis validators balances must be defined in manifest file and should not be changed in the genesis - if _, ok := genesisValidators[premineInfo.Address]; ok { - premineValidatorsAddrs = append(premineValidatorsAddrs, premineInfo.Address.String()) - } else { - premineInfos[i] = premineInfo + // premine initial validators + for _, v := range initialValidators { + allocs[v.Address] = &chain.GenesisAccount{ + Balance: v.Balance, } } - // if there are any premined validators in the genesis command, consider it as an error - if len(premineValidatorsAddrs) > 0 { - return fmt.Errorf("it is not allowed to override genesis validators balance outside from the manifest definition. "+ - "Validators which got premined: (%s)", strings.Join(premineValidatorsAddrs, ", ")) - } - - // populate genesis validators balances - for _, validator := range manifest.GenesisValidators { - allocs[validator.Address] = &chain.GenesisAccount{ - Balance: validator.Balance, + // premine other accounts + for _, premine := range premineBalances { + // validators have already been premined, so no need to premine them again + if _, ok := allocs[premine.address]; ok { + continue } - } - // premine non-validator accounts - for _, premine := range premineInfos { - allocs[premine.Address] = &chain.GenesisAccount{ - Balance: premine.Amount, + allocs[premine.address] = &chain.GenesisAccount{ + Balance: premine.amount, } } - validatorMetadata := make([]*polybft.ValidatorMetadata, len(manifest.GenesisValidators)) - - for i, validator := range manifest.GenesisValidators { - // update balance of genesis validator, because it could be changed via premine flag - balance, err := chain.GetGenesisAccountBalance(validator.Address, allocs) - if err != nil { - return err - } - - validator.Balance = balance + validatorMetadata := make([]*polybft.ValidatorMetadata, len(initialValidators)) + for i, validator := range initialValidators { // create validator metadata instance metadata, err := validator.ToValidatorMetadata() if err != nil { @@ -327,6 +300,91 @@ func generateExtraDataPolyBft(validators []*polybft.ValidatorMetadata) ([]byte, return extra.MarshalRLPTo(nil), nil } +// getValidatorAccounts gathers validator accounts info either from CLI or from provided local storage +func (p *genesisParams) getValidatorAccounts( + premineBalances map[types.Address]*premineInfo) ([]*polybft.Validator, error) { + // populate validators premine info + stakeMap := make(map[types.Address]*premineInfo, len(p.stakes)) + + for _, stake := range p.stakes { + stakeInfo, err := parsePremineInfo(stake) + if err != nil { + return nil, fmt.Errorf("invalid stake amount provided '%s' : %w", stake, err) + } + + stakeMap[stakeInfo.address] = stakeInfo + } + + if len(p.validators) > 0 { + validators := make([]*polybft.Validator, len(p.validators)) + for i, validator := range p.validators { + parts := strings.Split(validator, ":") + if len(parts) != 4 { + return nil, fmt.Errorf("expected 4 parts provided in the following format "+ + ", but got %d part(s)", + len(parts)) + } + + if _, err := multiaddr.NewMultiaddr(parts[0]); err != nil { + return nil, fmt.Errorf("invalid P2P multi address '%s' provided: %w ", parts[0], err) + } + + trimmedAddress := strings.TrimPrefix(parts[1], "0x") + if len(trimmedAddress) != ecdsaAddressLength { + return nil, fmt.Errorf("invalid ECDSA address: %s", parts[1]) + } + + trimmedBLSKey := strings.TrimPrefix(parts[2], "0x") + if len(trimmedBLSKey) != blsKeyLength { + return nil, fmt.Errorf("invalid BLS key: %s", parts[2]) + } + + if len(parts[3]) != blsSignatureLength { + return nil, fmt.Errorf("invalid BLS signature: %s", parts[3]) + } + + addr := types.StringToAddress(trimmedAddress) + validators[i] = &polybft.Validator{ + MultiAddr: parts[0], + Address: addr, + BlsKey: trimmedBLSKey, + BlsSignature: parts[3], + Balance: getPremineAmount(addr, premineBalances, command.DefaultPremineBalance), + Stake: getPremineAmount(addr, stakeMap, command.DefaultStake), + } + } + + return validators, nil + } + + validatorsPath := p.validatorsPath + if validatorsPath == "" { + validatorsPath = path.Dir(p.genesisPath) + } + + validators, err := ReadValidatorsByPrefix(validatorsPath, p.validatorsPrefixPath) + if err != nil { + return nil, err + } + + for _, v := range validators { + v.Balance = getPremineAmount(v.Address, premineBalances, command.DefaultPremineBalance) + v.Stake = getPremineAmount(v.Address, stakeMap, command.DefaultStake) + } + + return validators, nil +} + +// getPremineAmount retrieves amount from the premine map or if not provided, returns default amount +func getPremineAmount(addr types.Address, premineMap map[types.Address]*premineInfo, + defaultAmount *big.Int) *big.Int { + if premine, exists := premineMap[addr]; exists { + return premine.amount + } + + return defaultAmount +} + func stringSliceToAddressSlice(addrs []string) []types.Address { res := make([]types.Address, len(addrs)) for indx, addr := range addrs { diff --git a/command/genesis/utils.go b/command/genesis/utils.go index bef4153758..fb810b495e 100644 --- a/command/genesis/utils.go +++ b/command/genesis/utils.go @@ -62,13 +62,13 @@ func verifyGenesisExistence(genesisPath string) *GenesisGenError { return nil } -type PremineInfo struct { - Address types.Address - Amount *big.Int +type premineInfo struct { + address types.Address + amount *big.Int } -// ParsePremineInfo parses provided premine information and returns premine address and amount -func ParsePremineInfo(premineInfoRaw string) (*PremineInfo, error) { +// parsePremineInfo parses provided premine information and returns premine address and amount +func parsePremineInfo(premineInfoRaw string) (*premineInfo, error) { var ( address types.Address amount = command.DefaultPremineBalance @@ -90,7 +90,7 @@ func ParsePremineInfo(premineInfoRaw string) (*PremineInfo, error) { address = types.StringToAddress(premineInfoRaw) } - return &PremineInfo{Address: address, Amount: amount}, nil + return &premineInfo{address: address, amount: amount}, nil } // parseTrackerStartBlocks parses provided event tracker start blocks configuration. diff --git a/command/polybftmanifest/manifest_init.go b/command/polybftmanifest/manifest_init.go deleted file mode 100644 index 5d22a09486..0000000000 --- a/command/polybftmanifest/manifest_init.go +++ /dev/null @@ -1,268 +0,0 @@ -package polybftmanifest - -import ( - "bytes" - "errors" - "fmt" - "math/big" - "os" - "path" - "strings" - - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/command/genesis" - "github.com/0xPolygon/polygon-edge/consensus/polybft" - "github.com/0xPolygon/polygon-edge/types" - "github.com/multiformats/go-multiaddr" - "github.com/spf13/cobra" -) - -const ( - manifestPathFlag = "path" - premineValidatorsFlag = "premine-validators" - stakeFlag = "stake" - validatorsFlag = "validators" - validatorsPathFlag = "validators-path" - validatorsPrefixFlag = "validators-prefix" - chainIDFlag = "chain-id" - - defaultValidatorPrefixPath = "test-chain-" - defaultManifestPath = "./manifest.json" - - ecdsaAddressLength = 40 - blsKeyLength = 256 - blsSignatureLength = 128 -) - -var ( - params = &manifestInitParams{} -) - -func GetCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "manifest", - Short: "Initializes manifest file. It is applicable only to polybft consensus protocol.", - PreRunE: runPreRun, - Run: runCommand, - } - - setFlags(cmd) - - return cmd -} - -func runPreRun(_ *cobra.Command, _ []string) error { - return params.validateFlags() -} - -func setFlags(cmd *cobra.Command) { - cmd.Flags().StringVar( - ¶ms.manifestPath, - manifestPathFlag, - defaultManifestPath, - "the file path where manifest file is going to be stored", - ) - - cmd.Flags().StringVar( - ¶ms.validatorsPath, - validatorsPathFlag, - "./", - "root path containing polybft validator keys", - ) - - cmd.Flags().StringVar( - ¶ms.validatorsPrefixPath, - validatorsPrefixFlag, - defaultValidatorPrefixPath, - "folder prefix names for polybft validator keys", - ) - - cmd.Flags().StringArrayVar( - ¶ms.validators, - validatorsFlag, - []string{}, - "validators defined by user (format: :::)", - ) - - cmd.Flags().StringArrayVar( - ¶ms.premineValidators, - premineValidatorsFlag, - []string{}, - fmt.Sprintf( - "the premined validators and balances (format:
[:]). Default premined balance: %d", - command.DefaultPremineBalance, - ), - ) - - cmd.Flags().Int64Var( - ¶ms.chainID, - chainIDFlag, - command.DefaultChainID, - "the ID of the chain", - ) - - cmd.Flags().StringArrayVar( - ¶ms.stakes, - stakeFlag, - []string{}, - fmt.Sprintf( - "validators staked amount (format:
[:]). Default stake amount: %d", - command.DefaultStake, - ), - ) - - cmd.MarkFlagsMutuallyExclusive(validatorsFlag, validatorsPathFlag) - cmd.MarkFlagsMutuallyExclusive(validatorsFlag, validatorsPrefixFlag) -} - -func runCommand(cmd *cobra.Command, _ []string) { - outputter := command.InitializeOutputter(cmd) - defer outputter.WriteOutput() - - validators, err := params.getValidatorAccounts() - if err != nil { - outputter.SetError(fmt.Errorf("failed to get validator accounts: %w", err)) - - return - } - - manifest := &polybft.Manifest{GenesisValidators: validators, ChainID: params.chainID} - if err = manifest.Save(params.manifestPath); err != nil { - outputter.SetError(fmt.Errorf("failed to save manifest file '%s': %w", params.manifestPath, err)) - - return - } - - outputter.SetCommandResult(params.getResult()) -} - -type manifestInitParams struct { - manifestPath string - validatorsPath string - validatorsPrefixPath string - premineValidators []string - stakes []string - validators []string - chainID int64 -} - -func (p *manifestInitParams) validateFlags() error { - if _, err := os.Stat(p.validatorsPath); errors.Is(err, os.ErrNotExist) { - return fmt.Errorf("provided validators path '%s' doesn't exist", p.validatorsPath) - } - - return nil -} - -// getValidatorAccounts gathers validator accounts info either from CLI or from provided local storage -func (p *manifestInitParams) getValidatorAccounts() ([]*polybft.Validator, error) { - // populate validators premine info - premineMap := make(map[types.Address]*genesis.PremineInfo, len(p.premineValidators)) - stakeMap := make(map[types.Address]*genesis.PremineInfo, len(p.stakes)) - - for _, premine := range p.premineValidators { - premineInfo, err := genesis.ParsePremineInfo(premine) - if err != nil { - return nil, err - } - - premineMap[premineInfo.Address] = premineInfo - } - - for _, stake := range p.stakes { - stakeInfo, err := genesis.ParsePremineInfo(stake) - if err != nil { - return nil, fmt.Errorf("invalid stake amount provided '%s' : %w", stake, err) - } - - stakeMap[stakeInfo.Address] = stakeInfo - } - - if len(p.validators) > 0 { - validators := make([]*polybft.Validator, len(p.validators)) - for i, validator := range p.validators { - parts := strings.Split(validator, ":") - if len(parts) != 4 { - return nil, fmt.Errorf("expected 4 parts provided in the following format "+ - ", but got %d part(s)", - len(parts)) - } - - if _, err := multiaddr.NewMultiaddr(parts[0]); err != nil { - return nil, fmt.Errorf("invalid P2P multi address '%s' provided: %w ", parts[0], err) - } - - trimmedAddress := strings.TrimPrefix(parts[1], "0x") - if len(trimmedAddress) != ecdsaAddressLength { - return nil, fmt.Errorf("invalid ECDSA address: %s", parts[1]) - } - - trimmedBLSKey := strings.TrimPrefix(parts[2], "0x") - if len(trimmedBLSKey) != blsKeyLength { - return nil, fmt.Errorf("invalid BLS key: %s", parts[2]) - } - - if len(parts[3]) != blsSignatureLength { - return nil, fmt.Errorf("invalid BLS signature: %s", parts[3]) - } - - addr := types.StringToAddress(trimmedAddress) - validators[i] = &polybft.Validator{ - MultiAddr: parts[0], - Address: addr, - BlsKey: trimmedBLSKey, - BlsSignature: parts[3], - Balance: getPremineAmount(addr, premineMap, command.DefaultPremineBalance), - Stake: getPremineAmount(addr, stakeMap, command.DefaultStake), - } - } - - return validators, nil - } - - validatorsPath := p.validatorsPath - if validatorsPath == "" { - validatorsPath = path.Dir(p.manifestPath) - } - - validators, err := genesis.ReadValidatorsByPrefix(validatorsPath, p.validatorsPrefixPath) - if err != nil { - return nil, err - } - - for _, v := range validators { - v.Balance = getPremineAmount(v.Address, premineMap, command.DefaultPremineBalance) - v.Stake = getPremineAmount(v.Address, stakeMap, command.DefaultStake) - } - - return validators, nil -} - -// getPremineAmount retrieves amount from the premine map or if not provided, returns default amount -func getPremineAmount(addr types.Address, premineMap map[types.Address]*genesis.PremineInfo, - defaultAmount *big.Int) *big.Int { - if premine, exists := premineMap[addr]; exists { - return premine.Amount - } - - return defaultAmount -} - -func (p *manifestInitParams) getResult() command.CommandResult { - return &result{ - message: fmt.Sprintf("Manifest file written to %s\n", p.manifestPath), - } -} - -type result struct { - message string -} - -func (r *result) GetOutput() string { - var buffer bytes.Buffer - - buffer.WriteString("\n[MANIFEST INITIALIZATION SUCCESS]\n") - buffer.WriteString(r.message) - - return buffer.String() -} diff --git a/command/regenesis/howtotest.md b/command/regenesis/howtotest.md index 8a474a228c..6c0064cbae 100644 --- a/command/regenesis/howtotest.md +++ b/command/regenesis/howtotest.md @@ -1,166 +1,178 @@ -1) create cluster -```bash -scripts/cluster ibft -``` -2) check balance -```bash -curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002 - -{"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"} -``` - -3) get trie root -```bash -./polygon-edge regenesis getroot --rpc "http://localhost:10002" - -[Trie copy SUCCESS] -state root 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 for block 38 - -``` - -4) make trie snapshot -```bash - -./polygon-edge regenesis --target-path ./trie_new --stateRoot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 --source-path ./test-chain-1/trie - -[Trie copy SUCCESS] - -``` - -5) remove old chain data -```bash -rm -rf test-chain-* -``` -6) create new validators -```bash -./polygon-edge polybft-secrets --insecure --data-dir test-chain- --num 4 - -[WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] - -[SECRETS INIT] -Public key (address) = 0x467CaA6185461E4c518597dCE7DE497Fb98a5680 -BLS Public key = 197059fdc3a78bd4001d802481c5ff1d84870c0b37aef851c83522323bd80f6429751ddae63cf38d180a8d45a5b4bf5519f380d60d6eedf9ccd22c3f95fc5e3a1193155af6ff3ab9e2aea5beab3f52e5e364d2cb410d6108c92f9a8375aac73110b8526407691c7e92e5cfab984e9011202b0606dc2be942808554b848cce67b -Node ID = 16Uiu2HAmTN2YAviWyyG4A56Zz8gsVJhmksdojymS4pk54SZqVbGV - -[WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] - -[SECRETS INIT] -Public key (address) = 0x33177bBAebcB20F8545864a83b9b6EE334e4f94D -BLS Public key = 12d82d172646703d298453cef6f4415ceab2052267d9ec300fd4742fa46fd8db0168b5e98372ae3efd52d647f9b356043163fc4f76182f1ef685faf5e53b1dba15b7d0d9cb9b7868592e02179255775618dbacafd384cffba95b647a5d84de9a27995bb8cc0766194f370ad5b274d1a53b9b8ab21a3dee2f4ee4f177f63fb1f0 -Node ID = 16Uiu2HAkvtXkr1Hsct3UGn19ULNb7jgzPvEPu6Fpdakco8P45648 - -[WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] - -[SECRETS INIT] -Public key (address) = 0xf308dF858dA25c2e40485FfA2c037D98105FD254 -BLS Public key = 220efa87e71744f44e286230cf4ac95a419abdd6d33d1a578fee21387b841fa32184dd132c077adb8f46db0eb66333672e36b5f363778030475672defce0b5622bb0974424dd7babfdf722fe9eab75ab6e5e34e2ecfcea89420f757bf8adfeb7020f0f961ca946cdb2dde40413c5c0d48aa9f13182ec35b58c4052de466c0e25 -Node ID = 16Uiu2HAmJqYRtWGbepPjQMgWfXnFEkXuX4GKH8AdD1voTwHpKuFa - -[WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] - -[SECRETS INIT] -Public key (address) = 0x7eC6b7fc98D988472AD1AC0cFcaC6DA993d865B0 -BLS Public key = 2b8188f4bc99a19d5476fc97d14e17231cfb80b205a9fc45261725edefb0195209d972e9c1ad7d3c52b8fa129637738a88203c92fe8aa70fd0998d00f6251cb403ee077ddb4192fac270fe321468fe209308ea7597288e2505ed819f551ed00510c61f3da60f6a83d6017cbaeb7590c44bd354415178bbb160701b12a72a35a6 -Node ID = 16Uiu2HAmEuYYyzQKpyVr2HVCG8Gqx5e5DLCi8LWY4TkFYvHYcWAq - -``` - -7) generate genesis manifest -```bash -./polygon-edge manifest -``` - -8) generate genesis file -```bash -./polygon-edge genesis --consensus polybft --validator-set-size=4 --bridge-json-rpc http://127.0.0.1:8545 \ ---block-gas-limit 10000000 \ ---epoch-size 10 --trieroot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 - -[GENESIS SUCCESS] -**** POLYBFT CONSENSUS PROTOCOL IS IN EXPERIMENTAL PHASE AND IS NOT FULLY PRODUCTION READY. YOU ARE USING IT AT YOUR OWN RISK. **** -Genesis written to ./genesis.json - -``` - -9) Try to start a new v0.7 chain -```bash - ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG & -wait - -[1] 2615 -[2] 2616 -[3] 2617 -[4] 2618 -2023-03-15T11:02:25.149+0400 [INFO] polygon.server: Data dir: path=./test-chain-1 -2023-03-15T11:02:25.149+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:02:25.233+0400 [INFO] polygon.server: Data dir: path=./test-chain-3 -2023-03-15T11:02:25.251+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -invalid initial state root -[1] exit 1 ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json :10000 -2023-03-15T11:02:25.299+0400 [INFO] polygon.server: Data dir: path=./test-chain-2 -2023-03-15T11:02:25.302+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:02:25.396+0400 [INFO] polygon.server: Data dir: path=./test-chain-4 -2023-03-15T11:02:25.413+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -invalid initial state root -[3] - exit 1 ./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json :30000 -invalid initial state root -[2] - exit 1 ./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json :20000 -invalid initial state root -[4] + exit 1 ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json :40000 -``` - -It fails, because we havent provided trie database with correct state trie. - -10) Copy snapshot trie to our data directory -```bash -rm -rf ./test-chain-1/trie -rm -rf ./test-chain-2/trie -rm -rf ./test-chain-3/trie -rm -rf ./test-chain-4/trie -cp -fR ./trie_new/ ./test-chain-1/trie/ -cp -fR ./trie_new/ ./test-chain-2/trie/ -cp -fR ./trie_new/ ./test-chain-3/trie/ -cp -fR ./trie_new/ ./test-chain-4/trie/ -``` - -11) run chain again -```bash - ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG & -wait - -[1] 2721 -[2] 2722 -[3] 2723 -[4] 2724 -2023-03-15T11:09:41.481+0400 [INFO] polygon.server: Data dir: path=./test-chain-2 -2023-03-15T11:09:41.481+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:09:41.597+0400 [INFO] polygon.server: Data dir: path=./test-chain-1 -2023-03-15T11:09:41.597+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:09:41.609+0400 [WARN] polygon: Initial state root checked and correct -2023-03-15T11:09:41.661+0400 [INFO] polygon.server: Data dir: path=./test-chain-4 -2023-03-15T11:09:41.661+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:09:41.725+0400 [INFO] polygon.server: Data dir: path=./test-chain-3 -2023-03-15T11:09:41.725+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:09:41.844+0400 [INFO] polygon.blockchain: genesis: hash=0x627b70a8abc294324808d9820015faa5e0616afca5fdc75528b03b703a461acd -2023-03-15T11:09:41.844+0400 [INFO] polygon.server.polybft: initializing polybft... -2023-03-15T11:09:41.951+0400 [WARN] polygon: Initial state root checked and correct -2023-03-15T11:09:42.101+0400 [WARN] polygon: Initial state root checked and correct -2023-03-15T11:09:42.254+0400 [WARN] polygon: Initial state root checked and correct -2023-03-15T11:09:42.445+0400 [INFO] polygon.blockchain: genesis: hash=0x627b70a8abc294324808d9820015faa5e0616afca5fdc75528b03b703a461acd -2023-03-15T11:09:42.445+0400 [INFO] polygon.server.polybft: initializing polybft... -2023-03-15T11:09:42.462+0400 [INFO] polygon.server.polybft.consensus_runtime: restartEpoch: block number=0 epoch=1 validators=4 firstBlockInEpoch=1 -... -``` - -12) check that balance of account on v0.6 is not 0 -```bash - curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002 - -{"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"}% -``` \ No newline at end of file +# Regenesis procedure + +This document outlines step necessary to perform a regenesis data migration. + +## Steps + +1. Create cluster + + ```bash + scripts/cluster ibft + ``` + +2. Check balance + + ```bash + curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002 + + {"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"} + ``` + +3. Get trie root + + ```bash + ./polygon-edge regenesis getroot --rpc "http://localhost:10002" + + [Trie copy SUCCESS] + state root 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 for block 38 + ``` + +4. Make trie snapshot + + ```bash + ./polygon-edge regenesis --target-path ./trie_new --stateRoot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 --source-path ./test-chain-1/trie + + [Trie copy SUCCESS] + + ``` + +5. Remove old chain data + + ```bash + rm -rf test-chain-* + ``` + +6. Create new validators + + ```bash + ./polygon-edge polybft-secrets --insecure --data-dir test-chain- --num 4 + + [WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] + + [SECRETS INIT] + Public key (address. = 0x467CaA6185461E4c518597dCE7DE497Fb98a5680 + BLS Public key = 197059fdc3a78bd4001d802481c5ff1d84870c0b37aef851c83522323bd80f6429751ddae63cf38d180a8d45a5b4bf5519f380d60d6eedf9ccd22c3f95fc5e3a1193155af6ff3ab9e2aea5beab3f52e5e364d2cb410d6108c92f9a8375aac73110b8526407691c7e92e5cfab984e9011202b0606dc2be942808554b848cce67b + Node ID = 16Uiu2HAmTN2YAviWyyG4A56Zz8gsVJhmksdojymS4pk54SZqVbGV + + [WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] + + [SECRETS INIT] + Public key (address. = 0x33177bBAebcB20F8545864a83b9b6EE334e4f94D + BLS Public key = 12d82d172646703d298453cef6f4415ceab2052267d9ec300fd4742fa46fd8db0168b5e98372ae3efd52d647f9b356043163fc4f76182f1ef685faf5e53b1dba15b7d0d9cb9b7868592e02179255775618dbacafd384cffba95b647a5d84de9a27995bb8cc0766194f370ad5b274d1a53b9b8ab21a3dee2f4ee4f177f63fb1f0 + Node ID = 16Uiu2HAkvtXkr1Hsct3UGn19ULNb7jgzPvEPu6Fpdakco8P45648 + + [WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] + + [SECRETS INIT] + Public key (address. = 0xf308dF858dA25c2e40485FfA2c037D98105FD254 + BLS Public key = 220efa87e71744f44e286230cf4ac95a419abdd6d33d1a578fee21387b841fa32184dd132c077adb8f46db0eb66333672e36b5f363778030475672defce0b5622bb0974424dd7babfdf722fe9eab75ab6e5e34e2ecfcea89420f757bf8adfeb7020f0f961ca946cdb2dde40413c5c0d48aa9f13182ec35b58c4052de466c0e25 + Node ID = 16Uiu2HAmJqYRtWGbepPjQMgWfXnFEkXuX4GKH8AdD1voTwHpKuFa + + [WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] + + [SECRETS INIT] + Public key (address. = 0x7eC6b7fc98D988472AD1AC0cFcaC6DA993d865B0 + BLS Public key = 2b8188f4bc99a19d5476fc97d14e17231cfb80b205a9fc45261725edefb0195209d972e9c1ad7d3c52b8fa129637738a88203c92fe8aa70fd0998d00f6251cb403ee077ddb4192fac270fe321468fe209308ea7597288e2505ed819f551ed00510c61f3da60f6a83d6017cbaeb7590c44bd354415178bbb160701b12a72a35a6 + Node ID = 16Uiu2HAmEuYYyzQKpyVr2HVCG8Gqx5e5DLCi8LWY4TkFYvHYcWAq + + ``` + +7. Generate genesis file + + ```bash + ./polygon-edge genesis --consensus polybft \ + --block-gas-limit 10000000 \ + --epoch-size 10 --trieroot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 + + [GENESIS SUCCESS] + **** POLYBFT CONSENSUS PROTOCOL IS IN EXPERIMENTAL PHASE AND IS NOT FULLY PRODUCTION READY. YOU ARE USING IT AT YOUR OWN RISK. **** + Genesis written to ./genesis.json + + ``` + +8. Try to start a new v0.7 chain + + ```bash + ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG & + wait + + [1] 2615 + [2] 2616 + [3] 2617 + [4] 2618 + 2023-03-15T11:02:25.149+0400 [INFO] polygon.server: Data dir: path=./test-chain-1 + 2023-03-15T11:02:25.149+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:02:25.233+0400 [INFO] polygon.server: Data dir: path=./test-chain-3 + 2023-03-15T11:02:25.251+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + invalid initial state root + [1] exit 1 ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json :10000 + 2023-03-15T11:02:25.299+0400 [INFO] polygon.server: Data dir: path=./test-chain-2 + 2023-03-15T11:02:25.302+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:02:25.396+0400 [INFO] polygon.server: Data dir: path=./test-chain-4 + 2023-03-15T11:02:25.413+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + invalid initial state root + [3] - exit 1 ./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json :30000 + invalid initial state root + [2] - exit 1 ./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json :20000 + invalid initial state root + [4] + exit 1 ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json :40000 + ``` + + It fails, because we havent provided trie database with correct state trie. + +9. Copy snapshot trie to our data directory + + ```bash + rm -rf ./test-chain-1/trie + rm -rf ./test-chain-2/trie + rm -rf ./test-chain-3/trie + rm -rf ./test-chain-4/trie + cp -fR ./trie_new/ ./test-chain-1/trie/ + cp -fR ./trie_new/ ./test-chain-2/trie/ + cp -fR ./trie_new/ ./test-chain-3/trie/ + cp -fR ./trie_new/ ./test-chain-4/trie/ + ``` + +10. Run chain again + + ```bash + ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG & + wait + + [1] 2721 + [2] 2722 + [3] 2723 + [4] 2724 + 2023-03-15T11:09:41.481+0400 [INFO] polygon.server: Data dir: path=./test-chain-2 + 2023-03-15T11:09:41.481+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:09:41.597+0400 [INFO] polygon.server: Data dir: path=./test-chain-1 + 2023-03-15T11:09:41.597+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:09:41.609+0400 [WARN] polygon: Initial state root checked and correct + 2023-03-15T11:09:41.661+0400 [INFO] polygon.server: Data dir: path=./test-chain-4 + 2023-03-15T11:09:41.661+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:09:41.725+0400 [INFO] polygon.server: Data dir: path=./test-chain-3 + 2023-03-15T11:09:41.725+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:09:41.844+0400 [INFO] polygon.blockchain: genesis: hash=0x627b70a8abc294324808d9820015faa5e0616afca5fdc75528b03b703a461acd + 2023-03-15T11:09:41.844+0400 [INFO] polygon.server.polybft: initializing polybft... + 2023-03-15T11:09:41.951+0400 [WARN] polygon: Initial state root checked and correct + 2023-03-15T11:09:42.101+0400 [WARN] polygon: Initial state root checked and correct + 2023-03-15T11:09:42.254+0400 [WARN] polygon: Initial state root checked and correct + 2023-03-15T11:09:42.445+0400 [INFO] polygon.blockchain: genesis: hash=0x627b70a8abc294324808d9820015faa5e0616afca5fdc75528b03b703a461acd + 2023-03-15T11:09:42.445+0400 [INFO] polygon.server.polybft: initializing polybft... + 2023-03-15T11:09:42.462+0400 [INFO] polygon.server.polybft.consensus_runtime: restartEpoch: block number=0 epoch=1 validators=4 firstBlockInEpoch=1 + ... + ``` + +11. Check that balance of account on v0.6 is not 0 + + ```bash + curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002 + + {"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"}% + ``` diff --git a/command/root/root.go b/command/root/root.go index 958400825e..05805f9b11 100644 --- a/command/root/root.go +++ b/command/root/root.go @@ -15,7 +15,6 @@ import ( "github.com/0xPolygon/polygon-edge/command/monitor" "github.com/0xPolygon/polygon-edge/command/peers" "github.com/0xPolygon/polygon-edge/command/polybft" - "github.com/0xPolygon/polygon-edge/command/polybftmanifest" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" "github.com/0xPolygon/polygon-edge/command/regenesis" "github.com/0xPolygon/polygon-edge/command/rootchain" @@ -62,7 +61,6 @@ func (rc *RootCommand) registerSubCommands() { license.GetCommand(), polybftsecrets.GetCommand(), polybft.GetCommand(), - polybftmanifest.GetCommand(), bridge.GetCommand(), regenesis.GetCommand(), ) diff --git a/command/rootchain/README.md b/command/rootchain/README.md index 446e979af5..9721adb3c4 100644 --- a/command/rootchain/README.md +++ b/command/rootchain/README.md @@ -4,7 +4,7 @@ Top level command for manipulating rootchain server. ## Start rootchain server -This command starts `ethereum/client-go` container which is basically geth node. +This command starts `ethereum/client-go` container which is Geth node started in dev mode. ```bash $ polygon-edge rootchain server @@ -17,7 +17,9 @@ This command funds the initialized accounts via `polygon-edge polybft-secrets` c ```bash $ polygon-edge rootchain fund --data-dir data-dir- --num 2 ``` -Or + +or + ```bash $ polygon-edge rootchain fund --data-dir data-dir-1 ``` @@ -27,10 +29,10 @@ $ polygon-edge rootchain fund --data-dir data-dir-1 This command deploys and initializes rootchain contracts. Transactions are being sent to given `--json-rpc` endpoint and are signed by private key provided by `--adminKey` flag. ```bash -$ polygon-edge rootchain init-contracts - --manifest - --deployer-key +$ polygon-edge rootchain deploy \ + --genesis \ + --deployer-key \ --json-rpc ``` -**Note:** In case `test` flag is provided, it engages test mode, which uses predefined test account private key to send transactions to the rootchain. \ No newline at end of file +**Note:** In case `test` flag is provided, it engages test mode, which uses predefined test account private key to send transactions to the rootchain. diff --git a/command/rootchain/initcontracts/init_contracts.go b/command/rootchain/deploy/deploy.go similarity index 78% rename from command/rootchain/initcontracts/init_contracts.go rename to command/rootchain/deploy/deploy.go index 02adabff9c..eb99b01d1b 100644 --- a/command/rootchain/initcontracts/init_contracts.go +++ b/command/rootchain/deploy/deploy.go @@ -1,4 +1,4 @@ -package initcontracts +package deploy import ( "fmt" @@ -8,7 +8,9 @@ import ( "github.com/umbracle/ethgo" "github.com/umbracle/ethgo/jsonrpc" + "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/command" + cmdHelper "github.com/0xPolygon/polygon-edge/command/helper" "github.com/0xPolygon/polygon-edge/command/rootchain/helper" "github.com/0xPolygon/polygon-edge/consensus/polybft" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" @@ -36,7 +38,7 @@ const ( ) var ( - params initContractsParams + params deployParams // metadataPopulatorMap maps rootchain contract names to callback // which populates appropriate field in the RootchainMetadata @@ -80,27 +82,27 @@ var ( } ) -// GetCommand returns the rootchain init-contracts command +// GetCommand returns the rootchain deploy command func GetCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "init-contracts", + Use: "deploy", Short: "Deploys and initializes required smart contracts on the rootchain", - PreRunE: runPreRun, + PreRunE: preRunCommand, Run: runCommand, } cmd.Flags().StringVar( - ¶ms.manifestPath, - manifestPathFlag, - defaultManifestPath, - "manifest file path, which contains metadata", + ¶ms.genesisPath, + genesisPathFlag, + defaultGenesisPath, + "genesis file path, which contains chain configuration", ) cmd.Flags().StringVar( ¶ms.deployerKey, deployerKeyFlag, "", - "Hex encoded private key of the account which deploys rootchain contracts", + "hex-encoded private key of the account which deploys rootchain contracts", ) cmd.Flags().StringVar( @@ -144,7 +146,7 @@ func GetCommand() *cobra.Command { return cmd } -func runPreRun(_ *cobra.Command, _ []string) error { +func preRunCommand(_ *cobra.Command, _ []string) error { return params.validateFlags() } @@ -153,26 +155,33 @@ func runCommand(cmd *cobra.Command, _ []string) { defer outputter.WriteOutput() outputter.WriteCommandResult(&messageResult{ - Message: fmt.Sprintf("%s started...", contractsDeploymentTitle), + Message: fmt.Sprintf("%s started... Rootchain JSON RPC address %s.", contractsDeploymentTitle, params.jsonRPCAddress), }) - client, err := jsonrpc.NewClient(params.jsonRPCAddress) + chainConfig, err := chain.ImportFromFile(params.genesisPath) if err != nil { - outputter.SetError(fmt.Errorf("failed to initialize JSON RPC client for provided IP address: %s: %w", - params.jsonRPCAddress, err)) + outputter.SetError(fmt.Errorf("failed to read chain configuration: %w", err)) return } - manifest, err := polybft.LoadManifest(params.manifestPath) + consensusConfig, err := polybft.GetPolyBFTConfig(chainConfig) if err != nil { - outputter.SetError(fmt.Errorf("failed to read manifest: %w", err)) + outputter.SetError(fmt.Errorf("failed to retrieve consensus configuration: %w", err)) return } - if manifest.RootchainConfig != nil { - code, err := client.Eth().GetCode(ethgo.Address(manifest.RootchainConfig.StateSenderAddress), ethgo.Latest) + client, err := jsonrpc.NewClient(params.jsonRPCAddress) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize JSON RPC client for provided IP address: %s: %w", + params.jsonRPCAddress, err)) + + return + } + + if consensusConfig.Bridge != nil { + code, err := client.Eth().GetCode(ethgo.Address(consensusConfig.Bridge.StateSenderAddr), ethgo.Latest) if err != nil { outputter.SetError(fmt.Errorf("failed to check if rootchain contracts are deployed: %w", err)) @@ -186,38 +195,63 @@ func runCommand(cmd *cobra.Command, _ []string) { } } - if err := deployContracts(outputter, client, manifest); err != nil { + rootchainCfg, err := deployContracts(outputter, client, + chainConfig.Params.ChainID, consensusConfig.InitialValidatorSet) + if err != nil { outputter.SetError(fmt.Errorf("failed to deploy rootchain contracts: %w", err)) return } + // populate bridge configuration + consensusConfig.Bridge = rootchainCfg.ToBridgeConfig() + + // set event tracker start blocks for rootchain contract(s) of interest + blockNum, err := client.Eth().BlockNumber() + if err != nil { + outputter.SetError(fmt.Errorf("failed to query rootchain latest block number: %w", err)) + + return + } + + consensusConfig.Bridge.EventTrackerStartBlocks = map[types.Address]uint64{ + rootchainCfg.StateSenderAddress: blockNum, + } + + // write updated chain configuration + chainConfig.Params.Engine[polybft.ConsensusName] = consensusConfig + if err := cmdHelper.WriteGenesisConfigToDisk(chainConfig, params.genesisPath); err != nil { + outputter.SetError(fmt.Errorf("failed to save chain configuration bridge data: %w", err)) + + return + } + outputter.SetCommandResult(&messageResult{ Message: fmt.Sprintf("%s finished. All contracts are successfully deployed and initialized.", contractsDeploymentTitle), }) } +// deployContracts deploys and initializes rootchain smart contracts func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, - manifest *polybft.Manifest) error { + chainID int64, initialValidators []*polybft.Validator) (*polybft.RootchainConfig, error) { // if the bridge contract is not created, we have to deploy all the contracts txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(client)) if err != nil { - return fmt.Errorf("failed to initialize tx relayer: %w", err) + return nil, fmt.Errorf("failed to initialize tx relayer: %w", err) } deployerKey, err := helper.GetRootchainPrivateKey(params.deployerKey) if err != nil { - return fmt.Errorf("failed to initialize deployer key: %w", err) + return nil, fmt.Errorf("failed to initialize deployer key: %w", err) } if params.isTestMode { deployerAddr := deployerKey.Address() - txn := ðgo.Transaction{To: &deployerAddr, Value: big.NewInt(1000000000000000000)} + txn := ðgo.Transaction{To: &deployerAddr, Value: ethgo.Ether(1)} - _, err = txRelayer.SendTransactionLocal(txn) - if err != nil { - return err + if _, err = txRelayer.SendTransactionLocal(txn); err != nil { + return nil, err } } @@ -264,14 +298,15 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, artifact: contractsapi.RootERC1155Predicate, }, } - rootchainConfig := &polybft.RootchainConfig{} - manifest.RootchainConfig = rootchainConfig + rootchainConfig := &polybft.RootchainConfig{ + JSONRPCAddr: params.jsonRPCAddress, + } if params.rootERC20TokenAddr != "" { // use existing root chain ERC20 token if err := populateExistingTokenAddr(client.Eth(), - params.rootERC20TokenAddr, rootERC20Name, manifest); err != nil { - return err + params.rootERC20TokenAddr, rootERC20Name, rootchainConfig); err != nil { + return nil, err } } else { // deploy MockERC20 as a default root chain ERC20 token @@ -282,8 +317,8 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, if params.rootERC721TokenAddr != "" { // use existing root chain ERC721 token if err := populateExistingTokenAddr(client.Eth(), - params.rootERC721TokenAddr, rootERC721Name, manifest); err != nil { - return err + params.rootERC721TokenAddr, rootERC721Name, rootchainConfig); err != nil { + return nil, err } } else { // deploy MockERC721 as a default root chain ERC721 token @@ -294,8 +329,8 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, if params.rootERC1155TokenAddr != "" { // use existing root chain ERC1155 token if err := populateExistingTokenAddr(client.Eth(), - params.rootERC1155TokenAddr, rootERC1155Name, manifest); err != nil { - return err + params.rootERC1155TokenAddr, rootERC1155Name, rootchainConfig); err != nil { + return nil, err } } else { // deploy MockERC1155 as a default root chain ERC1155 token @@ -311,32 +346,29 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, receipt, err := txRelayer.SendTransaction(txn, deployerKey) if err != nil { - return err + return nil, err } if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) { - return fmt.Errorf("deployment of %s contract failed", contract.name) + return nil, fmt.Errorf("deployment of %s contract failed", contract.name) } contractAddr := types.Address(receipt.ContractAddress) populatorFn, ok := metadataPopulatorMap[contract.name] if !ok { - return fmt.Errorf("rootchain metadata populator not registered for contract '%s'", contract.name) + return nil, fmt.Errorf("rootchain metadata populator not registered for contract '%s'", contract.name) } - populatorFn(manifest.RootchainConfig, contractAddr) + populatorFn(rootchainConfig, contractAddr) outputter.WriteCommandResult(newDeployContractsResult(contract.name, contractAddr, receipt.TransactionHash)) } - if err := manifest.Save(params.manifestPath); err != nil { - return fmt.Errorf("failed to save manifest data: %w", err) - } - // init CheckpointManager - if err := initializeCheckpointManager(outputter, txRelayer, manifest, deployerKey); err != nil { - return err + if err := initializeCheckpointManager(outputter, txRelayer, chainID, + initialValidators, rootchainConfig, deployerKey); err != nil { + return nil, err } outputter.WriteCommandResult(&messageResult{ @@ -345,7 +377,7 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, // init ExitHelper if err := initializeExitHelper(txRelayer, rootchainConfig, deployerKey); err != nil { - return err + return nil, err } outputter.WriteCommandResult(&messageResult{ @@ -354,19 +386,20 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, // init RootERC20Predicate if err := initializeRootERC20Predicate(txRelayer, rootchainConfig, deployerKey); err != nil { - return err + return nil, err } outputter.WriteCommandResult(&messageResult{ Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, rootERC20PredicateName), }) - return nil + return rootchainConfig, nil } // populateExistingTokenAddr checks whether given token is deployed on the provided address. // If it is, then its address is set to the rootchain config, otherwise an error is returned -func populateExistingTokenAddr(eth *jsonrpc.Eth, tokenAddr, tokenName string, manifest *polybft.Manifest) error { +func populateExistingTokenAddr(eth *jsonrpc.Eth, tokenAddr, tokenName string, + rootchainCfg *polybft.RootchainConfig) error { addr := types.StringToAddress(tokenAddr) code, err := eth.GetCode(ethgo.Address(addr), ethgo.Latest) @@ -381,7 +414,7 @@ func populateExistingTokenAddr(eth *jsonrpc.Eth, tokenAddr, tokenName string, ma return fmt.Errorf("root chain metadata populator not registered for contract '%s'", tokenName) } - populatorFn(manifest.RootchainConfig, addr) + populatorFn(rootchainCfg, addr) return nil } @@ -390,17 +423,19 @@ func populateExistingTokenAddr(eth *jsonrpc.Eth, tokenAddr, tokenName string, ma func initializeCheckpointManager( o command.OutputFormatter, txRelayer txrelayer.TxRelayer, - manifest *polybft.Manifest, + chainID int64, + validators []*polybft.Validator, + rootchainCfg *polybft.RootchainConfig, deployerKey ethgo.Key) error { - validatorSet, err := validatorSetToABISlice(o, manifest.GenesisValidators) + validatorSet, err := validatorSetToABISlice(o, validators) if err != nil { return fmt.Errorf("failed to convert validators to map: %w", err) } initialize := contractsapi.InitializeCheckpointManagerFn{ - ChainID_: big.NewInt(manifest.ChainID), - NewBls: manifest.RootchainConfig.BLSAddress, - NewBn256G2: manifest.RootchainConfig.BN256G2Address, + ChainID_: big.NewInt(chainID), + NewBls: rootchainCfg.BLSAddress, + NewBn256G2: rootchainCfg.BN256G2Address, NewValidatorSet: validatorSet, } @@ -409,7 +444,7 @@ func initializeCheckpointManager( return fmt.Errorf("failed to encode parameters for CheckpointManager.initialize. error: %w", err) } - addr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) + addr := ethgo.Address(rootchainCfg.CheckpointManagerAddress) txn := ðgo.Transaction{ To: &addr, Input: initCheckpointInput, diff --git a/command/rootchain/initcontracts/init_contracts_test.go b/command/rootchain/deploy/deploy_test.go similarity index 76% rename from command/rootchain/initcontracts/init_contracts_test.go rename to command/rootchain/deploy/deploy_test.go index 60aeaa9a52..f61e2771b1 100644 --- a/command/rootchain/initcontracts/init_contracts_test.go +++ b/command/rootchain/deploy/deploy_test.go @@ -1,15 +1,17 @@ -package initcontracts +package deploy import ( "os" "testing" - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/command/rootchain/helper" - "github.com/0xPolygon/polygon-edge/consensus/polybft" "github.com/stretchr/testify/require" "github.com/umbracle/ethgo/jsonrpc" "github.com/umbracle/ethgo/testutil" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/types" ) func TestDeployContracts_NoPanics(t *testing.T) { @@ -17,8 +19,7 @@ func TestDeployContracts_NoPanics(t *testing.T) { server := testutil.DeployTestServer(t, nil) t.Cleanup(func() { - err := os.RemoveAll(params.manifestPath) - if err != nil { + if err := os.RemoveAll(params.genesisPath); err != nil { t.Fatal(err) } }) @@ -31,12 +32,12 @@ func TestDeployContracts_NoPanics(t *testing.T) { receipt, err := server.Fund(testKey.Address()) require.NoError(t, err) - require.Equal(t, uint64(1), receipt.Status) + require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) outputter := command.InitializeOutputter(GetCommand()) require.NotPanics(t, func() { - err = deployContracts(outputter, client, &polybft.Manifest{}) + _, err = deployContracts(outputter, client, 10, []*polybft.Validator{}) }) require.NoError(t, err) } diff --git a/command/rootchain/deploy/params.go b/command/rootchain/deploy/params.go new file mode 100644 index 0000000000..4307b76806 --- /dev/null +++ b/command/rootchain/deploy/params.go @@ -0,0 +1,35 @@ +package deploy + +import ( + "fmt" + "os" +) + +const ( + genesisPathFlag = "genesis" + deployerKeyFlag = "deployer-key" + jsonRPCFlag = "json-rpc" + erc20AddrFlag = "erc20-token" + erc721AddrFlag = "erc721-token" + erc1155AddrFlag = "erc1155-token" + + defaultGenesisPath = "./genesis.json" +) + +type deployParams struct { + genesisPath string + deployerKey string + jsonRPCAddress string + rootERC20TokenAddr string + rootERC721TokenAddr string + rootERC1155TokenAddr string + isTestMode bool +} + +func (ip *deployParams) validateFlags() error { + if _, err := os.Stat(ip.genesisPath); err != nil { + return fmt.Errorf("provided genesis path '%s' is invalid. Error: %w ", ip.genesisPath, err) + } + + return nil +} diff --git a/command/rootchain/initcontracts/result.go b/command/rootchain/deploy/result.go similarity index 98% rename from command/rootchain/initcontracts/result.go rename to command/rootchain/deploy/result.go index b268b571dd..da9cd577b8 100644 --- a/command/rootchain/initcontracts/result.go +++ b/command/rootchain/deploy/result.go @@ -1,4 +1,4 @@ -package initcontracts +package deploy import ( "bytes" diff --git a/command/rootchain/initcontracts/params.go b/command/rootchain/initcontracts/params.go deleted file mode 100644 index a92c1f02bf..0000000000 --- a/command/rootchain/initcontracts/params.go +++ /dev/null @@ -1,36 +0,0 @@ -package initcontracts - -import ( - "errors" - "fmt" - "os" -) - -const ( - manifestPathFlag = "manifest" - deployerKeyFlag = "deployer-key" - jsonRPCFlag = "json-rpc" - erc20AddrFlag = "erc20-token" - erc721AddrFlag = "erc721-token" - erc1155AddrFlag = "erc1155-token" - - defaultManifestPath = "./manifest.json" -) - -type initContractsParams struct { - manifestPath string - deployerKey string - jsonRPCAddress string - rootERC20TokenAddr string - rootERC721TokenAddr string - rootERC1155TokenAddr string - isTestMode bool -} - -func (ip *initContractsParams) validateFlags() error { - if _, err := os.Stat(ip.manifestPath); errors.Is(err, os.ErrNotExist) { - return fmt.Errorf("provided manifest path '%s' doesn't exist", ip.manifestPath) - } - - return nil -} diff --git a/command/rootchain/rootchain.go b/command/rootchain/rootchain.go index 2d7fa00f62..c49a8fcd73 100644 --- a/command/rootchain/rootchain.go +++ b/command/rootchain/rootchain.go @@ -3,8 +3,8 @@ package rootchain import ( "github.com/spf13/cobra" + "github.com/0xPolygon/polygon-edge/command/rootchain/deploy" "github.com/0xPolygon/polygon-edge/command/rootchain/fund" - "github.com/0xPolygon/polygon-edge/command/rootchain/initcontracts" "github.com/0xPolygon/polygon-edge/command/rootchain/server" ) @@ -15,18 +15,14 @@ func GetCommand() *cobra.Command { Short: "Top level rootchain helper command.", } - registerSubcommands(rootchainCmd) - - return rootchainCmd -} - -func registerSubcommands(baseCmd *cobra.Command) { - baseCmd.AddCommand( - // rootchain fund - fund.GetCommand(), + rootchainCmd.AddCommand( // rootchain server server.GetCommand(), - // init-contracts - initcontracts.GetCommand(), + // rootchain deploy + deploy.GetCommand(), + // rootchain fund + fund.GetCommand(), ) + + return rootchainCmd } diff --git a/consensus/polybft/README.md b/consensus/polybft/README.md index e18f0e263d..e1aa546aa0 100644 --- a/consensus/polybft/README.md +++ b/consensus/polybft/README.md @@ -3,88 +3,78 @@ Polybft is a consensus protocol, which runs [go-ibft](https://github.com/0xPolygon/go-ibft) consensus engine. -It has native support for running bridge, which enables running cross-chain transactions with Ethereum-compatible blockchains. +It has a native support for running bridge, which enables running cross-chain transactions with Ethereum-compatible blockchains. ## Setup local testing environment -### Precondition - 1. Build binary ```bash - go build -o polygon-edge . + $ go build -o polygon-edge . ``` 2. Init secrets - this command is used to generate account secrets (ECDSA, BLS as well as P2P networking node id). `--data-dir` denotes folder prefix names and `--num` how many accounts need to be created. **This command is for testing purposes only.** ```bash - polygon-edge polybft-secrets --data-dir test-chain- --num 4 + $ polygon-edge polybft-secrets --data-dir test-chain- --num 4 ``` -3. Start rootchain server - rootchain server is a Geth instance running in dev mode, which simulates Ethereum network. **This command is for testing purposes only.** +3. Create chain configuration - this command creates chain configuration, which is needed to run a blockchain. + It contains initial validator set as well and there are two ways to specify it: + + - all the validators information are present in local storage of single host and therefore directory if provided using `--validators-path` flag and validators folder prefix names using `--validators-prefix` flag ```bash - polygon-edge rootchain server + $ polygon-edge genesis --block-gas-limit 10000000 --epoch-size 10 \ + [--validators-path ./] [--validators-prefix test-chain-] \ + [--consensus polybft] ``` -4. Generate manifest file - manifest file contains public validator information as well as bridge configuration. It is intermediary file, which is later used for genesis specification generation as well as rootchain contracts deployment. - - There are two ways to provide validators information: - - - all the validators information are present in local storage of single host and therefore directory if provided using `--validators-path` flag and validators folder prefix names using `--validators-prefix` flag - - ```bash - polygon-edge manifest [--validators-path ./] [--validators-prefix test-chain-] - [--path ./manifest.json] [--premine-validators 100] - ``` - - - validators information are scafollded on multiple hosts and therefore necessary information are supplied using `--validators` flag. Validator information needs to be supplied in the strictly following format: - `:::`. + - validators information are scafollded on multiple hosts and therefore necessary information are supplied using `--validators` flag. Validator information needs to be supplied in the strictly following format: + `:::`. **Note:** when specifying validators via validators flag, entire multi address must be specified. - ```bash - polygon-edge manifest + ```bash + $ polygon-edge genesis --block-gas-limit 10000000 --epoch-size 10 \ --validators /ip4/127.0.0.1/tcp/30301/p2p/16Uiu2HAmV5hqAp77untfJRorxqKmyUxgaVn8YHFjBJm9gKMms3mr:0xDcBe0024206ec42b0Ef4214Ac7B71aeae1A11af0:1cf134e02c6b2afb2ceda50bf2c9a01da367ac48f7783ee6c55444e1cab418ec0f52837b90a4d8cf944814073fc6f2bd96f35366a3846a8393e3cb0b19197cde23e2b40c6401fa27ff7d0c36779d9d097d1393cab6fc1d332f92fb3df850b78703b2989d567d1344e219f0667a1863f52f7663092276770cf513f9704b5351c4:11b18bde524f4b02258a8d196b687f8d8e9490d536718666dc7babca14eccb631c238fb79aa2b44a5a4dceccad2dd797f537008dda185d952226a814c1acf7c2 [--validators /ip4/127.0.0.1/tcp/30302/p2p/16Uiu2HAmGmidRQY5BGJPGVRF8p1pYFdfzuf1StHzXGLDizuxJxex:0x2da750eD4AE1D5A7F7c996Faec592F3d44060e90:088d92c25b5f278750534e8a902da604a1aa39b524b4511f5f47c3a386374ca3031b667beb424faef068a01cee3428a1bc8c1c8bab826f30a1ee03fbe90cb5f01abcf4abd7af3bbe83eaed6f82179b9cbdc417aad65d919b802d91c2e1aaefec27ba747158bc18a0556e39bfc9175c099dd77517a85731894bbea3d191a622bc:08dc3006352fdc01b331907fd3a68d4d68ed40329032598c1c0faa260421d66720965ace3ba29c6d6608ec1facdbf4624bca72df36c34afd4bdd753c4dfe049c] - [--path ./manifest.json] [--premine-validators 100] - ``` + ``` -5. Deploy and initialize rootchain contracts - this command deploys rootchain smart contracts and initializes them. It also updates manifest configuration with rootchain contract addresses and rootchain default sender address. +4. Start rootchain server - rootchain server is a Geth instance running in dev mode, which simulates Ethereum network. **This command is for testing purposes only.** ```bash - polygon-edge rootchain init-contracts \ - --deployer-key \ - [--manifest ./manifest.json] \ - [--json-rpc http://127.0.0.1:8545] \ - [--test] + $ polygon-edge rootchain server ``` -6. Create chain configuration - this command creates chain configuration, which is needed to run a blockchain +5. Deploy and initialize rootchain contracts - this command deploys rootchain smart contracts and initializes them. It also updates genesis configuration with rootchain contract addresses and rootchain default sender address. ```bash - polygon-edge genesis --block-gas-limit 10000000 --epoch-size 10 \ - [--consensus polybft] [--bridge-json-rpc ] [--manifest ./manifest.json] + $ polygon-edge rootchain deploy \ + --deployer-key \ + [--genesis ./genesis.json] \ + [--json-rpc http://127.0.0.1:8545] \ + [--test] ``` -7. Fund validators on rootchain - in order for validators to be able to send transactions to Ethereum, they need to be funded in order to be able to cover gas cost. **This command is for testing purposes only.** +6. Fund validators on rootchain - in order for validators to be able to send transactions to Ethereum, they need to be funded in order to be able to cover gas cost. **This command is for testing purposes only.** ```bash - polygon-edge rootchain fund --data-dir test-chain- --num 4 + $ polygon-edge rootchain fund --data-dir test-chain- --num 4 ``` -8. Run (child chain) cluster, consisting of 4 Edge clients in this particular example +7. Run (child chain) cluster, consisting of 4 Edge clients in this particular example ```bash - polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :9545 \ + $ polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :9545 \ --seal --log-level DEBUG - polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :5002 --libp2p :30302 --jsonrpc :10002 \ + $ polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :5002 --libp2p :30302 --jsonrpc :10002 \ --seal --log-level DEBUG - polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :5003 --libp2p :30303 --jsonrpc :10003 \ + $ polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :5003 --libp2p :30303 --jsonrpc :10003 \ --seal --log-level DEBUG - polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :5004 --libp2p :30304 --jsonrpc :10004 \ + $ polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :5004 --libp2p :30304 --jsonrpc :10004 \ --seal --log-level DEBUG ``` @@ -92,6 +82,6 @@ It has native support for running bridge, which enables running cross-chain tran In order to start node in relayer mode, it is necessary to supply `--relayer` flag: ```bash - polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :9545 \ + $ polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :9545 \ --seal --log-level DEBUG --relayer ``` diff --git a/consensus/polybft/consensus_runtime.go b/consensus/polybft/consensus_runtime.go index 682ad6771e..b1a30cb70b 100644 --- a/consensus/polybft/consensus_runtime.go +++ b/consensus/polybft/consensus_runtime.go @@ -157,7 +157,7 @@ func (c *consensusRuntime) close() { // if bridge is not enabled, then a dummy state sync manager will be used func (c *consensusRuntime) initStateSyncManager(logger hcf.Logger) error { if c.IsBridgeEnabled() { - stateSenderAddr := c.config.PolyBFTConfig.Bridge.BridgeAddr + stateSenderAddr := c.config.PolyBFTConfig.Bridge.StateSenderAddr stateSyncManager, err := newStateSyncManager( logger.Named("state-sync-manager"), c.config.State, @@ -198,7 +198,7 @@ func (c *consensusRuntime) initCheckpointManager(logger hcf.Logger) error { c.checkpointManager = newCheckpointManager( wallet.NewEcdsaSigner(c.config.Key), defaultCheckpointsOffset, - c.config.PolyBFTConfig.Bridge.CheckpointAddr, + c.config.PolyBFTConfig.Bridge.CheckpointManagerAddr, txRelayer, c.config.blockchain, c.config.polybftBackend, diff --git a/consensus/polybft/consensus_runtime_test.go b/consensus/polybft/consensus_runtime_test.go index 1bbed2a081..99db59c789 100644 --- a/consensus/polybft/consensus_runtime_test.go +++ b/consensus/polybft/consensus_runtime_test.go @@ -442,9 +442,9 @@ func Test_NewConsensusRuntime(t *testing.T) { polyBftConfig := &PolyBFTConfig{ Bridge: &BridgeConfig{ - BridgeAddr: types.Address{0x13}, - CheckpointAddr: types.Address{0x10}, - JSONRPCEndpoint: "testEndpoint", + StateSenderAddr: types.Address{0x13}, + CheckpointManagerAddr: types.Address{0x10}, + JSONRPCEndpoint: "testEndpoint", }, EpochSize: 10, SprintSize: 10, @@ -484,8 +484,8 @@ func Test_NewConsensusRuntime(t *testing.T) { assert.Equal(t, uint64(10), runtime.config.PolyBFTConfig.SprintSize) assert.Equal(t, uint64(10), runtime.config.PolyBFTConfig.EpochSize) assert.Equal(t, "0x0000000000000000000000000000000000000101", contracts.ValidatorSetContract.String()) - assert.Equal(t, "0x1300000000000000000000000000000000000000", runtime.config.PolyBFTConfig.Bridge.BridgeAddr.String()) - assert.Equal(t, "0x1000000000000000000000000000000000000000", runtime.config.PolyBFTConfig.Bridge.CheckpointAddr.String()) + assert.Equal(t, "0x1300000000000000000000000000000000000000", runtime.config.PolyBFTConfig.Bridge.StateSenderAddr.String()) + assert.Equal(t, "0x1000000000000000000000000000000000000000", runtime.config.PolyBFTConfig.Bridge.CheckpointManagerAddr.String()) assert.True(t, runtime.IsBridgeEnabled()) systemStateMock.AssertExpectations(t) blockchainMock.AssertExpectations(t) diff --git a/consensus/polybft/extra_test.go b/consensus/polybft/extra_test.go index 585210db82..d478209160 100644 --- a/consensus/polybft/extra_test.go +++ b/consensus/polybft/extra_test.go @@ -673,7 +673,7 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { genesis := &chain.Genesis{ Config: &chain.Params{Engine: map[string]interface{}{ - "polybft": polyBftConfig, + ConsensusName: polyBftConfig, }}, ExtraData: extra.MarshalRLPTo(nil), } @@ -692,7 +692,7 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { genesis := &chain.Genesis{ Config: &chain.Params{Engine: map[string]interface{}{ - "polybft": polyBftConfig, + ConsensusName: polyBftConfig, }}, ExtraData: append(make([]byte, ExtraVanity), []byte{0x2, 0x3}...), } diff --git a/consensus/polybft/polybft_config.go b/consensus/polybft/polybft_config.go index 59917fbd89..b01cb9c3b7 100644 --- a/consensus/polybft/polybft_config.go +++ b/consensus/polybft/polybft_config.go @@ -5,8 +5,6 @@ import ( "encoding/json" "fmt" "math/big" - "os" - "path/filepath" "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" @@ -15,6 +13,8 @@ import ( "github.com/0xPolygon/polygon-edge/types" ) +const ConsensusName = "polybft" + // PolyBFTConfig is the configuration file for the Polybft consensus protocol. type PolyBFTConfig struct { // InitialValidatorSet are the genesis validators @@ -47,29 +47,41 @@ type PolyBFTConfig struct { InitialTrieRoot types.Hash `json:"initialTrieRoot"` } +// LoadPolyBFTConfig loads chain config from provided path and unmarshals PolyBFTConfig +func LoadPolyBFTConfig(chainConfigFile string) (PolyBFTConfig, error) { + chainCfg, err := chain.ImportFromFile(chainConfigFile) + if err != nil { + return PolyBFTConfig{}, err + } + + return GetPolyBFTConfig(chainCfg) +} + // GetPolyBFTConfig deserializes provided chain config and returns PolyBFTConfig func GetPolyBFTConfig(chainConfig *chain.Chain) (PolyBFTConfig, error) { - consensusConfigJSON, err := json.Marshal(chainConfig.Params.Engine["polybft"]) + consensusConfigJSON, err := json.Marshal(chainConfig.Params.Engine[ConsensusName]) if err != nil { return PolyBFTConfig{}, err } var polyBFTConfig PolyBFTConfig - err = json.Unmarshal(consensusConfigJSON, &polyBFTConfig) - - if err != nil { + if err = json.Unmarshal(consensusConfigJSON, &polyBFTConfig); err != nil { return PolyBFTConfig{}, err } return polyBFTConfig, nil } -// BridgeConfig is the rootchain bridge configuration +// BridgeConfig is the rootchain configuration, needed for bridging type BridgeConfig struct { - BridgeAddr types.Address `json:"stateSenderAddr"` - CheckpointAddr types.Address `json:"checkpointAddr"` - RootERC20PredicateAddr types.Address `json:"rootERC20PredicateAddr"` - RootNativeERC20Addr types.Address `json:"rootNativeERC20Addr"` + StateSenderAddr types.Address `json:"stateSenderAddress"` + CheckpointManagerAddr types.Address `json:"checkpointManagerAddress"` + ExitHelperAddr types.Address `json:"exitHelperAddress"` + RootERC20PredicateAddr types.Address `json:"erc20PredicateAddress"` + RootNativeERC20Addr types.Address `json:"nativeERC20Address"` + RootERC721PredicateAddr types.Address `json:"erc721PredicateAddress"` + RootERC1155PredicateAddr types.Address `json:"erc1155PredicateAddress"` + JSONRPCEndpoint string `json:"jsonRPCEndpoint"` EventTrackerStartBlocks map[types.Address]uint64 `json:"eventTrackerStartBlocks"` } @@ -202,68 +214,37 @@ func (v *Validator) String() string { v.Address, v.Balance, v.MultiAddr, v.BlsKey) } -// RootchainConfig contains information about rootchain contract addresses -// as well as rootchain admin account address +// RootchainConfig contains rootchain metadata (such as JSON RPC endpoint and contract addresses) type RootchainConfig struct { - StateSenderAddress types.Address `json:"stateSenderAddress"` - CheckpointManagerAddress types.Address `json:"checkpointManagerAddress"` - BLSAddress types.Address `json:"blsAddress"` - BN256G2Address types.Address `json:"bn256G2Address"` - ExitHelperAddress types.Address `json:"exitHelperAddress"` - RootERC20PredicateAddress types.Address `json:"erc20PredicateAddress"` - RootNativeERC20Address types.Address `json:"nativeERC20Address"` - ERC20TemplateAddress types.Address `json:"erc20TemplateAddress"` - RootERC721PredicateAddress types.Address `json:"erc721PredicateAddress"` - RootERC721Address types.Address `json:"erc721Address"` - RootERC1155PredicateAddress types.Address `json:"erc1155PredicateAddress"` - RootERC1155Address types.Address `json:"erc1155Address"` + JSONRPCAddr string + + StateSenderAddress types.Address + CheckpointManagerAddress types.Address + BLSAddress types.Address + BN256G2Address types.Address + ExitHelperAddress types.Address + RootERC20PredicateAddress types.Address + RootNativeERC20Address types.Address + ERC20TemplateAddress types.Address + RootERC721PredicateAddress types.Address + RootERC721Address types.Address + RootERC1155PredicateAddress types.Address + RootERC1155Address types.Address } // ToBridgeConfig creates BridgeConfig instance func (r *RootchainConfig) ToBridgeConfig() *BridgeConfig { return &BridgeConfig{ - BridgeAddr: r.StateSenderAddress, - CheckpointAddr: r.CheckpointManagerAddress, - RootERC20PredicateAddr: r.RootERC20PredicateAddress, - RootNativeERC20Addr: r.RootNativeERC20Address, - } -} + JSONRPCEndpoint: r.JSONRPCAddr, -// Manifest holds metadata, such as genesis validators and rootchain configuration -type Manifest struct { - GenesisValidators []*Validator `json:"validators"` - RootchainConfig *RootchainConfig `json:"rootchain"` - ChainID int64 `json:"chainID"` -} - -// LoadManifest deserializes Manifest instance -func LoadManifest(metadataFile string) (*Manifest, error) { - data, err := os.ReadFile(metadataFile) - if err != nil { - return nil, err - } - - var manifest Manifest - - if err := json.Unmarshal(data, &manifest); err != nil { - return nil, err - } - - return &manifest, nil -} - -// Save marshals RootchainManifest instance to json and persists it to given location -func (m *Manifest) Save(manifestPath string) error { - data, err := json.MarshalIndent(m, "", " ") - if err != nil { - return fmt.Errorf("failed to marshal rootchain manifest to JSON: %w", err) + StateSenderAddr: r.StateSenderAddress, + CheckpointManagerAddr: r.CheckpointManagerAddress, + ExitHelperAddr: r.ExitHelperAddress, + RootERC20PredicateAddr: r.RootERC20PredicateAddress, + RootNativeERC20Addr: r.RootNativeERC20Address, + RootERC721PredicateAddr: r.RootERC721PredicateAddress, + RootERC1155PredicateAddr: r.RootERC1155PredicateAddress, } - - if err := common.SaveFileSafe(filepath.Clean(manifestPath), data, 0660); err != nil { - return fmt.Errorf("failed to save rootchain manifest file: %w", err) - } - - return nil } // TokenConfig is the configuration of native token used by edge network diff --git a/docker/local/polygon-edge.sh b/docker/local/polygon-edge.sh index cbb813c501..687850aaa7 100755 --- a/docker/local/polygon-edge.sh +++ b/docker/local/polygon-edge.sh @@ -29,7 +29,6 @@ case "$1" in --dir genesis.json \ --consensus ibft \ --ibft-validators-prefix-path data- \ - --validator-set-size=4 \ --bootnode "/dns4/node-1/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[0] | .node_id')" \ --bootnode "/dns4/node-2/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[1] | .node_id')" fi @@ -39,15 +38,12 @@ case "$1" in secrets=$("$POLYGON_EDGE_BIN" polybft-secrets init --insecure --num 4 --data-dir /data/data- --json) echo "Secrets have been successfully generated" - echo "Generating manifest..." - "$POLYGON_EDGE_BIN" manifest --path /data/manifest.json --validators-path /data --validators-prefix data- - echo "Generating PolyBFT Genesis file..." "$POLYGON_EDGE_BIN" genesis $CHAIN_CUSTOM_OPTIONS \ --dir /data/genesis.json \ --consensus polybft \ - --manifest /data/manifest.json \ - --validator-set-size=4 \ + --validators-path /data \ + --validators-prefix data- \ --bootnode "/dns4/node-1/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[0] | .node_id')" \ --bootnode "/dns4/node-2/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[1] | .node_id')" ;; diff --git a/e2e-polybft/e2e/bridge_test.go b/e2e-polybft/e2e/bridge_test.go index 3ae3ab008b..0dde0408d6 100644 --- a/e2e-polybft/e2e/bridge_test.go +++ b/e2e-polybft/e2e/bridge_test.go @@ -25,7 +25,7 @@ import ( ) const ( - manifestFileName = "manifest.json" + chainConfigFileName = "genesis.json" ) func TestE2E_Bridge_Transfers(t *testing.T) { @@ -59,7 +59,7 @@ func TestE2E_Bridge_Transfers(t *testing.T) { cluster.WaitForReady(t) - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) validatorSrv := cluster.Servers[0] @@ -71,8 +71,8 @@ func TestE2E_Bridge_Transfers(t *testing.T) { require.NoError( t, cluster.Bridge.DepositERC20( - manifest.RootchainConfig.RootNativeERC20Address, - manifest.RootchainConfig.RootERC20PredicateAddress, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, strings.Join(receivers[:], ","), strings.Join(amounts[:], ","), ), @@ -141,9 +141,9 @@ func TestE2E_Bridge_Transfers(t *testing.T) { currentEpoch := currentExtra.Checkpoint.EpochNumber require.NoError(t, waitForRootchainEpoch(currentEpoch, 3*time.Minute, - rootchainTxRelayer, manifest.RootchainConfig.CheckpointManagerAddress)) + rootchainTxRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) - exitHelper := manifest.RootchainConfig.ExitHelperAddress + exitHelper := polybftCfg.Bridge.ExitHelperAddr rootJSONRPC := cluster.Bridge.JSONRPCAddr() childJSONRPC := validatorSrv.JSONRPCAddr() @@ -167,7 +167,7 @@ func TestE2E_Bridge_Transfers(t *testing.T) { require.NoError(t, err) balanceRaw, err := rootchainTxRelayer.Call(ethgo.ZeroAddress, - ethgo.Address(manifest.RootchainConfig.RootNativeERC20Address), balanceInput) + ethgo.Address(polybftCfg.Bridge.RootNativeERC20Addr), balanceInput) require.NoError(t, err) balance, err := types.ParseUint256orHex(&balanceRaw) @@ -193,8 +193,8 @@ func TestE2E_Bridge_Transfers(t *testing.T) { require.NoError( t, cluster.Bridge.DepositERC20( - manifest.RootchainConfig.RootNativeERC20Address, - manifest.RootchainConfig.RootERC20PredicateAddress, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, strings.Join(receivers[:depositsSubset], ","), strings.Join(amounts[:depositsSubset], ","), ), @@ -223,8 +223,8 @@ func TestE2E_Bridge_Transfers(t *testing.T) { require.NoError( t, cluster.Bridge.DepositERC20( - manifest.RootchainConfig.RootNativeERC20Address, - manifest.RootchainConfig.RootERC20PredicateAddress, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, strings.Join(receivers[depositsSubset:], ","), strings.Join(amounts[depositsSubset:], ","), ), @@ -274,10 +274,10 @@ func TestE2E_CheckpointSubmission(t *testing.T) { l1Relayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) - checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) + checkpointManagerAddr := ethgo.Address(polybftCfg.Bridge.CheckpointManagerAddr) testCheckpointBlockNumber := func(expectedCheckpointBlock uint64) (bool, error) { actualCheckpointBlock, err := getCheckpointBlockNumber(l1Relayer, checkpointManagerAddr) @@ -328,11 +328,11 @@ func TestE2E_Bridge_ChangeVotingPower(t *testing.T) { framework.WithEpochReward(1000)) defer cluster.Stop() - // load manifest file - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) + // load polybftCfg file + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) - checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) + checkpointManagerAddr := ethgo.Address(polybftCfg.Bridge.CheckpointManagerAddr) validatorSecretFiles, err := genesis.GetValidatorKeyFiles(cluster.Config.TmpDir, cluster.Config.ValidatorPrefix) require.NoError(t, err) diff --git a/e2e-polybft/e2e/consensus_test.go b/e2e-polybft/e2e/consensus_test.go index 0196b6033a..3ac51e5fd7 100644 --- a/e2e-polybft/e2e/consensus_test.go +++ b/e2e-polybft/e2e/consensus_test.go @@ -123,7 +123,7 @@ func TestE2E_Consensus_RegisterValidator(t *testing.T) { framework.WithEpochReward(epochReward), framework.WithSecretsCallback(func(addresses []types.Address, config *framework.TestClusterConfig) { for _, a := range addresses { - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%s", a, premineBalance)) + config.Premine = append(config.Premine, fmt.Sprintf("%s:%s", a, premineBalance)) } }), ) @@ -333,7 +333,7 @@ func TestE2E_Consensus_Delegation_Undelegation(t *testing.T) { framework.WithEpochSize(epochSize), framework.WithSecretsCallback(func(addresses []types.Address, config *framework.TestClusterConfig) { for _, a := range addresses { - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%s", a, premineBalance)) + config.Premine = append(config.Premine, fmt.Sprintf("%s:%s", a, premineBalance)) config.StakeAmounts = append(config.StakeAmounts, fmt.Sprintf("%s:%s", a, premineBalance)) } }), @@ -444,7 +444,7 @@ func TestE2E_Consensus_Validator_Unstake(t *testing.T) { framework.WithEpochSize(5), framework.WithSecretsCallback(func(addresses []types.Address, config *framework.TestClusterConfig) { for _, a := range addresses { - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%d", a, premineAmount)) + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", a, premineAmount)) config.StakeAmounts = append(config.StakeAmounts, fmt.Sprintf("%s:%d", a, premineAmount)) } }), @@ -509,10 +509,10 @@ func TestE2E_Consensus_Validator_Unstake(t *testing.T) { l1Relayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) - checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) + checkpointManagerAddr := ethgo.Address(polybftCfg.Bridge.CheckpointManagerAddr) // query rootchain validator set and make sure that validator which unstaked all the funds isn't present in validator set anymore // (execute it multiple times if needed, because it is unknown in advance how much time it is going to take until checkpoint is submitted) @@ -653,8 +653,8 @@ func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) { // (it is going to send mint transactions to all the other validators) if i > 0 { // premine other validators with as minimum stake as possible just to ensure liveness of consensus protocol + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", addr, initialBalance)) config.StakeAmounts = append(config.StakeAmounts, fmt.Sprintf("%s:%d", addr, initialStake)) - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%d", addr, initialBalance)) } validatorsAddrs[i] = addr } diff --git a/e2e-polybft/framework/test-bridge.go b/e2e-polybft/framework/test-bridge.go index 162b704dc3..78ed7c836c 100644 --- a/e2e-polybft/framework/test-bridge.go +++ b/e2e-polybft/framework/test-bridge.go @@ -170,11 +170,11 @@ func (t *TestBridge) cmdRun(args ...string) error { } // deployRootchainContracts deploys and initializes rootchain contracts -func (t *TestBridge) deployRootchainContracts(manifestPath string) error { +func (t *TestBridge) deployRootchainContracts(genesisPath string) error { args := []string{ "rootchain", - "init-contracts", - "--manifest", manifestPath, + "deploy", + "--genesis", genesisPath, "--test", } @@ -195,7 +195,7 @@ func (t *TestBridge) fundRootchainValidators() error { } if err := t.cmdRun(args...); err != nil { - return fmt.Errorf("failed to deploy fund validators: %w", err) + return fmt.Errorf("failed to fund validators on the rootchain: %w", err) } return nil diff --git a/e2e-polybft/framework/test-cluster.go b/e2e-polybft/framework/test-cluster.go index fe6537a7b6..53ecd172b0 100644 --- a/e2e-polybft/framework/test-cluster.go +++ b/e2e-polybft/framework/test-cluster.go @@ -19,7 +19,6 @@ import ( "time" "github.com/0xPolygon/polygon-edge/command/genesis" - "github.com/0xPolygon/polygon-edge/command/rootchain/helper" "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" @@ -307,15 +306,14 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T var err error config := &TestClusterConfig{ - t: t, - WithLogs: isTrueEnv(envLogsEnabled), - WithStdout: isTrueEnv(envStdoutEnabled), - Binary: resolveBinary(), - EpochSize: 10, - EpochReward: 1, - BlockGasLimit: 1e7, // 10M - PremineValidators: []string{}, - StakeAmounts: []string{}, + t: t, + WithLogs: isTrueEnv(envLogsEnabled), + WithStdout: isTrueEnv(envStdoutEnabled), + Binary: resolveBinary(), + EpochSize: 10, + EpochReward: 1, + BlockGasLimit: 1e7, // 10M + StakeAmounts: []string{}, } if config.ValidatorPrefix == "" { @@ -372,47 +370,15 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T } } - manifestPath := path.Join(config.TmpDir, "manifest.json") - args := []string{ - "manifest", - "--path", manifestPath, - "--validators-path", config.TmpDir, - "--validators-prefix", cluster.Config.ValidatorPrefix, - } - - // premine validators - for _, premineValidator := range cluster.Config.PremineValidators { - args = append(args, "--premine-validators", premineValidator) - } - - for _, validatorStake := range cluster.Config.StakeAmounts { - args = append(args, "--stake", validatorStake) - } - - // run manifest file creation - require.NoError(t, cluster.cmdRun(args...)) - - if cluster.Config.HasBridge { - // start bridge - cluster.Bridge, err = NewTestBridge(t, cluster.Config) - require.NoError(t, err) - } - - if cluster.Config.HasBridge { - err := cluster.Bridge.deployRootchainContracts(manifestPath) - require.NoError(t, err) - - err = cluster.Bridge.fundRootchainValidators() - require.NoError(t, err) - } + genesisPath := path.Join(config.TmpDir, "genesis.json") { // run genesis configuration population args := []string{ "genesis", - "--manifest", manifestPath, - "--consensus", "polybft", - "--dir", path.Join(config.TmpDir, "genesis.json"), + "--validators-path", config.TmpDir, + "--validators-prefix", cluster.Config.ValidatorPrefix, + "--dir", genesisPath, "--block-gas-limit", strconv.FormatUint(cluster.Config.BlockGasLimit, 10), "--epoch-size", strconv.Itoa(cluster.Config.EpochSize), "--epoch-reward", strconv.Itoa(cluster.Config.EpochReward), @@ -435,12 +401,6 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T args = append(args, "--mintable-native-token") } - if cluster.Config.HasBridge { - rootchainIP, err := helper.ReadRootchainIP() - require.NoError(t, err) - args = append(args, "--bridge-json-rpc", rootchainIP) - } - validators, err := genesis.ReadValidatorsByPrefix( cluster.Config.TmpDir, cluster.Config.ValidatorPrefix) require.NoError(t, err) @@ -456,6 +416,11 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T } } + // provide validators' stakes + for _, validatorStake := range cluster.Config.StakeAmounts { + args = append(args, "--stake", validatorStake) + } + if len(cluster.Config.ContractDeployerAllowListAdmin) != 0 { args = append(args, "--contract-deployer-allow-list-admin", strings.Join(sliceAddressToSliceString(cluster.Config.ContractDeployerAllowListAdmin), ",")) @@ -476,11 +441,25 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T strings.Join(sliceAddressToSliceString(cluster.Config.TransactionsAllowListEnabled), ",")) } - // run cmd init-genesis with all the arguments + // run genesis command with all the arguments err = cluster.cmdRun(args...) require.NoError(t, err) } + if cluster.Config.HasBridge { + // start bridge + cluster.Bridge, err = NewTestBridge(t, cluster.Config) + require.NoError(t, err) + + // deploy rootchain contracts + err := cluster.Bridge.deployRootchainContracts(genesisPath) + require.NoError(t, err) + + // fund validators on the rootchain + err = cluster.Bridge.fundRootchainValidators() + require.NoError(t, err) + } + for i := 1; i <= int(cluster.Config.ValidatorSetSize); i++ { dir := cluster.Config.ValidatorPrefix + strconv.Itoa(i) cluster.InitTestServer(t, dir, true, cluster.Config.HasBridge && i == 1 /* relayer */) diff --git a/e2e-polybft/property/property_test.go b/e2e-polybft/property/property_test.go index 25f7511481..46b95a379e 100644 --- a/e2e-polybft/property/property_test.go +++ b/e2e-polybft/property/property_test.go @@ -39,7 +39,7 @@ func TestProperty_DifferentVotingPower(t *testing.T) { framework.WithEpochSize(epochSize), framework.WithSecretsCallback(func(adresses []types.Address, config *framework.TestClusterConfig) { for i, a := range adresses { - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%d", a, premine[i])) + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", a, premine[i])) } })) defer cluster.Stop() diff --git a/scripts/cluster b/scripts/cluster index de26e41cfa..1305666f2b 100755 --- a/scripts/cluster +++ b/scripts/cluster @@ -14,9 +14,8 @@ function initIbftConsensus() { function initPolybftConsensus() { echo "Running with polybft consensus" - genesis_params="--consensus polybft --bridge-json-rpc http://127.0.0.1:8545" + genesis_params="--consensus polybft" ./polygon-edge polybft-secrets --insecure --data-dir test-chain- --num 4 - ./polygon-edge manifest } function createGenesis() { @@ -85,7 +84,6 @@ set -e # Reset test-dirs rm -rf test-chain-* rm -f genesis.json -rm -f manifest.json # Build binary go build -o polygon-edge . diff --git a/server/builtin.go b/server/builtin.go index 8aa7a49c80..435bb1a282 100644 --- a/server/builtin.go +++ b/server/builtin.go @@ -22,7 +22,7 @@ type ConsensusType string const ( DevConsensus ConsensusType = "dev" IBFTConsensus ConsensusType = "ibft" - PolyBFTConsensus ConsensusType = "polybft" + PolyBFTConsensus ConsensusType = consensusPolyBFT.ConsensusName DummyConsensus ConsensusType = "dummy" )