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

Add lru for eth_call #230

Closed
wants to merge 14 commits into from
Closed
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
3 changes: 3 additions & 0 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ DisableAPIs = []
Enabled = false
DestURI = ""
RPCs = []
[RPC.LRUConfig]
Enable = false
Size = 1000

[Synchronizer]
SyncInterval = "1s"
Expand Down
2 changes: 1 addition & 1 deletion docs/config-file/node-config-doc.html

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions docs/config-file/node-config-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,7 @@ FreeGasLimit=0
| - [BridgeAddress](#RPC_BridgeAddress ) | No | array of integer | No | - | BridgeAddress is the address of the bridge contract |
| - [ApiAuthentication](#RPC_ApiAuthentication ) | No | object | No | - | ApiAuthentication defines the authentication configuration for the API |
| - [ApiRelay](#RPC_ApiRelay ) | No | object | No | - | ApiRelay defines the relay configuration for the API |
| - [LRUConfig](#RPC_LRUConfig ) | No | object | No | - | LRUConfig defines the LRU cache configuration |

### <a name="RPC_Host"></a>8.1. `RPC.Host`

Expand Down Expand Up @@ -2372,6 +2373,40 @@ DestURI=""
RPCs=[]
```

### <a name="RPC_LRUConfig"></a>8.31. `[RPC.LRUConfig]`

**Type:** : `object`
**Description:** LRUConfig defines the LRU cache configuration

| Property | Pattern | Type | Deprecated | Definition | Title/Description |
| ---------------------------------- | ------- | ------- | ---------- | ---------- | ----------------- |
| - [Enable](#RPC_LRUConfig_Enable ) | No | boolean | No | - | - |
| - [Size](#RPC_LRUConfig_Size ) | No | integer | No | - | - |

#### <a name="RPC_LRUConfig_Enable"></a>8.31.1. `RPC.LRUConfig.Enable`

**Type:** : `boolean`

**Default:** `false`

**Example setting the default value** (false):
```
[RPC.LRUConfig]
Enable=false
```

#### <a name="RPC_LRUConfig_Size"></a>8.31.2. `RPC.LRUConfig.Size`

**Type:** : `integer`

**Default:** `1000`

**Example setting the default value** (1000):
```
[RPC.LRUConfig]
Size=1000
```

## <a name="Synchronizer"></a>9. `[Synchronizer]`

**Type:** : `object`
Expand Down
15 changes: 15 additions & 0 deletions docs/config-file/node-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,21 @@
"additionalProperties": false,
"type": "object",
"description": "ApiRelay defines the relay configuration for the API"
},
"LRUConfig": {
"properties": {
"Enable": {
"type": "boolean",
"default": false
},
"Size": {
"type": "integer",
"default": 1000
}
},
"additionalProperties": false,
"type": "object",
"description": "LRUConfig defines the LRU cache configuration"
}
},
"additionalProperties": false,
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ require (
github.com/0xPolygon/cdk-data-availability v0.0.5
github.com/apolloconfig/agollo/v4 v4.0.9
github.com/fatih/color v1.16.0
github.com/hashicorp/golang-lru v1.0.2
github.com/nacos-group/nacos-sdk-go v1.1.4
github.com/prometheus/client_golang v1.18.0
github.com/segmentio/kafka-go v0.4.47
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
Expand Down
2 changes: 2 additions & 0 deletions jsonrpc/apollo_xlayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package jsonrpc
import (
"sync"

"github.com/0xPolygonHermez/zkevm-node/jsonrpc/lru_xlayer"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/types"
)

Expand Down Expand Up @@ -72,6 +73,7 @@ func UpdateConfig(apolloConfig Config) {
setApiAuth(apolloConfig.ApiAuthentication)
getApolloConfig().DynamicGP = apolloConfig.DynamicGP
getApolloConfig().setApiRelayCfg(apolloConfig.ApiRelay)
lru_xlayer.SetConfig(apolloConfig.LRUConfig)
getApolloConfig().Unlock()
}

Expand Down
4 changes: 4 additions & 0 deletions jsonrpc/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package jsonrpc

import (
"github.com/0xPolygonHermez/zkevm-node/config/types"
lru "github.com/0xPolygonHermez/zkevm-node/jsonrpc/lru_xlayer"
"github.com/ethereum/go-ethereum/common"
)

Expand Down Expand Up @@ -111,6 +112,9 @@ type Config struct {

// ApiRelay defines the relay configuration for the API
ApiRelay ApiRelayConfig `mapstructure:"ApiRelay"`

// LRUConfig defines the LRU cache configuration
LRUConfig lru.Config `mapstructure:"LRUConfig"`
}

// ZKCountersLimits defines the ZK Counter limits
Expand Down
18 changes: 17 additions & 1 deletion jsonrpc/endpoints_eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (

"github.com/0xPolygonHermez/zkevm-node/hex"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/client"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/lru_xlayer"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/metrics"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/types"
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/0xPolygonHermez/zkevm-node/pool"
Expand Down Expand Up @@ -72,7 +74,7 @@ func (e *EthEndpoints) BlockNumber() (interface{}, types.Error) {
// Note, this function doesn't make any changes in the state/blockchain and is
// useful to execute view/pure methods and retrieve values.
func (e *EthEndpoints) Call(arg *types.TxArgs, blockArg *types.BlockNumberOrHash) (interface{}, types.Error) {
return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) {
return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (respRet interface{}, errRet types.Error) {
if arg == nil {
return RPCErrorResponse(types.InvalidParamsErrorCode, "missing value for required argument 0", nil, false)
}
Expand Down Expand Up @@ -108,6 +110,20 @@ func (e *EthEndpoints) Call(arg *types.TxArgs, blockArg *types.BlockNumberOrHash
return RPCErrorResponse(types.DefaultErrorCode, "failed to convert arguments into an unsigned transaction", err, false)
}

// X Layer LRU
if lru_xlayer.GetConfig().Enable {
ret, errValue, ok := getCallResultFromLRU(blockToProcess, sender, tx)
if ok {
log.Infof("Call result from LRU cache: %v, %v", ret, errValue)
metrics.RequestCallCachedCount()
return ret, errValue
}
metrics.RequestCallExecutedCount()
defer func() {
setCallResultToLRU(blockToProcess, sender, tx, respRet, errRet)
}()
}

result, err := e.state.ProcessUnsignedTransaction(ctx, tx, sender, blockToProcess, true, dbTx)
if err != nil {
errMsg := fmt.Sprintf("failed to execute the unsigned transaction: %v", err.Error())
Expand Down
50 changes: 50 additions & 0 deletions jsonrpc/endpoints_eth_lru_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package jsonrpc

import (
"fmt"

"github.com/0xPolygonHermez/zkevm-node/jsonrpc/lru_xlayer"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/types"
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)

func getCallKey(blockNumber *uint64, sender common.Address, tx *ethtypes.Transaction) (string, string) {
baseKey := fmt.Sprintf("%d-%s-%s", blockNumber, sender.String(), tx.Hash().String())
return baseKey + "ret", baseKey + "err"
}

func getCallResultFromLRU(blockNumber *uint64, sender common.Address, tx *ethtypes.Transaction) (interface{}, types.Error, bool) {
retKey, errKey := getCallKey(blockNumber, sender, tx)
value, ok := lru_xlayer.GetLRU().Get(retKey)
if !ok {
return nil, nil, false
}
errValue, ok := lru_xlayer.GetLRU().Get(errKey)
if !ok {
return nil, nil, false
}
if errValue == nil {
return value, nil, true
}
v, ok := errValue.(types.Error)
if !ok {
return nil, nil, false
}

return value, v, true
}

func setCallResultToLRU(blockNumber *uint64, sender common.Address, tx *ethtypes.Transaction, value interface{}, errValue types.Error) {
retKey, errKey := getCallKey(blockNumber, sender, tx)
err := lru_xlayer.GetLRU().Set(retKey, value)
if err != nil {
log.Debugf("Failed to set value to LRU cache call ret: %v", err)
return
}
err = lru_xlayer.GetLRU().Set(errKey, errValue)
if err != nil {
log.Debugf("Failed to set value to LRU cache call err: %v", err)
}
}
21 changes: 21 additions & 0 deletions jsonrpc/lru_xlayer/lru_config_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package lru_xlayer

var (
gConfigure Config
)

// Config is the configuration for the LRU cache
type Config struct {
Enable bool
Size int
}

// SetConfig sets the configuration for the LRU cache
func SetConfig(c Config) {
gConfigure = c
}

// GetConfig returns the configuration for the LRU cache
func GetConfig() Config {
return gConfigure
}
53 changes: 53 additions & 0 deletions jsonrpc/lru_xlayer/lru_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package lru_xlayer

import (
"sync"

"github.com/0xPolygonHermez/zkevm-node/log"
lru "github.com/hashicorp/golang-lru"
)

var (
once sync.Once
instance *LRUCache
)

// LRUCache is a simple interface for a LRU cache.
type LRUCache struct {
cache *lru.Cache
}

func newLRUCache() *LRUCache {
c, err := lru.New(GetConfig().Size)
if err != nil {
log.Fatal("Failed to create LRU cache", "err", err)
return nil
}
return &LRUCache{cache: c}
}

// Get retrieves a value from the cache.
func (l *LRUCache) Get(key string) (interface{}, bool) {
if l == nil || !GetConfig().Enable {
return nil, false
}

return l.cache.Get(key)
}

// Set adds a value to the cache.
func (l *LRUCache) Set(key string, value interface{}) error {
if l == nil || !GetConfig().Enable {
return nil
}
l.cache.Add(key, value)
return nil
}

// GetLRU returns the LRU cache instance.
func GetLRU() *LRUCache {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe cause nil panic

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea about the nil panic

once.Do(func() {
instance = newLRUCache()
})
return instance
}
26 changes: 26 additions & 0 deletions jsonrpc/metrics/metrics_xlayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ var (
requestAuthCountName = requestPrefix + "auth_count"
requestAuthErrorCountName = requestPrefix + "auth_error_count"
requestRelayFailCountName = requestPrefix + "relay_fail_count"
requestCallCachedName = requestPrefix + "call_cached"
requestCallExecutedName = requestPrefix + "call_executed"
requestBatchSizeName = requestPrefix + "batch_size"

wsRequestPrefix = prefix + "ws_request_"
Expand Down Expand Up @@ -121,6 +123,20 @@ var (
},
Labels: []string{"type"},
},
{
CounterOpts: prometheus.CounterOpts{
Name: requestCallCachedName,
Help: "[JSONRPC] number of cached call requests",
},
Labels: []string{"type"},
},
{
CounterOpts: prometheus.CounterOpts{
Name: requestCallExecutedName,
Help: "[JSONRPC] number of execute cache requests",
},
Labels: []string{"type"},
},
}
)

Expand Down Expand Up @@ -202,3 +218,13 @@ func RequestRelayFailCount(method string) {
func RequestBatchSize(batchSize int) {
metrics.GaugeSet(requestBatchSizeName, float64(batchSize))
}

// RequestCallCachedCount increments the call cached counter vector by one.
func RequestCallCachedCount() {
metrics.CounterVecInc(requestCallCachedName, "cached")
}

// RequestCallExecutedCount increments the call execute counter vector by one.
func RequestCallExecutedCount() {
metrics.CounterVecInc(requestCallExecutedName, "executed")
}
5 changes: 5 additions & 0 deletions jsonrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"syscall"
"time"

lru "github.com/0xPolygonHermez/zkevm-node/jsonrpc/lru_xlayer"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/metrics"
"github.com/0xPolygonHermez/zkevm-node/jsonrpc/types"
"github.com/0xPolygonHermez/zkevm-node/log"
Expand Down Expand Up @@ -90,6 +91,10 @@ func NewServer(
handler: handler,
chainID: chainID,
}

// X Layer handler
lru.SetConfig(cfg.LRUConfig)

return srv
}

Expand Down
3 changes: 3 additions & 0 deletions test/config/test.node.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ DisableAPIs = []
[RPC.WebSockets]
Enabled = true
Port = 8133
[RPC.LRUConfig]
Enable = true
Size = 1000

[Synchronizer]
SyncInterval = "1s"
Expand Down
Loading