From 2b67bbb5395e470a0ab5211b3970709bb97b9a09 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Thu, 30 Jul 2020 16:50:34 +0200 Subject: [PATCH 01/18] WIP, good start --- Cargo.lock | 117 ++++++++++++++++++++--- bin/node-template/node/src/service.rs | 2 + bin/node/cli/src/service.rs | 2 + client/network-gossip/src/bridge.rs | 3 +- client/network/Cargo.toml | 1 + client/network/src/behaviour.rs | 22 ++++- client/network/src/lib.rs | 1 + client/network/src/protocol/event.rs | 2 + client/network/src/service.rs | 14 ++- client/network/src/service/out_events.rs | 10 ++ client/rpc-api/Cargo.toml | 1 + client/rpc-api/src/system/error.rs | 9 +- client/rpc-api/src/system/mod.rs | 9 ++ client/rpc/src/system/mod.rs | 22 +++++ client/service/Cargo.toml | 2 + client/service/src/builder.rs | 12 ++- client/service/src/lib.rs | 64 ++++++++++++- 17 files changed, 269 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 574e4f4802550..02dcee6efa24d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,12 +258,23 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" +[[package]] +name = "async-attributes" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd3d156917d94862e779f356c5acae312b08fd3121e792c857d7928c8088423" +dependencies = [ + "quote 1.0.6", + "syn 1.0.33", +] + [[package]] name = "async-std" version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00d68a33ebc8b57800847d00787307f84a562224a14db069b0acefe4c2abbf5d" dependencies = [ + "async-attributes", "async-task", "crossbeam-utils", "futures-channel", @@ -337,6 +348,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base-x" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" + [[package]] name = "base58" version = "0.1.0" @@ -691,6 +708,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "cid" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8709d481fb78b9808f34a1b4b4fadd08a15a0971052c18bc2b751faefaed595e" +dependencies = [ + "multibase", + "multihash", + "unsigned-varint 0.3.3", +] + [[package]] name = "clang-sys" version = "0.29.3" @@ -1129,6 +1157,28 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11c0346158a19b3627234e15596f5e465c360fcdb97d817bcb255e0510f5a788" +[[package]] +name = "data-encoding-macro" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de6489dde5128f5ab2f71f88f8807a237cecf08d96dc7ca4be64e0730dc7d961" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", + "proc-macro-hack", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d2d6daefd5f1d4b74a891a5d2ab7dccba028d423107c074232a0c5dc0d40a9e" +dependencies = [ + "data-encoding", + "proc-macro-hack", + "syn 1.0.33", +] + [[package]] name = "derive_more" version = "0.99.5" @@ -1541,9 +1591,9 @@ dependencies = [ [[package]] name = "fnv" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fork-tree" @@ -2797,6 +2847,18 @@ dependencies = [ "take_mut", ] +[[package]] +name = "libipld-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb1d6e9195f4c088b65dd96b942efae068fbc49fd2ca9f15ac7f4407a9292d" +dependencies = [ + "cid", + "multibase", + "multihash", + "thiserror", +] + [[package]] name = "libloading" version = "0.5.2" @@ -2845,6 +2907,24 @@ dependencies = [ "wasm-timer", ] +[[package]] +name = "libp2p-bitswap" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fecd4a8c7c6e82d1cd49687f7057f52d78adb729888868d6dcb1e898ece44f" +dependencies = [ + "async-std", + "fnv", + "futures 0.3.5", + "libipld-core", + "libp2p", + "log", + "prost", + "prost-build", + "thiserror", + "unsigned-varint 0.3.3", +] + [[package]] name = "libp2p-core" version = "0.20.1" @@ -3212,9 +3292,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ "cfg-if", ] @@ -3421,11 +3501,22 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" +[[package]] +name = "multibase" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b78c60039650ff12e140ae867ef5299a58e19dded4d334c849dc7177083667e2" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + [[package]] name = "multihash" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae32179a9904ccc6e063de8beee7f5dd55fae85ecb851ca923d55722bc28cf5d" +checksum = "f75db05d738947aa5389863aadafbcf2e509d7ba099dc2ddcdf4fc66bf7a9e03" dependencies = [ "blake2b_simd", "blake2s_simd", @@ -6759,6 +6850,7 @@ dependencies = [ "hex", "ip_network", "libp2p", + "libp2p-bitswap", "linked-hash-map", "linked_hash_set", "log", @@ -6939,6 +7031,7 @@ dependencies = [ name = "sc-rpc-api" version = "0.8.0-rc5" dependencies = [ + "cid", "derive_more", "futures 0.3.5", "jsonrpc-core", @@ -6991,6 +7084,7 @@ name = "sc-service" version = "0.8.0-rc5" dependencies = [ "async-std", + "cid", "derive_more", "directories", "exit-future", @@ -7001,6 +7095,7 @@ dependencies = [ "jsonrpc-pubsub", "lazy_static", "log", + "multihash", "netstat2", "parity-scale-codec", "parity-util-mem 0.7.0", @@ -8822,18 +8917,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.15" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012" +checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.15" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd" +checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" dependencies = [ "proc-macro2", "quote 1.0.6", @@ -9347,7 +9442,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" dependencies = [ - "rand 0.3.23", + "rand 0.7.3", ] [[package]] diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 0de17103b05a4..cf0b0234fba07 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -87,6 +87,7 @@ pub fn new_full(config: Configuration) -> Result { sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), + backend: backend.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, @@ -242,6 +243,7 @@ pub fn new_light(config: Configuration) -> Result { sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), + backend: backend.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index a47869ed83232..f6a52f93f6c00 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -169,6 +169,7 @@ pub fn new_full_base( sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), + backend: backend.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, @@ -387,6 +388,7 @@ pub fn new_light_base(config: Configuration) -> Result<( sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), + backend: backend.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, diff --git a/client/network-gossip/src/bridge.rs b/client/network-gossip/src/bridge.rs index df2a5c8e7e94a..75700ffd8bfca 100644 --- a/client/network-gossip/src/bridge.rs +++ b/client/network-gossip/src/bridge.rs @@ -210,7 +210,8 @@ impl Future for GossipEngine { this.forwarding_state = ForwardingState::Busy(to_forward.into()); }, - Event::Dht(_) => {} + Event::Dht(_) => {}, + Event::Bitswap(_) => {}, } // The network event stream closed. Do the same for [`GossipValidator`]. Poll::Ready(None) => return Poll::Ready(()), diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 11346fdd3ffc6..6ab49df6a34bb 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -59,6 +59,7 @@ unsigned-varint = { version = "0.4.0", features = ["futures", "futures-codec"] } void = "1.0.2" wasm-timer = "0.2" zeroize = "1.0.0" +libp2p-bitswap = "0.5.1" [dependencies.libp2p] version = "0.22.0" diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index 2afcd2741381f..2110d198ef59b 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -50,6 +50,8 @@ pub struct Behaviour { peer_info: peer_info::PeerInfoBehaviour, /// Discovers nodes of the network. discovery: DiscoveryBehaviour, + /// Exchanges blocks of data with other nodes. + pub bitswap: libp2p_bitswap::Bitswap, /// Block request handling. block_requests: block_requests::BlockRequests, /// Finality proof request handling. @@ -147,6 +149,9 @@ pub enum BehaviourOut { /// Event generated by a DHT. Dht(DhtEvent), + + /// Event generated by bitswap. + Bitswap(libp2p_bitswap::BitswapEvent) } impl Behaviour { @@ -169,6 +174,7 @@ impl Behaviour { finality_proof_requests, light_client_handler, events: VecDeque::new(), + bitswap: libp2p_bitswap::Bitswap::new(), role, } } @@ -259,6 +265,11 @@ impl Behaviour { pub fn light_client_request(&mut self, r: light_client_handler::Request) -> Result<(), light_client_handler::Error> { self.light_client_handler.request(r) } + + fn add_discovered_node(&mut self, peer_id: PeerId) { + self.substrate.add_discovered_nodes(iter::once(peer_id.clone())); + self.bitswap.connect(peer_id); + } } fn reported_roles_to_observed_role(local_role: &Role, remote: &PeerId, roles: Roles) -> ObservedRole { @@ -437,7 +448,7 @@ impl NetworkBehaviourEventProcess NetworkBehaviourEventProcess // implementation for `PeerInfoEvent`. } DiscoveryOut::Discovered(peer_id) => { - self.substrate.add_discovered_nodes(iter::once(peer_id)); + self.add_discovered_node(peer_id); } DiscoveryOut::ValueFound(results) => { self.events.push_back(BehaviourOut::Dht(DhtEvent::ValueFound(results))); @@ -475,6 +486,13 @@ impl NetworkBehaviourEventProcess } } +impl NetworkBehaviourEventProcess + for Behaviour { + fn inject_event(&mut self, event: libp2p_bitswap::BitswapEvent) { + self.events.push_back(BehaviourOut::Bitswap(event)); + } +} + impl Behaviour { fn poll(&mut self, _: &mut Context, _: &mut impl PollParameters) -> Poll>> { if let Some(event) = self.events.pop_front() { diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index b8e5d7582b96b..da609fbc18549 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -267,6 +267,7 @@ pub use protocol::sync::SyncState; pub use libp2p::{Multiaddr, PeerId}; #[doc(inline)] pub use libp2p::multiaddr; +pub use libp2p_bitswap::BitswapEvent; pub use sc_peerset::ReputationChange; use sp_runtime::traits::{Block as BlockT, NumberFor}; diff --git a/client/network/src/protocol/event.rs b/client/network/src/protocol/event.rs index 637bf805b5024..7886b32389936 100644 --- a/client/network/src/protocol/event.rs +++ b/client/network/src/protocol/event.rs @@ -45,6 +45,8 @@ pub enum DhtEvent { pub enum Event { /// Event generated by a DHT. Dht(DhtEvent), + /// Event generated by Bitswap. + Bitswap(libp2p_bitswap::BitswapEvent), /// Opened a substream with the given node with the given notifications protocol. /// diff --git a/client/network/src/service.rs b/client/network/src/service.rs index c11a620c56720..2076357ef4e4d 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -551,6 +551,11 @@ impl NetworkWorker { pub fn add_reserved_peer(&self, peer: String) -> Result<(), String> { self.service.add_reserved_peer(peer) } + + /// Get a mutable reference to the Bitswap behaviour. + pub fn bitswap(&mut self) -> &mut libp2p_bitswap::Bitswap { + &mut self.network_service.bitswap + } } impl NetworkService { @@ -1511,6 +1516,9 @@ impl Future for NetworkWorker { Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::Dht(ev))) => { this.event_streams.send(Event::Dht(ev)); }, + Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::Bitswap(ev))) => { + this.event_streams.send(Event::Bitswap(ev)); + }, Poll::Ready(SwarmEvent::ConnectionEstablished { peer_id, endpoint, num_established }) => { trace!(target: "sub-libp2p", "Libp2p => Connected({:?})", peer_id); @@ -1537,13 +1545,13 @@ impl Future for NetworkWorker { ConnectionError::IO(_) => "transport-error", ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( EitherError::A(EitherError::A(EitherError::B( - EitherError::A(PingFailure::Timeout)))))))) => "ping-timeout", + todo))))))) => "ping-timeout", ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( EitherError::A(EitherError::A(EitherError::A( - NotifsHandlerError::Legacy(LegacyConnectionKillError)))))))) => "force-closed", + todo))))))) => "force-closed", ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( EitherError::A(EitherError::A(EitherError::A( - NotifsHandlerError::SyncNotificationsClogged))))))) => "sync-notifications-clogged", + todo))))))) => "sync-notifications-clogged", ConnectionError::Handler(NodeHandlerWrapperError::Handler(_)) => "protocol-error", ConnectionError::Handler(NodeHandlerWrapperError::KeepAliveTimeout) => "keep-alive-timeout", }; diff --git a/client/network/src/service/out_events.rs b/client/network/src/service/out_events.rs index 1b86a5fa4317d..2eb13d2cc93f2 100644 --- a/client/network/src/service/out_events.rs +++ b/client/network/src/service/out_events.rs @@ -227,6 +227,11 @@ impl Metrics { self.events_total .with_label_values(&["dht", "sent", name]) .inc_by(num); + }, + Event::Bitswap(_) => { + self.events_total + .with_label_values(&["bitswap", "sent", name]) + .inc_by(num); } Event::NotificationStreamOpened { engine_id, .. } => { self.events_total @@ -258,6 +263,11 @@ impl Metrics { .with_label_values(&["dht", "received", name]) .inc(); } + Event::Bitswap(_) => { + self.events_total + .with_label_values(&["bitswap", "received", name]) + .inc(); + } Event::NotificationStreamOpened { engine_id, .. } => { self.events_total .with_label_values(&[&format!("notif-open-{:?}", engine_id), "received", name]) diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 7701befbf71a4..5fba7dfa33b7e 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -29,3 +29,4 @@ serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" sp-transaction-pool = { version = "2.0.0-rc5", path = "../../primitives/transaction-pool" } sp-rpc = { version = "2.0.0-rc5", path = "../../primitives/rpc" } +cid = "0.5.1" diff --git a/client/rpc-api/src/system/error.rs b/client/rpc-api/src/system/error.rs index 4897aa485cbe4..e53025550c0bb 100644 --- a/client/rpc-api/src/system/error.rs +++ b/client/rpc-api/src/system/error.rs @@ -32,6 +32,8 @@ pub enum Error { NotHealthy(Health), /// Peer argument is malformatted. MalformattedPeerArg(String), + /// CID parsing error. + CidParse(cid::Error) } impl std::error::Error for Error {} @@ -48,9 +50,14 @@ impl From for rpc::Error { data: serde_json::to_value(h).ok(), }, Error::MalformattedPeerArg(ref e) => rpc::Error { - code :rpc::ErrorCode::ServerError(BASE_ERROR + 2), + code: rpc::ErrorCode::ServerError(BASE_ERROR + 2), message: e.clone(), data: None, + }, + Error::CidParse(ref e) => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 3), + message: e.to_string(), + data: None, } } } diff --git a/client/rpc-api/src/system/mod.rs b/client/rpc-api/src/system/mod.rs index a7b746ee1b114..60aacc032492c 100644 --- a/client/rpc-api/src/system/mod.rs +++ b/client/rpc-api/src/system/mod.rs @@ -103,4 +103,13 @@ pub trait SystemApi { /// Returns the roles the node is running as. #[rpc(name = "system_nodeRoles", returns = "Vec")] fn system_node_roles(&self) -> Receiver>; + + /// Publish some data via Bitswap. + #[rpc(name = "system_bitswapPublish", returns = "String")] + fn system_bitswap_publish(&self, data: String) -> Receiver; + + /// Request some data via Bitswap. + #[rpc(name = "system_bitswapWant", returns = "()")] + fn system_bitswap_want(&self, cid: String) + -> Compat>>; } diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs index 4b8abbe144462..c593300114a2d 100644 --- a/client/rpc/src/system/mod.rs +++ b/client/rpc/src/system/mod.rs @@ -65,6 +65,8 @@ pub enum Request { NetworkAddReservedPeer(String, oneshot::Sender>), /// Must return any potential parse error. NetworkRemoveReservedPeer(String, oneshot::Sender>), + NetworkBitswapPublish(String, oneshot::Sender), + NetworkBitswapWant(String, oneshot::Sender>), /// Must return the node role. NodeRoles(oneshot::Sender>) } @@ -184,6 +186,26 @@ impl SystemApi::Number> for Sy }.boxed().compat() } + fn system_bitswap_publish(&self, data: String) -> Receiver { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NetworkBitswapPublish(data, tx)); + Receiver(Compat::new(rx)) + } + + fn system_bitswap_want(&self, cid: String) + -> Compat>> + { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NetworkBitswapWant(cid, tx)); + async move { + match rx.await { + Ok(Ok(())) => Ok(()), + Ok(Err(e)) => Err(rpc::Error::from(e)), + Err(_) => Err(rpc::Error::internal_error()), + } + }.boxed().compat() + } + fn system_node_roles(&self) -> Receiver> { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NodeRoles(tx)); diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 32f6532e7e0d2..7e52cf385682c 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -75,6 +75,8 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../.. sc-tracing = { version = "2.0.0-rc5", path = "../tracing" } tracing = "0.1.10" parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } +multihash = "0.11.2" +cid = "0.5.1" [target.'cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))'.dependencies] netstat2 = "0.8.1" diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 4c7c1f57ee04b..5eea2ba25111b 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -791,11 +791,13 @@ fn gen_handler( } /// Parameters to pass into `build_network`. -pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> { +pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl, TBackend> { /// The service configuration. pub config: &'a Configuration, /// A shared client returned by `new_full_parts`/`new_light_parts`. pub client: Arc, + /// A shared backend returned by `new_full_parts`/`new_light_parts`. + pub backend: Arc, /// A shared transaction pool. pub transaction_pool: Arc, /// A handle for spawning tasks. @@ -815,8 +817,8 @@ pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> { } /// Build the network service, the network status sinks and an RPC sender. -pub fn build_network( - params: BuildNetworkParams +pub fn build_network( + params: BuildNetworkParams ) -> Result< ( Arc::Hash>>, @@ -832,9 +834,10 @@ pub fn build_network( HeaderBackend + BlockchainEvents + 'static, TExPool: MaintainedTransactionPool::Hash> + 'static, TImpQu: ImportQueue + 'static, + TBackend: Send + Sync + sc_client_api::AuxStore + 'static, { let BuildNetworkParams { - config, client, transaction_pool, spawn_handle, import_queue, on_demand, + config, client, backend, transaction_pool, spawn_handle, import_queue, on_demand, block_announce_validator_builder, finality_proof_request_builder, finality_proof_provider, } = params; @@ -898,6 +901,7 @@ pub fn build_network( system_rpc_rx, has_bootnodes, config.announce_block, + backend, ); // The network worker is responsible for gathering all network messages and processing diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 40826a70d4501..3626940fc543a 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -20,7 +20,7 @@ //! Manages communication between them. #![warn(missing_docs)] -#![recursion_limit = "1024"] +#![recursion_limit = "2048"] pub mod config; pub mod chain_ops; @@ -181,7 +181,8 @@ pub struct PartialComponents, - H: sc_network::ExHashT + H: sc_network::ExHashT, + BE: sc_client_api::AuxStore, > ( role: Role, mut network: sc_network::NetworkWorker, @@ -190,6 +191,7 @@ async fn build_network_future< mut rpc_rx: TracingUnboundedReceiver>, should_have_peers: bool, announce_imported_blocks: bool, + backend: Arc, ) { let mut imported_blocks_stream = client.import_notification_stream().fuse(); @@ -212,6 +214,14 @@ async fn build_network_future< }).fuse() }; + + let mut bitswap_stream = network.service().event_stream("bitswap") + .filter_map(|event| futures::future::ready(if let sc_network::Event::Bitswap(event) = event { + Some(event) + } else { + None + })).fuse(); + loop { futures::select!{ // List of blocks that the client has imported. @@ -304,6 +314,32 @@ async fn build_network_future< }; let _ = sender.send(vec![node_role]); + }, + sc_rpc::system::Request::NetworkBitswapPublish(data, sender) => { + let hash = multihash::Code::Sha2_256.digest(data.as_bytes()); + let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); + + let cid_bytes = &cid.to_bytes()[..]; + let res = backend.insert_aux(std::iter::once(&(cid_bytes, data.as_bytes())), std::iter::empty()); + + if let Err(e) = res { + warn!("{:?}", e); + } + + network.bitswap().send_block_all(&cid, data.as_bytes()); + + let _ = sender.send(cid.to_string()); + }, + sc_rpc::system::Request::NetworkBitswapWant(cid, sender) => { + let _ = match cid.parse() { + Ok(cid) => { + network.bitswap().want_block(cid, 100); + sender.send(Ok(())) + }, + Err(e) => sender.send(Err(sc_rpc::system::error::Error::CidParse( + e, + ))) + }; } } } @@ -328,6 +364,30 @@ async fn build_network_future< let state = network.network_state(); ready_sink.send((status, state)); } + + event = bitswap_stream.select_next_some() => { + match event { + sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { + let cid_bytes = &cid.to_bytes()[..]; + let res = backend.insert_aux(std::iter::once(&(cid_bytes, &data[..])), std::iter::empty()); + + if let Err(e) = res { + warn!("{:?}", e); + } + }, + sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { + match backend.get_aux(&cid.to_bytes()[..]) { + Ok(Some(data)) => { + network.bitswap().send_block(&peer_id, cid, data.into_boxed_slice()); + }, + Ok(None) => warn!("No data for {:?}", cid), + Err(e) => warn!("{:?}", e) + } + } + sc_network::BitswapEvent::ReceivedCancel(_, _) => {}, + _ => {} + } + } } } } From d5d3130009b33bcb3df22ad1a711cb856b4a1d99 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Sun, 2 Aug 2020 17:52:07 +0200 Subject: [PATCH 02/18] Add networking tests --- Cargo.lock | 3 +- client/network/src/service.rs | 12 +-- client/network/src/service/tests.rs | 2 + client/network/test/Cargo.toml | 2 + client/network/test/src/bitswap.rs | 140 ++++++++++++++++++++++++++++ client/network/test/src/lib.rs | 57 ++++++++++- client/rpc-api/Cargo.toml | 1 - client/rpc-api/src/system/error.rs | 7 -- client/rpc-api/src/system/mod.rs | 9 -- client/rpc/src/system/mod.rs | 22 ----- client/service/src/lib.rs | 30 +----- 11 files changed, 210 insertions(+), 75 deletions(-) create mode 100644 client/network/test/src/bitswap.rs diff --git a/Cargo.lock b/Cargo.lock index 02dcee6efa24d..9a5b2ef61b72a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6912,11 +6912,13 @@ dependencies = [ name = "sc-network-test" version = "0.8.0-rc5" dependencies = [ + "cid", "env_logger 0.7.1", "futures 0.3.5", "futures-timer 3.0.2", "libp2p", "log", + "multihash", "parking_lot 0.10.2", "rand 0.7.3", "sc-block-builder", @@ -7031,7 +7033,6 @@ dependencies = [ name = "sc-rpc-api" version = "0.8.0-rc5" dependencies = [ - "cid", "derive_more", "futures 0.3.5", "jsonrpc-core", diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 2076357ef4e4d..0593ca44fdb69 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -1544,14 +1544,14 @@ impl Future for NetworkWorker { let reason = match cause { ConnectionError::IO(_) => "transport-error", ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( - EitherError::A(EitherError::A(EitherError::B( - todo))))))) => "ping-timeout", + EitherError::A(EitherError::A(EitherError::A(EitherError::B( + EitherError::A(PingFailure::Timeout))))))))) => "ping-timeout", ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( - EitherError::A(EitherError::A(EitherError::A( - todo))))))) => "force-closed", + EitherError::A(EitherError::A(EitherError::A(EitherError::A( + NotifsHandlerError::Legacy(LegacyConnectionKillError))))))))) => "force-closed", ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( - EitherError::A(EitherError::A(EitherError::A( - todo))))))) => "sync-notifications-clogged", + EitherError::A(EitherError::A(EitherError::A(EitherError::A( + NotifsHandlerError::SyncNotificationsClogged)))))))) => "sync-notifications-clogged", ConnectionError::Handler(NodeHandlerWrapperError::Handler(_)) => "protocol-error", ConnectionError::Handler(NodeHandlerWrapperError::KeepAliveTimeout) => "keep-alive-timeout", }; diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs index f0982e30d9921..7bb6014ace92a 100644 --- a/client/network/src/service/tests.rs +++ b/client/network/src/service/tests.rs @@ -270,6 +270,8 @@ fn notifications_state_consistent() { // Add new events here. future::Either::Left(Event::Dht(_)) => {} future::Either::Right(Event::Dht(_)) => {} + future::Either::Left(Event::Bitswap(_)) => {} + future::Either::Right(Event::Bitswap(_)) => {} }; } }); diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index eb7788f541638..9645c3c2d304f 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -33,3 +33,5 @@ substrate-test-runtime-client = { version = "2.0.0-rc5", path = "../../../test-u substrate-test-runtime = { version = "2.0.0-rc5", path = "../../../test-utils/runtime" } tempfile = "3.1.0" sc-service = { version = "0.8.0-rc5", default-features = false, features = ["test-helpers"], path = "../../service" } +cid = "0.5.1" +multihash = "0.11.2" diff --git a/client/network/test/src/bitswap.rs b/client/network/test/src/bitswap.rs new file mode 100644 index 0000000000000..b5789de9d885e --- /dev/null +++ b/client/network/test/src/bitswap.rs @@ -0,0 +1,140 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use futures::executor::block_on; +use super::*; + +#[test] +fn test_bitswap_peers_connect() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + net.block_until_connected(); + + for peer in 0 .. 3 { + assert_eq!(net.peer(peer).network.bitswap().peers().count(), 2); + } +} + +#[test] +fn test_bitswap_peers_sending_and_cancelling_wants_works() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + let cid: cid::Cid = "bafkreiaapsxdkhlebw676iqic2r7fmq3gngqqcvfwh7aisvnxl7zrt24em".parse().unwrap(); + + net.peer(0).network.bitswap().want_block(cid.clone(), 0); + + let peer_0 = [&net.peer(0).id()]; + + block_on(futures::future::poll_fn::<(), _>(|cx| { + net.poll(cx); + for peer in 1..3 { + if net.peer(peer).network.bitswap().peers_want(&cid).collect::>() != peer_0 { + return Poll::Pending + } + } + Poll::Ready(()) + })); + + net.peer(0).network.bitswap().cancel_block(&cid); + + wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); +} + +fn wait_until_x_peers_want_cid(net: &mut TestNet, x: usize, peers: std::ops::Range, cid: &cid::Cid) { + block_on(futures::future::poll_fn::<(), _>(|cx| { + net.poll(cx); + for peer in peers.clone() { + if net.peer(peer).network.bitswap().peers_want(cid).count() != x { + return Poll::Pending + } + } + Poll::Ready(()) + })); +} + +#[test] +fn test_bitswap_sending_blocks_works() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + let block = "abcdefghi".as_bytes(); + + let hash = multihash::Code::Sha2_256.digest(block); + let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); + + net.peer(0).network.bitswap().want_block(cid.clone(), 0); + + wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); + + net.peer(2).network.bitswap().send_block_all(&cid, block); + + wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); + + assert_eq!( + net.peer(0).client.get_aux(&cid.to_bytes()).unwrap(), + Some(block.to_vec()) + ); + + assert_eq!( + net.peer(1).client.get_aux(&cid.to_bytes()).unwrap(), + None + ); + + assert_eq!( + net.peer(2).client.get_aux(&cid.to_bytes()).unwrap(), + None + ); +} + +#[test] +fn test_bitswap_sending_blocks_from_aux_store_works() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + let block = "abcdefghi".as_bytes(); + + let hash = multihash::Code::Sha2_256.digest(block); + let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); + + net.peer(2).client.insert_aux(&cid.to_bytes(), block).unwrap(); + + net.block_until_connected(); + + net.peer(0).network.bitswap().want_block(cid.clone(), 0); + + wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); + + wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); + + assert_eq!( + net.peer(0).client.get_aux(&cid.to_bytes()).unwrap(), + Some(block.to_vec()) + ); + + assert_eq!( + net.peer(1).client.get_aux(&cid.to_bytes()).unwrap(), + None + ); + + assert_eq!( + net.peer(2).client.get_aux(&cid.to_bytes()).unwrap(), + Some(block.to_vec()) + ); +} diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 35587cbdc08b3..4a49496b4d8cc 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -21,11 +21,13 @@ mod block_import; #[cfg(test)] mod sync; +#[cfg(test)] +mod bitswap; use std::{collections::HashMap, pin::Pin, sync::Arc, marker::PhantomData, task::{Poll, Context as FutureContext}}; use libp2p::build_multiaddr; -use log::trace; +use log::{trace, warn}; use sc_network::config::FinalityProofProvider; use sp_blockchain::{ HeaderBackend, Result as ClientResult, @@ -162,6 +164,17 @@ impl PeersClient { } } + fn insert_aux(&self, key: &[u8], value: &[u8]) -> ClientResult<()> { + match *self { + PeersClient::Full(ref client, ref _backend) => { + client.insert_aux(std::iter::once(&(key, value)), std::iter::empty()) + }, + PeersClient::Light(ref client, ref _backend) => { + client.insert_aux(std::iter::once(&(key, value)), std::iter::empty()) + } + } + } + pub fn info(&self) -> BlockchainInfo { match *self { PeersClient::Full(ref client, ref _backend) => client.chain_info(), @@ -224,6 +237,7 @@ pub struct Peer { network: NetworkWorker::Hash>, imported_blocks_stream: Pin> + Send>>, finality_notification_stream: Pin> + Send>>, + bitswap_stream: Pin + Send>>, } impl Peer { @@ -690,6 +704,14 @@ pub trait TestNetFactory: Sized { let imported_blocks_stream = Box::pin(client.import_notification_stream().fuse()); let finality_notification_stream = Box::pin(client.finality_notification_stream().fuse()); + let bitswap_stream = network.service().event_stream("bitswap") + .filter_map(|event| futures::future::ready(if let sc_network::Event::Bitswap(event) = event { + Some(event) + } else { + None + })) + .boxed(); + peers.push(Peer { data, client: PeersClient::Full(client, backend.clone()), @@ -700,6 +722,7 @@ pub trait TestNetFactory: Sized { block_import, verifier, network, + bitswap_stream, }); }); } @@ -769,6 +792,14 @@ pub trait TestNetFactory: Sized { let imported_blocks_stream = Box::pin(client.import_notification_stream().fuse()); let finality_notification_stream = Box::pin(client.finality_notification_stream().fuse()); + let bitswap_stream = network.service().event_stream("bitswap") + .filter_map(|event| futures::future::ready(if let sc_network::Event::Bitswap(event) = event { + Some(event) + } else { + None + })) + .boxed(); + peers.push(Peer { data, verifier, @@ -779,6 +810,7 @@ pub trait TestNetFactory: Sized { imported_blocks_stream, finality_notification_stream, network, + bitswap_stream, }); }); } @@ -884,6 +916,29 @@ pub trait TestNetFactory: Sized { if let Some(notification) = last { peer.network.on_block_finalized(notification.hash, notification.header); } + + while let Poll::Ready(Some(event)) = peer.bitswap_stream.as_mut().poll_next(cx) { + match event { + sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { + let cid_bytes = &cid.to_bytes()[..]; + let res = peer.client.insert_aux(cid_bytes, &data[..]); + + if let Err(e) = res { + warn!("{:?}", e); + } + }, + sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { + match peer.client.get_aux(&cid.to_bytes()[..]) { + Ok(Some(data)) => { + peer.network.bitswap().send_block(&peer_id, cid, data.into_boxed_slice()); + }, + Ok(None) => warn!("No data for {:?}", cid), + Err(e) => warn!("{:?}", e) + } + } + sc_network::BitswapEvent::ReceivedCancel(_, _) => {}, + } + } } }); } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 5fba7dfa33b7e..7701befbf71a4 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -29,4 +29,3 @@ serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" sp-transaction-pool = { version = "2.0.0-rc5", path = "../../primitives/transaction-pool" } sp-rpc = { version = "2.0.0-rc5", path = "../../primitives/rpc" } -cid = "0.5.1" diff --git a/client/rpc-api/src/system/error.rs b/client/rpc-api/src/system/error.rs index e53025550c0bb..198cc374e6df9 100644 --- a/client/rpc-api/src/system/error.rs +++ b/client/rpc-api/src/system/error.rs @@ -32,8 +32,6 @@ pub enum Error { NotHealthy(Health), /// Peer argument is malformatted. MalformattedPeerArg(String), - /// CID parsing error. - CidParse(cid::Error) } impl std::error::Error for Error {} @@ -53,11 +51,6 @@ impl From for rpc::Error { code: rpc::ErrorCode::ServerError(BASE_ERROR + 2), message: e.clone(), data: None, - }, - Error::CidParse(ref e) => rpc::Error { - code: rpc::ErrorCode::ServerError(BASE_ERROR + 3), - message: e.to_string(), - data: None, } } } diff --git a/client/rpc-api/src/system/mod.rs b/client/rpc-api/src/system/mod.rs index 60aacc032492c..a7b746ee1b114 100644 --- a/client/rpc-api/src/system/mod.rs +++ b/client/rpc-api/src/system/mod.rs @@ -103,13 +103,4 @@ pub trait SystemApi { /// Returns the roles the node is running as. #[rpc(name = "system_nodeRoles", returns = "Vec")] fn system_node_roles(&self) -> Receiver>; - - /// Publish some data via Bitswap. - #[rpc(name = "system_bitswapPublish", returns = "String")] - fn system_bitswap_publish(&self, data: String) -> Receiver; - - /// Request some data via Bitswap. - #[rpc(name = "system_bitswapWant", returns = "()")] - fn system_bitswap_want(&self, cid: String) - -> Compat>>; } diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs index c593300114a2d..4b8abbe144462 100644 --- a/client/rpc/src/system/mod.rs +++ b/client/rpc/src/system/mod.rs @@ -65,8 +65,6 @@ pub enum Request { NetworkAddReservedPeer(String, oneshot::Sender>), /// Must return any potential parse error. NetworkRemoveReservedPeer(String, oneshot::Sender>), - NetworkBitswapPublish(String, oneshot::Sender), - NetworkBitswapWant(String, oneshot::Sender>), /// Must return the node role. NodeRoles(oneshot::Sender>) } @@ -186,26 +184,6 @@ impl SystemApi::Number> for Sy }.boxed().compat() } - fn system_bitswap_publish(&self, data: String) -> Receiver { - let (tx, rx) = oneshot::channel(); - let _ = self.send_back.unbounded_send(Request::NetworkBitswapPublish(data, tx)); - Receiver(Compat::new(rx)) - } - - fn system_bitswap_want(&self, cid: String) - -> Compat>> - { - let (tx, rx) = oneshot::channel(); - let _ = self.send_back.unbounded_send(Request::NetworkBitswapWant(cid, tx)); - async move { - match rx.await { - Ok(Ok(())) => Ok(()), - Ok(Err(e)) => Err(rpc::Error::from(e)), - Err(_) => Err(rpc::Error::internal_error()), - } - }.boxed().compat() - } - fn system_node_roles(&self) -> Receiver> { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NodeRoles(tx)); diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 3626940fc543a..94f6bb5abd1c2 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -215,7 +215,7 @@ async fn build_network_future< }; - let mut bitswap_stream = network.service().event_stream("bitswap") + let mut bitswap_events = network.service().event_stream("bitswap") .filter_map(|event| futures::future::ready(if let sc_network::Event::Bitswap(event) = event { Some(event) } else { @@ -314,32 +314,6 @@ async fn build_network_future< }; let _ = sender.send(vec![node_role]); - }, - sc_rpc::system::Request::NetworkBitswapPublish(data, sender) => { - let hash = multihash::Code::Sha2_256.digest(data.as_bytes()); - let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); - - let cid_bytes = &cid.to_bytes()[..]; - let res = backend.insert_aux(std::iter::once(&(cid_bytes, data.as_bytes())), std::iter::empty()); - - if let Err(e) = res { - warn!("{:?}", e); - } - - network.bitswap().send_block_all(&cid, data.as_bytes()); - - let _ = sender.send(cid.to_string()); - }, - sc_rpc::system::Request::NetworkBitswapWant(cid, sender) => { - let _ = match cid.parse() { - Ok(cid) => { - network.bitswap().want_block(cid, 100); - sender.send(Ok(())) - }, - Err(e) => sender.send(Err(sc_rpc::system::error::Error::CidParse( - e, - ))) - }; } } } @@ -365,7 +339,7 @@ async fn build_network_future< ready_sink.send((status, state)); } - event = bitswap_stream.select_next_some() => { + event = bitswap_events.select_next_some() => { match event { sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { let cid_bytes = &cid.to_bytes()[..]; From 6fa276da0f4d58c856b6100efbe81510246c9e19 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Mon, 3 Aug 2020 09:51:31 +0200 Subject: [PATCH 03/18] Reindent bitswap tests using tabs --- client/network/test/src/bitswap.rs | 112 ++++++++++++++--------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/client/network/test/src/bitswap.rs b/client/network/test/src/bitswap.rs index b5789de9d885e..d17625e62da5b 100644 --- a/client/network/test/src/bitswap.rs +++ b/client/network/test/src/bitswap.rs @@ -22,27 +22,27 @@ use super::*; #[test] fn test_bitswap_peers_connect() { let _ = ::env_logger::try_init(); - let mut net = TestNet::new(3); - - net.block_until_connected(); + let mut net = TestNet::new(3); + + net.block_until_connected(); - for peer in 0 .. 3 { - assert_eq!(net.peer(peer).network.bitswap().peers().count(), 2); - } + for peer in 0 .. 3 { + assert_eq!(net.peer(peer).network.bitswap().peers().count(), 2); + } } #[test] fn test_bitswap_peers_sending_and_cancelling_wants_works() { let _ = ::env_logger::try_init(); - let mut net = TestNet::new(3); + let mut net = TestNet::new(3); - let cid: cid::Cid = "bafkreiaapsxdkhlebw676iqic2r7fmq3gngqqcvfwh7aisvnxl7zrt24em".parse().unwrap(); - - net.peer(0).network.bitswap().want_block(cid.clone(), 0); + let cid: cid::Cid = "bafkreiaapsxdkhlebw676iqic2r7fmq3gngqqcvfwh7aisvnxl7zrt24em".parse().unwrap(); + + net.peer(0).network.bitswap().want_block(cid.clone(), 0); - let peer_0 = [&net.peer(0).id()]; + let peer_0 = [&net.peer(0).id()]; - block_on(futures::future::poll_fn::<(), _>(|cx| { + block_on(futures::future::poll_fn::<(), _>(|cx| { net.poll(cx); for peer in 1..3 { if net.peer(peer).network.bitswap().peers_want(&cid).collect::>() != peer_0 { @@ -52,13 +52,13 @@ fn test_bitswap_peers_sending_and_cancelling_wants_works() { Poll::Ready(()) })); - net.peer(0).network.bitswap().cancel_block(&cid); + net.peer(0).network.bitswap().cancel_block(&cid); - wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); + wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); } fn wait_until_x_peers_want_cid(net: &mut TestNet, x: usize, peers: std::ops::Range, cid: &cid::Cid) { - block_on(futures::future::poll_fn::<(), _>(|cx| { + block_on(futures::future::poll_fn::<(), _>(|cx| { net.poll(cx); for peer in peers.clone() { if net.peer(peer).network.bitswap().peers_want(cid).count() != x { @@ -72,69 +72,69 @@ fn wait_until_x_peers_want_cid(net: &mut TestNet, x: usize, peers: std::ops::Ran #[test] fn test_bitswap_sending_blocks_works() { let _ = ::env_logger::try_init(); - let mut net = TestNet::new(3); + let mut net = TestNet::new(3); - let block = "abcdefghi".as_bytes(); - - let hash = multihash::Code::Sha2_256.digest(block); + let block = "abcdefghi".as_bytes(); + + let hash = multihash::Code::Sha2_256.digest(block); let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); - net.peer(0).network.bitswap().want_block(cid.clone(), 0); + net.peer(0).network.bitswap().want_block(cid.clone(), 0); - wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); + wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); - net.peer(2).network.bitswap().send_block_all(&cid, block); + net.peer(2).network.bitswap().send_block_all(&cid, block); - wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); + wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); - assert_eq!( - net.peer(0).client.get_aux(&cid.to_bytes()).unwrap(), - Some(block.to_vec()) - ); + assert_eq!( + net.peer(0).client.get_aux(&cid.to_bytes()).unwrap(), + Some(block.to_vec()) + ); - assert_eq!( - net.peer(1).client.get_aux(&cid.to_bytes()).unwrap(), - None - ); + assert_eq!( + net.peer(1).client.get_aux(&cid.to_bytes()).unwrap(), + None + ); - assert_eq!( - net.peer(2).client.get_aux(&cid.to_bytes()).unwrap(), - None - ); + assert_eq!( + net.peer(2).client.get_aux(&cid.to_bytes()).unwrap(), + None + ); } #[test] fn test_bitswap_sending_blocks_from_aux_store_works() { let _ = ::env_logger::try_init(); - let mut net = TestNet::new(3); + let mut net = TestNet::new(3); - let block = "abcdefghi".as_bytes(); - - let hash = multihash::Code::Sha2_256.digest(block); + let block = "abcdefghi".as_bytes(); + + let hash = multihash::Code::Sha2_256.digest(block); let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); - net.peer(2).client.insert_aux(&cid.to_bytes(), block).unwrap(); + net.peer(2).client.insert_aux(&cid.to_bytes(), block).unwrap(); - net.block_until_connected(); + net.block_until_connected(); - net.peer(0).network.bitswap().want_block(cid.clone(), 0); + net.peer(0).network.bitswap().want_block(cid.clone(), 0); - wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); + wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); - wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); + wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); - assert_eq!( - net.peer(0).client.get_aux(&cid.to_bytes()).unwrap(), - Some(block.to_vec()) - ); + assert_eq!( + net.peer(0).client.get_aux(&cid.to_bytes()).unwrap(), + Some(block.to_vec()) + ); - assert_eq!( - net.peer(1).client.get_aux(&cid.to_bytes()).unwrap(), - None - ); + assert_eq!( + net.peer(1).client.get_aux(&cid.to_bytes()).unwrap(), + None + ); - assert_eq!( - net.peer(2).client.get_aux(&cid.to_bytes()).unwrap(), - Some(block.to_vec()) - ); + assert_eq!( + net.peer(2).client.get_aux(&cid.to_bytes()).unwrap(), + Some(block.to_vec()) + ); } From 471b17173a5deef26866467cec1c5ca626baee05 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Mon, 3 Aug 2020 11:13:50 +0200 Subject: [PATCH 04/18] Use OffchainStorage instead of AuxStore --- Cargo.lock | 1 + client/network/src/service.rs | 20 ++++++++ client/network/test/Cargo.toml | 1 + client/network/test/src/bitswap.rs | 17 +++---- client/network/test/src/lib.rs | 75 +++++++++++++++++++----------- client/service/src/builder.rs | 2 +- client/service/src/lib.rs | 24 ++-------- 7 files changed, 83 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89a8385592802..b537166fbd8a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6938,6 +6938,7 @@ dependencies = [ "rand 0.7.3", "sc-block-builder", "sc-client-api", + "sc-client-db", "sc-consensus", "sc-network", "sc-service", diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 61c738300350b..d614be0276e17 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -61,6 +61,7 @@ use sp_runtime::{ ConsensusEngineId, }; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; +use sp_core::offchain::OffchainStorage; use std::{ borrow::{Borrow, Cow}, collections::{HashMap, HashSet}, @@ -557,6 +558,25 @@ impl NetworkWorker { pub fn bitswap(&mut self) -> &mut libp2p_bitswap::Bitswap { &mut self.network_service.bitswap } + + /// Handle a `BitswapEvent`, reading and writing from the `OffchainStorage`. + pub fn handle_bitswap_event( + &mut self, event: libp2p_bitswap::BitswapEvent, mut storage: S, + ) { + match event { + libp2p_bitswap::BitswapEvent::ReceivedBlock(_, cid, data) => { + let cid_bytes = &cid.to_bytes()[..]; + storage.set(b"bitswap", cid_bytes, &data[..]); + }, + libp2p_bitswap::BitswapEvent::ReceivedWant(peer_id, cid, _) => { + if let Some(data) = storage.get(b"bitswap", &cid.to_bytes()[..]) { + self.bitswap().send_block(&peer_id, cid, data.into_boxed_slice()); + } + } + libp2p_bitswap::BitswapEvent::ReceivedCancel(_, _) => {}, + } + } + } impl NetworkService { diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 9645c3c2d304f..b9548f173a21a 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -23,6 +23,7 @@ libp2p = { version = "0.22.0", default-features = false } sp-consensus = { version = "0.8.0-rc5", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.8.0-rc5", path = "../../../client/consensus/common" } sc-client-api = { version = "2.0.0-rc5", path = "../../api" } +sc-client-db = { version = "0.8.0-rc5", path = "../../db" } sp-blockchain = { version = "2.0.0-rc5", path = "../../../primitives/blockchain" } sp-runtime = { version = "2.0.0-rc5", path = "../../../primitives/runtime" } sp-core = { version = "2.0.0-rc5", path = "../../../primitives/core" } diff --git a/client/network/test/src/bitswap.rs b/client/network/test/src/bitswap.rs index d17625e62da5b..a05f9b5526b15 100644 --- a/client/network/test/src/bitswap.rs +++ b/client/network/test/src/bitswap.rs @@ -18,6 +18,7 @@ use futures::executor::block_on; use super::*; +use sp_core::offchain::OffchainStorage; #[test] fn test_bitswap_peers_connect() { @@ -88,23 +89,23 @@ fn test_bitswap_sending_blocks_works() { wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); assert_eq!( - net.peer(0).client.get_aux(&cid.to_bytes()).unwrap(), + net.peer(0).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), Some(block.to_vec()) ); assert_eq!( - net.peer(1).client.get_aux(&cid.to_bytes()).unwrap(), + net.peer(1).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), None ); assert_eq!( - net.peer(2).client.get_aux(&cid.to_bytes()).unwrap(), + net.peer(2).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), None ); } #[test] -fn test_bitswap_sending_blocks_from_aux_store_works() { +fn test_bitswap_sending_blocks_from_store_works() { let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); @@ -113,7 +114,7 @@ fn test_bitswap_sending_blocks_from_aux_store_works() { let hash = multihash::Code::Sha2_256.digest(block); let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); - net.peer(2).client.insert_aux(&cid.to_bytes(), block).unwrap(); + net.peer(2).client.offchain_storage().unwrap().set(b"bitswap", &cid.to_bytes(), block); net.block_until_connected(); @@ -124,17 +125,17 @@ fn test_bitswap_sending_blocks_from_aux_store_works() { wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); assert_eq!( - net.peer(0).client.get_aux(&cid.to_bytes()).unwrap(), + net.peer(0).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), Some(block.to_vec()) ); assert_eq!( - net.peer(1).client.get_aux(&cid.to_bytes()).unwrap(), + net.peer(1).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), None ); assert_eq!( - net.peer(2).client.get_aux(&cid.to_bytes()).unwrap(), + net.peer(2).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), Some(block.to_vec()) ); } diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 4a49496b4d8cc..af648d3fbe8fe 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -27,7 +27,7 @@ mod bitswap; use std::{collections::HashMap, pin::Pin, sync::Arc, marker::PhantomData, task::{Poll, Context as FutureContext}}; use libp2p::build_multiaddr; -use log::{trace, warn}; +use log::trace; use sc_network::config::FinalityProofProvider; use sp_blockchain::{ HeaderBackend, Result as ClientResult, @@ -164,14 +164,10 @@ impl PeersClient { } } - fn insert_aux(&self, key: &[u8], value: &[u8]) -> ClientResult<()> { + fn offchain_storage(&self) -> Option { match *self { - PeersClient::Full(ref client, ref _backend) => { - client.insert_aux(std::iter::once(&(key, value)), std::iter::empty()) - }, - PeersClient::Light(ref client, ref _backend) => { - client.insert_aux(std::iter::once(&(key, value)), std::iter::empty()) - } + PeersClient::Full(ref _client, ref backend) => backend.offchain_storage().map(PeerOffchainStorage::Full), + PeersClient::Light(ref _client, ref backend) => backend.offchain_storage().map(PeerOffchainStorage::Light), } } @@ -223,6 +219,48 @@ impl PeersClient { } } +#[derive(Clone)] +enum PeerOffchainStorage { + Full(sc_client_db::offchain::LocalStorage), + Light(sp_core::offchain::storage::InMemOffchainStorage), +} + +impl sp_core::offchain::OffchainStorage for PeerOffchainStorage { + fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { + match self { + Self::Full(storage) => storage.set(prefix, key, value), + Self::Light(storage) => storage.set(prefix, key, value), + } + } + + fn remove(&mut self, prefix: &[u8], key: &[u8]) { + match self { + Self::Full(storage) => storage.remove(prefix, key), + Self::Light(storage) => storage.remove(prefix, key), + } + } + + fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { + match self { + Self::Full(storage) => storage.get(prefix, key), + Self::Light(storage) => storage.get(prefix, key), + } + } + + fn compare_and_set( + &mut self, + prefix: &[u8], + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8] + ) -> bool { + match self { + Self::Full(storage) => storage.compare_and_set(prefix, key, old_value, new_value), + Self::Light(storage) => storage.compare_and_set(prefix, key, old_value, new_value), + } + } +} + pub struct Peer { pub data: D, client: PeersClient, @@ -918,25 +956,8 @@ pub trait TestNetFactory: Sized { } while let Poll::Ready(Some(event)) = peer.bitswap_stream.as_mut().poll_next(cx) { - match event { - sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { - let cid_bytes = &cid.to_bytes()[..]; - let res = peer.client.insert_aux(cid_bytes, &data[..]); - - if let Err(e) = res { - warn!("{:?}", e); - } - }, - sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { - match peer.client.get_aux(&cid.to_bytes()[..]) { - Ok(Some(data)) => { - peer.network.bitswap().send_block(&peer_id, cid, data.into_boxed_slice()); - }, - Ok(None) => warn!("No data for {:?}", cid), - Err(e) => warn!("{:?}", e) - } - } - sc_network::BitswapEvent::ReceivedCancel(_, _) => {}, + if let Some(offchain) = peer.client.offchain_storage() { + peer.network.handle_bitswap_event(event, offchain); } } } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 5eea2ba25111b..26d7b04fb2e2f 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -834,7 +834,7 @@ pub fn build_network( HeaderBackend + BlockchainEvents + 'static, TExPool: MaintainedTransactionPool::Hash> + 'static, TImpQu: ImportQueue + 'static, - TBackend: Send + Sync + sc_client_api::AuxStore + 'static, + TBackend: Send + Sync + sc_client_api::Backend + 'static, { let BuildNetworkParams { config, client, backend, transaction_pool, spawn_handle, import_queue, on_demand, diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 94f6bb5abd1c2..5ebe2570e23fb 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -182,7 +182,7 @@ async fn build_network_future< B: BlockT, C: BlockchainEvents, H: sc_network::ExHashT, - BE: sc_client_api::AuxStore, + BE: sc_client_api::Backend, > ( role: Role, mut network: sc_network::NetworkWorker, @@ -340,26 +340,8 @@ async fn build_network_future< } event = bitswap_events.select_next_some() => { - match event { - sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { - let cid_bytes = &cid.to_bytes()[..]; - let res = backend.insert_aux(std::iter::once(&(cid_bytes, &data[..])), std::iter::empty()); - - if let Err(e) = res { - warn!("{:?}", e); - } - }, - sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { - match backend.get_aux(&cid.to_bytes()[..]) { - Ok(Some(data)) => { - network.bitswap().send_block(&peer_id, cid, data.into_boxed_slice()); - }, - Ok(None) => warn!("No data for {:?}", cid), - Err(e) => warn!("{:?}", e) - } - } - sc_network::BitswapEvent::ReceivedCancel(_, _) => {}, - _ => {} + if let Some(offchain) = backend.offchain_storage() { + network.handle_bitswap_event(event, offchain); } } } From 83bc9c61984c2a9a163e7141a809f6c39e0b92e4 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Mon, 3 Aug 2020 13:56:46 +0200 Subject: [PATCH 05/18] Apply suggestions --- Cargo.lock | 1 + client/network/Cargo.toml | 1 + client/network/src/behaviour.rs | 77 +++++++++++++++++++++++++--- client/network/src/lib.rs | 2 +- client/network/src/protocol/event.rs | 3 +- client/network/src/service.rs | 26 ++-------- client/network/test/src/bitswap.rs | 18 +++---- client/network/test/src/lib.rs | 2 +- client/service/src/lib.rs | 23 ++++++++- 9 files changed, 109 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b537166fbd8a2..d498e0e1bc8eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6853,6 +6853,7 @@ dependencies = [ "bitflags", "bs58", "bytes 0.5.4", + "cid", "derive_more", "either", "env_logger 0.7.1", diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 6ab49df6a34bb..035c1d18575f8 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -60,6 +60,7 @@ void = "1.0.2" wasm-timer = "0.2" zeroize = "1.0.0" libp2p-bitswap = "0.5.1" +cid = "0.5.1" [dependencies.libp2p] version = "0.22.0" diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index 104da5fa874bb..54e3b62af3a6a 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -51,7 +51,7 @@ pub struct Behaviour { /// Discovers nodes of the network. discovery: DiscoveryBehaviour, /// Exchanges blocks of data with other nodes. - pub bitswap: libp2p_bitswap::Bitswap, + bitswap: libp2p_bitswap::Bitswap, /// Block request handling. block_requests: block_requests::BlockRequests, /// Finality proof request handling. @@ -152,7 +152,56 @@ pub enum BehaviourOut { Dht(DhtEvent, Duration), /// Event generated by bitswap. - Bitswap(libp2p_bitswap::BitswapEvent) + Bitswap(BitswapEvent) +} + +/// An event generated by bitswap. +#[derive(Clone, Debug)] +pub enum BitswapEvent { + /// A block was received. + ReceivedBlock(PeerId, cid::Cid, Box<[u8]>), + /// A WANT request was received. + ReceivedWant(PeerId, cid::Cid, i32), +} + +/// An opaque API used to interact with bitswap. +pub struct BitswapApi<'a>(&'a mut libp2p_bitswap::Bitswap); + +impl<'a> BitswapApi<'a> { + /// Send a block to a peer. + pub fn send_block(&mut self, peer_id: &PeerId, cid: cid::Cid, data: Box<[u8]>) { + self.0.send_block(peer_id, cid, data) + } + + /// Send a block to all peers that have the block in their wantlist. + pub fn send_block_all(&mut self, cid: &cid::Cid, data: &[u8]) { + self.0.send_block_all(cid, data) + } + + /// Send a WANT request to all peers for a block. + pub fn want_block(&mut self, cid: cid::Cid, priority: i32) { + self.0.want_block(cid, priority) + } + + /// Cancel a WANT request. + pub fn cancel_block(&mut self, cid: &cid::Cid) { + self.0.cancel_block(cid) + } + + /// Get the number of peers we are connected to. + pub fn num_peers(&self) -> usize { + self.0.peers().count() + } + + /// Get the number of peers who want a block. + pub fn num_peers_want(&self, cid: &cid::Cid) -> usize { + self.0.peers_want(cid).count() + } + + /// Get if a specific peer wants a block. + pub fn peer_wants_cid(&self, peer_id: &PeerId, cid: &cid::Cid) -> bool { + self.0.peers_want(cid).find(|id| **id == *peer_id).is_some() + } } impl Behaviour { @@ -267,9 +316,9 @@ impl Behaviour { self.light_client_handler.request(r) } - fn add_discovered_node(&mut self, peer_id: PeerId) { - self.substrate.add_discovered_nodes(iter::once(peer_id.clone())); - self.bitswap.connect(peer_id); + /// Returns an API to interact with bitswap. + pub fn bitswap_api(&mut self) -> BitswapApi { + BitswapApi(&mut self.bitswap) } } @@ -449,7 +498,7 @@ impl NetworkBehaviourEventProcess NetworkBehaviourEventProcess // implementation for `PeerInfoEvent`. } DiscoveryOut::Discovered(peer_id) => { - self.add_discovered_node(peer_id); + self.substrate.add_discovered_nodes(iter::once(peer_id)); } DiscoveryOut::ValueFound(results, duration) => { self.events.push_back(BehaviourOut::Dht(DhtEvent::ValueFound(results), duration)); @@ -490,7 +539,19 @@ impl NetworkBehaviourEventProcess impl NetworkBehaviourEventProcess for Behaviour { fn inject_event(&mut self, event: libp2p_bitswap::BitswapEvent) { - self.events.push_back(BehaviourOut::Bitswap(event)); + match event { + libp2p_bitswap::BitswapEvent::ReceivedBlock(peer_id, cid, data) => { + self.events.push_back( + BehaviourOut::Bitswap(BitswapEvent::ReceivedBlock(peer_id, cid, data)) + ); + }, + libp2p_bitswap::BitswapEvent::ReceivedWant(peer_id, cid, priority) => { + self.events.push_back( + BehaviourOut::Bitswap(BitswapEvent::ReceivedWant(peer_id, cid, priority)) + ); + } + libp2p_bitswap::BitswapEvent::ReceivedCancel(..) => {}, + } } } diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index 9ff10052dd65c..ee8560cd1dd5c 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -268,7 +268,7 @@ pub use protocol::sync::SyncState; pub use libp2p::{Multiaddr, PeerId}; #[doc(inline)] pub use libp2p::multiaddr; -pub use libp2p_bitswap::BitswapEvent; +pub use behaviour::{BitswapEvent, BitswapApi}; pub use sc_peerset::ReputationChange; use sp_runtime::traits::{Block as BlockT, NumberFor}; diff --git a/client/network/src/protocol/event.rs b/client/network/src/protocol/event.rs index 7886b32389936..0e45e38e8ca31 100644 --- a/client/network/src/protocol/event.rs +++ b/client/network/src/protocol/event.rs @@ -21,6 +21,7 @@ use bytes::Bytes; use libp2p::core::PeerId; use libp2p::kad::record::Key; use sp_runtime::ConsensusEngineId; +use crate::behaviour::BitswapEvent; /// Events generated by DHT as a response to get_value and put_value requests. #[derive(Debug, Clone)] @@ -46,7 +47,7 @@ pub enum Event { /// Event generated by a DHT. Dht(DhtEvent), /// Event generated by Bitswap. - Bitswap(libp2p_bitswap::BitswapEvent), + Bitswap(BitswapEvent), /// Opened a substream with the given node with the given notifications protocol. /// diff --git a/client/network/src/service.rs b/client/network/src/service.rs index d614be0276e17..ee067f2d08cc8 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -29,7 +29,7 @@ use crate::{ ExHashT, NetworkStateInfo, - behaviour::{Behaviour, BehaviourOut}, + behaviour::{Behaviour, BehaviourOut, BitswapApi}, config::{parse_addr, parse_str_addr, NonReservedPeerMode, Params, Role, TransportConfig}, DhtEvent, discovery::DiscoveryConfig, @@ -61,7 +61,6 @@ use sp_runtime::{ ConsensusEngineId, }; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; -use sp_core::offchain::OffchainStorage; use std::{ borrow::{Borrow, Cow}, collections::{HashMap, HashSet}, @@ -555,28 +554,9 @@ impl NetworkWorker { } /// Get a mutable reference to the Bitswap behaviour. - pub fn bitswap(&mut self) -> &mut libp2p_bitswap::Bitswap { - &mut self.network_service.bitswap + pub fn bitswap_api(&mut self) -> BitswapApi { + self.network_service.bitswap_api() } - - /// Handle a `BitswapEvent`, reading and writing from the `OffchainStorage`. - pub fn handle_bitswap_event( - &mut self, event: libp2p_bitswap::BitswapEvent, mut storage: S, - ) { - match event { - libp2p_bitswap::BitswapEvent::ReceivedBlock(_, cid, data) => { - let cid_bytes = &cid.to_bytes()[..]; - storage.set(b"bitswap", cid_bytes, &data[..]); - }, - libp2p_bitswap::BitswapEvent::ReceivedWant(peer_id, cid, _) => { - if let Some(data) = storage.get(b"bitswap", &cid.to_bytes()[..]) { - self.bitswap().send_block(&peer_id, cid, data.into_boxed_slice()); - } - } - libp2p_bitswap::BitswapEvent::ReceivedCancel(_, _) => {}, - } - } - } impl NetworkService { diff --git a/client/network/test/src/bitswap.rs b/client/network/test/src/bitswap.rs index a05f9b5526b15..1038dfa4656aa 100644 --- a/client/network/test/src/bitswap.rs +++ b/client/network/test/src/bitswap.rs @@ -28,7 +28,7 @@ fn test_bitswap_peers_connect() { net.block_until_connected(); for peer in 0 .. 3 { - assert_eq!(net.peer(peer).network.bitswap().peers().count(), 2); + assert_eq!(net.peer(peer).network.bitswap_api().num_peers(), 2); } } @@ -39,21 +39,21 @@ fn test_bitswap_peers_sending_and_cancelling_wants_works() { let cid: cid::Cid = "bafkreiaapsxdkhlebw676iqic2r7fmq3gngqqcvfwh7aisvnxl7zrt24em".parse().unwrap(); - net.peer(0).network.bitswap().want_block(cid.clone(), 0); + net.peer(0).network.bitswap_api().want_block(cid.clone(), 0); - let peer_0 = [&net.peer(0).id()]; + let peer_0 = net.peer(0).id(); block_on(futures::future::poll_fn::<(), _>(|cx| { net.poll(cx); for peer in 1..3 { - if net.peer(peer).network.bitswap().peers_want(&cid).collect::>() != peer_0 { + if !net.peer(peer).network.bitswap_api().peer_wants_cid(&peer_0, &cid) { return Poll::Pending } } Poll::Ready(()) })); - net.peer(0).network.bitswap().cancel_block(&cid); + net.peer(0).network.bitswap_api().cancel_block(&cid); wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); } @@ -62,7 +62,7 @@ fn wait_until_x_peers_want_cid(net: &mut TestNet, x: usize, peers: std::ops::Ran block_on(futures::future::poll_fn::<(), _>(|cx| { net.poll(cx); for peer in peers.clone() { - if net.peer(peer).network.bitswap().peers_want(cid).count() != x { + if net.peer(peer).network.bitswap_api().num_peers_want(cid) != x { return Poll::Pending } } @@ -80,11 +80,11 @@ fn test_bitswap_sending_blocks_works() { let hash = multihash::Code::Sha2_256.digest(block); let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); - net.peer(0).network.bitswap().want_block(cid.clone(), 0); + net.peer(0).network.bitswap_api().want_block(cid.clone(), 0); wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); - net.peer(2).network.bitswap().send_block_all(&cid, block); + net.peer(2).network.bitswap_api().send_block_all(&cid, block); wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); @@ -118,7 +118,7 @@ fn test_bitswap_sending_blocks_from_store_works() { net.block_until_connected(); - net.peer(0).network.bitswap().want_block(cid.clone(), 0); + net.peer(0).network.bitswap_api().want_block(cid.clone(), 0); wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index af648d3fbe8fe..28122c1b21fd8 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -957,7 +957,7 @@ pub trait TestNetFactory: Sized { while let Poll::Ready(Some(event)) = peer.bitswap_stream.as_mut().poll_next(cx) { if let Some(offchain) = peer.client.offchain_storage() { - peer.network.handle_bitswap_event(event, offchain); + sc_service::handle_bitswap_event(&mut peer.network, event, offchain); } } } diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 5ebe2570e23fb..9fd9bd06f9f48 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -49,6 +49,7 @@ use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use parity_util_mem::MallocSizeOf; use sp_utils::{status_sinks, mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}}; +use sp_api::offchain::OffchainStorage; pub use self::error::Error; pub use self::builder::{ @@ -341,13 +342,33 @@ async fn build_network_future< event = bitswap_events.select_next_some() => { if let Some(offchain) = backend.offchain_storage() { - network.handle_bitswap_event(event, offchain); + handle_bitswap_event(&mut network, event, offchain); } } } } } +/// Handle a `BitswapEvent`, reading and writing from the `OffchainStorage`. +pub fn handle_bitswap_event( + network: &mut sc_network::NetworkWorker, + event: sc_network::BitswapEvent, + mut storage: S, +) { + match event { + sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { + let cid_bytes = &cid.to_bytes()[..]; + storage.set(b"bitswap", cid_bytes, &data[..]); + }, + sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { + if let Some(data) = storage.get(b"bitswap", &cid.to_bytes()[..]) { + network.bitswap_api().send_block(&peer_id, cid, data.into_boxed_slice()); + } + } + } +} + + #[cfg(not(target_os = "unknown"))] // Wrapper for HTTP and WS servers that makes sure they are properly shut down. mod waiting { From be7baf5c4beaeb11c0d7d89f30a5ac257e3e6596 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Mon, 3 Aug 2020 15:06:59 +0200 Subject: [PATCH 06/18] Convert spaces to tabs --- client/network/src/behaviour.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index 54e3b62af3a6a..4d9605055a587 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -161,7 +161,7 @@ pub enum BitswapEvent { /// A block was received. ReceivedBlock(PeerId, cid::Cid, Box<[u8]>), /// A WANT request was received. - ReceivedWant(PeerId, cid::Cid, i32), + ReceivedWant(PeerId, cid::Cid, i32), } /// An opaque API used to interact with bitswap. From 2496778b18e5177d10436dc6bb5340658448e2bc Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Wed, 5 Aug 2020 13:59:35 +0200 Subject: [PATCH 07/18] Implement IPLD storage traits --- Cargo.lock | 48 ++++ client/network/test/src/bitswap.rs | 15 +- client/network/test/src/lib.rs | 13 +- client/service/Cargo.toml | 2 + client/service/src/bitswap.rs | 287 ++++++++++++++++++++++++ client/service/src/lib.rs | 24 +- primitives/core/src/offchain/storage.rs | 2 +- primitives/core/src/offchain/testing.rs | 5 + 8 files changed, 377 insertions(+), 19 deletions(-) create mode 100644 client/service/src/bitswap.rs diff --git a/Cargo.lock b/Cargo.lock index 6e4c99fc1af62..566a1a0e2581b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2846,6 +2846,43 @@ dependencies = [ "take_mut", ] +[[package]] +name = "libipld" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378647e4d5658b199cf651d52cc6a1fb454d161759141fb15679eb99ab19b934" +dependencies = [ + "async-std", + "libipld-cbor", + "libipld-cbor-derive", + "libipld-core", + "libipld-macro", + "thiserror", +] + +[[package]] +name = "libipld-cbor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d243510ff13f7155c2d5a5ef4609ca37c67729b5c4a4d5b628ea40bcc1a5d1a8" +dependencies = [ + "byteorder", + "libipld-core", + "thiserror", +] + +[[package]] +name = "libipld-cbor-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ebad2c94813ea57b19acf05135674caf44650b94f6a897c376da9670af32e90" +dependencies = [ + "proc-macro2", + "quote 1.0.6", + "syn 1.0.33", + "synstructure", +] + [[package]] name = "libipld-core" version = "0.3.0" @@ -2858,6 +2895,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "libipld-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34e065cbbf044ae30ff3bb84f91a94089f797521270d22db2e147511d5f2ac73" +dependencies = [ + "libipld-core", +] + [[package]] name = "libloading" version = "0.5.2" @@ -7104,6 +7150,7 @@ dependencies = [ "cid", "derive_more", "directories", + "env_logger 0.7.1", "exit-future", "futures 0.1.29", "futures 0.3.5", @@ -7111,6 +7158,7 @@ dependencies = [ "hash-db", "jsonrpc-pubsub", "lazy_static", + "libipld", "log", "multihash", "netstat2", diff --git a/client/network/test/src/bitswap.rs b/client/network/test/src/bitswap.rs index 1038dfa4656aa..fe2f6a8234671 100644 --- a/client/network/test/src/bitswap.rs +++ b/client/network/test/src/bitswap.rs @@ -18,7 +18,6 @@ use futures::executor::block_on; use super::*; -use sp_core::offchain::OffchainStorage; #[test] fn test_bitswap_peers_connect() { @@ -89,17 +88,17 @@ fn test_bitswap_sending_blocks_works() { wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); assert_eq!( - net.peer(0).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), + net.peer(0).client.bitswap_storage().unwrap().get(&cid).ok(), Some(block.to_vec()) ); assert_eq!( - net.peer(1).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), + net.peer(1).client.bitswap_storage().unwrap().get(&cid).ok(), None ); assert_eq!( - net.peer(2).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), + net.peer(2).client.bitswap_storage().unwrap().get(&cid).ok(), None ); } @@ -114,7 +113,7 @@ fn test_bitswap_sending_blocks_from_store_works() { let hash = multihash::Code::Sha2_256.digest(block); let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); - net.peer(2).client.offchain_storage().unwrap().set(b"bitswap", &cid.to_bytes(), block); + net.peer(2).client.bitswap_storage().unwrap().insert(&cid, block.into()).unwrap(); net.block_until_connected(); @@ -125,17 +124,17 @@ fn test_bitswap_sending_blocks_from_store_works() { wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); assert_eq!( - net.peer(0).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), + net.peer(0).client.bitswap_storage().unwrap().get(&cid).ok(), Some(block.to_vec()) ); assert_eq!( - net.peer(1).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), + net.peer(1).client.bitswap_storage().unwrap().get(&cid).ok(), None ); assert_eq!( - net.peer(2).client.offchain_storage().unwrap().get(b"bitswap", &cid.to_bytes()), + net.peer(2).client.bitswap_storage().unwrap().get(&cid).ok(), Some(block.to_vec()) ); } diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 28122c1b21fd8..71bcb282864ee 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -27,7 +27,7 @@ mod bitswap; use std::{collections::HashMap, pin::Pin, sync::Arc, marker::PhantomData, task::{Poll, Context as FutureContext}}; use libp2p::build_multiaddr; -use log::trace; +use log::{trace, warn}; use sc_network::config::FinalityProofProvider; use sp_blockchain::{ HeaderBackend, Result as ClientResult, @@ -171,6 +171,11 @@ impl PeersClient { } } + #[cfg(test)] + fn bitswap_storage(&self) -> Option> { + self.offchain_storage().map(sc_service::BitswapStorage::new) + } + pub fn info(&self) -> BlockchainInfo { match *self { PeersClient::Full(ref client, ref _backend) => client.chain_info(), @@ -957,7 +962,11 @@ pub trait TestNetFactory: Sized { while let Poll::Ready(Some(event)) = peer.bitswap_stream.as_mut().poll_next(cx) { if let Some(offchain) = peer.client.offchain_storage() { - sc_service::handle_bitswap_event(&mut peer.network, event, offchain); + if let Err(err) = + sc_service::handle_bitswap_event(&mut peer.network, event, offchain) + { + warn!("{}", err); + } } } } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 7e52cf385682c..d46ddc3d80c1b 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -77,6 +77,7 @@ tracing = "0.1.10" parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } multihash = "0.11.2" cid = "0.5.1" +libipld = "0.3.0" [target.'cfg(all(any(unix, windows), not(target_os = "android"), not(target_os = "ios")))'.dependencies] netstat2 = "0.8.1" @@ -95,3 +96,4 @@ grandpa = { version = "0.8.0-rc5", package = "sc-finality-grandpa", path = "../f grandpa-primitives = { version = "2.0.0-rc5", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" } tokio = { version = "0.2", default-features = false } async-std = { version = "1.6", default-features = false } +env_logger = "0.7.1" diff --git a/client/service/src/bitswap.rs b/client/service/src/bitswap.rs new file mode 100644 index 0000000000000..9184ddb0dc8fe --- /dev/null +++ b/client/service/src/bitswap.rs @@ -0,0 +1,287 @@ + +use libipld::store::{StoreResult, Visibility, Store, ReadonlyStore}; +pub use libipld::error::StoreError; +use sp_core::offchain::OffchainStorage; +use codec::{Decode, Encode}; +use std::collections::HashSet; +use log::debug; + +const BLOCK: &'static [u8] = b"bitswap_block"; +const PINS: &'static [u8] = b"bitswap_pins"; +const REFERRERS: &'static [u8] = b"bitswap_referrers"; +const REFS: &'static [u8] = b"bitswap_refs"; + +/// A wrapper around an `OffchainStorage` for the purpose of storing bitswap blocks. +/// +/// Mappings: +/// +/// `bitswap_block`: Cid -> Block bytes (`Vec`). +/// `bitswap_pins`: Cid -> Number of pins a block has (`u64`). +/// `bitswap_referrers`: Cid -> Number of blocks that we know refers to a block (`i64`, may be negative). +/// `bitswap_refs`: Cid -> List of Cids a block refers to (`Vec`) +#[derive(Clone, Debug)] +pub struct BitswapStorage { + storage: S, +} + +impl BitswapStorage { + /// Wrap an `OffchainStorage`. + pub fn new(storage: S) -> Self { + Self { + storage, + } + } + + fn get_any(&self, prefix: &[u8], cid: &cid::Cid) -> Result, StoreError> { + self.storage.get(prefix, &cid.to_bytes()[..]) + .ok_or_else(|| StoreError::BlockNotFound(cid.clone())) + } + + fn get_and_decode_any(&self, prefix: &[u8], cid: &cid::Cid) -> Result { + let bytes = self.get_any(prefix, cid)?; + D::decode(&mut &bytes[..]) + .map_err(|error| StoreError::Other(Box::new(error))) + } + + /// Get a blcok + pub fn get(&self, cid: &cid::Cid) -> Result, StoreError> { + self.get_any(BLOCK, cid) + } + + fn encode_and_set_any(&mut self, prefix: &[u8], cid: &cid::Cid, object: E) { + let cid_bytes = &cid.to_bytes()[..]; + let bytes = object.encode(); + self.storage.set(prefix, cid_bytes, &bytes[..]); + } + + fn modify_referrers(&mut self, cid: &cid::Cid, n: i64) { + let referrers = self.get_and_decode_any::(REFERRERS, cid).unwrap_or(0); + self.encode_and_set_any(REFERRERS, cid, referrers + n); + } + + fn pin(&mut self, cid: &cid::Cid) { + let mut pins = self.get_and_decode_any::(PINS, cid).unwrap_or(0); + pins += 1; + debug!("Pinning {}. Pins: {}.", cid, pins); + self.encode_and_set_any(PINS, cid, pins); + } + + /// Remove a pin from a block, removing it from the storage if it's the last pin. + pub fn unpin(&mut self, cid: &cid::Cid) -> Result<(), StoreError> { + let mut pins = self.get_and_decode_any::(PINS, cid)?; + pins -= 1; + self.encode_and_set_any(PINS, cid, pins); + + debug!("Unpinning {}. Pins: {}", cid, pins); + + if pins == 0 { + self.remove(cid)?; + } + + Ok(()) + } + + fn get_refs(&self, cid: &cid::Cid) -> Result, StoreError> { + self.get_and_decode_any::>>(REFS, cid)? + .into_iter() + .map(|bytes| { + use std::convert::TryFrom; + cid::Cid::try_from(bytes) + .map_err(|err| StoreError::Other(Box::new(err))) + + }) + .collect() + } + + fn set_refs(&mut self, cid: &cid::Cid, refs: HashSet) { + let vec: Vec> = refs + .into_iter() + .map(|cid| cid.to_bytes()) + .collect(); + + self.encode_and_set_any(REFS, cid, vec); + } + + fn remove(&mut self, cid: &cid::Cid) -> Result<(), StoreError> { + let pins = self.get_and_decode_any::(PINS, cid).unwrap_or_default(); + let referrers = self.get_and_decode_any::(REFERRERS, cid).unwrap_or_default(); + + debug!("Removing {}. Pins: {}, referrers: {}", cid, pins, referrers); + + if referrers < 1 && pins < 1 { + let cid_bytes = &cid.to_bytes()[..]; + + let refs = self.get_refs(cid)?; + + self.storage.remove(REFERRERS, cid_bytes); + self.storage.remove(BLOCK, cid_bytes); + self.storage.remove(PINS, cid_bytes); + self.storage.remove(REFS, cid_bytes); + + for cid in &refs { + self.modify_referrers(cid, -1); + self.remove(cid)?; + } + } + + Ok(()) + } + + /// Insert an ipld block into the storage and pin it. + pub fn insert_and_pin(&mut self, cid: &cid::Cid, data: Box<[u8]>) -> Result<(), StoreError> { + self.insert(cid, data)?; + self.pin(cid); + Ok(()) + } + + /// Insert an ipld block into the storage. + pub fn insert(&mut self, cid: &cid::Cid, data: Box<[u8]>) -> Result<(), StoreError> { + if self.get_any(BLOCK, cid).is_ok() { + return Ok(()) + } + + debug!("Inserting {} into storage.", cid); + + let ipld = libipld::block::decode_ipld(cid, &data) + .map_err(|e| StoreError::Other(Box::new(e)))?; + let refs = libipld::block::references(&ipld); + + for cid in &refs { + self.modify_referrers(&cid, 1); + } + + self.set_refs(cid, refs); + + let cid_bytes = &cid.to_bytes()[..]; + self.storage.set(BLOCK, cid_bytes, &data); + + Ok(()) + } + + fn insert_batch_inner(&mut self, batch: Vec) -> Result { + let mut last_cid = None; + for libipld::block::Block { cid, data } in batch.into_iter() { + self.insert(&cid, data)?; + last_cid = Some(cid); + } + Ok(last_cid.ok_or(StoreError::EmptyBatch)?) + } +} + +impl ReadonlyStore for BitswapStorage { + fn get<'a>(&'a self, cid: &'a cid::Cid) -> StoreResult<'a, Box<[u8]>> { + Box::pin(async move { + let vec = self.get_any(BLOCK, cid)?; + Ok(vec.into_boxed_slice()) + }) + } +} + +impl Store for BitswapStorage { + fn flush(&self) -> StoreResult<'_, ()> { + Box::pin(async move { Ok(()) }) + } + + fn insert<'a>( + &'a self, + cid: &'a cid::Cid, + data: Box<[u8]>, + _visibility: Visibility, + ) -> StoreResult<'a, ()> { + Box::pin(async move { + BitswapStorage::insert(&mut self.clone(), cid, data)?; + self.clone().pin(cid); + Ok(()) + }) + } + + fn insert_batch<'a>( + &'a self, + batch: Vec, + _visibility: Visibility, + ) -> StoreResult<'a, cid::Cid> { + Box::pin(async move { + self.clone().insert_batch_inner(batch) + }) + } + + fn unpin<'a>(&'a self, cid: &'a cid::Cid) -> StoreResult<'a, ()> { + Box::pin(async move { + BitswapStorage::unpin(&mut self.clone(), cid) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use libipld::block::{decode, encode, Block}; + use libipld::cbor::DagCborCodec; + use libipld::cid::Cid; + use libipld::ipld; + use libipld::ipld::Ipld; + use libipld::multihash::Sha2_256; + use libipld::store::{Store, Visibility}; + use sp_core::offchain::testing::TestPersistentOffchainDB; + + async fn get(store: &S, cid: &Cid) -> Option { + let bytes = match store.get(cid).await { + Ok(bytes) => bytes, + Err(StoreError::BlockNotFound { .. }) => return None, + Err(e) => Err(e).unwrap(), + }; + Some(decode::(cid, &bytes).unwrap()) + } + + async fn insert(store: &S, ipld: &Ipld) -> Cid { + let Block { cid, data } = encode::(ipld).unwrap(); + store.insert(&cid, data, Visibility::Public).await.unwrap(); + cid + } + + #[async_std::test] + async fn test_gc() { + let _ = env_logger::try_init(); + + let store = BitswapStorage::new(TestPersistentOffchainDB::default()); + let a = insert(&store, &ipld!({ "a": [] })).await; + let b = insert(&store, &ipld!({ "b": [&a] })).await; + store.unpin(&a).await.unwrap(); + let c = insert(&store, &ipld!({ "c": [&a] })).await; + assert!(get(&store, &a).await.is_some()); + assert!(get(&store, &b).await.is_some()); + assert!(get(&store, &c).await.is_some()); + store.unpin(&b).await.unwrap(); + assert!(get(&store, &a).await.is_some()); + assert!(get(&store, &b).await.is_none()); + assert!(get(&store, &c).await.is_some()); + store.unpin(&c).await.unwrap(); + assert!(get(&store, &a).await.is_none()); + assert!(get(&store, &b).await.is_none()); + assert!(get(&store, &c).await.is_none()); + assert!(store.storage.is_empty()); + } + + #[async_std::test] + async fn test_gc_2() { + let _ = env_logger::try_init(); + + let store = BitswapStorage::new(TestPersistentOffchainDB::default()); + let a = insert(&store, &ipld!({ "a": [] })).await; + let b = insert(&store, &ipld!({ "b": [&a] })).await; + store.unpin(&a).await.unwrap(); + let c = insert(&store, &ipld!({ "b": [&a] })).await; + assert!(get(&store, &a).await.is_some()); + assert!(get(&store, &b).await.is_some()); + assert!(get(&store, &c).await.is_some()); + store.unpin(&b).await.unwrap(); + assert!(get(&store, &a).await.is_some()); + assert!(get(&store, &b).await.is_some()); + assert!(get(&store, &c).await.is_some()); + store.unpin(&c).await.unwrap(); + assert!(get(&store, &a).await.is_none()); + assert!(get(&store, &b).await.is_none()); + assert!(get(&store, &c).await.is_none()); + assert!(store.storage.is_empty()); + } +} diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 9fd9bd06f9f48..5bbf06fa5383d 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -33,6 +33,7 @@ pub mod client; #[cfg(not(feature = "test-helpers"))] mod client; mod task_manager; +mod bitswap; use std::{io, pin::Pin}; use std::net::SocketAddr; @@ -83,6 +84,7 @@ pub use task_manager::TaskManager; pub use sp_consensus::import_queue::ImportQueue; use sc_client_api::BlockchainEvents; pub use sc_keystore::KeyStorePtr as KeyStore; +pub use bitswap::{BitswapStorage, StoreError as BitswapStorageError}; const DEFAULT_PROTOCOL_ID: &str = "sup"; @@ -342,7 +344,9 @@ async fn build_network_future< event = bitswap_events.select_next_some() => { if let Some(offchain) = backend.offchain_storage() { - handle_bitswap_event(&mut network, event, offchain); + if let Err(err) = handle_bitswap_event(&mut network, event, offchain) { + warn!("{}", err); + } } } } @@ -353,22 +357,26 @@ async fn build_network_future< pub fn handle_bitswap_event( network: &mut sc_network::NetworkWorker, event: sc_network::BitswapEvent, - mut storage: S, -) { + storage: S, +) -> Result<(), BitswapStorageError> { + let mut storage = BitswapStorage::new(storage); + match event { sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { - let cid_bytes = &cid.to_bytes()[..]; - storage.set(b"bitswap", cid_bytes, &data[..]); + storage.insert(&cid, data) }, sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { - if let Some(data) = storage.get(b"bitswap", &cid.to_bytes()[..]) { - network.bitswap_api().send_block(&peer_id, cid, data.into_boxed_slice()); + match storage.get(&cid) { + Ok(data) => { + network.bitswap_api().send_block(&peer_id, cid, data.into_boxed_slice()); + Ok(()) + }, + Err(error) => Err(error) } } } } - #[cfg(not(target_os = "unknown"))] // Wrapper for HTTP and WS servers that makes sure they are properly shut down. mod waiting { diff --git a/primitives/core/src/offchain/storage.rs b/primitives/core/src/offchain/storage.rs index 7d7c711ed95f0..363b3604ff63c 100644 --- a/primitives/core/src/offchain/storage.rs +++ b/primitives/core/src/offchain/storage.rs @@ -24,7 +24,7 @@ use std::iter::Iterator; /// In-memory storage for offchain workers. #[derive(Debug, Clone, Default)] pub struct InMemOffchainStorage { - storage: HashMap, Vec>, + pub(crate) storage: HashMap, Vec>, } impl InMemOffchainStorage { diff --git a/primitives/core/src/offchain/testing.rs b/primitives/core/src/offchain/testing.rs index c939c5cfccc14..cc8231d7e30b3 100644 --- a/primitives/core/src/offchain/testing.rs +++ b/primitives/core/src/offchain/testing.rs @@ -86,6 +86,11 @@ impl TestPersistentOffchainDB { } } } + + /// Get whether the DB is empty. + pub fn is_empty(&self) -> bool { + self.persistent.read().storage.is_empty() + } } impl OffchainStorage for TestPersistentOffchainDB { From 8d028d4cea4d1bc2d790d7c6f8996f0068492af2 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Wed, 5 Aug 2020 14:27:03 +0200 Subject: [PATCH 08/18] Documentation --- client/service/src/bitswap.rs | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/client/service/src/bitswap.rs b/client/service/src/bitswap.rs index 9184ddb0dc8fe..bcbb12d304285 100644 --- a/client/service/src/bitswap.rs +++ b/client/service/src/bitswap.rs @@ -1,4 +1,22 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + use libipld::store::{StoreResult, Visibility, Store, ReadonlyStore}; pub use libipld::error::StoreError; use sp_core::offchain::OffchainStorage; @@ -13,12 +31,14 @@ const REFS: &'static [u8] = b"bitswap_refs"; /// A wrapper around an `OffchainStorage` for the purpose of storing bitswap blocks. /// +/// This is based on the implementation of the `libipld` [`MemStore`](https://github.com/ipfs-rust/rust-ipld/blob/604fa5782479f322faa17d17ef3cbbb7f6e88aee/src/mem.rs#L13). +/// /// Mappings: /// -/// `bitswap_block`: Cid -> Block bytes (`Vec`). -/// `bitswap_pins`: Cid -> Number of pins a block has (`u64`). -/// `bitswap_referrers`: Cid -> Number of blocks that we know refers to a block (`i64`, may be negative). -/// `bitswap_refs`: Cid -> List of Cids a block refers to (`Vec`) +/// * `bitswap_block`: Cid -> Block bytes (`Vec`). +/// * `bitswap_pins`: Cid -> Number of pins a block has (`u64`). +/// * `bitswap_referrers`: Cid -> Number of blocks that we know refers to a block (`i64`, may be negative). +/// * `bitswap_refs`: Cid -> List of Cids a block refers to (`Vec`) #[derive(Clone, Debug)] pub struct BitswapStorage { storage: S, @@ -212,6 +232,7 @@ impl Store for BitswapStorage { } } +// These tests are copied from https://github.com/ipfs-rust/rust-ipld/blob/604fa5782479f322faa17d17ef3cbbb7f6e88aee/src/mem.rs#L221. #[cfg(test)] mod tests { use super::*; @@ -240,7 +261,7 @@ mod tests { } #[async_std::test] - async fn test_gc() { + async fn bitswap_garbage_collection() { let _ = env_logger::try_init(); let store = BitswapStorage::new(TestPersistentOffchainDB::default()); @@ -263,7 +284,7 @@ mod tests { } #[async_std::test] - async fn test_gc_2() { + async fn bitswap_garbage_collection_2() { let _ = env_logger::try_init(); let store = BitswapStorage::new(TestPersistentOffchainDB::default()); From ccb5910f9806cc25b924d193a54858062e187853 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Thu, 6 Aug 2020 12:14:08 +0200 Subject: [PATCH 09/18] Fix line widths --- client/network/test/src/bitswap.rs | 25 +++++++++++++------------ client/network/test/src/lib.rs | 6 ++++-- client/service/src/bitswap.rs | 6 ++++-- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/client/network/test/src/bitswap.rs b/client/network/test/src/bitswap.rs index fe2f6a8234671..a6745b33e5f0d 100644 --- a/client/network/test/src/bitswap.rs +++ b/client/network/test/src/bitswap.rs @@ -18,6 +18,19 @@ use futures::executor::block_on; use super::*; +use std::ops::Range; + +fn wait_until_x_peers_want_cid(net: &mut TestNet, x: usize, peers: Range, cid: &cid::Cid) { + block_on(futures::future::poll_fn::<(), _>(|cx| { + net.poll(cx); + for peer in peers.clone() { + if net.peer(peer).network.bitswap_api().num_peers_want(cid) != x { + return Poll::Pending + } + } + Poll::Ready(()) + })); +} #[test] fn test_bitswap_peers_connect() { @@ -57,18 +70,6 @@ fn test_bitswap_peers_sending_and_cancelling_wants_works() { wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); } -fn wait_until_x_peers_want_cid(net: &mut TestNet, x: usize, peers: std::ops::Range, cid: &cid::Cid) { - block_on(futures::future::poll_fn::<(), _>(|cx| { - net.poll(cx); - for peer in peers.clone() { - if net.peer(peer).network.bitswap_api().num_peers_want(cid) != x { - return Poll::Pending - } - } - Poll::Ready(()) - })); -} - #[test] fn test_bitswap_sending_blocks_works() { let _ = ::env_logger::try_init(); diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 71bcb282864ee..f34b1d7de6194 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -166,8 +166,10 @@ impl PeersClient { fn offchain_storage(&self) -> Option { match *self { - PeersClient::Full(ref _client, ref backend) => backend.offchain_storage().map(PeerOffchainStorage::Full), - PeersClient::Light(ref _client, ref backend) => backend.offchain_storage().map(PeerOffchainStorage::Light), + PeersClient::Full(ref _client, ref backend) => + backend.offchain_storage().map(PeerOffchainStorage::Full), + PeersClient::Light(ref _client, ref backend) => + backend.offchain_storage().map(PeerOffchainStorage::Light), } } diff --git a/client/service/src/bitswap.rs b/client/service/src/bitswap.rs index bcbb12d304285..8e98fa123fdbb 100644 --- a/client/service/src/bitswap.rs +++ b/client/service/src/bitswap.rs @@ -31,7 +31,8 @@ const REFS: &'static [u8] = b"bitswap_refs"; /// A wrapper around an `OffchainStorage` for the purpose of storing bitswap blocks. /// -/// This is based on the implementation of the `libipld` [`MemStore`](https://github.com/ipfs-rust/rust-ipld/blob/604fa5782479f322faa17d17ef3cbbb7f6e88aee/src/mem.rs#L13). +/// This is based on the implementation of the `libipld` +/// [`MemStore`](https://github.com/ipfs-rust/rust-ipld/blob/604fa5782479f322faa17d17ef3cbbb7f6e88aee/src/mem.rs#L13). /// /// Mappings: /// @@ -232,7 +233,8 @@ impl Store for BitswapStorage { } } -// These tests are copied from https://github.com/ipfs-rust/rust-ipld/blob/604fa5782479f322faa17d17ef3cbbb7f6e88aee/src/mem.rs#L221. +// These tests are copied from +// https://github.com/ipfs-rust/rust-ipld/blob/604fa5782479f322faa17d17ef3cbbb7f6e88aee/src/mem.rs#L221. #[cfg(test)] mod tests { use super::*; From 3da54fa6adf0fb13bbeef8ee050421ebd4e3fc28 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Thu, 6 Aug 2020 14:34:25 +0200 Subject: [PATCH 10/18] Fix browser build --- Cargo.lock | 1 + bin/node/cli/Cargo.toml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index d37a51982cc3b..6f72d8a3c35b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3679,6 +3679,7 @@ name = "node-cli" version = "2.0.0-rc5" dependencies = [ "assert_cmd", + "async-std", "frame-benchmarking-cli", "frame-support", "frame-system", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 4fbb48513b3ce..820b46871a15f 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -104,6 +104,8 @@ node-inspect = { version = "0.8.0-rc5", optional = true, path = "../inspect" } wasm-bindgen = { version = "0.2.57", optional = true } wasm-bindgen-futures = { version = "0.4.7", optional = true } browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.8.0-rc5"} +# `async-std` for wasm doesn't compile with `-Z features=itarget` without this feature +async-std = { version = "1.6.2", optional = true, features = ["unstable"] } [target.'cfg(target_arch="x86_64")'.dependencies] node-executor = { version = "2.0.0-rc5", path = "../executor", features = [ "wasmtime" ] } @@ -143,6 +145,7 @@ browser = [ "browser-utils", "wasm-bindgen", "wasm-bindgen-futures", + "async-std", ] cli = [ "node-executor/wasmi-errno", From 8e4c008cc4dd6ca04890f8d2424fcdae807b47b2 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Mon, 10 Aug 2020 16:19:34 +0200 Subject: [PATCH 11/18] Insert bitswap blocks into the dht, rework to put bitswap methods on network service --- client/network/src/behaviour.rs | 47 +----------------------- client/network/src/lib.rs | 2 +- client/network/src/service.rs | 58 +++++++++++++++++++++++++++--- client/network/test/src/bitswap.rs | 36 ++++++++++--------- client/network/test/src/lib.rs | 2 +- client/service/src/lib.rs | 14 ++++---- 6 files changed, 84 insertions(+), 75 deletions(-) diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index 4d9605055a587..3b026d1c38812 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -51,7 +51,7 @@ pub struct Behaviour { /// Discovers nodes of the network. discovery: DiscoveryBehaviour, /// Exchanges blocks of data with other nodes. - bitswap: libp2p_bitswap::Bitswap, + pub(crate) bitswap: libp2p_bitswap::Bitswap, /// Block request handling. block_requests: block_requests::BlockRequests, /// Finality proof request handling. @@ -164,46 +164,6 @@ pub enum BitswapEvent { ReceivedWant(PeerId, cid::Cid, i32), } -/// An opaque API used to interact with bitswap. -pub struct BitswapApi<'a>(&'a mut libp2p_bitswap::Bitswap); - -impl<'a> BitswapApi<'a> { - /// Send a block to a peer. - pub fn send_block(&mut self, peer_id: &PeerId, cid: cid::Cid, data: Box<[u8]>) { - self.0.send_block(peer_id, cid, data) - } - - /// Send a block to all peers that have the block in their wantlist. - pub fn send_block_all(&mut self, cid: &cid::Cid, data: &[u8]) { - self.0.send_block_all(cid, data) - } - - /// Send a WANT request to all peers for a block. - pub fn want_block(&mut self, cid: cid::Cid, priority: i32) { - self.0.want_block(cid, priority) - } - - /// Cancel a WANT request. - pub fn cancel_block(&mut self, cid: &cid::Cid) { - self.0.cancel_block(cid) - } - - /// Get the number of peers we are connected to. - pub fn num_peers(&self) -> usize { - self.0.peers().count() - } - - /// Get the number of peers who want a block. - pub fn num_peers_want(&self, cid: &cid::Cid) -> usize { - self.0.peers_want(cid).count() - } - - /// Get if a specific peer wants a block. - pub fn peer_wants_cid(&self, peer_id: &PeerId, cid: &cid::Cid) -> bool { - self.0.peers_want(cid).find(|id| **id == *peer_id).is_some() - } -} - impl Behaviour { /// Builds a new `Behaviour`. pub fn new( @@ -315,11 +275,6 @@ impl Behaviour { pub fn light_client_request(&mut self, r: light_client_handler::Request) -> Result<(), light_client_handler::Error> { self.light_client_handler.request(r) } - - /// Returns an API to interact with bitswap. - pub fn bitswap_api(&mut self) -> BitswapApi { - BitswapApi(&mut self.bitswap) - } } fn reported_roles_to_observed_role(local_role: &Role, remote: &PeerId, roles: Roles) -> ObservedRole { diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index ee8560cd1dd5c..76527b9876cd6 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -268,7 +268,7 @@ pub use protocol::sync::SyncState; pub use libp2p::{Multiaddr, PeerId}; #[doc(inline)] pub use libp2p::multiaddr; -pub use behaviour::{BitswapEvent, BitswapApi}; +pub use behaviour::BitswapEvent; pub use sc_peerset::ReputationChange; use sp_runtime::traits::{Block as BlockT, NumberFor}; diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 51cf8ebbd32bd..74ce31a62cca5 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -29,7 +29,7 @@ use crate::{ ExHashT, NetworkStateInfo, - behaviour::{Behaviour, BehaviourOut, BitswapApi}, + behaviour::{Behaviour, BehaviourOut}, config::{parse_str_addr, NonReservedPeerMode, Params, Role, TransportConfig}, DhtEvent, discovery::DiscoveryConfig, @@ -553,9 +553,19 @@ impl NetworkWorker { self.service.add_reserved_peer(peer) } - /// Get a mutable reference to the Bitswap behaviour. - pub fn bitswap_api(&mut self) -> BitswapApi { - self.network_service.bitswap_api() + /// Get the number of bitswap peers we are connected to. + pub fn bitswap_num_peers(&self) -> usize { + self.network_service.bitswap.peers().count() + } + + /// Get the number of bitswap peers who want a block. + pub fn bitswap_num_peers_want(&self, cid: &cid::Cid) -> usize { + self.network_service.bitswap.peers_want(cid).count() + } + + /// Get if a specific bitswap peer wants a block. + pub fn bitswap_peer_wants_cid(&self, peer_id: &PeerId, cid: &cid::Cid) -> bool { + self.network_service.bitswap.peers_want(cid).find(|id| **id == *peer_id).is_some() } } @@ -941,6 +951,34 @@ impl NetworkService { .to_worker .unbounded_send(ServiceToWorkerMsg::OwnBlockImported(hash, number)); } + + /// Send a bitswap block to a peer. + pub fn bitswap_send_block(&self, peer_id: PeerId, cid: cid::Cid, data: Box<[u8]>) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::BitswapSendBlock(peer_id, cid, data)); + } + + /// Send a bitswap block to all peers that have the block in their wantlist. + pub fn bitswap_send_block_all(&self, cid: cid::Cid, data: Box<[u8]>) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::BitswapSendBlockAll(cid, data)); + } + + /// Send a bitswap WANT request to all peers for a block. + pub fn bitswap_want_block(&self, cid: cid::Cid, priority: i32) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::BitswapWantBlock(cid, priority)); + } + + /// Cancel a bitswap WANT request. + pub fn bitswap_cancel_block(&self, cid: cid::Cid) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::BitswapCancelBlock(cid)); + } } impl sp_consensus::SyncOracle @@ -1084,6 +1122,10 @@ enum ServiceToWorkerMsg { DisconnectPeer(PeerId), UpdateChain, OwnBlockImported(B::Hash, NumberFor), + BitswapSendBlock(PeerId, cid::Cid, Box<[u8]>), + BitswapSendBlockAll(cid::Cid, Box<[u8]>), + BitswapWantBlock(cid::Cid, i32), + BitswapCancelBlock(cid::Cid), } /// Main network worker. Must be polled in order for the network to advance. @@ -1401,6 +1443,14 @@ impl Future for NetworkWorker { this.network_service.user_protocol_mut().update_chain(), ServiceToWorkerMsg::OwnBlockImported(hash, number) => this.network_service.user_protocol_mut().own_block_imported(hash, number), + ServiceToWorkerMsg::BitswapSendBlock(peer_id, cid, block) => + this.network_service.bitswap.send_block(&peer_id, cid, block), + ServiceToWorkerMsg::BitswapSendBlockAll(cid, block) => + this.network_service.bitswap.send_block_all(&cid, &block), + ServiceToWorkerMsg::BitswapWantBlock(cid, priority) => + this.network_service.bitswap.want_block(cid, priority), + ServiceToWorkerMsg::BitswapCancelBlock(cid) => + this.network_service.bitswap.cancel_block(&cid), } } diff --git a/client/network/test/src/bitswap.rs b/client/network/test/src/bitswap.rs index a6745b33e5f0d..b42bcd4fb2dad 100644 --- a/client/network/test/src/bitswap.rs +++ b/client/network/test/src/bitswap.rs @@ -20,11 +20,18 @@ use futures::executor::block_on; use super::*; use std::ops::Range; +fn generate_block_and_cid(string: &str) -> (&[u8], cid::Cid) { + let block = string.as_bytes(); + let hash = multihash::Code::Sha2_256.digest(block); + let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); + (block, cid) +} + fn wait_until_x_peers_want_cid(net: &mut TestNet, x: usize, peers: Range, cid: &cid::Cid) { block_on(futures::future::poll_fn::<(), _>(|cx| { net.poll(cx); for peer in peers.clone() { - if net.peer(peer).network.bitswap_api().num_peers_want(cid) != x { + if net.peer(peer).network.bitswap_num_peers_want(cid) != x { return Poll::Pending } } @@ -40,7 +47,7 @@ fn test_bitswap_peers_connect() { net.block_until_connected(); for peer in 0 .. 3 { - assert_eq!(net.peer(peer).network.bitswap_api().num_peers(), 2); + assert_eq!(net.peer(peer).network.bitswap_num_peers(), 2); } } @@ -49,23 +56,23 @@ fn test_bitswap_peers_sending_and_cancelling_wants_works() { let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); - let cid: cid::Cid = "bafkreiaapsxdkhlebw676iqic2r7fmq3gngqqcvfwh7aisvnxl7zrt24em".parse().unwrap(); + let (_, cid) = generate_block_and_cid("test_bitswap_peers_sending_and_cancelling_wants_works"); - net.peer(0).network.bitswap_api().want_block(cid.clone(), 0); + net.peer(0).network_service().bitswap_want_block(cid.clone(), 0); let peer_0 = net.peer(0).id(); block_on(futures::future::poll_fn::<(), _>(|cx| { net.poll(cx); for peer in 1..3 { - if !net.peer(peer).network.bitswap_api().peer_wants_cid(&peer_0, &cid) { + if !net.peer(peer).network.bitswap_peer_wants_cid(&peer_0, &cid) { return Poll::Pending } } Poll::Ready(()) })); - net.peer(0).network.bitswap_api().cancel_block(&cid); + net.peer(0).network.service().bitswap_cancel_block(cid.clone()); wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); } @@ -75,16 +82,14 @@ fn test_bitswap_sending_blocks_works() { let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); - let block = "abcdefghi".as_bytes(); + let (block, cid) = generate_block_and_cid("test_bitswap_sending_blocks_works"); - let hash = multihash::Code::Sha2_256.digest(block); - let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); - - net.peer(0).network.bitswap_api().want_block(cid.clone(), 0); + net.peer(0).network.service().bitswap_want_block(cid.clone(), 0); wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); - net.peer(2).network.bitswap_api().send_block_all(&cid, block); + net.peer(2).network.service() + .bitswap_send_block_all(cid.clone(), block.to_vec().into_boxed_slice()); wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); @@ -109,16 +114,13 @@ fn test_bitswap_sending_blocks_from_store_works() { let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); - let block = "abcdefghi".as_bytes(); + let (block, cid) = generate_block_and_cid("test_bitswap_sending_blocks_from_store_works"); - let hash = multihash::Code::Sha2_256.digest(block); - let cid = cid::Cid::new_v1(cid::Codec::Raw, hash); - net.peer(2).client.bitswap_storage().unwrap().insert(&cid, block.into()).unwrap(); net.block_until_connected(); - net.peer(0).network.bitswap_api().want_block(cid.clone(), 0); + net.peer(0).network.service().bitswap_want_block(cid.clone(), 0); wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index f34b1d7de6194..c1ab5934c42b0 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -965,7 +965,7 @@ pub trait TestNetFactory: Sized { while let Poll::Ready(Some(event)) = peer.bitswap_stream.as_mut().poll_next(cx) { if let Some(offchain) = peer.client.offchain_storage() { if let Err(err) = - sc_service::handle_bitswap_event(&mut peer.network, event, offchain) + sc_service::handle_bitswap_event(peer.network.service(), event, offchain) { warn!("{}", err); } diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 0b7d048c1e40a..2731144e9f4da 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -42,7 +42,7 @@ use std::time::Duration; use std::task::Poll; use parking_lot::Mutex; -use futures::{Future, FutureExt, Stream, StreamExt, stream, compat::*}; +use futures::{Future, FutureExt, Stream, StreamExt, stream, compat::*, future}; use sc_network::{NetworkStatus, network_state::NetworkState, PeerId}; use log::{warn, debug, error}; use codec::{Encode, Decode}; @@ -219,7 +219,7 @@ async fn build_network_future< let mut bitswap_events = network.service().event_stream("bitswap") - .filter_map(|event| futures::future::ready(if let sc_network::Event::Bitswap(event) = event { + .filter_map(|event| future::ready(if let sc_network::Event::Bitswap(event) = event { Some(event) } else { None @@ -344,7 +344,7 @@ async fn build_network_future< event = bitswap_events.select_next_some() => { if let Some(offchain) = backend.offchain_storage() { - if let Err(err) = handle_bitswap_event(&mut network, event, offchain) { + if let Err(err) = handle_bitswap_event(network.service(), event, offchain) { warn!("{}", err); } } @@ -355,7 +355,7 @@ async fn build_network_future< /// Handle a `BitswapEvent`, reading and writing from the `OffchainStorage`. pub fn handle_bitswap_event( - network: &mut sc_network::NetworkWorker, + service: &Arc>, event: sc_network::BitswapEvent, storage: S, ) -> Result<(), BitswapStorageError> { @@ -363,12 +363,14 @@ pub fn handle_bitswap_event { - storage.insert(&cid, data) + storage.insert(&cid, data.clone())?; + service.put_value(cid.to_bytes().into(), data.to_vec()); + Ok(()) }, sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { match storage.get(&cid) { Ok(data) => { - network.bitswap_api().send_block(&peer_id, cid, data.into_boxed_slice()); + service.bitswap_send_block(peer_id, cid, data.into_boxed_slice()); Ok(()) }, Err(error) => Err(error) From b8804df767f6b893962a2f09bf81714df6abd05a Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Mon, 31 Aug 2020 16:24:33 +0200 Subject: [PATCH 12/18] Fix wasm build, but via patch --- Cargo.lock | 3 +-- Cargo.toml | 3 +++ bin/node/cli/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0cbcf1d6d49e6..a64df2d9d78a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -318,8 +318,7 @@ dependencies = [ [[package]] name = "async-std" version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c8da367da62b8ff2313c406c9ac091c1b31d67a165becdd2de380d846260f7" +source = "git+https://github.com/expenses/async-std?branch=wasm-join-handle-future#552c2a1f946b556f49209df7e38074320d2fb83a" dependencies = [ "async-attributes", "async-executor", diff --git a/Cargo.toml b/Cargo.toml index 7589e8d774124..aa617972f65d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -257,3 +257,6 @@ zeroize = { opt-level = 3 } [profile.release] # Substrate runtime requires unwinding. panic = "unwind" + +[patch.crates-io] +async-std = { git = "https://github.com/expenses/async-std", branch = "wasm-join-handle-future" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index eefaad2c452cf..ec64638703c6e 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -106,7 +106,7 @@ wasm-bindgen = { version = "0.2.57", optional = true } wasm-bindgen-futures = { version = "0.4.7", optional = true } browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.8.0-rc6"} # `async-std` for wasm doesn't compile with `-Z features=itarget` without this feature -async-std = { version = "1.6.2", optional = true, features = ["unstable"] } +async-std = { version = "1.6.3", optional = true, features = ["unstable"] } [target.'cfg(target_arch="x86_64")'.dependencies] node-executor = { version = "2.0.0-rc6", path = "../executor", features = [ "wasmtime" ] } From 83de2293182e65747310fd8db410345725d4102f Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Fri, 18 Sep 2020 12:18:13 +0200 Subject: [PATCH 13/18] Remove storage impl and update --- Cargo.lock | 88 ++-------- bin/node/cli/src/service.rs | 4 +- client/service/Cargo.toml | 4 +- client/service/src/bitswap.rs | 319 ---------------------------------- client/service/src/builder.rs | 44 ++++- client/service/src/lib.rs | 54 +++--- 6 files changed, 83 insertions(+), 430 deletions(-) delete mode 100644 client/service/src/bitswap.rs diff --git a/Cargo.lock b/Cargo.lock index 2778cfb753509..b4efecf16c0c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,9 +717,9 @@ checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" [[package]] name = "cached" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aaf9983f274431ca66cd5a3b19952c774384f28ff42442afeb034bfc99ac994" +checksum = "c64ed980e5a154a1a34e4de3d81d20aa985f93b1bb6ab030f7afa0208b74396e" dependencies = [ "once_cell 1.4.0", ] @@ -1382,9 +1382,9 @@ dependencies = [ [[package]] name = "either" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f" [[package]] name = "enumflags2" @@ -2893,50 +2893,24 @@ checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "libipld" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfef06ff1af915d35b840c64986ae0c83a064fdcd34e4c506e980436e1c0aab" +checksum = "c6d7d72b188d3b5e948ead7c4511ec38d9ba91ba643df4abc56c42140df63120" dependencies = [ "async-std", "async-trait", "cached", - "libipld-cbor", - "libipld-cbor-derive", "libipld-core", - "libipld-json", "libipld-macro", - "libipld-pb", - "thiserror", -] - -[[package]] -name = "libipld-cbor" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025039273c91b943ff9c0e5818e43b13bd8eddcbd71d50ad3b5c4f3a001c7062" -dependencies = [ - "byteorder 1.3.4", - "libipld-core", + "log", "thiserror", ] -[[package]] -name = "libipld-cbor-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c482f222852993f971370c4a452b9460ba848ae0757c414993e825e05e6b36" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "libipld-core" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef7d2c3293102e8e25230c6e00f25c84067f9a56f033e6ff18ad1ea5473a28f2" +checksum = "4aedaeb9d3ffbd21570c2d046e54507c2029b0da3ef0c514a85046c967a7d9ce" dependencies = [ "anyhow", "multibase", @@ -2945,37 +2919,13 @@ dependencies = [ "tiny-multihash", ] -[[package]] -name = "libipld-json" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fa78242b6e9fb8d17e5ba73c7554add83543f6fa07f6f26db8a93d4b94dec4" -dependencies = [ - "base64 0.12.3", - "libipld-core", - "serde", - "serde_json", -] - [[package]] name = "libipld-macro" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e06b4b9e648e7b9089e794511eb902fa515ba8fbc8ea3377225e654272e6840" -dependencies = [ - "libipld-core", -] - -[[package]] -name = "libipld-pb" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb620478c1158bd4fb862dac9f80df4c34ba315e1055b76c52ca221b1bad1e1" +checksum = "e8f9dcf12344151583a17ca2cadee0453ed93d9dd7db9b005fba8cf7e917ba7a" dependencies = [ "libipld-core", - "prost", - "prost-build", - "thiserror", ] [[package]] @@ -3050,7 +3000,7 @@ dependencies = [ "thiserror", "tiny-cid", "tiny-multihash", - "unsigned-varint 0.5.0", + "unsigned-varint 0.5.1", ] [[package]] @@ -5380,9 +5330,9 @@ dependencies = [ [[package]] name = "parity-multiaddr" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc20af3143a62c16e7c9e92ea5c6ae49f7d271d97d4d8fe73afc28f0514a3d0f" +checksum = "2165a93382a93de55868dcbfa11e4a8f99676a9164eee6a2b4a9479ad319c257" dependencies = [ "arrayref", "bs58", @@ -7480,7 +7430,6 @@ dependencies = [ "lazy_static", "libipld", "log", - "multihash", "parity-scale-codec", "parity-util-mem", "parking_lot 0.10.2", @@ -7526,7 +7475,6 @@ dependencies = [ "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", - "tiny-cid", "tokio 0.2.22", "tracing", "wasm-timer", @@ -9384,7 +9332,7 @@ checksum = "1b635d214a0d951465523fd67ad11faf8838ad927b5a85f021142d4349d89f00" dependencies = [ "multibase", "tiny-multihash", - "unsigned-varint 0.5.0", + "unsigned-varint 0.5.1", ] [[package]] @@ -9413,7 +9361,7 @@ dependencies = [ "sha3 0.9.1", "strobe-rs", "tiny-multihash-derive", - "unsigned-varint 0.5.0", + "unsigned-varint 0.5.1", ] [[package]] @@ -10019,9 +9967,9 @@ dependencies = [ [[package]] name = "unsigned-varint" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98e44fc6af1e18c3a06666d829b4fd8d2714fb2dbffe8ab99d5dc7ea6baa628" +checksum = "f7fdeedbf205afadfe39ae559b75c3240f24e257d0ca27e85f85cb82aa19ac35" [[package]] name = "untrusted" diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index c2ea967d03228..2cd1fd26b9075 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -181,7 +181,6 @@ pub fn new_full_base( sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), - backend: backend.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, @@ -189,6 +188,7 @@ pub fn new_full_base( block_announce_validator_builder: None, finality_proof_request_builder: None, finality_proof_provider: Some(finality_proof_provider.clone()), + ipld_store_builder: (), })?; if config.offchain_worker.enabled { @@ -405,7 +405,6 @@ pub fn new_light_base(config: Configuration) -> Result<( sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), - backend: backend.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, @@ -413,6 +412,7 @@ pub fn new_light_base(config: Configuration) -> Result<( block_announce_validator_builder: None, finality_proof_request_builder: Some(finality_proof_request_builder), finality_proof_provider: Some(finality_proof_provider), + ipld_store_builder: (), })?; network_starter.start_network(); diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 6faa49eec7195..7a426480d5dfa 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -75,9 +75,7 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../.. sc-tracing = { version = "2.0.0-rc6", path = "../tracing" } tracing = "0.1.18" parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } -multihash = "0.11.2" -tiny-cid = "0.2.5" -libipld = "0.4.0" +libipld = { version = "0.5.1", default-features = false } [target.'cfg(not(target_os = "unknown"))'.dependencies] tempfile = "3.1.0" diff --git a/client/service/src/bitswap.rs b/client/service/src/bitswap.rs deleted file mode 100644 index 0e05e6c925d45..0000000000000 --- a/client/service/src/bitswap.rs +++ /dev/null @@ -1,319 +0,0 @@ - -// This file is part of Substrate. - -// Copyright (C) 2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use libipld::error; -use libipld::store::{StoreResult, Store, ReadonlyStore}; -pub use libipld::error::Error; -use sp_core::offchain::OffchainStorage; -use codec::{Decode, Encode}; -use std::collections::HashSet; -use log::debug; - -type Block = libipld::Block; - -const BLOCK: &'static [u8] = b"bitswap_block"; -const PINS: &'static [u8] = b"bitswap_pins"; -const REFERRERS: &'static [u8] = b"bitswap_referrers"; -const REFS: &'static [u8] = b"bitswap_refs"; - -/// A wrapper around an `OffchainStorage` for the purpose of storing bitswap blocks. -/// -/// This is based on the implementation of the `libipld` -/// [`MemStore`](https://github.com/ipfs-rust/rust-ipld/blob/604fa5782479f322faa17d17ef3cbbb7f6e88aee/src/mem.rs#L13). -/// -/// Mappings: -/// -/// * `bitswap_block`: Cid -> Block bytes (`Vec`). -/// * `bitswap_pins`: Cid -> Number of pins a block has (`u64`). -/// * `bitswap_referrers`: Cid -> Number of blocks that we know refers to a block (`i64`, may be negative). -/// * `bitswap_refs`: Cid -> List of Cids a block refers to (`Vec`) -#[derive(Clone, Debug, Default)] -pub struct BitswapStorage { - storage: S, -} - -impl BitswapStorage { - /// Wrap an `OffchainStorage`. - pub fn new(storage: S) -> Self { - Self { - storage, - } - } - - fn get_any(&self, prefix: &[u8], cid: &tiny_cid::Cid) -> Result, Error> { - self.storage.get(prefix, &cid.to_bytes()[..]) - .ok_or_else(|| error::BlockNotFound(cid.to_string()).into()) - } - - fn get_and_decode_any(&self, prefix: &[u8], cid: &tiny_cid::Cid) -> Result { - let bytes = self.get_any(prefix, cid)?; - D::decode(&mut &bytes[..]) - .map_err(|error| error.into()) - } - - /// Get a block - pub fn get(&self, cid: &tiny_cid::Cid) -> Result, Error> { - self.get_any(BLOCK, cid) - } - - fn encode_and_set_any(&mut self, prefix: &[u8], cid: &tiny_cid::Cid, object: E) { - let cid_bytes = &cid.to_bytes()[..]; - let bytes = object.encode(); - self.storage.set(prefix, cid_bytes, &bytes[..]); - } - - fn modify_referrers(&mut self, cid: &tiny_cid::Cid, n: i64) { - let referrers = self.get_and_decode_any::(REFERRERS, cid).unwrap_or(0); - self.encode_and_set_any(REFERRERS, cid, referrers + n); - } - - fn pin(&mut self, cid: &tiny_cid::Cid) { - let mut pins = self.get_and_decode_any::(PINS, cid).unwrap_or(0); - pins += 1; - debug!("Pinning {}. Pins: {}.", cid, pins); - self.encode_and_set_any(PINS, cid, pins); - } - - /// Remove a pin from a block, removing it from the storage if it's the last pin. - pub fn unpin(&mut self, cid: &tiny_cid::Cid) -> Result<(), Error> { - let mut pins = self.get_and_decode_any::(PINS, cid)?; - pins -= 1; - self.encode_and_set_any(PINS, cid, pins); - - debug!("Unpinning {}. Pins: {}", cid, pins); - - if pins == 0 { - self.remove(cid)?; - } - - Ok(()) - } - - fn get_refs(&self, cid: &tiny_cid::Cid) -> Result, Error> { - self.get_and_decode_any::>>(REFS, cid)? - .into_iter() - .map(|bytes| { - use std::convert::TryFrom; - tiny_cid::Cid::try_from(bytes) - .map_err(|err| err.into()) - - }) - .collect() - } - - fn set_refs(&mut self, cid: &tiny_cid::Cid, refs: HashSet) { - let vec: Vec> = refs - .into_iter() - .map(|cid| cid.to_bytes()) - .collect(); - - self.encode_and_set_any(REFS, cid, vec); - } - - fn remove(&mut self, cid: &tiny_cid::Cid) -> Result<(), Error> { - let pins = self.get_and_decode_any::(PINS, cid).unwrap_or_default(); - let referrers = self.get_and_decode_any::(REFERRERS, cid).unwrap_or_default(); - - debug!("Removing {}. Pins: {}, referrers: {}", cid, pins, referrers); - - if referrers < 1 && pins < 1 { - let cid_bytes = &cid.to_bytes()[..]; - - let refs = self.get_refs(cid)?; - - self.storage.remove(REFERRERS, cid_bytes); - self.storage.remove(BLOCK, cid_bytes); - self.storage.remove(PINS, cid_bytes); - self.storage.remove(REFS, cid_bytes); - - for cid in &refs { - self.modify_referrers(cid, -1); - self.remove(cid)?; - } - } - - Ok(()) - } - - /// Insert an ipld block into the storage and pin it. - pub fn insert_and_pin(&mut self, cid: &tiny_cid::Cid, data: Box<[u8]>) -> Result<(), Error> { - self.insert(cid, data)?; - self.pin(cid); - Ok(()) - } - - /// Insert an ipld block into the storage. - pub fn insert(&mut self, cid: &tiny_cid::Cid, data: Box<[u8]>) -> Result<(), Error> { - if self.get_any(BLOCK, cid).is_ok() { - return Ok(()) - } - - debug!("Inserting {} into storage.", cid); - - let ipld = Block::new(cid.clone(), data.clone()).decode_ipld()?; - let refs = ipld.references(); - - for cid in &refs { - self.modify_referrers(cid, 1); - } - - self.set_refs(cid, refs); - - let cid_bytes = &cid.to_bytes()[..]; - self.storage.set(BLOCK, cid_bytes, &data); - - Ok(()) - } - - fn insert_batch_inner(&mut self, batch: &[Block]) -> Result { - let mut last_cid = None; - for Block { cid, data, .. } in batch.iter().cloned() { - self.insert(&cid, data)?; - last_cid = Some(cid); - } - Ok(last_cid.ok_or(error::EmptyBatch)?) - } -} - -impl ReadonlyStore for BitswapStorage { - const MAX_BLOCK_SIZE: usize = libipld::MAX_BLOCK_SIZE; - - type Multihash = libipld::Multihash; - type Codec = libipld::codec_impl::Multicodec; - - fn get<'a>(&'a self, cid: tiny_cid::Cid) -> StoreResult<'a, Block> { - Box::pin(async move { - let vec = self.get_any(BLOCK, &cid)?; - let block = Block::new(cid, vec.into_boxed_slice()); - Ok(block) - }) - } -} - -impl Store for BitswapStorage { - fn flush(&self) -> StoreResult<'_, ()> { - Box::pin(async move { Ok(()) }) - } - - fn insert<'a>( - &'a self, - block: &'a Block, - ) -> StoreResult<'a, ()> { - Box::pin(async move { - BitswapStorage::insert(&mut self.clone(), &block.cid, block.data.clone())?; - self.clone().pin(&block.cid); - Ok(()) - }) - } - - fn insert_batch<'a>( - &'a self, - batch: &'a [Block], - ) -> StoreResult<'a, tiny_cid::Cid> { - Box::pin(async move { - self.clone().insert_batch_inner(batch) - }) - } - - fn unpin<'a>(&'a self, cid: &'a tiny_cid::Cid) -> StoreResult<'a, ()> { - Box::pin(async move { - BitswapStorage::unpin(&mut self.clone(), cid) - }) - } -} - -// These tests are copied from -// https://github.com/ipfs-rust/rust-ipld/blob/604fa5782479f322faa17d17ef3cbbb7f6e88aee/src/mem.rs#L221. -#[cfg(test)] -mod tests { - use super::*; - use libipld::codec_impl::Multicodec; - use tiny_cid::Cid; - use libipld::ipld; - use libipld::ipld::Ipld; - use libipld::multihash::SHA2_256; - use libipld::store::Store; - use libipld::error::BlockNotFound; - use sp_core::offchain::testing::TestPersistentOffchainDB; - type Storage = BitswapStorage; - - async fn get(store: &S, cid: &Cid) -> Option - where - Ipld: libipld::codec::Decode, - { - let block = match store.get(cid.clone()).await { - Ok(block) => block, - Err(e) if e.downcast_ref::().is_some() => return None, - Err(e) => Err(e).unwrap(), - }; - let ipld = block.decode::<_, Ipld>().unwrap(); - Some(ipld) - } - - async fn insert>(store: &S, ipld: &Ipld) -> Cid - where - S::Codec: From, - { - let block = Block::encode(Multicodec::DagCbor, SHA2_256, ipld).unwrap(); - store.insert(&block).await.unwrap(); - block.cid - } - - #[async_std::test] - async fn bitswap_garbage_collection() { - let _ = env_logger::try_init(); - let store = Storage::default(); - let a = insert(&store, &ipld!({ "a": [] })).await; - let b = insert(&store, &ipld!({ "b": [&a] })).await; - store.unpin(&a).await.unwrap(); - let c = insert(&store, &ipld!({ "c": [&a] })).await; - assert!(get(&store, &a).await.is_some()); - assert!(get(&store, &b).await.is_some()); - assert!(get(&store, &c).await.is_some()); - store.unpin(&b).await.unwrap(); - assert!(get(&store, &a).await.is_some()); - assert!(get(&store, &b).await.is_none()); - assert!(get(&store, &c).await.is_some()); - store.unpin(&c).await.unwrap(); - assert!(get(&store, &a).await.is_none()); - assert!(get(&store, &b).await.is_none()); - assert!(get(&store, &c).await.is_none()); - } - - #[async_std::test] - async fn bitswap_garbage_collection_2() { - let _ = env_logger::try_init(); - let store = Storage::default(); - let a = insert(&store, &ipld!({ "a": [] })).await; - let b = insert(&store, &ipld!({ "b": [&a] })).await; - store.unpin(&a).await.unwrap(); - let c = insert(&store, &ipld!({ "b": [&a] })).await; - assert!(get(&store, &a).await.is_some()); - assert!(get(&store, &b).await.is_some()); - assert!(get(&store, &c).await.is_some()); - store.unpin(&b).await.unwrap(); - assert!(get(&store, &a).await.is_some()); - assert!(get(&store, &b).await.is_some()); - assert!(get(&store, &c).await.is_some()); - store.unpin(&c).await.unwrap(); - assert!(get(&store, &a).await.is_none()); - assert!(get(&store, &b).await.is_none()); - assert!(get(&store, &c).await.is_none()); - } -} diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 390a9666044bd..24663a1875c96 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -750,13 +750,11 @@ fn gen_handler( } /// Parameters to pass into `build_network`. -pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl, TBackend> { +pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl, TIpld: IpldStoreBuilder> { /// The service configuration. pub config: &'a Configuration, /// A shared client returned by `new_full_parts`/`new_light_parts`. pub client: Arc, - /// A shared backend returned by `new_full_parts`/`new_light_parts`. - pub backend: Arc, /// A shared transaction pool. pub transaction_pool: Arc, /// A handle for spawning tasks. @@ -773,11 +771,40 @@ pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl, TBackend> { pub finality_proof_request_builder: Option>, /// An optional, shared finality proof request provider. pub finality_proof_provider: Option>>, + /// The builder for an IPLD store.f + pub ipld_store_builder: TIpld, +} + +/// Something that builds an IPLD store. You generally want `()`, which always returns `None`. +pub trait IpldStoreBuilder { + /// The type of store to potentially build. + type Store: libipld::store::Store+ + 'static; + + /// Build the store. + fn build(self) -> Option; } +impl IpldStoreBuilder for () { + type Store = libipld::mem::MemStore; + + fn build(self) -> Option { + None + } +} + +impl + 'static> IpldStoreBuilder for Option { + type Store = T; + + fn build(self) -> Option { + self + } +} + +#[warn(invalid_type_param_default)] /// Build the network service, the network status sinks and an RPC sender. -pub fn build_network( - params: BuildNetworkParams +pub fn build_network( + params: BuildNetworkParams ) -> Result< ( Arc::Hash>>, @@ -794,11 +821,12 @@ pub fn build_network( HeaderBackend + BlockchainEvents + 'static, TExPool: MaintainedTransactionPool::Hash> + 'static, TImpQu: ImportQueue + 'static, - TBackend: Send + Sync + sc_client_api::Backend + 'static, + TIpld: IpldStoreBuilder, { let BuildNetworkParams { - config, client, backend, transaction_pool, spawn_handle, import_queue, on_demand, + config, client, transaction_pool, spawn_handle, import_queue, on_demand, block_announce_validator_builder, finality_proof_request_builder, finality_proof_provider, + ipld_store_builder, } = params; let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { @@ -861,7 +889,7 @@ pub fn build_network( system_rpc_rx, has_bootnodes, config.announce_block, - backend, + ipld_store_builder.build(), ); // TODO: Normally, one is supposed to pass a list of notifications protocols supported by the diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index c5302e7b64b23..b739b3ccf18b4 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -33,7 +33,6 @@ pub mod client; #[cfg(not(feature = "test-helpers"))] mod client; mod task_manager; -mod bitswap; use std::{io, pin::Pin}; use std::net::SocketAddr; @@ -50,14 +49,13 @@ use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use parity_util_mem::MallocSizeOf; use sp_utils::{status_sinks, mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}}; -use sp_api::offchain::OffchainStorage; pub use self::error::Error; pub use self::builder::{ new_full_client, new_client, new_full_parts, new_light_parts, spawn_tasks, build_network, BuildNetworkParams, NetworkStarter, build_offchain_workers, SpawnTasksParams, TFullClient, TLightClient, TFullBackend, TLightBackend, - TLightBackendWithHash, TLightClientWithBackend, + TLightBackendWithHash, TLightClientWithBackend, IpldStoreBuilder, TFullCallExecutor, TLightCallExecutor, RpcExtensionBuilder, NoopRpcExtensionBuilder, }; pub use config::{ @@ -84,7 +82,9 @@ pub use task_manager::TaskManager; pub use sp_consensus::import_queue::ImportQueue; use sc_client_api::BlockchainEvents; pub use sc_keystore::KeyStorePtr as KeyStore; -pub use bitswap::{BitswapStorage, Error as BitswapStorageError}; + +use libipld::store::Store as IpldStore; +use libipld::DefaultStoreParams as IpldStoreParams; const DEFAULT_PROTOCOL_ID: &str = "sup"; @@ -204,7 +204,7 @@ async fn build_network_future< B: BlockT, C: BlockchainEvents, H: sc_network::ExHashT, - BE: sc_client_api::Backend, + S: IpldStore + 'static, > ( role: Role, mut network: sc_network::NetworkWorker, @@ -213,7 +213,7 @@ async fn build_network_future< mut rpc_rx: TracingUnboundedReceiver>, should_have_peers: bool, announce_imported_blocks: bool, - backend: Arc, + ipld_store: Option, ) { let mut imported_blocks_stream = client.import_notification_stream().fuse(); @@ -236,13 +236,22 @@ async fn build_network_future< }).fuse() }; - - let mut bitswap_events = network.service().event_stream("bitswap") + let network_service = network.service().clone(); + let mut handle_bitswap_events = network.service().event_stream("bitswap") .filter_map(|event| future::ready(if let sc_network::Event::Bitswap(event) = event { Some(event) } else { None - })).fuse(); + })) + .for_each(|event| { + Box::pin(async { + if let Some(store) = ipld_store.clone() { + if let Err(err) = handle_bitswap_event(&network_service, event, store).await { + warn!("{}", err); + } + } + }) + }); loop { futures::select!{ @@ -357,39 +366,28 @@ async fn build_network_future< state_sink.send(network.network_state()); } - event = bitswap_events.select_next_some() => { - if let Some(offchain) = backend.offchain_storage() { - if let Err(err) = handle_bitswap_event(network.service(), event, offchain) { - warn!("{}", err); - } - } - } + _ = (&mut handle_bitswap_events).fuse() => {} } } } /// Handle a `BitswapEvent`, reading and writing from the `OffchainStorage`. -pub fn handle_bitswap_event( +pub async fn handle_bitswap_event>( service: &Arc>, event: sc_network::BitswapEvent, storage: S, -) -> Result<(), BitswapStorageError> { - let mut storage = BitswapStorage::new(storage); - +) -> Result<(), libipld::error::Error> { match event { sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { - storage.insert(&cid, data.clone())?; + storage.insert(libipld::Block::new(cid.clone(), data.to_vec())?).await?; service.put_value(cid.to_bytes().into(), data.to_vec()); Ok(()) }, sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { - match storage.get(&cid) { - Ok(data) => { - service.bitswap_send_block(peer_id, cid, data.into_boxed_slice()); - Ok(()) - }, - Err(error) => Err(error) - } + let block = storage.get(&cid).await?; + let (_, data) = block.into_inner(); + service.bitswap_send_block(peer_id, cid, data.into_boxed_slice()); + Ok(()) } } } From 1f9c1716f956aa3565cd71a6e63a611086595262 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Fri, 18 Sep 2020 13:32:32 +0200 Subject: [PATCH 14/18] Fix wasm build --- Cargo.lock | 5 ----- Cargo.toml | 3 --- client/network/src/gossip.rs | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d28bcfa2d041..713503bdd413d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10593,8 +10593,3 @@ dependencies = [ "itertools 0.9.0", "libc", ] - -[[patch.unused]] -name = "async-std" -version = "1.6.3" -source = "git+https://github.com/expenses/async-std?branch=wasm-join-handle-future#ceb8258d9721cb10bdb110b8df9c356b3ef8d203" diff --git a/Cargo.toml b/Cargo.toml index 8a735de7339c6..8f483234dfa87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -256,6 +256,3 @@ zeroize = { opt-level = 3 } [profile.release] # Substrate runtime requires unwinding. panic = "unwind" - -[patch.crates-io] -async-std = { git = "https://github.com/expenses/async-std", branch = "wasm-join-handle-future" } diff --git a/client/network/src/gossip.rs b/client/network/src/gossip.rs index 0650e7a2f818b..b878ed09314f6 100644 --- a/client/network/src/gossip.rs +++ b/client/network/src/gossip.rs @@ -81,7 +81,7 @@ impl QueuedSender { protocol: ConsensusEngineId, queue_size_limit: usize, messages_encode: F - ) -> (Self, impl Future + Send + 'static) + ) -> (Self, impl Future + 'static) where M: Send + 'static, B: BlockT + 'static, From 9923b11ee08fe21b768b1122da21f0ae47264154 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Fri, 18 Sep 2020 15:51:19 +0200 Subject: [PATCH 15/18] Remove stuff --- Cargo.lock | 3 -- bin/node-template/node/src/service.rs | 2 -- bin/node/cli/Cargo.toml | 3 -- bin/node/cli/src/service.rs | 2 -- client/service/Cargo.toml | 2 -- client/service/src/builder.rs | 38 ++------------------ client/service/src/lib.rs | 51 ++------------------------- 7 files changed, 6 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 713503bdd413d..4162f303b2088 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3901,7 +3901,6 @@ name = "node-cli" version = "2.0.0-rc6" dependencies = [ "assert_cmd", - "async-std", "frame-benchmarking-cli", "frame-support", "frame-system", @@ -7398,7 +7397,6 @@ dependencies = [ "async-std", "derive_more", "directories", - "env_logger", "exit-future", "futures 0.1.29", "futures 0.3.5", @@ -7407,7 +7405,6 @@ dependencies = [ "jsonrpc-core", "jsonrpc-pubsub", "lazy_static", - "libipld", "log", "parity-scale-codec", "parity-util-mem", diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 2e299f5405c20..3de31dc61ab51 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -101,7 +101,6 @@ pub fn new_full(config: Configuration) -> Result { block_announce_validator_builder: None, finality_proof_request_builder: None, finality_proof_provider: Some(finality_proof_provider.clone()), - ipld_store_builder: (), })?; if config.offchain_worker.enabled { @@ -274,7 +273,6 @@ pub fn new_light(config: Configuration) -> Result { block_announce_validator_builder: None, finality_proof_request_builder: Some(finality_proof_request_builder), finality_proof_provider: Some(finality_proof_provider), - ipld_store_builder: (), })?; if config.offchain_worker.enabled { diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index e7d4b4b5a6105..26894a9115c89 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -103,8 +103,6 @@ node-inspect = { version = "0.8.0-rc6", optional = true, path = "../inspect" } wasm-bindgen = { version = "0.2.57", optional = true } wasm-bindgen-futures = { version = "0.4.7", optional = true } browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.8.0-rc6"} -# `async-std` for wasm doesn't compile with `-Z features=itarget` without this feature -async-std = { version = "1.6.3", optional = true, features = ["unstable"] } [target.'cfg(target_arch="x86_64")'.dependencies] node-executor = { version = "2.0.0-rc6", path = "../executor", features = [ "wasmtime" ] } @@ -145,7 +143,6 @@ browser = [ "browser-utils", "wasm-bindgen", "wasm-bindgen-futures", - "async-std", ] cli = [ "node-executor/wasmi-errno", diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 1f35d053f4111..03347e455e6a3 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -188,7 +188,6 @@ pub fn new_full_base( block_announce_validator_builder: None, finality_proof_request_builder: None, finality_proof_provider: Some(finality_proof_provider.clone()), - ipld_store_builder: (), })?; if config.offchain_worker.enabled { @@ -412,7 +411,6 @@ pub fn new_light_base(config: Configuration) -> Result<( block_announce_validator_builder: None, finality_proof_request_builder: Some(finality_proof_request_builder), finality_proof_provider: Some(finality_proof_provider), - ipld_store_builder: (), })?; network_starter.start_network(); diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 4f258531c2035..fb9d489adf480 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -76,7 +76,6 @@ sc-tracing = { version = "2.0.0-rc6", path = "../tracing" } sp-tracing = { version = "2.0.0-rc6", path = "../../primitives/tracing" } tracing = "0.1.19" parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } -libipld = { version = "0.5.1", default-features = false } [target.'cfg(not(target_os = "unknown"))'.dependencies] tempfile = "3.1.0" @@ -89,4 +88,3 @@ grandpa = { version = "0.8.0-rc6", package = "sc-finality-grandpa", path = "../f grandpa-primitives = { version = "2.0.0-rc6", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" } tokio = { version = "0.2", default-features = false } async-std = { version = "1.6", default-features = false } -env_logger = "0.7.1" diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index d4a44aa509c8a..25abfdffed845 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -747,7 +747,7 @@ fn gen_handler( } /// Parameters to pass into `build_network`. -pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl, TIpld: IpldStoreBuilder> { +pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> { /// The service configuration. pub config: &'a Configuration, /// A shared client returned by `new_full_parts`/`new_light_parts`. @@ -768,40 +768,11 @@ pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl, TIpld: Ipld pub finality_proof_request_builder: Option>, /// An optional, shared finality proof request provider. pub finality_proof_provider: Option>>, - /// The builder for an IPLD store.f - pub ipld_store_builder: TIpld, } -/// Something that builds an IPLD store. You generally want `()`, which always returns `None`. -pub trait IpldStoreBuilder { - /// The type of store to potentially build. - type Store: libipld::store::Store+ - 'static; - - /// Build the store. - fn build(self) -> Option; -} - -impl IpldStoreBuilder for () { - type Store = libipld::mem::MemStore; - - fn build(self) -> Option { - None - } -} - -impl + 'static> IpldStoreBuilder for Option { - type Store = T; - - fn build(self) -> Option { - self - } -} - -#[warn(invalid_type_param_default)] /// Build the network service, the network status sinks and an RPC sender. -pub fn build_network( - params: BuildNetworkParams +pub fn build_network( + params: BuildNetworkParams ) -> Result< ( Arc::Hash>>, @@ -818,12 +789,10 @@ pub fn build_network( HeaderBackend + BlockchainEvents + 'static, TExPool: MaintainedTransactionPool::Hash> + 'static, TImpQu: ImportQueue + 'static, - TIpld: IpldStoreBuilder, { let BuildNetworkParams { config, client, transaction_pool, spawn_handle, import_queue, on_demand, block_announce_validator_builder, finality_proof_request_builder, finality_proof_provider, - ipld_store_builder, } = params; let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { @@ -886,7 +855,6 @@ pub fn build_network( system_rpc_rx, has_bootnodes, config.announce_block, - ipld_store_builder.build(), ); // TODO: Normally, one is supposed to pass a list of notifications protocols supported by the diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 72842d978fcb2..4e02b77d0e373 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -20,7 +20,7 @@ //! Manages communication between them. #![warn(missing_docs)] -#![recursion_limit = "2048"] +#![recursion_limit = "1024"] pub mod config; pub mod chain_ops; @@ -41,7 +41,7 @@ use std::time::Duration; use std::task::Poll; use parking_lot::Mutex; -use futures::{Future, FutureExt, Stream, StreamExt, stream, compat::*, future}; +use futures::{Future, FutureExt, Stream, StreamExt, stream, compat::*}; use sc_network::{NetworkStatus, network_state::NetworkState, PeerId}; use log::{warn, debug, error}; use codec::{Encode, Decode}; @@ -55,7 +55,7 @@ pub use self::builder::{ new_full_client, new_client, new_full_parts, new_light_parts, spawn_tasks, build_network, BuildNetworkParams, NetworkStarter, build_offchain_workers, SpawnTasksParams, TFullClient, TLightClient, TFullBackend, TLightBackend, - TLightBackendWithHash, TLightClientWithBackend, IpldStoreBuilder, + TLightBackendWithHash, TLightClientWithBackend, TFullCallExecutor, TLightCallExecutor, RpcExtensionBuilder, NoopRpcExtensionBuilder, }; pub use config::{ @@ -83,9 +83,6 @@ pub use sp_consensus::import_queue::ImportQueue; use sc_client_api::BlockchainEvents; pub use sc_keystore::KeyStorePtr as KeyStore; -use libipld::store::Store as IpldStore; -use libipld::DefaultStoreParams as IpldStoreParams; - const DEFAULT_PROTOCOL_ID: &str = "sup"; /// A type that implements `MallocSizeOf` on native but not wasm. @@ -204,7 +201,6 @@ async fn build_network_future< B: BlockT, C: BlockchainEvents, H: sc_network::ExHashT, - S: IpldStore + 'static, > ( role: Role, mut network: sc_network::NetworkWorker, @@ -213,7 +209,6 @@ async fn build_network_future< mut rpc_rx: TracingUnboundedReceiver>, should_have_peers: bool, announce_imported_blocks: bool, - ipld_store: Option, ) { let mut imported_blocks_stream = client.import_notification_stream().fuse(); @@ -236,23 +231,6 @@ async fn build_network_future< }).fuse() }; - let network_service = network.service().clone(); - let mut handle_bitswap_events = network.service().event_stream("bitswap") - .filter_map(|event| future::ready(if let sc_network::Event::Bitswap(event) = event { - Some(event) - } else { - None - })) - .for_each(|event| { - Box::pin(async { - if let Some(store) = ipld_store.clone() { - if let Err(err) = handle_bitswap_event(&network_service, event, store).await { - warn!("{}", err); - } - } - }) - }); - loop { futures::select!{ // List of blocks that the client has imported. @@ -364,29 +342,6 @@ async fn build_network_future< state_sink = status_sinks.state.next().fuse() => { state_sink.send(network.network_state()); } - - _ = (&mut handle_bitswap_events).fuse() => {} - } - } -} - -/// Handle a `BitswapEvent`, reading and writing from the `OffchainStorage`. -pub async fn handle_bitswap_event>( - service: &Arc>, - event: sc_network::BitswapEvent, - storage: S, -) -> Result<(), libipld::error::Error> { - match event { - sc_network::BitswapEvent::ReceivedBlock(_, cid, data) => { - storage.insert(libipld::Block::new(cid.clone(), data.to_vec())?).await?; - service.put_value(cid.to_bytes().into(), data.to_vec()); - Ok(()) - }, - sc_network::BitswapEvent::ReceivedWant(peer_id, cid, _) => { - let block = storage.get(&cid).await?; - let (_, data) = block.into_inner(); - service.bitswap_send_block(peer_id, cid, data.into_boxed_slice()); - Ok(()) } } } From 30fd353bf283644662044afedf70aaac863d8b79 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Fri, 18 Sep 2020 16:02:11 +0200 Subject: [PATCH 16/18] Remove bitswap network tests --- Cargo.lock | 103 ----------------------- client/network/test/Cargo.toml | 6 -- client/network/test/src/bitswap.rs | 129 ----------------------------- client/network/test/src/lib.rs | 48 +---------- 4 files changed, 1 insertion(+), 285 deletions(-) delete mode 100644 client/network/test/src/bitswap.rs diff --git a/Cargo.lock b/Cargo.lock index 4162f303b2088..bda405aa5aee2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -689,15 +689,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" -[[package]] -name = "cached" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64ed980e5a154a1a34e4de3d81d20aa985f93b1bb6ab030f7afa0208b74396e" -dependencies = [ - "once_cell 1.4.1", -] - [[package]] name = "cargo_metadata" version = "0.10.1" @@ -2855,94 +2846,6 @@ version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" -[[package]] -name = "libipld" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6d7d72b188d3b5e948ead7c4511ec38d9ba91ba643df4abc56c42140df63120" -dependencies = [ - "async-std", - "async-trait", - "cached", - "libipld-cbor", - "libipld-cbor-derive", - "libipld-core", - "libipld-json", - "libipld-macro", - "libipld-pb", - "log", - "thiserror", -] - -[[package]] -name = "libipld-cbor" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f4cff508958813505dbbdf0049694a42078d6729ed25b56701c8962dfa16ce" -dependencies = [ - "byteorder 1.3.4", - "libipld-core", - "thiserror", -] - -[[package]] -name = "libipld-cbor-derive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc31bf44ccce7c8614f0667e1db88a6819da4b0c00fcea8c9f6df56efb1ab079" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "libipld-core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aedaeb9d3ffbd21570c2d046e54507c2029b0da3ef0c514a85046c967a7d9ce" -dependencies = [ - "anyhow", - "multibase", - "thiserror", - "tiny-cid", - "tiny-multihash", -] - -[[package]] -name = "libipld-json" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc12851f224b5a2b32717bf03b9605f9f5ec5deb0cdbe711bc04da0ede0697e" -dependencies = [ - "base64 0.12.3", - "libipld-core", - "serde", - "serde_json", -] - -[[package]] -name = "libipld-macro" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8f9dcf12344151583a17ca2cadee0453ed93d9dd7db9b005fba8cf7e917ba7a" -dependencies = [ - "libipld-core", -] - -[[package]] -name = "libipld-pb" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ff1b5cfdf3e42f44a17455d993acb157addc8dc1a32c03453aec72a6061ff3" -dependencies = [ - "libipld-core", - "prost", - "prost-build", - "thiserror", -] - [[package]] name = "libloading" version = "0.5.2" @@ -7218,18 +7121,14 @@ dependencies = [ name = "sc-network-test" version = "0.8.0-rc6" dependencies = [ - "env_logger", "futures 0.3.5", "futures-timer 3.0.2", - "libipld", "libp2p", "log", - "multihash", "parking_lot 0.10.2", "rand 0.7.3", "sc-block-builder", "sc-client-api", - "sc-client-db", "sc-consensus", "sc-network", "sc-service", @@ -7242,8 +7141,6 @@ dependencies = [ "substrate-test-runtime", "substrate-test-runtime-client", "tempfile", - "tiny-cid", - "tiny-multihash", ] [[package]] diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 7166fa8510ad4..29b1139877208 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -23,7 +23,6 @@ libp2p = { version = "0.28.1", default-features = false } sp-consensus = { version = "0.8.0-rc6", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.8.0-rc6", path = "../../../client/consensus/common" } sc-client-api = { version = "2.0.0-rc6", path = "../../api" } -sc-client-db = { version = "0.8.0-rc6", path = "../../db" } sp-blockchain = { version = "2.0.0-rc6", path = "../../../primitives/blockchain" } sp-runtime = { version = "2.0.0-rc6", path = "../../../primitives/runtime" } sp-core = { version = "2.0.0-rc6", path = "../../../primitives/core" } @@ -34,8 +33,3 @@ substrate-test-runtime = { version = "2.0.0-rc6", path = "../../../test-utils/ru tempfile = "3.1.0" sp-tracing = { version = "2.0.0-rc6", path = "../../../primitives/tracing" } sc-service = { version = "0.8.0-rc6", default-features = false, features = ["test-helpers"], path = "../../service" } -tiny-cid = "0.2.5" -multihash = "0.11.2" -tiny-multihash = "0.4.5" -libipld = "0.5.1" -env_logger = "0.7.1" diff --git a/client/network/test/src/bitswap.rs b/client/network/test/src/bitswap.rs deleted file mode 100644 index c099746adb9af..0000000000000 --- a/client/network/test/src/bitswap.rs +++ /dev/null @@ -1,129 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use futures::executor::block_on; -use super::*; -use std::ops::Range; -use tiny_multihash::StatefulHasher; -use tiny_multihash::MultihashDigest; - -fn generate_block(string: &str) -> libipld::Block { - let block = string.as_bytes().to_vec(); - let mut hasher = tiny_multihash::Sha2_256::default(); - hasher.update(&block); - let hash = tiny_multihash::Multihash::Sha2_256(hasher.finalize()); - let hash = hash.to_raw().unwrap(); - let cid = tiny_cid::Cid::new_v1(tiny_cid::RAW, hash); - libipld::Block::new(cid, block).unwrap() -} - -fn wait_until_x_peers_want_cid(net: &mut TestNet, x: usize, peers: Range, cid: &tiny_cid::Cid) { - block_on(futures::future::poll_fn::<(), _>(|cx| { - net.poll(cx); - for peer in peers.clone() { - if net.peer(peer).network.bitswap_num_peers_want(cid) != x { - return Poll::Pending - } - } - Poll::Ready(()) - })); -} - -#[test] -fn test_bitswap_peers_connect() { - let _ = ::env_logger::try_init(); - let mut net = TestNet::new(3); - - net.block_until_connected(); - - for peer in 0 .. 3 { - assert_eq!(net.peer(peer).network.bitswap_num_peers(), 2); - } -} - -#[test] -fn test_bitswap_peers_sending_and_cancelling_wants_works() { - let _ = ::env_logger::try_init(); - let mut net = TestNet::new(3); - - let block = generate_block("test_bitswap_peers_sending_and_cancelling_wants_works"); - let cid = block.cid(); - - net.peer(0).network_service().bitswap_want_block(cid.clone(), 0); - - let peer_0 = net.peer(0).id(); - - block_on(futures::future::poll_fn::<(), _>(|cx| { - net.poll(cx); - for peer in 1..3 { - if !net.peer(peer).network.bitswap_peer_wants_cid(&peer_0, &cid) { - return Poll::Pending - } - } - Poll::Ready(()) - })); - - net.peer(0).network.service().bitswap_cancel_block(cid.clone()); - - wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); -} - -#[test] -fn test_bitswap_sending_blocks_works() { - let _ = ::env_logger::try_init(); - let mut net = TestNet::new(3); - - let block = generate_block("test_bitswap_sending_blocks_works"); - let cid = block.cid(); - - net.peer(0).network.service().bitswap_want_block(cid.clone(), 0); - - wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); - - net.peer(2).network.service() - .bitswap_send_block_all(cid.clone(), block.data().to_vec().into_boxed_slice()); - - wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); - - assert_eq!(net.peer(0).get_ipld_block(&cid), Some(block.clone())); - assert_eq!(net.peer(1).get_ipld_block(&cid), None); - assert_eq!(net.peer(2).get_ipld_block(&cid), None); -} - -#[test] -fn test_bitswap_sending_blocks_from_store_works() { - let _ = ::env_logger::try_init(); - let mut net = TestNet::new(3); - - let block = generate_block("test_bitswap_sending_blocks_from_store_works"); - let cid = block.cid(); - - net.peer(2).insert_ipld_block(block.clone()).unwrap(); - - net.block_until_connected(); - - net.peer(0).network.service().bitswap_want_block(cid.clone(), 0); - - wait_until_x_peers_want_cid(&mut net, 1, 1..3, &cid); - - wait_until_x_peers_want_cid(&mut net, 0, 0..3, &cid); - - assert_eq!(net.peer(0).get_ipld_block(&cid), Some(block.clone())); - assert_eq!(net.peer(1).get_ipld_block(&cid), None); - assert_eq!(net.peer(2).get_ipld_block(&cid), Some(block.clone())); -} diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index c234f9574f89b..587feebe55c14 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -21,8 +21,6 @@ mod block_import; #[cfg(test)] mod sync; -#[cfg(test)] -mod bitswap; use std::{ borrow::Cow, collections::HashMap, pin::Pin, sync::Arc, marker::PhantomData, @@ -30,7 +28,7 @@ use std::{ }; use libp2p::build_multiaddr; -use log::{trace, warn}; +use log::trace; use sc_network::config::FinalityProofProvider; use sp_blockchain::{ HeaderBackend, Result as ClientResult, @@ -63,8 +61,6 @@ use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use sp_runtime::{ConsensusEngineId, Justification}; use substrate_test_runtime_client::{self, AccountKeyring}; use sc_service::client::Client; -use futures::executor::block_on; -use libipld::store::Store; pub use sc_network::config::EmptyTransactionPool; pub use substrate_test_runtime_client::runtime::{Block, Extrinsic, Hash, Transfer}; pub use substrate_test_runtime_client::{TestClient, TestClientBuilder, TestClientBuilderExt}; @@ -231,8 +227,6 @@ pub struct Peer { network: NetworkWorker::Hash>, imported_blocks_stream: Pin> + Send>>, finality_notification_stream: Pin> + Send>>, - bitswap_stream: Pin + Send>>, - ipld_store: libipld::mem::MemStore, } impl Peer { @@ -434,18 +428,6 @@ impl Peer { |backend| backend.blockchain().header(BlockId::hash(*hash)).unwrap().is_some() ).unwrap_or(false) } - - pub fn get_ipld_block(&self, cid: &tiny_cid::Cid) -> - Option> - { - block_on(self.ipld_store.info(&cid)).map(|info| info.block().clone()) - } - - pub fn insert_ipld_block(&self, block: libipld::Block) -> - Result<(), libipld::error::Error> - { - block_on(self.ipld_store.insert(block)) - } } /// Implements `BlockImport` for any `Transaction`. Internally the transaction is @@ -714,14 +696,6 @@ pub trait TestNetFactory: Sized { let imported_blocks_stream = Box::pin(client.import_notification_stream().fuse()); let finality_notification_stream = Box::pin(client.finality_notification_stream().fuse()); - let bitswap_stream = network.service().event_stream("bitswap") - .filter_map(|event| futures::future::ready(if let sc_network::Event::Bitswap(event) = event { - Some(event) - } else { - None - })) - .boxed(); - peers.push(Peer { data, client: PeersClient::Full(client, backend.clone()), @@ -732,8 +706,6 @@ pub trait TestNetFactory: Sized { block_import, verifier, network, - bitswap_stream, - ipld_store: Default::default(), }); }); } @@ -803,14 +775,6 @@ pub trait TestNetFactory: Sized { let imported_blocks_stream = Box::pin(client.import_notification_stream().fuse()); let finality_notification_stream = Box::pin(client.finality_notification_stream().fuse()); - let bitswap_stream = network.service().event_stream("bitswap") - .filter_map(|event| futures::future::ready(if let sc_network::Event::Bitswap(event) = event { - Some(event) - } else { - None - })) - .boxed(); - peers.push(Peer { data, verifier, @@ -821,8 +785,6 @@ pub trait TestNetFactory: Sized { imported_blocks_stream, finality_notification_stream, network, - bitswap_stream, - ipld_store: Default::default(), }); }); } @@ -928,14 +890,6 @@ pub trait TestNetFactory: Sized { if let Some(notification) = last { peer.network.on_block_finalized(notification.hash, notification.header); } - - while let Poll::Ready(Some(event)) = peer.bitswap_stream.as_mut().poll_next(cx) { - if let Err(err) = sc_service::handle_bitswap_event( - peer.network.service(), event, peer.ipld_store.clone(), - ).now_or_never().unwrap() { - warn!("{}", err); - } - } } }); } From da1c738436996bfb61e64472b3257834232d4b03 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Tue, 22 Sep 2020 15:24:18 +0200 Subject: [PATCH 17/18] Remove changes that slipped in accidentally --- client/network/Cargo.toml | 4 ++-- client/network/src/gossip.rs | 2 +- client/network/src/service.rs | 5 ----- client/rpc-api/src/system/error.rs | 2 +- client/service/src/lib.rs | 2 +- primitives/core/src/offchain/storage.rs | 2 +- primitives/core/src/offchain/testing.rs | 5 ----- 7 files changed, 6 insertions(+), 16 deletions(-) diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index a4a0a8d7e2e81..2ecbec75ec1c3 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -32,6 +32,7 @@ futures-timer = "3.0.2" futures_codec = "0.4.0" hex = "0.4.0" ip_network = "0.3.4" +libp2p-bitswap = "0.7.0" linked-hash-map = "0.5.2" linked_hash_set = "0.1.3" log = "0.4.8" @@ -57,12 +58,11 @@ sp-core = { version = "2.0.0-rc6", path = "../../primitives/core" } sp-runtime = { version = "2.0.0-rc6", path = "../../primitives/runtime" } sp-utils = { version = "2.0.0-rc6", path = "../../primitives/utils" } thiserror = "1" +tiny-cid = "0.2.5" unsigned-varint = { version = "0.4.0", features = ["futures", "futures-codec"] } void = "1.0.2" wasm-timer = "0.2" zeroize = "1.0.0" -libp2p-bitswap = "0.7.0" -tiny-cid = "0.2.5" [dependencies.libp2p] version = "0.28.1" diff --git a/client/network/src/gossip.rs b/client/network/src/gossip.rs index b878ed09314f6..0650e7a2f818b 100644 --- a/client/network/src/gossip.rs +++ b/client/network/src/gossip.rs @@ -81,7 +81,7 @@ impl QueuedSender { protocol: ConsensusEngineId, queue_size_limit: usize, messages_encode: F - ) -> (Self, impl Future + 'static) + ) -> (Self, impl Future + Send + 'static) where M: Send + 'static, B: BlockT + 'static, diff --git a/client/network/src/service.rs b/client/network/src/service.rs index d105370c95873..6c09dc0fae717 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -598,11 +598,6 @@ impl NetworkWorker { self.service.add_reserved_peer(peer) } - /// Get the number of bitswap peers we are connected to. - pub fn bitswap_num_peers(&self) -> usize { - self.network_service.bitswap.peers().count() - } - /// Get the number of bitswap peers who want a block. pub fn bitswap_num_peers_want(&self, cid: &tiny_cid::Cid) -> usize { self.network_service.bitswap.peers_want(cid).count() diff --git a/client/rpc-api/src/system/error.rs b/client/rpc-api/src/system/error.rs index 198cc374e6df9..4897aa485cbe4 100644 --- a/client/rpc-api/src/system/error.rs +++ b/client/rpc-api/src/system/error.rs @@ -48,7 +48,7 @@ impl From for rpc::Error { data: serde_json::to_value(h).ok(), }, Error::MalformattedPeerArg(ref e) => rpc::Error { - code: rpc::ErrorCode::ServerError(BASE_ERROR + 2), + code :rpc::ErrorCode::ServerError(BASE_ERROR + 2), message: e.clone(), data: None, } diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 91bb5d93efcc4..39f1dff289a1a 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -201,7 +201,7 @@ pub struct PartialComponents, - H: sc_network::ExHashT, + H: sc_network::ExHashT > ( role: Role, mut network: sc_network::NetworkWorker, diff --git a/primitives/core/src/offchain/storage.rs b/primitives/core/src/offchain/storage.rs index 363b3604ff63c..7d7c711ed95f0 100644 --- a/primitives/core/src/offchain/storage.rs +++ b/primitives/core/src/offchain/storage.rs @@ -24,7 +24,7 @@ use std::iter::Iterator; /// In-memory storage for offchain workers. #[derive(Debug, Clone, Default)] pub struct InMemOffchainStorage { - pub(crate) storage: HashMap, Vec>, + storage: HashMap, Vec>, } impl InMemOffchainStorage { diff --git a/primitives/core/src/offchain/testing.rs b/primitives/core/src/offchain/testing.rs index 706744ed7335f..3fe34cc0cfa7b 100644 --- a/primitives/core/src/offchain/testing.rs +++ b/primitives/core/src/offchain/testing.rs @@ -87,11 +87,6 @@ impl TestPersistentOffchainDB { } } } - - /// Get whether the DB is empty. - pub fn is_empty(&self) -> bool { - self.persistent.read().storage.is_empty() - } } impl OffchainStorage for TestPersistentOffchainDB { From b8f0981179025afca822ac0d3fde6849488d92f5 Mon Sep 17 00:00:00 2001 From: Ashley Ruglys Date: Tue, 22 Sep 2020 16:09:50 +0200 Subject: [PATCH 18/18] Improve documentation somewhat --- client/network/src/behaviour.rs | 44 +++++++++++++++++++++++++--- client/network/src/protocol/event.rs | 3 +- client/network/src/service.rs | 29 +++++++++--------- 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index 6d8bae3eaf638..becc127b550da 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -55,7 +55,7 @@ pub struct Behaviour { /// Discovers nodes of the network. discovery: DiscoveryBehaviour, /// Exchanges blocks of data with other nodes. - pub(crate) bitswap: libp2p_bitswap::Bitswap, + bitswap: libp2p_bitswap::Bitswap, /// Generic request-reponse protocols. request_responses: request_responses::RequestResponsesBehaviour, /// Block request handling. @@ -182,10 +182,15 @@ pub enum BehaviourOut { /// An event generated by bitswap. #[derive(Clone, Debug)] pub enum BitswapEvent { - /// A block was received. + /// A block has been received. + /// + /// There are no guarantees about the recieved block: + /// * The CID and block contents might not match. + /// * We might have receieved a block without having sent out a want request first. + /// * It is possible to receieve this message multiple times with the same block. ReceivedBlock(PeerId, tiny_cid::Cid, Box<[u8]>), - /// A WANT request was received. - ReceivedWant(PeerId, tiny_cid::Cid, i32), + /// A peer wants the block with the hash of `cid`, and with a given priority. + ReceivedWant(PeerId, tiny_cid::Cid, libp2p_bitswap::Priority), } impl Behaviour { @@ -315,6 +320,37 @@ impl Behaviour { pub fn light_client_request(&mut self, r: light_client_handler::Request) -> Result<(), light_client_handler::Error> { self.light_client_handler.request(r) } + + /// Count the number of connected peers who want the bitswap block with the hash of `cid`. + pub fn bitswap_num_peers_want(&self, cid: &tiny_cid::Cid) -> usize { + self.bitswap.peers_want(cid).count() + } + + /// Determine whether a specific peer wants a bitswap block with the hash of `cid`. + pub fn bitswap_peer_wants_cid(&self, peer_id: &PeerId, cid: &tiny_cid::Cid) -> bool { + self.bitswap.peers_want(cid).find(|id| **id == *peer_id).is_some() + } + + /// Send a bitswap block to a specific peer, regardless of whether they want it or not. + pub fn bitswap_send_block(&mut self, peer_id: &PeerId, cid: tiny_cid::Cid, block: Box<[u8]>) { + self.bitswap.send_block(peer_id, cid, block) + } + + /// Send a bitswap block to all connected peers who want it. + pub fn bitswap_send_block_all(&mut self, cid: &tiny_cid::Cid, block: &[u8]) { + self.bitswap.send_block_all(cid, block) + } + + /// Send out a bitswap message telling connected peers that we want the block with the hash of + /// `cid`. We can also say how this block should be prioritised. + pub fn bitswap_want_block(&mut self, cid: tiny_cid::Cid, priority: libp2p_bitswap::Priority) { + self.bitswap.want_block(cid, priority) + } + + /// Send out a bitswap message cancelling a previously wanted block with the hash of `cid`. + pub fn bitswap_cancel_block(&mut self, cid: &tiny_cid::Cid) { + self.bitswap.cancel_block(cid) + } } fn reported_roles_to_observed_role(local_role: &Role, remote: &PeerId, roles: Roles) -> ObservedRole { diff --git a/client/network/src/protocol/event.rs b/client/network/src/protocol/event.rs index 0e45e38e8ca31..3bc52207530ae 100644 --- a/client/network/src/protocol/event.rs +++ b/client/network/src/protocol/event.rs @@ -21,7 +21,8 @@ use bytes::Bytes; use libp2p::core::PeerId; use libp2p::kad::record::Key; use sp_runtime::ConsensusEngineId; -use crate::behaviour::BitswapEvent; + +pub use crate::behaviour::BitswapEvent; /// Events generated by DHT as a response to get_value and put_value requests. #[derive(Debug, Clone)] diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 6c09dc0fae717..64d9526707d03 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -598,14 +598,14 @@ impl NetworkWorker { self.service.add_reserved_peer(peer) } - /// Get the number of bitswap peers who want a block. + /// Count the number of connected peers who want the bitswap block with the hash of `cid`. pub fn bitswap_num_peers_want(&self, cid: &tiny_cid::Cid) -> usize { - self.network_service.bitswap.peers_want(cid).count() + self.network_service.bitswap_num_peers_want(cid) } - /// Get if a specific bitswap peer wants a block. + /// Determine whether a specific peer wants a bitswap block with the hash of `cid`. pub fn bitswap_peer_wants_cid(&self, peer_id: &PeerId, cid: &tiny_cid::Cid) -> bool { - self.network_service.bitswap.peers_want(cid).find(|id| **id == *peer_id).is_some() + self.network_service.bitswap_peer_wants_cid(peer_id, cid) } } @@ -1038,28 +1038,29 @@ impl NetworkService { .unbounded_send(ServiceToWorkerMsg::OwnBlockImported(hash, number)); } - /// Send a bitswap block to a peer. + /// Send a bitswap block to a specific peer, regardless of whether they want it or not. pub fn bitswap_send_block(&self, peer_id: PeerId, cid: tiny_cid::Cid, data: Box<[u8]>) { let _ = self .to_worker .unbounded_send(ServiceToWorkerMsg::BitswapSendBlock(peer_id, cid, data)); } - /// Send a bitswap block to all peers that have the block in their wantlist. + /// Send a bitswap block to all connected peers who want it. pub fn bitswap_send_block_all(&self, cid: tiny_cid::Cid, data: Box<[u8]>) { let _ = self .to_worker .unbounded_send(ServiceToWorkerMsg::BitswapSendBlockAll(cid, data)); } - /// Send a bitswap WANT request to all peers for a block. - pub fn bitswap_want_block(&self, cid: tiny_cid::Cid, priority: i32) { + /// Send out a bitswap message telling connected peers that we want the block with the hash of + /// `cid`. We can also say how this block should be prioritised. + pub fn bitswap_want_block(&self, cid: tiny_cid::Cid, priority: libp2p_bitswap::Priority) { let _ = self .to_worker .unbounded_send(ServiceToWorkerMsg::BitswapWantBlock(cid, priority)); } - /// Cancel a bitswap WANT request. + /// Send out a bitswap message cancelling a previously wanted block with the hash of `cid`. pub fn bitswap_cancel_block(&self, cid: tiny_cid::Cid) { let _ = self .to_worker @@ -1199,7 +1200,7 @@ enum ServiceToWorkerMsg { OwnBlockImported(B::Hash, NumberFor), BitswapSendBlock(PeerId, tiny_cid::Cid, Box<[u8]>), BitswapSendBlockAll(tiny_cid::Cid, Box<[u8]>), - BitswapWantBlock(tiny_cid::Cid, i32), + BitswapWantBlock(tiny_cid::Cid, libp2p_bitswap::Priority), BitswapCancelBlock(tiny_cid::Cid), } @@ -1344,13 +1345,13 @@ impl Future for NetworkWorker { ServiceToWorkerMsg::OwnBlockImported(hash, number) => this.network_service.user_protocol_mut().own_block_imported(hash, number), ServiceToWorkerMsg::BitswapSendBlock(peer_id, cid, block) => - this.network_service.bitswap.send_block(&peer_id, cid, block), + this.network_service.bitswap_send_block(&peer_id, cid, block), ServiceToWorkerMsg::BitswapSendBlockAll(cid, block) => - this.network_service.bitswap.send_block_all(&cid, &block), + this.network_service.bitswap_send_block_all(&cid, &block), ServiceToWorkerMsg::BitswapWantBlock(cid, priority) => - this.network_service.bitswap.want_block(cid, priority), + this.network_service.bitswap_want_block(cid, priority), ServiceToWorkerMsg::BitswapCancelBlock(cid) => - this.network_service.bitswap.cancel_block(&cid), + this.network_service.bitswap_cancel_block(&cid), } }