Add forwardGetStorageAt setting.

This commit is contained in:
Thomas E Lackey 2023-01-10 12:04:28 -06:00
parent e3c2e92265
commit d64ac5792c
7 changed files with 57 additions and 30 deletions

View File

@ -395,6 +395,7 @@ func init() {
viper.BindPFlag("ethereum.chainConfig", serveCmd.PersistentFlags().Lookup("eth-chain-config")) viper.BindPFlag("ethereum.chainConfig", serveCmd.PersistentFlags().Lookup("eth-chain-config"))
viper.BindPFlag("ethereum.supportsStateDiff", serveCmd.PersistentFlags().Lookup("eth-supports-state-diff")) viper.BindPFlag("ethereum.supportsStateDiff", serveCmd.PersistentFlags().Lookup("eth-supports-state-diff"))
viper.BindPFlag("ethereum.forwardEthCalls", serveCmd.PersistentFlags().Lookup("eth-forward-eth-calls")) viper.BindPFlag("ethereum.forwardEthCalls", serveCmd.PersistentFlags().Lookup("eth-forward-eth-calls"))
viper.BindPFlag("ethereum.forwardGetStorageAt", serveCmd.PersistentFlags().Lookup("eth-forward-get-storage-at"))
viper.BindPFlag("ethereum.proxyOnError", serveCmd.PersistentFlags().Lookup("eth-proxy-on-error")) viper.BindPFlag("ethereum.proxyOnError", serveCmd.PersistentFlags().Lookup("eth-proxy-on-error"))
// groupcache flags // groupcache flags

View File

@ -57,18 +57,22 @@ type PublicEthAPI struct {
B *Backend B *Backend
// Proxy node for forwarding cache misses // Proxy node for forwarding cache misses
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 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 forwardEthCalls bool // if true, forward eth_call calls directly to the configured proxy node
proxyOnError bool // turn on regular proxy fall-through on errors; needed to test difference between direct and indirect fall-through forwardGetStorageAt bool // if true, forward eth_getStorageAt calls directly to the configured proxy node
proxyOnError bool // turn on regular proxy fall-through on errors; needed to test difference between direct and indirect fall-through
} }
// 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, forwardEthCalls, proxyOnError bool) (*PublicEthAPI, error) { func NewPublicEthAPI(b *Backend, client *rpc.Client, supportsStateDiff, forwardEthCalls, forwardGetStorageAt, proxyOnError bool) (*PublicEthAPI, error) {
if forwardEthCalls && client == nil { 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") return nil, errors.New("ipld-eth-server is configured to forward eth_calls to proxy node but no proxy node is configured")
} }
if forwardGetStorageAt && client == nil {
return nil, errors.New("ipld-eth-server is configured to forward eth_getStorageAt to proxy node but no proxy node is configured")
}
if proxyOnError && client == nil { if proxyOnError && client == nil {
return nil, errors.New("ipld-eth-server is configured to forward all calls to proxy node on errors but no proxy node is configured") return nil, errors.New("ipld-eth-server is configured to forward all calls to proxy node on errors but no proxy node is configured")
} }
@ -77,12 +81,13 @@ func NewPublicEthAPI(b *Backend, client *rpc.Client, supportsStateDiff, forwardE
ethClient = ethclient.NewClient(client) ethClient = ethclient.NewClient(client)
} }
return &PublicEthAPI{ return &PublicEthAPI{
B: b, B: b,
supportsStateDiff: supportsStateDiff, supportsStateDiff: supportsStateDiff,
rpc: client, rpc: client,
ethClient: ethClient, ethClient: ethClient,
forwardEthCalls: forwardEthCalls, forwardEthCalls: forwardEthCalls,
proxyOnError: proxyOnError, forwardGetStorageAt: forwardGetStorageAt,
proxyOnError: proxyOnError,
}, nil }, nil
} }
@ -720,6 +725,13 @@ func (pea *PublicEthAPI) localGetBalance(ctx context.Context, address common.Add
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block // block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// numbers are also allowed. // numbers are also allowed.
func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
if pea.forwardGetStorageAt {
var res hexutil.Bytes
// If forwarding all getStorageAt calls, don't request statediffing.
if err := pea.rpc.CallContext(ctx, &res, "eth_getStorageAt", address, key, blockNrOrHash); res != nil && err == nil {
return res, nil
}
}
storageVal, err := pea.B.GetStorageByNumberOrHash(ctx, address, common.HexToHash(key), blockNrOrHash) storageVal, err := pea.B.GetStorageByNumberOrHash(ctx, address, common.HexToHash(key), blockNrOrHash)
if storageVal != nil && err == nil { if storageVal != nil && err == nil {
var value common.Hash var value common.Hash
@ -735,8 +747,10 @@ func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Addres
return value[:], nil return value[:], nil
} }
if pea.proxyOnError { if pea.proxyOnError {
logrus.Warnf("Missing eth_getStorageAt(%s, %s, %s)", address.Hash().String(), key, blockNrOrHash.String())
var res hexutil.Bytes var res hexutil.Bytes
if err := pea.rpc.CallContext(ctx, &res, "eth_getStorageAt", address, key, blockNrOrHash); res != nil && err == nil { if err := pea.rpc.CallContext(ctx, &res, "eth_getStorageAt", address, key, blockNrOrHash); res != nil && err == nil {
// If only proxying on error, request statediffing for the missing data.
go pea.writeStateDiffAtOrFor(blockNrOrHash) go pea.writeStateDiffAtOrFor(blockNrOrHash)
return res, nil return res, nil
} }
@ -1065,6 +1079,7 @@ func (pea *PublicEthAPI) writeStateDiffAt(height int64) {
IncludeTD: true, IncludeTD: true,
IncludeCode: true, IncludeCode: true,
} }
logrus.Debugf("Calling statediff_writeStateDiffAt(%d)", height)
if err := pea.rpc.CallContext(ctx, &data, "statediff_writeStateDiffAt", uint64(height), params); err != nil { if err := pea.rpc.CallContext(ctx, &data, "statediff_writeStateDiffAt", uint64(height), params); err != nil {
logrus.Errorf("writeStateDiffAt %d faild with err %s", height, err.Error()) logrus.Errorf("writeStateDiffAt %d faild with err %s", height, err.Error())
} }
@ -1087,6 +1102,7 @@ func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) {
IncludeTD: true, IncludeTD: true,
IncludeCode: true, IncludeCode: true,
} }
logrus.Debugf("Calling statediff_writeStateDiffFor(%s)", blockHash.Hex())
if err := pea.rpc.CallContext(ctx, &data, "statediff_writeStateDiffFor", blockHash, params); err != nil { if err := pea.rpc.CallContext(ctx, &data, "statediff_writeStateDiffFor", blockHash, params); err != nil {
logrus.Errorf("writeStateDiffFor %s faild with err %s", blockHash.Hex(), err.Error()) logrus.Errorf("writeStateDiffFor %s faild with err %s", blockHash.Hex(), err.Error())
} }

