Skip to content
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

Start creating connections (edges) with large nonces #7966

Merged
merged 23 commits into from
Nov 25, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion chain/network/src/peer/peer_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,11 @@ impl PeerActor {
})
});

// This time is used to figure out when the first run of the callbacks it run.
// It is important that it is set here (rather than calling clock.now() within the future) - as it makes testing a lot easier (and more deterministic).

let start_time = self.clock.now();

// Here we stop processing any PeerActor events until PeerManager
// decides whether to accept the connection or not: ctx.wait makes
// the actor event loop poll on the future until it completes before
Expand Down Expand Up @@ -651,7 +656,7 @@ impl PeerActor {
async move {
// How often should we refresh a nonce from a peer.
// It should be smaller than PRUNE_EDGES_AFTER.
let mut interval = time::Interval::new(clock.now() + PRUNE_EDGES_AFTER / 3, PRUNE_EDGES_AFTER / 3);
let mut interval = time::Interval::new(start_time + PRUNE_EDGES_AFTER / 3, PRUNE_EDGES_AFTER / 3);
loop {
interval.tick(&clock).await;
conn.send_message(Arc::new(
Expand Down
14 changes: 14 additions & 0 deletions chain/network/src/peer_manager/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,20 @@ impl Pool {
pool.ready.remove(peer_id);
});
}
/// Update the edge in the pool (if it is newer).
pub fn update_edge(&self, new_edge: &Edge) {
self.0.update(|pool| {
let other = new_edge.other(&pool.me);
if let Some(other) = other {
if let Some(connection) = pool.ready.get_mut(other) {
let edge = connection.edge.load();
if edge.nonce() < new_edge.nonce() {
connection.edge.store(new_edge.clone());
}
}
}
})
}

/// Send message to peer that belongs to our active set
/// Return whether the message is sent or not.
Expand Down
9 changes: 8 additions & 1 deletion chain/network/src/peer_manager/network_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,13 @@ impl NetworkState {
})
})
.await;
this.routing_table_view.add_local_edges(&edges);
let new_local_edges = this.routing_table_view.add_local_edges(&edges);

// Local edge information is also kept in the Connection fields in peers.
// Make sure that it gets updated too.
for new_edge in new_local_edges {
this.tier2.update_edge(&new_edge);
}
Copy link
Contributor

@pompon0 pompon0 Nov 24, 2022

Choose a reason for hiding this comment

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

local_edges are the edges of the graph adjacent to this node.
edge stored in connection is the edge that the ends of the connection have agreed upon during handshake.

Given that now the edge is supposed to change dynamically and that it is delivered to a node via SyncRoutingTable message it doesn't make sense to duplicate it I guess. We can either:

  • remove edge field from the connection entirely and just rely on local_edges (I think that would be preferred)
  • revert to using ResponseUpdateNonce message, so that each PeerActor can manage the connection.edge on their own.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, we could remove the edge from the connection -- but I'd do that in a separate PR (as this one is becoming too large)

Copy link
Contributor

Choose a reason for hiding this comment

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

ack, please add a TODO

Copy link
Contributor

Choose a reason for hiding this comment

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

also you unnecesarily take a lock on the whole pool in Pool::update_edge. Instead just update the edge in-place.

Copy link
Contributor

Choose a reason for hiding this comment

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

and for that you might want ArcMutex/ArcSwap instead of AtomicCell.


let mut new_edges = match this
.routing_table_addr
Expand Down Expand Up @@ -614,6 +620,7 @@ impl NetworkState {
&self.config.node_key,
edge_info.signature,
);
self.tier2.update_edge(&edge);
self.add_edges(&clock, vec![edge.clone()]).await?;
Ok(edge)
}
Expand Down
24 changes: 21 additions & 3 deletions chain/network/src/peer_manager/tests/nonce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,33 @@ async fn test_nonce_refresh() {
// Advance a clock by 1 hour.
clock.advance(Duration::HOUR);

let new_nonce_utc = clock.now_utc();

loop {
let edge = wait_for_edge(&mut pm2).await;
if Edge::nonce_to_utc(edge.nonce()).unwrap().unwrap() == start_time {
tracing::debug!("Still seeing old edge..");
//
clock.advance(Duration::HOUR);
} else {
assert_eq!(Edge::nonce_to_utc(edge.nonce()).unwrap().unwrap(), clock.now_utc());
assert_eq!(Edge::nonce_to_utc(edge.nonce()).unwrap().unwrap(), new_nonce_utc);
break;
}
pompon0 marked this conversation as resolved.
Show resolved Hide resolved
}

// Check that the nonces were properly updates on both pm and pm2 states.
let pm_peer_info = pm.peer_info().id.clone();
let pm2_nonce = pm2
.with_state(|s| async move {
s.tier2.load().ready.get(&pm_peer_info).unwrap().edge.load().nonce()
})
.await;

assert_eq!(Edge::nonce_to_utc(pm2_nonce).unwrap().unwrap(), new_nonce_utc);

let pm_nonce = pm
.with_state(|s| async move {
s.tier2.load().ready.get(&pm2.peer_info().id).unwrap().edge.load().nonce()
})
.await;

assert_eq!(Edge::nonce_to_utc(pm_nonce).unwrap().unwrap(), new_nonce_utc);
}
2 changes: 1 addition & 1 deletion core/primitives/src/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ pub struct PeerInfoView {
pub last_time_received_message_millis: u64,
pub connection_established_time_millis: u64,
pub is_outbound_peer: bool,
// Connection nonce.
/// Connection nonce.
pub nonce: u64,
}

Expand Down