Skip to content

Commit

Permalink
rpc: make json-rpc API namespaces extensible (evmos#1056)
Browse files Browse the repository at this point in the history
* make jsonrpc api namespaces extensible

Closes: evmos#1052, evmos#1037

* Apply suggestions from code review

Co-authored-by: Federico Kunze Küllmer <[email protected]>
  • Loading branch information
yihuang and fedekunze committed Apr 27, 2022
1 parent 1e063e1 commit 1d16a8a
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 50 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (ante) [tharsis#991](https://github.com/tharsis/ethermint/pull/991) Set an upper bound to gasWanted to prevent DoS attack.
* (ante) [tharsis#1004](https://github.com/tharsis/ethermint/pull/1004) make MaxTxGasWanted configurable.
* (rpc) [tharsis#1012](https://github.com/tharsis/ethermint/pull/1012) fix the tx hash in filter entries created by `eth_newPendingTransactionFilter`.
* (rpc) [tharsis#1056](https://github.com/tharsis/ethermint/pull/1056) Make json-rpc namespaces extensible

## [v0.7.2-cronos-6] - 2021-12-17

Expand Down
117 changes: 68 additions & 49 deletions rpc/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package rpc

import (
"fmt"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server"

Expand Down Expand Up @@ -35,102 +37,119 @@ 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

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
}

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)
}
// 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)
}
return list
apiCreators[ns] = creator
return nil
}
2 changes: 1 addition & 1 deletion server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func (c JSONRPCConfig) Validate() error {
return errors.New("JSON-RPC block range cap cannot be negative")
}

// TODO: validate APIs
// check for duplicates
seenAPIs := make(map[string]bool)
for _, api := range c.API {
if seenAPIs[api] {
Expand Down

0 comments on commit 1d16a8a

Please sign in to comment.