Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Merge v3 feat native esdts #280

Merged
merged 39 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4e83b8c
sc proposal step implementation
ccorcoveanu Nov 22, 2023
ea04012
add sign action step
ccorcoveanu Nov 28, 2023
0fcd4cc
improved steps ordering
ccorcoveanu Nov 28, 2023
873f58a
added logic to reuse the same perform
ccorcoveanu Nov 28, 2023
bd713f0
propose sc transfer - without metadata for now
ccorcoveanu Nov 28, 2023
ad4268c
add gas limit to mapper
ccorcoveanu Nov 28, 2023
773ea2c
reverted extra steps - integrated sc calls in normal batch transfers
ccorcoveanu Nov 29, 2023
e4364b7
sorted client imports
ccorcoveanu Nov 29, 2023
1b42fb0
reverted performAction
ccorcoveanu Nov 29, 2023
8d41473
fixed all imports in pr
ccorcoveanu Nov 29, 2023
11e8923
fixed linter errors
ccorcoveanu Nov 29, 2023
688fa39
small fixes + unit test
ccorcoveanu Nov 29, 2023
1d5bc3d
fixed unit tests
ccorcoveanu Nov 29, 2023
4fe1209
fixed go imports issues
ccorcoveanu Dec 11, 2023
65b784d
fixed unit tests
ccorcoveanu Dec 12, 2023
c5d7c96
Merge pull request #271 from multiversx/feat/v3
ccorcoveanu Dec 13, 2023
c8ce4d2
Merge branch 'feat/sc-execution' into sc-exec-impl
ccorcoveanu Dec 13, 2023
23c4784
Merge branch 'feat/sc-execution' into sc-exec-impl
ccorcoveanu Dec 13, 2023
fbd948b
update unit test to use only non indexed args in Data - also check al…
ccorcoveanu Dec 13, 2023
cd241fe
Merge branch 'sc-exec-impl' of github.com:multiversx/mx-bridge-eth-go…
ccorcoveanu Dec 13, 2023
81152ae
Merge pull request #267 from multiversx/sc-exec-impl
iulianpascalau Dec 14, 2023
08ab429
- added SC call integration test
iulianpascalau Dec 14, 2023
0dc9af7
Merge branch 'feat/v3' into merge-v3-feat-sc-exec-2023.12.14
iulianpascalau Dec 14, 2023
5f6441d
Merge pull request #275 from multiversx/merge-v3-feat-sc-exec-2023.12.14
iulianpascalau Dec 15, 2023
891af32
Merge branch 'feat/sc-execution' into sc-execution-integration-test
iulianpascalau Dec 15, 2023
d6644bd
- fixes after review
iulianpascalau Dec 15, 2023
79b77aa
Merge pull request #276 from multiversx/sc-execution-integration-test
iulianpascalau Dec 18, 2023
64d582d
- added extra gas for SC calls
iulianpascalau Dec 21, 2023
999a14f
- fixed tests
iulianpascalau Dec 21, 2023
8871c77
- fixed linter issue
iulianpascalau Dec 21, 2023
fd545ea
Merge pull request #277 from multiversx/extra-gas-config-for-sc-calls
iulianpascalau Dec 22, 2023
4ea5f75
Merge pull request #273 from multiversx/feat/sc-execution
iulianpascalau Dec 22, 2023
408f756
- fixes after integration
iulianpascalau Dec 22, 2023
fd347d2
Merge branch 'feat/v3' into latest-libs-2023.12.22
iulianpascalau Dec 22, 2023
0069390
- fixes after merge
iulianpascalau Dec 22, 2023
7551e1f
Merge pull request #279 from multiversx/latest-libs-2023.12.22
iulianpascalau Dec 22, 2023
c448f57
Merge branch 'feat/v3' into merge-v3-feat-native-esdts
iulianpascalau Dec 22, 2023
d793ff8
- fixes after merge
iulianpascalau Dec 22, 2023
3172fd0
- linter fixes
iulianpascalau Dec 22, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion bridges/ethMultiversX/bridgeExecutor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package ethmultiversx

