Skip to content

Commit

Permalink
Implementation of cacheable by tx hash methods (#66)
Browse files Browse the repository at this point in the history
* Implementation of cacheable by tx hash methods

* Update CACHING.md
  • Loading branch information
evgeniy-scherbina authored Nov 9, 2023
1 parent a831fc5 commit 73b9c8e
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 0 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ REDIS_PASSWORD=
CACHE_METHOD_HAS_BLOCK_NUMBER_PARAM_TTL_SECONDS=600
CACHE_METHOD_HAS_BLOCK_HASH_PARAM_TTL_SECONDS=600
CACHE_STATIC_METHOD_TTL_SECONDS=600
CACHE_METHOD_HAS_TX_HASH_PARAM_TTL_SECONDS=600
# CACHE_PREFIX is used as prefix for any key in the cache, key has such structure:
# <cache_prefix>:evm-request:<method_name>:sha256:<sha256(body)>
# Possible values are testnet, mainnet, etc...
Expand Down
9 changes: 9 additions & 0 deletions architecture/CACHING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ As of now we have 3 different groups of cacheable EVM methods:
- cacheable by block number (for ex.: `eth_getBlockByNumber`)
- cacheable by block hash (for ex.: `eth_getBlockByHash`)
- static methods (for ex.: `eth_chainId`, `net_version`)
- cacheable by tx hash (for ex.: `eth_getTransactionReceipt`)

### Cacheable by block number

Expand Down Expand Up @@ -86,6 +87,14 @@ For example:
{"jsonrpc":"2.0","method":"net_version","params":[],"id":67}
```

### Cacheable by tx hash

Cacheable by tx hash means that for specific:
- method
- params
- tx hash (which is part of params)
response won't change over time, so we can cache it indefinitely

### Where to find list of methods for every group?

It can be found in source code: https://github.com/Kava-Labs/kava-proxy-service/blob/main/decode/evm_rpc.go
Expand Down
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type Config struct {
CacheMethodHasBlockNumberParamTTL time.Duration
CacheMethodHasBlockHashParamTTL time.Duration
CacheStaticMethodTTL time.Duration
CacheMethodHasTxHashParamTTL time.Duration
CachePrefix string
WhitelistedHeaders []string
DefaultAccessControlAllowOriginValue string
Expand Down Expand Up @@ -114,6 +115,7 @@ const (
CACHE_METHOD_HAS_BLOCK_NUMBER_PARAM_TTL_ENVIRONMENT_KEY = "CACHE_METHOD_HAS_BLOCK_NUMBER_PARAM_TTL_SECONDS"
CACHE_METHOD_HAS_BLOCK_HASH_PARAM_TTL_ENVIRONMENT_KEY = "CACHE_METHOD_HAS_BLOCK_HASH_PARAM_TTL_SECONDS"
CACHE_STATIC_METHOD_TTL_ENVIRONMENT_KEY = "CACHE_STATIC_METHOD_TTL_SECONDS"
CACHE_METHOD_HAS_TX_HASH_PARAM_TTL_ENVIRONMENT_KEY = "CACHE_METHOD_HAS_TX_HASH_PARAM_TTL_SECONDS"
CACHE_PREFIX_ENVIRONMENT_KEY = "CACHE_PREFIX"
WHITELISTED_HEADERS_ENVIRONMENT_KEY = "WHITELISTED_HEADERS"
DEFAULT_ACCESS_CONTROL_ALLOW_ORIGIN_VALUE_ENVIRONMENT_KEY = "DEFAULT_ACCESS_CONTROL_ALLOW_ORIGIN_VALUE"
Expand Down Expand Up @@ -307,6 +309,7 @@ func ReadConfig() Config {
CacheMethodHasBlockNumberParamTTL: time.Duration(EnvOrDefaultInt(CACHE_METHOD_HAS_BLOCK_NUMBER_PARAM_TTL_ENVIRONMENT_KEY, 0)) * time.Second,
CacheMethodHasBlockHashParamTTL: time.Duration(EnvOrDefaultInt(CACHE_METHOD_HAS_BLOCK_HASH_PARAM_TTL_ENVIRONMENT_KEY, 0)) * time.Second,
CacheStaticMethodTTL: time.Duration(EnvOrDefaultInt(CACHE_STATIC_METHOD_TTL_ENVIRONMENT_KEY, 0)) * time.Second,
CacheMethodHasTxHashParamTTL: time.Duration(EnvOrDefaultInt(CACHE_METHOD_HAS_TX_HASH_PARAM_TTL_ENVIRONMENT_KEY, 0)) * time.Second,
CachePrefix: os.Getenv(CACHE_PREFIX_ENVIRONMENT_KEY),
WhitelistedHeaders: parsedWhitelistedHeaders,
DefaultAccessControlAllowOriginValue: os.Getenv(DEFAULT_ACCESS_CONTROL_ALLOW_ORIGIN_VALUE_ENVIRONMENT_KEY),
Expand Down
3 changes: 3 additions & 0 deletions config/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ func Validate(config Config) error {
if err := checkTTLConfig(config.CacheStaticMethodTTL, CACHE_STATIC_METHOD_TTL_ENVIRONMENT_KEY); err != nil {
allErrs = errors.Join(allErrs, err)
}
if err := checkTTLConfig(config.CacheMethodHasTxHashParamTTL, CACHE_METHOD_HAS_TX_HASH_PARAM_TTL_ENVIRONMENT_KEY); err != nil {
allErrs = errors.Join(allErrs, err)
}

if strings.Contains(config.CachePrefix, ":") {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s, must not contain colon symbol", CACHE_PREFIX_ENVIRONMENT_KEY, config.CachePrefix))
Expand Down
18 changes: 18 additions & 0 deletions decode/evm_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,24 @@ func IsMethodStatic(method string) bool {
return false
}

// CacheableByTxHashMethods is a list of EVM methods which can be cached indefinitely by transaction hash.
// It means that for specific method and params (which includes tx hash) response will never change.
var CacheableByTxHashMethods = []string{
"eth_getTransactionReceipt",
"eth_getTransactionByHash",
}

// MethodHasTxHashParam checks if method is cacheable by tx hash.
func MethodHasTxHashParam(method string) bool {
for _, cacheableByTxHashMethod := range CacheableByTxHashMethods {
if method == cacheableByTxHashMethod {
return true
}
}

return false
}

// NoHistoryMethods is a list of JSON-RPC methods that rely only on the present state of the chain.
// They can always be safely routed to an up-to-date pruning cluster.
var NoHistoryMethods = []string{
Expand Down
9 changes: 9 additions & 0 deletions service/cachemdw/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type Config struct {
CacheMethodHasBlockNumberParamTTL time.Duration
CacheMethodHasBlockHashParamTTL time.Duration
CacheStaticMethodTTL time.Duration
CacheMethodHasTxHashParamTTL time.Duration
}

// ServiceCache is responsible for caching EVM requests and provides corresponding middleware
Expand Down Expand Up @@ -115,6 +116,10 @@ func IsCacheable(
return true
}

if decode.MethodHasTxHashParam(req.Method) {
return true
}

return false
}

Expand All @@ -132,6 +137,10 @@ func (c *ServiceCache) GetTTL(method string) (time.Duration, error) {
return c.config.CacheStaticMethodTTL, nil
}

if decode.MethodHasTxHashParam(method) {
return c.config.CacheMethodHasTxHashParamTTL, nil
}

return 0, ErrRequestIsNotCacheable
}

Expand Down
1 change: 1 addition & 0 deletions service/cachemdw/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var (
CacheMethodHasBlockNumberParamTTL: time.Hour,
CacheMethodHasBlockHashParamTTL: time.Hour,
CacheStaticMethodTTL: time.Hour,
CacheMethodHasTxHashParamTTL: time.Hour,
}
)

Expand Down
1 change: 1 addition & 0 deletions service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ func createServiceCache(
CacheMethodHasBlockNumberParamTTL: config.CacheMethodHasBlockNumberParamTTL,
CacheMethodHasBlockHashParamTTL: config.CacheMethodHasBlockHashParamTTL,
CacheStaticMethodTTL: config.CacheStaticMethodTTL,
CacheMethodHasTxHashParamTTL: config.CacheMethodHasTxHashParamTTL,
}

serviceCache := cachemdw.NewServiceCache(
Expand Down

0 comments on commit 73b9c8e

Please sign in to comment.