Skip to content

Commit

Permalink
Parallelize bootstrap rootchain CLI commands (#1468)
Browse files Browse the repository at this point in the history
* Paralelize fund command

* Paralelize rootchain contract deployment

* Parallelize rootchain contracts initialization

* Decrease timeout to 1h
  • Loading branch information
Stefan-Ethernal committed May 5, 2023
1 parent 25eb3a2 commit 5826c7e
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 232 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ test-e2e-polybft:
# We can not build with race because of a bug in boltdb dependency
go build -o artifacts/polygon-edge .
env EDGE_BINARY=${PWD}/artifacts/polygon-edge E2E_TESTS=true E2E_LOGS=true \
go test -v -timeout=1h30m ./e2e-polybft/e2e/...
go test -v -timeout=1h ./e2e-polybft/e2e/...

.PHONY: test-property-polybft
test-property-polybft:
Expand Down
157 changes: 112 additions & 45 deletions command/rootchain/deploy/deploy.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package deploy

import (
"context"
"errors"
"fmt"
"math/big"

"github.com/spf13/cobra"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/jsonrpc"
"golang.org/x/sync/errgroup"

"github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/command"
Expand Down Expand Up @@ -98,6 +100,53 @@ var (
rootchainConfig.StakeManagerAddress = addr
},
}

// initializersMap maps rootchain contract names to initializer function callbacks
initializersMap = map[string]func(command.OutputFormatter, txrelayer.TxRelayer,
*polybft.RootchainConfig, ethgo.Key) error{
stakeManagerName: func(fmt command.OutputFormatter,
relayer txrelayer.TxRelayer,
config *polybft.RootchainConfig,
key ethgo.Key) error {

return initializeStakeManager(fmt, relayer, config, key)
},
customSupernetManagerName: func(fmt command.OutputFormatter,
relayer txrelayer.TxRelayer,
config *polybft.RootchainConfig,
key ethgo.Key) error {

return initializeSupernetManager(fmt, relayer, config, key)
},
exitHelperName: func(fmt command.OutputFormatter,
relayer txrelayer.TxRelayer,
config *polybft.RootchainConfig,
key ethgo.Key) error {

return initializeExitHelper(fmt, relayer, config, key)
},
rootERC20PredicateName: func(fmt command.OutputFormatter,
relayer txrelayer.TxRelayer,
config *polybft.RootchainConfig,
key ethgo.Key) error {

return initializeRootERC20Predicate(fmt, relayer, config, key)
},
rootERC721PredicateName: func(fmt command.OutputFormatter,
relayer txrelayer.TxRelayer,
config *polybft.RootchainConfig,
key ethgo.Key) error {

return initializeRootERC721Predicate(fmt, relayer, config, key)
},
rootERC1155PredicateName: func(fmt command.OutputFormatter,
relayer txrelayer.TxRelayer,
config *polybft.RootchainConfig,
key ethgo.Key) error {

return initializeRootERC1155Predicate(fmt, relayer, config, key)
},
}
)

// GetCommand returns the rootchain deploy command
Expand Down Expand Up @@ -213,7 +262,7 @@ func runCommand(cmd *cobra.Command, _ []string) {
}
}

