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 implementation to v3.5 #342

Merged
merged 8 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
63 changes: 60 additions & 3 deletions bridges/ethMultiversX/bridgeExecutor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ 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/clients/multiversx"
"github.com/multiversx/mx-bridge-eth-go/core"
bridgeCore "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"
"github.com/multiversx/mx-chain-core-go/data/transaction"
logger "github.com/multiversx/mx-chain-logger-go"
)

Expand Down Expand Up @@ -153,10 +155,24 @@ func (executor *bridgeExecutor) MyTurnAsLeader() bool {
// GetBatchFromMultiversX fetches the pending batch from MultiversX
func (executor *bridgeExecutor) GetBatchFromMultiversX(ctx context.Context) (*bridgeCore.TransferBatch, error) {
batch, err := executor.multiversXClient.GetPendingBatch(ctx)
if err == nil {
executor.statusHandler.SetIntMetric(core.MetricNumBatches, int(batch.ID)-1)
if err != nil {
return nil, err
}

executor.statusHandler.SetIntMetric(core.MetricNumBatches, int(batch.ID)-1)

isBatchInvalid := len(batch.Deposits) == 0
if isBatchInvalid {
return nil, fmt.Errorf("%w, fetched nonce: %d, num deposits: %d",
sstanculeanu marked this conversation as resolved.
Show resolved Hide resolved
ErrFinalBatchNotFound, batch.ID, len(batch.Deposits))
}

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

return batch, nil
}

// StoreBatchFromMultiversX saves the pending batch from MultiversX
Expand All @@ -169,6 +185,47 @@ func (executor *bridgeExecutor) StoreBatchFromMultiversX(batch *bridgeCore.Trans
return nil
}

// addBatchSCMetadataMvx fetches the logs containing sc calls metadata for the current batch
func (executor *bridgeExecutor) addBatchSCMetadataMvx(ctx context.Context, transfers *bridgeCore.TransferBatch) (*bridgeCore.TransferBatch, error) {
sstanculeanu marked this conversation as resolved.
Show resolved Hide resolved
if transfers == nil {
sstanculeanu marked this conversation as resolved.
Show resolved Hide resolved
return nil, ErrNilBatch
}

events, err := executor.multiversXClient.GetBatchSCMetadata(ctx, transfers)
sstanculeanu marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

for i, t := range transfers.Deposits {
transfers.Deposits[i], err = executor.addMetadataToTransferMvx(t, events)
sstanculeanu marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}
}

return transfers, nil
}

// addMetadataToTransferMvx fetches the logs containing sc calls metadata for the current batch
func (executor *bridgeExecutor) addMetadataToTransferMvx(transfer *bridgeCore.DepositTransfer, events []*transaction.Events) (*bridgeCore.DepositTransfer, error) {
for _, event := range events {
depositNonce, err := multiversx.ParseUInt64FromByteSlice(event.Topics[1])
sstanculeanu marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, fmt.Errorf("%w while parsing batch ID", err)
sstanculeanu marked this conversation as resolved.
Show resolved Hide resolved
}

if depositNonce == transfer.Nonce {
processData(transfer, event.Topics[7])
iulianpascalau marked this conversation as resolved.
Show resolved Hide resolved
iulianpascalau marked this conversation as resolved.
Show resolved Hide resolved
sstanculeanu marked this conversation as resolved.
Show resolved Hide resolved
iulianpascalau marked this conversation as resolved.
Show resolved Hide resolved
return transfer, nil
}
}

transfer.Data = []byte{bridgeCore.MissingDataProtocolMarker}
transfer.DisplayableData = ""

return transfer, nil
}

