Skip to content

Commit

Permalink
add EstimateGasOpt (#225)
Browse files Browse the repository at this point in the history
* add EstimateGasOpt

* fix log

* add transaction_xlayer.go

* add log

* add log

* use max gaslimit

* fix json
chengzhinei authored Jun 25, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent b281613 commit 889bf00
Showing 11 changed files with 253 additions and 36 deletions.
2 changes: 1 addition & 1 deletion docs/config-file/node-config-doc.html

Large diffs are not rendered by default.

79 changes: 46 additions & 33 deletions docs/config-file/node-config-doc.md
Original file line number Diff line number Diff line change
@@ -1333,6 +1333,7 @@ FreeGasLimit=0
| - [Nacos](#RPC_Nacos ) | No | object | No | - | Nacos configuration |
| - [NacosWs](#RPC_NacosWs ) | No | object | No | - | NacosWs configuration |
| - [GasLimitFactor](#RPC_GasLimitFactor ) | No | number | No | - | GasLimitFactor is used to multiply the suggested gas provided by the network<br />in order to allow a enough gas to be set for all the transactions default value is 1.<br /><br />ex:<br />suggested gas limit: 100<br />GasLimitFactor: 1<br />gas limit = 100<br /><br />suggested gas limit: 100<br />GasLimitFactor: 1.1<br />gas limit = 110 |
| - [EnableEstimateGasOpt](#RPC_EnableEstimateGasOpt ) | No | boolean | No | - | - |
| - [DisableAPIs](#RPC_DisableAPIs ) | No | array of string | No | - | DisableAPIs disable some API |
| - [RateLimit](#RPC_RateLimit ) | No | object | No | - | RateLimit enable rate limit |
| - [DynamicGP](#RPC_DynamicGP ) | No | object | No | - | DynamicGP defines the config of dynamic gas price |
@@ -1929,7 +1930,19 @@ gas limit = 110
GasLimitFactor=1
```

### <a name="RPC_DisableAPIs"></a>8.22. `RPC.DisableAPIs`
### <a name="RPC_EnableEstimateGasOpt"></a>8.22. `RPC.EnableEstimateGasOpt`

**Type:** : `boolean`

**Default:** `false`

**Example setting the default value** (false):
```
[RPC]
EnableEstimateGasOpt=false
```

### <a name="RPC_DisableAPIs"></a>8.23. `RPC.DisableAPIs`

**Type:** : `array of string`

@@ -1943,7 +1956,7 @@ GasLimitFactor=1
DisableAPIs=[]
```

### <a name="RPC_RateLimit"></a>8.23. `[RPC.RateLimit]`
### <a name="RPC_RateLimit"></a>8.24. `[RPC.RateLimit]`

**Type:** : `object`
**Description:** RateLimit enable rate limit
@@ -1956,7 +1969,7 @@ DisableAPIs=[]
| - [RateLimitDuration](#RPC_RateLimit_RateLimitDuration ) | No | integer | No | - | RateLimitDuration defines the time window for the rate limit |
| - [SpecialApis](#RPC_RateLimit_SpecialApis ) | No | array of object | No | - | SpecialApis defines the apis that need to be rate limited with special rate limit |

#### <a name="RPC_RateLimit_Enabled"></a>8.23.1. `RPC.RateLimit.Enabled`
#### <a name="RPC_RateLimit_Enabled"></a>8.24.1. `RPC.RateLimit.Enabled`

**Type:** : `boolean`

@@ -1970,7 +1983,7 @@ DisableAPIs=[]
Enabled=false
```

#### <a name="RPC_RateLimit_RateLimitApis"></a>8.23.2. `RPC.RateLimit.RateLimitApis`
#### <a name="RPC_RateLimit_RateLimitApis"></a>8.24.2. `RPC.RateLimit.RateLimitApis`

**Type:** : `array of string`

@@ -1984,7 +1997,7 @@ Enabled=false
RateLimitApis=[]
```

#### <a name="RPC_RateLimit_RateLimitCount"></a>8.23.3. `RPC.RateLimit.RateLimitCount`
#### <a name="RPC_RateLimit_RateLimitCount"></a>8.24.3. `RPC.RateLimit.RateLimitCount`

**Type:** : `integer`

@@ -1998,7 +2011,7 @@ RateLimitApis=[]
RateLimitCount=100
```

#### <a name="RPC_RateLimit_RateLimitDuration"></a>8.23.4. `RPC.RateLimit.RateLimitDuration`
#### <a name="RPC_RateLimit_RateLimitDuration"></a>8.24.4. `RPC.RateLimit.RateLimitDuration`

**Type:** : `integer`

@@ -2012,7 +2025,7 @@ RateLimitCount=100
RateLimitDuration=1
```

#### <a name="RPC_RateLimit_SpecialApis"></a>8.23.5. `RPC.RateLimit.SpecialApis`
#### <a name="RPC_RateLimit_SpecialApis"></a>8.24.5. `RPC.RateLimit.SpecialApis`

**Type:** : `array of object`

@@ -2038,7 +2051,7 @@ SpecialApis=[]
| ----------------------------------------------------- | ---------------------------------------------------------- |
| [SpecialApis items](#RPC_RateLimit_SpecialApis_items) | RateLimitItem defines the special rate limit for some apis |

##### <a name="autogenerated_heading_3"></a>8.23.5.1. [RPC.RateLimit.SpecialApis.SpecialApis items]
##### <a name="autogenerated_heading_3"></a>8.24.5.1. [RPC.RateLimit.SpecialApis.SpecialApis items]

**Type:** : `object`
**Description:** RateLimitItem defines the special rate limit for some apis
@@ -2049,22 +2062,22 @@ SpecialApis=[]
| - [Count](#RPC_RateLimit_SpecialApis_items_Count ) | No | integer | No | - | Count defines the maximum burst size of requests |
| - [Duration](#RPC_RateLimit_SpecialApis_items_Duration ) | No | integer | No | - | Duration defines the time window for the rate limit |

##### <a name="RPC_RateLimit_SpecialApis_items_Api"></a>8.23.5.1.1. `RPC.RateLimit.SpecialApis.SpecialApis items.Api`
##### <a name="RPC_RateLimit_SpecialApis_items_Api"></a>8.24.5.1.1. `RPC.RateLimit.SpecialApis.SpecialApis items.Api`

**Type:** : `string`
**Description:** Api defines the api that need to be rate limited

##### <a name="RPC_RateLimit_SpecialApis_items_Count"></a>8.23.5.1.2. `RPC.RateLimit.SpecialApis.SpecialApis items.Count`
##### <a name="RPC_RateLimit_SpecialApis_items_Count"></a>8.24.5.1.2. `RPC.RateLimit.SpecialApis.SpecialApis items.Count`

**Type:** : `integer`
**Description:** Count defines the maximum burst size of requests

##### <a name="RPC_RateLimit_SpecialApis_items_Duration"></a>8.23.5.1.3. `RPC.RateLimit.SpecialApis.SpecialApis items.Duration`
##### <a name="RPC_RateLimit_SpecialApis_items_Duration"></a>8.24.5.1.3. `RPC.RateLimit.SpecialApis.SpecialApis items.Duration`

**Type:** : `integer`
**Description:** Duration defines the time window for the rate limit

### <a name="RPC_DynamicGP"></a>8.24. `[RPC.DynamicGP]`
### <a name="RPC_DynamicGP"></a>8.25. `[RPC.DynamicGP]`

**Type:** : `object`
**Description:** DynamicGP defines the config of dynamic gas price
@@ -2080,7 +2093,7 @@ SpecialApis=[]
| - [MinPrice](#RPC_DynamicGP_MinPrice ) | No | integer | No | - | MinPrice defines the dynamic gas price lower limit |
| - [UpdatePeriod](#RPC_DynamicGP_UpdatePeriod ) | No | string | No | - | Duration |

#### <a name="RPC_DynamicGP_Enabled"></a>8.24.1. `RPC.DynamicGP.Enabled`
#### <a name="RPC_DynamicGP_Enabled"></a>8.25.1. `RPC.DynamicGP.Enabled`

**Type:** : `boolean`

@@ -2094,7 +2107,7 @@ SpecialApis=[]
Enabled=false
```

#### <a name="RPC_DynamicGP_CongestionTxThreshold"></a>8.24.2. `RPC.DynamicGP.CongestionTxThreshold`
#### <a name="RPC_DynamicGP_CongestionTxThreshold"></a>8.25.2. `RPC.DynamicGP.CongestionTxThreshold`

**Type:** : `integer`

@@ -2108,7 +2121,7 @@ Enabled=false
CongestionTxThreshold=100
```

#### <a name="RPC_DynamicGP_CheckBatches"></a>8.24.3. `RPC.DynamicGP.CheckBatches`
#### <a name="RPC_DynamicGP_CheckBatches"></a>8.25.3. `RPC.DynamicGP.CheckBatches`

**Type:** : `integer`

@@ -2122,7 +2135,7 @@ CongestionTxThreshold=100
CheckBatches=5
```

#### <a name="RPC_DynamicGP_SampleNumber"></a>8.24.4. `RPC.DynamicGP.SampleNumber`
#### <a name="RPC_DynamicGP_SampleNumber"></a>8.25.4. `RPC.DynamicGP.SampleNumber`

**Type:** : `integer`

@@ -2136,7 +2149,7 @@ CheckBatches=5
SampleNumber=3
```

#### <a name="RPC_DynamicGP_Percentile"></a>8.24.5. `RPC.DynamicGP.Percentile`
#### <a name="RPC_DynamicGP_Percentile"></a>8.25.5. `RPC.DynamicGP.Percentile`

**Type:** : `integer`

@@ -2150,7 +2163,7 @@ SampleNumber=3
Percentile=70
```

#### <a name="RPC_DynamicGP_MaxPrice"></a>8.24.6. `RPC.DynamicGP.MaxPrice`
#### <a name="RPC_DynamicGP_MaxPrice"></a>8.25.6. `RPC.DynamicGP.MaxPrice`

**Type:** : `integer`

@@ -2164,7 +2177,7 @@ Percentile=70
MaxPrice=20000000000
```

#### <a name="RPC_DynamicGP_MinPrice"></a>8.24.7. `RPC.DynamicGP.MinPrice`
#### <a name="RPC_DynamicGP_MinPrice"></a>8.25.7. `RPC.DynamicGP.MinPrice`

**Type:** : `integer`

@@ -2178,7 +2191,7 @@ MaxPrice=20000000000
MinPrice=2000000000
```

#### <a name="RPC_DynamicGP_UpdatePeriod"></a>8.24.8. `RPC.DynamicGP.UpdatePeriod`
#### <a name="RPC_DynamicGP_UpdatePeriod"></a>8.25.8. `RPC.DynamicGP.UpdatePeriod`

**Title:** Duration

@@ -2204,7 +2217,7 @@ MinPrice=2000000000
UpdatePeriod="10s"
```

### <a name="RPC_EnableInnerTxCacheDB"></a>8.25. `RPC.EnableInnerTxCacheDB`
### <a name="RPC_EnableInnerTxCacheDB"></a>8.26. `RPC.EnableInnerTxCacheDB`

**Type:** : `boolean`

@@ -2218,12 +2231,12 @@ UpdatePeriod="10s"
EnableInnerTxCacheDB=false
```

### <a name="RPC_BridgeAddress"></a>8.26. `RPC.BridgeAddress`
### <a name="RPC_BridgeAddress"></a>8.27. `RPC.BridgeAddress`

**Type:** : `array of integer`
**Description:** BridgeAddress is the address of the bridge contract

### <a name="RPC_ApiAuthentication"></a>8.27. `[RPC.ApiAuthentication]`
### <a name="RPC_ApiAuthentication"></a>8.28. `[RPC.ApiAuthentication]`

**Type:** : `object`
**Description:** ApiAuthentication defines the authentication configuration for the API
@@ -2233,7 +2246,7 @@ EnableInnerTxCacheDB=false
| - [Enabled](#RPC_ApiAuthentication_Enabled ) | No | boolean | No | - | Enabled defines if the api authentication is enabled |
| - [ApiKeys](#RPC_ApiAuthentication_ApiKeys ) | No | array of object | No | - | ApiKeys defines the api keys |

#### <a name="RPC_ApiAuthentication_Enabled"></a>8.27.1. `RPC.ApiAuthentication.Enabled`
#### <a name="RPC_ApiAuthentication_Enabled"></a>8.28.1. `RPC.ApiAuthentication.Enabled`

**Type:** : `boolean`

@@ -2247,7 +2260,7 @@ EnableInnerTxCacheDB=false
Enabled=false
```

#### <a name="RPC_ApiAuthentication_ApiKeys"></a>8.27.2. `RPC.ApiAuthentication.ApiKeys`
#### <a name="RPC_ApiAuthentication_ApiKeys"></a>8.28.2. `RPC.ApiAuthentication.ApiKeys`

**Type:** : `array of object`

@@ -2273,7 +2286,7 @@ ApiKeys=[]
| ----------------------------------------------------- | --------------------------- |
| [ApiKeys items](#RPC_ApiAuthentication_ApiKeys_items) | KeyItem is the api key item |

##### <a name="autogenerated_heading_4"></a>8.27.2.1. [RPC.ApiAuthentication.ApiKeys.ApiKeys items]
##### <a name="autogenerated_heading_4"></a>8.28.2.1. [RPC.ApiAuthentication.ApiKeys.ApiKeys items]

**Type:** : `object`
**Description:** KeyItem is the api key item
@@ -2284,22 +2297,22 @@ ApiKeys=[]
| - [Key](#RPC_ApiAuthentication_ApiKeys_items_Key ) | No | string | No | - | Key defines the key |
| - [Timeout](#RPC_ApiAuthentication_ApiKeys_items_Timeout ) | No | string | No | - | Timeout defines the timeout |

##### <a name="RPC_ApiAuthentication_ApiKeys_items_Project"></a>8.27.2.1.1. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Project`
##### <a name="RPC_ApiAuthentication_ApiKeys_items_Project"></a>8.28.2.1.1. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Project`

**Type:** : `string`
**Description:** Name defines the name of the key

##### <a name="RPC_ApiAuthentication_ApiKeys_items_Key"></a>8.27.2.1.2. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Key`
##### <a name="RPC_ApiAuthentication_ApiKeys_items_Key"></a>8.28.2.1.2. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Key`

**Type:** : `string`
**Description:** Key defines the key

##### <a name="RPC_ApiAuthentication_ApiKeys_items_Timeout"></a>8.27.2.1.3. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Timeout`
##### <a name="RPC_ApiAuthentication_ApiKeys_items_Timeout"></a>8.28.2.1.3. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Timeout`

**Type:** : `string`
**Description:** Timeout defines the timeout

### <a name="RPC_ApiRelay"></a>8.28. `[RPC.ApiRelay]`
### <a name="RPC_ApiRelay"></a>8.29. `[RPC.ApiRelay]`

**Type:** : `object`
**Description:** ApiRelay defines the relay configuration for the API
@@ -2310,7 +2323,7 @@ ApiKeys=[]
| - [DestURI](#RPC_ApiRelay_DestURI ) | No | string | No | - | - |
| - [RPCs](#RPC_ApiRelay_RPCs ) | No | array of string | No | - | - |

#### <a name="RPC_ApiRelay_Enabled"></a>8.28.1. `RPC.ApiRelay.Enabled`
#### <a name="RPC_ApiRelay_Enabled"></a>8.29.1. `RPC.ApiRelay.Enabled`

**Type:** : `boolean`

@@ -2322,7 +2335,7 @@ ApiKeys=[]
Enabled=false
```

#### <a name="RPC_ApiRelay_DestURI"></a>8.28.2. `RPC.ApiRelay.DestURI`
#### <a name="RPC_ApiRelay_DestURI"></a>8.29.2. `RPC.ApiRelay.DestURI`

**Type:** : `string`

@@ -2334,7 +2347,7 @@ Enabled=false
DestURI=""
```

#### <a name="RPC_ApiRelay_RPCs"></a>8.28.3. `RPC.ApiRelay.RPCs`
#### <a name="RPC_ApiRelay_RPCs"></a>8.29.3. `RPC.ApiRelay.RPCs`

**Type:** : `array of string`

4 changes: 4 additions & 0 deletions docs/config-file/node-config-schema.json
Original file line number Diff line number Diff line change
@@ -727,6 +727,10 @@
"description": "GasLimitFactor is used to multiply the suggested gas provided by the network\nin order to allow a enough gas to be set for all the transactions default value is 1.\n\nex:\nsuggested gas limit: 100\nGasLimitFactor: 1\ngas limit = 100\n\nsuggested gas limit: 100\nGasLimitFactor: 1.1\ngas limit = 110",
"default": 1
},
"EnableEstimateGasOpt": {
"type": "boolean",
"default": false
},
"DisableAPIs": {
"items": {
"type": "string"
2 changes: 2 additions & 0 deletions jsonrpc/apollo_xlayer.go
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ type ApolloConfig struct {
BatchRequestsEnabled bool
BatchRequestsLimit uint
GasLimitFactor float64
EnableEstimateGasOpt bool
DisableAPIs []string
RateLimit RateLimitConfig
DynamicGP DynamicGPConfig
@@ -63,6 +64,7 @@ func UpdateConfig(apolloConfig Config) {
getApolloConfig().BatchRequestsEnabled = apolloConfig.BatchRequestsEnabled
getApolloConfig().BatchRequestsLimit = apolloConfig.BatchRequestsLimit
getApolloConfig().GasLimitFactor = apolloConfig.GasLimitFactor
getApolloConfig().EnableEstimateGasOpt = apolloConfig.EnableEstimateGasOpt
getApolloConfig().setDisableAPIs(apolloConfig.DisableAPIs)
setRateLimit(apolloConfig.RateLimit)
setApiAuth(apolloConfig.ApiAuthentication)
3 changes: 2 additions & 1 deletion jsonrpc/config.go
Original file line number Diff line number Diff line change
@@ -87,7 +87,8 @@ type Config struct {
// suggested gas limit: 100
// GasLimitFactor: 1.1
// gas limit = 110
GasLimitFactor float64 `mapstructure:"GasLimitFactor"`
GasLimitFactor float64 `mapstructure:"GasLimitFactor"`
EnableEstimateGasOpt bool `mapstructure:"EnableEstimateGasOpt"`

// DisableAPIs disable some API
DisableAPIs []string `mapstructure:"DisableAPIs"`
8 changes: 7 additions & 1 deletion jsonrpc/endpoints_eth.go
Original file line number Diff line number Diff line change
@@ -207,7 +207,13 @@ func (e *EthEndpoints) EstimateGas(arg *types.TxArgs, blockArg *types.BlockNumbe
t2 := time.Now()
toTxTime := t2.Sub(t1)

gasEstimation, returnValue, err := e.state.EstimateGas(tx, sender, isGasFreeSender, blockToProcess, dbTx)
var gasEstimation uint64
var returnValue []byte
if e.enableEstimateGasOpt() {
gasEstimation, returnValue, err = e.state.EstimateGasOpt(tx, sender, isGasFreeSender, blockToProcess, dbTx)
} else {
gasEstimation, returnValue, err = e.state.EstimateGas(tx, sender, isGasFreeSender, blockToProcess, dbTx)
}
if errors.Is(err, runtime.ErrExecutionReverted) {
data := make([]byte, len(returnValue))
copy(data, returnValue)
16 changes: 16 additions & 0 deletions jsonrpc/endpoints_eth_xlayer.go
Original file line number Diff line number Diff line change
@@ -278,9 +278,25 @@ func (e *EthEndpoints) getGasEstimationWithFactorXLayer(gasEstimation uint64) ui
if gasLimitFactor > 0 {
gasEstimationWithFactor = uint64(float64(gasEstimation) * gasLimitFactor)
}
if gasEstimationWithFactor > state.MaxTxGasLimit {
gasEstimationWithFactor = state.MaxTxGasLimit
}
return gasEstimationWithFactor
}

func (e *EthEndpoints) enableEstimateGasOpt() bool {
res := false
if getApolloConfig().Enable() {
getApolloConfig().RLock()
res = getApolloConfig().EnableEstimateGasOpt
getApolloConfig().RUnlock()
} else {
res = e.cfg.EnableEstimateGasOpt
}

return res
}

// internal
func (e *EthEndpoints) newPendingTransactionFilterXLayer(wsConn *concurrentWsConn) (interface{}, types.Error) {
//XLayer handle
5 changes: 5 additions & 0 deletions jsonrpc/mocks/mock_state.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions jsonrpc/types/interfaces.go
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@ type StateInterface interface {
BeginStateTransaction(ctx context.Context) (pgx.Tx, error)
DebugTransaction(ctx context.Context, transactionHash common.Hash, traceConfig state.TraceConfig, dbTx pgx.Tx) (*runtime.ExecutionResult, error)
EstimateGas(transaction *types.Transaction, senderAddress common.Address, isGasFreeSender bool, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, []byte, error)
EstimateGasOpt(transaction *types.Transaction, senderAddress common.Address, isGasFreeSender bool, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, []byte, error)
GetBalance(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error)
GetCode(ctx context.Context, address common.Address, root common.Hash) ([]byte, error)
GetL2BlockByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*state.L2Block, error)
3 changes: 3 additions & 0 deletions state/transaction.go
Original file line number Diff line number Diff line change
@@ -863,6 +863,8 @@ func (s *State) EstimateGas(transaction *types.Transaction, senderAddress common
if lowEnd < estimationResult.gasUsed {
lowEnd = estimationResult.gasUsed
}
firstLowEnd := lowEnd
firstGasued := estimationResult.gasUsed

optimisticGasLimit := (estimationResult.gasUsed + estimationResult.gasRefund + params.CallStipend) * 64 / 63 // nolint:gomnd
if optimisticGasLimit < highEnd {
@@ -927,6 +929,7 @@ func (s *State) EstimateGas(transaction *types.Transaction, senderAddress common
}
log.Infof("state-EstimateGas time. getBlock:%vms, getBatch:%vms, getForkID:%vms, getNonce:%vms, getEnd:%vms, internalGas:%vms, exec:%vms",
getBlockTime.Milliseconds(), getBatchTime.Milliseconds(), getForkIDTime.Milliseconds(), getNonceTime.Milliseconds(), getEndTime.Milliseconds(), internalGasTime.Milliseconds(), time.Since(t6).Milliseconds())
log.Infof("state-EstimateGas value.firstLowEnd:%d, first gasUsed:%d, final gas:%d, factor:%f", firstLowEnd, firstGasued, highEnd, float64(highEnd)/float64(firstGasued))

return highEnd, nil, nil
}
166 changes: 166 additions & 0 deletions state/transaction_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package state

import (
"context"
"errors"
"fmt"
"math/big"
"time"

"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/jackc/pgx/v4"
)

// EstimateGasOpt for a transaction
func (s *State) EstimateGasOpt(transaction *types.Transaction, senderAddress common.Address, isGasFreeSender bool, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, []byte, error) {
const ethTransferGas = 21000

ctx := context.Background()

t0 := time.Now()

var l2Block *L2Block
var err error
if l2BlockNumber == nil {
l2Block, err = s.GetLastL2Block(ctx, dbTx)
} else {
l2Block, err = s.GetL2BlockByNumber(ctx, *l2BlockNumber, dbTx)
}
if err != nil {
return 0, nil, err
}

t1 := time.Now()
getBlockTime := t1.Sub(t0)

batch, err := s.GetBatchByL2BlockNumber(ctx, l2Block.NumberU64(), dbTx)
if err != nil {
return 0, nil, err
}

t2 := time.Now()
getBatchTime := t2.Sub(t1)

forkID := s.GetForkIDByBatchNumber(batch.BatchNumber)
latestL2BlockNumber, err := s.GetLastL2BlockNumber(ctx, dbTx)
if err != nil {
return 0, nil, err
}

t3 := time.Now()
getForkIDTime := t3.Sub(t2)

loadedNonce, err := s.tree.GetNonce(ctx, senderAddress, l2Block.Root().Bytes())
if err != nil {
return 0, nil, err
}
nonce := loadedNonce.Uint64()

t4 := time.Now()
getNonceTime := t4.Sub(t3)

highEnd := MaxTxGasLimit

// if gas price is set, set the highEnd to the max amount
// of the account afford
isGasPriceSet := !isGasFreeSender && transaction.GasPrice().BitLen() != 0
if isGasPriceSet {
senderBalance, err := s.tree.GetBalance(ctx, senderAddress, l2Block.Root().Bytes())
if errors.Is(err, ErrNotFound) {
senderBalance = big.NewInt(0)
} else if err != nil {
return 0, nil, err
}

availableBalance := new(big.Int).Set(senderBalance)
// check if the account has funds to pay the transfer value
if transaction.Value() != nil {
if transaction.Value().Cmp(availableBalance) > 0 {
return 0, nil, ErrInsufficientFundsForTransfer
}

// deduct the value from the available balance
availableBalance.Sub(availableBalance, transaction.Value())
}

// Check the gas allowance for this account, make sure high end is capped to it
gasAllowance := new(big.Int).Div(availableBalance, transaction.GasPrice())
if gasAllowance.IsUint64() && highEnd > gasAllowance.Uint64() {
log.Debugf("Gas estimation high-end capped by allowance [%d]", gasAllowance.Uint64())
highEnd = gasAllowance.Uint64()
}
}

// if the tx gas is set and it is smaller than the highEnd,
// limit the highEnd to the maximum allowed by the tx gas
if transaction.Gas() != 0 && transaction.Gas() < highEnd {
highEnd = transaction.Gas()
}

// set start values for lowEnd and highEnd:
lowEnd, err := core.IntrinsicGas(transaction.Data(), transaction.AccessList(), s.isContractCreation(transaction), true, false, false)
if err != nil {
return 0, nil, err
}

// if the intrinsic gas is the same as the constant value for eth transfer
// and the transaction has a receiver address
if lowEnd == ethTransferGas && transaction.To() != nil {
receiver := *transaction.To()
// check if the receiver address is not a smart contract
code, err := s.tree.GetCode(ctx, receiver, l2Block.Root().Bytes())
if err != nil {
log.Warnf("error while getting code for address %v: %v", receiver.String(), err)
} else if len(code) == 0 {
// in case it is just an account, we can avoid the execution and return
// the transfer constant amount
return lowEnd, nil, nil
}
}

t5 := time.Now()
getEndTime := t5.Sub(t4)

// testTransaction runs the transaction with the specified gas value.
// it returns a status indicating if the transaction has failed, if it
// was reverted and the accompanying error

// Check if the highEnd is a good value to make the transaction pass, if it fails we
// can return immediately.
log.Debugf("Estimate gas. Trying to execute TX with %v gas", highEnd)
var estimationResult *testGasEstimationResult
if forkID < FORKID_ETROG {
estimationResult, err = s.internalTestGasEstimationTransactionV1(ctx, batch, l2Block, latestL2BlockNumber, transaction, forkID, senderAddress, isGasFreeSender, highEnd, nonce, false)
} else {
estimationResult, err = s.internalTestGasEstimationTransactionV2(ctx, batch, l2Block, latestL2BlockNumber, transaction, forkID, senderAddress, isGasFreeSender, highEnd, nonce, false)
}
if err != nil {
return 0, nil, err
}
if estimationResult.failed {
if estimationResult.reverted {
return 0, estimationResult.returnValue, estimationResult.executionError
}

if estimationResult.ooc {
return 0, nil, estimationResult.executionError
}

// The transaction shouldn't fail, for whatever reason, at highEnd
return 0, nil, fmt.Errorf(
"gas required exceeds allowance (%d)",
highEnd,
)
}

t6 := time.Now()
internalGasTime := t6.Sub(t5)

log.Infof("state-EstimateGas time. getBlock:%vms, getBatch:%vms, getForkID:%vms, getNonce:%vms, getEnd:%vms, internalGas:%vms",
getBlockTime.Milliseconds(), getBatchTime.Milliseconds(), getForkIDTime.Milliseconds(), getNonceTime.Milliseconds(), getEndTime.Milliseconds(), internalGasTime.Milliseconds())

return estimationResult.gasUsed, nil, nil
}

0 comments on commit 889bf00

Please sign in to comment.