From 64d582dabe984140e91c94173d16831d81a054f7 Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Thu, 21 Dec 2023 10:09:45 +0200 Subject: [PATCH 1/3] - added extra gas for SC calls --- clients/multiversx/client.go | 29 +++++++++++++++ clients/multiversx/client_test.go | 61 +++++++++++++++++++++++++++++-- cmd/bridge/config/config.toml | 2 + config/config.go | 2 + 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/clients/multiversx/client.go b/clients/multiversx/client.go index 08882961..faf3b3be 100644 --- a/clients/multiversx/client.go +++ b/clients/multiversx/client.go @@ -66,6 +66,11 @@ type client struct { mut sync.RWMutex } +type scCallExtraGas struct { + basicGas uint64 + performAction uint64 +} + // NewClient returns a new MultiversX Client instance func NewClient(args ClientArgs) (*client, error) { err := checkArgs(args) @@ -317,7 +322,10 @@ func (c *client) ProposeTransfer(ctx context.Context, batch *clients.TransferBat } } + scCallGas := c.computeExtraGasForSCCallsBasic(batch) + gasLimit := c.gasMapConfig.ProposeTransferBase + uint64(len(batch.Deposits))*c.gasMapConfig.ProposeTransferForEach + gasLimit += scCallGas.basicGas hash, err := c.txHandler.SendTransactionReturnHash(ctx, txBuilder, gasLimit) if err == nil { c.log.Info("proposed transfer"+batch.String(), "transaction hash", hash) @@ -356,7 +364,10 @@ func (c *client) PerformAction(ctx context.Context, actionID uint64, batch *clie txBuilder := c.createCommonTxDataBuilder(performActionFuncName, int64(actionID)) + scCallGas := c.computeExtraGasForSCCallsBasic(batch) + gasLimit := c.gasMapConfig.PerformActionBase + uint64(len(batch.Statuses))*c.gasMapConfig.PerformActionForEach + gasLimit += scCallGas.basicGas + scCallGas.performAction hash, err := c.txHandler.SendTransactionReturnHash(ctx, txBuilder, gasLimit) if err == nil { @@ -366,6 +377,24 @@ func (c *client) PerformAction(ctx context.Context, actionID uint64, batch *clie return hash, err } +func (c *client) computeExtraGasForSCCallsBasic(batch *clients.TransferBatch) scCallExtraGas { + result := scCallExtraGas{} + for _, deposit := range batch.Deposits { + if len(deposit.Data) == 0 { + continue + } + + computedLen := 2 // 2 extra arguments separators (@) + computedLen += len(deposit.Data) * 2 // the data is hexed, so, double the size + computedLen += len(big.NewInt(int64(deposit.ExtraGasLimit)).Bytes()) * 2 // the gas is converted to bytes, then hexed + + result.basicGas += uint64(computedLen) * c.gasMapConfig.ScCallPerByte + result.performAction += c.gasMapConfig.ScCallPerformForEach + } + + return result +} + func (c *client) checkIsPaused(ctx context.Context) error { isPaused, err := c.IsPaused(ctx) if err != nil { diff --git a/clients/multiversx/client_test.go b/clients/multiversx/client_test.go index 641caea7..e1ef017b 100644 --- a/clients/multiversx/client_test.go +++ b/clients/multiversx/client_test.go @@ -45,6 +45,8 @@ func createMockClientArgs() ClientArgs { ProposeStatusForEach: 50, PerformActionBase: 60, PerformActionForEach: 70, + ScCallPerByte: 80, + ScCallPerformForEach: 90, }, Proxy: &interactors.ProxyStub{}, Log: logger.GetOrCreate("test"), @@ -574,14 +576,19 @@ func TestClient_ProposeTransfer(t *testing.T) { proposeTransferFuncName, hex.EncodeToString(big.NewInt(int64(batch.ID)).Bytes()), } + extraGas := uint64(0) for _, dt := range batch.Deposits { dataStrings = append(dataStrings, depositToStrings(dt)...) + if len(dt.Data) > 0 { + gasLimitBytes := big.NewInt(int64(dt.ExtraGasLimit)).Bytes() + extraGas += (uint64(len(dt.Data)+len(gasLimitBytes))*2 + 2) * args.GasMapConfig.ScCallPerByte + } } expectedDataField := strings.Join(dataStrings, "@") assert.Equal(t, expectedDataField, dataField) - expectedGasLimit := c.gasMapConfig.ProposeTransferBase + uint64(len(batch.Deposits))*c.gasMapConfig.ProposeTransferForEach + expectedGasLimit := c.gasMapConfig.ProposeTransferBase + uint64(len(batch.Deposits))*c.gasMapConfig.ProposeTransferForEach + extraGas assert.Equal(t, expectedGasLimit, gasLimit) return expectedHash, nil @@ -754,8 +761,56 @@ func TestClient_PerformAction(t *testing.T) { } expectedDataField := strings.Join(dataStrings, "@") assert.Equal(t, expectedDataField, dataField) - expectedGasdLimit := c.gasMapConfig.PerformActionBase + uint64(len(batch.Statuses))*c.gasMapConfig.PerformActionForEach - assert.Equal(t, expectedGasdLimit, gasLimit) + expectedGasLimit := c.gasMapConfig.PerformActionBase + uint64(len(batch.Statuses))*c.gasMapConfig.PerformActionForEach + assert.Equal(t, expectedGasLimit, gasLimit) + + return expectedHash, nil + }, + } + + hash, err := c.PerformAction(context.Background(), actionID, batch) + assert.Nil(t, err) + assert.Equal(t, expectedHash, hash) + assert.True(t, sendWasCalled) + }) + t.Run("should perform action with SC call", func(t *testing.T) { + t.Parallel() + + args := createMockClientArgs() + args.Proxy = createMockProxy(make([][]byte, 0)) + expectedHash := "expected hash" + c, _ := NewClient(args) + sendWasCalled := false + batch := createMockBatch() + batch.Deposits[0].ExtraGasLimit = 37373 + batch.Deposits[0].Data = []byte("doSomething@7788") + batch.Deposits[0].DisplayableData = hex.EncodeToString(batch.Deposits[0].Data) + + c.txHandler = &bridgeTests.TxHandlerStub{ + SendTransactionReturnHashCalled: func(ctx context.Context, builder builders.TxDataBuilder, gasLimit uint64) (string, error) { + sendWasCalled = true + + dataField, err := builder.ToDataString() + assert.Nil(t, err) + + dataStrings := []string{ + performActionFuncName, + hex.EncodeToString(big.NewInt(int64(actionID)).Bytes()), + } + expectedDataField := strings.Join(dataStrings, "@") + assert.Equal(t, expectedDataField, dataField) + extraGas := uint64(0) + for _, dt := range batch.Deposits { + dataStrings = append(dataStrings, depositToStrings(dt)...) + if len(dt.Data) > 0 { + gasLimitBytes := big.NewInt(int64(dt.ExtraGasLimit)).Bytes() + extraGas += (uint64(len(dt.Data)+len(gasLimitBytes))*2 + 2) * args.GasMapConfig.ScCallPerByte + extraGas += args.GasMapConfig.ScCallPerformForEach + } + } + + expectedGasLimit := c.gasMapConfig.PerformActionBase + uint64(len(batch.Statuses))*c.gasMapConfig.PerformActionForEach + expectedGasLimit += extraGas return expectedHash, nil }, diff --git a/cmd/bridge/config/config.toml b/cmd/bridge/config/config.toml index 03b39877..d95d4dc6 100644 --- a/cmd/bridge/config/config.toml +++ b/cmd/bridge/config/config.toml @@ -44,6 +44,8 @@ ProposeStatusForEach = 7000000 PerformActionBase = 40000000 PerformActionForEach = 5500000 + ScCallPerByte = 100000 # 1500 tx data field + the rest for the actual storage in the contract + ScCallPerformForEach = 10000000 [P2P] Port = "10010" diff --git a/config/config.go b/config/config.go index e14326d4..cffa7a4c 100644 --- a/config/config.go +++ b/config/config.go @@ -169,6 +169,8 @@ type MultiversXGasMapConfig struct { ProposeStatusForEach uint64 PerformActionBase uint64 PerformActionForEach uint64 + ScCallPerByte uint64 + ScCallPerformForEach uint64 } // PeersRatingConfig will hold settings related to peers rating From 999a14f4d5632caa98df28d4cf2a2750ff3b649f Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Thu, 21 Dec 2023 10:15:10 +0200 Subject: [PATCH 2/3] - fixed tests --- testsCommon/gasMap.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsCommon/gasMap.go b/testsCommon/gasMap.go index f2617cfd..39aa12c9 100644 --- a/testsCommon/gasMap.go +++ b/testsCommon/gasMap.go @@ -14,5 +14,7 @@ func CreateTestMultiversXGasMap() config.MultiversXGasMapConfig { ProposeStatusForEach: 105, PerformActionBase: 106, PerformActionForEach: 107, + ScCallPerByte: 108, + ScCallPerformForEach: 109, } } From 8871c7718ab782e52a754796413d4951c346d739 Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Thu, 21 Dec 2023 10:16:36 +0200 Subject: [PATCH 3/3] - fixed linter issue --- clients/multiversx/client_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clients/multiversx/client_test.go b/clients/multiversx/client_test.go index e1ef017b..425ce5d0 100644 --- a/clients/multiversx/client_test.go +++ b/clients/multiversx/client_test.go @@ -799,6 +799,7 @@ func TestClient_PerformAction(t *testing.T) { } expectedDataField := strings.Join(dataStrings, "@") assert.Equal(t, expectedDataField, dataField) + extraGas := uint64(0) for _, dt := range batch.Deposits { dataStrings = append(dataStrings, depositToStrings(dt)...) @@ -811,6 +812,7 @@ func TestClient_PerformAction(t *testing.T) { expectedGasLimit := c.gasMapConfig.PerformActionBase + uint64(len(batch.Statuses))*c.gasMapConfig.PerformActionForEach expectedGasLimit += extraGas + assert.Equal(t, expectedGasLimit, gasLimit) return expectedHash, nil },