Skip to content

p2p/discover: pass node instead of node ID to TALKREQ handler #31075

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 2, 2025

Conversation

thinkAfCod
Copy link
Contributor

@thinkAfCod thinkAfCod commented Jan 25, 2025

This is for the implementation of Portal Network in the Shisui client. Their handler needs access to the node object in order to send further calls to the requesting node. This is a breaking API change but it should be fine, since there are basically no known users of TALKREQ outside of Portal network.

@thinkAfCod thinkAfCod force-pushed the workspace branch 2 times, most recently from 52c7b8c to cd9f1b7 Compare January 25, 2025 07:55
@thinkAfCod
Copy link
Contributor Author

fix #31094

func (t *UDPv5) getNode(id enode.ID) *enode.Node {
if n := t.tab.getNode(id); n != nil {
return n
func (t *UDPv5) GetNode(id enode.ID) (n *enode.Node) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider thread-safe if the method is public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each method called within GetNode already has locks, so there is no need to add additional locks to ensure thread safety.

@fjl fjl added the shisui Portal Network label Feb 18, 2025
@fjl
Copy link
Contributor

fjl commented Mar 11, 2025

We discussed this in a meeting with Shisui developers, and the need for calling GetNode arises because we do not provide the *enode.Node to the TALKREQ handler. They get the enode.ID from us, but really need the complete node.

So we should change talk handling to pass the node to the handler function. Doing this will require changing the discv5 session cache to include the node alongside the keys.

@thinkAfCod thinkAfCod changed the title cache the mapping of addr to node in v5_udp p2p/discover: TalkRequestHandler interface parameter should provide enode.Node Mar 12, 2025
@thinkAfCod thinkAfCod force-pushed the workspace branch 3 times, most recently from 7c9bb00 to 4770320 Compare March 18, 2025 09:40
@fjl
Copy link
Contributor

fjl commented Mar 18, 2025

I think the approach you chose is too complicated, and the message flag should not be exposed. I might be wrong since I didn't try to implement myself, but here is my suggestion:

In p2p/discover/v5wire/encoding.go, a new session will be stored into the cache in two places:

  1. c.sc.storeNewSession(toID, addr, session)
  2. c.sc.storeNewSession(auth.h.SrcID, fromAddr, session)

In both of these places, the node is available:

  1. in challenge.Node
  2. in node

So we could just add the node as a parameter in storeNewSession and put it into the cache then.

@GrapeBaBa
Copy link
Contributor

I think the approach you chose is too complicated, and the message flag should not be exposed. I might be wrong since I didn't try to implement myself, but here is my suggestion:

In p2p/discover/v5wire/encoding.go, a new session will be stored into the cache in two places:

  1. c.sc.storeNewSession(toID, addr, session)
  2. c.sc.storeNewSession(auth.h.SrcID, fromAddr, session)

In both of these places, the node is available:

  1. in challenge.Node
  2. in node

So we could just add the node as a parameter in storeNewSession and put it into the cache then.

Seems make sense, however how to get node from session cache, session cache is only available in Codec.

@fjl
Copy link
Contributor

fjl commented Mar 18, 2025

Yeah, an accessor method has to be added to the Codec for this.

@thinkAfCod
Copy link
Contributor Author

Oh, I missed a place to call storeNewSession.

And you mentioned the necessity of exposing the Flag. I've also been struggling with this.

The codec field in UDPv5 is an interface type, it only provides the Encode and Decode methods.

In UDPv5, its cannot directly use codec.sc to query session.

So I tried to make the codec's Decode method return the node most of the time, rather than only returning the node after a successful handshake.

handlePacket origin code:

func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr netip.AddrPort) error {
	addr := fromAddr.String()
	fromID, fromNode, packet, err := t.codec.Decode(rawpacket, addr)
	if err != nil {
		// handle invalid packet and return...
	}
	if fromNode != nil {
		// Handshake succeeded, add to table.
		t.tab.addInboundNode(fromNode)
	}
	// ignoring...
	return nil
}

Here got a problem, which is that now fromNode is almost always not nil, causing addInboundNode to be called every time.

I need a new Flag to indicate whether it is the successful handshake.

And I have other two alternative options:

  1. Add a bool flag():
fromID, fromNode, packet, handshakeSuccess, err := t.codec.Decode(rawpacket, addr)
// blabla...
if fromNode != nil && handshakeSuccess {
	// Handshake succeeded, add to table.
	t.tab.addInboundNode(fromNode)
}
  1. use a closure:
fromID, fromNode, packet, isHandShake, err := t.codec.Decode(rawpacket, addr, func(node *enode.Node) {
        // Handshake succeeded, add to table.
	t.tab.addInboundNode(fromNode)
})

Or if there are other ways.

@thinkAfCod
Copy link
Contributor Author

Yeah, an accessor method has to be added to the Codec for this.

I considered it as well, but I feel that adding a new method to the Codec to get the Session seems a bit out of place for its functionality.

@thinkAfCod thinkAfCod force-pushed the workspace branch 2 times, most recently from 750bc55 to d1c3505 Compare March 22, 2025 03:28
Signed-off-by: thinkAfCod <q315xia@163.com>
@fjl fjl changed the title p2p/discover: TalkRequestHandler interface parameter should provide enode.Node p2p/discover: pass node instead of node ID to TALKREQ handler Apr 2, 2025
@fjl fjl merged commit d2176f4 into ethereum:master Apr 2, 2025
3 of 4 checks passed
@fjl fjl added this to the 1.15.8 milestone Apr 2, 2025
sivaratrisrinivas pushed a commit to sivaratrisrinivas/go-ethereum that referenced this pull request Apr 21, 2025
…um#31075)

This is for the implementation of Portal Network in the Shisui client.
Their handler needs access to the node object in order to send further
calls to the requesting node. This is a breaking API change but it
should be fine, since there are basically no known users of TALKREQ
outside of Portal network.

---------

Signed-off-by: thinkAfCod <q315xia@163.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
Rampex1 pushed a commit to streamingfast/go-ethereum that referenced this pull request May 15, 2025
…um#31075)

This is for the implementation of Portal Network in the Shisui client.
Their handler needs access to the node object in order to send further
calls to the requesting node. This is a breaking API change but it
should be fine, since there are basically no known users of TALKREQ
outside of Portal network.

---------

Signed-off-by: thinkAfCod <q315xia@163.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
shisui Portal Network
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants