mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
Add addPeer RPC (#7804)
This PR mirrors https://github.com/testinprod-io/op-erigon/pull/54. Actual implementation for `admin_addPeer` method. RPC Spec: Refer to https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-admin. > The addPeer administrative method requests adding a new remote node to the list of tracked static nodes. The node will try to maintain connectivity to these nodes at all times, reconnecting every once in a while if the remote connection goes down. Requires https://github.com/ledgerwatch/erigon-lib/pull/1033/ After https://github.com/ledgerwatch/erigon-lib/pull/1033 is merged, will update erigon-lib version, removing replace at go.mod. Note that even if RPC response returns `true`, it does not guarantee that RLPx protocol is established between peers. It just adds node entrypoint to its static peer list, and periodically tries and tests connections. ## Testing This RPC needs integration testing, so I made some scenario. Use below command for testing: Spin up two dev nodes which p2p enabled: Start Node 1: RPC running at port 8545: ```sh ./build/bin/erigon --datadir=dev --chain=dev --port=30303 --http.port=8545 --authrpc.port=8551 --torrent.port=42069 --no-downloader --nodiscover --private.api.addr=127.0.0.1:9090 --http --ws --http.api=admin --p2p.allowed-ports=30306,30307,30308 --authrpc.jwtsecret=/tmp/jwt1 --p2p.protocol=67,68 --log.console.verbosity=5 ``` Start Node 2: RPC running at port 8546: ```sh ./build/bin/erigon --datadir=dev2 --chain=dev --port=30304 --http.port=8546 --authrpc.port=8552 --torrent.port=42068 --no-downloader --nodiscover --private.api.addr=127.0.0.1:9091 --http --ws --http.api=admin --p2p.allowed-ports=30309,30310,30311 --authrpc.jwtsecret=/tmp/jwt2 --p2p.protocol=67,68 --log.console.verbosity=5 ``` Get nodeInfo of node 1 using `admin_nodeInfo` RPC: ```sh curl --location 'localhost:8545/' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc":"2.0", "method":"admin_nodeInfo", "params":[], "id":1 }' ``` Example response: ``` { "jsonrpc": "2.0", "id": 1, "result": { "id": "b75e0c4d2113b6f144ea8fd356a8f90e612a2a5f48a13c78d7e0e176e5724eb2", "name": "erigon/v2.47.0-dev-5d86cdb5/darwin-arm64/go1.19.6", "enode": "enode://05ab575d947f2d73065ea0f795dc2d96ed0ad603f3e730ab90dc881122d552c9f59ffcb148fe50546bec8b319daeb3c22ec02e7d12a7c4f2ac4cd26456a04a7c@127.0.0.1:30303?discport=0", ... ``` Get nodeInfo of node 2 using `admin_nodeInfo` RPC: ```sh curl --location 'localhost:8546/' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc":"2.0", "method":"admin_nodeInfo", "params":[], "id":2 }' ``` Example response: ``` { "jsonrpc": "2.0", "id": 2, "result": { "id": "32d721e4d75219b021d7f83235f1f1eb8b705d6f85e634bccde564b8f7f94d78", "name": "erigon/v2.47.0-dev-5d86cdb5/darwin-arm64/go1.19.6", "enode": "enode://1abb8579647779e13b7f68d18f9c776cbd29281841c7f950e9cf9afa996e31120a6f481cea8e90e0f42a0eb1aa00aeafee81c4bae6c31aa16810b795c6d6e069@127.0.0.1:30304?discport=0", ... ``` Call `admin_addPeer` RPC to node 2: ```sh curl --location 'localhost:8546/' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc":"2.0", "method":"admin_addPeer", "params":["enode://05ab575d947f2d73065ea0f795dc2d96ed0ad603f3e730ab90dc881122d552c9f59ffcb148fe50546bec8b319daeb3c22ec02e7d12a7c4f2ac4cd26456a04a7c@127.0.0.1:30303"], "id":2 }' ``` Example response: ``` { "jsonrpc": "2.0", "id": 2, "result": true } ``` Check peer info of node 1 using `admin_peers` RPC: ```sh curl --location 'localhost:8545/' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc":"2.0", "method":"admin_peers", "params":[], "id":1 }' ``` Example response: ``` { "jsonrpc": "2.0", "id": 1, "result": [ { "enode": "enode://1abb8579647779e13b7f68d18f9c776cbd29281841c7f950e9cf9afa996e31120a6f481cea8e90e0f42a0eb1aa00aeafee81c4bae6c31aa16810b795c6d6e069@127.0.0.1:55426", "id": "32d721e4d75219b021d7f83235f1f1eb8b705d6f85e634bccde564b8f7f94d78", "name": "erigon/v2.47.0-dev-5d86cdb5/darwin-arm64/go1.19.6", "caps": [ "eth/66", "eth/67" ], "network": { "localAddress": "127.0.0.1:30303", "remoteAddress": "127.0.0.1:55426", "inbound": true, "trusted": false, "static": false }, "protocols": null } ] } ``` --------- Co-authored-by: alex.sharov <AskAlexSharov@gmail.com>
This commit is contained in:
parent
1c4819ffe3
commit
ef84972e7c
@ -196,6 +196,7 @@ The following table shows the current implementation status of Erigon's RPC daem
|
||||
| ------------------------------------------ |---------|--------------------------------------|
|
||||
| admin_nodeInfo | Yes | |
|
||||
| admin_peers | Yes | |
|
||||
| admin_addPeer | Yes | |
|
||||
| | | |
|
||||
| web3_clientVersion | Yes | |
|
||||
| web3_sha3 | Yes | |
|
||||
|
@ -315,6 +315,14 @@ func (back *RemoteBackend) NodeInfo(ctx context.Context, limit uint32) ([]p2p.No
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (back *RemoteBackend) AddPeer(ctx context.Context, request *remote.AddPeerRequest) (*remote.AddPeerReply, error) {
|
||||
result, err := back.remoteEthBackend.AddPeer(ctx, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ETHBACKENDClient.AddPeer() error: %w", err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (back *RemoteBackend) Peers(ctx context.Context) ([]*p2p.PeerInfo, error) {
|
||||
rpcPeers, err := back.remoteEthBackend.Peers(ctx, &emptypb.Empty{})
|
||||
if err != nil {
|
||||
|
@ -1209,6 +1209,15 @@ func (ss *GrpcServer) PeerEvents(req *proto_sentry.PeerEventsRequest, server pro
|
||||
}
|
||||
}
|
||||
|
||||
func (ss *GrpcServer) AddPeer(_ context.Context, req *proto_sentry.AddPeerRequest) (*proto_sentry.AddPeerReply, error) {
|
||||
node, err := enode.Parse(enode.ValidSchemes, req.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ss.P2pServer.AddPeer(node)
|
||||
return &proto_sentry.AddPeerReply{Success: true}, nil
|
||||
}
|
||||
|
||||
func (ss *GrpcServer) NodeInfo(_ context.Context, _ *emptypb.Empty) (*proto_types.NodeInfoReply, error) {
|
||||
if ss.P2pServer == nil {
|
||||
return nil, errors.New("p2p server was not started")
|
||||
|
@ -1158,6 +1158,16 @@ func (s *Ethereum) Peers(ctx context.Context) (*remote.PeersReply, error) {
|
||||
return &reply, nil
|
||||
}
|
||||
|
||||
func (s *Ethereum) AddPeer(ctx context.Context, req *remote.AddPeerRequest) (*remote.AddPeerReply, error) {
|
||||
for _, sentryClient := range s.sentriesClient.Sentries() {
|
||||
_, err := sentryClient.AddPeer(ctx, &proto_sentry.AddPeerRequest{Url: req.Url})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ethereum backend MultiClient.AddPeers error: %w", err)
|
||||
}
|
||||
}
|
||||
return &remote.AddPeerReply{Success: true}, nil
|
||||
}
|
||||
|
||||
// Protocols returns all the currently configured
|
||||
// network protocols to start.
|
||||
func (s *Ethereum) Protocols() []p2p.Protocol {
|
||||
|
@ -53,6 +53,7 @@ type EthBackend interface {
|
||||
NetPeerCount() (uint64, error)
|
||||
NodesInfo(limit int) (*remote.NodesInfoReply, error)
|
||||
Peers(ctx context.Context) (*remote.PeersReply, error)
|
||||
AddPeer(ctx context.Context, url *remote.AddPeerRequest) (*remote.AddPeerReply, error)
|
||||
}
|
||||
|
||||
func NewEthBackendServer(ctx context.Context, eth EthBackend, db kv.RwDB, events *shards.Events, blockReader services.FullBlockReader,
|
||||
@ -237,6 +238,10 @@ func (s *EthBackendServer) Peers(ctx context.Context, _ *emptypb.Empty) (*remote
|
||||
return s.eth.Peers(ctx)
|
||||
}
|
||||
|
||||
func (s *EthBackendServer) AddPeer(ctx context.Context, req *remote.AddPeerRequest) (*remote.AddPeerReply, error) {
|
||||
return s.eth.AddPeer(ctx, req)
|
||||
}
|
||||
|
||||
func (s *EthBackendServer) SubscribeLogs(server remote.ETHBACKEND_SubscribeLogsServer) (err error) {
|
||||
if s.logsFilter != nil {
|
||||
return s.logsFilter.subscribeLogs(server)
|
||||
|
2
go.mod
2
go.mod
@ -4,7 +4,7 @@ go 1.19
|
||||
|
||||
require (
|
||||
github.com/erigontech/mdbx-go v0.27.14
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230906075933-15c288cb15e2
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230906082456-e6e986651a99
|
||||
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230818153427-cc16b83a89be
|
||||
github.com/ledgerwatch/log/v3 v3.9.0
|
||||
github.com/ledgerwatch/secp256k1 v1.0.0
|
||||
|
4
go.sum
4
go.sum
@ -497,8 +497,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0=
|
||||
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
|
||||
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230906075933-15c288cb15e2 h1:jFTcWwgVntIEbz1/XCIIyx3+lDIuWiZ2VLMU+xkPh+8=
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230906075933-15c288cb15e2/go.mod h1:GAusrYt0h9+407hBbOjfMzoFIX14xzXTl250QJBhTpE=
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230906082456-e6e986651a99 h1:uEiCTjWnE9mcM1DmDAH1rMieu5URyweJuXm97jFU2XA=
|
||||
github.com/ledgerwatch/erigon-lib v0.0.0-20230906082456-e6e986651a99/go.mod h1:GaedHoxQeHl1nKalZlv5idXr3ZR2ojo/0Lb1uF8l/so=
|
||||
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230818153427-cc16b83a89be h1:6/4MXkk5AoKUHivIpCokHOX/WV9L7tXgURp1k8KfmSM=
|
||||
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230818153427-cc16b83a89be/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo=
|
||||
github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk=
|
||||
|
@ -5,7 +5,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ledgerwatch/erigon-lib/gointerfaces/remote"
|
||||
"github.com/ledgerwatch/erigon/p2p"
|
||||
|
||||
"github.com/ledgerwatch/erigon/turbo/rpchelper"
|
||||
)
|
||||
|
||||
@ -17,6 +19,9 @@ type AdminAPI interface {
|
||||
// Peers returns information about the connected remote nodes.
|
||||
// https://geth.ethereum.org/docs/rpc/ns-admin#admin_peers
|
||||
Peers(ctx context.Context) ([]*p2p.PeerInfo, error)
|
||||
|
||||
// AddPeer requests connecting to a remote node.
|
||||
AddPeer(ctx context.Context, url string) (bool, error)
|
||||
}
|
||||
|
||||
// AdminAPIImpl data structure to store things needed for admin_* commands.
|
||||
@ -47,3 +52,14 @@ func (api *AdminAPIImpl) NodeInfo(ctx context.Context) (*p2p.NodeInfo, error) {
|
||||
func (api *AdminAPIImpl) Peers(ctx context.Context) ([]*p2p.PeerInfo, error) {
|
||||
return api.ethBackend.Peers(ctx)
|
||||
}
|
||||
|
||||
func (api *AdminAPIImpl) AddPeer(ctx context.Context, url string) (bool, error) {
|
||||
result, err := api.ethBackend.AddPeer(ctx, &remote.AddPeerRequest{Url: url})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if result == nil {
|
||||
return false, errors.New("nil addPeer response")
|
||||
}
|
||||
return result.Success, nil
|
||||
}
|
||||
|
@ -27,5 +27,6 @@ type ApiBackend interface {
|
||||
BlockWithSenders(ctx context.Context, tx kv.Getter, hash libcommon.Hash, blockHeight uint64) (block *types.Block, senders []libcommon.Address, err error)
|
||||
NodeInfo(ctx context.Context, limit uint32) ([]p2p.NodeInfo, error)
|
||||
Peers(ctx context.Context) ([]*p2p.PeerInfo, error)
|
||||
AddPeer(ctx context.Context, url *remote.AddPeerRequest) (*remote.AddPeerReply, error)
|
||||
PendingBlock(ctx context.Context) (*types.Block, error)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user