mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
feat:rpc disc/history part1
Signed-off-by: Chen Kai <281165273grape@gmail.com>
This commit is contained in:
parent
1b8bfec093
commit
a9643f4ba7
2 changed files with 242 additions and 3 deletions
183
p2p/discover/api.go
Normal file
183
p2p/discover/api.go
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
package discover
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
)
|
||||
|
||||
type DiscV5API struct {
|
||||
DiscV5 *UDPv5
|
||||
}
|
||||
|
||||
func NewAPI(discV5 *UDPv5) *DiscV5API {
|
||||
return &DiscV5API{discV5}
|
||||
}
|
||||
|
||||
type NodeInfo struct {
|
||||
NodeId string `json:"nodeId"`
|
||||
Enr string `json:"enr"`
|
||||
Ip string `json:"ip"`
|
||||
}
|
||||
|
||||
type RoutingTableInfo struct {
|
||||
Buckets []string `json:"buckets"`
|
||||
LocalNodeId string `json:"localNodeId"`
|
||||
}
|
||||
|
||||
func (d *DiscV5API) NodeInfo() *NodeInfo {
|
||||
n := d.DiscV5.LocalNode().Node()
|
||||
|
||||
return &NodeInfo{
|
||||
NodeId: n.ID().String(),
|
||||
Enr: n.String(),
|
||||
Ip: n.IP().String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DiscV5API) RoutingTableInfo() *RoutingTableInfo {
|
||||
n := d.DiscV5.LocalNode().Node()
|
||||
|
||||
closestNodes := d.DiscV5.AllNodes()
|
||||
buckets := make([]string, len(closestNodes))
|
||||
for _, e := range closestNodes {
|
||||
buckets = append(buckets, e.ID().String())
|
||||
}
|
||||
|
||||
return &RoutingTableInfo{
|
||||
Buckets: buckets,
|
||||
LocalNodeId: n.ID().String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DiscV5API) AddEnr(enr string) (bool, error) {
|
||||
n, err := enode.Parse(enode.ValidSchemes, enr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
d.DiscV5.tab.addSeenNode(wrapNode(n))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (d *DiscV5API) GetEnr(nodeId string) (bool, error) {
|
||||
id, err := enode.ParseID(nodeId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
n := d.DiscV5.tab.getNode(id)
|
||||
if n == nil {
|
||||
return false, errors.New("record not in local routing table")
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type PortalAPI struct {
|
||||
*DiscV5API
|
||||
portalProtocol *PortalProtocol
|
||||
}
|
||||
|
||||
func NewPortalAPI(portalProtocol *PortalProtocol) *PortalAPI {
|
||||
return &PortalAPI{
|
||||
DiscV5API: &DiscV5API{portalProtocol.DiscV5},
|
||||
portalProtocol: portalProtocol,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PortalAPI) NodeInfo() *NodeInfo {
|
||||
n := p.portalProtocol.localNode.Node()
|
||||
|
||||
return &NodeInfo{
|
||||
NodeId: n.ID().String(),
|
||||
Enr: n.String(),
|
||||
Ip: n.IP().String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PortalAPI) RoutingTableInfo() *RoutingTableInfo {
|
||||
n := p.portalProtocol.localNode.Node()
|
||||
|
||||
closestNodes := p.portalProtocol.table.Nodes()
|
||||
buckets := make([]string, len(closestNodes))
|
||||
for _, e := range closestNodes {
|
||||
buckets = append(buckets, e.ID().String())
|
||||
}
|
||||
|
||||
return &RoutingTableInfo{
|
||||
Buckets: buckets,
|
||||
LocalNodeId: n.ID().String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PortalAPI) AddEnr(enr string) (bool, error) {
|
||||
n, err := enode.Parse(enode.ValidSchemes, enr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
p.portalProtocol.table.addSeenNode(wrapNode(n))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (p *PortalAPI) AddEnrs(enrs []string) bool {
|
||||
// Note: unspecified RPC, but useful for our local testnet test
|
||||
for _, enr := range enrs {
|
||||
n, err := enode.Parse(enode.ValidSchemes, enr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
p.portalProtocol.table.addSeenNode(wrapNode(n))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *PortalAPI) GetEnr(nodeId string) (string, error) {
|
||||
id, err := enode.ParseID(nodeId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if id == p.portalProtocol.localNode.Node().ID() {
|
||||
return p.portalProtocol.localNode.Node().String(), nil
|
||||
}
|
||||
|
||||
n := p.portalProtocol.table.getNode(id)
|
||||
if n == nil {
|
||||
return "", errors.New("record not in local routing table")
|
||||
}
|
||||
|
||||
return n.String(), nil
|
||||
}
|
||||
|
||||
func (p *PortalAPI) DeleteEnr(nodeId string) bool {
|
||||
id, err := enode.ParseID(nodeId)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
n := p.portalProtocol.table.getNode(id)
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
p.portalProtocol.table.delete(wrapNode(n))
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *PortalAPI) LookupEnr(nodeId string) (string, error) {
|
||||
id, err := enode.ParseID(nodeId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
enr := p.portalProtocol.ResolveNodeId(id)
|
||||
|
||||
if enr == nil {
|
||||
return "", errors.New("record not found in DHT lookup")
|
||||
}
|
||||
|
||||
return enr.String(), nil
|
||||
}
|
||||
|
|
@ -273,7 +273,7 @@ func (p *PortalProtocol) setupDiscV5AndTable() error {
|
|||
}
|
||||
|
||||
func (p *PortalProtocol) ping(node *enode.Node) (uint64, error) {
|
||||
enrSeq := p.DiscV5.LocalNode().Seq()
|
||||
enrSeq := p.Self().Seq()
|
||||
radiusBytes, err := p.nodeRadius.MarshalSSZ()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
|
@ -753,7 +753,7 @@ func (p *PortalProtocol) handlePing(id enode.ID, ping *portalwire.Ping) ([]byte,
|
|||
|
||||
p.radiusCache.Set([]byte(id.String()), pingCustomPayload.Radius)
|
||||
|
||||
enrSeq := p.DiscV5.LocalNode().Seq()
|
||||
enrSeq := p.Self().Seq()
|
||||
radiusBytes, err := p.nodeRadius.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -1111,7 +1111,7 @@ func (p *PortalProtocol) handleOfferedContents(id enode.ID, keys [][]byte, paylo
|
|||
}
|
||||
|
||||
func (p *PortalProtocol) Self() *enode.Node {
|
||||
return p.DiscV5.LocalNode().Node()
|
||||
return p.localNode.Node()
|
||||
}
|
||||
|
||||
func (p *PortalProtocol) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||
|
|
@ -1239,6 +1239,62 @@ func (p *PortalProtocol) findNodesCloseToContent(contentId []byte) []*enode.Node
|
|||
return allNodes
|
||||
}
|
||||
|
||||
// Lookup performs a recursive lookup for the given target.
|
||||
// It returns the closest nodes to target.
|
||||
func (p *PortalProtocol) Lookup(target enode.ID) []*enode.Node {
|
||||
return p.newLookup(p.closeCtx, target).run()
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (p *PortalProtocol) Resolve(n *enode.Node) *enode.Node {
|
||||
if intable := p.table.getNode(n.ID()); intable != nil && intable.Seq() > n.Seq() {
|
||||
n = intable
|
||||
}
|
||||
// Try asking directly. This works if the Node is still responding on the endpoint we have.
|
||||
if resp, err := p.RequestENR(n); err == nil {
|
||||
return resp
|
||||
}
|
||||
// Otherwise do a network lookup.
|
||||
result := p.Lookup(n.ID())
|
||||
for _, rn := range result {
|
||||
if rn.ID() == n.ID() && rn.Seq() > n.Seq() {
|
||||
return rn
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// ResolveNodeId searches for a specific Node with the given ID.
|
||||
// It returns nil if the nodeId could not be resolved.
|
||||
func (p *PortalProtocol) ResolveNodeId(id enode.ID) *enode.Node {
|
||||
if id == p.Self().ID() {
|
||||
return p.Self()
|
||||
}
|
||||
|
||||
n := p.table.getNode(id)
|
||||
if n != nil {
|
||||
// Try asking directly. This works if the Node is still responding on the endpoint we have.
|
||||
if resp, err := p.RequestENR(n); err == nil {
|
||||
return resp
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise do a network lookup.
|
||||
result := p.Lookup(n.ID())
|
||||
for _, rn := range result {
|
||||
if rn.ID() == id {
|
||||
if n != nil && rn.Seq() <= n.Seq() {
|
||||
return n
|
||||
} else {
|
||||
return rn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func inRange(nodeId enode.ID, nodeRadius *uint256.Int, contentId []byte) bool {
|
||||
distance := enode.LogDist(nodeId, enode.ID(contentId))
|
||||
disBig := new(big.Int).SetInt64(int64(distance))
|
||||
|
|
|
|||
Loading…
Reference in a new issue