import (
"context"
"encoding/hex"
"fmt"
"math/big"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/multiversx/mx-bridge-eth-go/clients"
"github.com/multiversx/mx-bridge-eth-go/clients/ethereum/contract"
"github.com/multiversx/mx-bridge-eth-go/core"
"github.com/multiversx/mx-bridge-eth-go/core/batchProcessor"
"github.com/multiversx/mx-chain-core-go/core/check"
Expand All @@ -17,9 +19,11 @@ import (
// splits - represent the number of times we split the maximum interval
// we wait for the transfer confirmation on Ethereum
const splits = 10

const minRetries = 1

// MissingCallData is a placeholder for wrongly initiated contract calls that do not contain data
const MissingCallData = "<missing call data>"

// ArgsBridgeExecutor is the arguments DTO struct used in both bridges
type ArgsBridgeExecutor struct {
Log logger.Logger
Expand Down Expand Up @@ -450,11 +454,64 @@ func (executor *bridgeExecutor) GetAndStoreBatchFromEthereum(ctx context.Context
ErrBatchNotFound, nonce, batch.ID, len(batch.Deposits))
}

batch, err = executor.addBatchSCMetadata(ctx, batch)
if err != nil {
return err
}
executor.batch = batch

return nil
}

// addBatchSCMetadata fetches the logs containing sc calls metadata for the current batch
func (executor *bridgeExecutor) addBatchSCMetadata(ctx context.Context, transfers *clients.TransferBatch) (*clients.TransferBatch, error) {
if transfers == nil {
return nil, ErrNilBatch
}

if !executor.hasSCCalls(transfers) {
return transfers, nil
}

events, err := executor.ethereumClient.GetBatchSCMetadata(ctx, transfers.ID)
if err != nil {
return nil, err
}

for i, t := range transfers.Deposits {
transfers.Deposits[i] = executor.addMetadataToTransfer(t, events)
}

return transfers, nil
}

func (executor *bridgeExecutor) addMetadataToTransfer(transfer *clients.DepositTransfer, events []*contract.SCExecProxyERC20SCDeposit) *clients.DepositTransfer {
for _, event := range events {
if event.DepositNonce == transfer.Nonce {
transfer.ExtraGasLimit = event.MvxGasLimit
transfer.Data = []byte(event.CallData)
if len(transfer.Data) == 0 {
// will add a dummy data so the relayers won't panic
transfer.Data = []byte(MissingCallData)
}
transfer.DisplayableData = hex.EncodeToString(transfer.Data)

return transfer
}
}
return transfer
}

func (executor *bridgeExecutor) hasSCCalls(transfers *clients.TransferBatch) bool {
for _, t := range transfers.Deposits {
if executor.ethereumClient.IsDepositSCCall(t) {
return true
}
}

return false
}

// WasTransferPerformedOnEthereum returns true if the batch was performed on Ethereum
func (executor *bridgeExecutor) WasTransferPerformedOnEthereum(ctx context.Context) (bool, error) {
if executor.batch == nil {
Expand Down
71 changes: 71 additions & 0 deletions bridges/ethMultiversX/bridgeExecutor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/multiversx/mx-bridge-eth-go/clients"
"github.com/multiversx/mx-bridge-eth-go/clients/ethereum/contract"
"github.com/multiversx/mx-bridge-eth-go/core"
"github.com/multiversx/mx-bridge-eth-go/core/batchProcessor"
"github.com/multiversx/mx-bridge-eth-go/testsCommon"
Expand Down Expand Up @@ -363,6 +364,76 @@ func TestEthToMultiversXBridgeExecutor_GetAndStoreBatchFromEthereum(t *testing.T
assert.True(t, expectedBatch == executor.GetStoredBatch()) // pointer testing
assert.True(t, expectedBatch == executor.batch)
})
t.Run("should add deposits metadata for sc calls", func(t *testing.T) {
args := createMockExecutorArgs()
providedNonce := uint64(8346)
depositNonce := uint64(100)
depositData := "testData"
expectedBatch := &clients.TransferBatch{
ID: providedNonce,
Deposits: []*clients.DepositTransfer{
{
Nonce: depositNonce,
},
},
}
args.EthereumClient = &bridgeTests.EthereumClientStub{
GetBatchCalled: func(ctx context.Context, nonce uint64) (*clients.TransferBatch, error) {
assert.Equal(t, providedNonce, nonce)
return expectedBatch, nil
},
GetBatchSCMetadataCalled: func(ctx context.Context, nonce uint64) ([]*contract.SCExecProxyERC20SCDeposit, error) {
return []*contract.SCExecProxyERC20SCDeposit{{
DepositNonce: depositNonce,
CallData: depositData,
}}, nil
},
IsDepositSCCallCalled: func(deposit *clients.DepositTransfer) bool {
return deposit.Nonce == depositNonce
},
}
executor, _ := NewBridgeExecutor(args)
err := executor.GetAndStoreBatchFromEthereum(context.Background(), providedNonce)

assert.Nil(t, err)
assert.True(t, expectedBatch == executor.GetStoredBatch()) // pointer testing
assert.Equal(t, depositData, string(executor.batch.Deposits[0].Data))
})
t.Run("should add deposits metadata for sc calls even if with invalid data", func(t *testing.T) {
args := createMockExecutorArgs()
providedNonce := uint64(8346)
depositNonce := uint64(100)
depositData := ""
expectedBatch := &clients.TransferBatch{
ID: providedNonce,
Deposits: []*clients.DepositTransfer{
{
Nonce: depositNonce,
},
},
}
args.EthereumClient = &bridgeTests.EthereumClientStub{
GetBatchCalled: func(ctx context.Context, nonce uint64) (*clients.TransferBatch, error) {
assert.Equal(t, providedNonce, nonce)
return expectedBatch, nil
},
GetBatchSCMetadataCalled: func(ctx context.Context, nonce uint64) ([]*contract.SCExecProxyERC20SCDeposit, error) {
return []*contract.SCExecProxyERC20SCDeposit{{
DepositNonce: depositNonce,
CallData: depositData,
}}, nil
},
IsDepositSCCallCalled: func(deposit *clients.DepositTransfer) bool {
return deposit.Nonce == depositNonce
},
}
executor, _ := NewBridgeExecutor(args)
err := executor.GetAndStoreBatchFromEthereum(context.Background(), providedNonce)

assert.Nil(t, err)
assert.True(t, expectedBatch == executor.GetStoredBatch()) // pointer testing
assert.Equal(t, MissingCallData, string(executor.batch.Deposits[0].Data))
})
}

func TestEthToMultiversXBridgeExecutor_GetLastExecutedEthBatchIDFromMultiversX(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions bridges/ethMultiversX/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/multiversx/mx-bridge-eth-go/clients"
"github.com/multiversx/mx-bridge-eth-go/clients/ethereum/contract"
"github.com/multiversx/mx-bridge-eth-go/core/batchProcessor"
)

Expand Down Expand Up @@ -40,13 +41,15 @@ type MultiversXClient interface {
type EthereumClient interface {
GetBatch(ctx context.Context, nonce uint64) (*clients.TransferBatch, error)
WasExecuted(ctx context.Context, batchID uint64) (bool, error)
IsDepositSCCall(deposit *clients.DepositTransfer) bool
GenerateMessageHash(batch *batchProcessor.ArgListsBatch, batchId uint64) (common.Hash, error)

BroadcastSignatureForMessageHash(msgHash common.Hash)
ExecuteTransfer(ctx context.Context, msgHash common.Hash, batch *batchProcessor.ArgListsBatch, batchId uint64, quorum int) (string, error)
GetTransactionsStatuses(ctx context.Context, batchId uint64) ([]byte, error)
GetQuorumSize(ctx context.Context) (*big.Int, error)
IsQuorumReached(ctx context.Context, msgHash common.Hash) (bool, error)
GetBatchSCMetadata(ctx context.Context, nonce uint64) ([]*contract.SCExecProxyERC20SCDeposit, error)
CheckClientAvailability(ctx context.Context) error
CheckRequiredBalance(ctx context.Context, erc20Address common.Address, value *big.Int) error
TokenMintedBalances(ctx context.Context, token common.Address) (*big.Int, error)
Expand Down
2 changes: 1 addition & 1 deletion bridges/ethMultiversX/steps/ethToMultiversX/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const (
// GettingPendingBatchFromEthereum is the step identifier for fetching the pending batch from the Ethereum chain
GettingPendingBatchFromEthereum = "get pending batch from Ethereum"

// ProposingTransferOnMultiversX is the step idetifier for proposing transfer on MultiversX
// ProposingTransferOnMultiversX is the step identifier for proposing transfer on MultiversX
ProposingTransferOnMultiversX = "propose transfer"

// SigningProposedTransferOnMultiversX is the step identifier for signing proposed transfer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import (

var expectedError = errors.New("expected error")
var testBatch = &clients.TransferBatch{
ID: 112233,
Deposits: nil,
Statuses: nil,
ID: 112233,
Deposits: []*clients.DepositTransfer{
{},
},
Statuses: []byte{0},
}

func TestExecuteGetPending(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions bridges/ethMultiversX/steps/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Executor interface {
GetBatchFromMultiversX(ctx context.Context) (*clients.TransferBatch, error)
StoreBatchFromMultiversX(batch *clients.TransferBatch) error
GetStoredBatch() *clients.TransferBatch

GetLastExecutedEthBatchIDFromMultiversX(ctx context.Context) (uint64, error)
VerifyLastDepositNonceExecutedOnEthereumBatch(ctx context.Context) error

Expand Down
4 changes: 2 additions & 2 deletions bridges/ethMultiversX/topology/topologyHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ func (t *topologyHandler) MyTurnAsLeader() bool {
}

t.log.Debug(msg,
"leader", t.addressConverter.ToBech32String(leaderAddress),
"leader", t.addressConverter.ToBech32StringSilent(leaderAddress),
"index", index,
"self address", t.addressConverter.ToBech32String(t.addressBytes))
"self address", t.addressConverter.ToBech32StringSilent(t.addressBytes))

return isLeader
}
Expand Down
10 changes: 8 additions & 2 deletions clients/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,15 @@ type DepositTransfer struct {
ConvertedTokenBytes []byte `json:"-"`
DisplayableToken string `json:"token"`
Amount *big.Int `json:"amount"`
ExtraGasLimit uint64 `json:"gasLimit"`
Data []byte `json:"-"`
DisplayableData string `json:"data"`
}

// String will convert the deposit transfer to a string
func (dt *DepositTransfer) String() string {
return fmt.Sprintf("to: %s, from: %s, token address: %s, amount: %v, deposit nonce: %d",
dt.DisplayableTo, dt.DisplayableFrom, dt.DisplayableToken, dt.Amount, dt.Nonce)
return fmt.Sprintf("to: %s, from: %s, token address: %s, amount: %v, deposit nonce: %d, gas limit: %d, hex data: %s",
dt.DisplayableTo, dt.DisplayableFrom, dt.DisplayableToken, dt.Amount, dt.Nonce, dt.ExtraGasLimit, dt.DisplayableData)
}

// Clone will deep clone the current DepositTransfer instance
Expand All @@ -94,12 +97,15 @@ func (dt *DepositTransfer) Clone() *DepositTransfer {
ConvertedTokenBytes: make([]byte, len(dt.ConvertedTokenBytes)),
DisplayableToken: dt.DisplayableToken,
Amount: big.NewInt(0),
Data: make([]byte, len(dt.Data)),
DisplayableData: dt.DisplayableData,
}

copy(cloned.ToBytes, dt.ToBytes)
copy(cloned.FromBytes, dt.FromBytes)
copy(cloned.TokenBytes, dt.TokenBytes)
copy(cloned.ConvertedTokenBytes, dt.ConvertedTokenBytes)
copy(cloned.Data, dt.Data)
if dt.Amount != nil {
cloned.Amount.Set(dt.Amount)
}
Expand Down
2 changes: 1 addition & 1 deletion clients/batchValidator/batchValidator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestBatchValidator_ValidateBatch(t *testing.T) {
},
Statuses: []byte{0x3, 0x4},
}
expectedJsonString := `{"batchId":1,"deposits":[{"nonce":1,"to":"to1","from":"from1","token":"token1","amount":1000000000000000000001},{"nonce":2,"to":"to2","from":"from2","token":"token2","amount":1000000000000000000002}],"statuses":"AwQ="}`
expectedJsonString := `{"batchId":1,"deposits":[{"nonce":1,"to":"to1","from":"from1","token":"token1","amount":1000000000000000000001,"gasLimit":0,"data":""},{"nonce":2,"to":"to2","from":"from2","token":"token2","amount":1000000000000000000002,"gasLimit":0,"data":""}],"statuses":"AwQ="}`

t.Run("server errors with Bad Request, but no reason", func(t *testing.T) {
t.Parallel()
Expand Down
9 changes: 6 additions & 3 deletions clients/batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func TestDepositTransfer_Clone(t *testing.T) {
DisplayableToken: "token",
Amount: big.NewInt(7463),
ConvertedTokenBytes: []byte("converted token"),
Data: []byte("tx data"),
}

cloned := dt.Clone()
Expand All @@ -42,7 +43,7 @@ func TestDepositTransfer_String(t *testing.T) {
Amount: big.NewInt(7463),
}

expectedString := "to: to, from: from, token address: token, amount: 7463, deposit nonce: 112334"
expectedString := "to: to, from: from, token address: token, amount: 7463, deposit nonce: 112334, gas limit: 0, hex data: "
assert.Equal(t, expectedString, dt.String())
}

Expand All @@ -62,6 +63,7 @@ func TestTransferBatch_Clone(t *testing.T) {
DisplayableToken: "token1",
Amount: big.NewInt(3344),
ConvertedTokenBytes: []byte("converted token1"),
Data: []byte("tx data"),
},
{
Nonce: 2,
Expand All @@ -73,6 +75,7 @@ func TestTransferBatch_Clone(t *testing.T) {
DisplayableToken: "token2",
Amount: big.NewInt(5566),
ConvertedTokenBytes: []byte("converted token2"),
Data: []byte("tx data"),
},
},
Statuses: []byte{Executed, Rejected},
Expand Down Expand Up @@ -115,8 +118,8 @@ func TestTransferBatch_String(t *testing.T) {
}

expectedString := `Batch id 2243:
to: to1, from: from1, token address: token1, amount: 3344, deposit nonce: 1
to: to2, from: from2, token address: token2, amount: 5566, deposit nonce: 2
to: to1, from: from1, token address: token1, amount: 3344, deposit nonce: 1, gas limit: 0, hex data:
to: to2, from: from2, token address: token2, amount: 5566, deposit nonce: 2, gas limit: 0, hex data:
Statuses: 0304`
assert.Equal(t, expectedString, tb.String())
}
Expand Down
Loading