Remove RpcProxy from Fluffy and use RpcHttpServer instead. (#2634)

* Remove RpcProxy from Fluffy and use RpcHttpServer instead.

* Cleanup test.
This commit is contained in:
web3-developer 2024-09-18 15:46:50 +08:00 committed by GitHub
parent c652f5efc2
commit 0ee8e61a3a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 44 additions and 161 deletions

View File

@ -15,7 +15,6 @@ import
chronicles,
eth/keys,
eth/p2p/discoveryv5/[enr, node, routing_table],
json_rpc/rpcproxy,
nimcrypto/hash,
stew/byteutils,
eth/net/nat, # must be late (compilation annoyance)
@ -36,13 +35,10 @@ proc defaultDataDir*(): string =
const
defaultListenAddress* = (static parseIpAddress("0.0.0.0"))
defaultAdminListenAddress* = (static parseIpAddress("127.0.0.1"))
defaultProxyAddress* = (static "http://127.0.0.1:8546")
defaultClientConfig* = getHttpClientConfig(defaultProxyAddress)
defaultListenAddressDesc = $defaultListenAddress
defaultAdminListenAddressDesc = $defaultAdminListenAddress
defaultDataDirDesc = defaultDataDir()
defaultClientConfigDesc = $(defaultClientConfig.httpUri)
defaultStorageCapacity* = 2000'u32 # 2 GB default
defaultStorageCapacityDesc* = $defaultStorageCapacity
@ -192,15 +188,6 @@ type
name: "rpc-address"
.}: IpAddress
# it makes little sense to have default value here in final release, but until then
# it would be troublesome to add some fake uri param every time
proxyUri* {.
defaultValue: defaultClientConfig,
defaultValueDesc: $defaultClientConfigDesc,
desc: "URI of eth client where to proxy unimplemented JSON-RPC methods to",
name: "proxy-uri"
.}: ClientConfig
tableIpLimit* {.
hidden,
desc:
@ -329,20 +316,6 @@ proc parseCmdArg*(T: type PrivateKey, p: string): T {.raises: [ValueError].} =
proc completeCmdArg*(T: type PrivateKey, val: string): seq[string] =
return @[]
proc parseCmdArg*(T: type ClientConfig, p: string): T {.raises: [ValueError].} =
let uri = parseUri(p)
if (uri.scheme == "http" or uri.scheme == "https"):
getHttpClientConfig(p)
elif (uri.scheme == "ws" or uri.scheme == "wss"):
getWebSocketClientConfig(p)
else:
raise newException(
ValueError, "Proxy uri should have defined scheme (http/https/ws/wss)"
)
proc completeCmdArg*(T: type ClientConfig, val: string): seq[string] =
return @[]
proc parseCmdArg*(
T: type set[PortalSubnetwork], p: string
): T {.raises: [ValueError].} =

View File

@ -17,7 +17,6 @@ import
metrics,
metrics/chronos_httpserver,
json_rpc/clients/httpclient,
json_rpc/rpcproxy,
results,
stew/[byteutils, io2],
eth/keys,
@ -216,30 +215,29 @@ proc run(config: PortalConf) {.raises: [CatchableError].} =
# Note: Set maxRequestBodySize to 4MB instead of 1MB as there are blocks
# that reach that limit (in hex, for gossip method).
rpcHttpServer.addHttpServer(ta, maxRequestBodySize = 4 * 1_048_576)
var rpcHttpServerWithProxy = RpcProxy.new(rpcHttpServer, config.proxyUri)
rpcHttpServerWithProxy.installDiscoveryApiHandlers(d)
rpcHttpServerWithProxy.installWeb3ApiHandlers()
rpcHttpServer.installDiscoveryApiHandlers(d)
rpcHttpServer.installWeb3ApiHandlers()
if node.stateNetwork.isSome():
rpcHttpServerWithProxy.installPortalApiHandlers(
rpcHttpServer.installPortalApiHandlers(
node.stateNetwork.value.portalProtocol, "state"
)
if node.historyNetwork.isSome():
rpcHttpServerWithProxy.installEthApiHandlers(
rpcHttpServer.installEthApiHandlers(
node.historyNetwork.value, node.beaconLightClient, node.stateNetwork
)
rpcHttpServerWithProxy.installPortalApiHandlers(
rpcHttpServer.installPortalApiHandlers(
node.historyNetwork.value.portalProtocol, "history"
)
rpcHttpServerWithProxy.installPortalDebugApiHandlers(
rpcHttpServer.installPortalDebugApiHandlers(
node.historyNetwork.value.portalProtocol, "history"
)
if node.beaconNetwork.isSome():
rpcHttpServerWithProxy.installPortalApiHandlers(
rpcHttpServer.installPortalApiHandlers(
node.beaconNetwork.value.portalProtocol, "beacon"
)
# TODO: Test proxy with remote node over HTTPS
waitFor rpcHttpServerWithProxy.start()
rpcHttpServer.start()
runForever()

View File

@ -9,7 +9,7 @@
import
std/sequtils,
json_rpc/[rpcproxy, rpcserver],
json_rpc/rpcserver,
stew/byteutils,
eth/p2p/discoveryv5/protocol as discv5_protocol,
./rpc_types
@ -23,9 +23,7 @@ type PongResponse* = object
PongResponse.useDefaultSerializationIn JrpcConv
proc installDiscoveryApiHandlers*(
rpcServer: RpcServer | RpcProxy, d: discv5_protocol.Protocol
) =
proc installDiscoveryApiHandlers*(rpcServer: RpcServer, d: discv5_protocol.Protocol) =
## Discovery v5 JSON-RPC API such as defined here:
## https://github.com/ethereum/portal-network-specs/tree/master/jsonrpc

View File

@ -9,7 +9,7 @@
import
std/[times, sequtils, strutils, typetraits],
json_rpc/[rpcproxy, rpcserver],
json_rpc/rpcserver,
chronicles,
web3/conversions, # sigh, for FixedBytes marshalling
web3/eth_api_types,
@ -35,12 +35,6 @@ from ../../nimbus/beacon/web3_eth_conv import w3Addr, w3Hash, ethHash
# - eth_getBlockTransactionCountByHash
# - eth_getLogs - Partially: only requests by block hash
#
# In order to be able to use Fluffy as drop-in replacement for apps/tools that
# use the JSON RPC API, unsupported methods can be forwarded to a configured
# web3 provider.
# Supported methods will be handled by Fluffy by making use of the Portal network,
# unsupported methods will be proxied to the given web3 provider.
#
# Some similar code as from nimbus `rpc_utils`, but avoiding that import as it
# brings in a lot more. Should restructure `rpc_utils` a bit before using that.
@ -128,94 +122,19 @@ func init*(
blockObject
proc installEthApiHandlers*(
rpcServerWithProxy: var RpcProxy,
rpcServer: RpcServer,
historyNetwork: HistoryNetwork,
beaconLightClient: Opt[LightClient],
stateNetwork: Opt[StateNetwork],
) =
# Supported API
rpcServerWithProxy.registerProxyMethod("eth_blockNumber")
rpcServerWithProxy.registerProxyMethod("eth_call")
# rpcServerWithProxy.registerProxyMethod("eth_chainId")
rpcServerWithProxy.registerProxyMethod("eth_estimateGas")
rpcServerWithProxy.registerProxyMethod("eth_feeHistory")
#rpcServerWithProxy.registerProxyMethod("eth_getBalance")
# rpcServerWithProxy.registerProxyMethod("eth_getBlockByHash")
# rpcServerWithProxy.registerProxyMethod("eth_getBlockByNumber")
# rpcServerWithProxy.registerProxyMethod("eth_getBlockTransactionCountByHash")
rpcServerWithProxy.registerProxyMethod("eth_getBlockTransactionCountByNumber")
#rpcServerWithProxy.registerProxyMethod("eth_getCode")
rpcServerWithProxy.registerProxyMethod("eth_getRawTransactionByHash")
rpcServerWithProxy.registerProxyMethod("eth_getRawTransactionByBlockHashAndIndex")
rpcServerWithProxy.registerProxyMethod("eth_getRawTransactionByBlockNumberAndIndex")
#rpcServerWithProxy.registerProxyMethod("eth_getStorageAt")
rpcServerWithProxy.registerProxyMethod("eth_getTransactionByBlockHashAndIndex")
rpcServerWithProxy.registerProxyMethod("eth_getTransactionByBlockNumberAndIndex")
rpcServerWithProxy.registerProxyMethod("eth_getTransactionByHash")
#rpcServerWithProxy.registerProxyMethod("eth_getTransactionCount")
rpcServerWithProxy.registerProxyMethod("eth_getTransactionReceipt")
rpcServerWithProxy.registerProxyMethod("eth_getUncleByBlockHashAndIndex")
rpcServerWithProxy.registerProxyMethod("eth_getUncleByBlockNumberAndIndex")
rpcServerWithProxy.registerProxyMethod("eth_getUncleCountByBlockHash")
rpcServerWithProxy.registerProxyMethod("eth_getUncleCountByBlockNumber")
#rpcServerWithProxy.registerProxyMethod("eth_getProof")
rpcServerWithProxy.registerProxyMethod("eth_sendRawTransaction")
# Optional API
rpcServerWithProxy.registerProxyMethod("eth_gasPrice")
rpcServerWithProxy.registerProxyMethod("eth_getFilterChanges")
rpcServerWithProxy.registerProxyMethod("eth_getFilterLogs")
# rpcServerWithProxy.registerProxyMethod("eth_getLogs")
rpcServerWithProxy.registerProxyMethod("eth_newBlockFilter")
rpcServerWithProxy.registerProxyMethod("eth_newFilter")
rpcServerWithProxy.registerProxyMethod("eth_newPendingTransactionFilter")
rpcServerWithProxy.registerProxyMethod("eth_pendingTransactions")
rpcServerWithProxy.registerProxyMethod("eth_syncing")
rpcServerWithProxy.registerProxyMethod("eth_uninstallFilter")
# Supported API through the Portal Network
rpcServerWithProxy.rpc("eth_chainId") do() -> Quantity:
rpcServer.rpc("eth_chainId") do() -> Quantity:
# The Portal Network can only support MainNet at the moment, so always return
# 1
return Quantity(uint64(1))
rpcServerWithProxy.rpc("eth_getBlockByHash") do(
rpcServer.rpc("eth_getBlockByHash") do(
data: eth_api_types.Hash256, fullTransactions: bool
) -> Opt[BlockObject]:
## Returns information about a block by hash.
@ -232,7 +151,7 @@ proc installEthApiHandlers*(
return Opt.some(BlockObject.init(header, body, fullTransactions))
rpcServerWithProxy.rpc("eth_getBlockByNumber") do(
rpcServer.rpc("eth_getBlockByNumber") do(
quantityTag: RtBlockIdentifier, fullTransactions: bool
) -> Opt[BlockObject]:
if quantityTag.kind == bidAlias:
@ -286,7 +205,7 @@ proc installEthApiHandlers*(
return Opt.some(BlockObject.init(header, body, fullTransactions))
rpcServerWithProxy.rpc("eth_getBlockTransactionCountByHash") do(
rpcServer.rpc("eth_getBlockTransactionCountByHash") do(
data: eth_api_types.Hash256
) -> Quantity:
## Returns the number of transactions in a block from a block matching the
@ -309,12 +228,10 @@ proc installEthApiHandlers*(
# of tx hash -> block number -> block hash, in order to get the receipt
# from from the block with that block hash. The Canonical Indices Network
# would need to be implemented to get this information.
# rpcServerWithProxy.rpc("eth_getTransactionReceipt") do(
# rpcServer.rpc("eth_getTransactionReceipt") do(
# data: EthHashStr) -> Opt[ReceiptObject]:
rpcServerWithProxy.rpc("eth_getLogs") do(
filterOptions: FilterOptions
) -> seq[LogObject]:
rpcServer.rpc("eth_getLogs") do(filterOptions: FilterOptions) -> seq[LogObject]:
if filterOptions.blockHash.isNone():
# Currently only queries by blockhash are supported.
# TODO: Can impolement range queries by block number now.
@ -346,7 +263,7 @@ proc installEthApiHandlers*(
# bloomfilter returned false, there are no logs matching the criteria
return @[]
rpcServerWithProxy.rpc("eth_getBalance") do(
rpcServer.rpc("eth_getBalance") do(
data: web3Types.Address, quantityTag: RtBlockIdentifier
) -> UInt256:
## Returns the balance of the account of given address.
@ -369,7 +286,7 @@ proc installEthApiHandlers*(
return balance
rpcServerWithProxy.rpc("eth_getTransactionCount") do(
rpcServer.rpc("eth_getTransactionCount") do(
data: web3Types.Address, quantityTag: RtBlockIdentifier
) -> Quantity:
## Returns the number of transactions sent from an address.
@ -391,7 +308,7 @@ proc installEthApiHandlers*(
raise newException(ValueError, "Unable to get transaction count")
return nonce.Quantity
rpcServerWithProxy.rpc("eth_getStorageAt") do(
rpcServer.rpc("eth_getStorageAt") do(
data: web3Types.Address, slot: UInt256, quantityTag: RtBlockIdentifier
) -> FixedBytes[32]:
## Returns the value from a storage position at a given address.
@ -414,7 +331,7 @@ proc installEthApiHandlers*(
raise newException(ValueError, "Unable to get storage slot")
return FixedBytes[32](slotValue.toBytesBE())
rpcServerWithProxy.rpc("eth_getCode") do(
rpcServer.rpc("eth_getCode") do(
data: web3Types.Address, quantityTag: RtBlockIdentifier
) -> seq[byte]:
## Returns code at a given address.
@ -436,7 +353,7 @@ proc installEthApiHandlers*(
raise newException(ValueError, "Unable to get code")
return bytecode.asSeq()
rpcServerWithProxy.rpc("eth_getProof") do(
rpcServer.rpc("eth_getProof") do(
data: web3Types.Address, slots: seq[UInt256], quantityTag: RtBlockIdentifier
) -> ProofResponse:
## Returns information about an account and storage slots along with account
@ -483,7 +400,7 @@ proc installEthApiHandlers*(
# TODO: Should we move these debug methods into a separate debug rpcServer?
rpcServerWithProxy.rpc("debug_getBalanceByStateRoot") do(
rpcServer.rpc("debug_getBalanceByStateRoot") do(
data: web3Types.Address, stateRoot: web3types.Hash256
) -> UInt256:
## Returns the balance of the account of given address.
@ -504,7 +421,7 @@ proc installEthApiHandlers*(
return balance
rpcServerWithProxy.rpc("debug_getTransactionCountByStateRoot") do(
rpcServer.rpc("debug_getTransactionCountByStateRoot") do(
data: web3Types.Address, stateRoot: web3types.Hash256
) -> Quantity:
## Returns the number of transactions sent from an address.
@ -524,7 +441,7 @@ proc installEthApiHandlers*(
raise newException(ValueError, "Unable to get transaction count")
return nonce.Quantity
rpcServerWithProxy.rpc("debug_getStorageAtByStateRoot") do(
rpcServer.rpc("debug_getStorageAtByStateRoot") do(
data: web3Types.Address, slot: UInt256, stateRoot: web3types.Hash256
) -> FixedBytes[32]:
## Returns the value from a storage position at a given address.
@ -545,7 +462,7 @@ proc installEthApiHandlers*(
raise newException(ValueError, "Unable to get storage slot")
return FixedBytes[32](slotValue.toBytesBE())
rpcServerWithProxy.rpc("debug_getCodeByStateRoot") do(
rpcServer.rpc("debug_getCodeByStateRoot") do(
data: web3Types.Address, stateRoot: web3types.Hash256
) -> seq[byte]:
## Returns code at a given address.
@ -566,7 +483,7 @@ proc installEthApiHandlers*(
return bytecode.asSeq()
rpcServerWithProxy.rpc("debug_getProofByStateRoot") do(
rpcServer.rpc("debug_getProofByStateRoot") do(
data: web3Types.Address, slots: seq[UInt256], stateRoot: web3types.Hash256
) -> ProofResponse:
## Returns information about an account and storage slots along with account

View File

@ -9,7 +9,7 @@
import
std/[sequtils, json],
json_rpc/[rpcproxy, rpcserver],
json_rpc/rpcserver,
json_serialization/std/tables,
stew/byteutils,
../network/wire/portal_protocol,
@ -41,7 +41,7 @@ TraceResponse.useDefaultSerializationIn JrpcConv
# as the proc becomes generic, where the rpc macro from router.nim can no longer
# be found, which is why we export rpcserver which should export router.
proc installPortalApiHandlers*(
rpcServer: RpcServer | RpcProxy, p: PortalProtocol, network: static string
rpcServer: RpcServer, p: PortalProtocol, network: static string
) =
let
invalidKeyErr =

View File

@ -8,7 +8,7 @@
{.push raises: [].}
import
json_rpc/[rpcproxy, rpcserver],
json_rpc/rpcserver,
stew/byteutils,
../network/wire/portal_protocol,
../eth_data/history_data_seeding,
@ -19,7 +19,7 @@ export rpcserver
# Non-spec-RPCs that are used for testing, debugging and seeding data without a
# bridge.
proc installPortalDebugApiHandlers*(
rpcServer: RpcServer | RpcProxy, p: PortalProtocol, network: static string
rpcServer: RpcServer, p: PortalProtocol, network: static string
) =
## Portal debug API calls related to storage and seeding from Era1 files.
rpcServer.rpc("portal_" & network & "GossipHeaders") do(

View File

@ -7,10 +7,10 @@
{.push raises: [].}
import json_rpc/[rpcproxy, rpcserver], ../version
import json_rpc/rpcserver, ../version
export rpcserver
proc installWeb3ApiHandlers*(rpcServer: RpcServer | RpcProxy) =
proc installWeb3ApiHandlers*(rpcServer: RpcServer) =
rpcServer.rpc("web3_clientVersion") do() -> string:
return clientVersion

View File

@ -10,7 +10,7 @@
import
chronos,
testutils/unittests,
json_rpc/[rpcproxy, rpcserver],
json_rpc/rpcserver,
json_rpc/clients/httpclient,
stint,
eth/p2p/discoveryv5/enr,
@ -21,7 +21,7 @@ import
type TestCase = ref object
localDiscovery: discv5_protocol.Protocol
server: RpcProxy
server: RpcHttpServer
client: RpcHttpClient
proc setupTest(rng: ref HmacDrbgContext): Future[TestCase] {.async.} =
@ -31,20 +31,17 @@ proc setupTest(rng: ref HmacDrbgContext): Future[TestCase] {.async.} =
ta = initTAddress(localSrvAddress, localSrvPort)
localDiscoveryNode =
initDiscoveryNode(rng, PrivateKey.random(rng[]), localAddress(20302))
fakeProxyConfig = getHttpClientConfig("http://127.0.0.1:8546")
client = newRpcHttpClient()
var rpcHttpServerWithProxy = RpcProxy.new([ta], fakeProxyConfig)
let rpcHttpServer = RpcHttpServer.new()
rpcHttpServer.addHttpServer(ta, maxRequestBodySize = 4 * 1_048_576)
rpcHttpServerWithProxy.installDiscoveryApiHandlers(localDiscoveryNode)
rpcHttpServer.installDiscoveryApiHandlers(localDiscoveryNode)
await rpcHttpServerWithProxy.start()
await client.connect(
localSrvAddress, rpcHttpServerWithProxy.localAddress[0].port, false
)
return TestCase(
localDiscovery: localDiscoveryNode, server: rpcHttpServerWithProxy, client: client
)
rpcHttpServer.start()
await client.connect(localSrvAddress, rpcHttpServer.localAddress[0].port, false)
return
TestCase(localDiscovery: localDiscoveryNode, server: rpcHttpServer, client: client)
proc stop(testCase: TestCase) {.async.} =
await testCase.server.stop()