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 API Filter to node #266

Merged
merged 1 commit into from
Nov 2, 2023
Merged
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
8 changes: 8 additions & 0 deletions arbitrum/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ func NewBackend(stack *node.Node, config *Config, chainDb ethdb.Database, publis
chanNewBlock: make(chan struct{}, 1),
}

if len(config.AllowMethod) > 0 {
rpcFilter := make(map[string]bool)
for _, method := range config.AllowMethod {
rpcFilter[method] = true
}
backend.stack.ApplyAPIFilter(rpcFilter)
}

backend.bloomIndexer.Start(backend.arb.BlockChain())
filterSystem, err := createRegisterAPIBackend(backend, filterConfig, config.ClassicRedirect, config.ClassicRedirectTimeout)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions arbitrum/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ type Config struct {
ClassicRedirect string `koanf:"classic-redirect"`
ClassicRedirectTimeout time.Duration `koanf:"classic-redirect-timeout"`
MaxRecreateStateDepth int64 `koanf:"max-recreate-state-depth"`

AllowMethod []string `koanf:"allow-method"`
}

type ArbDebugConfig struct {
Expand All @@ -57,6 +59,7 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) {
f.Int(prefix+".filter-log-cache-size", DefaultConfig.FilterLogCacheSize, "log filter system maximum number of cached blocks")
f.Duration(prefix+".filter-timeout", DefaultConfig.FilterTimeout, "log filter system maximum time filters stay active")
f.Int64(prefix+".max-recreate-state-depth", DefaultConfig.MaxRecreateStateDepth, "maximum depth for recreating state, measured in l2 gas (0=don't recreate state, -1=infinite, -2=use default value for archive or non-archive node (whichever is configured))")
f.StringSlice(prefix+".allow-method", DefaultConfig.AllowMethod, "list of whitelisted rpc methods")
arbDebug := DefaultConfig.ArbDebug
f.Uint64(prefix+".arbdebug.block-range-bound", arbDebug.BlockRangeBound, "bounds the number of blocks arbdebug calls may return")
f.Uint64(prefix+".arbdebug.timeout-queue-bound", arbDebug.TimeoutQueueBound, "bounds the length of timeout queues arbdebug calls may return")
Expand All @@ -81,6 +84,7 @@ var DefaultConfig = Config{
FeeHistoryMaxBlockCount: 1024,
ClassicRedirect: "",
MaxRecreateStateDepth: UninitializedMaxRecreateStateDepth, // default value should be set for depending on node type (archive / non-archive)
AllowMethod: []string{},
ArbDebug: ArbDebugConfig{
BlockRangeBound: 256,
TimeoutQueueBound: 512,
Expand Down
17 changes: 14 additions & 3 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ type Node struct {
inprocHandler *rpc.Server // In-process RPC request handler to process the API requests

databases map[*closeTrackingDB]struct{} // All open databases

apiFilter map[string]bool // Whitelisting API methods
}

const (
Expand Down Expand Up @@ -378,6 +380,11 @@ func (n *Node) obtainJWTSecret(cliParam string) ([]byte, error) {
return jwtSecret, nil
}

// ApplyAPIFilter is the first step in whitelisting given rpc methods inside apiFilter
func (n *Node) ApplyAPIFilter(apiFilter map[string]bool) {
n.apiFilter = apiFilter
}

// startRPC is a helper method to configure all the various RPC endpoints during node
// startup. It's not meant to be called at any time afterwards as it makes certain
// assumptions about the state of the node.
Expand Down Expand Up @@ -418,6 +425,7 @@ func (n *Node) startRPC() error {
Vhosts: n.config.HTTPVirtualHosts,
Modules: n.config.HTTPModules,
prefix: n.config.HTTPPathPrefix,
apiFilter: n.apiFilter,
}); err != nil {
return err
}
Expand All @@ -431,9 +439,10 @@ func (n *Node) startRPC() error {
return err
}
if err := server.enableWS(openAPIs, wsConfig{
Modules: n.config.WSModules,
Origins: n.config.WSOrigins,
prefix: n.config.WSPathPrefix,
Modules: n.config.WSModules,
Origins: n.config.WSOrigins,
prefix: n.config.WSPathPrefix,
apiFilter: n.apiFilter,
}); err != nil {
return err
}
Expand All @@ -453,6 +462,7 @@ func (n *Node) startRPC() error {
Modules: n.config.AuthModules,
prefix: DefaultAuthPrefix,
jwtSecret: secret,
apiFilter: n.apiFilter,
}); err != nil {
return err
}
Expand All @@ -467,6 +477,7 @@ func (n *Node) startRPC() error {
Origins: n.config.AuthOrigins,
prefix: DefaultAuthPrefix,
jwtSecret: secret,
apiFilter: n.apiFilter,
}); err != nil {
return err
}
Expand Down
4 changes: 4 additions & 0 deletions node/rpcstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type httpConfig struct {
Vhosts []string
prefix string // path prefix on which to mount http handler
jwtSecret []byte // optional JWT secret
apiFilter map[string]bool
}

// wsConfig is the JSON-RPC/Websocket configuration
Expand All @@ -50,6 +51,7 @@ type wsConfig struct {
Modules []string
prefix string // path prefix on which to mount ws handler
jwtSecret []byte // optional JWT secret
apiFilter map[string]bool
}

type rpcHandler struct {
Expand Down Expand Up @@ -302,6 +304,7 @@ func (h *httpServer) enableRPC(apis []rpc.API, config httpConfig) error {

// Create RPC server and handler.
srv := rpc.NewServer()
srv.ApplyAPIFilter(config.apiFilter)
if err := RegisterApis(apis, config.Modules, srv); err != nil {
return err
}
Expand Down Expand Up @@ -339,6 +342,7 @@ func (h *httpServer) enableWS(apis []rpc.API, config wsConfig) error {
}
// Create RPC server and handler.
srv := rpc.NewServer()
srv.ApplyAPIFilter(config.apiFilter)
if err := RegisterApis(apis, config.Modules, srv); err != nil {
return err
}
Expand Down
4 changes: 4 additions & 0 deletions rpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ func NewServer() *Server {
return server
}

func (s *Server) ApplyAPIFilter(apiFilter map[string]bool) {
s.services.apiFilter = apiFilter
}

// RegisterName creates a service for the given receiver type under the given name. When no
// methods on the given receiver match the criteria to be either a RPC method or a
// subscription an error is returned. Otherwise a new service is created and added to the
Expand Down
14 changes: 11 additions & 3 deletions rpc/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ var (
type serviceRegistry struct {
mu sync.Mutex
services map[string]service

apiFilter map[string]bool
}

// service represents a registered object.
Expand Down Expand Up @@ -81,11 +83,17 @@ func (r *serviceRegistry) registerName(name string, rcvr interface{}) error {
}
r.services[name] = svc
}
for name, cb := range callbacks {
for methodName, cb := range callbacks {
if r.apiFilter != nil {
key := name + "_" + methodName
if _, ok := r.apiFilter[key]; !ok {
continue
}
}
if cb.isSubscribe {
svc.subscriptions[name] = cb
svc.subscriptions[methodName] = cb
} else {
svc.callbacks[name] = cb
svc.callbacks[methodName] = cb
}
}
return nil
Expand Down