mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-18 05:56:37 +00:00
p2p/discover: expose discv5 functions for portal JSON-RPC interface (#31117)
Fixes #31093 Here we add some API functions on the UDPv5 object for the purpose of implementing the Portal Network JSON-RPC API in the shisui client. --------- Signed-off-by: Chen Kai <281165273grape@gmail.com>
This commit is contained in:
parent
f3e4866073
commit
5117f77af9
6 changed files with 92 additions and 26 deletions
|
|
@ -163,7 +163,7 @@ func discv4Ping(ctx *cli.Context) error {
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if err := disc.Ping(n); err != nil {
|
if _, err := disc.Ping(n); err != nil {
|
||||||
return fmt.Errorf("node didn't respond: %v", err)
|
return fmt.Errorf("node didn't respond: %v", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("node responded to ping (RTT %v).\n", time.Since(start))
|
fmt.Printf("node responded to ping (RTT %v).\n", time.Since(start))
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,8 @@ func discv5Ping(ctx *cli.Context) error {
|
||||||
disc, _ := startV5(ctx)
|
disc, _ := startV5(ctx)
|
||||||
defer disc.Close()
|
defer disc.Close()
|
||||||
|
|
||||||
fmt.Println(disc.Ping(n))
|
_, err := disc.Ping(n)
|
||||||
|
fmt.Println(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -694,3 +694,11 @@ func pushNode(list []*tableNode, n *tableNode, max int) ([]*tableNode, *tableNod
|
||||||
list[0] = n
|
list[0] = n
|
||||||
return list, removed
|
return list, removed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deleteNode removes a node from the table.
|
||||||
|
func (tab *Table) deleteNode(n *enode.Node) {
|
||||||
|
tab.mutex.Lock()
|
||||||
|
defer tab.mutex.Unlock()
|
||||||
|
b := tab.bucket(n.ID())
|
||||||
|
tab.deleteInBucket(b, n.ID())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,12 +210,6 @@ func (t *UDPv4) ourEndpoint() v4wire.Endpoint {
|
||||||
return v4wire.NewEndpoint(addr, uint16(node.TCP()))
|
return v4wire.NewEndpoint(addr, uint16(node.TCP()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ping sends a ping message to the given node.
|
|
||||||
func (t *UDPv4) Ping(n *enode.Node) error {
|
|
||||||
_, err := t.ping(n)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ping sends a ping message to the given node and waits for a reply.
|
// ping sends a ping message to the given node and waits for a reply.
|
||||||
func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) {
|
func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) {
|
||||||
addr, ok := n.UDPEndpoint()
|
addr, ok := n.UDPEndpoint()
|
||||||
|
|
@ -229,6 +223,19 @@ func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) {
|
||||||
return seq, err
|
return seq, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ping calls PING on a node and waits for a PONG response.
|
||||||
|
func (t *UDPv4) Ping(n *enode.Node) (pong *v4wire.Pong, err error) {
|
||||||
|
addr, ok := n.UDPEndpoint()
|
||||||
|
if !ok {
|
||||||
|
return nil, errNoUDPEndpoint
|
||||||
|
}
|
||||||
|
rm := t.sendPing(n.ID(), addr, nil)
|
||||||
|
if err = <-rm.errc; err == nil {
|
||||||
|
pong = rm.reply.(*v4wire.Pong)
|
||||||
|
}
|
||||||
|
return pong, err
|
||||||
|
}
|
||||||
|
|
||||||
// sendPing sends a ping message to the given node and invokes the callback
|
// sendPing sends a ping message to the given node and invokes the callback
|
||||||
// when the reply arrives.
|
// when the reply arrives.
|
||||||
func (t *UDPv4) sendPing(toid enode.ID, toaddr netip.AddrPort, callback func()) *replyMatcher {
|
func (t *UDPv4) sendPing(toid enode.ID, toaddr netip.AddrPort, callback func()) *replyMatcher {
|
||||||
|
|
|
||||||
|
|
@ -200,12 +200,6 @@ func (t *UDPv5) Close() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ping sends a ping message to the given node.
|
|
||||||
func (t *UDPv5) Ping(n *enode.Node) error {
|
|
||||||
_, err := t.ping(n)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve searches for a specific node with the given ID and tries to get the most recent
|
// Resolve searches for a specific node with the given ID and tries to get the most recent
|
||||||
// version of the node record for it. It returns n if the node could not be resolved.
|
// version of the node record for it. It returns n if the node could not be resolved.
|
||||||
func (t *UDPv5) Resolve(n *enode.Node) *enode.Node {
|
func (t *UDPv5) Resolve(n *enode.Node) *enode.Node {
|
||||||
|
|
@ -226,6 +220,36 @@ func (t *UDPv5) Resolve(n *enode.Node) *enode.Node {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveNodeId searches for a specific Node with the given ID.
|
||||||
|
// It returns nil if the nodeId could not be resolved.
|
||||||
|
func (t *UDPv5) ResolveNodeId(id enode.ID) *enode.Node {
|
||||||
|
if id == t.Self().ID() {
|
||||||
|
return t.Self()
|
||||||
|
}
|
||||||
|
|
||||||
|
n := t.tab.getNode(id)
|
||||||
|
if n != nil {
|
||||||
|
// Try asking directly. This works if the Node is still responding on the endpoint we have.
|
||||||
|
if resp, err := t.RequestENR(n); err == nil {
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise do a network lookup.
|
||||||
|
result := t.Lookup(id)
|
||||||
|
for _, rn := range result {
|
||||||
|
if rn.ID() == id {
|
||||||
|
if n != nil && rn.Seq() <= n.Seq() {
|
||||||
|
return n
|
||||||
|
} else {
|
||||||
|
return rn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
// AllNodes returns all the nodes stored in the local table.
|
// AllNodes returns all the nodes stored in the local table.
|
||||||
func (t *UDPv5) AllNodes() []*enode.Node {
|
func (t *UDPv5) AllNodes() []*enode.Node {
|
||||||
t.tab.mutex.Lock()
|
t.tab.mutex.Lock()
|
||||||
|
|
@ -240,7 +264,18 @@ func (t *UDPv5) AllNodes() []*enode.Node {
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalNode returns the current local node running the
|
// AddKnownNode adds a node to the routing table.
|
||||||
|
// The function should be used for testing only.
|
||||||
|
func (t *UDPv5) AddKnownNode(n *enode.Node) bool {
|
||||||
|
return t.tab.addFoundNode(n, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteNode removes a node from the routing table. Used for Portal discv5 DeleteEnr API.
|
||||||
|
func (t *UDPv5) DeleteNode(n *enode.Node) {
|
||||||
|
t.tab.deleteNode(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalNode returns the current local Node running the
|
||||||
// protocol.
|
// protocol.
|
||||||
func (t *UDPv5) LocalNode() *enode.LocalNode {
|
func (t *UDPv5) LocalNode() *enode.LocalNode {
|
||||||
return t.localNode
|
return t.localNode
|
||||||
|
|
@ -328,7 +363,7 @@ func (t *UDPv5) lookupWorker(destNode *enode.Node, target enode.ID) ([]*enode.No
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
var r []*enode.Node
|
var r []*enode.Node
|
||||||
r, err = t.findnode(destNode, dists)
|
r, err = t.Findnode(destNode, dists)
|
||||||
if errors.Is(err, errClosed) {
|
if errors.Is(err, errClosed) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -359,21 +394,31 @@ func lookupDistances(target, dest enode.ID) (dists []uint) {
|
||||||
|
|
||||||
// ping calls PING on a node and waits for a PONG response.
|
// ping calls PING on a node and waits for a PONG response.
|
||||||
func (t *UDPv5) ping(n *enode.Node) (uint64, error) {
|
func (t *UDPv5) ping(n *enode.Node) (uint64, error) {
|
||||||
|
pong, err := t.Ping(n)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pong.ENRSeq, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping calls PING on a node and waits for a PONG response.
|
||||||
|
func (t *UDPv5) Ping(n *enode.Node) (*v5wire.Pong, error) {
|
||||||
req := &v5wire.Ping{ENRSeq: t.localNode.Node().Seq()}
|
req := &v5wire.Ping{ENRSeq: t.localNode.Node().Seq()}
|
||||||
resp := t.callToNode(n, v5wire.PongMsg, req)
|
resp := t.callToNode(n, v5wire.PongMsg, req)
|
||||||
defer t.callDone(resp)
|
defer t.callDone(resp)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case pong := <-resp.ch:
|
case pong := <-resp.ch:
|
||||||
return pong.(*v5wire.Pong).ENRSeq, nil
|
return pong.(*v5wire.Pong), nil
|
||||||
case err := <-resp.err:
|
case err := <-resp.err:
|
||||||
return 0, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestENR requests n's record.
|
// RequestENR requests n's record.
|
||||||
func (t *UDPv5) RequestENR(n *enode.Node) (*enode.Node, error) {
|
func (t *UDPv5) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||||
nodes, err := t.findnode(n, []uint{0})
|
nodes, err := t.Findnode(n, []uint{0})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -383,8 +428,8 @@ func (t *UDPv5) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||||
return nodes[0], nil
|
return nodes[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// findnode calls FINDNODE on a node and waits for responses.
|
// Findnode calls FINDNODE on a node and waits for responses.
|
||||||
func (t *UDPv5) findnode(n *enode.Node, distances []uint) ([]*enode.Node, error) {
|
func (t *UDPv5) Findnode(n *enode.Node, distances []uint) ([]*enode.Node, error) {
|
||||||
resp := t.callToNode(n, v5wire.NodesMsg, &v5wire.Findnode{Distances: distances})
|
resp := t.callToNode(n, v5wire.NodesMsg, &v5wire.Findnode{Distances: distances})
|
||||||
return t.waitForNodes(resp, distances)
|
return t.waitForNodes(resp, distances)
|
||||||
}
|
}
|
||||||
|
|
@ -736,8 +781,8 @@ func (t *UDPv5) handleCallResponse(fromID enode.ID, fromAddr netip.AddrPort, p v
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// getNode looks for a node record in table and database.
|
// GetNode looks for a node record in table and database.
|
||||||
func (t *UDPv5) getNode(id enode.ID) *enode.Node {
|
func (t *UDPv5) GetNode(id enode.ID) *enode.Node {
|
||||||
if n := t.tab.getNode(id); n != nil {
|
if n := t.tab.getNode(id); n != nil {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
@ -747,6 +792,11 @@ func (t *UDPv5) getNode(id enode.ID) *enode.Node {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nodes returns the nodes in the routing table.
|
||||||
|
func (t *UDPv5) Nodes() [][]BucketNode {
|
||||||
|
return t.tab.Nodes()
|
||||||
|
}
|
||||||
|
|
||||||
// handle processes incoming packets according to their message type.
|
// handle processes incoming packets according to their message type.
|
||||||
func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort) {
|
func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort) {
|
||||||
switch p := p.(type) {
|
switch p := p.(type) {
|
||||||
|
|
@ -776,7 +826,7 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort
|
||||||
func (t *UDPv5) handleUnknown(p *v5wire.Unknown, fromID enode.ID, fromAddr netip.AddrPort) {
|
func (t *UDPv5) handleUnknown(p *v5wire.Unknown, fromID enode.ID, fromAddr netip.AddrPort) {
|
||||||
challenge := &v5wire.Whoareyou{Nonce: p.Nonce}
|
challenge := &v5wire.Whoareyou{Nonce: p.Nonce}
|
||||||
crand.Read(challenge.IDNonce[:])
|
crand.Read(challenge.IDNonce[:])
|
||||||
if n := t.getNode(fromID); n != nil {
|
if n := t.GetNode(fromID); n != nil {
|
||||||
challenge.Node = n
|
challenge.Node = n
|
||||||
challenge.RecordSeq = n.Seq()
|
challenge.RecordSeq = n.Seq()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,7 @@ func TestUDPv5_findnodeCall(t *testing.T) {
|
||||||
)
|
)
|
||||||
go func() {
|
go func() {
|
||||||
var err error
|
var err error
|
||||||
response, err = test.udp.findnode(remote, distances)
|
response, err = test.udp.Findnode(remote, distances)
|
||||||
done <- err
|
done <- err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -398,7 +398,7 @@ func TestUDPv5_callTimeoutReset(t *testing.T) {
|
||||||
done = make(chan error, 1)
|
done = make(chan error, 1)
|
||||||
)
|
)
|
||||||
go func() {
|
go func() {
|
||||||
_, err := test.udp.findnode(remote, []uint{distance})
|
_, err := test.udp.Findnode(remote, []uint{distance})
|
||||||
done <- err
|
done <- err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue