feat(p2p): ensure time synchronization in the network#2255
Conversation
b675759 to
afe2212
Compare
Signed-off-by: onur-ozkan <work@onurozkan.dev>
afe2212 to
4343c0e
Compare
Signed-off-by: onur-ozkan <work@onurozkan.dev>
f9dd830 to
5acfe8d
Compare
Signed-off-by: onur-ozkan <work@onurozkan.dev>
da8335c to
82ae6d2
Compare
Signed-off-by: onur-ozkan <work@onurozkan.dev>
Signed-off-by: onur-ozkan <work@onurozkan.dev>
Signed-off-by: onur-ozkan <work@onurozkan.dev>
| /// TODO: This should be called `PeerInfoRequest` instead. However, renaming it | ||
| /// will introduce a breaking change in the network and is not worth it. Do this | ||
| /// renaming when there is already a breaking change in the release. | ||
| NetworkInfo(network_info::NetworkInfoRequest), |
There was a problem hiding this comment.
This PR already leads to breaking change. It's perfect time to rename this.
There was a problem hiding this comment.
One way to avoid breaking changes is to have a timeout on the request for peer timestamp and allow them to connect if there is no response from the peer. We later remove this when most peers update. Another way is to get the mm2 version and do the timestamp request depending on the version. What do you think?
There was a problem hiding this comment.
One way to avoid breaking changes is to have a timeout on the request for peer timestamp and allow them to connect if there is no response from the peer. We later remove this when most peers update.
This sounds like a good plan!
Another way is to get the mm2 version and do the timestamp request depending on the version. What do you think?
I think the first idea was better, but then I need to revert the peer-info renaming part. What about bundling these changes in some branch, and then releasing multiple breaking changes at once (like removing mm2 binaries and some other stuff) ?
There was a problem hiding this comment.
What about bundling these changes in some branch, and then releasing multiple breaking changes at once (like removing mm2 binaries and some other stuff) ?
I am fine with this or the first approach.
Signed-off-by: onur-ozkan <work@onurozkan.dev>
Signed-off-by: onur-ozkan <work@onurozkan.dev>
5ba1ac5 to
e86a166
Compare
Signed-off-by: onur-ozkan <work@onurozkan.dev>
e86a166 to
c1a6eaf
Compare
Signed-off-by: onur-ozkan <work@onurozkan.dev>
Signed-off-by: onur-ozkan <work@onurozkan.dev>
Signed-off-by: onur-ozkan <work@onurozkan.dev>
… into time-synced-network
Signed-off-by: onur-ozkan <work@onurozkan.dev>
| /// Determines if a dial attempt to the remote should be made. | ||
| /// | ||
| /// Returns `false` if a dial attempt to the given address has already been made, | ||
| /// in which case the caller must skip the dial attempt. | ||
| fn pre_dial_check(recently_dialed_peers: &mut MutexGuard<TimedMap<StdClock, Multiaddr, ()>>, addr: &Multiaddr) -> bool { |
There was a problem hiding this comment.
Neither the doc comment nor the func name signify how this function changes the timedmap (only visible from the mutability of the passed map). Let's change this to something like check_and_mark_dialed or something.
Also, no need for the MutexGuard annotation here.
There was a problem hiding this comment.
Neither the doc comment nor the func name signify how this function changes the timedmap (only visible from the mutability of the passed map)
"only visible from the mutability of the passed map" that's visible everywhere, both in the function signature and on the caller side!
I struggle to see how check_and_mark_dialed describes the function better than pre_dial_check but whatever, I am okay with it.
Also, no need for the MutexGuard annotation here.
It gives/documents the background context how this map is utilized from caller.
Signed-off-by: onur-ozkan <work@onurozkan.dev>
… into time-synced-network
|
Do we have any blocker for this PR? @shamardy |
Signed-off-by: onur-ozkan <work@onurozkan.dev>
Signed-off-by: onur-ozkan <work@onurozkan.dev>
|
Doesn't cause the breakage anymore. |
… into time-synced-network
|
Resolved conflicts |
mariocynicys
left a comment
There was a problem hiding this comment.
non-blocking comments inline (just to not block this further).
LGTM
| debug!( | ||
| "Peer '{peer}' is within the acceptable time gap ({MAX_TIME_GAP_FOR_CONNECTED_PEER} seconds); time difference is {diff} seconds." | ||
| ); | ||
| response_tx.send(None).await.unwrap(); |
There was a problem hiding this comment.
this send in redundant. what about not sending anything in here, as the other end of the end of the channel doesn't really use the None for anything.
There was a problem hiding this comment.
If you don't send anything, it will block the request/process until timeout. The channel plays a request-response style communication here.
There was a problem hiding this comment.
please take a second look at this. the response_tx is for the timestamp checker and not a response to some node or something (i didn't really get what u mean).
There was a problem hiding this comment.
Ah, thought was awaiting on result of this channel
| error!("Unexpected response `{other:?}` from peer `{peer}`"); | ||
| // TODO: Ideally, we should send `Some(peer)` to end the connection, | ||
| // but we don't want to cause a breaking change yet. | ||
| response_tx.send(None).await.unwrap(); |
| } | ||
| } | ||
|
|
||
| while let Poll::Ready(Some(Some(peer_id))) = timestamp_rx.poll_next_unpin(cx) { |
There was a problem hiding this comment.
and we can make this channel transmit PeerIDs instead of Option<PeerID>s.
|
BTW I tried to run tests in the mm2_p2p module with command |
That's weird lol. The crate path can't be resolved when targeting |
cargo test -p mm2_p2p --features "application" is needed |
|
I am aware, it's fixed in #2302 already |
* dev: (35 commits) fix(crypto): allow non bip39 mnemonics storage (GLEECBTC#2312) fix(legacy_swap): check for existing maker/taker payment before timeout (GLEECBTC#2283) feat(tendermint): validators RPC (GLEECBTC#2310) chore(CI): validate Cargo lock file (GLEECBTC#2309) test(P2P): add test for peer time sync validation (GLEECBTC#2304) fix mm2_p2p dev build (GLEECBTC#2311) update Cargo.lock (GLEECBTC#2308) chore(CI): unlock wasm-pack version (GLEECBTC#2307) add `wasm` feature on WASM for timed-map (GLEECBTC#2306) replace broken rpc link (GLEECBTC#2305) chore(eth-websocket): remove some unnecessary wrappers (GLEECBTC#2291) improvement(CI): switch to proper rust caching (GLEECBTC#2303) fix(wasm): add test-ext-api feature to mm2_main and mm2_bin_lib tomls (GLEECBTC#2295) chore(ci): Update docker build for wasm (GLEECBTC#2294) chore(p2p): follow-up nits (GLEECBTC#2302) feat(p2p): ensure time synchronization in the network (GLEECBTC#2255) bump libp2p (GLEECBTC#2296) chore(adex-cli): use "Komodo DeFi Framework" name in adex_cli (GLEECBTC#2290) chore(ctx): replace gstuff constructible with oncelock (GLEECBTC#2267) don't rely on core (GLEECBTC#2289) ...
* add time validation core logic Signed-off-by: onur-ozkan <work@onurozkan.dev> * nit fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * handle time gap Signed-off-by: onur-ozkan <work@onurozkan.dev> * improve logging Signed-off-by: onur-ozkan <work@onurozkan.dev> * add more trackable processing logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * improve info log and remove debugging leftover Signed-off-by: onur-ozkan <work@onurozkan.dev> * rename `NetworkInfoRequest` to `PeerInfoRequest` Signed-off-by: onur-ozkan <work@onurozkan.dev> * handle recently dialed peers Signed-off-by: onur-ozkan <work@onurozkan.dev> * add useful logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * create function for pre-dial check Signed-off-by: onur-ozkan <work@onurozkan.dev> * set max cap for timestamp channel Signed-off-by: onur-ozkan <work@onurozkan.dev> * remove leftover Signed-off-by: onur-ozkan <work@onurozkan.dev> * use `Multiaddr` as key Signed-off-by: onur-ozkan <work@onurozkan.dev> * fix p2p tests Signed-off-by: onur-ozkan <work@onurozkan.dev> * update logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * rename leftovers Signed-off-by: onur-ozkan <work@onurozkan.dev> * update timing values Signed-off-by: onur-ozkan <work@onurozkan.dev> * minor fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * update pre dial check calls Signed-off-by: onur-ozkan <work@onurozkan.dev> * apply nit fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * don't update existing expiries Signed-off-by: onur-ozkan <work@onurozkan.dev> * revert breakage Signed-off-by: onur-ozkan <work@onurozkan.dev> --------- Signed-off-by: onur-ozkan <work@onurozkan.dev>
* add time validation core logic Signed-off-by: onur-ozkan <work@onurozkan.dev> * nit fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * handle time gap Signed-off-by: onur-ozkan <work@onurozkan.dev> * improve logging Signed-off-by: onur-ozkan <work@onurozkan.dev> * add more trackable processing logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * improve info log and remove debugging leftover Signed-off-by: onur-ozkan <work@onurozkan.dev> * rename `NetworkInfoRequest` to `PeerInfoRequest` Signed-off-by: onur-ozkan <work@onurozkan.dev> * handle recently dialed peers Signed-off-by: onur-ozkan <work@onurozkan.dev> * add useful logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * create function for pre-dial check Signed-off-by: onur-ozkan <work@onurozkan.dev> * set max cap for timestamp channel Signed-off-by: onur-ozkan <work@onurozkan.dev> * remove leftover Signed-off-by: onur-ozkan <work@onurozkan.dev> * use `Multiaddr` as key Signed-off-by: onur-ozkan <work@onurozkan.dev> * fix p2p tests Signed-off-by: onur-ozkan <work@onurozkan.dev> * update logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * rename leftovers Signed-off-by: onur-ozkan <work@onurozkan.dev> * update timing values Signed-off-by: onur-ozkan <work@onurozkan.dev> * minor fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * update pre dial check calls Signed-off-by: onur-ozkan <work@onurozkan.dev> * apply nit fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * don't update existing expiries Signed-off-by: onur-ozkan <work@onurozkan.dev> * revert breakage Signed-off-by: onur-ozkan <work@onurozkan.dev> --------- Signed-off-by: onur-ozkan <work@onurozkan.dev>
* add time validation core logic Signed-off-by: onur-ozkan <work@onurozkan.dev> * nit fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * handle time gap Signed-off-by: onur-ozkan <work@onurozkan.dev> * improve logging Signed-off-by: onur-ozkan <work@onurozkan.dev> * add more trackable processing logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * improve info log and remove debugging leftover Signed-off-by: onur-ozkan <work@onurozkan.dev> * rename `NetworkInfoRequest` to `PeerInfoRequest` Signed-off-by: onur-ozkan <work@onurozkan.dev> * handle recently dialed peers Signed-off-by: onur-ozkan <work@onurozkan.dev> * add useful logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * create function for pre-dial check Signed-off-by: onur-ozkan <work@onurozkan.dev> * set max cap for timestamp channel Signed-off-by: onur-ozkan <work@onurozkan.dev> * remove leftover Signed-off-by: onur-ozkan <work@onurozkan.dev> * use `Multiaddr` as key Signed-off-by: onur-ozkan <work@onurozkan.dev> * fix p2p tests Signed-off-by: onur-ozkan <work@onurozkan.dev> * update logs Signed-off-by: onur-ozkan <work@onurozkan.dev> * rename leftovers Signed-off-by: onur-ozkan <work@onurozkan.dev> * update timing values Signed-off-by: onur-ozkan <work@onurozkan.dev> * minor fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * update pre dial check calls Signed-off-by: onur-ozkan <work@onurozkan.dev> * apply nit fixes Signed-off-by: onur-ozkan <work@onurozkan.dev> * don't update existing expiries Signed-off-by: onur-ozkan <work@onurozkan.dev> * revert breakage Signed-off-by: onur-ozkan <work@onurozkan.dev> --------- Signed-off-by: onur-ozkan <work@onurozkan.dev>
Implementation Details
Once a connection is established with a peer, validation check is immediately performed to confirm the peer's clock. If the peer's time exceeds the maximum allowed cap, the connection is terminated. This approach ensures that all peers performing operations in the network are synchronized in terms of time. Current time cap is set to 30 seconds, which can be changed if it doesn't fit the requirements.
Each peer is temporarily added to the
RECENTLY_DIALED_PEERSmap for 5 minutes before any connection attempt. This prevents repeated connection attempts to peers that are unavailable or out-of-sync, which reduces unnecessary reconnection overheads.Breaking Changes1. A new request-response payload (GetPeerUtcTimestamp) has been added. This request is sent at each connection attempt, which makes it mandatory for all seed nodes and GUI applications in the network to be updated to this version. Meaning, this version is incompatible with any older version.2. TheNetworkInfoRequesthas been renamed toPeerInfoRequest. This likely affects the encoded payload ofGetMm2Version(not yet verified but highly likely).Resolves #1115 and #1683
Blocked by #2256