diff --git a/docs/config-file/node-config-doc.html b/docs/config-file/node-config-doc.html index a12f577869..a07f59acaf 100644 --- a/docs/config-file/node-config-doc.html +++ b/docs/config-file/node-config-doc.html @@ -18,7 +18,7 @@
"300ms"
WriteTimeout is the HTTP server write timeout
check net/http.server.WriteTimeout
"1m"
"300ms"
-
MaxRequestsPerIPAndSecond defines how much requests a single IP can
send within a single second
SequencerNodeURI is used allow Non-Sequencer nodes
to relay transactions to the Sequencer node
MaxCumulativeGasUsed is the max gas allowed per batch
Enabled defines if the WebSocket requests are enabled or disabled
Host defines the network adapter that will be used to serve the WS requests
Port defines the port to serve the endpoints via WS
ReadLimit defines the maximum size of a message read from the client (in bytes)
EnableL2SuggestedGasPricePolling enables polling of the L2 gas price to block tx in the RPC with lower gas price.
BatchRequestsEnabled defines if the Batch requests are enabled or disabled
BatchRequestsLimit defines the limit of requests that can be incorporated into each batch request
L2Coinbase defines which address is going to receive the fees
Must contain a minimum of 20
items
Must contain a maximum of 20
items
MaxLogsCount is a configuration to set the max number of logs that can be returned
in a single call to the state, if zero it means no limit
MaxLogsBlockRange is a configuration to set the max range for block number when querying TXs
logs in a single call to the state, if zero it means no limit
MaxNativeBlockHashBlockRange is a configuration to set the max range for block number when querying
native block hashes in a single call to the state, if zero it means no limit
EnableHttpLog allows the user to enable or disable the logs related to the HTTP
requests to be captured by the server.
XLayer config
EnablePendingTransactionFilter enables pending transaction filter that can support query L2 pending transaction
URLs nacos server urls for discovery service of rest api, url is separated by ","
NamespaceId nacos namepace id for discovery service of rest api
ApplicationName rest application name in nacos
ExternalListenAddr Set the rest-server external ip and port, when it is launched by Docker
URLs nacos server urls for discovery service of rest api, url is separated by ","
NamespaceId nacos namepace id for discovery service of rest api
ApplicationName rest application name in nacos
ExternalListenAddr Set the rest-server external ip and port, when it is launched by Docker
GasLimitFactor is used to multiply the suggested gas provided by the network
in order to allow a enough gas to be set for all the transactions default value is 1.
ex:
suggested gas limit: 100
GasLimitFactor: 1
gas limit = 100
suggested gas limit: 100
GasLimitFactor: 1.1
gas limit = 110
DisableAPIs disable some API
Enabled defines if the rate limit is enabled or disabled
RateLimitApis defines the apis that need to be rate limited
RateLimitBurst defines the maximum burst size of requests
RateLimitDuration defines the time window for the rate limit
SpecialApis defines the apis that need to be rate limited with special rate limit
Api defines the api that need to be rate limited
Count defines the maximum burst size of requests
Duration defines the time window for the rate limit
Enabled defines if the dynamic gas price is enabled or disabled
CongestionTxThreshold defines the tx threshold to measure whether there is congestion
CheckBatches defines the number of recent Batches used to sample gas price
SampleTxNumer defines the number of sampled gas prices in each batch
Percentile defines the sampling weight of all sampled gas prices
MaxPrice defines the dynamic gas price upper limit
MinPrice defines the dynamic gas price lower limit
UpdatePeriod defines the time interval for updating dynamic gas price
"1m"
+
MaxRequestsPerIPAndSecond defines how much requests a single IP can
send within a single second
SequencerNodeURI is used allow Non-Sequencer nodes
to relay transactions to the Sequencer node
MaxCumulativeGasUsed is the max gas allowed per batch
Enabled defines if the WebSocket requests are enabled or disabled
Host defines the network adapter that will be used to serve the WS requests
Port defines the port to serve the endpoints via WS
ReadLimit defines the maximum size of a message read from the client (in bytes)
EnableL2SuggestedGasPricePolling enables polling of the L2 gas price to block tx in the RPC with lower gas price.
BatchRequestsEnabled defines if the Batch requests are enabled or disabled
BatchRequestsLimit defines the limit of requests that can be incorporated into each batch request
L2Coinbase defines which address is going to receive the fees
Must contain a minimum of 20
items
Must contain a maximum of 20
items
MaxLogsCount is a configuration to set the max number of logs that can be returned
in a single call to the state, if zero it means no limit
MaxLogsBlockRange is a configuration to set the max range for block number when querying TXs
logs in a single call to the state, if zero it means no limit
MaxNativeBlockHashBlockRange is a configuration to set the max range for block number when querying
native block hashes in a single call to the state, if zero it means no limit
EnableHttpLog allows the user to enable or disable the logs related to the HTTP
requests to be captured by the server.
XLayer config
EnablePendingTransactionFilter enables pending transaction filter that can support query L2 pending transaction
URLs nacos server urls for discovery service of rest api, url is separated by ","
NamespaceId nacos namepace id for discovery service of rest api
ApplicationName rest application name in nacos
ExternalListenAddr Set the rest-server external ip and port, when it is launched by Docker
URLs nacos server urls for discovery service of rest api, url is separated by ","
NamespaceId nacos namepace id for discovery service of rest api
ApplicationName rest application name in nacos
ExternalListenAddr Set the rest-server external ip and port, when it is launched by Docker
GasLimitFactor is used to multiply the suggested gas provided by the network
in order to allow a enough gas to be set for all the transactions default value is 1.
ex:
suggested gas limit: 100
GasLimitFactor: 1
gas limit = 100
suggested gas limit: 100
GasLimitFactor: 1.1
gas limit = 110
DisableAPIs disable some API
Enabled defines if the rate limit is enabled or disabled
RateLimitApis defines the apis that need to be rate limited
RateLimitBurst defines the maximum burst size of requests
RateLimitDuration defines the time window for the rate limit
SpecialApis defines the apis that need to be rate limited with special rate limit
Api defines the api that need to be rate limited
Count defines the maximum burst size of requests
Duration defines the time window for the rate limit
Enabled defines if the dynamic gas price is enabled or disabled
CongestionTxThreshold defines the tx threshold to measure whether there is congestion
CheckBatches defines the number of recent Batches used to sample gas price
SampleTxNumer defines the number of sampled gas prices in each batch
Percentile defines the sampling weight of all sampled gas prices
MaxPrice defines the dynamic gas price upper limit
MinPrice defines the dynamic gas price lower limit
UpdatePeriod defines the time interval for updating dynamic gas price
"1m"
"300ms"
EnableInnerTxCacheDB enables the inner tx cache db
BridgeAddress is the address of the bridge contract
Must contain a minimum of 20
items
Must contain a maximum of 20
items
Enabled defines if the api authentication is enabled
ApiKeys defines the api keys
Name defines the name of the key
Key defines the key
Timeout defines the timeout
SyncInterval is the delay interval between reading new rollup information
"1m"
"300ms"
diff --git a/docs/config-file/node-config-doc.md b/docs/config-file/node-config-doc.md
index dc55845efc..986e0cefc0 100644
--- a/docs/config-file/node-config-doc.md
+++ b/docs/config-file/node-config-doc.md
@@ -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
in order to allow a enough gas to be set for all the transactions default value is 1.
ex:
suggested gas limit: 100
GasLimitFactor: 1
gas limit = 100
suggested gas limit: 100
GasLimitFactor: 1.1
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
```
-### 8.22. `RPC.DisableAPIs`
+### 8.22. `RPC.EnableEstimateGasOpt`
+
+**Type:** : `boolean`
+
+**Default:** `false`
+
+**Example setting the default value** (false):
+```
+[RPC]
+EnableEstimateGasOpt=false
+```
+
+### 8.23. `RPC.DisableAPIs`
**Type:** : `array of string`
@@ -1943,7 +1956,7 @@ GasLimitFactor=1
DisableAPIs=[]
```
-### 8.23. `[RPC.RateLimit]`
+### 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 |
-#### 8.23.1. `RPC.RateLimit.Enabled`
+#### 8.24.1. `RPC.RateLimit.Enabled`
**Type:** : `boolean`
@@ -1970,7 +1983,7 @@ DisableAPIs=[]
Enabled=false
```
-#### 8.23.2. `RPC.RateLimit.RateLimitApis`
+#### 8.24.2. `RPC.RateLimit.RateLimitApis`
**Type:** : `array of string`
@@ -1984,7 +1997,7 @@ Enabled=false
RateLimitApis=[]
```
-#### 8.23.3. `RPC.RateLimit.RateLimitCount`
+#### 8.24.3. `RPC.RateLimit.RateLimitCount`
**Type:** : `integer`
@@ -1998,7 +2011,7 @@ RateLimitApis=[]
RateLimitCount=100
```
-#### 8.23.4. `RPC.RateLimit.RateLimitDuration`
+#### 8.24.4. `RPC.RateLimit.RateLimitDuration`
**Type:** : `integer`
@@ -2012,7 +2025,7 @@ RateLimitCount=100
RateLimitDuration=1
```
-#### 8.23.5. `RPC.RateLimit.SpecialApis`
+#### 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 |
-##### 8.23.5.1. [RPC.RateLimit.SpecialApis.SpecialApis items]
+##### 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 |
-##### 8.23.5.1.1. `RPC.RateLimit.SpecialApis.SpecialApis items.Api`
+##### 8.24.5.1.1. `RPC.RateLimit.SpecialApis.SpecialApis items.Api`
**Type:** : `string`
**Description:** Api defines the api that need to be rate limited
-##### 8.23.5.1.2. `RPC.RateLimit.SpecialApis.SpecialApis items.Count`
+##### 8.24.5.1.2. `RPC.RateLimit.SpecialApis.SpecialApis items.Count`
**Type:** : `integer`
**Description:** Count defines the maximum burst size of requests
-##### 8.23.5.1.3. `RPC.RateLimit.SpecialApis.SpecialApis items.Duration`
+##### 8.24.5.1.3. `RPC.RateLimit.SpecialApis.SpecialApis items.Duration`
**Type:** : `integer`
**Description:** Duration defines the time window for the rate limit
-### 8.24. `[RPC.DynamicGP]`
+### 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 |
-#### 8.24.1. `RPC.DynamicGP.Enabled`
+#### 8.25.1. `RPC.DynamicGP.Enabled`
**Type:** : `boolean`
@@ -2094,7 +2107,7 @@ SpecialApis=[]
Enabled=false
```
-#### 8.24.2. `RPC.DynamicGP.CongestionTxThreshold`
+#### 8.25.2. `RPC.DynamicGP.CongestionTxThreshold`
**Type:** : `integer`
@@ -2108,7 +2121,7 @@ Enabled=false
CongestionTxThreshold=100
```
-#### 8.24.3. `RPC.DynamicGP.CheckBatches`
+#### 8.25.3. `RPC.DynamicGP.CheckBatches`
**Type:** : `integer`
@@ -2122,7 +2135,7 @@ CongestionTxThreshold=100
CheckBatches=5
```
-#### 8.24.4. `RPC.DynamicGP.SampleNumber`
+#### 8.25.4. `RPC.DynamicGP.SampleNumber`
**Type:** : `integer`
@@ -2136,7 +2149,7 @@ CheckBatches=5
SampleNumber=3
```
-#### 8.24.5. `RPC.DynamicGP.Percentile`
+#### 8.25.5. `RPC.DynamicGP.Percentile`
**Type:** : `integer`
@@ -2150,7 +2163,7 @@ SampleNumber=3
Percentile=70
```
-#### 8.24.6. `RPC.DynamicGP.MaxPrice`
+#### 8.25.6. `RPC.DynamicGP.MaxPrice`
**Type:** : `integer`
@@ -2164,7 +2177,7 @@ Percentile=70
MaxPrice=20000000000
```
-#### 8.24.7. `RPC.DynamicGP.MinPrice`
+#### 8.25.7. `RPC.DynamicGP.MinPrice`
**Type:** : `integer`
@@ -2178,7 +2191,7 @@ MaxPrice=20000000000
MinPrice=2000000000
```
-#### 8.24.8. `RPC.DynamicGP.UpdatePeriod`
+#### 8.25.8. `RPC.DynamicGP.UpdatePeriod`
**Title:** Duration
@@ -2204,7 +2217,7 @@ MinPrice=2000000000
UpdatePeriod="10s"
```
-### 8.25. `RPC.EnableInnerTxCacheDB`
+### 8.26. `RPC.EnableInnerTxCacheDB`
**Type:** : `boolean`
@@ -2218,12 +2231,12 @@ UpdatePeriod="10s"
EnableInnerTxCacheDB=false
```
-### 8.26. `RPC.BridgeAddress`
+### 8.27. `RPC.BridgeAddress`
**Type:** : `array of integer`
**Description:** BridgeAddress is the address of the bridge contract
-### 8.27. `[RPC.ApiAuthentication]`
+### 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 |
-#### 8.27.1. `RPC.ApiAuthentication.Enabled`
+#### 8.28.1. `RPC.ApiAuthentication.Enabled`
**Type:** : `boolean`
@@ -2247,7 +2260,7 @@ EnableInnerTxCacheDB=false
Enabled=false
```
-#### 8.27.2. `RPC.ApiAuthentication.ApiKeys`
+#### 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 |
-##### 8.27.2.1. [RPC.ApiAuthentication.ApiKeys.ApiKeys items]
+##### 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 |
-##### 8.27.2.1.1. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Project`
+##### 8.28.2.1.1. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Project`
**Type:** : `string`
**Description:** Name defines the name of the key
-##### 8.27.2.1.2. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Key`
+##### 8.28.2.1.2. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Key`
**Type:** : `string`
**Description:** Key defines the key
-##### 8.27.2.1.3. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Timeout`
+##### 8.28.2.1.3. `RPC.ApiAuthentication.ApiKeys.ApiKeys items.Timeout`
**Type:** : `string`
**Description:** Timeout defines the timeout
-### 8.28. `[RPC.ApiRelay]`
+### 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 | - | - |
-#### 8.28.1. `RPC.ApiRelay.Enabled`
+#### 8.29.1. `RPC.ApiRelay.Enabled`
**Type:** : `boolean`
@@ -2322,7 +2335,7 @@ ApiKeys=[]
Enabled=false
```
-#### 8.28.2. `RPC.ApiRelay.DestURI`
+#### 8.29.2. `RPC.ApiRelay.DestURI`
**Type:** : `string`
@@ -2334,7 +2347,7 @@ Enabled=false
DestURI=""
```
-#### 8.28.3. `RPC.ApiRelay.RPCs`
+#### 8.29.3. `RPC.ApiRelay.RPCs`
**Type:** : `array of string`
diff --git a/docs/config-file/node-config-schema.json b/docs/config-file/node-config-schema.json
index 7f220848ec..df973e70e8 100644
--- a/docs/config-file/node-config-schema.json
+++ b/docs/config-file/node-config-schema.json
@@ -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"
diff --git a/jsonrpc/apollo_xlayer.go b/jsonrpc/apollo_xlayer.go
index ecb6dee4f6..156625f98e 100644
--- a/jsonrpc/apollo_xlayer.go
+++ b/jsonrpc/apollo_xlayer.go
@@ -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)
diff --git a/jsonrpc/config.go b/jsonrpc/config.go
index fe9f2b202f..53ec1e6053 100644
--- a/jsonrpc/config.go
+++ b/jsonrpc/config.go
@@ -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"`
diff --git a/jsonrpc/endpoints_eth.go b/jsonrpc/endpoints_eth.go
index 9b67934cdf..fa3f359ef5 100644
--- a/jsonrpc/endpoints_eth.go
+++ b/jsonrpc/endpoints_eth.go
@@ -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)
diff --git a/jsonrpc/endpoints_eth_xlayer.go b/jsonrpc/endpoints_eth_xlayer.go
index 2ab478108d..36ca8be500 100644
--- a/jsonrpc/endpoints_eth_xlayer.go
+++ b/jsonrpc/endpoints_eth_xlayer.go
@@ -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
diff --git a/jsonrpc/mocks/mock_state.go b/jsonrpc/mocks/mock_state.go
index bc9070e6a6..5c93ab7272 100644
--- a/jsonrpc/mocks/mock_state.go
+++ b/jsonrpc/mocks/mock_state.go
@@ -151,6 +151,11 @@ func (_m *StateMock) EstimateGas(transaction *coretypes.Transaction, senderAddre
return r0, r1, r2
}
+// EstimateGasOpt provides a mock function with given fields: transaction, senderAddress, l2BlockNumber, dbTx
+func (_m *StateMock) EstimateGasOpt(transaction *coretypes.Transaction, senderAddress common.Address, isGasFreeSender bool, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, []byte, error) {
+ return _m.EstimateGas(transaction, senderAddress, isGasFreeSender, l2BlockNumber, dbTx)
+}
+
// GetBalance provides a mock function with given fields: ctx, address, root
func (_m *StateMock) GetBalance(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) {
ret := _m.Called(ctx, address, root)
diff --git a/jsonrpc/types/interfaces.go b/jsonrpc/types/interfaces.go
index c09dcdc0ce..f733df5eb2 100644
--- a/jsonrpc/types/interfaces.go
+++ b/jsonrpc/types/interfaces.go
@@ -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)
diff --git a/state/transaction.go b/state/transaction.go
index ef62cc14fe..2fd7562377 100644
--- a/state/transaction.go
+++ b/state/transaction.go
@@ -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
}
diff --git a/state/transaction_xlayer.go b/state/transaction_xlayer.go
new file mode 100644
index 0000000000..7cc3186eef
--- /dev/null
+++ b/state/transaction_xlayer.go
@@ -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
+}