rootchainCfg, chainID, err := deployContracts(outputter, client, consensusConfig.InitialValidatorSet)
rootchainCfg, chainID, err := deployContracts(outputter, client, consensusConfig.InitialValidatorSet, cmd.Context())
if err != nil {
outputter.SetError(fmt.Errorf("failed to deploy rootchain contracts: %w", err))

Expand Down Expand Up @@ -253,8 +302,7 @@ func runCommand(cmd *cobra.Command, _ []string) {

// deployContracts deploys and initializes rootchain smart contracts
func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client,
initialValidators []*polybft.Validator) (*polybft.RootchainConfig, int64, error) {
// if the bridge contract is not created, we have to deploy all the contracts
initialValidators []*polybft.Validator, cmdCtx context.Context) (*polybft.RootchainConfig, int64, error) {
txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(client))
if err != nil {
return nil, 0, fmt.Errorf("failed to initialize tx relayer: %w", err)
Expand Down Expand Up @@ -378,43 +426,82 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client,

allContracts = append(tokenContracts, allContracts...)

for _, contract := range allContracts {
txn := &ethgo.Transaction{
To: nil, // contract deployment
Input: contract.artifact.Bytecode,
}
g, ctx := errgroup.WithContext(cmdCtx)
resultsCh := make(chan *deployContractResult, len(allContracts))

receipt, err := txRelayer.SendTransaction(txn, deployerKey)
if err != nil {
return nil, 0, err
}
for _, contract := range allContracts {
contract := contract

g.Go(func() error {
select {
case <-ctx.Done():
return ctx.Err()
default:
txn := &ethgo.Transaction{
To: nil, // contract deployment
Input: contract.artifact.Bytecode,
}

receipt, err := txRelayer.SendTransaction(txn, deployerKey)
if err != nil {
return err
}

if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) {
return fmt.Errorf("deployment of %s contract failed", contract.name)
}

resultsCh <- newDeployContractsResult(contract.name,
types.Address(receipt.ContractAddress),
receipt.TransactionHash)

return nil
}
})
}

if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) {
return nil, 0, fmt.Errorf("deployment of %s contract failed", contract.name)
}
if err := g.Wait(); err != nil {
return nil, 0, err
}

contractAddr := types.Address(receipt.ContractAddress)
close(resultsCh)

populatorFn, ok := metadataPopulatorMap[contract.name]
for result := range resultsCh {
populatorFn, ok := metadataPopulatorMap[result.Name]
if !ok {
return nil, 0, fmt.Errorf("rootchain metadata populator not registered for contract '%s'", contract.name)
return nil, 0, fmt.Errorf("rootchain metadata populator not registered for contract '%s'", result.Name)
}

populatorFn(rootchainConfig, contractAddr)
populatorFn(rootchainConfig, result.Address)

outputter.WriteCommandResult(newDeployContractsResult(contract.name, contractAddr, receipt.TransactionHash))
outputter.WriteCommandResult(result)
}

// init StakeManager
if err := initializeStakeManager(outputter, txRelayer, rootchainConfig, deployerKey); err != nil {
return nil, 0, err
g, ctx = errgroup.WithContext(cmdCtx)

for _, contract := range allContracts {
contract := contract

initializer, exists := initializersMap[contract.name]
if !exists {
continue
}

g.Go(func() error {
select {
case <-cmdCtx.Done():
return cmdCtx.Err()
default:
return initializer(outputter, txRelayer, rootchainConfig, deployerKey)
}
})
}

// init SupernetManager
if err := initializeSupernetManager(outputter, txRelayer, rootchainConfig, deployerKey); err != nil {
if err := g.Wait(); err != nil {
return nil, 0, err
}

// register supernets manager on stake manager
chainID, err := registerChainOnStakeManager(txRelayer, rootchainConfig, deployerKey)
if err != nil {
return nil, 0, err
Expand All @@ -426,26 +513,6 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client,
return nil, 0, err
}

// init ExitHelper
if err := initializeExitHelper(outputter, txRelayer, rootchainConfig, deployerKey); err != nil {
return nil, 0, err
}

// init RootERC20Predicate
if err := initializeRootERC20Predicate(outputter, txRelayer, rootchainConfig, deployerKey); err != nil {
return nil, 0, err
}

// init RootERC721Predicate
if err := initializeRootERC721Predicate(outputter, txRelayer, rootchainConfig, deployerKey); err != nil {
return nil, 0, err
}

// init RootERC1155Predicate
if err := initializeRootERC1155Predicate(outputter, txRelayer, rootchainConfig, deployerKey); err != nil {
return rootchainConfig, 0, err
}

return rootchainConfig, chainID, nil
}

Expand Down
3 changes: 2 additions & 1 deletion command/rootchain/deploy/deploy_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package deploy

import (
"context"
"os"
"testing"

Expand Down Expand Up @@ -37,7 +38,7 @@ func TestDeployContracts_NoPanics(t *testing.T) {
outputter := command.InitializeOutputter(GetCommand())

require.NotPanics(t, func() {
_, _, err = deployContracts(outputter, client, []*polybft.Validator{})
_, _, err = deployContracts(outputter, client, []*polybft.Validator{}, context.Background())
})
require.NoError(t, err)
}

0 comments on commit 5826c7e

Please sign in to comment.