Skip to content

Commit

Permalink
Merge pull request #354 from multiversx/fix-migration-app
Browse files Browse the repository at this point in the history
Fixed the migration app to use the correct batch ID
  • Loading branch information
iulianpascalau authored Oct 15, 2024
2 parents af47429 + 750efde commit 5c14856
Show file tree
Hide file tree
Showing 4 changed files with 340 additions and 91 deletions.
49 changes: 23 additions & 26 deletions cmd/migration/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ const (
var log = logger.GetOrCreate("main")

type internalComponents struct {
batch *ethereum.BatchInfo
cryptoHandler ethereumClient.CryptoHandler
ethClient *ethclient.Client
batch *ethereum.BatchInfo
cryptoHandler ethereumClient.CryptoHandler
ethClient *ethclient.Client
ethereumChainWrapper ethereum.EthereumChainWrapper
}

func main() {
Expand Down Expand Up @@ -90,7 +91,6 @@ func execute(ctx *cli.Context) error {
operationMode := strings.ToLower(ctx.GlobalString(mode.Name))
switch operationMode {
case signMode:

_, err = generateAndSign(ctx, cfg)
return err
case executeMode:
Expand Down Expand Up @@ -153,7 +153,19 @@ func generateAndSign(ctx *cli.Context, cfg config.MigrationToolConfig) (*interna
}

safeEthAddress := common.HexToAddress(cfg.Eth.SafeContractAddress)
safeInstance, err := contract.NewERC20Safe(safeEthAddress, ethClient)

bridgeEthAddress := common.HexToAddress(cfg.Eth.MultisigContractAddress)
multiSigInstance, err := contract.NewBridge(bridgeEthAddress, ethClient)
if err != nil {
return nil, err
}

argsClientWrapper := bridgeV2Wrappers.ArgsEthereumChainWrapper{
StatusHandler: &disabled.StatusHandler{},
MultiSigContract: multiSigInstance,
BlockchainClient: ethClient,
}
ethereumChainWrapper, err := bridgeV2Wrappers.NewEthereumChainWrapper(argsClientWrapper)
if err != nil {
return nil, err
}
Expand All @@ -162,7 +174,7 @@ func generateAndSign(ctx *cli.Context, cfg config.MigrationToolConfig) (*interna
MvxDataGetter: mxDataGetter,
Erc20ContractsHolder: erc20ContractsHolder,
SafeContractAddress: safeEthAddress,
SafeContractWrapper: safeInstance,
EthereumChainWrapper: ethereumChainWrapper,
Logger: log,
}

Expand Down Expand Up @@ -235,9 +247,10 @@ func generateAndSign(ctx *cli.Context, cfg config.MigrationToolConfig) (*interna
}

return &internalComponents{
batch: batchInfo,
cryptoHandler: cryptoHandler,
ethClient: ethClient,
batch: batchInfo,
cryptoHandler: cryptoHandler,
ethClient: ethClient,
ethereumChainWrapper: ethereumChainWrapper,
}, nil
}

Expand All @@ -247,22 +260,6 @@ func executeTransfer(ctx *cli.Context, cfg config.MigrationToolConfig) error {
return err
}

bridgeEthAddress := common.HexToAddress(cfg.Eth.MultisigContractAddress)
multiSigInstance, err := contract.NewBridge(bridgeEthAddress, components.ethClient)
if err != nil {
return err
}

argsClientWrapper := bridgeV2Wrappers.ArgsEthereumChainWrapper{
StatusHandler: &disabled.StatusHandler{},
MultiSigContract: multiSigInstance,
BlockchainClient: components.ethClient,
}
ethereumChainWrapper, err := bridgeV2Wrappers.NewEthereumChainWrapper(argsClientWrapper)
if err != nil {
return err
}

gasStationConfig := cfg.Eth.GasStation
argsGasStation := gasManagement.ArgsGasStation{
RequestURL: gasStationConfig.URL,
Expand All @@ -280,7 +277,7 @@ func executeTransfer(ctx *cli.Context, cfg config.MigrationToolConfig) error {
}

args := ethereum.ArgsMigrationBatchExecutor{
EthereumChainWrapper: ethereumChainWrapper,
EthereumChainWrapper: components.ethereumChainWrapper,
CryptoHandler: components.cryptoHandler,
Batch: *components.batch,
Signatures: ethereum.LoadAllSignatures(log, configPath),
Expand Down
1 change: 1 addition & 0 deletions executors/ethereum/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type EthereumChainWrapper interface {
NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
Quorum(ctx context.Context) (*big.Int, error)
GetRelayers(ctx context.Context) ([]common.Address, error)
WasBatchExecuted(ctx context.Context, batchNonce *big.Int) (bool, error)
IsPaused(ctx context.Context) (bool, error)
}

Expand Down
106 changes: 90 additions & 16 deletions executors/ethereum/migrationBatchCreator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"fmt"
"math/big"
"strings"
"time"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/multiversx/mx-bridge-eth-go/clients/ethereum"
"github.com/multiversx/mx-bridge-eth-go/core/batchProcessor"
Expand All @@ -17,20 +17,22 @@ import (

var zero = big.NewInt(0)

const timeBetweenBatchIDChecks = time.Millisecond * 100

// ArgsMigrationBatchCreator is the argument for the NewMigrationBatchCreator constructor
type ArgsMigrationBatchCreator struct {
MvxDataGetter MvxDataGetter
Erc20ContractsHolder Erc20ContractsHolder
SafeContractAddress common.Address
SafeContractWrapper SafeContractWrapper
EthereumChainWrapper EthereumChainWrapper
Logger logger.Logger
}

type migrationBatchCreator struct {
mvxDataGetter MvxDataGetter
erc20ContractsHolder Erc20ContractsHolder
safeContractAddress common.Address
safeContractWrapper SafeContractWrapper
ethereumChainWrapper EthereumChainWrapper
logger logger.Logger
}

Expand All @@ -42,8 +44,8 @@ func NewMigrationBatchCreator(args ArgsMigrationBatchCreator) (*migrationBatchCr
if check.IfNil(args.Erc20ContractsHolder) {
return nil, errNilErc20ContractsHolder
}
if check.IfNilReflect(args.SafeContractWrapper) {
return nil, errNilSafeContractWrapper
if check.IfNilReflect(args.EthereumChainWrapper) {
return nil, errNilEthereumChainWrapper
}
if check.IfNil(args.Logger) {
return nil, errNilLogger
Expand All @@ -53,26 +55,28 @@ func NewMigrationBatchCreator(args ArgsMigrationBatchCreator) (*migrationBatchCr
mvxDataGetter: args.MvxDataGetter,
erc20ContractsHolder: args.Erc20ContractsHolder,
safeContractAddress: args.SafeContractAddress,
safeContractWrapper: args.SafeContractWrapper,
logger: args.Logger,
ethereumChainWrapper: args.EthereumChainWrapper,
}, nil
}

// CreateBatchInfo creates an instance of type BatchInfo
func (creator *migrationBatchCreator) CreateBatchInfo(ctx context.Context, newSafeAddress common.Address, trimAmount core.OptionalUint64) (*BatchInfo, error) {
creator.logger.Info("started the batch creation process...")

batchesCount, err := creator.safeContractWrapper.BatchesCount(&bind.CallOpts{Context: ctx})
if err != nil {
return nil, err
}
depositStart := uint64(0) // deposits inside a batch are not tracked, we can start from 0

creator.logger.Info("will try to find a usable batch ID, please wait, this might take a while...")

depositsCount, err := creator.safeContractWrapper.DepositsCount(&bind.CallOpts{Context: ctx})
startTime := time.Now()
freeBatchID, err := creator.findAnUsableBatchID(ctx, timeBetweenBatchIDChecks)
endTime := time.Now()
if err != nil {
return nil, err
}

creator.logger.Info("fetched Ethereum contracts state", "batches count", batchesCount, "deposits count", depositsCount)
creator.logger.Info("fetched Ethereum contracts state",
"free batch ID", freeBatchID, "time took", endTime.Sub(startTime))

tokensList, err := creator.getTokensList(ctx)
if err != nil {
Expand All @@ -81,7 +85,7 @@ func (creator *migrationBatchCreator) CreateBatchInfo(ctx context.Context, newSa

creator.logger.Info("fetched known tokens", "tokens", strings.Join(tokensList, ", "))

deposits, err := creator.fetchERC20ContractsAddresses(ctx, tokensList, depositsCount)
deposits, err := creator.fetchERC20ContractsAddresses(ctx, tokensList, depositStart)
if err != nil {
return nil, err
}
Expand All @@ -95,7 +99,77 @@ func (creator *migrationBatchCreator) CreateBatchInfo(ctx context.Context, newSa

creator.logger.Info("fetched balances contract addresses")

return creator.assembleBatchInfo(batchesCount, deposits, newSafeAddress)
return creator.assembleBatchInfo(freeBatchID, deposits, newSafeAddress)
}

func (creator *migrationBatchCreator) findAnUsableBatchID(ctx context.Context, timeBetweenChecks time.Duration) (uint64, error) {
highBatchID := uint64(100000)
lowBatchID := uint64(1)
increaseHigh := uint64(100000)

batchesUsedMap := make(map[uint64]bool)
for {
err := creator.checkAvailableBatch(ctx, highBatchID, batchesUsedMap, timeBetweenChecks)
if err != nil {
return 0, err
}

err = creator.checkAvailableBatch(ctx, lowBatchID, batchesUsedMap, timeBetweenChecks)
if err != nil {
return 0, err
}

if !batchesUsedMap[lowBatchID] {
// beginning of the interval optimization
return lowBatchID, nil
}

if batchesUsedMap[highBatchID] && batchesUsedMap[lowBatchID] {
// high was too low
highBatchID += increaseHigh
continue
}

mid := (highBatchID + lowBatchID) / 2
if mid == lowBatchID {
// high and low are so close that their middle value between them is actually the low value, return high
return highBatchID, nil
}

err = creator.checkAvailableBatch(ctx, mid, batchesUsedMap, timeBetweenChecks)
if err != nil {
return 0, err
}

if batchesUsedMap[mid] {
// the middle value was set, bring the low value to it and restart the checking process
lowBatchID = mid
} else {
// the middle value was not set, bring the high value to it and restart the checking process
highBatchID = mid
}
}
}

func (creator *migrationBatchCreator) checkAvailableBatch(
ctx context.Context,
batchID uint64,
batchesUsedMap map[uint64]bool,
timeBetweenChecks time.Duration,
) error {
_, checked := batchesUsedMap[batchID]
if checked {
return nil
}

time.Sleep(timeBetweenChecks)
wasExecuted, err := creator.ethereumChainWrapper.WasBatchExecuted(ctx, big.NewInt(0).SetUint64(batchID))
if err != nil {
return err
}

batchesUsedMap[batchID] = wasExecuted
return nil
}

func (creator *migrationBatchCreator) getTokensList(ctx context.Context) ([]string, error) {
Expand Down Expand Up @@ -165,11 +239,11 @@ func (creator *migrationBatchCreator) fetchBalances(ctx context.Context, deposit
return nil
}

func (creator *migrationBatchCreator) assembleBatchInfo(batchesCount uint64, deposits []*DepositInfo, newSafeAddress common.Address) (*BatchInfo, error) {
func (creator *migrationBatchCreator) assembleBatchInfo(usableBatchID uint64, deposits []*DepositInfo, newSafeAddress common.Address) (*BatchInfo, error) {
batchInfo := &BatchInfo{
OldSafeContractAddress: creator.safeContractAddress.String(),
NewSafeContractAddress: newSafeAddress.String(),
BatchID: batchesCount + 1,
BatchID: usableBatchID,
DepositsInfo: make([]*DepositInfo, 0, len(deposits)),
}

Expand Down
Loading

0 comments on commit 5c14856

Please sign in to comment.