You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

731 lines
20 KiB

9 years ago
9 years ago
9 years ago
9 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
7 years ago
9 years ago
9 years ago
9 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
9 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
9 years ago
8 years ago
7 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: introduce peerConn to simplify peer creation (#1226) * expose AuthEnc in the P2P config if AuthEnc is true, dialed peers must have a node ID in the address and it must match the persistent pubkey from the secret handshake. Refs #1157 * fixes after my own review * fix docs * fix build failure ``` p2p/pex/pex_reactor_test.go:288:88: cannot use seed.NodeInfo().NetAddress() (type *p2p.NetAddress) as type string in array or slice literal ``` * p2p: introduce peerConn to simplify peer creation * Introduce `peerConn` containing the known fields of `peer` * `peer` only created in `sw.addPeer` once handshake is complete and NodeInfo is checked * Eliminates some mutable variables and makes the code flow better * Simplifies the `newXxxPeer` funcs * Use ID instead of PubKey where possible. * SetPubKeyFilter -> SetIDFilter * nodeInfo.Validate takes ID * remove peer.PubKey() * persistent node ids * fixes from review * test: use ip_plus_id.sh more * fix invalid memory panic during fast_sync test ``` 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: panic: runtime error: invalid memory address or nil pointer dereference 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: [signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x98dd3e] 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: goroutine 3432 [running]: 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.newOutboundPeerConn(0xc423fd1380, 0xc420933e00, 0x1, 0x1239a60, 0 xc420128c40, 0x2, 0x42caf6, 0xc42001f300, 0xc422831d98, 0xc4227951c0, ...) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/peer.go:123 +0x31e 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).addOutboundPeerWithConfig(0xc4200ad040, 0xc423fd1380, 0 xc420933e00, 0xc423f48801, 0x28, 0x2) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:455 +0x12b 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).DialPeerWithAddress(0xc4200ad040, 0xc423fd1380, 0x1, 0x 0, 0x0) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:371 +0xdc 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).reconnectToPeer(0xc4200ad040, 0x123e000, 0xc42007bb00) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:290 +0x25f 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: created by github.com/tendermint/tendermint/p2p.(*Switch).StopPeerForError 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:256 +0x1b7 ```
7 years ago
p2p: introduce peerConn to simplify peer creation (#1226) * expose AuthEnc in the P2P config if AuthEnc is true, dialed peers must have a node ID in the address and it must match the persistent pubkey from the secret handshake. Refs #1157 * fixes after my own review * fix docs * fix build failure ``` p2p/pex/pex_reactor_test.go:288:88: cannot use seed.NodeInfo().NetAddress() (type *p2p.NetAddress) as type string in array or slice literal ``` * p2p: introduce peerConn to simplify peer creation * Introduce `peerConn` containing the known fields of `peer` * `peer` only created in `sw.addPeer` once handshake is complete and NodeInfo is checked * Eliminates some mutable variables and makes the code flow better * Simplifies the `newXxxPeer` funcs * Use ID instead of PubKey where possible. * SetPubKeyFilter -> SetIDFilter * nodeInfo.Validate takes ID * remove peer.PubKey() * persistent node ids * fixes from review * test: use ip_plus_id.sh more * fix invalid memory panic during fast_sync test ``` 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: panic: runtime error: invalid memory address or nil pointer dereference 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: [signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x98dd3e] 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: goroutine 3432 [running]: 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.newOutboundPeerConn(0xc423fd1380, 0xc420933e00, 0x1, 0x1239a60, 0 xc420128c40, 0x2, 0x42caf6, 0xc42001f300, 0xc422831d98, 0xc4227951c0, ...) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/peer.go:123 +0x31e 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).addOutboundPeerWithConfig(0xc4200ad040, 0xc423fd1380, 0 xc420933e00, 0xc423f48801, 0x28, 0x2) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:455 +0x12b 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).DialPeerWithAddress(0xc4200ad040, 0xc423fd1380, 0x1, 0x 0, 0x0) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:371 +0xdc 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: github.com/tendermint/tendermint/p2p.(*Switch).reconnectToPeer(0xc4200ad040, 0x123e000, 0xc42007bb00) 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:290 +0x25f 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: created by github.com/tendermint/tendermint/p2p.(*Switch).StopPeerForError 2018-02-21T06:30:05Z box887.localdomain docker/local_testnet_4[14907]: #011/go/src/github.com/tendermint/tendermint/p2p/switch.go:256 +0x1b7 ```
7 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
9 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package pex
  2. import (
  3. "fmt"
  4. "reflect"
  5. "sync"
  6. "time"
  7. "github.com/pkg/errors"
  8. amino "github.com/tendermint/go-amino"
  9. cmn "github.com/tendermint/tendermint/libs/common"
  10. "github.com/tendermint/tendermint/p2p"
  11. "github.com/tendermint/tendermint/p2p/conn"
  12. )
  13. type Peer = p2p.Peer
  14. const (
  15. // PexChannel is a channel for PEX messages
  16. PexChannel = byte(0x00)
  17. // over-estimate of max NetAddress size
  18. // hexID (40) + IP (16) + Port (2) + Name (100) ...
  19. // NOTE: dont use massive DNS name ..
  20. maxAddressSize = 256
  21. // NOTE: amplificaiton factor!
  22. // small request results in up to maxMsgSize response
  23. maxMsgSize = maxAddressSize * maxGetSelection
  24. // ensure we have enough peers
  25. defaultEnsurePeersPeriod = 30 * time.Second
  26. // Seed/Crawler constants
  27. // minTimeBetweenCrawls is a minimum time between attempts to crawl a peer.
  28. minTimeBetweenCrawls = 2 * time.Minute
  29. // check some peers every this
  30. crawlPeerPeriod = 30 * time.Second
  31. maxAttemptsToDial = 16 // ~ 35h in total (last attempt - 18h)
  32. // if node connects to seed, it does not have any trusted peers.
  33. // Especially in the beginning, node should have more trusted peers than
  34. // untrusted.
  35. biasToSelectNewPeers = 30 // 70 to select good peers
  36. )
  37. // PEXReactor handles PEX (peer exchange) and ensures that an
  38. // adequate number of peers are connected to the switch.
  39. //
  40. // It uses `AddrBook` (address book) to store `NetAddress`es of the peers.
  41. //
  42. // ## Preventing abuse
  43. //
  44. // Only accept pexAddrsMsg from peers we sent a corresponding pexRequestMsg too.
  45. // Only accept one pexRequestMsg every ~defaultEnsurePeersPeriod.
  46. type PEXReactor struct {
  47. p2p.BaseReactor
  48. book AddrBook
  49. config *PEXReactorConfig
  50. ensurePeersPeriod time.Duration // TODO: should go in the config
  51. // maps to prevent abuse
  52. requestsSent *cmn.CMap // ID->struct{}: unanswered send requests
  53. lastReceivedRequests *cmn.CMap // ID->time.Time: last time peer requested from us
  54. seedAddrs []*p2p.NetAddress
  55. attemptsToDial sync.Map // address (string) -> {number of attempts (int), last time dialed (time.Time)}
  56. // seed/crawled mode fields
  57. crawlPeerInfos map[p2p.ID]crawlPeerInfo
  58. }
  59. func (r *PEXReactor) minReceiveRequestInterval() time.Duration {
  60. // NOTE: must be less than ensurePeersPeriod, otherwise we'll request
  61. // peers too quickly from others and they'll think we're bad!
  62. return r.ensurePeersPeriod / 3
  63. }
  64. // PEXReactorConfig holds reactor specific configuration data.
  65. type PEXReactorConfig struct {
  66. // Seed/Crawler mode
  67. SeedMode bool
  68. // We want seeds to only advertise good peers. Therefore they should wait at
  69. // least as long as we expect it to take for a peer to become good before
  70. // disconnecting.
  71. SeedDisconnectWaitPeriod time.Duration
  72. // Seeds is a list of addresses reactor may use
  73. // if it can't connect to peers in the addrbook.
  74. Seeds []string
  75. }
  76. type _attemptsToDial struct {
  77. number int
  78. lastDialed time.Time
  79. }
  80. // NewPEXReactor creates new PEX reactor.
  81. func NewPEXReactor(b AddrBook, config *PEXReactorConfig) *PEXReactor {
  82. r := &PEXReactor{
  83. book: b,
  84. config: config,
  85. ensurePeersPeriod: defaultEnsurePeersPeriod,
  86. requestsSent: cmn.NewCMap(),
  87. lastReceivedRequests: cmn.NewCMap(),
  88. crawlPeerInfos: make(map[p2p.ID]crawlPeerInfo),
  89. }
  90. r.BaseReactor = *p2p.NewBaseReactor("PEXReactor", r)
  91. return r
  92. }
  93. // OnStart implements BaseService
  94. func (r *PEXReactor) OnStart() error {
  95. err := r.book.Start()
  96. if err != nil && err != cmn.ErrAlreadyStarted {
  97. return err
  98. }
  99. numOnline, seedAddrs, err := r.checkSeeds()
  100. if err != nil {
  101. return err
  102. } else if numOnline == 0 && r.book.Empty() {
  103. return errors.New("Address book is empty, and could not connect to any seed nodes")
  104. }
  105. r.seedAddrs = seedAddrs
  106. // Check if this node should run
  107. // in seed/crawler mode
  108. if r.config.SeedMode {
  109. go r.crawlPeersRoutine()
  110. } else {
  111. go r.ensurePeersRoutine()
  112. }
  113. return nil
  114. }
  115. // OnStop implements BaseService
  116. func (r *PEXReactor) OnStop() {
  117. r.book.Stop()
  118. }
  119. // GetChannels implements Reactor
  120. func (r *PEXReactor) GetChannels() []*conn.ChannelDescriptor {
  121. return []*conn.ChannelDescriptor{
  122. {
  123. ID: PexChannel,
  124. Priority: 1,
  125. SendQueueCapacity: 10,
  126. },
  127. }
  128. }
  129. // AddPeer implements Reactor by adding peer to the address book (if inbound)
  130. // or by requesting more addresses (if outbound).
  131. func (r *PEXReactor) AddPeer(p Peer) {
  132. if p.IsOutbound() {
  133. // For outbound peers, the address is already in the books -
  134. // either via DialPeersAsync or r.Receive.
  135. // Ask it for more peers if we need.
  136. if r.book.NeedMoreAddrs() {
  137. r.RequestAddrs(p)
  138. }
  139. } else {
  140. // inbound peer is its own source
  141. addr, err := p.NodeInfo().NetAddress()
  142. if err != nil {
  143. r.Logger.Error("Failed to get peer NetAddress", "err", err, "peer", p)
  144. return
  145. }
  146. // Make it explicit that addr and src are the same for an inbound peer.
  147. src := addr
  148. // add to book. dont RequestAddrs right away because
  149. // we don't trust inbound as much - let ensurePeersRoutine handle it.
  150. err = r.book.AddAddress(addr, src)
  151. r.logErrAddrBook(err)
  152. }
  153. }
  154. func (r *PEXReactor) logErrAddrBook(err error) {
  155. if err != nil {
  156. switch err.(type) {
  157. case ErrAddrBookNilAddr:
  158. r.Logger.Error("Failed to add new address", "err", err)
  159. default:
  160. // non-routable, self, full book, private, etc.
  161. r.Logger.Debug("Failed to add new address", "err", err)
  162. }
  163. }
  164. }
  165. // RemovePeer implements Reactor.
  166. func (r *PEXReactor) RemovePeer(p Peer, reason interface{}) {
  167. id := string(p.ID())
  168. r.requestsSent.Delete(id)
  169. r.lastReceivedRequests.Delete(id)
  170. }
  171. // Receive implements Reactor by handling incoming PEX messages.
  172. func (r *PEXReactor) Receive(chID byte, src Peer, msgBytes []byte) {
  173. msg, err := decodeMsg(msgBytes)
  174. if err != nil {
  175. r.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes)
  176. r.Switch.StopPeerForError(src, err)
  177. return
  178. }
  179. r.Logger.Debug("Received message", "src", src, "chId", chID, "msg", msg)
  180. switch msg := msg.(type) {
  181. case *pexRequestMessage:
  182. // NOTE: this is a prime candidate for amplification attacks,
  183. // so it's important we
  184. // 1) restrict how frequently peers can request
  185. // 2) limit the output size
  186. // If we're a seed and this is an inbound peer,
  187. // respond once and disconnect.
  188. if r.config.SeedMode && !src.IsOutbound() {
  189. id := string(src.ID())
  190. v := r.lastReceivedRequests.Get(id)
  191. if v != nil {
  192. // FlushStop/StopPeer are already
  193. // running in a go-routine.
  194. return
  195. }
  196. r.lastReceivedRequests.Set(id, time.Now())
  197. // Send addrs and disconnect
  198. r.SendAddrs(src, r.book.GetSelectionWithBias(biasToSelectNewPeers))
  199. go func() {
  200. // In a go-routine so it doesn't block .Receive.
  201. src.FlushStop()
  202. r.Switch.StopPeerGracefully(src)
  203. }()
  204. } else {
  205. // Check we're not receiving requests too frequently.
  206. if err := r.receiveRequest(src); err != nil {
  207. r.Switch.StopPeerForError(src, err)
  208. return
  209. }
  210. r.SendAddrs(src, r.book.GetSelection())
  211. }
  212. case *pexAddrsMessage:
  213. // If we asked for addresses, add them to the book
  214. if err := r.ReceiveAddrs(msg.Addrs, src); err != nil {
  215. r.Switch.StopPeerForError(src, err)
  216. return
  217. }
  218. default:
  219. r.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
  220. }
  221. }
  222. // enforces a minimum amount of time between requests
  223. func (r *PEXReactor) receiveRequest(src Peer) error {
  224. id := string(src.ID())
  225. v := r.lastReceivedRequests.Get(id)
  226. if v == nil {
  227. // initialize with empty time
  228. lastReceived := time.Time{}
  229. r.lastReceivedRequests.Set(id, lastReceived)
  230. return nil
  231. }
  232. lastReceived := v.(time.Time)
  233. if lastReceived.Equal(time.Time{}) {
  234. // first time gets a free pass. then we start tracking the time
  235. lastReceived = time.Now()
  236. r.lastReceivedRequests.Set(id, lastReceived)
  237. return nil
  238. }
  239. now := time.Now()
  240. minInterval := r.minReceiveRequestInterval()
  241. if now.Sub(lastReceived) < minInterval {
  242. return fmt.Errorf("Peer (%v) sent next PEX request too soon. lastReceived: %v, now: %v, minInterval: %v. Disconnecting",
  243. src.ID(),
  244. lastReceived,
  245. now,
  246. minInterval,
  247. )
  248. }
  249. r.lastReceivedRequests.Set(id, now)
  250. return nil
  251. }
  252. // RequestAddrs asks peer for more addresses if we do not already
  253. // have a request out for this peer.
  254. func (r *PEXReactor) RequestAddrs(p Peer) {
  255. r.Logger.Debug("Request addrs", "from", p)
  256. id := string(p.ID())
  257. if r.requestsSent.Has(id) {
  258. return
  259. }
  260. r.requestsSent.Set(id, struct{}{})
  261. p.Send(PexChannel, cdc.MustMarshalBinaryBare(&pexRequestMessage{}))
  262. }
  263. // ReceiveAddrs adds the given addrs to the addrbook if theres an open
  264. // request for this peer and deletes the open request.
  265. // If there's no open request for the src peer, it returns an error.
  266. func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error {
  267. id := string(src.ID())
  268. if !r.requestsSent.Has(id) {
  269. return errors.New("Unsolicited pexAddrsMessage")
  270. }
  271. r.requestsSent.Delete(id)
  272. srcAddr, err := src.NodeInfo().NetAddress()
  273. if err != nil {
  274. return err
  275. }
  276. for _, netAddr := range addrs {
  277. // Validate netAddr. Disconnect from a peer if it sends us invalid data.
  278. if netAddr == nil {
  279. return errors.New("nil address in pexAddrsMessage")
  280. }
  281. // TODO: extract validating logic from NewNetAddressStringWithOptionalID
  282. // and put it in netAddr#Valid (#2722)
  283. na, err := p2p.NewNetAddressString(netAddr.String())
  284. if err != nil {
  285. return fmt.Errorf("%s address in pexAddrsMessage is invalid: %v",
  286. netAddr.String(),
  287. err,
  288. )
  289. }
  290. // NOTE: we check netAddr validity and routability in book#AddAddress.
  291. err = r.book.AddAddress(na, srcAddr)
  292. if err != nil {
  293. r.logErrAddrBook(err)
  294. // XXX: should we be strict about incoming data and disconnect from a
  295. // peer here too?
  296. continue
  297. }
  298. // If this address came from a seed node, try to connect to it without
  299. // waiting.
  300. for _, seedAddr := range r.seedAddrs {
  301. if seedAddr.Equals(srcAddr) {
  302. r.ensurePeers()
  303. }
  304. }
  305. }
  306. return nil
  307. }
  308. // SendAddrs sends addrs to the peer.
  309. func (r *PEXReactor) SendAddrs(p Peer, netAddrs []*p2p.NetAddress) {
  310. p.Send(PexChannel, cdc.MustMarshalBinaryBare(&pexAddrsMessage{Addrs: netAddrs}))
  311. }
  312. // SetEnsurePeersPeriod sets period to ensure peers connected.
  313. func (r *PEXReactor) SetEnsurePeersPeriod(d time.Duration) {
  314. r.ensurePeersPeriod = d
  315. }
  316. // Ensures that sufficient peers are connected. (continuous)
  317. func (r *PEXReactor) ensurePeersRoutine() {
  318. var (
  319. seed = cmn.NewRand()
  320. jitter = seed.Int63n(r.ensurePeersPeriod.Nanoseconds())
  321. )
  322. // Randomize first round of communication to avoid thundering herd.
  323. // If no peers are present directly start connecting so we guarantee swift
  324. // setup with the help of configured seeds.
  325. if r.nodeHasSomePeersOrDialingAny() {
  326. time.Sleep(time.Duration(jitter))
  327. }
  328. // fire once immediately.
  329. // ensures we dial the seeds right away if the book is empty
  330. r.ensurePeers()
  331. // fire periodically
  332. ticker := time.NewTicker(r.ensurePeersPeriod)
  333. for {
  334. select {
  335. case <-ticker.C:
  336. r.ensurePeers()
  337. case <-r.Quit():
  338. ticker.Stop()
  339. return
  340. }
  341. }
  342. }
  343. // ensurePeers ensures that sufficient peers are connected. (once)
  344. //
  345. // heuristic that we haven't perfected yet, or, perhaps is manually edited by
  346. // the node operator. It should not be used to compute what addresses are
  347. // already connected or not.
  348. func (r *PEXReactor) ensurePeers() {
  349. var (
  350. out, in, dial = r.Switch.NumPeers()
  351. numToDial = r.Switch.MaxNumOutboundPeers() - (out + dial)
  352. )
  353. r.Logger.Info(
  354. "Ensure peers",
  355. "numOutPeers", out,
  356. "numInPeers", in,
  357. "numDialing", dial,
  358. "numToDial", numToDial,
  359. )
  360. if numToDial <= 0 {
  361. return
  362. }
  363. // bias to prefer more vetted peers when we have fewer connections.
  364. // not perfect, but somewhate ensures that we prioritize connecting to more-vetted
  365. // NOTE: range here is [10, 90]. Too high ?
  366. newBias := cmn.MinInt(out, 8)*10 + 10
  367. toDial := make(map[p2p.ID]*p2p.NetAddress)
  368. // Try maxAttempts times to pick numToDial addresses to dial
  369. maxAttempts := numToDial * 3
  370. for i := 0; i < maxAttempts && len(toDial) < numToDial; i++ {
  371. try := r.book.PickAddress(newBias)
  372. if try == nil {
  373. continue
  374. }
  375. if _, selected := toDial[try.ID]; selected {
  376. continue
  377. }
  378. if r.Switch.IsDialingOrExistingAddress(try) {
  379. continue
  380. }
  381. // TODO: consider moving some checks from toDial into here
  382. // so we don't even consider dialing peers that we want to wait
  383. // before dialling again, or have dialed too many times already
  384. r.Logger.Info("Will dial address", "addr", try)
  385. toDial[try.ID] = try
  386. }
  387. // Dial picked addresses
  388. for _, addr := range toDial {
  389. go r.dialPeer(addr)
  390. }
  391. // If we need more addresses, pick a random peer and ask for more.
  392. if r.book.NeedMoreAddrs() {
  393. peers := r.Switch.Peers().List()
  394. peersCount := len(peers)
  395. if peersCount > 0 {
  396. peer := peers[cmn.RandInt()%peersCount] // nolint: gas
  397. r.Logger.Info("We need more addresses. Sending pexRequest to random peer", "peer", peer)
  398. r.RequestAddrs(peer)
  399. }
  400. }
  401. // If we are not connected to nor dialing anybody, fallback to dialing a seed.
  402. if out+in+dial+len(toDial) == 0 {
  403. r.Logger.Info("No addresses to dial nor connected peers. Falling back to seeds")
  404. r.dialSeeds()
  405. }
  406. }
  407. func (r *PEXReactor) dialAttemptsInfo(addr *p2p.NetAddress) (attempts int, lastDialed time.Time) {
  408. _attempts, ok := r.attemptsToDial.Load(addr.DialString())
  409. if !ok {
  410. return
  411. }
  412. atd := _attempts.(_attemptsToDial)
  413. return atd.number, atd.lastDialed
  414. }
  415. func (r *PEXReactor) dialPeer(addr *p2p.NetAddress) {
  416. attempts, lastDialed := r.dialAttemptsInfo(addr)
  417. if attempts > maxAttemptsToDial {
  418. // Do not log the message if the addr gets readded.
  419. if attempts+1 == maxAttemptsToDial {
  420. r.Logger.Info("Reached max attempts to dial", "addr", addr, "attempts", attempts)
  421. r.attemptsToDial.Store(addr.DialString(), _attemptsToDial{attempts + 1, time.Now()})
  422. }
  423. r.book.MarkBad(addr)
  424. return
  425. }
  426. // exponential backoff if it's not our first attempt to dial given address
  427. if attempts > 0 {
  428. jitterSeconds := time.Duration(cmn.RandFloat64() * float64(time.Second)) // 1s == (1e9 ns)
  429. backoffDuration := jitterSeconds + ((1 << uint(attempts)) * time.Second)
  430. sinceLastDialed := time.Since(lastDialed)
  431. if sinceLastDialed < backoffDuration {
  432. r.Logger.Debug("Too early to dial", "addr", addr, "backoff_duration", backoffDuration, "last_dialed", lastDialed, "time_since", sinceLastDialed)
  433. return
  434. }
  435. }
  436. err := r.Switch.DialPeerWithAddress(addr, false)
  437. if err != nil {
  438. if _, ok := err.(p2p.ErrCurrentlyDialingOrExistingAddress); ok {
  439. return
  440. }
  441. r.Logger.Error("Dialing failed", "addr", addr, "err", err, "attempts", attempts)
  442. markAddrInBookBasedOnErr(addr, r.book, err)
  443. if _, ok := err.(p2p.ErrSwitchAuthenticationFailure); ok {
  444. r.attemptsToDial.Delete(addr.DialString())
  445. } else {
  446. // FIXME: if the addr is going to be removed from the addrbook (hard to
  447. // tell at this point), we need to Delete it from attemptsToDial, not
  448. // record another attempt.
  449. // record attempt
  450. r.attemptsToDial.Store(addr.DialString(), _attemptsToDial{attempts + 1, time.Now()})
  451. }
  452. return
  453. }
  454. // cleanup any history
  455. r.attemptsToDial.Delete(addr.DialString())
  456. }
  457. // checkSeeds checks that addresses are well formed.
  458. // Returns number of seeds we can connect to, along with all seeds addrs.
  459. // return err if user provided any badly formatted seed addresses.
  460. // Doesn't error if the seed node can't be reached.
  461. // numOnline returns -1 if no seed nodes were in the initial configuration.
  462. func (r *PEXReactor) checkSeeds() (numOnline int, netAddrs []*p2p.NetAddress, err error) {
  463. lSeeds := len(r.config.Seeds)
  464. if lSeeds == 0 {
  465. return -1, nil, nil
  466. }
  467. netAddrs, errs := p2p.NewNetAddressStrings(r.config.Seeds)
  468. numOnline = lSeeds - len(errs)
  469. for _, err := range errs {
  470. switch e := err.(type) {
  471. case p2p.ErrNetAddressLookup:
  472. r.Logger.Error("Connecting to seed failed", "err", e)
  473. default:
  474. return 0, nil, errors.Wrap(e, "seed node configuration has error")
  475. }
  476. }
  477. return
  478. }
  479. // randomly dial seeds until we connect to one or exhaust them
  480. func (r *PEXReactor) dialSeeds() {
  481. perm := cmn.RandPerm(len(r.seedAddrs))
  482. // perm := r.Switch.rng.Perm(lSeeds)
  483. for _, i := range perm {
  484. // dial a random seed
  485. seedAddr := r.seedAddrs[i]
  486. err := r.Switch.DialPeerWithAddress(seedAddr, false)
  487. if err == nil {
  488. return
  489. }
  490. r.Switch.Logger.Error("Error dialing seed", "err", err, "seed", seedAddr)
  491. }
  492. r.Switch.Logger.Error("Couldn't connect to any seeds")
  493. }
  494. // AttemptsToDial returns the number of attempts to dial specific address. It
  495. // returns 0 if never attempted or successfully connected.
  496. func (r *PEXReactor) AttemptsToDial(addr *p2p.NetAddress) int {
  497. lAttempts, attempted := r.attemptsToDial.Load(addr.DialString())
  498. if attempted {
  499. return lAttempts.(_attemptsToDial).number
  500. }
  501. return 0
  502. }
  503. //----------------------------------------------------------
  504. // Explores the network searching for more peers. (continuous)
  505. // Seed/Crawler Mode causes this node to quickly disconnect
  506. // from peers, except other seed nodes.
  507. func (r *PEXReactor) crawlPeersRoutine() {
  508. // Do an initial crawl
  509. r.crawlPeers(r.book.GetSelection())
  510. // Fire periodically
  511. ticker := time.NewTicker(crawlPeerPeriod)
  512. for {
  513. select {
  514. case <-ticker.C:
  515. r.attemptDisconnects()
  516. r.crawlPeers(r.book.GetSelection())
  517. r.cleanupCrawlPeerInfos()
  518. case <-r.Quit():
  519. return
  520. }
  521. }
  522. }
  523. // nodeHasSomePeersOrDialingAny returns true if the node is connected to some
  524. // peers or dialing them currently.
  525. func (r *PEXReactor) nodeHasSomePeersOrDialingAny() bool {
  526. out, in, dial := r.Switch.NumPeers()
  527. return out+in+dial > 0
  528. }
  529. // crawlPeerInfo handles temporary data needed for the network crawling
  530. // performed during seed/crawler mode.
  531. type crawlPeerInfo struct {
  532. Addr *p2p.NetAddress `json:"addr"`
  533. // The last time we crawled the peer or attempted to do so.
  534. LastCrawled time.Time `json:"last_crawled"`
  535. }
  536. // crawlPeers will crawl the network looking for new peer addresses.
  537. func (r *PEXReactor) crawlPeers(addrs []*p2p.NetAddress) {
  538. now := time.Now()
  539. for _, addr := range addrs {
  540. peerInfo, ok := r.crawlPeerInfos[addr.ID]
  541. // Do not attempt to connect with peers we recently crawled.
  542. if ok && now.Sub(peerInfo.LastCrawled) < minTimeBetweenCrawls {
  543. continue
  544. }
  545. // Record crawling attempt.
  546. r.crawlPeerInfos[addr.ID] = crawlPeerInfo{
  547. Addr: addr,
  548. LastCrawled: now,
  549. }
  550. err := r.Switch.DialPeerWithAddress(addr, false)
  551. if err != nil {
  552. if _, ok := err.(p2p.ErrCurrentlyDialingOrExistingAddress); ok {
  553. continue
  554. }
  555. r.Logger.Error("Dialing failed", "addr", addr, "err", err)
  556. markAddrInBookBasedOnErr(addr, r.book, err)
  557. continue
  558. }
  559. peer := r.Switch.Peers().Get(addr.ID)
  560. if peer != nil {
  561. r.RequestAddrs(peer)
  562. }
  563. }
  564. }
  565. func (r *PEXReactor) cleanupCrawlPeerInfos() {
  566. for id, info := range r.crawlPeerInfos {
  567. // If we did not crawl a peer for 24 hours, it means the peer was removed
  568. // from the addrbook => remove
  569. //
  570. // 10000 addresses / maxGetSelection = 40 cycles to get all addresses in
  571. // the ideal case,
  572. // 40 * crawlPeerPeriod ~ 20 minutes
  573. if time.Since(info.LastCrawled) > 24*time.Hour {
  574. delete(r.crawlPeerInfos, id)
  575. }
  576. }
  577. }
  578. // attemptDisconnects checks if we've been with each peer long enough to disconnect
  579. func (r *PEXReactor) attemptDisconnects() {
  580. for _, peer := range r.Switch.Peers().List() {
  581. if peer.Status().Duration < r.config.SeedDisconnectWaitPeriod {
  582. continue
  583. }
  584. if peer.IsPersistent() {
  585. continue
  586. }
  587. r.Switch.StopPeerGracefully(peer)
  588. }
  589. }
  590. func markAddrInBookBasedOnErr(addr *p2p.NetAddress, book AddrBook, err error) {
  591. // TODO: detect more "bad peer" scenarios
  592. switch err.(type) {
  593. case p2p.ErrSwitchAuthenticationFailure:
  594. book.MarkBad(addr)
  595. default:
  596. book.MarkAttempt(addr)
  597. }
  598. }
  599. //-----------------------------------------------------------------------------
  600. // Messages
  601. // PexMessage is a primary type for PEX messages. Underneath, it could contain
  602. // either pexRequestMessage, or pexAddrsMessage messages.
  603. type PexMessage interface{}
  604. func RegisterPexMessage(cdc *amino.Codec) {
  605. cdc.RegisterInterface((*PexMessage)(nil), nil)
  606. cdc.RegisterConcrete(&pexRequestMessage{}, "tendermint/p2p/PexRequestMessage", nil)
  607. cdc.RegisterConcrete(&pexAddrsMessage{}, "tendermint/p2p/PexAddrsMessage", nil)
  608. }
  609. func decodeMsg(bz []byte) (msg PexMessage, err error) {
  610. if len(bz) > maxMsgSize {
  611. return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", len(bz), maxMsgSize)
  612. }
  613. err = cdc.UnmarshalBinaryBare(bz, &msg)
  614. return
  615. }
  616. /*
  617. A pexRequestMessage requests additional peer addresses.
  618. */
  619. type pexRequestMessage struct {
  620. }
  621. func (m *pexRequestMessage) String() string {
  622. return "[pexRequest]"
  623. }
  624. /*
  625. A message with announced peer addresses.
  626. */
  627. type pexAddrsMessage struct {
  628. Addrs []*p2p.NetAddress
  629. }
  630. func (m *pexAddrsMessage) String() string {
  631. return fmt.Sprintf("[pexAddrs %v]", m.Addrs)
  632. }