diff --git a/p2p/discover/portal_protocol.go b/p2p/discover/portal_protocol.go index cceb256d1152..d2b26d09c6a9 100644 --- a/p2p/discover/portal_protocol.go +++ b/p2p/discover/portal_protocol.go @@ -167,9 +167,7 @@ func DefaultPortalProtocolConfig() *PortalProtocolConfig { } type PortalProtocol struct { - table *Table - cachedIdsLock sync.Mutex - cachedIds map[string]enode.ID + table *Table protocolId string protocolName string @@ -213,7 +211,6 @@ func NewPortalProtocol(config *PortalProtocolConfig, protocolId portalwire.Proto closeCtx, cancelCloseCtx := context.WithCancel(context.Background()) protocol := &PortalProtocol{ - cachedIds: make(map[string]enode.ID), protocolId: string(protocolId), protocolName: protocolId.Name(), ListenAddr: config.ListenAddr, @@ -328,12 +325,10 @@ func (p *PortalProtocol) setupUDPListening() error { func(buf []byte, addr *net.UDPAddr) (int, error) { p.Log.Info("will send to target data", "ip", addr.IP.To4().String(), "port", addr.Port, "bufLength", len(buf)) - p.cachedIdsLock.Lock() - defer p.cachedIdsLock.Unlock() - if id, ok := p.cachedIds[addr.String()]; ok { + if n, ok := p.DiscV5.cachedAddrNode[addr.String()]; ok { //_, err := p.DiscV5.TalkRequestToID(id, addr, string(portalwire.UTPNetwork), buf) req := &v5wire.TalkRequest{Protocol: string(portalwire.Utp), Message: buf} - p.DiscV5.sendFromAnotherThread(id, netip.AddrPortFrom(netutil.IPToAddr(addr.IP), uint16(addr.Port)), req) + p.DiscV5.sendFromAnotherThreadWithNode(n, netip.AddrPortFrom(netutil.IPToAddr(addr.IP), uint16(addr.Port)), req) return len(buf), err } else { @@ -388,23 +383,6 @@ func (p *PortalProtocol) setupDiscV5AndTable() error { return nil } -func (p *PortalProtocol) putCacheNodeId(node *enode.Node) { - p.cachedIdsLock.Lock() - defer p.cachedIdsLock.Unlock() - addr := &net.UDPAddr{IP: node.IP(), Port: node.UDP()} - if _, ok := p.cachedIds[addr.String()]; !ok { - p.cachedIds[addr.String()] = node.ID() - } -} - -func (p *PortalProtocol) putCacheId(id enode.ID, addr *net.UDPAddr) { - p.cachedIdsLock.Lock() - defer p.cachedIdsLock.Unlock() - if _, ok := p.cachedIds[addr.String()]; !ok { - p.cachedIds[addr.String()] = id - } -} - func (p *PortalProtocol) ping(node *enode.Node) (uint64, error) { pong, err := p.pingInner(node) if err != nil { @@ -566,7 +544,6 @@ func (p *PortalProtocol) processOffer(target *enode.Node, resp []byte, request * } p.Log.Info("will process Offer", "id", target.ID(), "ip", target.IP().To4().String(), "port", target.UDP()) - p.putCacheNodeId(target) accept := &portalwire.Accept{} err = accept.UnmarshalSSZ(resp[1:]) @@ -704,7 +681,6 @@ func (p *PortalProtocol) processContent(target *enode.Node, resp []byte) (byte, } p.Log.Info("will process content", "id", target.ID(), "ip", target.IP().To4().String(), "port", target.UDP()) - p.putCacheNodeId(target) switch resp[1] { case portalwire.ContentRawSelector: @@ -913,8 +889,6 @@ func (p *PortalProtocol) handleUtpTalkRequest(id enode.ID, addr *net.UDPAddr, ms if n := p.DiscV5.getNode(id); n != nil { p.table.addInboundNode(n) } - - p.putCacheId(id, addr) p.Log.Trace("receive utp data", "addr", addr, "msg-length", len(msg)) p.packetRouter.ReceiveMessage(msg, addr) return []byte("") @@ -924,7 +898,6 @@ func (p *PortalProtocol) handleTalkRequest(id enode.ID, addr *net.UDPAddr, msg [ if n := p.DiscV5.getNode(id); n != nil { p.table.addInboundNode(n) } - p.putCacheId(id, addr) msgCode := msg[0] @@ -1107,8 +1080,6 @@ func (p *PortalProtocol) handleFindContent(id enode.ID, addr *net.UDPAddr, reque return nil, err } - p.putCacheId(id, addr) - if errors.Is(err, ContentNotFound) { closestNodes := p.findNodesCloseToContent(contentId, portalFindnodesResultLimit) for i, n := range closestNodes { @@ -1303,8 +1274,6 @@ func (p *PortalProtocol) handleOffer(id enode.ID, addr *net.UDPAddr, request *po } } - p.putCacheId(id, addr) - idBuffer := make([]byte, 2) if contentKeyBitlist.Count() != 0 { connId := p.connIdGen.GenCid(id, false) diff --git a/p2p/discover/portal_protocol_test.go b/p2p/discover/portal_protocol_test.go index 8b4732fd510f..7f42ee71f4c6 100644 --- a/p2p/discover/portal_protocol_test.go +++ b/p2p/discover/portal_protocol_test.go @@ -114,15 +114,6 @@ func TestPortalWireProtocolUdp(t *testing.T) { assert.NoError(t, err) time.Sleep(12 * time.Second) - node1.putCacheNodeId(node2.localNode.Node()) - node1.putCacheNodeId(node3.localNode.Node()) - - node2.putCacheNodeId(node1.localNode.Node()) - node2.putCacheNodeId(node3.localNode.Node()) - - node3.putCacheNodeId(node1.localNode.Node()) - node3.putCacheNodeId(node2.localNode.Node()) - udpAddrStr1 := fmt.Sprintf("%s:%d", node1.localNode.Node().IP(), node1.localNode.Node().UDP()) udpAddrStr2 := fmt.Sprintf("%s:%d", node2.localNode.Node().IP(), node2.localNode.Node().UDP()) diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go index d4d9a054d9f1..92a97929ea4a 100644 --- a/p2p/discover/v5_udp.go +++ b/p2p/discover/v5_udp.go @@ -62,15 +62,17 @@ type codecV5 interface { // UDPv5 is the implementation of protocol version 5. type UDPv5 struct { // static fields - conn UDPConn - tab *Table - netrestrict *netutil.Netlist - priv *ecdsa.PrivateKey - localNode *enode.LocalNode - db *enode.DB - log log.Logger - clock mclock.Clock - validSchemes enr.IdentityScheme + conn UDPConn + tab *Table + cachedIds map[enode.ID]*enode.Node + cachedAddrNode map[string]*enode.Node + netrestrict *netutil.Netlist + priv *ecdsa.PrivateKey + localNode *enode.LocalNode + db *enode.DB + log log.Logger + clock mclock.Clock + validSchemes enr.IdentityScheme // misc buffers used during message handling logcontext []interface{} @@ -102,6 +104,7 @@ type UDPv5 struct { type sendRequest struct { destID enode.ID + destNode *enode.Node destAddr netip.AddrPort msg v5wire.Packet } @@ -150,14 +153,16 @@ func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) { cfg = cfg.withDefaults() t := &UDPv5{ // static fields - conn: newMeteredConn(conn), - localNode: ln, - db: ln.Database(), - netrestrict: cfg.NetRestrict, - priv: cfg.PrivateKey, - log: cfg.Log, - validSchemes: cfg.ValidSchemes, - clock: cfg.Clock, + conn: newMeteredConn(conn), + cachedAddrNode: make(map[string]*enode.Node), + cachedIds: make(map[enode.ID]*enode.Node), + localNode: ln, + db: ln.Database(), + netrestrict: cfg.NetRestrict, + priv: cfg.PrivateKey, + log: cfg.Log, + validSchemes: cfg.ValidSchemes, + clock: cfg.Clock, // channels into dispatch packetInCh: make(chan ReadPacket, 1), readNextCh: make(chan struct{}, 1), @@ -596,7 +601,24 @@ func (t *UDPv5) dispatch() { t.sendNextCall(c.id) case r := <-t.sendCh: - t.send(r.destID, r.destAddr, r.msg, nil) + c := &callV5{id: r.destID, addr: r.destAddr} + c.node = r.destNode + c.packet = r.msg + c.reqid = make([]byte, 8) + c.ch = make(chan v5wire.Packet, 1) + c.err = make(chan error, 1) + // Assign request ID. + if tq, ok := r.msg.(*v5wire.TalkRequest); ok { + if len(tq.ReqID) == 0 { + crand.Read(c.reqid) + c.packet.SetRequestID(c.reqid) + } + } + nonce, _ := t.send(c.id, c.addr, c.packet, nil) + c.nonce = nonce + t.activeCallByAuth[nonce] = c + t.startResponseTimeout(c) + //t.send(r.destID, r.destAddr, r.msg, nil) case p := <-t.packetInCh: t.handlePacket(p.Data, p.Addr) @@ -681,7 +703,14 @@ func (t *UDPv5) sendResponse(toID enode.ID, toAddr netip.AddrPort, packet v5wire func (t *UDPv5) sendFromAnotherThread(toID enode.ID, toAddr netip.AddrPort, packet v5wire.Packet) { select { - case t.sendCh <- sendRequest{toID, toAddr, packet}: + case t.sendCh <- sendRequest{toID, nil, toAddr, packet}: + case <-t.closeCtx.Done(): + } +} + +func (t *UDPv5) sendFromAnotherThreadWithNode(node *enode.Node, toAddr netip.AddrPort, packet v5wire.Packet) { + select { + case t.sendCh <- sendRequest{node.ID(), node, toAddr, packet}: case <-t.closeCtx.Done(): } } @@ -693,11 +722,16 @@ func (t *UDPv5) send(toID enode.ID, toAddr netip.AddrPort, packet v5wire.Packet, t.logcontext = packet.AppendLogInfo(t.logcontext) enc, nonce, err := t.codec.Encode(toID, addr, packet, c) + t.logcontext = append(t.logcontext, "nonce", fmt.Sprintf("%x", nonce[:])) if err != nil { t.logcontext = append(t.logcontext, "err", err) t.log.Warn(">> "+packet.Name(), t.logcontext...) return nonce, err } + if c != nil && c.Node != nil { + t.cachedIds[toID] = c.Node + t.cachedAddrNode[toAddr.String()] = c.Node + } _, err = t.conn.WriteToUDPAddrPort(enc, toAddr) t.log.Trace(">> "+packet.Name(), t.logcontext...) @@ -759,6 +793,8 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr netip.AddrPort) error { if fromNode != nil { // Handshake succeeded, add to table. t.tab.addInboundNode(fromNode) + t.cachedIds[fromID] = fromNode + t.cachedAddrNode[fromAddr.String()] = fromNode } if packet.Kind() != v5wire.WhoareyouPacket { // WHOAREYOU logged separately to report errors. @@ -846,7 +882,7 @@ var ( func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr netip.AddrPort) { c, err := t.matchWithCall(fromID, p.Nonce) if err != nil { - t.log.Debug("Invalid "+p.Name(), "addr", fromAddr, "err", err) + t.log.Debug("Invalid "+p.Name(), "addr", fromAddr, "nonce", fmt.Sprintf("%x", p.Nonce[:]), "err", err) return } @@ -857,7 +893,7 @@ func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr n return } // Resend the call that was answered by WHOAREYOU. - t.log.Trace("<< "+p.Name(), "id", c.node.ID(), "addr", fromAddr) + t.log.Trace("<< "+p.Name(), "id", c.node.ID(), "addr", fromAddr, "nonce", fmt.Sprintf("%x", p.Nonce[:])) c.handshakeCount++ c.challenge = p p.Node = c.node diff --git a/portalnetwork/history/storage.go b/portalnetwork/history/storage.go index 7878093f6b52..488d2ff3622c 100644 --- a/portalnetwork/history/storage.go +++ b/portalnetwork/history/storage.go @@ -452,7 +452,7 @@ func (p *ContentStorage) deleteContentOutOfRadius(radius *uint256.Int) error { return err } count, _ := res.RowsAffected() - p.log.Trace("delete %d items", count) + p.log.Trace("delete items", "count", count) return err }