Skip to content

Commit 2440ac2

Browse files
authored
IPC-520: Upgrade the IPLD Resolver for libp2p 0.53 (#522)
1 parent 3e7984d commit 2440ac2

13 files changed

Lines changed: 1245 additions & 1835 deletions

File tree

Cargo.lock

Lines changed: 786 additions & 1549 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,24 @@ clap = { version = "4.1", features = ["derive", "env"] }
5252
config = "0.13"
5353
dirs = "5.0"
5454
dircpy = "0.3"
55+
env_logger = "0.10"
5556
erased-serde = "0.3"
5657
ethers = { version = "2.0", features = ["abigen", "ws"] }
5758
ethers-core = { version = "2.0" }
59+
ethers-contract = "2.0.8"
5860
fnv = "1.0"
5961
futures = "0.3"
6062
futures-core = "0.3"
6163
futures-util = "0.3"
6264
gcra = "0.4"
6365
hex = "0.4"
6466
im = "15.1.0"
67+
integer-encoding = { version = "3.0.3", default-features = false }
6568
jsonrpc-v2 = { version = "0.11", default-features = false, features = ["bytes-v10"] }
6669
k256 = "0.11" # Same as tendermint-rs
6770
lazy_static = "1.4"
6871
libipld = { version = "0.14", default-features = false, features = ["dag-cbor"] }
69-
libp2p = { version = "0.50", default-features = false, features = [
72+
libp2p = { version = "0.53", default-features = false, features = [
7073
"gossipsub",
7174
"kad",
7275
"identify",
@@ -75,7 +78,6 @@ libp2p = { version = "0.50", default-features = false, features = [
7578
"yamux",
7679
"tcp",
7780
"dns",
78-
"mplex",
7981
"request-response",
8082
"metrics",
8183
"tokio",
@@ -84,22 +86,29 @@ libp2p = { version = "0.50", default-features = false, features = [
8486
"secp256k1",
8587
"plaintext",
8688
] }
87-
libp2p-bitswap = "0.25.1"
89+
libp2p-mplex = { version = "0.41" }
90+
# libp2p-bitswap = "0.25.1"
91+
libp2p-bitswap = { git = "https://github.com/consensus-shipyard/libp2p-bitswap.git", branch = "chore-upgrade-libp2p" } # Updated to libp2p v0.53
92+
libsecp256k1 = "0.7"
93+
literally = "0.1.3"
94+
log = "0.4"
8895
lru_time_cache = "0.11"
8996
merkle-tree-rs = "0.1.0"
90-
multiaddr = "0.16"
97+
multiaddr = "0.18"
9198
multihash = { version = "0.16.1", default-features = false }
9299
num-bigint = "0.4"
93100
num-derive = "0.3"
94101
num-traits = "0.2"
95102
paste = "1"
96103
pin-project = "1.1.2"
104+
prometheus = "0.13"
97105
prost = { version = "0.11" }
98106
quickcheck = "1"
99107
quickcheck_macros = "1"
100108
rand = "0.8"
101109
rand_chacha = "0.3"
102110
regex = "1"
111+
reqwest = { version = "0.11.13", features = ["json"] }
103112
sha2 = "0.10"
104113
serde = { version = "1", features = ["derive"] }
105114
serde_bytes = "0.11"
@@ -118,21 +127,13 @@ tokio = { version = "1", features = [
118127
] }
119128
tokio-stream = "0.1.14"
120129
tokio-util = { version = "0.7.8", features = ["compat"] }
130+
tokio-tungstenite = { version = "0.18.0", features = ["native-tls"] }
121131
toml = "0.7"
122132
tracing = "0.1"
123133
tracing-subscriber = "0.3"
134+
trace4rs = "0.5.1"
124135
url = { version = "2.4.1", features = ["serde"] }
125136
zeroize = "1.6"
126-
trace4rs = "0.5.1"
127-
literally = "0.1.3"
128-
reqwest = { version = "0.11.13", features = ["json"] }
129-
log = "0.4"
130-
env_logger = "0.10"
131-
prometheus = "0.13"
132-
tokio-tungstenite = { version = "0.18.0", features = ["native-tls"] }
133-
libsecp256k1 = "0.7"
134-
ethers-contract = "2.0.8"
135-
integer-encoding = {version = "3.0.3", default-features = false}
136137

137138
# Workspace deps
138139
ipc-api = { path = "ipc/api" }
@@ -149,7 +150,7 @@ openssl = { version = "0.10", features = ["vendored"] }
149150
# Using the 3.3 version of the FVM because the newer ones update the IPLD dependencies
150151
# to version which are different than the ones in the builtin-actors project, and since
151152
# they are 0.x cargo cannot upgrade them automatically, which leads to version conflicts.
152-
fvm = { version = "~3.2", default-features = false } # no opencl feature or it fails on CI
153+
fvm = { version = "~3.2", default-features = false } # no opencl feature or it fails on CI
153154
fvm_shared = { version = "~3.2", features = ["crypto"] }
154155
fvm_sdk = { version = "~3.2" }
155156

fendermint/app/src/cmd/run.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,11 @@ fn to_resolver_config(settings: &Settings) -> anyhow::Result<ipc_ipld_resolver::
313313

314314
let r = &settings.resolver;
315315

316-
let local_key = {
316+
let local_key: Keypair = {
317317
let path = r.network.local_key(settings.home_dir());
318318
let sk = read_secret_key(&path)?;
319-
let sk = secp256k1::SecretKey::from_bytes(sk.serialize())?;
320-
Keypair::Secp256k1(secp256k1::Keypair::from(sk))
319+
let sk = secp256k1::SecretKey::try_from_bytes(sk.serialize())?;
320+
secp256k1::Keypair::from(sk).into()
321321
};
322322

323323
let network_name = format!(

ipld/resolver/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ lazy_static = { workspace = true }
1616
libipld = { workspace = true }
1717
libp2p = { workspace = true }
1818
libp2p-bitswap = { workspace = true }
19+
libp2p-mplex = { workspace = true }
20+
lru_time_cache = { workspace = true }
1921
log = { workspace = true }
2022
prometheus = { workspace = true }
2123
quickcheck = { workspace = true, optional = true }

ipld/resolver/src/behaviour/content.rs

Lines changed: 112 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,17 @@ use std::{
99

1010
use libipld::{store::StoreParams, Cid};
1111
use libp2p::{
12-
core::ConnectedPoint,
12+
core::{ConnectedPoint, Endpoint},
1313
futures::channel::oneshot,
1414
multiaddr::Protocol,
15-
request_response::handler::RequestResponseHandlerEvent,
1615
swarm::{
17-
derive_prelude::{ConnectionId, FromSwarm},
18-
ConnectionHandler, IntoConnectionHandler, NetworkBehaviour, NetworkBehaviourAction,
19-
PollParameters,
16+
derive_prelude::FromSwarm, ConnectionDenied, ConnectionId, NetworkBehaviour, THandler,
17+
THandlerInEvent, THandlerOutEvent, ToSwarm,
2018
},
2119
Multiaddr, PeerId,
2220
};
2321
use libp2p_bitswap::{Bitswap, BitswapConfig, BitswapEvent, BitswapResponse, BitswapStore};
24-
use log::warn;
22+
use log::debug;
2523
use prometheus::Registry;
2624

2725
use crate::{
@@ -54,6 +52,7 @@ pub enum Event {
5452
/// This is only raised if we are tracking rate limits. The service has to
5553
/// do the forwarding between the two oneshot channels, and call this module
5654
/// back between doing so.
55+
#[allow(dead_code)]
5756
BitswapForward {
5857
peer_id: PeerId,
5958
/// Receive response from the [`Bitswap`] behaviour.
@@ -140,12 +139,14 @@ impl<P: StoreParams> Behaviour<P> {
140139
/// The underlying [`libp2p_request_response::RequestResponse`] behaviour
141140
/// will initiate connections to the peers which aren't connected at the moment.
142141
pub fn resolve(&mut self, cid: Cid, peers: Vec<PeerId>) -> QueryId {
142+
debug!("resolving {cid} from {peers:?}");
143143
stats::CONTENT_RESOLVE_RUNNING.inc();
144144
// Not passing any missing items, which will result in a call to `BitswapStore::missing_blocks`.
145145
self.inner.sync(cid, peers, [].into_iter())
146146
}
147147

148148
/// Check whether the peer has already exhaused their rate limit.
149+
#[allow(dead_code)]
149150
fn check_rate_limit(&mut self, peer_id: &PeerId, cid: &Cid) -> bool {
150151
if let Some(ref rate_limit) = self.rate_limit {
151152
if let Some(addr) = self.peer_addresses.get(peer_id).cloned() {
@@ -181,17 +182,9 @@ impl<P: StoreParams> Behaviour<P> {
181182

182183
impl<P: StoreParams> NetworkBehaviour for Behaviour<P> {
183184
type ConnectionHandler = <Bitswap<P> as NetworkBehaviour>::ConnectionHandler;
184-
type OutEvent = Event;
185+
type ToSwarm = Event;
185186

186-
fn new_handler(&mut self) -> Self::ConnectionHandler {
187-
self.inner.new_handler()
188-
}
189-
190-
fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec<Multiaddr> {
191-
self.inner.addresses_of_peer(peer_id)
192-
}
193-
194-
fn on_swarm_event(&mut self, event: FromSwarm<Self::ConnectionHandler>) {
187+
fn on_swarm_event(&mut self, event: FromSwarm) {
195188
// Store the remote address.
196189
match &event {
197190
FromSwarm::ConnectionEstablished(c) => {
@@ -226,61 +219,124 @@ impl<P: StoreParams> NetworkBehaviour for Behaviour<P> {
226219
&mut self,
227220
peer_id: PeerId,
228221
connection_id: ConnectionId,
229-
event: <<Self::ConnectionHandler as IntoConnectionHandler>::Handler as ConnectionHandler>::OutEvent,
222+
event: THandlerOutEvent<Self>,
230223
) {
231-
match event {
232-
RequestResponseHandlerEvent::Request {
233-
request_id,
234-
request,
235-
sender,
236-
} if self.rate_limit.is_some() => {
237-
if !self.check_rate_limit(&peer_id, &request.cid) {
238-
warn!("rate limiting {peer_id}");
239-
stats::CONTENT_RATE_LIMITED.inc();
240-
return;
241-
}
242-
// We need to hijack the response channel to record the size, otherwise it goes straight to the handler.
243-
let (tx, rx) = libp2p::futures::channel::oneshot::channel();
244-
let event = RequestResponseHandlerEvent::Request {
245-
request_id,
246-
request,
247-
sender: tx,
248-
};
249-
250-
self.inner
251-
.on_connection_handler_event(peer_id, connection_id, event);
252-
253-
let forward = Event::BitswapForward {
254-
peer_id,
255-
response_rx: rx,
256-
response_tx: sender,
257-
};
258-
self.outbox.push_back(forward);
259-
}
260-
_ => self
261-
.inner
262-
.on_connection_handler_event(peer_id, connection_id, event),
263-
}
224+
// TODO: `request_response::handler` is now private, so we cannot pattern match on the handler event.
225+
// By the looks of the only way to access the request event is to let it go right into the RR protocol
226+
// wrapped by the Bitswap behaviour and let it raise an event, however we will not see that event here.
227+
// I'm not sure what we can do without moving rate limiting into the bitswap library itself, because
228+
// what we did here relied on the ability to redirect the channels inside the request, but if the event
229+
// itself is private to the `request_response` protocol there's nothing I can do.
230+
// match event {
231+
232+
// request_response::handler::Event::Request {
233+
// request_id,
234+
// request,
235+
// sender,
236+
// } if self.rate_limit.is_some() => {
237+
// if !self.check_rate_limit(&peer_id, &request.cid) {
238+
// warn!("rate limiting {peer_id}");
239+
// stats::CONTENT_RATE_LIMITED.inc();
240+
// return;
241+
// }
242+
// // We need to hijack the response channel to record the size, otherwise it goes straight to the handler.
243+
// let (tx, rx) = libp2p::futures::channel::oneshot::channel();
244+
// let event = request_response::Event::Request {
245+
// request_id,
246+
// request,
247+
// sender: tx,
248+
// };
249+
250+
// self.inner
251+
// .on_connection_handler_event(peer_id, connection_id, event);
252+
253+
// let forward = Event::BitswapForward {
254+
// peer_id,
255+
// response_rx: rx,
256+
// response_tx: sender,
257+
// };
258+
// self.outbox.push_back(forward);
259+
// }
260+
// _ => self
261+
// .inner
262+
// .on_connection_handler_event(peer_id, connection_id, event),
263+
// }
264+
265+
// debug!("BITSWAP CONNECTION HANDLER EVENT: {event:?}");
266+
267+
self.inner
268+
.on_connection_handler_event(peer_id, connection_id, event)
269+
}
270+
271+
fn handle_pending_inbound_connection(
272+
&mut self,
273+
connection_id: ConnectionId,
274+
local_addr: &Multiaddr,
275+
remote_addr: &Multiaddr,
276+
) -> Result<(), ConnectionDenied> {
277+
self.inner
278+
.handle_pending_inbound_connection(connection_id, local_addr, remote_addr)
279+
}
280+
281+
fn handle_established_inbound_connection(
282+
&mut self,
283+
connection_id: ConnectionId,
284+
peer: PeerId,
285+
local_addr: &Multiaddr,
286+
remote_addr: &Multiaddr,
287+
) -> Result<THandler<Self>, ConnectionDenied> {
288+
self.inner.handle_established_inbound_connection(
289+
connection_id,
290+
peer,
291+
local_addr,
292+
remote_addr,
293+
)
294+
}
295+
296+
fn handle_pending_outbound_connection(
297+
&mut self,
298+
connection_id: ConnectionId,
299+
maybe_peer: Option<PeerId>,
300+
addresses: &[Multiaddr],
301+
effective_role: Endpoint,
302+
) -> Result<Vec<Multiaddr>, ConnectionDenied> {
303+
self.inner.handle_pending_outbound_connection(
304+
connection_id,
305+
maybe_peer,
306+
addresses,
307+
effective_role,
308+
)
309+
}
310+
311+
fn handle_established_outbound_connection(
312+
&mut self,
313+
connection_id: ConnectionId,
314+
peer: PeerId,
315+
addr: &Multiaddr,
316+
role_override: Endpoint,
317+
) -> Result<THandler<Self>, ConnectionDenied> {
318+
self.inner
319+
.handle_established_outbound_connection(connection_id, peer, addr, role_override)
264320
}
265321

266322
fn poll(
267323
&mut self,
268324
cx: &mut Context<'_>,
269-
params: &mut impl PollParameters,
270-
) -> Poll<NetworkBehaviourAction<Self::OutEvent, Self::ConnectionHandler>> {
325+
) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
271326
// Emit own events first.
272327
if let Some(ev) = self.outbox.pop_front() {
273-
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
328+
return Poll::Ready(ToSwarm::GenerateEvent(ev));
274329
}
275330
// Poll Bitswap.
276-
while let Poll::Ready(ev) = self.inner.poll(cx, params) {
331+
while let Poll::Ready(ev) = self.inner.poll(cx) {
332+
// debug!("BITSWAP POLL: {ev:?}");
277333
match ev {
278-
NetworkBehaviourAction::GenerateEvent(ev) => match ev {
334+
ToSwarm::GenerateEvent(ev) => match ev {
279335
BitswapEvent::Progress(_, _) => {}
280336
BitswapEvent::Complete(id, result) => {
281337
stats::CONTENT_RESOLVE_RUNNING.dec();
282338
let out = Event::Complete(id, result);
283-
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(out));
339+
return Poll::Ready(ToSwarm::GenerateEvent(out));
284340
}
285341
},
286342
other => {

0 commit comments

Comments
 (0)