From bfd5b5f7b68f84816f88ec8b445cdd9ead03d7fa Mon Sep 17 00:00:00 2001 From: HuangYi Date: Tue, 19 Apr 2022 11:56:41 +0800 Subject: [PATCH 1/3] make jsonrpc api namespaces extensible Closes: #1052, #1037 --- CHANGELOG.md | 1 + rpc/apis.go | 112 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 73 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 731d032a7b..40059c2c68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (deps) [tharsis#1046](https://github.com/tharsis/ethermint/pull/1046) Bump Cosmos SDK version to [`v0.45.3`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.3) +* (rpc) [tharsis#1056](https://github.com/tharsis/ethermint/pull/1056) Make json-rpc namespaces extensible ### Bug Fixes diff --git a/rpc/apis.go b/rpc/apis.go index 29c431a9fe..547c9a1da6 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -3,6 +3,8 @@ package rpc import ( + "fmt" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server" @@ -35,94 +37,124 @@ const ( apiVersion = "1.0" ) -// GetRPCAPIs returns the list of all APIs -func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, selectedAPIs []string) []rpc.API { - nonceLock := new(types.AddrLocker) - evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx) +// APICreator creates the json-rpc api implementations. +type APICreator = func(*server.Context, client.Context, *rpcclient.WSClient) []rpc.API - var apis []rpc.API - // remove duplicates - selectedAPIs = unique(selectedAPIs) +// apiCreators defines the json-rpc api namespaces. +var apiCreators map[string]APICreator - for index := range selectedAPIs { - switch selectedAPIs[index] { - case EthNamespace: - apis = append(apis, - rpc.API{ +func init() { + apiCreators = map[string]APICreator{ + EthNamespace: func(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient) []rpc.API { + nonceLock := new(types.AddrLocker) + evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx) + return []rpc.API{ + { Namespace: EthNamespace, Version: apiVersion, Service: eth.NewPublicAPI(ctx.Logger, clientCtx, evmBackend, nonceLock), Public: true, }, - rpc.API{ + { Namespace: EthNamespace, Version: apiVersion, Service: filters.NewPublicAPI(ctx.Logger, clientCtx, tmWSClient, evmBackend), Public: true, }, - ) - case Web3Namespace: - apis = append(apis, - rpc.API{ + } + }, + Web3Namespace: func(*server.Context, client.Context, *rpcclient.WSClient) []rpc.API { + return []rpc.API{ + { Namespace: Web3Namespace, Version: apiVersion, Service: web3.NewPublicAPI(), Public: true, }, - ) - case NetNamespace: - apis = append(apis, - rpc.API{ + } + }, + NetNamespace: func(_ *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API { + return []rpc.API{ + { Namespace: NetNamespace, Version: apiVersion, Service: net.NewPublicAPI(clientCtx), Public: true, }, - ) - case PersonalNamespace: - apis = append(apis, - rpc.API{ + } + }, + PersonalNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API { + evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx) + return []rpc.API{ + { Namespace: PersonalNamespace, Version: apiVersion, Service: personal.NewAPI(ctx.Logger, clientCtx, evmBackend), Public: false, }, - ) - case TxPoolNamespace: - apis = append(apis, - rpc.API{ + } + }, + TxPoolNamespace: func(ctx *server.Context, _ client.Context, _ *rpcclient.WSClient) []rpc.API { + return []rpc.API{ + { Namespace: TxPoolNamespace, Version: apiVersion, Service: txpool.NewPublicAPI(ctx.Logger), Public: true, }, - ) - case DebugNamespace: - apis = append(apis, - rpc.API{ + } + }, + DebugNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API { + evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx) + return []rpc.API{ + { Namespace: DebugNamespace, Version: apiVersion, Service: debug.NewAPI(ctx, evmBackend, clientCtx), Public: true, }, - ) - case MinerNamespace: - apis = append(apis, - rpc.API{ + } + }, + MinerNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API { + evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx) + return []rpc.API{ + { Namespace: MinerNamespace, Version: apiVersion, Service: miner.NewPrivateAPI(ctx, clientCtx, evmBackend), Public: false, }, - ) - default: - ctx.Logger.Error("invalid namespace value", "namespace", selectedAPIs[index]) + } + }, + } +} + +// GetRPCAPIs returns the list of all APIs +func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, selectedAPIs []string) []rpc.API { + var apis []rpc.API + // remove duplicates + selectedAPIs = unique(selectedAPIs) + + for _, ns := range selectedAPIs { + if creator, ok := apiCreators[ns]; ok { + apis = append(apis, creator(ctx, clientCtx, tmWSClient)...) + } else { + ctx.Logger.Error("invalid namespace value", "namespace", ns) } } return apis } +// RegisterAPINamespace registers an api namespace with the api creator. +func RegisterAPINamespace(ns string, creator APICreator) error { + if _, ok := apiCreators[ns]; ok { + return fmt.Errorf("duplicated api namespace %s", ns) + } + apiCreators[ns] = creator + return nil +} + func unique(intSlice []string) []string { keys := make(map[string]bool) var list []string From e948bce31592b6b6b4894b818b3187a5b11978f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Federico=20Kunze=20K=C3=BCllmer?= <31522760+fedekunze@users.noreply.github.com> Date: Tue, 19 Apr 2022 14:38:45 +0200 Subject: [PATCH 2/3] Apply suggestions from code review --- rpc/apis.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rpc/apis.go b/rpc/apis.go index 547c9a1da6..768b8b71d1 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -132,8 +132,6 @@ func init() { // GetRPCAPIs returns the list of all APIs func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, selectedAPIs []string) []rpc.API { var apis []rpc.API - // remove duplicates - selectedAPIs = unique(selectedAPIs) for _, ns := range selectedAPIs { if creator, ok := apiCreators[ns]; ok { @@ -146,7 +144,8 @@ func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpccl return apis } -// RegisterAPINamespace registers an api namespace with the api creator. +// RegisterAPINamespace registers a new API namespace with the API creator. +// This function fails if the namespace is already registered. func RegisterAPINamespace(ns string, creator APICreator) error { if _, ok := apiCreators[ns]; ok { return fmt.Errorf("duplicated api namespace %s", ns) From e58931634a60fb9ce1db39a96069d8c9e976d0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Federico=20Kunze=20K=C3=BCllmer?= Date: Tue, 19 Apr 2022 14:42:41 +0200 Subject: [PATCH 3/3] rm unique --- rpc/apis.go | 12 ------------ server/config/config.go | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/rpc/apis.go b/rpc/apis.go index 768b8b71d1..e437c431df 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -153,15 +153,3 @@ func RegisterAPINamespace(ns string, creator APICreator) error { apiCreators[ns] = creator return nil } - -func unique(intSlice []string) []string { - keys := make(map[string]bool) - var list []string - for _, entry := range intSlice { - if _, value := keys[entry]; !value { - keys[entry] = true - list = append(list, entry) - } - } - return list -} diff --git a/server/config/config.go b/server/config/config.go index 023e5a62b7..ed0f463bd0 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -237,7 +237,7 @@ func (c JSONRPCConfig) Validate() error { return errors.New("JSON-RPC HTTP idle timeout duration cannot be negative") } - // TODO: validate APIs + // check for duplicates seenAPIs := make(map[string]bool) for _, api := range c.API { if seenAPIs[api] {