View File

@ -213,7 +213,7 @@ var _ = Describe("API", func() {
}, },
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
api, _ = eth.NewPublicEthAPI(backend, nil, false, false, false) api, _ = eth.NewPublicEthAPI(backend, nil, false, false, false, false)
tx, err = indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty()) tx, err = indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())

View File

@ -92,7 +92,7 @@ var _ = Describe("eth state reading tests", func() {
}, },
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
api, _ = eth.NewPublicEthAPI(backend, nil, false, false, false) api, _ = eth.NewPublicEthAPI(backend, nil, false, false, false, false)
// make the test blockchain (and state) // make the test blockchain (and state)
blocks, receipts, chain = test_helpers.MakeChain(chainLength, test_helpers.Genesis, test_helpers.TestChainGen) blocks, receipts, chain = test_helpers.MakeChain(chainLength, test_helpers.Genesis, test_helpers.TestChainGen)

View File

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/lib/pq" "github.com/lib/pq"
log "github.com/sirupsen/logrus"
) )
const ( const (
@ -493,6 +494,8 @@ func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(add
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil { if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
return "", nil, nil, err return "", nil, nil, err
} }
log.Debugf("getStorageAt: state_leaf_key=%s, storage_hex=%s, storage_leaf_key=%s, block_hash=%s",
stateLeafKey.Hex(), key.Hex(), storageHash.Hex(), hash.Hex())
if storageResult.StateLeafRemoved || storageResult.NodeType == removedNode { if storageResult.StateLeafRemoved || storageResult.NodeType == removedNode {
return "", EmptyNodeValue, EmptyNodeValue, nil return "", EmptyNodeValue, EmptyNodeValue, nil
} }

View File

@ -46,12 +46,13 @@ const (
SERVER_MAX_OPEN_CONNECTIONS = "SERVER_MAX_OPEN_CONNECTIONS" SERVER_MAX_OPEN_CONNECTIONS = "SERVER_MAX_OPEN_CONNECTIONS"
SERVER_MAX_CONN_LIFETIME = "SERVER_MAX_CONN_LIFETIME" SERVER_MAX_CONN_LIFETIME = "SERVER_MAX_CONN_LIFETIME"
ETH_DEFAULT_SENDER_ADDR = "ETH_DEFAULT_SENDER_ADDR" ETH_DEFAULT_SENDER_ADDR = "ETH_DEFAULT_SENDER_ADDR"
ETH_RPC_GAS_CAP = "ETH_RPC_GAS_CAP" ETH_RPC_GAS_CAP = "ETH_RPC_GAS_CAP"
ETH_CHAIN_CONFIG = "ETH_CHAIN_CONFIG" ETH_CHAIN_CONFIG = "ETH_CHAIN_CONFIG"
ETH_SUPPORTS_STATEDIFF = "ETH_SUPPORTS_STATEDIFF" ETH_SUPPORTS_STATEDIFF = "ETH_SUPPORTS_STATEDIFF"
ETH_FORWARD_ETH_CALLS = "ETH_FORWARD_ETH_CALLS" ETH_FORWARD_ETH_CALLS = "ETH_FORWARD_ETH_CALLS"
ETH_PROXY_ON_ERROR = "ETH_PROXY_ON_ERROR" ETH_FORWARD_GET_STORAGE_AT = "ETH_FORWARD_GET_STORAGE_AT"
ETH_PROXY_ON_ERROR = "ETH_PROXY_ON_ERROR"
VALIDATOR_ENABLED = "VALIDATOR_ENABLED" VALIDATOR_ENABLED = "VALIDATOR_ENABLED"
VALIDATOR_EVERY_NTH_BLOCK = "VALIDATOR_EVERY_NTH_BLOCK" VALIDATOR_EVERY_NTH_BLOCK = "VALIDATOR_EVERY_NTH_BLOCK"
@ -80,15 +81,16 @@ type Config struct {
TracingHttpEndpoint string TracingHttpEndpoint string
TracingPostgraphileEndpoint string TracingPostgraphileEndpoint string
ChainConfig *params.ChainConfig ChainConfig *params.ChainConfig
DefaultSender *common.Address DefaultSender *common.Address
RPCGasCap *big.Int RPCGasCap *big.Int
EthHttpEndpoint string EthHttpEndpoint string
Client *rpc.Client Client *rpc.Client
SupportStateDiff bool SupportStateDiff bool
ForwardEthCalls bool ForwardEthCalls bool
ProxyOnError bool ForwardGetStorageAt bool
NodeNetworkID string ProxyOnError bool
NodeNetworkID string
// Cache configuration. // Cache configuration.
GroupCache *ethServerShared.GroupCacheConfig GroupCache *ethServerShared.GroupCacheConfig
@ -108,6 +110,7 @@ func NewConfig() (*Config, error) {
viper.BindEnv("ethereum.chainConfig", ETH_CHAIN_CONFIG) viper.BindEnv("ethereum.chainConfig", ETH_CHAIN_CONFIG)
viper.BindEnv("ethereum.supportsStateDiff", ETH_SUPPORTS_STATEDIFF) viper.BindEnv("ethereum.supportsStateDiff", ETH_SUPPORTS_STATEDIFF)
viper.BindEnv("ethereum.forwardEthCalls", ETH_FORWARD_ETH_CALLS) viper.BindEnv("ethereum.forwardEthCalls", ETH_FORWARD_ETH_CALLS)
viper.BindEnv("ethereum.forwardGetStorageAt", ETH_FORWARD_GET_STORAGE_AT)
viper.BindEnv("ethereum.proxyOnError", ETH_PROXY_ON_ERROR) viper.BindEnv("ethereum.proxyOnError", ETH_PROXY_ON_ERROR)
c.dbInit() c.dbInit()
@ -121,6 +124,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.ForwardEthCalls = viper.GetBool("ethereum.forwardEthCalls")
c.ForwardGetStorageAt = viper.GetBool("ethereum.forwardGetStorageAt")
c.ProxyOnError = viper.GetBool("ethereum.proxyOnError") c.ProxyOnError = viper.GetBool("ethereum.proxyOnError")
c.EthHttpEndpoint = ethHTTPEndpoint c.EthHttpEndpoint = ethHTTPEndpoint

View File

@ -85,6 +85,8 @@ type Service struct {
backend *eth.Backend backend *eth.Backend
// whether to forward eth_calls directly to proxy node // whether to forward eth_calls directly to proxy node
forwardEthCalls bool forwardEthCalls bool
// whether to forward eth_getStorageAt directly to proxy node
forwardGetStorageAt bool
// whether to forward all calls to proxy node if they throw an error locally // whether to forward all calls to proxy node if they throw an error locally
proxyOnError bool proxyOnError bool
// eth node network id // eth node network id
@ -104,6 +106,7 @@ func NewServer(settings *Config) (Server, error) {
sap.client = settings.Client sap.client = settings.Client
sap.supportsStateDiffing = settings.SupportStateDiff sap.supportsStateDiffing = settings.SupportStateDiff
sap.forwardEthCalls = settings.ForwardEthCalls sap.forwardEthCalls = settings.ForwardEthCalls
sap.forwardGetStorageAt = settings.ForwardGetStorageAt
sap.proxyOnError = settings.ProxyOnError sap.proxyOnError = settings.ProxyOnError
sap.nodeNetworkId = settings.NodeNetworkID sap.nodeNetworkId = settings.NodeNetworkID
var err error var err error
@ -139,7 +142,7 @@ func (sap *Service) APIs() []rpc.API {
Public: true, Public: true,
}, },
} }
ethAPI, err := eth.NewPublicEthAPI(sap.backend, sap.client, sap.supportsStateDiffing, sap.forwardEthCalls, sap.proxyOnError) ethAPI, err := eth.NewPublicEthAPI(sap.backend, sap.client, sap.supportsStateDiffing, sap.forwardEthCalls, sap.forwardGetStorageAt, sap.proxyOnError)
if err != nil { if err != nil {
log.Fatalf("unable to create public eth api: %v", err) log.Fatalf("unable to create public eth api: %v", err)
} }