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

Added extra gas for SC calls #277

Merged
merged 3 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
29 changes: 29 additions & 0 deletions clients/multiversx/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
63 changes: 60 additions & 3 deletions clients/multiversx/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ func createMockClientArgs() ClientArgs {
ProposeStatusForEach: 50,
PerformActionBase: 60,
PerformActionForEach: 70,
ScCallPerByte: 80,
ScCallPerformForEach: 90,
},
Proxy: &interactors.ProxyStub{},
Log: logger.GetOrCreate("test"),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -754,8 +761,58 @@ 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
assert.Equal(t, expectedGasLimit, gasLimit)

return expectedHash, nil
},
Expand Down
2 changes: 2 additions & 0 deletions cmd/bridge/config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions testsCommon/gasMap.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ func CreateTestMultiversXGasMap() config.MultiversXGasMapConfig {
ProposeStatusForEach: 105,
PerformActionBase: 106,
PerformActionForEach: 107,
ScCallPerByte: 108,
ScCallPerformForEach: 109,
}
}