-
Notifications
You must be signed in to change notification settings - Fork 378
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
feat: clean up p2p
& implement missing peering functionality
#2852
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is 📢 Thoughts on this report? Let us know! |
seed
peers) supportp2p
& implement bootnode (seed
peers) support
@@ -36,10 +26,10 @@ type P2PConfig struct { | |||
UPNP bool `json:"upnp" toml:"upnp" comment:"UPNP port forwarding"` | |||
|
|||
// Maximum number of inbound peers | |||
MaxNumInboundPeers int `json:"max_num_inbound_peers" toml:"max_num_inbound_peers" comment:"Maximum number of inbound peers"` | |||
MaxNumInboundPeers uint64 `json:"max_num_inbound_peers" toml:"max_num_inbound_peers" comment:"Maximum number of inbound peers"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unsigned may be better than signed if we don't need to use patterns like -1
. However, since we're constrained by the OS limits, a size of 64 may be excessive.
There is a leftover issue with this PR that I'm currently investigating, which is a hanging test somewhere in TM2. I will resolve this before opening the PR for reviews 🙏 |
Opening this up for an initial review 🙏 I have no idea why the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you check somewhere to not have a number of peers greater than max_num_outboud_peers
?
I see some calls to NumOutbound(), but i don't think i saw this limitation.
I've made a test with a local node, and i'm failing to peer with test5.
A devnet cluster with this PR would be amazing to make some tests
// peers. If another node asks it for addresses, it responds and disconnects. | ||
// | ||
// Does not work if the peer-exchange reactor is disabled. | ||
SeedMode bool `json:"seed_mode" toml:"seed_mode" comment:"Seed mode, in which node constantly crawls the network and looks for\n peers. If another node asks it for addresses, it responds and disconnects.\n\n Does not work if the peer-exchange reactor is disabled."` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So there is no seed_mode
anymore right ? So all pex node are seeding and constently crowling the network ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to review this PR as thoroughly as I could, but it is too much. I vote to merge as it is and change/fix things as needed.
// the consensus machine | ||
SwitchToConsensus(sm.State, int) | ||
} | ||
type SwitchToConsensusFn func(sm.State, int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add some comments here to understand why this is needed?
@@ -1777,7 +1777,7 @@ func TestStateOutputVoteStats(t *testing.T) { | |||
|
|||
cs, vss := randConsensusState(2) | |||
// create dummy peer | |||
peer := p2pmock.NewPeer(nil) | |||
peer := &p2pmock.Peer{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why one is a pointer and the other is not?
@@ -162,7 +163,7 @@ func (memR *Reactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) { | |||
|
|||
switch msg := msg.(type) { | |||
case *TxMessage: | |||
peerID := memR.ids.GetForPeer(src) | |||
peerID := memR.ids.GetForPeer(src.ID()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit strange IMO. src is already a Peer with an ID, why do we have to call ids.GetForPeer to get the peerID?
reactors := []nodeReactor{ | ||
{ | ||
"MEMPOOL", mempoolReactor, | ||
}, | ||
{ | ||
"BLOCKCHAIN", bcReactor, | ||
}, | ||
{ | ||
"CONSENSUS", consensusReactor, | ||
}, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we use constants for these strings?
if config.P2P.PeerExchange { | ||
discoveryReactor = discovery.NewReactor() | ||
|
||
discoveryReactor.SetLogger(logger.With("module", "discovery")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we use constant for these strings?
} | ||
|
||
// PeerSet has a (immutable) subset of the methods of PeerSet. | ||
type PeerSet interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No error handling, so really difficult to implement that interface using other persistence than memory...
|
||
// Grab a random peer, and engage | ||
// them for peer discovery | ||
peers := r.Switch.Peers().List() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How many elements peers are we expecting to have here? are they always on memory? I thing that this interface should return an iterator instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code of discovery.go and Switch is a bit flaky in general, there is almost no error handling. For something like network connections, it is super important to have a robust system.
Send(byte, []byte) bool | ||
TrySend(byte, []byte) bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No error handling, so the amount of info you can send to the callee is just yes/no. Also, what is the difference between Send and TrySend?
Accept(context.Context, PeerBehavior) (Peer, error) | ||
|
||
// Dial dials a peer, and returns it | ||
Dial(context.Context, types.NetAddress, PeerBehavior) (Peer, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why Dial is returning a Peer instead of something like a PeerConnection?
Merge RequirementsThe following requirements must be fulfilled before a pull request can be merged. These requirements are defined in this configuration file. Automated Checks🔴 Maintainers must be able to edit this pull request Details
Manual Checks
Details
|
Description
Closes #2308
There is a lot happening in this PR, so don't be discouraged by the files changed.
I'll outline the way the PR should be reviewed, and give you pointers along the way.
What this PR set out to do
This PR initially set out to implement peer discovery in the TM2
p2p
module -- that's it, basically.The change was meant to be minimal, and not involve larger changes.
After spending more time than I'd like to admit in the
p2p
codebase, I've come to a couple of realizations:p2p
package are sketchy to say the least, and not convincing at all that we were covering actual functionality we needed to cover.All of these are temporarily fine, and not blocking us.
But the pattern was there -- to add peer discovery, it would require continuing the same pattern of code gymnastics present in the
p2p
module for the last 5+ years.I took this opportunity, ahead of the mainnet launch, to fill out a few checkboxes:
PHILOSOPHY.md
.test4
andtest5
.I wanted to implement all of this, without breaking any existing TM2 functionality that relies on the
p2p
module, or introducing additional complexities.What this PR actually accomplished
I'm proud to say that this PR brings more than a few bells and whistles to the table, in terms of TM2 improvements:
Switch
andTransport
implementations. No more gazillion redundant checks, or expensive lookups, or convoluted APIs.For the sake of not making groundbreaking changes ahead of mainnet, I didn't touch a few things, and this will be evident from the code:
conn
package, or how the multiplex connections are established and maintained (or the STS implementation) -- this would be too much, and require an exponential amount of time to get right.Peer
abstraction is still the same, and TM2 modules interact with the peers in the same way as before (directly, asReactor
s). I've outlined the issues with this in the README, so check it out.In retrospect, I should've limited the scope of this PR by a lot. At the time I was at the mid-way point, I committed fully to leaving this module in a better state than I found it in, rather than leave additional tech debt for future cleanup.
The other primary goal of this PR is to scope out changes needed to upgrade the networking layer implementation into utilizing a stack like libp2p. I am happy to say that we have 0 limitations in terms of p2p functionality to make the switch. We're just bound by time. This upgrade is scheduled for after the mainnet MVP launch 🤞
How do I review this PR?
There is no point in looking at the older implementation, and trying to figure out the changes from there.
There are just too many, and it can get overwhelming quickly.
Instead, as the first step -- read the new
p2p
README. It outlines how thep2p
module works on a core level, and highlights current challenges.After the README, open the
p2p
package intm2/pkg/p2p
, and start looking at the implementation from there. Leave comments on things that are unclear, or can be improved. I'll try to answer and give as much context as I can.What
p2p
config params are changed?Here is a complete list of changed
p2p
configuration params, and the reasoning behind them:UPNP
- UPNP port forwarding, it was completely unused, removed.PexReactor
- peer exchange reactor enable-ment flag, renamed toPeerExchange
, renameSeedMode
- enabled network crawls, was tied toPexReactor
beingtrue
. Useless flag, sincePeerExchange
exists, removedAllowDuplicateIP
- useless flag to prevent same-IP dials, even outside previous dial "filters", **removed **HandshakeTimeout
- excessive config option for setting an STS timeout, sane default is3s
, removedDialTimeout
- excessive config option for finishing a peer dial, sane default is3s
, removedThe following config options were removed, as they related to testing, and were replaced by unit / integration tests.
TestDialFail
TestFuzz
TestFuzzConfig
Contributors' checklist...
BREAKING CHANGE: xxx
message was included in the description