diff --git a/.gitignore b/.gitignore
index ae1daec466..56d22509a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
peers.json
genesis.json
+manifest.json
secretsManagerConfig.json
*-packr.go
config*.json
diff --git a/command/genesis/genesis.go b/command/genesis/genesis.go
index 28d7ded4e4..6816466303 100644
--- a/command/genesis/genesis.go
+++ b/command/genesis/genesis.go
@@ -150,56 +150,49 @@ func setFlags(cmd *cobra.Command) {
// PolyBFT
{
+ cmd.Flags().StringVar(
+ ¶ms.manifestPath,
+ manifestPathFlag,
+ defaultManifestPath,
+ "the manifest file path, which contains genesis metadata",
+ )
+
cmd.Flags().IntVar(
¶ms.validatorSetSize,
validatorSetSizeFlag,
defaultValidatorSetSize,
"the total number of validators",
)
- cmd.Flags().StringVar(
- ¶ms.polyBftValidatorPrefixPath,
- polyBftValidatorPrefixPathFlag,
- defaultPolyBftValidatorPrefixPath,
- "prefix path for polybft validator folder directory",
- )
+
cmd.Flags().Uint64Var(
¶ms.sprintSize,
sprintSizeFlag,
defaultSprintSize,
"the number of block included into a sprint",
)
+
cmd.Flags().DurationVar(
¶ms.blockTime,
blockTimeFlag,
defaultBlockTime,
"the predefined period which determines block creation frequency",
)
- cmd.Flags().StringArrayVar(
- ¶ms.validators,
- validatorsFlag,
- []string{},
- "validators defined by user throughout a parameter (format:
:)",
- )
- cmd.Flags().StringVar(
- ¶ms.premineValidators,
- premineValidatorsFlag,
- command.DefaultPremineBalance,
- "the amount which will be premined to all the validators",
- )
+
cmd.Flags().StringVar(
¶ms.smartContractsRootPath,
smartContractsRootPathFlag,
contracts.ContractsRootFolder,
"the smart contracts folder",
)
+
cmd.Flags().StringVar(
¶ms.bridgeJSONRPCAddr,
bridgeFlag,
"",
"the rootchain JSON RPC IP address. If present, node is running in bridge mode.",
)
+
cmd.Flags().Lookup(bridgeFlag).NoOptDefVal = "http://127.0.0.1:8545"
- cmd.MarkFlagsMutuallyExclusive(validatorsFlag, premineValidatorsFlag)
}
}
@@ -234,7 +227,7 @@ func runCommand(cmd *cobra.Command, _ []string) {
var err error
if params.isPolyBFTConsensus() {
- err = params.generatePolyBftGenesis()
+ err = params.generatePolyBftChainConfig()
} else {
err = params.generateGenesis()
}
diff --git a/command/genesis/params.go b/command/genesis/params.go
index f0c08aebfc..281683491e 100644
--- a/command/genesis/params.go
+++ b/command/genesis/params.go
@@ -75,15 +75,12 @@ type genesisParams struct {
genesisConfig *chain.Chain
// PolyBFT
- validatorSetSize int
- sprintSize uint64
- blockTime time.Duration
- validators []string
-
- polyBftValidatorPrefixPath string
- premineValidators string
- smartContractsRootPath string
- bridgeJSONRPCAddr string
+ manifestPath string
+ smartContractsRootPath string
+ validatorSetSize int
+ sprintSize uint64
+ blockTime time.Duration
+ bridgeJSONRPCAddr string
}
func (p *genesisParams) validateFlags() error {
@@ -336,19 +333,17 @@ func (p *genesisParams) initGenesisConfig() error {
chainConfig.Genesis.Alloc[staking.AddrStakingContract] = stakingAccount
}
- premineInfos := make([]*premineInfo, len(p.premine))
-
- for i, premineRaw := range p.premine {
+ for _, premineRaw := range p.premine {
premineInfo, err := parsePremineInfo(premineRaw)
if err != nil {
return err
}
- premineInfos[i] = premineInfo
+ chainConfig.Genesis.Alloc[premineInfo.address] = &chain.GenesisAccount{
+ Balance: premineInfo.balance,
+ }
}
- fillPremineMap(chainConfig.Genesis.Alloc, premineInfos)
-
p.genesisConfig = chainConfig
return nil
diff --git a/command/genesis/polybft_params.go b/command/genesis/polybft_params.go
index 266b8fbfd2..f9a2033253 100644
--- a/command/genesis/polybft_params.go
+++ b/command/genesis/polybft_params.go
@@ -5,9 +5,7 @@ import (
"errors"
"fmt"
"math/big"
- "path"
"sort"
- "strings"
"time"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact"
@@ -16,7 +14,6 @@ import (
"github.com/0xPolygon/polygon-edge/command"
"github.com/0xPolygon/polygon-edge/command/helper"
- rootchain "github.com/0xPolygon/polygon-edge/command/rootchain/helper"
"github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap"
"github.com/0xPolygon/polygon-edge/contracts"
@@ -25,22 +22,19 @@ import (
)
const (
- premineValidatorsFlag = "premine-validators"
- polyBftValidatorPrefixPathFlag = "validator-prefix"
- smartContractsRootPathFlag = "contracts-path"
-
- validatorSetSizeFlag = "validator-set-size"
- sprintSizeFlag = "sprint-size"
- blockTimeFlag = "block-time"
- validatorsFlag = "polybft-validators"
- bridgeFlag = "bridge-json-rpc"
-
- defaultEpochSize = uint64(10)
- defaultSprintSize = uint64(5)
- defaultValidatorSetSize = 100
- defaultBlockTime = 2 * time.Second
- defaultPolyBftValidatorPrefixPath = "test-chain-"
- defaultBridge = false
+ smartContractsRootPathFlag = "contracts-path"
+ manifestPathFlag = "manifest"
+ validatorSetSizeFlag = "validator-set-size"
+ sprintSizeFlag = "sprint-size"
+ blockTimeFlag = "block-time"
+ bridgeFlag = "bridge-json-rpc"
+
+ defaultManifestPath = "./manifest.json"
+ defaultEpochSize = uint64(10)
+ defaultSprintSize = uint64(5)
+ defaultValidatorSetSize = 100
+ defaultBlockTime = 2 * time.Second
+ defaultBridge = false
bootnodePortStart = 30301
)
@@ -49,115 +43,116 @@ var (
errNoGenesisValidators = errors.New("genesis validators aren't provided")
)
-func (p *genesisParams) generatePolyBFTConfig() (*chain.Chain, error) {
- // set initial validator set
- genesisValidators, err := p.getGenesisValidators()
+// generatePolyBftChainConfig creates and persists polybft chain configuration to the provided file path
+func (p *genesisParams) generatePolyBftChainConfig() error {
+ // load manifest file
+ manifest, err := polybft.LoadManifest(p.manifestPath)
if err != nil {
- return nil, err
+ return fmt.Errorf("failed to load manifest file from provided path '%s': %w", p.manifestPath, err)
}
- if len(genesisValidators) == 0 {
- return nil, errNoGenesisValidators
+ if len(manifest.GenesisValidators) == 0 {
+ return errNoGenesisValidators
+ }
+
+ var bridge *polybft.BridgeConfig
+
+ // populate bridge configuration
+ if p.bridgeJSONRPCAddr != "" && manifest.RootchainConfig != nil {
+ bridge = manifest.RootchainConfig.ToBridgeConfig()
+ bridge.JSONRPCEndpoint = p.bridgeJSONRPCAddr
+ }
+
+ polyBftConfig := &polybft.PolyBFTConfig{
+ InitialValidatorSet: manifest.GenesisValidators,
+ BlockTime: p.blockTime,
+ EpochSize: p.epochSize,
+ SprintSize: p.sprintSize,
+ // use 1st account as governance address
+ Governance: manifest.GenesisValidators[0].Address,
+ Bridge: bridge,
+ ValidatorSetAddr: contracts.ValidatorSetContract,
+ StateReceiverAddr: contracts.StateReceiverContract,
+ }
+
+ chainConfig := &chain.Chain{
+ Name: p.name,
+ Params: &chain.Params{
+ ChainID: int(p.chainID),
+ Forks: chain.AllForksEnabled,
+ Engine: map[string]interface{}{
+ string(server.PolyBFTConsensus): polyBftConfig,
+ },
+ },
+ Bootnodes: p.bootnodes,
}
// deploy genesis contracts
allocs, err := p.deployContracts()
if err != nil {
- return nil, err
+ return err
}
- // premine accounts with some tokens
- var (
- validatorPreminesMap map[types.Address]int
- premineInfos []*premineInfo
- )
-
- if p.premineValidators != "" {
- validatorPreminesMap = make(map[types.Address]int, len(genesisValidators))
+ premineInfos := make([]*premineInfo, len(manifest.GenesisValidators))
+ validatorPreminesMap := make(map[types.Address]int, len(manifest.GenesisValidators))
- for i, vi := range genesisValidators {
- premineInfo, err := parsePremineInfo(fmt.Sprintf("%s:%s", vi.Address, p.premineValidators))
- if err != nil {
- return nil, err
- }
-
- premineInfos = append(premineInfos, premineInfo)
- validatorPreminesMap[premineInfo.address] = i
- }
+ // populate premine info for validator accounts
+ for i, validator := range manifest.GenesisValidators {
+ premineInfo := &premineInfo{address: validator.Address, balance: validator.Balance}
+ premineInfos[i] = premineInfo
+ validatorPreminesMap[premineInfo.address] = i
}
+ // either premine non-validator or override validator accounts balance
for _, premine := range p.premine {
premineInfo, err := parsePremineInfo(premine)
if err != nil {
- return nil, err
+ return err
}
if i, ok := validatorPreminesMap[premineInfo.address]; ok {
premineInfos[i] = premineInfo
} else {
- premineInfos = append(premineInfos, premineInfo)
+ premineInfos = append(premineInfos, premineInfo) //nolint:makezero
}
}
// premine accounts
- fillPremineMap(allocs, premineInfos)
+ for _, premine := range premineInfos {
+ allocs[premine.address] = &chain.GenesisAccount{
+ Balance: premine.balance,
+ }
+ }
+
+ validatorMetadata := make([]*polybft.ValidatorMetadata, len(manifest.GenesisValidators))
- // populate genesis validators balances
- for _, validator := range 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 nil, err
+ return err
}
validator.Balance = balance
- }
- polyBftConfig := &polybft.PolyBFTConfig{
- BlockTime: p.blockTime,
- EpochSize: p.epochSize,
- SprintSize: p.sprintSize,
- ValidatorSetSize: p.validatorSetSize,
- ValidatorSetAddr: contracts.ValidatorSetContract,
- StateReceiverAddr: contracts.StateReceiverContract,
- // use 1st account as governance address
- Governance: genesisValidators[0].Address,
- }
-
- // populate bridge configuration
- if p.bridgeJSONRPCAddr != "" {
- polyBftConfig.Bridge = &polybft.BridgeConfig{
- // TODO: Figure out population of rootchain contracts and whether those should be part of genesis configuration
- BridgeAddr: rootchain.StateSenderAddress,
- CheckpointAddr: rootchain.CheckpointManagerAddress,
- JSONRPCEndpoint: p.bridgeJSONRPCAddr,
+ // create validator metadata instance
+ metadata, err := validator.ToValidatorMetadata()
+ if err != nil {
+ return err
}
- }
- chainConfig := &chain.Chain{
- Name: p.name,
- Params: &chain.Params{
- ChainID: int(p.chainID),
- Forks: chain.AllForksEnabled,
- Engine: map[string]interface{}{
- string(server.PolyBFTConsensus): polyBftConfig,
- },
- },
- Bootnodes: p.bootnodes,
- }
+ validatorMetadata[i] = metadata
- // set generic validators as bootnodes if needed
- if len(p.bootnodes) == 0 {
- for i, validator := range genesisValidators {
- bootNode := fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", "127.0.0.1", bootnodePortStart+i, validator.NodeID)
- chainConfig.Bootnodes = append(chainConfig.Bootnodes, bootNode)
+ // set genesis validators as boot nodes if boot nodes not provided via CLI
+ if len(p.bootnodes) == 0 {
+ bootNodeMultiAddr := fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", "127.0.0.1", bootnodePortStart+i, validator.NodeID)
+ chainConfig.Bootnodes = append(chainConfig.Bootnodes, bootNodeMultiAddr)
}
}
- polyBftConfig.InitialValidatorSet = genesisValidators
-
- genesisExtraData, err := generateExtraDataPolyBft(genesisValidators)
+ genesisExtraData, err := generateExtraDataPolyBft(validatorMetadata)
if err != nil {
- return nil, err
+ return err
}
// populate genesis parameters
@@ -170,52 +165,7 @@ func (p *genesisParams) generatePolyBFTConfig() (*chain.Chain, error) {
Mixhash: polybft.PolyBFTMixDigest,
}
- return chainConfig, nil
-}
-
-func (p *genesisParams) getGenesisValidators() ([]*polybft.Validator, error) {
- 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) != 3 {
- return nil, fmt.Errorf("expected 3 parts provided in the following format , but got %d",
- len(parts))
- }
-
- if len(parts[0]) != 53 {
- return nil, fmt.Errorf("invalid node id: %s", parts[0])
- }
-
- if len(parts[1]) != 42 {
- return nil, fmt.Errorf("invalid address: %s", parts[1])
- }
-
- if len(parts[2]) < 2 {
- return nil, fmt.Errorf("invalid bls key: %s", parts[2])
- }
-
- validators[i] = &polybft.Validator{
- NodeID: parts[0],
- Address: types.StringToAddress(parts[1]),
- BlsKey: parts[2],
- }
- }
-
- return validators, nil
- }
-
- return ReadValidatorsByRegexp(path.Dir(p.genesisPath), p.polyBftValidatorPrefixPath)
-}
-
-func (p *genesisParams) generatePolyBftGenesis() error {
- config, err := params.generatePolyBFTConfig()
- if err != nil {
- return err
- }
-
- return helper.WriteGenesisConfigToDisk(config, params.genesisPath)
+ return helper.WriteGenesisConfigToDisk(chainConfig, params.genesisPath)
}
func (p *genesisParams) deployContracts() (map[types.Address]*chain.GenesisAccount, error) {
@@ -280,25 +230,12 @@ func (p *genesisParams) deployContracts() (map[types.Address]*chain.GenesisAccou
}
// generateExtraDataPolyBft populates Extra with specific fields required for polybft consensus protocol
-func generateExtraDataPolyBft(validators []*polybft.Validator) ([]byte, error) {
+func generateExtraDataPolyBft(validators []*polybft.ValidatorMetadata) ([]byte, error) {
delta := &polybft.ValidatorSetDelta{
- Added: make(polybft.AccountSet, len(validators)),
+ Added: validators,
Removed: bitmap.Bitmap{},
}
- for i, validator := range validators {
- blsKey, err := validator.UnmarshalBLSPublicKey()
- if err != nil {
- return nil, err
- }
-
- delta.Added[i] = &polybft.ValidatorMetadata{
- Address: validator.Address,
- BlsKey: blsKey,
- VotingPower: chain.ConvertWeiToTokensAmount(validator.Balance).Uint64(),
- }
- }
-
// Order validators based on its addresses
sort.Slice(delta.Added, func(i, j int) bool {
return bytes.Compare(delta.Added[i].Address[:], delta.Added[j].Address[:]) < 0
diff --git a/command/genesis/utils.go b/command/genesis/utils.go
index be63f2726d..81d7af8bda 100644
--- a/command/genesis/utils.go
+++ b/command/genesis/utils.go
@@ -11,7 +11,6 @@ import (
"strconv"
"strings"
- "github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/command"
"github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/wallet"
@@ -68,15 +67,6 @@ func verifyGenesisExistence(genesisPath string) *GenesisGenError {
return nil
}
-// fillPremineMap fills the premine map for the genesis.json file with passed in balances and accounts
-func fillPremineMap(premineMap map[types.Address]*chain.GenesisAccount, premineInfos []*premineInfo) {
- for _, premine := range premineInfos {
- premineMap[premine.address] = &chain.GenesisAccount{
- Balance: premine.balance,
- }
- }
-}
-
// parsePremineInfo parses provided premine information and returns premine address and premine balance
func parsePremineInfo(premineInfoRaw string) (*premineInfo, error) {
address := types.ZeroAddress
diff --git a/command/polybftmanifest/manifest_init.go b/command/polybftmanifest/manifest_init.go
new file mode 100644
index 0000000000..5bf0b3e0c5
--- /dev/null
+++ b/command/polybftmanifest/manifest_init.go
@@ -0,0 +1,210 @@
+package polybftmanifest
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "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/spf13/cobra"
+)
+
+const (
+ manifestPathFlag = "path"
+ premineValidatorsFlag = "premine-validators"
+ validatorsFlag = "validators"
+ validatorsPathFlag = "validators-path"
+ validatorsPrefixFlag = "validators-prefix"
+
+ defaultValidatorPrefixPath = "test-chain-"
+ defaultManifestPath = "./manifest.json"
+
+ nodeIDLength = 53
+ ecdsaAddressLength = 42
+ blsKeyLength = 2
+)
+
+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().StringVar(
+ ¶ms.premineValidators,
+ premineValidatorsFlag,
+ command.DefaultPremineBalance,
+ "the amount which will be pre-mined to all the validators",
+ )
+
+ 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}
+ 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
+ validators []string
+}
+
+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)
+ }
+
+ if _, err := types.ParseUint256orHex(&p.premineValidators); err != nil {
+ return fmt.Errorf("invalid premine validators balance provided '%s': %w", p.premineValidators, err)
+ }
+
+ return nil
+}
+
+// getValidatorAccounts gathers validator accounts info either from CLI or from provided local storage
+func (p *manifestInitParams) getValidatorAccounts() ([]*polybft.Validator, error) {
+ balance, err := types.ParseUint256orHex(¶ms.premineValidators)
+ if err != nil {
+ return nil, fmt.Errorf("provided invalid premine validators balance: %s", params.premineValidators)
+ }
+
+ 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) != 3 {
+ return nil, fmt.Errorf("expected 3 parts provided in the following format "+
+ ", but got %d part(s)",
+ len(parts))
+ }
+
+ if len(parts[0]) != nodeIDLength {
+ return nil, fmt.Errorf("invalid node id: %s", parts[0])
+ }
+
+ if len(parts[1]) != ecdsaAddressLength {
+ return nil, fmt.Errorf("invalid address: %s", parts[1])
+ }
+
+ if len(parts[2]) < blsKeyLength {
+ return nil, fmt.Errorf("invalid bls key: %s", parts[2])
+ }
+
+ validators[i] = &polybft.Validator{
+ NodeID: parts[0],
+ Address: types.StringToAddress(parts[1]),
+ BlsKey: parts[2],
+ Balance: balance,
+ }
+ }
+
+ return validators, nil
+ }
+
+ validatorsPath := p.validatorsPath
+ if validatorsPath == "" {
+ validatorsPath = path.Dir(p.manifestPath)
+ }
+
+ validators, err := genesis.ReadValidatorsByRegexp(validatorsPath, p.validatorsPrefixPath)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, v := range validators {
+ v.Balance = balance
+ }
+
+ return validators, nil
+}
+
+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/root/root.go b/command/root/root.go
index aa946f0eb5..fb3d6e7a6d 100644
--- a/command/root/root.go
+++ b/command/root/root.go
@@ -15,6 +15,7 @@ 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/rootchain"
"github.com/0xPolygon/polygon-edge/command/secrets"
@@ -61,6 +62,7 @@ func (rc *RootCommand) registerSubCommands() {
license.GetCommand(),
polybftsecrets.GetCommand(),
polybft.GetCommand(),
+ polybftmanifest.GetCommand(),
)
}
diff --git a/command/rootchain/emit/emit.go b/command/rootchain/emit/emit.go
index 5c7ca19468..62560f8f49 100644
--- a/command/rootchain/emit/emit.go
+++ b/command/rootchain/emit/emit.go
@@ -10,6 +10,7 @@ import (
"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/contracts"
"github.com/0xPolygon/polygon-edge/txrelayer"
"github.com/0xPolygon/polygon-edge/types"
@@ -18,8 +19,6 @@ import (
var (
params emitParams
- jsonRPCAddress string
-
contractsToParamTypes = map[string]string{
contracts.NativeTokenContract.String(): "tuple(address,uint256)",
}
@@ -42,6 +41,13 @@ func GetCommand() *cobra.Command {
}
func setFlags(cmd *cobra.Command) {
+ cmd.Flags().StringVar(
+ ¶ms.manifestPath,
+ manifestPathFlag,
+ "./manifest.json",
+ "the manifest file path, which contains genesis metadata",
+ )
+
cmd.Flags().StringVar(
¶ms.address,
contractFlag,
@@ -64,11 +70,18 @@ func setFlags(cmd *cobra.Command) {
)
cmd.Flags().StringVar(
- &jsonRPCAddress,
+ ¶ms.jsonRPCAddress,
jsonRPCFlag,
"http://127.0.0.1:8545",
"the JSON RPC rootchain IP address (e.g. http://127.0.0.1:8545)",
)
+
+ cmd.Flags().StringVar(
+ ¶ms.adminKey,
+ adminKeyFlag,
+ helper.DefaultPrivateKeyRaw,
+ "Hex encoded private key of the account which sends rootchain transactions",
+ )
}
func runPreRun(_ *cobra.Command, _ []string) error {
@@ -79,6 +92,20 @@ func runCommand(cmd *cobra.Command, _ []string) {
outputter := command.InitializeOutputter(cmd)
defer outputter.WriteOutput()
+ err := helper.InitRootchainAdminKey(params.adminKey)
+ if err != nil {
+ outputter.SetError(err)
+
+ return
+ }
+
+ manifest, err := polybft.LoadManifest(params.manifestPath)
+ if err != nil {
+ outputter.SetError(fmt.Errorf("failed to load manifest file from '%s': %w", params.manifestPath, err))
+
+ return
+ }
+
paramsType, exists := contractsToParamTypes[params.address]
if !exists {
outputter.SetError(fmt.Errorf("no parameter types for given contract address: %v", params.address))
@@ -86,7 +113,7 @@ func runCommand(cmd *cobra.Command, _ []string) {
return
}
- txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(jsonRPCAddress))
+ txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPCAddress))
if err != nil {
outputter.SetError(fmt.Errorf("could not create rootchain interactor: %w", err))
@@ -104,7 +131,7 @@ func runCommand(cmd *cobra.Command, _ []string) {
case <-ctx.Done():
return ctx.Err()
default:
- txn, err := createEmitTxn(paramsType, wallet, amount)
+ txn, err := createEmitTxn(manifest.RootchainConfig.StateSenderAddress, paramsType, wallet, amount)
if err != nil {
return fmt.Errorf("failed to create tx input: %w", err)
}
@@ -133,7 +160,10 @@ func runCommand(cmd *cobra.Command, _ []string) {
})
}
-func createEmitTxn(paramsType string, parameters ...interface{}) (*ethgo.Transaction, error) {
+func createEmitTxn(
+ stateSenderAddr types.Address,
+ paramsType string,
+ parameters ...interface{}) (*ethgo.Transaction, error) {
var prms []interface{}
prms = append(prms, parameters...)
@@ -150,7 +180,7 @@ func createEmitTxn(paramsType string, parameters ...interface{}) (*ethgo.Transac
}
return ðgo.Transaction{
- To: (*ethgo.Address)(&helper.StateSenderAddress),
+ To: (*ethgo.Address)(&stateSenderAddr),
Input: input,
}, nil
}
diff --git a/command/rootchain/emit/params.go b/command/rootchain/emit/params.go
index 7590005a2d..afc8b7f6fe 100644
--- a/command/rootchain/emit/params.go
+++ b/command/rootchain/emit/params.go
@@ -1,12 +1,18 @@
package emit
-import "errors"
+import (
+ "errors"
+ "fmt"
+ "os"
+)
const (
- contractFlag = "contract"
- walletsFlag = "wallets"
- amountsFlag = "amounts"
- jsonRPCFlag = "json-rpc"
+ manifestPathFlag = "manifest"
+ contractFlag = "contract"
+ walletsFlag = "wallets"
+ amountsFlag = "amounts"
+ jsonRPCFlag = "json-rpc"
+ adminKeyFlag = "admin-key"
)
var (
@@ -16,12 +22,19 @@ var (
)
type emitParams struct {
- address string
- wallets []string
- amounts []string
+ manifestPath string
+ address string
+ wallets []string
+ amounts []string
+ jsonRPCAddress string
+ adminKey string
}
func (ep *emitParams) validateFlags() error {
+ if _, err := os.Stat(ep.manifestPath); errors.Is(err, os.ErrNotExist) {
+ return fmt.Errorf("provided manifest path '%s' doesn't exist", ep.manifestPath)
+ }
+
if len(ep.wallets) == 0 {
return errWalletsMissing
}
diff --git a/command/rootchain/helper/metadata.go b/command/rootchain/helper/metadata.go
index 11585c253c..85154ed38a 100644
--- a/command/rootchain/helper/metadata.go
+++ b/command/rootchain/helper/metadata.go
@@ -2,32 +2,52 @@ package helper
import (
"context"
+ "encoding/hex"
"errors"
"fmt"
- "github.com/umbracle/ethgo"
-
- "github.com/0xPolygon/polygon-edge/types"
dockertypes "github.com/docker/docker/api/types"
"github.com/docker/docker/client"
+ "github.com/umbracle/ethgo"
+ "github.com/umbracle/ethgo/wallet"
)
-var (
- // StateSenderAddress is an address of StateSender.sol smart contract
- StateSenderAddress = types.StringToAddress("0x6FE03c2768C9d800AF3Dedf1878b5687FE120a27")
- // CheckpointManagerAddress is an address of CheckpointManager.sol smart contract
- CheckpointManagerAddress = types.StringToAddress("0x3d46A809D5767B81a8836f0E79145ba615A2Dd61")
- // BLSAddress is an address of BLS.sol smart contract
- BLSAddress = types.StringToAddress("0x72E1C51FE6dABF2e3d5701170cf5aD3620E6B8ba")
- // BN256G2Address is an address of BN256G2Address.sol smart contract
- BN256G2Address = types.StringToAddress("0x436604426F31A05f905C64edc973E575BdB46471")
- // ExitHelperAddress is an address of ExitHelper.sol smart contract
- ExitHelperAddress = ethgo.Address(types.StringToAddress("0x947a581B2713F58A8145201DA41BCb6aAE90196B"))
+const DefaultPrivateKeyRaw = "aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d"
+var (
ErrRootchainNotFound = errors.New("rootchain not found")
ErrRootchainPortBind = errors.New("port 8545 is not bind with localhost")
+
+ // rootchainAdminKey is a private key of account which is rootchain administrator
+ // namely it represents account which deploys rootchain smart contracts
+ rootchainAdminKey *wallet.Key
)
+// InitRootchainAdminKey initializes a private key instance from provided hex encoded private key
+func InitRootchainAdminKey(rawKey string) error {
+ privateKeyRaw := DefaultPrivateKeyRaw
+ if rawKey != "" {
+ privateKeyRaw = rawKey
+ }
+
+ dec, err := hex.DecodeString(privateKeyRaw)
+ if err != nil {
+ return fmt.Errorf("failed to decode private key string '%s': %w", privateKeyRaw, err)
+ }
+
+ rootchainAdminKey, err = wallet.NewWalletFromPrivKey(dec)
+ if err != nil {
+ return fmt.Errorf("failed to initialize key from provided private key '%s': %w", privateKeyRaw, err)
+ }
+
+ return nil
+}
+
+// GetRootchainAdminKey returns rootchain admin private key
+func GetRootchainAdminKey() ethgo.Key {
+ return rootchainAdminKey
+}
+
func GetRootchainID() (string, error) {
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
diff --git a/command/rootchain/helper/txn.go b/command/rootchain/helper/txn.go
deleted file mode 100644
index c82cb0c622..0000000000
--- a/command/rootchain/helper/txn.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package helper
-
-import (
- "encoding/hex"
-
- "github.com/umbracle/ethgo"
- "github.com/umbracle/ethgo/wallet"
-
- "github.com/0xPolygon/polygon-edge/types"
-)
-
-const (
- defaultGasPrice = 1879048192 // 0x70000000
- defaultGasLimit = 5242880 // 0x500000
-)
-
-var (
- // TODO: @Stefan-Ethernal Use either private key provided through CLI input or this (denoting dev vs prod mode)
- // use a deterministic wallet/private key so that the address of the deployed contracts
- // are deterministic
- rootchainAdminKey *wallet.Key
-)
-
-func init() {
- dec, err := hex.DecodeString("aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d")
- if err != nil {
- panic(err)
- }
-
- rootchainAdminKey, err = wallet.NewWalletFromPrivKey(dec)
- if err != nil {
- panic(err)
- }
-}
-
-func GetRootchainAdminAddr() types.Address {
- return types.Address(rootchainAdminKey.Address())
-}
-
-func GetRootchainAdminKey() ethgo.Key {
- return rootchainAdminKey
-}
diff --git a/command/rootchain/initcontracts/init_contracts.go b/command/rootchain/initcontracts/init_contracts.go
index af155a2b0f..5b843c7c5e 100644
--- a/command/rootchain/initcontracts/init_contracts.go
+++ b/command/rootchain/initcontracts/init_contracts.go
@@ -7,7 +7,6 @@ import (
"fmt"
"io/ioutil"
"math/big"
- "os"
"path/filepath"
"sort"
"strings"
@@ -21,7 +20,6 @@ import (
"github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/command"
- "github.com/0xPolygon/polygon-edge/command/genesis"
"github.com/0xPolygon/polygon-edge/command/rootchain/helper"
"github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
@@ -32,6 +30,16 @@ import (
"github.com/0xPolygon/polygon-edge/types"
)
+const (
+ contractsDeploymentTitle = "[ROOTCHAIN - CONTRACTS DEPLOYMENT]"
+
+ stateSenderName = "StateSender"
+ checkpointManagerName = "CheckpointManager"
+ blsName = "BLS"
+ bn256G2Name = "BN256G2"
+ exitHelperName = "ExitHelper"
+)
+
var (
params initContractsParams
@@ -42,12 +50,28 @@ var (
"address newBn256G2," +
// domain used for BLS signing
"bytes32 newDomain," +
- // RootValidatorSet contract address
+ // rootchain validator set
"tuple(address _address, uint256[4] blsKey, uint256 votingPower)[] newValidatorSet)")
-)
-const (
- contractsDeploymentTitle = "[ROOTCHAIN - CONTRACTS DEPLOYMENT]"
+ // metadataPopulatorMap maps rootchain contract names to callback
+ // which populates appropriate field in the RootchainMetadata
+ metadataPopulatorMap = map[string]func(*polybft.RootchainConfig, types.Address){
+ stateSenderName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
+ rootchainConfig.StateSenderAddress = addr
+ },
+ checkpointManagerName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
+ rootchainConfig.CheckpointManagerAddress = addr
+ },
+ blsName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
+ rootchainConfig.BLSAddress = addr
+ },
+ bn256G2Name: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
+ rootchainConfig.BN256G2Address = addr
+ },
+ exitHelperName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
+ rootchainConfig.ExitHelperAddress = addr
+ },
+ }
)
// GetCommand returns the rootchain emit command
@@ -69,26 +93,23 @@ func setFlags(cmd *cobra.Command) {
¶ms.contractsPath,
contractsPathFlag,
contracts.ContractsRootFolder,
- "Root path for the smart contracts",
- )
- cmd.Flags().StringVar(
- ¶ms.validatorPath,
- validatorPathFlag,
- defaultValidatorPath,
- "Validators path",
+ "Root directory path containing POS smart contracts",
)
+
cmd.Flags().StringVar(
- ¶ms.validatorPrefixPath,
- validatorPrefixPathFlag,
- defaultValidatorPrefixPath,
- "Validators prefix path",
+ ¶ms.manifestPath,
+ manifestPathFlag,
+ defaultManifestPath,
+ "Manifest file path, which contains metadata",
)
+
cmd.Flags().StringVar(
- ¶ms.genesisPath,
- genesisPathFlag,
- defaultGenesisPath,
- "Genesis configuration path",
+ ¶ms.adminKey,
+ adminKeyFlag,
+ helper.DefaultPrivateKeyRaw,
+ "Hex encoded private key of the account which deploys rootchain contracts",
)
+
cmd.Flags().StringVar(
¶ms.jsonRPCAddress,
jsonRPCFlag,
@@ -97,7 +118,7 @@ func setFlags(cmd *cobra.Command) {
)
}
-func runPreRun(_ *cobra.Command, _ []string) error {
+func runPreRun(cmd *cobra.Command, _ []string) error {
return params.validateFlags()
}
@@ -117,20 +138,35 @@ func runCommand(cmd *cobra.Command, _ []string) {
return
}
- code, err := client.Eth().GetCode(ethgo.Address(helper.StateSenderAddress), ethgo.Latest)
+ manifest, err := polybft.LoadManifest(params.manifestPath)
if err != nil {
- outputter.SetError(fmt.Errorf("failed to check if rootchain contracts are deployed: %w", err))
+ outputter.SetError(fmt.Errorf("failed to read manifest: %w", err))
return
- } else if code != "0x" {
- outputter.SetCommandResult(&messageResult{
- Message: fmt.Sprintf("%s contracts are already deployed. Aborting.", contractsDeploymentTitle),
- })
+ }
+
+ if manifest.RootchainConfig != nil {
+ code, err := client.Eth().GetCode(ethgo.Address(manifest.RootchainConfig.StateSenderAddress), ethgo.Latest)
+ if err != nil {
+ outputter.SetError(fmt.Errorf("failed to check if rootchain contracts are deployed: %w", err))
+
+ return
+ } else if code != "0x" {
+ outputter.SetCommandResult(&messageResult{
+ Message: fmt.Sprintf("%s contracts are already deployed. Aborting.", contractsDeploymentTitle),
+ })
+
+ return
+ }
+ }
+
+ if err := helper.InitRootchainAdminKey(params.adminKey); err != nil {
+ outputter.SetError(err)
return
}
- if err := deployContracts(outputter); err != nil {
+ if err := deployContracts(outputter, client, manifest); err != nil {
outputter.SetError(fmt.Errorf("failed to deploy rootchain contracts: %w", err))
return
@@ -142,98 +178,85 @@ func runCommand(cmd *cobra.Command, _ []string) {
})
}
-func getGenesisAlloc() (map[types.Address]*chain.GenesisAccount, error) {
- genesisFile, err := os.Open(params.genesisPath)
- if err != nil {
- return nil, fmt.Errorf("failed to open genesis config file: %w", err)
- }
-
- genesisRaw, err := ioutil.ReadAll(genesisFile)
- if err != nil {
- return nil, fmt.Errorf("failed to read genesis config file: %w", err)
- }
-
- var chain *chain.Chain
- if err := json.Unmarshal(genesisRaw, &chain); err != nil {
- return nil, fmt.Errorf("failed to unmarshal genesis configuration: %w", err)
- }
-
- return chain.Genesis.Alloc, nil
-}
-
-func deployContracts(outputter command.OutputFormatter) error {
+func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, manifest *polybft.Manifest) error {
// if the bridge contract is not created, we have to deploy all the contracts
- txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPCAddress))
+ txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(client))
if err != nil {
return fmt.Errorf("failed to initialize tx relayer: %w", err)
}
- // TODO: @Stefan-Ethernal Skip FundAccount part in follow up PR if in "dev" mode
- // fund account
- rootchainAdminAddr := ethgo.Address(helper.GetRootchainAdminAddr())
- txn := ðgo.Transaction{To: &rootchainAdminAddr, Value: big.NewInt(1000000000000000000)}
+ rootchainAdminKey := helper.GetRootchainAdminKey()
+ // if admin key is equal to the test private key, then we assume we are working in dev mode
+ // and therefore need to fund that account
+ if params.adminKey == helper.DefaultPrivateKeyRaw {
+ // fund account
+ rootchainAdminAddr := rootchainAdminKey.Address()
+ txn := ðgo.Transaction{To: &rootchainAdminAddr, Value: big.NewInt(1000000000000000000)}
+ _, err = txRelayer.SendTransactionLocal(txn)
- _, err = txRelayer.SendTransactionLocal(txn)
- if err != nil {
- return err
+ if err != nil {
+ return err
+ }
}
deployContracts := []struct {
name string
artifact *artifact.Artifact
- expected types.Address
}{
{
name: "StateSender",
artifact: contractsapi.StateSender,
- expected: helper.StateSenderAddress,
},
{
name: "CheckpointManager",
artifact: contractsapi.CheckpointManager,
- expected: helper.CheckpointManagerAddress,
},
{
name: "BLS",
artifact: contractsapi.BLS,
- expected: helper.BLSAddress,
},
{
name: "BN256G2",
artifact: contractsapi.BLS256,
- expected: helper.BN256G2Address,
},
{
name: "ExitHelper",
artifact: contractsapi.ExitHelper,
- expected: types.Address(helper.ExitHelperAddress),
},
}
+ rootchainConfig := &polybft.RootchainConfig{}
+ manifest.RootchainConfig = rootchainConfig
+ rootchainConfig.AdminAddress = types.Address(rootchainAdminKey.Address())
+
for _, contract := range deployContracts {
txn := ðgo.Transaction{
To: nil, // contract deployment
Input: contract.artifact.Bytecode,
}
- receipt, err := txRelayer.SendTransaction(txn, helper.GetRootchainAdminKey())
+ receipt, err := txRelayer.SendTransaction(txn, rootchainAdminKey)
if err != nil {
return err
}
- if types.Address(receipt.ContractAddress) != contract.expected {
- return fmt.Errorf("wrong deployed address for contract %s: expected %s but found %s",
- contract.name, contract.expected, receipt.ContractAddress)
+ 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)
}
- outputter.WriteCommandResult(newDeployContractsResult(contract.name, contract.expected, receipt.TransactionHash))
+ populatorFn(manifest.RootchainConfig, contractAddr)
+
+ outputter.WriteCommandResult(newDeployContractsResult(contract.name, contractAddr, receipt.TransactionHash))
}
- if err := initializeCheckpointManager(txRelayer); err != nil {
- return err
+ if err := manifest.Save(params.manifestPath); err != nil {
+ return fmt.Errorf("failed to save manifest data: %w", err)
}
- if err := initializeExitHelper(txRelayer, ethgo.Address(helper.CheckpointManagerAddress)); err != nil {
+ if err := initializeCheckpointManager(txRelayer, rootchainAdminKey, manifest); err != nil {
return err
}
@@ -241,26 +264,31 @@ func deployContracts(outputter command.OutputFormatter) error {
Message: fmt.Sprintf("%s CheckpointManager contract is initialized", contractsDeploymentTitle),
})
- return nil
-}
-
-// initializeCheckpointManager invokes initialize function on CheckpointManager smart contract
-func initializeCheckpointManager(txRelayer txrelayer.TxRelayer) error {
- allocs, err := getGenesisAlloc()
- if err != nil {
+ if err := initializeExitHelper(txRelayer, rootchainConfig); err != nil {
return err
}
- validatorSetMap, err := validatorSetToABISlice(allocs)
+ outputter.WriteCommandResult(&messageResult{
+ Message: fmt.Sprintf("%s ExitHelper contract is initialized", contractsDeploymentTitle),
+ })
+
+ return nil
+}
+// initializeCheckpointManager invokes initialize function on CheckpointManager smart contract
+func initializeCheckpointManager(
+ txRelayer txrelayer.TxRelayer,
+ rootchainAdminKey ethgo.Key,
+ manifest *polybft.Manifest) error {
+ validatorSetMap, err := validatorSetToABISlice(manifest.GenesisValidators)
if err != nil {
return fmt.Errorf("failed to convert validators to map: %w", err)
}
initCheckpointInput, err := initCheckpointManager.Encode(
[]interface{}{
- helper.BLSAddress,
- helper.BN256G2Address,
+ manifest.RootchainConfig.BLSAddress,
+ manifest.RootchainConfig.BN256G2Address,
bls.GetDomain(),
validatorSetMap,
})
@@ -269,13 +297,13 @@ func initializeCheckpointManager(txRelayer txrelayer.TxRelayer) error {
return fmt.Errorf("failed to encode parameters for CheckpointManager.initialize. error: %w", err)
}
- checkpointManagerAddress := ethgo.Address(helper.CheckpointManagerAddress)
+ checkpointManagerAddress := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress)
txn := ðgo.Transaction{
To: &checkpointManagerAddress,
Input: initCheckpointInput,
}
- receipt, err := txRelayer.SendTransaction(txn, helper.GetRootchainAdminKey())
+ receipt, err := txRelayer.SendTransaction(txn, rootchainAdminKey)
if err != nil {
return fmt.Errorf("failed to send transaction to CheckpointManager. error: %w", err)
}
@@ -287,15 +315,16 @@ func initializeCheckpointManager(txRelayer txrelayer.TxRelayer) error {
return nil
}
-func initializeExitHelper(txRelayer txrelayer.TxRelayer, checkpointManagerAddress ethgo.Address) error {
+func initializeExitHelper(txRelayer txrelayer.TxRelayer, rootchainConfig *polybft.RootchainConfig) error {
input, err := contractsapi.ExitHelper.Abi.GetMethod("initialize").
- Encode([]interface{}{checkpointManagerAddress})
+ Encode([]interface{}{rootchainConfig.CheckpointManagerAddress})
if err != nil {
return fmt.Errorf("failed to encode parameters for ExitHelper.initialize. error: %w", err)
}
+ exitHelperAddr := ethgo.Address(rootchainConfig.ExitHelperAddress)
txn := ðgo.Transaction{
- To: &helper.ExitHelperAddress,
+ To: &exitHelperAddr,
Input: input,
}
@@ -312,30 +341,26 @@ func initializeExitHelper(txRelayer txrelayer.TxRelayer, checkpointManagerAddres
}
// initializeCheckpointManager invokes initialize function on CheckpointManager smart contract
-func validatorSetToABISlice(allocs map[types.Address]*chain.GenesisAccount) ([]map[string]interface{}, error) {
- validatorsInfo, err := genesis.ReadValidatorsByRegexp(params.validatorPath, params.validatorPrefixPath)
- if err != nil {
- return nil, err
- }
-
- sort.Slice(validatorsInfo, func(i, j int) bool {
- return bytes.Compare(validatorsInfo[i].Address.Bytes(),
- validatorsInfo[j].Address.Bytes()) < 0
+func validatorSetToABISlice(validators []*polybft.Validator) ([]map[string]interface{}, error) {
+ genesisValidators := make([]*polybft.Validator, len(validators))
+ copy(genesisValidators, validators)
+ sort.Slice(genesisValidators, func(i, j int) bool {
+ return bytes.Compare(genesisValidators[i].Address.Bytes(), genesisValidators[j].Address.Bytes()) < 0
})
- accSet := polybft.AccountSet{}
+ accSet := make(polybft.AccountSet, len(genesisValidators))
- for _, validatorInfo := range validatorsInfo {
+ for i, validatorInfo := range genesisValidators {
blsKey, err := validatorInfo.UnmarshalBLSPublicKey()
if err != nil {
return nil, err
}
- accSet = append(accSet, &polybft.ValidatorMetadata{
+ accSet[i] = &polybft.ValidatorMetadata{
Address: validatorInfo.Address,
BlsKey: blsKey,
- VotingPower: allocs[validatorInfo.Address].Balance.Uint64(),
- })
+ VotingPower: chain.ConvertWeiToTokensAmount(validatorInfo.Balance).Uint64(),
+ }
}
return accSet.AsGenericMaps(), nil
diff --git a/command/rootchain/initcontracts/params.go b/command/rootchain/initcontracts/params.go
index c01a1610dc..cbdbf8ce3e 100644
--- a/command/rootchain/initcontracts/params.go
+++ b/command/rootchain/initcontracts/params.go
@@ -7,23 +7,19 @@ import (
)
const (
- contractsPathFlag = "path"
- validatorPrefixPathFlag = "validator-prefix"
- validatorPathFlag = "validator-path"
- genesisPathFlag = "genesis-path"
- jsonRPCFlag = "json-rpc"
+ contractsPathFlag = "path"
+ manifestPathFlag = "manifest"
+ jsonRPCFlag = "json-rpc"
+ adminKeyFlag = "admin-key"
- defaultValidatorPrefixPath = "test-chain-"
- defaultValidatorPath = "./"
- defaultGenesisPath = "./genesis.json"
+ defaultManifestPath = "./manifest.json"
)
type initContractsParams struct {
- contractsPath string
- validatorPrefixPath string
- validatorPath string
- genesisPath string
- jsonRPCAddress string
+ contractsPath string
+ manifestPath string
+ adminKey string
+ jsonRPCAddress string
}
func (ip *initContractsParams) validateFlags() error {
@@ -31,12 +27,8 @@ func (ip *initContractsParams) validateFlags() error {
return fmt.Errorf("provided smart contracts directory '%s' doesn't exist", ip.contractsPath)
}
- if _, err := os.Stat(ip.validatorPath); errors.Is(err, os.ErrNotExist) {
- return fmt.Errorf("provided validators data directory '%s' doesn't exist", ip.validatorPath)
- }
-
- if _, err := os.Stat(ip.genesisPath); errors.Is(err, os.ErrNotExist) {
- return fmt.Errorf("provided genesis path '%s' doesn't exist", ip.genesisPath)
+ 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/consensus/polybft/README.md b/consensus/polybft/README.md
new file mode 100644
index 0000000000..c1b5f1935d
--- /dev/null
+++ b/consensus/polybft/README.md
@@ -0,0 +1,84 @@
+
+# Polybft consensus protocol
+
+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.
+
+## Setup local testing environment
+
+### Precondition
+
+Smart contracts in the `core-contracts` submodule must be compiled before running following commands.
+In order to do so, run `make compile-core-contracts`.
+
+1. Build binary
+
+ ```bash
+ go build -o polygon-edge .
+ ```
+
+2. Init secrets - this command is used to generate private keys (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
+ ```
+
+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.**
+
+ ```bash
+ polygon-edge rootchain server
+ ```
+
+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 is 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 we supply necessary information using `--validators` flag. Validator information needs to be supplied in the strictly following format:
+ `::`.
+
+ ```bash
+ polygon-edge manifest
+ --validators 16Uiu2HAmTkqGixWVxshMbbgtXhTUP8zLCZZiG1UyCNtxLhCkZJuv:0xDcBe0024206ec42b0Ef4214Ac7B71aeae1A11af0:1cf134e02c6b2afb2ceda50bf2c9a01da367ac48f7783ee6c55444e1cab418ec0f52837b90a4d8cf944814073fc6f2bd96f35366a3846a8393e3cb0b19197cde23e2b40c6401fa27ff7d0c36779d9d097d1393cab6fc1d332f92fb3df850b78703b2989d567d1344e219f0667a1863f52f7663092276770cf513f9704b5351c4
+ [--validators 16Uiu2HAm1kVEh4uVw41WuhDfreCaVuj3kiWZy44kbnJrZnwnMKDW:0x2da750eD4AE1D5A7F7c996Faec592F3d44060e90:088d92c25b5f278750534e8a902da604a1aa39b524b4511f5f47c3a386374ca3031b667beb424faef068a01cee3428a1bc8c1c8bab826f30a1ee03fbe90cb5f01abcf4abd7af3bbe83eaed6f82179b9cbdc417aad65d919b802d91c2e1aaefec27ba747158bc18a0556e39bfc9175c099dd77517a85731894bbea3d191a622bc]
+ [--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.
+
+ ```bash
+ polygon-edge rootchain init-contracts [--manifest ./manifest.json] [--contracts-path ./core-contracts/artifacts]
+ [--json-rpc http://127.0.0.1:8545] [--admin-key ]
+ ```
+
+6. Create chain configuration - this command creates chain configuration, which is needed to run a blockchain
+
+ ```bash
+ polygon-edge genesis --consensus polybft --block-gas-limit 10000000 --epoch-size 10
+ [--bridge-json-rpc ] [--contracts-path ./core-contracts/artifacts] [--manifest ./manifest.json]
+ ```
+
+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.**
+
+ ```bash
+ polygon-edge rootchain fund --data-dir test-chain- --num 4
+ ```
+
+8. Run (sidechain) 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 --seal --log-level DEBUG
+
+ 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 --seal --log-level DEBUG
+
+ polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :5004 --libp2p :30304 --jsonrpc :10004 --seal --log-level DEBUG
+ ```
diff --git a/consensus/polybft/checkpoint_manager.go b/consensus/polybft/checkpoint_manager.go
index aa128ec62e..235d7d3184 100644
--- a/consensus/polybft/checkpoint_manager.go
+++ b/consensus/polybft/checkpoint_manager.go
@@ -5,7 +5,6 @@ import (
"math/big"
"strconv"
- "github.com/0xPolygon/polygon-edge/command/rootchain/helper"
bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer"
"github.com/0xPolygon/polygon-edge/txrelayer"
"github.com/0xPolygon/polygon-edge/types"
@@ -46,6 +45,8 @@ type checkpointManager struct {
txRelayer txrelayer.TxRelayer
// checkpointsOffset represents offset between checkpoint blocks (applicable only for non-epoch ending blocks)
checkpointsOffset uint64
+ // checkpointManagerAddr is address of CheckpointManager smart contract
+ checkpointManagerAddr types.Address
// latestCheckpointID represents last checkpointed block number
latestCheckpointID uint64
// logger instance
@@ -53,15 +54,17 @@ type checkpointManager struct {
}
// newCheckpointManager creates a new instance of checkpointManager
-func newCheckpointManager(key ethgo.Key, checkpointOffset uint64, txRelayer txrelayer.TxRelayer,
+func newCheckpointManager(key ethgo.Key, checkpointOffset uint64,
+ checkpointManagerSC types.Address, txRelayer txrelayer.TxRelayer,
blockchain blockchainBackend, backend polybftBackend, logger hclog.Logger) *checkpointManager {
return &checkpointManager{
- key: key,
- blockchain: blockchain,
- consensusBackend: backend,
- txRelayer: txRelayer,
- checkpointsOffset: checkpointOffset,
- logger: logger,
+ key: key,
+ blockchain: blockchain,
+ consensusBackend: backend,
+ txRelayer: txRelayer,
+ checkpointsOffset: checkpointOffset,
+ checkpointManagerAddr: checkpointManagerSC,
+ logger: logger,
}
}
@@ -74,7 +77,7 @@ func (c *checkpointManager) getLatestCheckpointBlock() (uint64, error) {
latestCheckpointBlockRaw, err := c.txRelayer.Call(
c.key.Address(),
- ethgo.Address(helper.CheckpointManagerAddress),
+ ethgo.Address(c.checkpointManagerAddr),
checkpointBlockNumMethodEncoded)
if err != nil {
return 0, fmt.Errorf("failed to invoke currentCheckpointId function on the rootchain: %w", err)
@@ -100,7 +103,7 @@ func (c *checkpointManager) submitCheckpoint(latestHeader types.Header, isEndOfE
"latest checkpoint block", lastCheckpointBlockNumber,
"checkpoint block", latestHeader.Number)
- checkpointManagerAddr := ethgo.Address(helper.CheckpointManagerAddress)
+ checkpointManagerAddr := ethgo.Address(c.checkpointManagerAddr)
txn := ðgo.Transaction{
To: &checkpointManagerAddr,
From: c.key.Address(),
diff --git a/consensus/polybft/checkpoint_manager_test.go b/consensus/polybft/checkpoint_manager_test.go
index 3d1cad7eba..ecb7ffe6a5 100644
--- a/consensus/polybft/checkpoint_manager_test.go
+++ b/consensus/polybft/checkpoint_manager_test.go
@@ -267,7 +267,7 @@ func TestCheckpointManager_isCheckpointBlock(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
t.Parallel()
- checkpointMgr := newCheckpointManager(wallet.NewEcdsaSigner(createTestKey(t)), c.checkpointsOffset, nil, nil, nil, hclog.NewNullLogger())
+ checkpointMgr := newCheckpointManager(wallet.NewEcdsaSigner(createTestKey(t)), c.checkpointsOffset, types.ZeroAddress, nil, nil, nil, hclog.NewNullLogger())
require.Equal(t, c.isCheckpointBlock, checkpointMgr.isCheckpointBlock(c.blockNumber))
})
}
diff --git a/consensus/polybft/consensus_runtime.go b/consensus/polybft/consensus_runtime.go
index 3ad0e645b7..95d0fa9de9 100644
--- a/consensus/polybft/consensus_runtime.go
+++ b/consensus/polybft/consensus_runtime.go
@@ -129,6 +129,7 @@ func newConsensusRuntime(log hcf.Logger, config *runtimeConfig) (*consensusRunti
runtime.checkpointManager = newCheckpointManager(
wallet.NewEcdsaSigner(config.Key),
defaultCheckpointsOffset,
+ config.PolyBFTConfig.Bridge.CheckpointAddr,
txRelayer,
config.blockchain,
config.polybftBackend,
diff --git a/consensus/polybft/consensus_runtime_test.go b/consensus/polybft/consensus_runtime_test.go
index 0fc69c9bf2..766b7049c4 100644
--- a/consensus/polybft/consensus_runtime_test.go
+++ b/consensus/polybft/consensus_runtime_test.go
@@ -1620,7 +1620,7 @@ func TestConsensusRuntime_FSM_EndOfEpoch_OnBlockInserted(t *testing.T) {
epoch: metadata,
config: config,
lastBuiltBlock: lastBuiltBlock,
- checkpointManager: newCheckpointManager(wallet.NewEcdsaSigner(signer), 5, nil, nil, nil, hclog.NewNullLogger()),
+ checkpointManager: newCheckpointManager(wallet.NewEcdsaSigner(signer), 5, types.ZeroAddress, nil, nil, nil, hclog.NewNullLogger()),
}
err = runtime.FSM()
diff --git a/consensus/polybft/contractsapi/gen_sc_data.go b/consensus/polybft/contractsapi/gen_sc_data.go
index cbade664ec..daba2bae92 100644
--- a/consensus/polybft/contractsapi/gen_sc_data.go
+++ b/consensus/polybft/contractsapi/gen_sc_data.go
@@ -1,6 +1,6 @@
package contractsapi
-// This is generated file don't change it manually. DO NOT EDIT.
+// This is auto-generated file. DO NOT EDIT.
var CheckpointManagerArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"CheckpointManager\",\n \"sourceName\": \"contracts/root/CheckpointManager.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"bls\",\n \"outputs\": [\n {\n \"internalType\": \"contract IBLS\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"bn256G2\",\n \"outputs\": [\n {\n \"internalType\": \"contract IBN256G2\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"checkpointBlockNumbers\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"checkpoints\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"eventRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentCheckpointBlockNumber\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentEpoch\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"currentValidatorSet\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentValidatorSetLength\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"domain\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"leaf\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"getEventMembershipByBlockNumber\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"leaf\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"getEventMembershipByEpoch\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getEventRootByBlock\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IBLS\",\n \"name\": \"newBls\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"contract IBN256G2\",\n \"name\": \"newBn256G2\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"newDomain\",\n \"type\": \"bytes32\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Validator[]\",\n \"name\": \"newValidatorSet\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"chainId\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"blockHash\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockRound\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"currentValidatorSetHash\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.CheckpointMetadata\",\n \"name\": \"checkpointMetadata\",\n \"type\": \"tuple\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"eventRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Checkpoint\",\n \"name\": \"checkpoint\",\n \"type\": \"tuple\"\n },\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Validator[]\",\n \"name\": \"newValidatorSet\",\n \"type\": \"tuple[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"bitmap\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"submit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalVotingPower\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611565806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80637667180811610097578063c2fb26a611610066578063c2fb26a614610260578063d4c8e3e814610269578063e416d6771461027c578063e9193d2b1461028557600080fd5b806376671808146101cf57806395b0b027146101d8578063b8a2425214610203578063bb1853ca1461024d57600080fd5b806361a02208116100d357806361a022081461013e578063671b3793146101615780636969a25c1461016a578063729e7c6e146101bc57600080fd5b80631d1d4f26146100fa5780633569ed93146101165780635036759a14610129575b600080fd5b61010360025481565b6040519081526020015b60405180910390f35b610103610124366004610e7b565b610298565b61013c610137366004610ef8565b6102cc565b005b61015161014c366004610f6b565b610423565b604051901515815260200161010d565b61010360045481565b61019d610178366004610e7b565b600960205260009081526040902080546005909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161010d565b6101516101ca366004610f6b565b610496565b61010360015481565b6006546101eb906001600160a01b031681565b6040516001600160a01b03909116815260200161010d565b610232610211366004610e7b565b60086020526000908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161010d565b61013c61025b366004611013565b6104f5565b61010360055481565b6007546101eb906001600160a01b031681565b61010360035481565b610103610293366004610e7b565b61070b565b60006008816102a8600a8561072c565b6102b390600161110b565b8152602001908152602001600020600201549050919050565b600054610100900460ff16158080156102ec5750600054600160ff909116105b806103065750303b158015610306575060005460ff166001145b61036e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610391576000805461ff0019166101001790555b600680546001600160a01b038089166001600160a01b0319928316179092556007805492881692909116919091179055600584905560028290556103d583836107db565b801561041b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b60008061042f87610298565b90508061047e5760405162461bcd60e51b815260206004820152601e60248201527f4e4f5f4556454e545f524f4f545f464f525f424c4f434b5f4e554d42455200006044820152606401610365565b61048b86868387876108b2565b979650505050505050565b6000858152600860205260408120600201548061047e5760405162461bcd60e51b815260206004820152601760248201527f4e4f5f4556454e545f524f4f545f464f525f45504f43480000000000000000006044820152606401610365565b600088876020013589600001358a602001358a600001358b604001358d604001358b8b60405160200161052992919061111e565b60408051601f198184030181528282528051602091820120908301999099528101969096526060860194909452608085019290925260a084015260c083015260e08201526101008101919091526101200160408051601f198184030181528282528051602091820120908301520160408051601f198184030181529082905260065460055463a850a90960e01b8452919350610628926001600160a01b039091169163a850a909916105e091908690600401611181565b6040805180830381865afa1580156105fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062091906111d7565b8785856109cb565b600180546000918261063983611265565b9190505590506106498189610d0b565b8735600081815260086020908152604091829020838155908b01356001820155908a01356002909101558110156106b957600a805460018101825560009190915260208901357fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8909101556106ed565b600a805460208a013591906106d09060019061127e565b815481106106e0576106e0611291565b6000918252602090912001555b60208801356003556106ff86866107db565b50505050505050505050565b600a818154811061071b57600080fd5b600091825260209091200154905081565b8154600090810361073f575060006107d5565b82546000905b8082101561078c5760006107598383610dd2565b6000878152602090209091508590820154111561077857809150610786565b61078381600161110b565b92505b50610745565b6000821180156107b85750836107b5866107a760018661127e565b600091825260209091200190565b54145b156107d1576107c860018361127e565b925050506107d5565b5090505b92915050565b6002819055806000805b828110156108a957600085858381811061080157610801611291565b905060c0020160a001359050600081116108515760405162461bcd60e51b8152602060048201526011602482015270564f54494e475f504f5745525f5a45524f60781b6044820152606401610365565b61085b818461110b565b925085858381811061086f5761086f611291565b905060c0020160096000848152602001908152602001600020818161089491906112be565b90505050806108a290611265565b90506107e5565b50600455505050565b6000816108c0816002611401565b86106109035760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b6044820152606401610365565b8660005b828110156109bd57600086868381811061092357610923611291565b9050602002013590506002896109399190611423565b60000361097157604080516020810185905290810182905260600160405160208183030381529060405280519060200120925061099e565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b6109a960028a611437565b985050806109b690611265565b9050610907565b509094149695505050505050565b6002546109d6610e5d565b6000805b83811015610b81576109ed868683610df4565b15610b795781600003610a41576000818152600960205260409081902081516080810190925260010160048282826020028201915b815481526020019060010190808311610a225750505050509250610b5a565b60008181526009602052604080822081516080810190925260010160048282826020028201915b815481526020019060010190808311610a6857505060075488516020808b01516040808d01516060808f01518b51958c0151848d0151928d01519451630cbe96a560e41b81526004810198909852602488019590955260448701929092526064860191909152608485019390935260a484019190915260c483019190915260e48201529495506001600160a01b03169363cbe96a50935061010401915050608060405180830381865afa158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b47919061144b565b6060880152604087015260208601528452505b600081815260096020526040902060050154610b76908361110b565b91505b6001016109da565b5080600003610bc45760405162461bcd60e51b815260206004820152600f60248201526e4249544d41505f49535f454d50545960881b6044820152606401610365565b60036004546002610bd591906112a7565b610bdf9190611437565b8111610c2d5760405162461bcd60e51b815260206004820152601960248201527f494e53554646494349454e545f564f54494e475f504f574552000000000000006044820152606401610365565b60065460405163ebbdac9160e01b815260009182916001600160a01b039091169063ebbdac9190610c66908b9088908e90600401611481565b6040805180830381865afa158015610c82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca691906114fc565b91509150818015610cb45750805b610d005760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c45440000006044820152606401610365565b505050505050505050565b600082815260086020908152604091829020825160608101845281548082526001830154938201939093526002909101549281019290925282351015610d835760405162461bcd60e51b815260206004820152600d60248201526c0929cac82989288be8aa09e869609b1b6044820152606401610365565b8060200151826020013511610dcd5760405162461bcd60e51b815260206004820152601060248201526f115354151657d0d21150d2d413d2539560821b6044820152606401610365565b505050565b6000610de16002848418611437565b610ded9084841661110b565b9392505050565b600080610e02600884611437565b90506000610e11600885611423565b9050848210610e2557600092505050610ded565b6000600160ff83161b878785818110610e4057610e40611291565b9050013560f81c60f81b60f81c60ff161611925050509392505050565b60405180608001604052806004906020820280368337509192915050565b600060208284031215610e8d57600080fd5b5035919050565b6001600160a01b0381168114610ea957600080fd5b50565b60008083601f840112610ebe57600080fd5b50813567ffffffffffffffff811115610ed657600080fd5b60208301915083602060c083028501011115610ef157600080fd5b9250929050565b600080600080600060808688031215610f1057600080fd5b8535610f1b81610e94565b94506020860135610f2b81610e94565b935060408601359250606086013567ffffffffffffffff811115610f4e57600080fd5b610f5a88828901610eac565b969995985093965092949392505050565b600080600080600060808688031215610f8357600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff80821115610fb057600080fd5b818801915088601f830112610fc457600080fd5b813581811115610fd357600080fd5b8960208260051b8501011115610fe857600080fd5b9699959850939650602001949392505050565b60006060828403121561100d57600080fd5b50919050565b600080600080600080600080610160898b03121561103057600080fd5b883597506110418a60208b01610ffb565b96506110508a60808b01610ffb565b955061012089018a81111561106457600080fd5b60e08a0195503567ffffffffffffffff8082111561108157600080fd5b61108d8c838d01610eac565b90965094506101408b01359150808211156110a757600080fd5b818b0191508b601f8301126110bb57600080fd5b8135818111156110ca57600080fd5b8c60208285010111156110dc57600080fd5b6020830194508093505050509295985092959890939650565b634e487b7160e01b600052601160045260246000fd5b808201808211156107d5576107d56110f5565b60208082528181018390526000908460408401835b8681101561117657823561114681610e94565b6001600160a01b0316825260808385018584013760a0838101359083015260c09283019290910190600101611133565b509695505050505050565b82815260006020604081840152835180604085015260005b818110156111b557858101830151858201606001528201611199565b506000606082860101526060601f19601f830116850101925050509392505050565b6000604082840312156111e957600080fd5b82601f8301126111f857600080fd5b6040516040810181811067ffffffffffffffff8211171561122957634e487b7160e01b600052604160045260246000fd5b806040525080604084018581111561124057600080fd5b845b8181101561125a578051835260209283019201611242565b509195945050505050565b600060018201611277576112776110f5565b5060010190565b818103818111156107d5576107d56110f5565b634e487b7160e01b600052603260045260246000fd5b80820281158282048414176107d5576107d56110f5565b81356112c981610e94565b81546001600160a01b0319166001600160a01b0391909116178155602082810160005b600481101561130c578135600182860181019190915591830191016112ec565b50505060a082013560058201555050565b600181815b8085111561135857816000190482111561133e5761133e6110f5565b8085161561134b57918102915b93841c9390800290611322565b509250929050565b60008261136f575060016107d5565b8161137c575060006107d5565b8160018114611392576002811461139c576113b8565b60019150506107d5565b60ff8411156113ad576113ad6110f5565b50506001821b6107d5565b5060208310610133831016604e8410600b84101617156113db575081810a6107d5565b6113e5838361131d565b80600019048211156113f9576113f96110f5565b029392505050565b6000610ded8383611360565b634e487b7160e01b600052601260045260246000fd5b6000826114325761143261140d565b500690565b6000826114465761144661140d565b500490565b6000806000806080858703121561146157600080fd5b505082516020840151604085015160609095015191969095509092509050565b61010081016040858337604082018460005b60048110156114b2578151835260209283019290910190600101611493565b50505060c082018360005b60028110156114dc5781518352602092830192909101906001016114bd565b505050949350505050565b805180151581146114f757600080fd5b919050565b6000806040838503121561150f57600080fd5b611518836114e7565b9150611526602084016114e7565b9050925092905056fea2646970667358221220a0c0838b66ae5561939526edc9c8be8257337a63060f8b3cb9c0f83765c9510364736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80637667180811610097578063c2fb26a611610066578063c2fb26a614610260578063d4c8e3e814610269578063e416d6771461027c578063e9193d2b1461028557600080fd5b806376671808146101cf57806395b0b027146101d8578063b8a2425214610203578063bb1853ca1461024d57600080fd5b806361a02208116100d357806361a022081461013e578063671b3793146101615780636969a25c1461016a578063729e7c6e146101bc57600080fd5b80631d1d4f26146100fa5780633569ed93146101165780635036759a14610129575b600080fd5b61010360025481565b6040519081526020015b60405180910390f35b610103610124366004610e7b565b610298565b61013c610137366004610ef8565b6102cc565b005b61015161014c366004610f6b565b610423565b604051901515815260200161010d565b61010360045481565b61019d610178366004610e7b565b600960205260009081526040902080546005909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161010d565b6101516101ca366004610f6b565b610496565b61010360015481565b6006546101eb906001600160a01b031681565b6040516001600160a01b03909116815260200161010d565b610232610211366004610e7b565b60086020526000908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161010d565b61013c61025b366004611013565b6104f5565b61010360055481565b6007546101eb906001600160a01b031681565b61010360035481565b610103610293366004610e7b565b61070b565b60006008816102a8600a8561072c565b6102b390600161110b565b8152602001908152602001600020600201549050919050565b600054610100900460ff16158080156102ec5750600054600160ff909116105b806103065750303b158015610306575060005460ff166001145b61036e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610391576000805461ff0019166101001790555b600680546001600160a01b038089166001600160a01b0319928316179092556007805492881692909116919091179055600584905560028290556103d583836107db565b801561041b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b60008061042f87610298565b90508061047e5760405162461bcd60e51b815260206004820152601e60248201527f4e4f5f4556454e545f524f4f545f464f525f424c4f434b5f4e554d42455200006044820152606401610365565b61048b86868387876108b2565b979650505050505050565b6000858152600860205260408120600201548061047e5760405162461bcd60e51b815260206004820152601760248201527f4e4f5f4556454e545f524f4f545f464f525f45504f43480000000000000000006044820152606401610365565b600088876020013589600001358a602001358a600001358b604001358d604001358b8b60405160200161052992919061111e565b60408051601f198184030181528282528051602091820120908301999099528101969096526060860194909452608085019290925260a084015260c083015260e08201526101008101919091526101200160408051601f198184030181528282528051602091820120908301520160408051601f198184030181529082905260065460055463a850a90960e01b8452919350610628926001600160a01b039091169163a850a909916105e091908690600401611181565b6040805180830381865afa1580156105fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062091906111d7565b8785856109cb565b600180546000918261063983611265565b9190505590506106498189610d0b565b8735600081815260086020908152604091829020838155908b01356001820155908a01356002909101558110156106b957600a805460018101825560009190915260208901357fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8909101556106ed565b600a805460208a013591906106d09060019061127e565b815481106106e0576106e0611291565b6000918252602090912001555b60208801356003556106ff86866107db565b50505050505050505050565b600a818154811061071b57600080fd5b600091825260209091200154905081565b8154600090810361073f575060006107d5565b82546000905b8082101561078c5760006107598383610dd2565b6000878152602090209091508590820154111561077857809150610786565b61078381600161110b565b92505b50610745565b6000821180156107b85750836107b5866107a760018661127e565b600091825260209091200190565b54145b156107d1576107c860018361127e565b925050506107d5565b5090505b92915050565b6002819055806000805b828110156108a957600085858381811061080157610801611291565b905060c0020160a001359050600081116108515760405162461bcd60e51b8152602060048201526011602482015270564f54494e475f504f5745525f5a45524f60781b6044820152606401610365565b61085b818461110b565b925085858381811061086f5761086f611291565b905060c0020160096000848152602001908152602001600020818161089491906112be565b90505050806108a290611265565b90506107e5565b50600455505050565b6000816108c0816002611401565b86106109035760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b6044820152606401610365565b8660005b828110156109bd57600086868381811061092357610923611291565b9050602002013590506002896109399190611423565b60000361097157604080516020810185905290810182905260600160405160208183030381529060405280519060200120925061099e565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b6109a960028a611437565b985050806109b690611265565b9050610907565b509094149695505050505050565b6002546109d6610e5d565b6000805b83811015610b81576109ed868683610df4565b15610b795781600003610a41576000818152600960205260409081902081516080810190925260010160048282826020028201915b815481526020019060010190808311610a225750505050509250610b5a565b60008181526009602052604080822081516080810190925260010160048282826020028201915b815481526020019060010190808311610a6857505060075488516020808b01516040808d01516060808f01518b51958c0151848d0151928d01519451630cbe96a560e41b81526004810198909852602488019590955260448701929092526064860191909152608485019390935260a484019190915260c483019190915260e48201529495506001600160a01b03169363cbe96a50935061010401915050608060405180830381865afa158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b47919061144b565b6060880152604087015260208601528452505b600081815260096020526040902060050154610b76908361110b565b91505b6001016109da565b5080600003610bc45760405162461bcd60e51b815260206004820152600f60248201526e4249544d41505f49535f454d50545960881b6044820152606401610365565b60036004546002610bd591906112a7565b610bdf9190611437565b8111610c2d5760405162461bcd60e51b815260206004820152601960248201527f494e53554646494349454e545f564f54494e475f504f574552000000000000006044820152606401610365565b60065460405163ebbdac9160e01b815260009182916001600160a01b039091169063ebbdac9190610c66908b9088908e90600401611481565b6040805180830381865afa158015610c82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca691906114fc565b91509150818015610cb45750805b610d005760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c45440000006044820152606401610365565b505050505050505050565b600082815260086020908152604091829020825160608101845281548082526001830154938201939093526002909101549281019290925282351015610d835760405162461bcd60e51b815260206004820152600d60248201526c0929cac82989288be8aa09e869609b1b6044820152606401610365565b8060200151826020013511610dcd5760405162461bcd60e51b815260206004820152601060248201526f115354151657d0d21150d2d413d2539560821b6044820152606401610365565b505050565b6000610de16002848418611437565b610ded9084841661110b565b9392505050565b600080610e02600884611437565b90506000610e11600885611423565b9050848210610e2557600092505050610ded565b6000600160ff83161b878785818110610e4057610e40611291565b9050013560f81c60f81b60f81c60ff161611925050509392505050565b60405180608001604052806004906020820280368337509192915050565b600060208284031215610e8d57600080fd5b5035919050565b6001600160a01b0381168114610ea957600080fd5b50565b60008083601f840112610ebe57600080fd5b50813567ffffffffffffffff811115610ed657600080fd5b60208301915083602060c083028501011115610ef157600080fd5b9250929050565b600080600080600060808688031215610f1057600080fd5b8535610f1b81610e94565b94506020860135610f2b81610e94565b935060408601359250606086013567ffffffffffffffff811115610f4e57600080fd5b610f5a88828901610eac565b969995985093965092949392505050565b600080600080600060808688031215610f8357600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff80821115610fb057600080fd5b818801915088601f830112610fc457600080fd5b813581811115610fd357600080fd5b8960208260051b8501011115610fe857600080fd5b9699959850939650602001949392505050565b60006060828403121561100d57600080fd5b50919050565b600080600080600080600080610160898b03121561103057600080fd5b883597506110418a60208b01610ffb565b96506110508a60808b01610ffb565b955061012089018a81111561106457600080fd5b60e08a0195503567ffffffffffffffff8082111561108157600080fd5b61108d8c838d01610eac565b90965094506101408b01359150808211156110a757600080fd5b818b0191508b601f8301126110bb57600080fd5b8135818111156110ca57600080fd5b8c60208285010111156110dc57600080fd5b6020830194508093505050509295985092959890939650565b634e487b7160e01b600052601160045260246000fd5b808201808211156107d5576107d56110f5565b60208082528181018390526000908460408401835b8681101561117657823561114681610e94565b6001600160a01b0316825260808385018584013760a0838101359083015260c09283019290910190600101611133565b509695505050505050565b82815260006020604081840152835180604085015260005b818110156111b557858101830151858201606001528201611199565b506000606082860101526060601f19601f830116850101925050509392505050565b6000604082840312156111e957600080fd5b82601f8301126111f857600080fd5b6040516040810181811067ffffffffffffffff8211171561122957634e487b7160e01b600052604160045260246000fd5b806040525080604084018581111561124057600080fd5b845b8181101561125a578051835260209283019201611242565b509195945050505050565b600060018201611277576112776110f5565b5060010190565b818103818111156107d5576107d56110f5565b634e487b7160e01b600052603260045260246000fd5b80820281158282048414176107d5576107d56110f5565b81356112c981610e94565b81546001600160a01b0319166001600160a01b0391909116178155602082810160005b600481101561130c578135600182860181019190915591830191016112ec565b50505060a082013560058201555050565b600181815b8085111561135857816000190482111561133e5761133e6110f5565b8085161561134b57918102915b93841c9390800290611322565b509250929050565b60008261136f575060016107d5565b8161137c575060006107d5565b8160018114611392576002811461139c576113b8565b60019150506107d5565b60ff8411156113ad576113ad6110f5565b50506001821b6107d5565b5060208310610133831016604e8410600b84101617156113db575081810a6107d5565b6113e5838361131d565b80600019048211156113f9576113f96110f5565b029392505050565b6000610ded8383611360565b634e487b7160e01b600052601260045260246000fd5b6000826114325761143261140d565b500690565b6000826114465761144661140d565b500490565b6000806000806080858703121561146157600080fd5b505082516020840151604085015160609095015191969095509092509050565b61010081016040858337604082018460005b60048110156114b2578151835260209283019290910190600101611493565b50505060c082018360005b60028110156114dc5781518352602092830192909101906001016114bd565b505050949350505050565b805180151581146114f757600080fd5b919050565b6000806040838503121561150f57600080fd5b611518836114e7565b9150611526602084016114e7565b9050925092905056fea2646970667358221220a0c0838b66ae5561939526edc9c8be8257337a63060f8b3cb9c0f83765c9510364736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n"
var ExitHelperArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ExitHelper\",\n \"sourceName\": \"contracts/root/ExitHelper.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"success\",\n \"type\": \"bool\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"returnData\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"ExitProcessed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"unhashedLeaf\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"internalType\": \"struct IExitHelper.BatchExitInput[]\",\n \"name\": \"inputs\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"batchExit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"checkpointManager\",\n \"outputs\": [\n {\n \"internalType\": \"contract ICheckpointManager\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"unhashedLeaf\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"exit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract ICheckpointManager\",\n \"name\": \"newCheckpointManager\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"processedExits\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610b6f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806350607b351461005c578063aa209cc314610071578063bd88ea7914610084578063c0857ba0146100bc578063c4d66de8146100e7575b600080fd5b61006f61006a36600461070d565b6100fa565b005b61006f61007f36600461074f565b61022c565b6100a7610092366004610800565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6002546100cf906001600160a01b031681565b6040516001600160a01b0390911681526020016100b3565b61006f6100f5366004610831565b61029c565b6002546001600160a01b03166101575760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a204e4f545f494e495449414c495a4544000000000060448201526064015b60405180910390fd5b8060005b818110156102265761021e84848381811061017857610178610855565b905060200281019061018a919061086b565b3585858481811061019d5761019d610855565b90506020028101906101af919061086b565b602001358686858181106101c5576101c5610855565b90506020028101906101d7919061086b565b6101e590604081019061088b565b8888878181106101f7576101f7610855565b9050602002810190610209919061086b565b6102179060608101906108d2565b600161042e565b60010161015b565b50505050565b6002546001600160a01b03166102845760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a204e4f545f494e495449414c495a45440000000000604482015260640161014e565b610294868686868686600061042e565b505050505050565b600054610100900460ff16158080156102bc5750600054600160ff909116105b806102d65750303b1580156102d6575060005460ff166001145b6103395760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161014e565b6000805460ff19166001179055801561035c576000805461ff0019166101001790555b6001600160a01b0382161580159061037d57506001600160a01b0382163b15155b6103c95760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a20494e56414c49445f414444524553530000000000604482015260640161014e565b600280546001600160a01b0319166001600160a01b038416179055801561042a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600080808061043f888a018a610932565b935093509350935084156104725760008481526001602052604090205460ff161561046d57505050506106b8565b6104dc565b60008481526001602052604090205460ff16156104dc5760405162461bcd60e51b815260206004820152602260248201527f4578697448656c7065723a20455849545f414c52454144595f50524f43455353604482015261115160f21b606482015260840161014e565b6002546040516001600160a01b03909116906361a02208908d90610503908d908d90610a12565b6040519081900381206001600160e01b031960e085901b16825261053092918f908d908d90600401610a22565b602060405180830381865afa15801561054d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105719190610a6f565b6105bd5760405162461bcd60e51b815260206004820152601960248201527f4578697448656c7065723a20494e56414c49445f50524f4f4600000000000000604482015260640161014e565b6000848152600160208190526040808320805460ff19169092179091555181906001600160a01b038516906105fa90889088908790602401610ae1565b60408051601f198184030181529181526020820180516001600160e01b031663f43cda8b60e01b1790525161062f9190610b14565b6000604051808303816000865af19150503d806000811461066c576040519150601f19603f3d011682016040523d82523d6000602084013e610671565b606091505b5091509150811515867f8bbfa0c9bee3785c03700d2a909592286efb83fc7e7002be5764424b9842f7ec836040516106a99190610b26565b60405180910390a35050505050505b50505050505050565b60008083601f8401126106d357600080fd5b50813567ffffffffffffffff8111156106eb57600080fd5b6020830191508360208260051b850101111561070657600080fd5b9250929050565b6000806020838503121561072057600080fd5b823567ffffffffffffffff81111561073757600080fd5b610743858286016106c1565b90969095509350505050565b6000806000806000806080878903121561076857600080fd5b8635955060208701359450604087013567ffffffffffffffff8082111561078e57600080fd5b818901915089601f8301126107a257600080fd5b8135818111156107b157600080fd5b8a60208285010111156107c357600080fd5b6020830196508095505060608901359150808211156107e157600080fd5b506107ee89828a016106c1565b979a9699509497509295939492505050565b60006020828403121561081257600080fd5b5035919050565b6001600160a01b038116811461082e57600080fd5b50565b60006020828403121561084357600080fd5b813561084e81610819565b9392505050565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261088157600080fd5b9190910192915050565b6000808335601e198436030181126108a257600080fd5b83018035915067ffffffffffffffff8211156108bd57600080fd5b60200191503681900382131561070657600080fd5b6000808335601e198436030181126108e957600080fd5b83018035915067ffffffffffffffff82111561090457600080fd5b6020019150600581901b360382131561070657600080fd5b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561094857600080fd5b84359350602085013561095a81610819565b9250604085013561096a81610819565b9150606085013567ffffffffffffffff8082111561098757600080fd5b818701915087601f83011261099b57600080fd5b8135818111156109ad576109ad61091c565b604051601f8201601f19908116603f011681019083821181831017156109d5576109d561091c565b816040528281528a60208487010111156109ee57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b85815284602082015283604082015260806060820152816080820152600060018060fb1b03831115610a5357600080fd5b8260051b808560a08501379190910160a0019695505050505050565b600060208284031215610a8157600080fd5b8151801515811461084e57600080fd5b60005b83811015610aac578181015183820152602001610a94565b50506000910152565b60008151808452610acd816020860160208601610a91565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090610b0b90830184610ab5565b95945050505050565b60008251610881818460208701610a91565b60208152600061084e6020830184610ab556fea2646970667358221220f024c117ff29e95e3e391e2131ae3a5484ff847b61c45d9cfa75dd4b0eef5f8b64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100575760003560e01c806350607b351461005c578063aa209cc314610071578063bd88ea7914610084578063c0857ba0146100bc578063c4d66de8146100e7575b600080fd5b61006f61006a36600461070d565b6100fa565b005b61006f61007f36600461074f565b61022c565b6100a7610092366004610800565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6002546100cf906001600160a01b031681565b6040516001600160a01b0390911681526020016100b3565b61006f6100f5366004610831565b61029c565b6002546001600160a01b03166101575760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a204e4f545f494e495449414c495a4544000000000060448201526064015b60405180910390fd5b8060005b818110156102265761021e84848381811061017857610178610855565b905060200281019061018a919061086b565b3585858481811061019d5761019d610855565b90506020028101906101af919061086b565b602001358686858181106101c5576101c5610855565b90506020028101906101d7919061086b565b6101e590604081019061088b565b8888878181106101f7576101f7610855565b9050602002810190610209919061086b565b6102179060608101906108d2565b600161042e565b60010161015b565b50505050565b6002546001600160a01b03166102845760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a204e4f545f494e495449414c495a45440000000000604482015260640161014e565b610294868686868686600061042e565b505050505050565b600054610100900460ff16158080156102bc5750600054600160ff909116105b806102d65750303b1580156102d6575060005460ff166001145b6103395760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161014e565b6000805460ff19166001179055801561035c576000805461ff0019166101001790555b6001600160a01b0382161580159061037d57506001600160a01b0382163b15155b6103c95760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a20494e56414c49445f414444524553530000000000604482015260640161014e565b600280546001600160a01b0319166001600160a01b038416179055801561042a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600080808061043f888a018a610932565b935093509350935084156104725760008481526001602052604090205460ff161561046d57505050506106b8565b6104dc565b60008481526001602052604090205460ff16156104dc5760405162461bcd60e51b815260206004820152602260248201527f4578697448656c7065723a20455849545f414c52454144595f50524f43455353604482015261115160f21b606482015260840161014e565b6002546040516001600160a01b03909116906361a02208908d90610503908d908d90610a12565b6040519081900381206001600160e01b031960e085901b16825261053092918f908d908d90600401610a22565b602060405180830381865afa15801561054d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105719190610a6f565b6105bd5760405162461bcd60e51b815260206004820152601960248201527f4578697448656c7065723a20494e56414c49445f50524f4f4600000000000000604482015260640161014e565b6000848152600160208190526040808320805460ff19169092179091555181906001600160a01b038516906105fa90889088908790602401610ae1565b60408051601f198184030181529181526020820180516001600160e01b031663f43cda8b60e01b1790525161062f9190610b14565b6000604051808303816000865af19150503d806000811461066c576040519150601f19603f3d011682016040523d82523d6000602084013e610671565b606091505b5091509150811515867f8bbfa0c9bee3785c03700d2a909592286efb83fc7e7002be5764424b9842f7ec836040516106a99190610b26565b60405180910390a35050505050505b50505050505050565b60008083601f8401126106d357600080fd5b50813567ffffffffffffffff8111156106eb57600080fd5b6020830191508360208260051b850101111561070657600080fd5b9250929050565b6000806020838503121561072057600080fd5b823567ffffffffffffffff81111561073757600080fd5b610743858286016106c1565b90969095509350505050565b6000806000806000806080878903121561076857600080fd5b8635955060208701359450604087013567ffffffffffffffff8082111561078e57600080fd5b818901915089601f8301126107a257600080fd5b8135818111156107b157600080fd5b8a60208285010111156107c357600080fd5b6020830196508095505060608901359150808211156107e157600080fd5b506107ee89828a016106c1565b979a9699509497509295939492505050565b60006020828403121561081257600080fd5b5035919050565b6001600160a01b038116811461082e57600080fd5b50565b60006020828403121561084357600080fd5b813561084e81610819565b9392505050565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261088157600080fd5b9190910192915050565b6000808335601e198436030181126108a257600080fd5b83018035915067ffffffffffffffff8211156108bd57600080fd5b60200191503681900382131561070657600080fd5b6000808335601e198436030181126108e957600080fd5b83018035915067ffffffffffffffff82111561090457600080fd5b6020019150600581901b360382131561070657600080fd5b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561094857600080fd5b84359350602085013561095a81610819565b9250604085013561096a81610819565b9150606085013567ffffffffffffffff8082111561098757600080fd5b818701915087601f83011261099b57600080fd5b8135818111156109ad576109ad61091c565b604051601f8201601f19908116603f011681019083821181831017156109d5576109d561091c565b816040528281528a60208487010111156109ee57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b85815284602082015283604082015260806060820152816080820152600060018060fb1b03831115610a5357600080fd5b8260051b808560a08501379190910160a0019695505050505050565b600060208284031215610a8157600080fd5b8151801515811461084e57600080fd5b60005b83811015610aac578181015183820152602001610a94565b50506000910152565b60008151808452610acd816020860160208601610a91565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090610b0b90830184610ab5565b95945050505050565b60008251610881818460208701610a91565b60208152600061084e6020830184610ab556fea2646970667358221220f024c117ff29e95e3e391e2131ae3a5484ff847b61c45d9cfa75dd4b0eef5f8b64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n"
var L2StateSenderArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"L2StateSender\",\n \"sourceName\": \"contracts/child/L2StateSender.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"L2StateSynced\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"counter\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"syncState\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610239806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806316f198311461003b57806361bc221a14610050575b600080fd5b61004e61004936600461011c565b61006b565b005b61005960005481565b60405190815260200160405180910390f35b6108008111156100b65760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b604482015260640160405180910390fd5b826001600160a01b0316336001600160a01b031660008081546100d8906101ad565b9190508190557fedaf3c471ebd67d60c29efe34b639ede7d6a1d92eaeb3f503e784971e67118a5858560405161010f9291906101d4565b60405180910390a4505050565b60008060006040848603121561013157600080fd5b83356001600160a01b038116811461014857600080fd5b9250602084013567ffffffffffffffff8082111561016557600080fd5b818601915086601f83011261017957600080fd5b81358181111561018857600080fd5b87602082850101111561019a57600080fd5b6020830194508093505050509250925092565b6000600182016101cd57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122025c8b63e0888fc8f500a5ce6bf1553db80a3f3339c5c12f5ba280a7b7466c5f664736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100365760003560e01c806316f198311461003b57806361bc221a14610050575b600080fd5b61004e61004936600461011c565b61006b565b005b61005960005481565b60405190815260200160405180910390f35b6108008111156100b65760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b604482015260640160405180910390fd5b826001600160a01b0316336001600160a01b031660008081546100d8906101ad565b9190508190557fedaf3c471ebd67d60c29efe34b639ede7d6a1d92eaeb3f503e784971e67118a5858560405161010f9291906101d4565b60405180910390a4505050565b60008060006040848603121561013157600080fd5b83356001600160a01b038116811461014857600080fd5b9250602084013567ffffffffffffffff8082111561016557600080fd5b818601915086601f83011261017957600080fd5b81358181111561018857600080fd5b87602082850101111561019a57600080fd5b6020830194508093505050509250925092565b6000600182016101cd57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122025c8b63e0888fc8f500a5ce6bf1553db80a3f3339c5c12f5ba280a7b7466c5f664736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n"
diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go
index f553df459f..f3b955c072 100644
--- a/consensus/polybft/polybft.go
+++ b/consensus/polybft/polybft.go
@@ -9,7 +9,6 @@ import (
"time"
"github.com/0xPolygon/polygon-edge/chain"
- "github.com/0xPolygon/polygon-edge/command/rootchain/helper"
"github.com/0xPolygon/polygon-edge/consensus"
"github.com/0xPolygon/polygon-edge/consensus/polybft/wallet"
"github.com/0xPolygon/polygon-edge/contracts"
@@ -112,14 +111,7 @@ type Polybft struct {
func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *state.Transition) error {
return func(transition *state.Transition) error {
- consensusConfigJSON, err := json.Marshal(config.Params.Engine[engineName])
- if err != nil {
- return err
- }
-
- var polyBFTConfig PolyBFTConfig
- err = json.Unmarshal(consensusConfigJSON, &polyBFTConfig)
-
+ polyBFTConfig, err := GetPolyBFTConfig(config)
if err != nil {
return err
}
@@ -134,8 +126,17 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st
return err
}
+ if err != nil {
+ return fmt.Errorf("failed loading rootchain manifest: %w", err)
+ }
+
+ rootchainAdmin := types.ZeroAddress
+ if polyBFTConfig.IsBridgeEnabled() {
+ rootchainAdmin = polyBFTConfig.Bridge.AdminAddress
+ }
+
input, err = nativeTokenInitializer.Encode(
- []interface{}{helper.GetRootchainAdminAddr(), nativeTokenName, nativeTokenSymbol})
+ []interface{}{rootchainAdmin, nativeTokenName, nativeTokenSymbol})
if err != nil {
return err
}
diff --git a/consensus/polybft/polybft_config.go b/consensus/polybft/polybft_config.go
index b19f3d2ea5..6d0bc701a3 100644
--- a/consensus/polybft/polybft_config.go
+++ b/consensus/polybft/polybft_config.go
@@ -3,38 +3,65 @@ package polybft
import (
"encoding/hex"
"encoding/json"
+ "fmt"
"math/big"
+ "os"
+ "path/filepath"
"time"
+ "github.com/0xPolygon/polygon-edge/chain"
bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer"
"github.com/0xPolygon/polygon-edge/types"
)
// PolyBFTConfig is the configuration file for the Polybft consensus protocol.
type PolyBFTConfig struct {
- InitialValidatorSet []*Validator `json:"initialValidatorSet"`
- Bridge *BridgeConfig `json:"bridge"`
+ // InitialValidatorSet are the genesis validators
+ InitialValidatorSet []*Validator `json:"initialValidatorSet"`
- ValidatorSetSize int `json:"validatorSetSize"`
+ // Bridge is the rootchain bridge configuration
+ Bridge *BridgeConfig `json:"bridge"`
- // Address of the system contracts, as of now (testing) this is populated automatically during genesis
- ValidatorSetAddr types.Address `json:"validatorSetAddr"`
- StateReceiverAddr types.Address `json:"stateReceiverAddr"`
+ // EpochSize is size of epoch
+ EpochSize uint64 `json:"epochSize"`
- // size of the epoch and sprint
- EpochSize uint64 `json:"epochSize"`
+ // SprintSize is size of sprint
SprintSize uint64 `json:"sprintSize"`
+ // BlockTime is target frequency of blocks production
BlockTime time.Duration `json:"blockTime"`
// Governance is the initial governance address
Governance types.Address `json:"governance"`
+
+ // TODO: Remove these two addresses as they are hardcoded and known in advance
+ // Address of the system contracts, as of now (testing) this is populated automatically during genesis
+ ValidatorSetAddr types.Address `json:"validatorSetAddr"`
+ StateReceiverAddr types.Address `json:"stateReceiverAddr"`
+}
+
+// GetPolyBFTConfig deserializes provided chain config and returns PolyBFTConfig
+func GetPolyBFTConfig(chainConfig *chain.Chain) (PolyBFTConfig, error) {
+ consensusConfigJSON, err := json.Marshal(chainConfig.Params.Engine["polybft"])
+ if err != nil {
+ return PolyBFTConfig{}, err
+ }
+
+ var polyBFTConfig PolyBFTConfig
+ err = json.Unmarshal(consensusConfigJSON, &polyBFTConfig)
+
+ if err != nil {
+ return PolyBFTConfig{}, err
+ }
+
+ return polyBFTConfig, nil
}
// BridgeConfig is the rootchain bridge configuration
type BridgeConfig struct {
BridgeAddr types.Address `json:"stateSenderAddr"`
CheckpointAddr types.Address `json:"checkpointAddr"`
+ AdminAddress types.Address `json:"adminAddress"`
JSONRPCEndpoint string `json:"jsonRPCEndpoint"`
}
@@ -42,21 +69,23 @@ func (p *PolyBFTConfig) IsBridgeEnabled() bool {
return p.Bridge != nil
}
+// Validator represents public information about validator accounts which are the part of genesis
type Validator struct {
- Address types.Address `json:"address"`
- BlsKey string `json:"blsKey"`
- Balance *big.Int `json:"balance"`
- NodeID string `json:"-"`
+ Address types.Address
+ BlsKey string
+ Balance *big.Int
+ NodeID string
}
type validatorRaw struct {
Address types.Address `json:"address"`
BlsKey string `json:"blsKey"`
Balance *string `json:"balance"`
+ NodeID string `json:"nodeId"`
}
func (v *Validator) MarshalJSON() ([]byte, error) {
- raw := &validatorRaw{Address: v.Address, BlsKey: v.BlsKey}
+ raw := &validatorRaw{Address: v.Address, BlsKey: v.BlsKey, NodeID: v.NodeID}
raw.Balance = types.EncodeBigInt(v.Balance)
return json.Marshal(raw)
@@ -73,6 +102,7 @@ func (v *Validator) UnmarshalJSON(data []byte) error {
v.Address = raw.Address
v.BlsKey = raw.BlsKey
+ v.NodeID = raw.NodeID
v.Balance, err = types.ParseUint256orHex(raw.Balance)
if err != nil {
@@ -92,7 +122,74 @@ func (v *Validator) UnmarshalBLSPublicKey() (*bls.PublicKey, error) {
return bls.UnmarshalPublicKey(decoded)
}
-// DebugConfig is a struct used for test configuration in init genesis
-type DebugConfig struct {
- ValidatorSetSize uint64 `json:"validatorSetSize"`
+// ToValidatorMetadata creates ValidatorMetadata instance
+func (v *Validator) ToValidatorMetadata() (*ValidatorMetadata, error) {
+ blsKey, err := v.UnmarshalBLSPublicKey()
+ if err != nil {
+ return nil, err
+ }
+
+ metadata := &ValidatorMetadata{
+ Address: v.Address,
+ BlsKey: blsKey,
+ VotingPower: chain.ConvertWeiToTokensAmount(v.Balance).Uint64(),
+ }
+
+ return metadata, nil
+}
+
+// RootchainConfig contains information about rootchain contract addresses
+// as well as rootchain admin account address
+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"`
+ AdminAddress types.Address `json:"adminAddress"`
+}
+
+// ToBridgeConfig creates BridgeConfig instance
+func (r *RootchainConfig) ToBridgeConfig() *BridgeConfig {
+ return &BridgeConfig{
+ BridgeAddr: r.StateSenderAddress,
+ CheckpointAddr: r.CheckpointManagerAddress,
+ AdminAddress: r.AdminAddress,
+ }
+}
+
+// Manifest holds metadata, such as genesis validators and rootchain configuration
+type Manifest struct {
+ GenesisValidators []*Validator `json:"validators"`
+ RootchainConfig *RootchainConfig `json:"rootchain"`
+}
+
+// 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)
+ }
+
+ if err := os.WriteFile(filepath.Clean(manifestPath), data, os.ModePerm); err != nil {
+ return fmt.Errorf("failed to save rootchain manifest file: %w", err)
+ }
+
+ return nil
}
diff --git a/consensus/polybft/polybft_test.go b/consensus/polybft/polybft_test.go
index 766f7e7a0c..6096f916f2 100644
--- a/consensus/polybft/polybft_test.go
+++ b/consensus/polybft/polybft_test.go
@@ -24,10 +24,7 @@ import (
func TestPolybft_VerifyHeader(t *testing.T) {
t.Parallel()
- const (
- allValidatorsSize = 6 // overall there are 6 validators
- validatorSetSize = 5 // only 5 validators are active at the time
- )
+ const validatorSetSize = 6 // overall there are 6 validators
updateHeaderExtra := func(header *types.Header,
validators *ValidatorSetDelta,
@@ -61,14 +58,13 @@ func TestPolybft_VerifyHeader(t *testing.T) {
}
// create all valdators
- validators := newTestValidators(allValidatorsSize)
+ validators := newTestValidators(validatorSetSize)
// create configuration
polyBftConfig := PolyBFTConfig{
InitialValidatorSet: validators.getParamValidators(),
EpochSize: 10,
SprintSize: 5,
- ValidatorSetSize: validatorSetSize,
}
validatorSet := validators.getPublicIdentities()
diff --git a/e2e-polybft/README.md b/e2e-polybft/README.md
index 17822a2a0f..a74ceefa23 100644
--- a/e2e-polybft/README.md
+++ b/e2e-polybft/README.md
@@ -1,7 +1,7 @@
# End-to-End testing
-The implemented E2E tests start a local instance of V3.
+The implemented E2E tests start a local instance of Polybft consensus protocol.
As such, they require the binary 'polygon-edge' to be available in the $PATH variable.
diff --git a/e2e-polybft/bridge_test.go b/e2e-polybft/bridge_test.go
index e8b442cde6..78e0e8a2a4 100644
--- a/e2e-polybft/bridge_test.go
+++ b/e2e-polybft/bridge_test.go
@@ -7,14 +7,15 @@ import (
"io"
"math/big"
"net/http"
+ "path"
"strings"
"testing"
"time"
+ "github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact"
rootchainHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper"
- "github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
"github.com/0xPolygon/polygon-edge/contracts"
@@ -44,6 +45,8 @@ type ResultEventStatus uint8
const (
ResultEventSuccess ResultEventStatus = iota
ResultEventFailure
+
+ manifestFileName = "manifest.json"
)
// checkLogs is helper function which parses given ResultEvent event's logs,
@@ -181,11 +184,6 @@ func TestE2E_Bridge_MainWorkflow(t *testing.T) {
}
func TestE2E_CheckpointSubmission(t *testing.T) {
- var (
- rootchainSender = rootchainHelper.GetRootchainAdminKey().Address()
- checkpointManagerAddr = ethgo.Address(rootchainHelper.CheckpointManagerAddress)
- )
-
// spin up a cluster with epoch size set to 5 blocks
cluster := framework.NewTestCluster(t, 5, framework.WithBridge(), framework.WithEpochSize(5))
defer cluster.Stop()
@@ -197,6 +195,12 @@ func TestE2E_CheckpointSubmission(t *testing.T) {
checkpointBlockNumInput, err := currentCheckpointBlockNumMethod.Encode([]interface{}{})
require.NoError(t, err)
+ manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName))
+ require.NoError(t, err)
+
+ checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress)
+ rootchainSender := ethgo.Address(manifest.RootchainConfig.AdminAddress)
+
testCheckpointBlockNumber := func(expectedCheckpointBlock int64) (bool, error) {
checkpointBlockNumRaw, err := rootchainTxRelayer.Call(rootchainSender, checkpointManagerAddr, checkpointBlockNumInput)
if err != nil {
@@ -239,36 +243,48 @@ func TestE2E_CheckpointSubmission(t *testing.T) {
}
func TestE2E_Bridge_L2toL1Exit(t *testing.T) {
- key, err := ethgow.GenerateKey()
+ sidechainKey, err := ethgow.GenerateKey()
+ require.NoError(t, err)
+
+ // initialize rootchain admin key to default one
+ err = rootchainHelper.InitRootchainAdminKey("")
require.NoError(t, err)
cluster := framework.NewTestCluster(t, 5,
framework.WithBridge(),
- framework.WithPremine(types.Address(key.Address())),
+ framework.WithPremine(types.Address(sidechainKey.Address())),
)
defer cluster.Stop()
+ manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName))
+ require.NoError(t, err)
+
+ checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress)
+ exitHelperAddr := ethgo.Address(manifest.RootchainConfig.ExitHelperAddress)
+ adminAddr := ethgo.Address(manifest.RootchainConfig.AdminAddress)
+
// wait for a couple of blocks
require.NoError(t, cluster.WaitForBlock(2, 2*time.Minute))
- //init rpc clients
- txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(txrelayer.DefaultRPCAddress))
+ // init rpc clients
+ l1TxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(txrelayer.DefaultRPCAddress))
require.NoError(t, err)
- l2Relayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Servers[0].JSONRPCAddr()))
+ l2TxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Servers[0].JSONRPCAddr()))
require.NoError(t, err)
- //deploy l1,l2, ExitHelper contracts
- receipt, err := DeployTransaction(txRelayer, rootchainHelper.GetRootchainAdminKey(), contractsapi.L1ExitTestBytecode)
+ // deploy L1ExitTest contract
+ receipt, err := l1TxRelayer.SendTransaction(ðgo.Transaction{Input: contractsapi.L1ExitTestBytecode},
+ rootchainHelper.GetRootchainAdminKey())
require.NoError(t, err)
+ require.Equal(t, receipt.Status, uint64(types.ReceiptSuccess))
- l1ContractAddress := receipt.ContractAddress
+ l1ExitTestAddr := receipt.ContractAddress
l2StateSenderAddress := ethgo.Address(contracts.L2StateSenderContract)
- checkpointManagerAddress := ethgo.Address(rootchainHelper.CheckpointManagerAddress)
- //Start test
- //send crosschain transaction on l2 and get exit id
+ // Start test
+ // send crosschain transaction on l2 and get exit id
stateSenderData := []byte{123}
- receipt, err = ABITransaction(l2Relayer, key, contractsapi.L2StateSender, l2StateSenderAddress, "syncState", l1ContractAddress, stateSenderData)
+ receipt, err = ABITransaction(l2TxRelayer, sidechainKey, contractsapi.L2StateSender, l2StateSenderAddress, "syncState", l1ExitTestAddr, stateSenderData)
require.NoError(t, err)
require.Equal(t, receipt.Status, uint64(types.ReceiptSuccess))
l2SenderBlock := receipt.BlockNumber
@@ -284,15 +300,15 @@ func TestE2E_Bridge_L2toL1Exit(t *testing.T) {
extra, err := polybft.GetIbftExtra(l2SenderBlockData.ExtraData)
require.NoError(t, err)
- receipt, err = ABITransaction(l2Relayer, key, contractsapi.L2StateSender, l2StateSenderAddress, "syncState", l1ContractAddress, stateSenderData)
+ receipt, err = ABITransaction(l2TxRelayer, sidechainKey, contractsapi.L2StateSender, l2StateSenderAddress, "syncState", l1ExitTestAddr, stateSenderData)
require.Equal(t, receipt.Status, uint64(types.ReceiptSuccess))
require.NoError(t, err)
- //wait when a new checkpoint will be accepted
+ // wait when a new checkpoint will be accepted
fail := 0
for range time.Tick(time.Second) {
- currentEpochString, err := ABICall(txRelayer, contractsapi.CheckpointManager, checkpointManagerAddress, "currentEpoch")
+ currentEpochString, err := ABICall(l1TxRelayer, contractsapi.CheckpointManager, checkpointManagerAddr, adminAddr, "currentEpoch")
require.NoError(t, err)
currentEpoch, err := types.ParseUint64orHex(¤tEpochString)
@@ -313,13 +329,13 @@ func TestE2E_Bridge_L2toL1Exit(t *testing.T) {
proofExitEventEncoded, err := polybft.ExitEventABIType.Encode(&polybft.ExitEvent{
ID: 1,
- Sender: key.Address(),
- Receiver: l1ContractAddress,
+ Sender: sidechainKey.Address(),
+ Receiver: l1ExitTestAddr,
Data: stateSenderData,
})
require.NoError(t, err)
- _, err = ABITransaction(txRelayer, rootchainHelper.GetRootchainAdminKey(), contractsapi.ExitHelper, rootchainHelper.ExitHelperAddress,
+ receipt, err = ABITransaction(l1TxRelayer, rootchainHelper.GetRootchainAdminKey(), contractsapi.ExitHelper, exitHelperAddr,
"exit",
big.NewInt(int64(extra.Checkpoint.EpochNumber*10)),
proof.LeafIndex,
@@ -327,8 +343,9 @@ func TestE2E_Bridge_L2toL1Exit(t *testing.T) {
proof.Proof,
)
require.NoError(t, err)
+ require.Equal(t, receipt.Status, uint64(types.ReceiptSuccess))
- res, err := ABICall(txRelayer, contractsapi.ExitHelper, rootchainHelper.ExitHelperAddress, "processedExits", big.NewInt(1))
+ res, err := ABICall(l1TxRelayer, contractsapi.ExitHelper, exitHelperAddr, adminAddr, "processedExits", big.NewInt(1))
require.NoError(t, err)
parserRes, err := types.ParseUint64orHex(&res)
require.NoError(t, err)
@@ -375,14 +392,15 @@ func getExitProof(rpcAddress string, exitID, epoch, checkpointBlock uint64) (typ
return rspProof.Result, nil
}
-func ABICall(relayer txrelayer.TxRelayer, artifact *artifact.Artifact, contractAddress ethgo.Address, method string, params ...interface{}) (string, error) {
+func ABICall(relayer txrelayer.TxRelayer, artifact *artifact.Artifact, contractAddress ethgo.Address, senderAddr ethgo.Address, method string, params ...interface{}) (string, error) {
input, err := artifact.Abi.GetMethod(method).Encode(params)
if err != nil {
return "", err
}
- return relayer.Call(ethgo.Address(rootchainHelper.GetRootchainAdminAddr()), contractAddress, input)
+ return relayer.Call(senderAddr, contractAddress, input)
}
+
func ABITransaction(relayer txrelayer.TxRelayer, key ethgo.Key, artifact *artifact.Artifact, contractAddress ethgo.Address, method string, params ...interface{}) (*ethgo.Receipt, error) {
input, err := artifact.Abi.GetMethod(method).Encode(params)
if err != nil {
@@ -394,9 +412,3 @@ func ABITransaction(relayer txrelayer.TxRelayer, key ethgo.Key, artifact *artifa
Input: input,
}, key)
}
-
-func DeployTransaction(relayer txrelayer.TxRelayer, key ethgo.Key, bytecode []byte) (*ethgo.Receipt, error) {
- return relayer.SendTransaction(ðgo.Transaction{
- Input: bytecode,
- }, key)
-}
diff --git a/e2e-polybft/framework/test-bridge.go b/e2e-polybft/framework/test-bridge.go
index 98408fdea3..2ce89a0325 100644
--- a/e2e-polybft/framework/test-bridge.go
+++ b/e2e-polybft/framework/test-bridge.go
@@ -60,14 +60,12 @@ func (t *TestBridge) Start() error {
return nil
}
-func (t *TestBridge) deployRootchainContracts(genesisPath string) error {
+func (t *TestBridge) deployRootchainContracts(manifestPath string) error {
args := []string{
"rootchain",
"init-contracts",
"--path", t.clusterConfig.ContractsDir,
- "--validator-path", t.clusterConfig.TmpDir,
- "--validator-prefix", t.clusterConfig.ValidatorPrefix,
- "--genesis-path", genesisPath,
+ "--manifest", manifestPath,
}
err := runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("bridge"))
diff --git a/e2e-polybft/framework/test-cluster.go b/e2e-polybft/framework/test-cluster.go
index 248ecdf779..ad91004a84 100644
--- a/e2e-polybft/framework/test-cluster.go
+++ b/e2e-polybft/framework/test-cluster.go
@@ -228,6 +228,13 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T
require.NoError(t, err)
}
+ manifestPath := path.Join(tmpDir, "manifest.json")
+ // run manifest file creation
+ cluster.cmdRun("manifest",
+ "--path", manifestPath,
+ "--validators-path", tmpDir,
+ "--validators-prefix", cluster.Config.ValidatorPrefix)
+
if cluster.Config.HasBridge {
// start bridge
cluster.Bridge, err = NewTestBridge(t, cluster.Config)
@@ -239,13 +246,21 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T
cluster.Config.ValidatorSetSize = uint64(validatorsCount)
}
- genesisPath := path.Join(tmpDir, "genesis.json")
+ if cluster.Config.HasBridge {
+ err := cluster.Bridge.deployRootchainContracts(manifestPath)
+ require.NoError(t, err)
+
+ err = cluster.Bridge.fundValidators()
+ require.NoError(t, err)
+ }
+
{
// run genesis configuration population
args := []string{
"genesis",
+ "--manifest", manifestPath,
"--consensus", "polybft",
- "--dir", genesisPath,
+ "--dir", path.Join(tmpDir, "genesis.json"),
"--contracts-path", defaultContractsPath,
"--epoch-size", strconv.Itoa(cluster.Config.EpochSize),
"--premine", "0x0000000000000000000000000000000000000000",
@@ -293,14 +308,6 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T
require.NoError(t, err)
}
- if cluster.Config.HasBridge {
- err := cluster.Bridge.deployRootchainContracts(genesisPath)
- require.NoError(t, err)
-
- err = cluster.Bridge.fundValidators()
- require.NoError(t, err)
- }
-
for i := 1; i <= int(cluster.Config.ValidatorSetSize); i++ {
cluster.initTestServer(t, i, true)
}
@@ -375,6 +382,7 @@ func (c *TestCluster) EmitTransfer(contractAddress, walletAddresses, amounts str
return c.cmdRun("rootchain",
"emit",
+ "--manifest", path.Join(c.Config.TmpDir, "manifest.json"),
"--contract", contractAddress,
"--wallets", walletAddresses,
"--amounts", amounts)
diff --git a/scripts/cluster b/scripts/cluster
index 2cc04c8b08..e941a84996 100755
--- a/scripts/cluster
+++ b/scripts/cluster
@@ -5,6 +5,7 @@ set -e
# Reset test-dirs
rm -rf test-chain-*
rm -f genesis.json
+rm -f manifest.json
go build -o polygon-edge .
@@ -18,6 +19,7 @@ else
echo "Running with polybft consensus"
genesis_params="--consensus polybft --validator-set-size=4 --bridge-json-rpc http://127.0.0.1:8545"
./polygon-edge polybft-secrets --data-dir test-chain- --num 4
+ ./polygon-edge manifest
fi
./polygon-edge genesis $genesis_params \