// GetStoredBatch returns the stored batch
func (executor *bridgeExecutor) GetStoredBatch() *bridgeCore.TransferBatch {
return executor.batch
Expand Down
150 changes: 146 additions & 4 deletions bridges/ethMultiversX/bridgeExecutor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ethmultiversx

import (
"context"
"encoding/binary"
"errors"
"fmt"
"math/big"
Expand All @@ -17,12 +18,14 @@ import (
"github.com/multiversx/mx-bridge-eth-go/testsCommon"
bridgeTests "github.com/multiversx/mx-bridge-eth-go/testsCommon/bridge"
"github.com/multiversx/mx-chain-core-go/core/check"
"github.com/multiversx/mx-chain-core-go/data/transaction"
logger "github.com/multiversx/mx-chain-logger-go"
"github.com/stretchr/testify/assert"
)

var expectedErr = errors.New("expected error")
var providedBatch = &bridgeCore.TransferBatch{}
var providedTxnEvents []*transaction.Events
iulianpascalau marked this conversation as resolved.
Show resolved Hide resolved
var expectedMaxRetries = uint64(3)

func createMockExecutorArgs() ArgsBridgeExecutor {
Expand Down Expand Up @@ -991,11 +994,11 @@ func TestMultiversXToEthBridgeExecutor_GetAndStoreBatchFromMultiversX(t *testing
err := executor.StoreBatchFromMultiversX(nil)
assert.Equal(t, ErrNilBatch, err)
})
t.Run("should work", func(t *testing.T) {
t.Run("no deposits should error", func(t *testing.T) {
t.Parallel()

wasCalled := false
args := createMockExecutorArgs()
wasCalled := false
args.MultiversXClient = &bridgeTests.MultiversXClientStub{
GetPendingBatchCalled: func(ctx context.Context) (*bridgeCore.TransferBatch, error) {
wasCalled = true
Expand All @@ -1006,12 +1009,151 @@ func TestMultiversXToEthBridgeExecutor_GetAndStoreBatchFromMultiversX(t *testing
executor, _ := NewBridgeExecutor(args)
batch, err := executor.GetBatchFromMultiversX(context.Background())
assert.True(t, wasCalled)
assert.Equal(t, providedBatch, batch)
assert.Nil(t, batch)
assert.Equal(t, fmt.Errorf("%w, fetched nonce: %d, num deposits: %d", ErrFinalBatchNotFound, 0, 0), err)
})
t.Run("should work", func(t *testing.T) {
t.Parallel()

wasPendingBatchCalled := false
wasGetBatchSCMetadataCalled := false
providedBatchWithDeposits := &bridgeCore.TransferBatch{
Deposits: []*bridgeCore.DepositTransfer{{}, {}},
}
args := createMockExecutorArgs()
args.MultiversXClient = &bridgeTests.MultiversXClientStub{
GetPendingBatchCalled: func(ctx context.Context) (*bridgeCore.TransferBatch, error) {
wasPendingBatchCalled = true
return providedBatchWithDeposits, nil
},
GetBatchSCMetadataCalled: func(ctx context.Context, batch *bridgeCore.TransferBatch) ([]*transaction.Events, error) {
wasGetBatchSCMetadataCalled = true
return providedTxnEvents, nil
},
}

executor, _ := NewBridgeExecutor(args)
batch, err := executor.GetBatchFromMultiversX(context.Background())
assert.True(t, wasPendingBatchCalled)
assert.True(t, wasGetBatchSCMetadataCalled)
assert.Equal(t, providedBatchWithDeposits, batch)
assert.Nil(t, err)

err = executor.StoreBatchFromMultiversX(batch)
assert.Equal(t, providedBatchWithDeposits, executor.batch)
assert.Nil(t, err)
})
t.Run("should add deposits metadata for sc calls", func(t *testing.T) {
t.Parallel()

providedNonce := uint64(8346)
depositNonce := uint64(100)
depositData := []byte("testData")
expectedBatch := &bridgeCore.TransferBatch{
ID: providedNonce,
Deposits: []*bridgeCore.DepositTransfer{
{
Nonce: depositNonce,
},
},
}
args := createMockExecutorArgs()
args.MultiversXClient = &bridgeTests.MultiversXClientStub{
GetPendingBatchCalled: func(ctx context.Context) (*bridgeCore.TransferBatch, error) {
return expectedBatch, nil
},
GetBatchSCMetadataCalled: func(ctx context.Context, batch *bridgeCore.TransferBatch) ([]*transaction.Events, error) {
depositNonceBytes := make([]byte, 8)
binary.BigEndian.PutUint64(depositNonceBytes, depositNonce)
return []*transaction.Events{
{Topics: [][]byte{{}, depositNonceBytes, {}, {}, {}, {}, {}, depositData}},
}, nil
},
}

executor, _ := NewBridgeExecutor(args)
batch, err := executor.GetBatchFromMultiversX(context.Background())
assert.Nil(t, err)
assert.Equal(t, expectedBatch, batch)
iulianpascalau marked this conversation as resolved.
Show resolved Hide resolved
expectedDepositData := []byte{bridgeCore.DataPresentProtocolMarker, 0, 0, 0, byte(len(depositData))}
expectedDepositData = append(expectedDepositData, depositData...)
assert.Equal(t, string(expectedDepositData), string(batch.Deposits[0].Data))
})
t.Run("should add deposits metadata for sc calls with a data starting with missing data marker", func(t *testing.T) {
t.Parallel()

providedNonce := uint64(8346)
depositNonce := uint64(100)
depositData := append([]byte{bridgeCore.MissingDataProtocolMarker}, "testData"...)
expectedBatch := &bridgeCore.TransferBatch{
ID: providedNonce,
Deposits: []*bridgeCore.DepositTransfer{
{
Nonce: depositNonce,
},
},
}
args := createMockExecutorArgs()
args.MultiversXClient = &bridgeTests.MultiversXClientStub{
GetPendingBatchCalled: func(ctx context.Context) (*bridgeCore.TransferBatch, error) {
return expectedBatch, nil
},
GetBatchSCMetadataCalled: func(ctx context.Context, batch *bridgeCore.TransferBatch) ([]*transaction.Events, error) {
depositNonceBytes := make([]byte, 8)
binary.BigEndian.PutUint64(depositNonceBytes, depositNonce)
return []*transaction.Events{
{Topics: [][]byte{{}, depositNonceBytes, {}, {}, {}, {}, {}, depositData}},
}, nil
},
}

executor, _ := NewBridgeExecutor(args)
batch, err := executor.GetBatchFromMultiversX(context.Background())
assert.Nil(t, err)

err = executor.StoreBatchFromMultiversX(batch)
assert.Equal(t, providedBatch, executor.batch)
assert.Nil(t, err)
assert.True(t, expectedBatch == executor.GetStoredBatch()) // pointer testing
iulianpascalau marked this conversation as resolved.
Show resolved Hide resolved
expectedDepositData := []byte{bridgeCore.DataPresentProtocolMarker, 0, 0, 0, byte(len(depositData))}
expectedDepositData = append(expectedDepositData, depositData...)
assert.Equal(t, string(expectedDepositData), string(executor.batch.Deposits[0].Data))
})
t.Run("should add deposits metadata for sc calls even if with no data", func(t *testing.T) {
t.Parallel()

providedNonce := uint64(8346)
depositNonce := uint64(100)
depositData := []byte{bridgeCore.MissingDataProtocolMarker}
expectedBatch := &bridgeCore.TransferBatch{
ID: providedNonce,
Deposits: []*bridgeCore.DepositTransfer{
{
Nonce: depositNonce,
},
},
}
args := createMockExecutorArgs()
args.MultiversXClient = &bridgeTests.MultiversXClientStub{
GetPendingBatchCalled: func(ctx context.Context) (*bridgeCore.TransferBatch, error) {
return expectedBatch, nil
},
GetBatchSCMetadataCalled: func(ctx context.Context, batch *bridgeCore.TransferBatch) ([]*transaction.Events, error) {
depositNonceBytes := make([]byte, 8)
binary.BigEndian.PutUint64(depositNonceBytes, depositNonce)
return []*transaction.Events{
{Topics: [][]byte{{}, depositNonceBytes, {}, {}, {}, {}, {}, depositData}},
}, nil
},
}

executor, _ := NewBridgeExecutor(args)
batch, err := executor.GetBatchFromMultiversX(context.Background())
assert.Nil(t, err)

err = executor.StoreBatchFromMultiversX(batch)
assert.Nil(t, err)
assert.True(t, expectedBatch == executor.GetStoredBatch()) // pointer testing
iulianpascalau marked this conversation as resolved.
Show resolved Hide resolved
assert.Equal(t, depositData, executor.batch.Deposits[0].Data)
})
}

Expand Down
2 changes: 2 additions & 0 deletions bridges/ethMultiversX/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/multiversx/mx-bridge-eth-go/clients/ethereum/contract"
bridgeCore "github.com/multiversx/mx-bridge-eth-go/core"
"github.com/multiversx/mx-bridge-eth-go/core/batchProcessor"
"github.com/multiversx/mx-chain-core-go/data/transaction"
)

// MultiversXClient defines the behavior of the MultiversX client able to communicate with the MultiversX chain
Expand All @@ -25,6 +26,7 @@ type MultiversXClient interface {
GetLastExecutedEthBatchID(ctx context.Context) (uint64, error)
GetLastExecutedEthTxID(ctx context.Context) (uint64, error)
GetCurrentNonce(ctx context.Context) (uint64, error)
GetBatchSCMetadata(ctx context.Context, batch *bridgeCore.TransferBatch) ([]*transaction.Events, error)

ProposeSetStatus(ctx context.Context, batch *bridgeCore.TransferBatch) (string, error)
ProposeTransfer(ctx context.Context, batch *bridgeCore.TransferBatch) (string, error)
Expand Down
Loading
Loading