option to immediately forward eth_calls to proxy node

This commit is contained in:
i-norden 2021-12-27 12:25:54 -06:00
parent 68152b0d77
commit 140989cbf7
6 changed files with 81 additions and 58 deletions

View File

@ -57,13 +57,17 @@ type PublicEthAPI struct {
B *Backend B *Backend
// Proxy node for forwarding cache misses // Proxy node for forwarding cache misses
supportsStateDiff bool // Whether or not the remote node supports the statediff_writeStateDiffAt endpoint, if it does we can fill the local cache when we hit a miss supportsStateDiff bool // Whether the remote node supports the statediff_writeStateDiffAt endpoint, if it does we can fill the local cache when we hit a miss
rpc *rpc.Client rpc *rpc.Client
ethClient *ethclient.Client ethClient *ethclient.Client
forwardEthCalls bool // if true, forward eth_call calls directly to the configured proxy node
} }
// NewPublicEthAPI creates a new PublicEthAPI with the provided underlying Backend // NewPublicEthAPI creates a new PublicEthAPI with the provided underlying Backend
func NewPublicEthAPI(b *Backend, client *rpc.Client, supportsStateDiff bool) *PublicEthAPI { func NewPublicEthAPI(b *Backend, client *rpc.Client, supportsStateDiff, forwardEthCalls bool) (*PublicEthAPI, error) {
if forwardEthCalls && client == nil {
return nil, errors.New("ipld-eth-server is configured to forward eth_calls to proxy node but no proxy node is configured")
}
var ethClient *ethclient.Client var ethClient *ethclient.Client
if client != nil { if client != nil {
ethClient = ethclient.NewClient(client) ethClient = ethclient.NewClient(client)
@ -73,7 +77,8 @@ func NewPublicEthAPI(b *Backend, client *rpc.Client, supportsStateDiff bool) *Pu
supportsStateDiff: supportsStateDiff, supportsStateDiff: supportsStateDiff,
rpc: client, rpc: client,
ethClient: ethClient, ethClient: ethClient,
} forwardEthCalls: forwardEthCalls,
}, nil
} }
/* /*
@ -910,6 +915,12 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
// Note, this function doesn't make and changes in the state/blockchain and is // Note, this function doesn't make and changes in the state/blockchain and is
// useful to execute and retrieve values. // useful to execute and retrieve values.
func (pea *PublicEthAPI) Call(ctx context.Context, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) { func (pea *PublicEthAPI) Call(ctx context.Context, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) {
if pea.forwardEthCalls {
var hex hexutil.Bytes
err := pea.rpc.CallContext(ctx, &hex, "eth_call", args, blockNrOrHash, overrides)
return hex, err
}
result, err := DoCall(ctx, pea.B, args, blockNrOrHash, overrides, 5*time.Second, pea.B.Config.RPCGasCap.Uint64()) result, err := DoCall(ctx, pea.B, args, blockNrOrHash, overrides, 5*time.Second, pea.B.Config.RPCGasCap.Uint64())
// If the result contains a revert reason, try to unpack and return it. // If the result contains a revert reason, try to unpack and return it.

View File

@ -19,9 +19,10 @@ package eth
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"os"
sdtypes "github.com/ethereum/go-ethereum/statediff/types" sdtypes "github.com/ethereum/go-ethereum/statediff/types"

View File

@ -36,21 +36,22 @@ import (
// Env variables // Env variables
const ( const (
serverWsPath = "SERVER_WS_PATH" SERVER_WS_PATH = "SERVER_WS_PATH"
serverIpcPath = "SERVER_IPC_PATH" SERVER_IPC_PATH = "SERVER_IPC_PATH"
serverHTTPPath = "SERVER_HTTP_PATH" SERVER_HTTP_PATH = "SERVER_HTTP_PATH"
serverMaxIdleConnections = "SERVER_MAX_IDLE_CONNECTIONS" SERVER_MAX_IDLE_CONNECTIONS = "SERVER_MAX_IDLE_CONNECTIONS"
serverMaxOpenConnections = "SERVER_MAX_OPEN_CONNECTIONS" SERVER_MAX_OPEN_CONNECTIONS = "SERVER_MAX_OPEN_CONNECTIONS"
serverMaxConnLifetime = "SERVER_MAX_CONN_LIFETIME" SERVER_MAX_CONN_LIFETIME = "SERVER_MAX_CONN_LIFETIME"
ethDefaultSenderAddr = "ETH_DEFAULT_SENDER_ADDR" ETH_DEFAULT_SENDER_ADDR = "ETH_DEFAULT_SENDER_ADDR"
ethRPCGasCap = "ETH_RPC_GAS_CAP" ETH_RPC_GAS_CAP = "ETH_RPC_GAS_CAP"
ethChainConfig = "ETH_CHAIN_CONFIG" ETH_CHAIN_CONFIG = "ETH_CHAIN_CONFIG"
ethSupportsStatediff = "ETH_SUPPORTS_STATEDIFF" ETH_SUPPORTS_STATEDIFF = "ETH_SUPPORTS_STATEDIFF"
ETH_FORWARD_ETH_CALLS = "ETH_FORWARD_ETH_CALLS"
ValidatorEnabled = "VALIDATOR_ENABLED" VALIDATOR_ENABLED = "VALIDATOR_ENABLED"
ValidatorEveryNthBlock = "VALIDATOR_EVERY_NTH_BLOCK" VALIDATOR_EVERY_NTH_BLOCK = "VALIDATOR_EVERY_NTH_BLOCK"
) )
// Config struct // Config struct
@ -83,6 +84,7 @@ type Config struct {
EthHttpEndpoint string EthHttpEndpoint string
Client *rpc.Client Client *rpc.Client
SupportStateDiff bool SupportStateDiff bool
ForwardEthCalls bool
// Cache configuration. // Cache configuration.
GroupCache *ethServerShared.GroupCacheConfig GroupCache *ethServerShared.GroupCacheConfig
@ -96,11 +98,12 @@ type Config struct {
func NewConfig() (*Config, error) { func NewConfig() (*Config, error) {
c := new(Config) c := new(Config)
viper.BindEnv("ethereum.httpPath", ethHTTPPath) viper.BindEnv("ethereum.httpPath", ETH_HTTP_PATH)
viper.BindEnv("ethereum.defaultSender", ethDefaultSenderAddr) viper.BindEnv("ethereum.defaultSender", ETH_DEFAULT_SENDER_ADDR)
viper.BindEnv("ethereum.rpcGasCap", ethRPCGasCap) viper.BindEnv("ethereum.rpcGasCap", ETH_RPC_GAS_CAP)
viper.BindEnv("ethereum.chainConfig", ethChainConfig) viper.BindEnv("ethereum.chainConfig", ETH_CHAIN_CONFIG)
viper.BindEnv("ethereum.supportsStateDiff", ethSupportsStatediff) viper.BindEnv("ethereum.supportsStateDiff", ETH_SUPPORTS_STATEDIFF)
viper.BindEnv("ethereum.forwardEthCalls", ETH_FORWARD_ETH_CALLS)
c.dbInit() c.dbInit()
ethHTTP := viper.GetString("ethereum.httpPath") ethHTTP := viper.GetString("ethereum.httpPath")
@ -111,6 +114,7 @@ func NewConfig() (*Config, error) {
} }
c.Client = cli c.Client = cli
c.SupportStateDiff = viper.GetBool("ethereum.supportsStateDiff") c.SupportStateDiff = viper.GetBool("ethereum.supportsStateDiff")
c.ForwardEthCalls = viper.GetBool("ethereum.forwardEthCalls")
c.EthHttpEndpoint = ethHTTPEndpoint c.EthHttpEndpoint = ethHTTPEndpoint
// websocket server // websocket server
@ -224,23 +228,23 @@ func NewConfig() (*Config, error) {
} }
func overrideDBConnConfig(con *postgres.ConnectionConfig) { func overrideDBConnConfig(con *postgres.ConnectionConfig) {
viper.BindEnv("database.server.maxIdle", serverMaxIdleConnections) viper.BindEnv("database.server.maxIdle", SERVER_MAX_IDLE_CONNECTIONS)
viper.BindEnv("database.server.maxOpen", serverMaxOpenConnections) viper.BindEnv("database.server.maxOpen", SERVER_MAX_OPEN_CONNECTIONS)
viper.BindEnv("database.server.maxLifetime", serverMaxConnLifetime) viper.BindEnv("database.server.maxLifetime", SERVER_MAX_CONN_LIFETIME)
con.MaxIdle = viper.GetInt("database.server.maxIdle") con.MaxIdle = viper.GetInt("database.server.maxIdle")
con.MaxOpen = viper.GetInt("database.server.maxOpen") con.MaxOpen = viper.GetInt("database.server.maxOpen")
con.MaxLifetime = viper.GetInt("database.server.maxLifetime") con.MaxLifetime = viper.GetInt("database.server.maxLifetime")
} }
func (c *Config) dbInit() { func (c *Config) dbInit() {
viper.BindEnv("database.name", databaseName) viper.BindEnv("database.name", DATABASE_NAME)
viper.BindEnv("database.hostname", databaseHostname) viper.BindEnv("database.hostname", DATABASE_HOSTNAME)
viper.BindEnv("database.port", databasePort) viper.BindEnv("database.port", DATABASE_PORT)
viper.BindEnv("database.user", databaseUser) viper.BindEnv("database.user", DATABASE_USER)
viper.BindEnv("database.password", databasePassword) viper.BindEnv("database.password", DATABASE_PASSWORD)
viper.BindEnv("database.maxIdle", databaseMaxIdleConnections) viper.BindEnv("database.maxIdle", DATABASE_MAX_IDLE_CONNECTIONS)
viper.BindEnv("database.maxOpen", databaseMaxOpenConnections) viper.BindEnv("database.maxOpen", DATABASE_MAX_OPEN_CONNECTIONS)
viper.BindEnv("database.maxLifetime", databaseMaxOpenConnLifetime) viper.BindEnv("database.maxLifetime", DATABASE_MAX_CONN_LIFETIME)
c.DBParams.Name = viper.GetString("database.name") c.DBParams.Name = viper.GetString("database.name")
c.DBParams.Hostname = viper.GetString("database.hostname") c.DBParams.Hostname = viper.GetString("database.hostname")
@ -276,8 +280,8 @@ func (c *Config) loadGroupCacheConfig() {
} }
func (c *Config) loadValidatorConfig() { func (c *Config) loadValidatorConfig() {
viper.BindEnv("validator.enabled", ValidatorEnabled) viper.BindEnv("validator.enabled", VALIDATOR_ENABLED)
viper.BindEnv("validator.everyNthBlock", ValidatorEveryNthBlock) viper.BindEnv("validator.everyNthBlock", VALIDATOR_EVERY_NTH_BLOCK)
c.StateValidationEnabled = viper.GetBool("validator.enabled") c.StateValidationEnabled = viper.GetBool("validator.enabled")
c.StateValidationEveryNthBlock = viper.GetUint64("validator.everyNthBlock") c.StateValidationEveryNthBlock = viper.GetUint64("validator.everyNthBlock")

View File

@ -8,33 +8,33 @@ import (
// Env variables // Env variables
const ( const (
HTTPTimeout = "HTTP_TIMEOUT" HTTP_TIMEOUT = "HTTP_TIMEOUT"
EthWsPath = "ETH_WS_PATH" ETH_WS_PATH = "ETH_WS_PATH"
ethHTTPPath = "ETH_HTTP_PATH" ETH_HTTP_PATH = "ETH_HTTP_PATH"
ethNodeID = "ETH_NODE_ID" ETH_NODE_ID = "ETH_NODE_ID"
ethClientName = "ETH_CLIENT_NAME" ETH_CLIENT_NAME = "ETH_CLIENT_NAME"
ethGenesisBlock = "ETH_GENESIS_BLOCK" ETH_GENESIS_BLOCK = "ETH_GENESIS_BLOCK"
ethNetworkID = "ETH_NETWORK_ID" ETH_NETWORK_ID = "ETH_NETWORK_ID"
ethChainID = "ETH_CHAIN_ID" ETH_CHAIN_ID = "ETH_CHAIN_ID"
databaseName = "DATABASE_NAME" DATABASE_NAME = "DATABASE_NAME"
databaseHostname = "DATABASE_HOSTNAME" DATABASE_HOSTNAME = "DATABASE_HOSTNAME"
databasePort = "DATABASE_PORT" DATABASE_PORT = "DATABASE_PORT"
databaseUser = "DATABASE_USER" DATABASE_USER = "DATABASE_USER"
databasePassword = "DATABASE_PASSWORD" DATABASE_PASSWORD = "DATABASE_PASSWORD"
databaseMaxIdleConnections = "DATABASE_MAX_IDLE_CONNECTIONS" DATABASE_MAX_IDLE_CONNECTIONS = "DATABASE_MAX_IDLE_CONNECTIONS"
databaseMaxOpenConnections = "DATABASE_MAX_OPEN_CONNECTIONS" DATABASE_MAX_OPEN_CONNECTIONS = "DATABASE_MAX_OPEN_CONNECTIONS"
databaseMaxOpenConnLifetime = "DATABASE_MAX_CONN_LIFETIME" DATABASE_MAX_CONN_LIFETIME = "DATABASE_MAX_CONN_LIFETIME"
) )
// GetEthNodeAndClient returns eth node info and client from path url // GetEthNodeAndClient returns eth node info and client from path url
func getEthNodeAndClient(path string) (node.Info, *rpc.Client, error) { func getEthNodeAndClient(path string) (node.Info, *rpc.Client, error) {
viper.BindEnv("ethereum.nodeID", ethNodeID) viper.BindEnv("ethereum.nodeID", ETH_NODE_ID)
viper.BindEnv("ethereum.clientName", ethClientName) viper.BindEnv("ethereum.clientName", ETH_CLIENT_NAME)
viper.BindEnv("ethereum.genesisBlock", ethGenesisBlock) viper.BindEnv("ethereum.genesisBlock", ETH_GENESIS_BLOCK)
viper.BindEnv("ethereum.networkID", ethNetworkID) viper.BindEnv("ethereum.networkID", ETH_NETWORK_ID)
viper.BindEnv("ethereum.chainID", ethChainID) viper.BindEnv("ethereum.chainID", ETH_CHAIN_ID)
rpcClient, err := rpc.Dial(path) rpcClient, err := rpc.Dial(path)
if err != nil { if err != nil {

View File

@ -83,6 +83,8 @@ type Service struct {
supportsStateDiffing bool supportsStateDiffing bool
// backend for the server // backend for the server
backend *eth.Backend backend *eth.Backend
// whether to forward eth_calls directly to proxy node
forwardEthCalls bool
} }
// NewServer creates a new Server using an underlying Service struct // NewServer creates a new Server using an underlying Service struct
@ -97,6 +99,7 @@ func NewServer(settings *Config) (Server, error) {
sap.SubscriptionTypes = make(map[common.Hash]eth.SubscriptionSettings) sap.SubscriptionTypes = make(map[common.Hash]eth.SubscriptionSettings)
sap.client = settings.Client sap.client = settings.Client
sap.supportsStateDiffing = settings.SupportStateDiff sap.supportsStateDiffing = settings.SupportStateDiff
sap.forwardEthCalls = settings.ForwardEthCalls
var err error var err error
sap.backend, err = eth.NewEthBackend(sap.db, &eth.Config{ sap.backend, err = eth.NewEthBackend(sap.db, &eth.Config{
ChainConfig: settings.ChainConfig, ChainConfig: settings.ChainConfig,
@ -130,10 +133,14 @@ func (sap *Service) APIs() []rpc.API {
Public: true, Public: true,
}, },
} }
ethAPI, err := eth.NewPublicEthAPI(sap.backend, sap.client, sap.supportsStateDiffing, sap.forwardEthCalls)
if err != nil {
log.Fatalf("unable to create public eth api: %v", err)
}
return append(apis, rpc.API{ return append(apis, rpc.API{
Namespace: eth.APIName, Namespace: eth.APIName,
Version: eth.APIVersion, Version: eth.APIVersion,
Service: eth.NewPublicEthAPI(sap.backend, sap.client, sap.supportsStateDiffing), Service: ethAPI,
Public: true, Public: true,
}) })
} }

View File

@ -20,8 +20,8 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/statediff/indexer/ipfs/ipld" "github.com/ethereum/go-ethereum/statediff/indexer/ipfs/ipld"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/ipfs/go-ipfs-ds-help" dshelp "github.com/ipfs/go-ipfs-ds-help"
node "github.com/ipfs/go-ipld-format" node "github.com/ipfs/go-ipld-format"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"