add StateDiffTimeout config setting #224

Merged
telackey merged 1 commits from roy/config-statediff-timeout into v4 2023-01-13 01:18:12 +00:00
7 changed files with 100 additions and 68 deletions

View File

@ -22,6 +22,7 @@
rpcGasCap = "1000000000000" # $ETH_RPC_GAS_CAP rpcGasCap = "1000000000000" # $ETH_RPC_GAS_CAP
httpPath = "127.0.0.1:8545" # $ETH_HTTP_PATH httpPath = "127.0.0.1:8545" # $ETH_HTTP_PATH
supportsStateDiff = true # $ETH_SUPPORTS_STATEDIFF supportsStateDiff = true # $ETH_SUPPORTS_STATEDIFF
stateDiffTimeout = "4m" # $ETH_STATEDIFF_TIMEOUT
forwardEthCalls = false # $ETH_FORWARD_ETH_CALLS forwardEthCalls = false # $ETH_FORWARD_ETH_CALLS
proxyOnError = true # $ETH_PROXY_ON_ERROR proxyOnError = true # $ETH_PROXY_ON_ERROR
nodeID = "arch1" # $ETH_NODE_ID nodeID = "arch1" # $ETH_NODE_ID

View File

@ -47,7 +47,6 @@ import (
const ( const (
defaultEVMTimeout = 30 * time.Second defaultEVMTimeout = 30 * time.Second
defaultStateDiffTimeout = 240 * time.Second
) )
// APIName is the namespace for the watcher's eth api // APIName is the namespace for the watcher's eth api
@ -56,32 +55,37 @@ const APIName = "eth"
// APIVersion is the version of the watcher's eth api // APIVersion is the version of the watcher's eth api
const APIVersion = "0.0.1" const APIVersion = "0.0.1"
type APIConfig struct {
// 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
ForwardEthCalls bool // if true, forward eth_call calls directly to the configured proxy node
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
StateDiffTimeout time.Duration
}
// PublicEthAPI is the eth namespace API // PublicEthAPI is the eth namespace API
type PublicEthAPI struct { type PublicEthAPI struct {
// Local db backend // Local db backend
B *Backend B *Backend
// 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
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 config APIConfig
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, forwardGetStorageAt, proxyOnError bool) (*PublicEthAPI, error) { func NewPublicEthAPI(b *Backend, client *rpc.Client, config APIConfig) (*PublicEthAPI, error) {
if b == nil { if b == nil {
return nil, errors.New("ipld-eth-server must be configured with an ethereum backend") return nil, errors.New("ipld-eth-server must be configured with an ethereum backend")
} }
if forwardEthCalls && client == nil { if config.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 { if config.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") 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 config.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")
} }
var ethClient *ethclient.Client var ethClient *ethclient.Client
@ -90,12 +94,9 @@ func NewPublicEthAPI(b *Backend, client *rpc.Client, supportsStateDiff, forwardE
} }
return &PublicEthAPI{ return &PublicEthAPI{
B: b, B: b,
supportsStateDiff: supportsStateDiff,
rpc: client, rpc: client,
ethClient: ethClient, ethClient: ethClient,
forwardEthCalls: forwardEthCalls, config: config,
forwardGetStorageAt: forwardGetStorageAt,
proxyOnError: proxyOnError,
}, nil }, nil
} }
@ -113,7 +114,7 @@ func (pea *PublicEthAPI) GetHeaderByNumber(ctx context.Context, number rpc.Block
if header != nil && err == nil { if header != nil && err == nil {
return pea.rpcMarshalHeader(header) return pea.rpcMarshalHeader(header)
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
if header, err := pea.ethClient.HeaderByNumber(ctx, big.NewInt(number.Int64())); header != nil && err == nil { if header, err := pea.ethClient.HeaderByNumber(ctx, big.NewInt(number.Int64())); header != nil && err == nil {
go pea.writeStateDiffAt(number.Int64()) go pea.writeStateDiffAt(number.Int64())
return pea.rpcMarshalHeader(header) return pea.rpcMarshalHeader(header)
@ -132,7 +133,7 @@ func (pea *PublicEthAPI) GetHeaderByHash(ctx context.Context, hash common.Hash)
} }
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var result map[string]interface{} var result map[string]interface{}
if err := pea.rpc.CallContext(ctx, &result, "eth_getHeaderByHash", hash); result != nil && err == nil { if err := pea.rpc.CallContext(ctx, &result, "eth_getHeaderByHash", hash); result != nil && err == nil {
go pea.writeStateDiffFor(hash) go pea.writeStateDiffFor(hash)
@ -174,7 +175,7 @@ func (pea *PublicEthAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockN
return pea.rpcMarshalBlock(block, true, fullTx) return pea.rpcMarshalBlock(block, true, fullTx)
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
if block, err := pea.ethClient.BlockByNumber(ctx, big.NewInt(number.Int64())); block != nil && err == nil { if block, err := pea.ethClient.BlockByNumber(ctx, big.NewInt(number.Int64())); block != nil && err == nil {
go pea.writeStateDiffAt(number.Int64()) go pea.writeStateDiffAt(number.Int64())
return pea.rpcMarshalBlock(block, true, fullTx) return pea.rpcMarshalBlock(block, true, fullTx)
@ -193,7 +194,7 @@ func (pea *PublicEthAPI) GetBlockByHash(ctx context.Context, hash common.Hash, f
return pea.rpcMarshalBlock(block, true, fullTx) return pea.rpcMarshalBlock(block, true, fullTx)
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
if block, err := pea.ethClient.BlockByHash(ctx, hash); block != nil && err == nil { if block, err := pea.ethClient.BlockByHash(ctx, hash); block != nil && err == nil {
go pea.writeStateDiffFor(hash) go pea.writeStateDiffFor(hash)
return pea.rpcMarshalBlock(block, true, fullTx) return pea.rpcMarshalBlock(block, true, fullTx)
@ -206,7 +207,7 @@ func (pea *PublicEthAPI) GetBlockByHash(ctx context.Context, hash common.Hash, f
// ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config. // ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config.
func (pea *PublicEthAPI) ChainId() *hexutil.Big { func (pea *PublicEthAPI) ChainId() *hexutil.Big {
if pea.B.Config.ChainConfig.ChainID == nil || pea.B.Config.ChainConfig.ChainID.Cmp(big.NewInt(0)) <= 0 { if pea.B.Config.ChainConfig.ChainID == nil || pea.B.Config.ChainConfig.ChainID.Cmp(big.NewInt(0)) <= 0 {
if pea.proxyOnError { if pea.config.ProxyOnError {
if id, err := pea.ethClient.ChainID(context.Background()); err == nil { if id, err := pea.ethClient.ChainID(context.Background()); err == nil {
return (*hexutil.Big)(id) return (*hexutil.Big)(id)
} }
@ -237,7 +238,7 @@ func (pea *PublicEthAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, bloc
return pea.rpcMarshalBlock(block, false, false) return pea.rpcMarshalBlock(block, false, false)
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
if uncle, uncleHashes, err := getBlockAndUncleHashes(pea.rpc, ctx, "eth_getUncleByBlockNumberAndIndex", blockNr, index); uncle != nil && err == nil { if uncle, uncleHashes, err := getBlockAndUncleHashes(pea.rpc, ctx, "eth_getUncleByBlockNumberAndIndex", blockNr, index); uncle != nil && err == nil {
go pea.writeStateDiffAt(blockNr.Int64()) go pea.writeStateDiffAt(blockNr.Int64())
return pea.rpcMarshalBlockWithUncleHashes(uncle, uncleHashes, false, false) return pea.rpcMarshalBlockWithUncleHashes(uncle, uncleHashes, false, false)
@ -261,7 +262,7 @@ func (pea *PublicEthAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockH
return pea.rpcMarshalBlock(block, false, false) return pea.rpcMarshalBlock(block, false, false)
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
if uncle, uncleHashes, err := getBlockAndUncleHashes(pea.rpc, ctx, "eth_getUncleByBlockHashAndIndex", blockHash, index); uncle != nil && err == nil { if uncle, uncleHashes, err := getBlockAndUncleHashes(pea.rpc, ctx, "eth_getUncleByBlockHashAndIndex", blockHash, index); uncle != nil && err == nil {
go pea.writeStateDiffFor(blockHash) go pea.writeStateDiffFor(blockHash)
return pea.rpcMarshalBlockWithUncleHashes(uncle, uncleHashes, false, false) return pea.rpcMarshalBlockWithUncleHashes(uncle, uncleHashes, false, false)
@ -278,7 +279,7 @@ func (pea *PublicEthAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr
return &n return &n
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var num *hexutil.Uint var num *hexutil.Uint
if err := pea.rpc.CallContext(ctx, &num, "eth_getUncleCountByBlockNumber", blockNr); num != nil && err == nil { if err := pea.rpc.CallContext(ctx, &num, "eth_getUncleCountByBlockNumber", blockNr); num != nil && err == nil {
go pea.writeStateDiffAt(blockNr.Int64()) go pea.writeStateDiffAt(blockNr.Int64())
@ -296,7 +297,7 @@ func (pea *PublicEthAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash
return &n return &n
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var num *hexutil.Uint var num *hexutil.Uint
if err := pea.rpc.CallContext(ctx, &num, "eth_getUncleCountByBlockHash", blockHash); num != nil && err == nil { if err := pea.rpc.CallContext(ctx, &num, "eth_getUncleCountByBlockHash", blockHash); num != nil && err == nil {
go pea.writeStateDiffFor(blockHash) go pea.writeStateDiffFor(blockHash)
@ -320,7 +321,7 @@ func (pea *PublicEthAPI) GetTransactionCount(ctx context.Context, address common
return count, nil return count, nil
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var num *hexutil.Uint64 var num *hexutil.Uint64
if err := pea.rpc.CallContext(ctx, &num, "eth_getTransactionCount", address, blockNrOrHash); num != nil && err == nil { if err := pea.rpc.CallContext(ctx, &num, "eth_getTransactionCount", address, blockNrOrHash); num != nil && err == nil {
go pea.writeStateDiffAtOrFor(blockNrOrHash) go pea.writeStateDiffAtOrFor(blockNrOrHash)
@ -348,7 +349,7 @@ func (pea *PublicEthAPI) GetBlockTransactionCountByNumber(ctx context.Context, b
return &n return &n
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var num *hexutil.Uint var num *hexutil.Uint
if err := pea.rpc.CallContext(ctx, &num, "eth_getBlockTransactionCountByNumber", blockNr); num != nil && err == nil { if err := pea.rpc.CallContext(ctx, &num, "eth_getBlockTransactionCountByNumber", blockNr); num != nil && err == nil {
go pea.writeStateDiffAt(blockNr.Int64()) go pea.writeStateDiffAt(blockNr.Int64())
@ -366,7 +367,7 @@ func (pea *PublicEthAPI) GetBlockTransactionCountByHash(ctx context.Context, blo
return &n return &n
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var num *hexutil.Uint var num *hexutil.Uint
if err := pea.rpc.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash); num != nil && err == nil { if err := pea.rpc.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash); num != nil && err == nil {
go pea.writeStateDiffFor(blockHash) go pea.writeStateDiffFor(blockHash)
@ -383,7 +384,7 @@ func (pea *PublicEthAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context
return newRPCTransactionFromBlockIndex(block, uint64(index)) return newRPCTransactionFromBlockIndex(block, uint64(index))
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var tx *RPCTransaction var tx *RPCTransaction
if err := pea.rpc.CallContext(ctx, &tx, "eth_getTransactionByBlockNumberAndIndex", blockNr, index); tx != nil && err == nil { if err := pea.rpc.CallContext(ctx, &tx, "eth_getTransactionByBlockNumberAndIndex", blockNr, index); tx != nil && err == nil {
go pea.writeStateDiffAt(blockNr.Int64()) go pea.writeStateDiffAt(blockNr.Int64())
@ -400,7 +401,7 @@ func (pea *PublicEthAPI) GetTransactionByBlockHashAndIndex(ctx context.Context,
return newRPCTransactionFromBlockIndex(block, uint64(index)) return newRPCTransactionFromBlockIndex(block, uint64(index))
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var tx *RPCTransaction var tx *RPCTransaction
if err := pea.rpc.CallContext(ctx, &tx, "eth_getTransactionByBlockHashAndIndex", blockHash, index); tx != nil && err == nil { if err := pea.rpc.CallContext(ctx, &tx, "eth_getTransactionByBlockHashAndIndex", blockHash, index); tx != nil && err == nil {
go pea.writeStateDiffFor(blockHash) go pea.writeStateDiffFor(blockHash)
@ -416,7 +417,7 @@ func (pea *PublicEthAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Cont
if block, _ := pea.B.BlockByNumber(ctx, blockNr); block != nil { if block, _ := pea.B.BlockByNumber(ctx, blockNr); block != nil {
return newRPCRawTransactionFromBlockIndex(block, uint64(index)) return newRPCRawTransactionFromBlockIndex(block, uint64(index))
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var tx hexutil.Bytes var tx hexutil.Bytes
if err := pea.rpc.CallContext(ctx, &tx, "eth_getRawTransactionByBlockNumberAndIndex", blockNr, index); tx != nil && err == nil { if err := pea.rpc.CallContext(ctx, &tx, "eth_getRawTransactionByBlockNumberAndIndex", blockNr, index); tx != nil && err == nil {
go pea.writeStateDiffAt(blockNr.Int64()) go pea.writeStateDiffAt(blockNr.Int64())
@ -431,7 +432,7 @@ func (pea *PublicEthAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Contex
if block, _ := pea.B.BlockByHash(ctx, blockHash); block != nil { if block, _ := pea.B.BlockByHash(ctx, blockHash); block != nil {
return newRPCRawTransactionFromBlockIndex(block, uint64(index)) return newRPCRawTransactionFromBlockIndex(block, uint64(index))
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var tx hexutil.Bytes var tx hexutil.Bytes
if err := pea.rpc.CallContext(ctx, &tx, "eth_getRawTransactionByBlockHashAndIndex", blockHash, index); tx != nil && err == nil { if err := pea.rpc.CallContext(ctx, &tx, "eth_getRawTransactionByBlockHashAndIndex", blockHash, index); tx != nil && err == nil {
go pea.writeStateDiffFor(blockHash) go pea.writeStateDiffFor(blockHash)
@ -453,7 +454,7 @@ func (pea *PublicEthAPI) GetTransactionByHash(ctx context.Context, hash common.H
return NewRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee), nil return NewRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee), nil
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var tx *RPCTransaction var tx *RPCTransaction
if err := pea.rpc.CallContext(ctx, &tx, "eth_getTransactionByHash", hash); tx != nil && err == nil { if err := pea.rpc.CallContext(ctx, &tx, "eth_getTransactionByHash", hash); tx != nil && err == nil {
go pea.writeStateDiffFor(hash) go pea.writeStateDiffFor(hash)
@ -470,7 +471,7 @@ func (pea *PublicEthAPI) GetRawTransactionByHash(ctx context.Context, hash commo
if tx != nil && err == nil { if tx != nil && err == nil {
return rlp.EncodeToBytes(tx) return rlp.EncodeToBytes(tx)
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var tx hexutil.Bytes var tx hexutil.Bytes
if err := pea.rpc.CallContext(ctx, &tx, "eth_getRawTransactionByHash", hash); tx != nil && err == nil { if err := pea.rpc.CallContext(ctx, &tx, "eth_getRawTransactionByHash", hash); tx != nil && err == nil {
go pea.writeStateDiffFor(hash) go pea.writeStateDiffFor(hash)
@ -492,7 +493,7 @@ func (pea *PublicEthAPI) GetTransactionReceipt(ctx context.Context, hash common.
if receipt != nil && err == nil { if receipt != nil && err == nil {
return receipt, nil return receipt, nil
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
if receipt := pea.remoteGetTransactionReceipt(ctx, hash); receipt != nil { if receipt := pea.remoteGetTransactionReceipt(ctx, hash); receipt != nil {
go pea.writeStateDiffFor(hash) go pea.writeStateDiffFor(hash)
return receipt, nil return receipt, nil
@ -590,7 +591,7 @@ func (pea *PublicEthAPI) remoteGetTransactionReceipt(ctx context.Context, hash c
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
func (pea *PublicEthAPI) GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*types.Log, error) { func (pea *PublicEthAPI) GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*types.Log, error) {
logs, err := pea.localGetLogs(crit) logs, err := pea.localGetLogs(crit)
if err != nil && pea.proxyOnError { if err != nil && pea.config.ProxyOnError {
var res []*types.Log var res []*types.Log
if err := pea.rpc.CallContext(ctx, &res, "eth_getLogs", crit); err == nil { if err := pea.rpc.CallContext(ctx, &res, "eth_getLogs", crit); err == nil {
go pea.writeStateDiffWithCriteria(crit) go pea.writeStateDiffWithCriteria(crit)
@ -704,7 +705,7 @@ func (pea *PublicEthAPI) GetBalance(ctx context.Context, address common.Address,
if bal != nil && err == nil { if bal != nil && err == nil {
return bal, nil return bal, nil
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var res *hexutil.Big var res *hexutil.Big
if err := pea.rpc.CallContext(ctx, &res, "eth_getBalance", address, blockNrOrHash); res != nil && err == nil { if err := pea.rpc.CallContext(ctx, &res, "eth_getBalance", address, blockNrOrHash); res != nil && err == nil {
return res, nil return res, nil
@ -729,7 +730,7 @@ 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 { if pea.config.ForwardGetStorageAt {
var res hexutil.Bytes var res hexutil.Bytes
// If forwarding all getStorageAt calls, don't request statediffing. // If forwarding all getStorageAt calls, don't request statediffing.
err := pea.rpc.CallContext(ctx, &res, "eth_getStorageAt", address, key, blockNrOrHash) err := pea.rpc.CallContext(ctx, &res, "eth_getStorageAt", address, key, blockNrOrHash)
@ -750,7 +751,7 @@ func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Addres
return value[:], nil return value[:], nil
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
logrus.Warnf("Missing eth_getStorageAt(%s, %s, %s)", address.Hash().String(), key, blockNrOrHash.String()) 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 {
@ -769,7 +770,7 @@ func (pea *PublicEthAPI) GetCode(ctx context.Context, address common.Address, bl
if code != nil && err == nil { if code != nil && err == nil {
return code, nil return code, nil
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var res hexutil.Bytes var res hexutil.Bytes
if err := pea.rpc.CallContext(ctx, &res, "eth_getCode", address, blockNrOrHash); res != nil && err == nil { if err := pea.rpc.CallContext(ctx, &res, "eth_getCode", address, blockNrOrHash); res != nil && err == nil {
return res, nil return res, nil
@ -788,7 +789,7 @@ func (pea *PublicEthAPI) GetProof(ctx context.Context, address common.Address, s
if proof != nil && err == nil { if proof != nil && err == nil {
return proof, nil return proof, nil
} }
if pea.proxyOnError { if pea.config.ProxyOnError {
var res *AccountResult var res *AccountResult
if err := pea.rpc.CallContext(ctx, &res, "eth_getProof", address, storageKeys, blockNrOrHash); res != nil && err == nil { if err := pea.rpc.CallContext(ctx, &res, "eth_getProof", address, storageKeys, blockNrOrHash); res != nil && err == nil {
return res, nil return res, nil
@ -940,7 +941,7 @@ 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 { if pea.config.ForwardEthCalls {
var hex hexutil.Bytes var hex hexutil.Bytes
err := pea.rpc.CallContext(ctx, &hex, "eth_call", args, blockNrOrHash, overrides) err := pea.rpc.CallContext(ctx, &hex, "eth_call", args, blockNrOrHash, overrides)
return hex, err return hex, err
@ -957,7 +958,7 @@ func (pea *PublicEthAPI) Call(ctx context.Context, args CallArgs, blockNrOrHash
} }
} }
if err != nil && pea.proxyOnError { if err != nil && pea.config.ProxyOnError {
var hex hexutil.Bytes var hex hexutil.Bytes
if err := pea.rpc.CallContext(ctx, &hex, "eth_call", args, blockNrOrHash, overrides); hex != nil && err == nil { if err := pea.rpc.CallContext(ctx, &hex, "eth_call", args, blockNrOrHash, overrides); hex != nil && err == nil {
return hex, nil return hex, nil
@ -1035,7 +1036,7 @@ func DoCall(ctx context.Context, b *Backend, args CallArgs, blockNrOrHash rpc.Bl
// writeStateDiffAtOrFor calls out to the proxy statediffing geth client to fill in a gap in the index // writeStateDiffAtOrFor calls out to the proxy statediffing geth client to fill in a gap in the index
func (pea *PublicEthAPI) writeStateDiffAtOrFor(blockNrOrHash rpc.BlockNumberOrHash) { func (pea *PublicEthAPI) writeStateDiffAtOrFor(blockNrOrHash rpc.BlockNumberOrHash) {
// short circuit right away if the proxy doesn't support diffing // short circuit right away if the proxy doesn't support diffing
if !pea.supportsStateDiff { if !pea.config.SupportsStateDiff {
return return
} }
if blockNr, ok := blockNrOrHash.Number(); ok { if blockNr, ok := blockNrOrHash.Number(); ok {
@ -1050,7 +1051,7 @@ func (pea *PublicEthAPI) writeStateDiffAtOrFor(blockNrOrHash rpc.BlockNumberOrHa
// writeStateDiffWithCriteria calls out to the proxy statediffing geth client to fill in a gap in the index // writeStateDiffWithCriteria calls out to the proxy statediffing geth client to fill in a gap in the index
func (pea *PublicEthAPI) writeStateDiffWithCriteria(crit filters.FilterCriteria) { func (pea *PublicEthAPI) writeStateDiffWithCriteria(crit filters.FilterCriteria) {
// short circuit right away if the proxy doesn't support diffing // short circuit right away if the proxy doesn't support diffing
if !pea.supportsStateDiff || crit.BlockHash == nil { if !pea.config.SupportsStateDiff || crit.BlockHash == nil {
return return
} }
pea.writeStateDiffFor(*crit.BlockHash) pea.writeStateDiffFor(*crit.BlockHash)
@ -1058,11 +1059,11 @@ func (pea *PublicEthAPI) writeStateDiffWithCriteria(crit filters.FilterCriteria)
// writeStateDiffAt calls out to the proxy statediffing geth client to fill in a gap in the index // writeStateDiffAt calls out to the proxy statediffing geth client to fill in a gap in the index
func (pea *PublicEthAPI) writeStateDiffAt(height int64) { func (pea *PublicEthAPI) writeStateDiffAt(height int64) {
if !pea.supportsStateDiff { if !pea.config.SupportsStateDiff {
return return
} }
// we use a separate context than the one provided by the client // we use a separate context than the one provided by the client
ctx, cancel := context.WithTimeout(context.Background(), defaultStateDiffTimeout) ctx, cancel := context.WithTimeout(context.Background(), pea.config.StateDiffTimeout)
defer cancel() defer cancel()
var data json.RawMessage var data json.RawMessage
params := statediff.Params{ params := statediff.Params{
@ -1075,17 +1076,17 @@ func (pea *PublicEthAPI) writeStateDiffAt(height int64) {
} }
logrus.Debugf("Calling statediff_writeStateDiffAt(%d)", height) 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 failed with err %s", height, err.Error())
} }
} }
// writeStateDiffFor calls out to the proxy statediffing geth client to fill in a gap in the index // writeStateDiffFor calls out to the proxy statediffing geth client to fill in a gap in the index
func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) { func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) {
if !pea.supportsStateDiff { if !pea.config.SupportsStateDiff {
return return
} }
// we use a separate context than the one provided by the client // we use a separate context than the one provided by the client
ctx, cancel := context.WithTimeout(context.Background(), defaultStateDiffTimeout) ctx, cancel := context.WithTimeout(context.Background(), pea.config.StateDiffTimeout)
defer cancel() defer cancel()
var data json.RawMessage var data json.RawMessage
params := statediff.Params{ params := statediff.Params{
@ -1098,7 +1099,7 @@ func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) {
} }
logrus.Debugf("Calling statediff_writeStateDiffFor(%s)", blockHash.Hex()) 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 failed with err %s", blockHash.Hex(), err.Error())
} }
} }

View File

@ -21,9 +21,6 @@ import (
"math/big" "math/big"
"strconv" "strconv"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -38,6 +35,10 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
) )
var ( var (
@ -211,7 +212,7 @@ var _ = Describe("API", func() {
}, },
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
api, _ = eth.NewPublicEthAPI(backend, nil, false, false, false, false) api, _ = eth.NewPublicEthAPI(backend, nil, eth.APIConfig{false, false, false, false, shared.DefaultStateDiffTimeout})
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

@ -24,9 +24,6 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@ -40,6 +37,10 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
) )
var ( var (
@ -125,7 +126,7 @@ var _ = Describe("eth state reading tests", func() {
}, },
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
api, _ = eth.NewPublicEthAPI(backend, nil, false, false, false, false) api, _ = eth.NewPublicEthAPI(backend, nil, eth.APIConfig{false, false, false, false, shared.DefaultStateDiffTimeout})
// 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

@ -50,6 +50,7 @@ const (
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_STATEDIFF_TIMEOUT = "ETH_STATEDIFF_TIMEOUT"
ETH_FORWARD_ETH_CALLS = "ETH_FORWARD_ETH_CALLS" ETH_FORWARD_ETH_CALLS = "ETH_FORWARD_ETH_CALLS"
ETH_FORWARD_GET_STORAGE_AT = "ETH_FORWARD_GET_STORAGE_AT" ETH_FORWARD_GET_STORAGE_AT = "ETH_FORWARD_GET_STORAGE_AT"
ETH_PROXY_ON_ERROR = "ETH_PROXY_ON_ERROR" ETH_PROXY_ON_ERROR = "ETH_PROXY_ON_ERROR"
@ -87,6 +88,7 @@ type Config struct {
EthHttpEndpoint string EthHttpEndpoint string
Client *rpc.Client Client *rpc.Client
SupportStateDiff bool SupportStateDiff bool
StateDiffTimeout time.Duration
ForwardEthCalls bool ForwardEthCalls bool
ForwardGetStorageAt bool ForwardGetStorageAt bool
ProxyOnError bool ProxyOnError bool
@ -109,6 +111,7 @@ func NewConfig() (*Config, error) {
viper.BindEnv("ethereum.rpcGasCap", ETH_RPC_GAS_CAP) viper.BindEnv("ethereum.rpcGasCap", ETH_RPC_GAS_CAP)
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.stateDiffTimeout", ETH_STATEDIFF_TIMEOUT)
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.forwardGetStorageAt", ETH_FORWARD_GET_STORAGE_AT)
viper.BindEnv("ethereum.proxyOnError", ETH_PROXY_ON_ERROR) viper.BindEnv("ethereum.proxyOnError", ETH_PROXY_ON_ERROR)
@ -226,6 +229,17 @@ func NewConfig() (*Config, error) {
} else { } else {
c.RPCGasCap = big.NewInt(0) c.RPCGasCap = big.NewInt(0)
} }
if sdTimeout := viper.GetString("ethereum.stateDiffTimeout"); sdTimeout != "" {
var err error
if c.StateDiffTimeout, err = time.ParseDuration(sdTimeout); err != nil {
return nil, err
}
} else {
c.StateDiffTimeout = ethServerShared.DefaultStateDiffTimeout
}
if c.StateDiffTimeout < 0 {
return nil, errors.New("ethereum.stateDiffTimeout < 0")
}
chainConfigPath := viper.GetString("ethereum.chainConfig") chainConfigPath := viper.GetString("ethereum.chainConfig")
if chainConfigPath != "" { if chainConfigPath != "" {
c.ChainConfig, err = statediff.LoadConfig(chainConfigPath) c.ChainConfig, err = statediff.LoadConfig(chainConfigPath)

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"sync" "sync"
"time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
@ -83,6 +84,8 @@ type Service struct {
client *rpc.Client client *rpc.Client
// whether the proxied client supports state diffing // whether the proxied client supports state diffing
supportsStateDiffing bool supportsStateDiffing bool
// timeout for statediff RPC calls
stateDiffTimeout time.Duration
// backend for the server // backend for the server
backend *eth.Backend backend *eth.Backend
// whether to forward eth_calls directly to proxy node // whether to forward eth_calls directly to proxy node
@ -107,6 +110,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.stateDiffTimeout = settings.StateDiffTimeout
sap.forwardEthCalls = settings.ForwardEthCalls sap.forwardEthCalls = settings.ForwardEthCalls
sap.forwardGetStorageAt = settings.ForwardGetStorageAt sap.forwardGetStorageAt = settings.ForwardGetStorageAt
sap.proxyOnError = settings.ProxyOnError sap.proxyOnError = settings.ProxyOnError
@ -144,7 +148,14 @@ func (sap *Service) APIs() []rpc.API {
Public: true, Public: true,
}, },
} }
ethAPI, err := eth.NewPublicEthAPI(sap.backend, sap.client, sap.supportsStateDiffing, sap.forwardEthCalls, sap.forwardGetStorageAt, sap.proxyOnError) conf := eth.APIConfig{
SupportsStateDiff: sap.supportsStateDiffing,
ForwardEthCalls: sap.forwardEthCalls,
ForwardGetStorageAt: sap.forwardGetStorageAt,
ProxyOnError: sap.proxyOnError,
StateDiffTimeout: sap.stateDiffTimeout,
}
ethAPI, err := eth.NewPublicEthAPI(sap.backend, sap.client, conf)
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)
} }

View File

@ -16,9 +16,12 @@
package shared package shared
import "time"
const ( const (
DefaultMaxBatchSize uint64 = 100 DefaultMaxBatchSize uint64 = 100
DefaultMaxBatchNumber int64 = 50 DefaultMaxBatchNumber int64 = 50
DefaultStateDiffTimeout time.Duration = 240 * time.Second
GcachePoolEnabled = "GCACHE_POOL_ENABLED" GcachePoolEnabled = "GCACHE_POOL_ENABLED"
GcachePoolHttpPath = "GCACHE_POOL_HTTP_PATH" GcachePoolHttpPath = "GCACHE_POOL_HTTP_PATH"