From 2c7467e2580edc4a7a169a54858d153cc74fe70c Mon Sep 17 00:00:00 2001 From: Kolby Moroz Liebl <31669092+KolbyML@users.noreply.github.com> Date: Sat, 14 Dec 2024 12:43:52 -0700 Subject: [PATCH 1/2] refactor: update `Gossip` to `PutContent` --- book/src/developers/protocols/json_rpc.md | 4 +- ethportal-api/src/beacon.rs | 15 +++-- ethportal-api/src/history.rs | 15 +++-- ethportal-api/src/state.rs | 15 +++-- ethportal-api/src/types/jsonrpc/endpoints.rs | 12 ++-- ethportal-api/src/types/portal.rs | 14 +++- ethportal-peertest/src/scenarios/mod.rs | 2 +- .../scenarios/{gossip.rs => put_content.rs} | 6 +- portal-bridge/src/bridge/beacon.rs | 14 ++-- portal-bridge/src/bridge/era1.rs | 2 +- portal-bridge/src/bridge/history.rs | 2 +- portal-bridge/src/lib.rs | 2 +- .../src/{gossip.rs => put_content.rs} | 43 +++++++------ portal-bridge/src/stats.rs | 12 ++-- portalnet/src/lib.rs | 2 +- portalnet/src/overlay/protocol.rs | 64 ++++++++++++++----- portalnet/src/overlay/service.rs | 8 +-- portalnet/src/{gossip.rs => put_content.rs} | 61 +++++++++--------- rpc/src/beacon_rpc.rs | 16 ++--- rpc/src/history_rpc.rs | 16 ++--- rpc/src/state_rpc.rs | 16 ++--- tests/self_peertest.rs | 7 +- trin-beacon/src/jsonrpc.rs | 19 +++--- trin-history/src/jsonrpc.rs | 23 ++++--- trin-state/src/jsonrpc.rs | 20 +++--- 25 files changed, 229 insertions(+), 181 deletions(-) rename ethportal-peertest/src/scenarios/{gossip.rs => put_content.rs} (98%) rename portal-bridge/src/{gossip.rs => put_content.rs} (79%) rename portalnet/src/{gossip.rs => put_content.rs} (81%) diff --git a/book/src/developers/protocols/json_rpc.md b/book/src/developers/protocols/json_rpc.md index 5574413eb..10b36b3bc 100644 --- a/book/src/developers/protocols/json_rpc.md +++ b/book/src/developers/protocols/json_rpc.md @@ -12,7 +12,7 @@ The specification for these endpoints can be found [here](https://playground.ope - `discv5_routingTableInfo` - `portal_historyFindContent` - `portal_historyFindNodes` -- `portal_historyGossip` +- `portal_historyPutContent` - `portal_historyLocalContent` - `portal_historyPing` - `portal_historyOffer` @@ -21,7 +21,7 @@ The specification for these endpoints can be found [here](https://playground.ope - `portal_stateFindContent` - `portal_stateFindNodes` - `portal_stateLocalContent` -- `portal_stateGossip` +- `portal_statePutContent` - `portal_stateOffer` - `portal_stateStore` - `portal_statePing` diff --git a/ethportal-api/src/beacon.rs b/ethportal-api/src/beacon.rs index 1ecd00ef8..24e689f78 100644 --- a/ethportal-api/src/beacon.rs +++ b/ethportal-api/src/beacon.rs @@ -14,7 +14,8 @@ use crate::{ enr::Enr, portal::{ AcceptInfo, DataRadius, FindContentInfo, FindNodesInfo, GetContentInfo, - PaginateLocalContentInfo, PongInfo, TraceContentInfo, TraceGossipInfo, + PaginateLocalContentInfo, PongInfo, PutContentInfo, TraceContentInfo, + TracePutContentInfo, }, portal_wire::OfferTrace, }, @@ -114,21 +115,21 @@ pub trait BeaconNetworkApi { /// Send the provided content value to interested peers. Clients may choose to send to some or /// all peers. Return the number of peers that the content was gossiped to. - #[method(name = "beaconGossip")] - async fn gossip( + #[method(name = "beaconPutContent")] + async fn put_content( &self, content_key: BeaconContentKey, content_value: RawContentValue, - ) -> RpcResult; + ) -> RpcResult; /// Send the provided content value to interested peers. Clients may choose to send to some or /// all peers. Return tracing info detailing the gossip propagation. - #[method(name = "beaconTraceGossip")] - async fn trace_gossip( + #[method(name = "beaconTracePutContent")] + async fn trace_put_content( &self, content_key: BeaconContentKey, content_value: RawContentValue, - ) -> RpcResult; + ) -> RpcResult; /// Send an OFFER request with given ContentItems, to the designated peer and wait for a /// response. Does not store the content locally. diff --git a/ethportal-api/src/history.rs b/ethportal-api/src/history.rs index 6e56d4da0..c02fb58c6 100644 --- a/ethportal-api/src/history.rs +++ b/ethportal-api/src/history.rs @@ -7,7 +7,8 @@ use crate::{ enr::Enr, portal::{ AcceptInfo, DataRadius, FindContentInfo, FindNodesInfo, GetContentInfo, - PaginateLocalContentInfo, PongInfo, TraceContentInfo, TraceGossipInfo, + PaginateLocalContentInfo, PongInfo, PutContentInfo, TraceContentInfo, + TracePutContentInfo, }, portal_wire::OfferTrace, }, @@ -85,21 +86,21 @@ pub trait HistoryNetworkApi { /// Send the provided content value to interested peers. Clients may choose to send to some or /// all peers. Return the number of peers that the content was gossiped to. - #[method(name = "historyGossip")] - async fn gossip( + #[method(name = "historyPutContent")] + async fn put_content( &self, content_key: HistoryContentKey, content_value: RawContentValue, - ) -> RpcResult; + ) -> RpcResult; /// Send the provided content value to interested peers. Clients may choose to send to some or /// all peers. Return tracing info detailing the gossip propagation. - #[method(name = "historyTraceGossip")] - async fn trace_gossip( + #[method(name = "historyTracePutContent")] + async fn trace_put_content( &self, content_key: HistoryContentKey, content_value: RawContentValue, - ) -> RpcResult; + ) -> RpcResult; /// Send an OFFER request with given ContentItems, to the designated peer and wait for a /// response. Does not store the content locally. diff --git a/ethportal-api/src/state.rs b/ethportal-api/src/state.rs index 3fd211a9f..7357f5651 100644 --- a/ethportal-api/src/state.rs +++ b/ethportal-api/src/state.rs @@ -7,7 +7,8 @@ use crate::{ enr::Enr, portal::{ AcceptInfo, DataRadius, FindContentInfo, FindNodesInfo, GetContentInfo, - PaginateLocalContentInfo, PongInfo, TraceContentInfo, TraceGossipInfo, + PaginateLocalContentInfo, PongInfo, PutContentInfo, TraceContentInfo, + TracePutContentInfo, }, portal_wire::OfferTrace, }, @@ -82,21 +83,21 @@ pub trait StateNetworkApi { /// Send the provided content value to interested peers. Clients may choose to send to some or /// all peers. Return the number of peers that the content was gossiped to. - #[method(name = "stateGossip")] - async fn gossip( + #[method(name = "statePutContent")] + async fn put_content( &self, content_key: StateContentKey, content_value: RawContentValue, - ) -> RpcResult; + ) -> RpcResult; /// Send the provided content value to interested peers. Clients may choose to send to some or /// all peers. Return tracing info detailing the gossip propagation. - #[method(name = "stateTraceGossip")] - async fn trace_gossip( + #[method(name = "stateTracePutContent")] + async fn trace_put_content( &self, content_key: StateContentKey, content_value: RawContentValue, - ) -> RpcResult; + ) -> RpcResult; /// Send an OFFER request with given ContentItems, to the designated peer and wait for a /// response. Does not store the content locally. diff --git a/ethportal-api/src/types/jsonrpc/endpoints.rs b/ethportal-api/src/types/jsonrpc/endpoints.rs index 3398a73bc..888f3f0bd 100644 --- a/ethportal-api/src/types/jsonrpc/endpoints.rs +++ b/ethportal-api/src/types/jsonrpc/endpoints.rs @@ -48,9 +48,9 @@ pub enum StateEndpoint { /// params: [enr, content_key, content_value] TraceOffer(Enr, StateContentKey, StateContentValue), /// params: [enr, content_key, content_value] - Gossip(StateContentKey, StateContentValue), + PutContent(StateContentKey, StateContentValue), /// params: [content_key, content_value] - TraceGossip(StateContentKey, StateContentValue), + TracePutContent(StateContentKey, StateContentValue), /// params: [offset, limit] PaginateLocalContentKeys(u64, u64), } @@ -75,9 +75,9 @@ pub enum HistoryEndpoint { /// params: [node_id] LookupEnr(NodeId), /// params: [content_key, content_value] - Gossip(HistoryContentKey, HistoryContentValue), + PutContent(HistoryContentKey, HistoryContentValue), /// params: [content_key, content_value] - TraceGossip(HistoryContentKey, HistoryContentValue), + TracePutContent(HistoryContentKey, HistoryContentValue), /// params: [enr, Vec<(content_key, content_value)>] Offer(Enr, Vec<(HistoryContentKey, HistoryContentValue)>), /// params: [enr, content_key, content_value] @@ -131,9 +131,9 @@ pub enum BeaconEndpoint { /// params: node_id LookupEnr(NodeId), /// params: [content_key, content_value] - Gossip(BeaconContentKey, BeaconContentValue), + PutContent(BeaconContentKey, BeaconContentValue), /// params: [content_key, content_value] - TraceGossip(BeaconContentKey, BeaconContentValue), + TracePutContent(BeaconContentKey, BeaconContentValue), /// params: [enr, Vec<(content_key, content_value>)] Offer(Enr, Vec<(BeaconContentKey, BeaconContentValue)>), /// params: [enr, content_key, content_value] diff --git a/ethportal-api/src/types/portal.rs b/ethportal-api/src/types/portal.rs index 2bfcc39f0..98ed0231f 100644 --- a/ethportal-api/src/types/portal.rs +++ b/ethportal-api/src/types/portal.rs @@ -67,10 +67,20 @@ pub struct AcceptInfo { pub content_keys: BitList, } -/// Response for TraceGossip endpoint +/// Response for PutContent endpoint #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TraceGossipInfo { +pub struct PutContentInfo { + // Indicates how many peers the content was gossiped to + pub peer_count: u32, + // Indicates whether the content was stored locally or not + pub stored_locally: bool, +} + +/// Response for TracePutContent endpoint +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TracePutContentInfo { // List of all ENRs that were offered the content pub offered: Vec, // List of all ENRs that accepted the offer diff --git a/ethportal-peertest/src/scenarios/mod.rs b/ethportal-peertest/src/scenarios/mod.rs index 345d93b7a..fc0054a14 100644 --- a/ethportal-peertest/src/scenarios/mod.rs +++ b/ethportal-peertest/src/scenarios/mod.rs @@ -2,9 +2,9 @@ pub mod basic; pub mod bridge; pub mod eth_rpc; pub mod find; -pub mod gossip; pub mod offer_accept; pub mod paginate; +pub mod put_content; pub mod state; pub mod utp; pub mod validation; diff --git a/ethportal-peertest/src/scenarios/gossip.rs b/ethportal-peertest/src/scenarios/put_content.rs similarity index 98% rename from ethportal-peertest/src/scenarios/gossip.rs rename to ethportal-peertest/src/scenarios/put_content.rs index 3676bad88..e4852cad8 100644 --- a/ethportal-peertest/src/scenarios/gossip.rs +++ b/ethportal-peertest/src/scenarios/put_content.rs @@ -20,7 +20,7 @@ pub async fn test_gossip_with_trace(peertest: &Peertest, target: &Client) { let _ = target.ping(peertest.bootnode.enr.clone()).await.unwrap(); let (content_key, content_value) = fixture_header_by_hash(); let result = target - .trace_gossip(content_key.clone(), content_value.encode()) + .trace_put_content(content_key.clone(), content_value.encode()) .await .unwrap(); @@ -50,7 +50,7 @@ pub async fn test_gossip_with_trace(peertest: &Peertest, target: &Client) { // send new trace gossip request let result = target - .trace_gossip(content_key.clone(), content_value.encode()) + .trace_put_content(content_key.clone(), content_value.encode()) .await .unwrap(); @@ -67,7 +67,7 @@ pub async fn test_gossip_with_trace(peertest: &Peertest, target: &Client) { // test trace gossip without any expected accepts let result = target - .trace_gossip(content_key, content_value.encode()) + .trace_put_content(content_key, content_value.encode()) .await .unwrap(); diff --git a/portal-bridge/src/bridge/beacon.rs b/portal-bridge/src/bridge/beacon.rs index 37881ba81..a89ce5a2e 100644 --- a/portal-bridge/src/bridge/beacon.rs +++ b/portal-bridge/src/bridge/beacon.rs @@ -44,7 +44,7 @@ use trin_metrics::bridge::BridgeMetricsReporter; use crate::{ api::consensus::ConsensusApi, constants::BEACON_GENESIS_TIME, - gossip::gossip_beacon_content, + put_content::put_content_beacon_content, stats::{BeaconSlotStats, StatsReporter}, types::mode::BridgeMode, utils::{ @@ -127,7 +127,7 @@ impl BeaconBridge { // test files have no slot number data, so report all gossiped content at height 0. let slot_stats = Arc::new(StdMutex::new(BeaconSlotStats::new(0))); for asset in assets.0.into_iter() { - gossip_beacon_content( + put_content_beacon_content( self.portal_client.clone(), asset.content_key.clone(), asset.content_value().expect("Error getting content value"), @@ -336,7 +336,7 @@ impl BeaconBridge { }); // Return the latest finalized block root if we successfully gossiped the latest bootstrap. - gossip_beacon_content(portal_client, content_key, content_value, slot_stats).await?; + put_content_beacon_content(portal_client, content_key, content_value, slot_stats).await?; finalized_bootstrap.lock().await.finalized_block_root = latest_finalized_block_root; finalized_bootstrap.lock().await.in_progress = false; @@ -402,7 +402,7 @@ impl BeaconBridge { ); // Update the current known period if we successfully gossiped the latest data. - gossip_beacon_content(portal_client, content_key, content_value, slot_stats).await?; + put_content_beacon_content(portal_client, content_key, content_value, slot_stats).await?; *current_period.lock().await = expected_current_period; Ok(()) @@ -426,7 +426,7 @@ impl BeaconBridge { LightClientOptimisticUpdateKey::new(update.signature_slot), ); let content_value = BeaconContentValue::LightClientOptimisticUpdate(update.into()); - gossip_beacon_content(portal_client, content_key, content_value, slot_stats).await + put_content_beacon_content(portal_client, content_key, content_value, slot_stats).await } async fn serve_light_client_finality_update( @@ -465,7 +465,7 @@ impl BeaconBridge { ); let content_value = BeaconContentValue::LightClientFinalityUpdate(update.into()); - gossip_beacon_content(portal_client, content_key, content_value, slot_stats).await?; + put_content_beacon_content(portal_client, content_key, content_value, slot_stats).await?; *finalized_slot.lock().await = new_finalized_slot; Ok(()) @@ -532,7 +532,7 @@ impl BeaconBridge { let content_value = BeaconContentValue::HistoricalSummariesWithProof(historical_summaries_with_proof); - gossip_beacon_content(portal_client, content_key, content_value, slot_stats).await?; + put_content_beacon_content(portal_client, content_key, content_value, slot_stats).await?; finalized_state_root.lock().await.state_root = latest_finalized_state_root; finalized_state_root.lock().await.in_progress = false; diff --git a/portal-bridge/src/bridge/era1.rs b/portal-bridge/src/bridge/era1.rs index 473cc5f97..bb4d1faf2 100644 --- a/portal-bridge/src/bridge/era1.rs +++ b/portal-bridge/src/bridge/era1.rs @@ -37,7 +37,7 @@ use crate::{ history::{HEADER_SATURATION_DELAY, SERVE_BLOCK_TIMEOUT}, utils::lookup_epoch_acc, }, - gossip::gossip_history_content, + put_content::gossip_history_content, stats::{HistoryBlockStats, StatsReporter}, types::mode::{BridgeMode, FourFoursMode}, }; diff --git a/portal-bridge/src/bridge/history.rs b/portal-bridge/src/bridge/history.rs index f937ff251..9928663b1 100644 --- a/portal-bridge/src/bridge/history.rs +++ b/portal-bridge/src/bridge/history.rs @@ -23,7 +23,7 @@ use trin_validation::{ use crate::{ api::execution::ExecutionApi, bridge::utils::lookup_epoch_acc, - gossip::gossip_history_content, + put_content::gossip_history_content, stats::{HistoryBlockStats, StatsReporter}, types::{full_header::FullHeader, mode::BridgeMode}, utils::{read_test_assets_from_file, TestAssets}, diff --git a/portal-bridge/src/lib.rs b/portal-bridge/src/lib.rs index 50f7a7a80..c2381f47c 100644 --- a/portal-bridge/src/lib.rs +++ b/portal-bridge/src/lib.rs @@ -6,8 +6,8 @@ pub mod bridge; pub mod census; pub mod cli; pub mod constants; -pub mod gossip; pub mod handle; +pub mod put_content; pub mod stats; pub mod types; pub mod utils; diff --git a/portal-bridge/src/gossip.rs b/portal-bridge/src/put_content.rs similarity index 79% rename from portal-bridge/src/gossip.rs rename to portal-bridge/src/put_content.rs index ba133f83d..deac33e9c 100644 --- a/portal-bridge/src/gossip.rs +++ b/portal-bridge/src/put_content.rs @@ -1,9 +1,9 @@ use std::sync::{Arc, Mutex}; use ethportal_api::{ - types::portal::TraceGossipInfo, BeaconContentKey, BeaconContentValue, BeaconNetworkApiClient, - ContentValue, HistoryContentKey, HistoryContentValue, HistoryNetworkApiClient, - OverlayContentKey, + types::portal::TracePutContentInfo, BeaconContentKey, BeaconContentValue, + BeaconNetworkApiClient, ContentValue, HistoryContentKey, HistoryContentValue, + HistoryNetworkApiClient, OverlayContentKey, }; use jsonrpsee::http_client::HttpClient; use tokio::time::{sleep, Duration}; @@ -15,34 +15,35 @@ const GOSSIP_RETRY_COUNT: u64 = 3; const RETRY_AFTER: Duration = Duration::from_secs(15); /// Gossip any given content key / value to the beacon network. -pub async fn gossip_beacon_content( +pub async fn put_content_beacon_content( portal_client: HttpClient, content_key: BeaconContentKey, content_value: BeaconContentValue, slot_stats: Arc>, ) -> anyhow::Result<()> { let result = tokio::spawn( - beacon_trace_gossip(portal_client, content_key.clone(), content_value).in_current_span(), + beacon_trace_put_content(portal_client, content_key.clone(), content_value) + .in_current_span(), ) .await?; if let Ok(mut data) = slot_stats.lock() { data.update(content_key, result.into()); } else { - warn!("Error updating beacon gossip stats. Unable to acquire lock."); + warn!("Error updating beacon put content stats. Unable to acquire lock."); } Ok(()) } -async fn beacon_trace_gossip( +async fn beacon_trace_put_content( client: HttpClient, content_key: BeaconContentKey, content_value: BeaconContentValue, -) -> GossipReport { +) -> PutContentReport { let mut retries = 0; let mut traces = vec![]; let mut found = false; while retries < GOSSIP_RETRY_COUNT { - let result = BeaconNetworkApiClient::trace_gossip( + let result = BeaconNetworkApiClient::trace_put_content( &client, content_key.clone(), content_value.encode(), @@ -52,7 +53,7 @@ async fn beacon_trace_gossip( if let Ok(trace) = result { traces.push(trace.clone()); if !trace.transferred.is_empty() { - return GossipReport { + return PutContentReport { traces, retries, found, @@ -62,16 +63,16 @@ async fn beacon_trace_gossip( // if not, make rfc request to see if data is available on network let result = BeaconNetworkApiClient::get_content(&client, content_key.clone()).await; if result.is_ok() { - debug!("Found content on network, after failing to gossip, aborting gossip. content key={:?}", content_key.to_hex()); + debug!("Found content on network, after failing to put content, aborting put content. content key={:?}", content_key.to_hex()); found = true; - return GossipReport { + return PutContentReport { traces, retries, found, }; } retries += 1; - debug!("Unable to locate content on network, after failing to gossip, retrying in {:?} seconds. content key={:?}", RETRY_AFTER, content_key.to_hex()); + debug!("Unable to locate content on network, after failing to put content, retrying in {:?} seconds. content key={:?}", RETRY_AFTER, content_key.to_hex()); sleep(RETRY_AFTER).await; } warn!( @@ -79,7 +80,7 @@ async fn beacon_trace_gossip( GOSSIP_RETRY_COUNT, content_key.to_hex(), ); - GossipReport { + PutContentReport { traces, retries, found, @@ -109,12 +110,12 @@ async fn history_trace_gossip( client: HttpClient, content_key: HistoryContentKey, content_value: HistoryContentValue, -) -> GossipReport { +) -> PutContentReport { let mut retries = 0; let mut traces = vec![]; let mut found = false; while retries < GOSSIP_RETRY_COUNT { - let result = HistoryNetworkApiClient::trace_gossip( + let result = HistoryNetworkApiClient::trace_put_content( &client, content_key.clone(), content_value.encode(), @@ -124,7 +125,7 @@ async fn history_trace_gossip( if let Ok(trace) = result { traces.push(trace.clone()); if !trace.transferred.is_empty() { - return GossipReport { + return PutContentReport { traces, retries, found, @@ -136,7 +137,7 @@ async fn history_trace_gossip( if result.is_ok() { debug!("Found content on network, after failing to gossip, aborting gossip. content key={:?}", content_key.to_hex()); found = true; - return GossipReport { + return PutContentReport { traces, retries, found, @@ -151,15 +152,15 @@ async fn history_trace_gossip( GOSSIP_RETRY_COUNT, content_key.to_hex(), ); - GossipReport { + PutContentReport { traces, retries, found, } } -pub struct GossipReport { - pub traces: Vec, +pub struct PutContentReport { + pub traces: Vec, pub retries: u64, pub found: bool, } diff --git a/portal-bridge/src/stats.rs b/portal-bridge/src/stats.rs index dd7800aa4..41b9ce849 100644 --- a/portal-bridge/src/stats.rs +++ b/portal-bridge/src/stats.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, str::FromStr}; use ethportal_api::{types::enr::Enr, BeaconContentKey, HistoryContentKey}; use tracing::{debug, info}; -use crate::gossip::GossipReport; +use crate::put_content::PutContentReport; // Trait for tracking / reporting gossip stats pub trait StatsReporter { @@ -194,18 +194,18 @@ impl std::fmt::Display for ContentStats { } } -impl From for ContentStats { - fn from(gossip_report: GossipReport) -> Self { +impl From for ContentStats { + fn from(put_content_report: PutContentReport) -> Self { let mut content_stats = ContentStats { - retries: gossip_report.retries, - found: gossip_report.found, + retries: put_content_report.retries, + found: put_content_report.found, ..ContentStats::default() }; let enr_from_str = |enr: &String| { Enr::from_str(enr).expect("ENR from trace gossip response to successfully decode.") }; - for trace in &gossip_report.traces { + for trace in &put_content_report.traces { content_stats .offered .extend(trace.offered.iter().map(enr_from_str)); diff --git a/portalnet/src/lib.rs b/portalnet/src/lib.rs index 7788e69f4..1dbf6c471 100644 --- a/portalnet/src/lib.rs +++ b/portalnet/src/lib.rs @@ -7,8 +7,8 @@ pub mod constants; pub mod discovery; pub mod events; pub mod find; -pub mod gossip; pub mod overlay; +pub mod put_content; pub mod socket; pub mod types; pub mod utils; diff --git a/portalnet/src/overlay/protocol.rs b/portalnet/src/overlay/protocol.rs index 90dc3a630..42887282b 100644 --- a/portalnet/src/overlay/protocol.rs +++ b/portalnet/src/overlay/protocol.rs @@ -21,6 +21,7 @@ use ethportal_api::{ distance::{Distance, Metric}, enr::Enr, network::Subnetwork, + portal::PutContentInfo, portal_wire::{ Accept, Content, CustomPayload, FindContent, FindNodes, Message, Nodes, OfferTrace, Ping, Pong, PopulatedOffer, PopulatedOfferWithResult, Request, Response, @@ -35,7 +36,7 @@ use ssz::Encode; use tokio::sync::{broadcast, mpsc::UnboundedSender}; use tracing::{debug, error, info, warn}; use trin_metrics::{overlay::OverlayMetricsReporter, portalnet::PORTALNET_METRICS}; -use trin_storage::ContentStore; +use trin_storage::{ContentStore, ShouldWeStoreContent}; use trin_validation::validator::{ValidationResult, Validator}; use utp_rs::socket::UtpSocket; @@ -43,7 +44,6 @@ use crate::{ discovery::{Discovery, UtpEnr}, events::EventEnvelope, find::query_info::{FindContentResult, RecursiveFindContentResult}, - gossip::{propagate_gossip_cross_thread, trace_propagate_gossip_cross_thread, GossipResult}, overlay::{ command::OverlayCommand, config::{FindContentConfig, OverlayConfig}, @@ -51,6 +51,10 @@ use crate::{ request::{OverlayRequest, RequestDirection}, service::OverlayService, }, + put_content::{ + propagate_put_content_cross_thread, trace_propagate_put_content_cross_thread, + PutContentResult, + }, types::{ kbucket::{Entry, SharedKBucketsTable}, node::Node, @@ -204,24 +208,54 @@ impl< Ok(()) } - /// Propagate gossip accepted content via OFFER/ACCEPT, return number of peers propagated - pub fn propagate_gossip(&self, content: Vec<(TContentKey, RawContentValue)>) -> usize { - propagate_gossip_cross_thread::<_, TMetric>( - content, - &self.kbuckets, - self.command_tx.clone(), - None, - ) + /// Propagate put_content accepted content via OFFER/ACCEPT, return number of peers propagated + pub fn propagate_put_content( + &self, + content_key: TContentKey, + content_value: RawContentValue, + ) -> PutContentInfo { + let should_we_store = match self + .store + .read() + .is_key_within_radius_and_unavailable(&content_key) + { + Ok(should_we_store) => matches!(should_we_store, ShouldWeStoreContent::Store), + Err(err) => { + warn!( + protocol = %self.protocol, + error = %err, + "Error checking if content key is within radius and unavailable", + ); + false + } + }; + + if should_we_store { + let _ = self + .store + .write() + .put(content_key.clone(), content_value.clone()); + } + + PutContentInfo { + peer_count: propagate_put_content_cross_thread::<_, TMetric>( + vec![(content_key, content_value)], + &self.kbuckets, + self.command_tx.clone(), + None, + ) as u32, + stored_locally: should_we_store, + } } - /// Propagate gossip accepted content via OFFER/ACCEPT, returns trace detailing outcome of - /// gossip - pub async fn propagate_gossip_trace( + /// Propagate put content accepted content via OFFER/ACCEPT, returns trace detailing outcome of + /// put content + pub async fn propagate_put_content_trace( &self, content_key: TContentKey, data: RawContentValue, - ) -> GossipResult { - trace_propagate_gossip_cross_thread::<_, TMetric>( + ) -> PutContentResult { + trace_propagate_put_content_cross_thread::<_, TMetric>( content_key, data, &self.kbuckets, diff --git a/portalnet/src/overlay/service.rs b/portalnet/src/overlay/service.rs index aaa67a492..482d7e6f3 100644 --- a/portalnet/src/overlay/service.rs +++ b/portalnet/src/overlay/service.rs @@ -70,7 +70,6 @@ use crate::{ query_info::{QueryInfo, QueryType, RecursiveFindContentResult}, query_pool::{QueryId, QueryPool, QueryPoolState, TargetKey}, }, - gossip::propagate_gossip_cross_thread, overlay::{ command::OverlayCommand, config::FindContentConfig, @@ -80,6 +79,7 @@ use crate::{ RequestDirection, }, }, + put_content::propagate_put_content_cross_thread, types::{ kbucket::{DiscoveredNodesUpdateResult, Entry, SharedKBucketsTable}, node::Node, @@ -1313,7 +1313,7 @@ impl< }) .flatten() .collect(); - propagate_gossip_cross_thread::<_, TMetric>( + propagate_put_content_cross_thread::<_, TMetric>( validated_content, &utp_processing.kbuckets, utp_processing.command_tx.clone(), @@ -1789,7 +1789,7 @@ impl< } }; - propagate_gossip_cross_thread::<_, TMetric>( + propagate_put_content_cross_thread::<_, TMetric>( validated_content, &utp_processing.kbuckets, utp_processing.command_tx.clone(), @@ -1974,7 +1974,7 @@ impl< ); content_to_propagate.extend(dropped_content.clone()); } - propagate_gossip_cross_thread::<_, TMetric>( + propagate_put_content_cross_thread::<_, TMetric>( content_to_propagate, &utp_processing.kbuckets, utp_processing.command_tx.clone(), diff --git a/portalnet/src/gossip.rs b/portalnet/src/put_content.rs similarity index 81% rename from portalnet/src/gossip.rs rename to portalnet/src/put_content.rs index 0a87b14b9..c66076699 100644 --- a/portalnet/src/gossip.rs +++ b/portalnet/src/put_content.rs @@ -25,9 +25,9 @@ use crate::{ utp_controller::UtpController, }; -/// Datatype to store the result of a gossip request. +/// Datatype to store the result of a put content request. #[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Default)] -pub struct GossipResult { +pub struct PutContentResult { /// List of all ENRs that were offered the content pub offered: Vec, /// List of all ENRs that accepted the offer @@ -36,9 +36,9 @@ pub struct GossipResult { pub transferred: Vec, } -/// Propagate gossip in a way that can be used across threads, without &self. -/// Doesn't trace gossip results -pub fn propagate_gossip_cross_thread( +/// Propagate put content in a way that can be used across threads, without &self. +/// Doesn't trace put content results +pub fn propagate_put_content_cross_thread( content: Vec<(TContentKey, RawContentValue)>, kbuckets: &SharedKBucketsTable, command_tx: mpsc::UnboundedSender>, @@ -61,7 +61,7 @@ pub fn propagate_gossip_cross_thread(&content_ids); - // Map from ENRs to content they will gossip + // Map from ENRs to content they will put content let mut enrs_and_content: HashMap> = HashMap::new(); for (content_id, content_key_value) in &content { let interested_enrs = content_id_to_interested_enrs.remove(content_id).unwrap_or_else(|| { @@ -76,8 +76,8 @@ pub fn propagate_gossip_cross_thread(content_id, interested_enrs) { + // Select put content recipients + for enr in select_put_content_recipients::(content_id, interested_enrs) { enrs_and_content .entry(enr) .or_default() @@ -93,7 +93,7 @@ pub fn propagate_gossip_cross_thread match utp_controller.get_outbound_semaphore() { Some(permit) => Some(permit), None => { - trace!("Permit for gossip not acquired! Skipping gossiping to enr: {enr}"); + trace!("Permit for put content not acquired! Skipping offering to enr: {enr}"); continue; } }, @@ -140,11 +140,11 @@ pub fn propagate_gossip_cross_thread( @@ -152,19 +152,19 @@ pub async fn trace_propagate_gossip_cross_thread< data: RawContentValue, kbuckets: &SharedKBucketsTable, command_tx: mpsc::UnboundedSender>, -) -> GossipResult { - let mut gossip_result = GossipResult::default(); +) -> PutContentResult { + let mut put_content_result = PutContentResult::default(); let content_id = content_key.content_id(); let interested_enrs = kbuckets.interested_enrs::(&content_id); if interested_enrs.is_empty() { - debug!(content.id = %hex_encode(content_id), "No peers eligible for trace gossip"); - return gossip_result; + debug!(content.id = %hex_encode(content_id), "No peers eligible for trace put content"); + return put_content_result; }; - // Select ENRs to gossip to, create and send OFFER overlay request to the interested nodes - for enr in select_gossip_recipients::(&content_id, interested_enrs) { + // Select ENRs to put content to, create and send OFFER overlay request to the interested nodes + for enr in select_put_content_recipients::(&content_id, interested_enrs) { let (result_tx, mut result_rx) = tokio::sync::mpsc::unbounded_channel(); let offer_request = Request::PopulatedOfferWithResult(PopulatedOfferWithResult { content_item: (content_key.clone().to_bytes(), data.clone()), @@ -186,14 +186,14 @@ pub async fn trace_propagate_gossip_cross_thread< error!(error = %err, "Error sending OFFER message to service"); continue; } - // update gossip result with peer marked as being offered the content - gossip_result.offered.push(enr.clone()); + // update put content result with peer marked as being offered the content + put_content_result.offered.push(enr.clone()); match rx.await { Ok(res) => { if let Ok(Response::Accept(accept)) = res { if !accept.content_keys.is_zero() { - // update gossip result with peer marked as accepting the content - gossip_result.accepted.push(enr.clone()); + // update put content result with peer marked as accepting the content + put_content_result.accepted.push(enr.clone()); } } else { // continue to next peer if no content was accepted @@ -204,24 +204,24 @@ pub async fn trace_propagate_gossip_cross_thread< Err(_) => continue, } if let Some(OfferTrace::Success(_)) = result_rx.recv().await { - // update gossip result with peer marked as successfully transferring the content - gossip_result.transferred.push(enr); + // update put content result with peer marked as successfully transferring the content + put_content_result.transferred.push(enr); } } - gossip_result + put_content_result } const NUM_CLOSEST_NODES: usize = 4; const NUM_FARTHER_NODES: usize = 4; -/// Selects gossip recipients from a vec of interested ENRs. +/// Selects put content recipients from a vec of interested ENRs. /// /// If number of ENRs is at most `NUM_CLOSEST_NODES + NUM_FARTHER_NODES`, then all are returned. /// Otherwise, ENRs are sorted by distance from `content_id` and then: /// /// 1. Closest `NUM_CLOSEST_NODES` ENRs are selected /// 2. Random `NUM_FARTHER_NODES` ENRs are selected from the rest -fn select_gossip_recipients( +fn select_put_content_recipients( content_id: &[u8; 32], mut enrs: Vec, ) -> Vec { @@ -263,11 +263,12 @@ mod tests { #[case(vec![generate_random_remote_enr().1; NUM_CLOSEST_NODES + 1], NUM_CLOSEST_NODES + 1)] #[case(vec![generate_random_remote_enr().1; NUM_CLOSEST_NODES + NUM_FARTHER_NODES], NUM_CLOSEST_NODES + NUM_FARTHER_NODES)] #[case(vec![generate_random_remote_enr().1; 256], NUM_CLOSEST_NODES + NUM_FARTHER_NODES)] - fn test_select_gossip_recipients_no_panic( + fn test_select_put_content_recipients_no_panic( #[case] all_nodes: Vec, #[case] expected_size: usize, ) { - let gossip_recipients = select_gossip_recipients::(&random(), all_nodes); - assert_eq!(gossip_recipients.len(), expected_size); + let put_content_recipients = + select_put_content_recipients::(&random(), all_nodes); + assert_eq!(put_content_recipients.len(), expected_size); } } diff --git a/rpc/src/beacon_rpc.rs b/rpc/src/beacon_rpc.rs index 5317c30f1..a55a9e593 100644 --- a/rpc/src/beacon_rpc.rs +++ b/rpc/src/beacon_rpc.rs @@ -12,8 +12,8 @@ use ethportal_api::{ jsonrpc::{endpoints::BeaconEndpoint, request::BeaconJsonRpcRequest}, portal::{ AcceptInfo, DataRadius, FindContentInfo, FindNodesInfo, GetContentInfo, - PaginateLocalContentInfo, PongInfo, TraceContentInfo, TraceGossipInfo, - MAX_CONTENT_KEYS_PER_OFFER, + PaginateLocalContentInfo, PongInfo, PutContentInfo, TraceContentInfo, + TracePutContentInfo, MAX_CONTENT_KEYS_PER_OFFER, }, portal_wire::OfferTrace, }, @@ -171,27 +171,27 @@ impl BeaconNetworkApiServer for BeaconNetworkApi { /// Send the provided content to interested peers. Clients may choose to send to some or all /// peers. Return the number of peers that the content was gossiped to. - async fn gossip( + async fn put_content( &self, content_key: BeaconContentKey, content_value: RawContentValue, - ) -> RpcResult { + ) -> RpcResult { let content_value = BeaconContentValue::decode(&content_key, &content_value) .map_err(RpcServeError::from)?; - let endpoint = BeaconEndpoint::Gossip(content_key, content_value); + let endpoint = BeaconEndpoint::PutContent(content_key, content_value); Ok(proxy_to_subnet(&self.network, endpoint).await?) } /// Send the provided content to interested peers. Clients may choose to send to some or all /// peers. Return tracing info. - async fn trace_gossip( + async fn trace_put_content( &self, content_key: BeaconContentKey, content_value: RawContentValue, - ) -> RpcResult { + ) -> RpcResult { let content_value = BeaconContentValue::decode(&content_key, &content_value) .map_err(RpcServeError::from)?; - let endpoint = BeaconEndpoint::TraceGossip(content_key, content_value); + let endpoint = BeaconEndpoint::TracePutContent(content_key, content_value); Ok(proxy_to_subnet(&self.network, endpoint).await?) } diff --git a/rpc/src/history_rpc.rs b/rpc/src/history_rpc.rs index 80dd879ab..151706a94 100644 --- a/rpc/src/history_rpc.rs +++ b/rpc/src/history_rpc.rs @@ -5,8 +5,8 @@ use ethportal_api::{ jsonrpc::{endpoints::HistoryEndpoint, request::HistoryJsonRpcRequest}, portal::{ AcceptInfo, DataRadius, FindContentInfo, FindNodesInfo, GetContentInfo, - PaginateLocalContentInfo, PongInfo, TraceContentInfo, TraceGossipInfo, - MAX_CONTENT_KEYS_PER_OFFER, + PaginateLocalContentInfo, PongInfo, PutContentInfo, TraceContentInfo, + TracePutContentInfo, MAX_CONTENT_KEYS_PER_OFFER, }, portal_wire::OfferTrace, }, @@ -127,27 +127,27 @@ impl HistoryNetworkApiServer for HistoryNetworkApi { /// Send the provided content to interested peers. Clients may choose to send to some or all /// peers. Return the number of peers that the content was gossiped to. - async fn gossip( + async fn put_content( &self, content_key: HistoryContentKey, content_value: RawContentValue, - ) -> RpcResult { + ) -> RpcResult { let content_value = HistoryContentValue::decode(&content_key, &content_value) .map_err(RpcServeError::from)?; - let endpoint = HistoryEndpoint::Gossip(content_key, content_value); + let endpoint = HistoryEndpoint::PutContent(content_key, content_value); Ok(proxy_to_subnet(&self.network, endpoint).await?) } /// Send the provided content to interested peers. Clients may choose to send to some or all /// peers. Return tracing info. - async fn trace_gossip( + async fn trace_put_content( &self, content_key: HistoryContentKey, content_value: RawContentValue, - ) -> RpcResult { + ) -> RpcResult { let content_value = HistoryContentValue::decode(&content_key, &content_value) .map_err(RpcServeError::from)?; - let endpoint = HistoryEndpoint::TraceGossip(content_key, content_value); + let endpoint = HistoryEndpoint::TracePutContent(content_key, content_value); Ok(proxy_to_subnet(&self.network, endpoint).await?) } diff --git a/rpc/src/state_rpc.rs b/rpc/src/state_rpc.rs index 82c7d7a0f..b4496578c 100644 --- a/rpc/src/state_rpc.rs +++ b/rpc/src/state_rpc.rs @@ -5,8 +5,8 @@ use ethportal_api::{ jsonrpc::{endpoints::StateEndpoint, request::StateJsonRpcRequest}, portal::{ AcceptInfo, DataRadius, FindContentInfo, FindNodesInfo, GetContentInfo, - PaginateLocalContentInfo, PongInfo, TraceContentInfo, TraceGossipInfo, - MAX_CONTENT_KEYS_PER_OFFER, + PaginateLocalContentInfo, PongInfo, PutContentInfo, TraceContentInfo, + TracePutContentInfo, MAX_CONTENT_KEYS_PER_OFFER, }, portal_wire::OfferTrace, }, @@ -124,27 +124,27 @@ impl StateNetworkApiServer for StateNetworkApi { /// Send the provided content to interested peers. Clients may choose to send to some or all /// peers. Return the number of peers that the content was gossiped to. - async fn gossip( + async fn put_content( &self, content_key: StateContentKey, content_value: RawContentValue, - ) -> RpcResult { + ) -> RpcResult { let content_value = StateContentValue::decode(&content_key, &content_value).map_err(RpcServeError::from)?; - let endpoint = StateEndpoint::Gossip(content_key, content_value); + let endpoint = StateEndpoint::PutContent(content_key, content_value); Ok(proxy_to_subnet(&self.network, endpoint).await?) } /// Send the provided content to interested peers. Clients may choose to send to some or all /// peers. Return tracing info. - async fn trace_gossip( + async fn trace_put_content( &self, content_key: StateContentKey, content_value: RawContentValue, - ) -> RpcResult { + ) -> RpcResult { let content_value = StateContentValue::decode(&content_key, &content_value).map_err(RpcServeError::from)?; - let endpoint = StateEndpoint::TraceGossip(content_key, content_value); + let endpoint = StateEndpoint::TracePutContent(content_key, content_value); Ok(proxy_to_subnet(&self.network, endpoint).await?) } diff --git a/tests/self_peertest.rs b/tests/self_peertest.rs index f2abbbada..7a48ca630 100644 --- a/tests/self_peertest.rs +++ b/tests/self_peertest.rs @@ -95,7 +95,7 @@ async fn peertest_offer_concurrent_utp_transfer_limit() { async fn peertest_gossip_with_trace() { let (peertest, target, handle) = setup_peertest(&Network::Mainnet, &[Subnetwork::History]).await; - peertest::scenarios::gossip::test_gossip_with_trace(&peertest, &target).await; + peertest::scenarios::put_content::test_gossip_with_trace(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); } @@ -297,7 +297,7 @@ async fn peertest_history_offer_propagates_gossip_multiple_large_content_values( async fn peertest_history_gossip_dropped_with_offer() { let (peertest, target, handle) = setup_peertest(&Network::Mainnet, &[Subnetwork::History]).await; - peertest::scenarios::gossip::test_gossip_dropped_with_offer(&peertest, &target).await; + peertest::scenarios::put_content::test_gossip_dropped_with_offer(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); } @@ -307,7 +307,8 @@ async fn peertest_history_gossip_dropped_with_offer() { async fn peertest_history_gossip_dropped_with_find_content() { let (peertest, target, handle) = setup_peertest(&Network::Mainnet, &[Subnetwork::History]).await; - peertest::scenarios::gossip::test_gossip_dropped_with_find_content(&peertest, &target).await; + peertest::scenarios::put_content::test_gossip_dropped_with_find_content(&peertest, &target) + .await; peertest.exit_all_nodes(); handle.stop().unwrap(); } diff --git a/trin-beacon/src/jsonrpc.rs b/trin-beacon/src/jsonrpc.rs index 24472ca0b..b833597b8 100644 --- a/trin-beacon/src/jsonrpc.rs +++ b/trin-beacon/src/jsonrpc.rs @@ -62,11 +62,11 @@ async fn complete_request(network: Arc, request: BeaconJsonRpcReq } BeaconEndpoint::FindNodes(enr, distances) => find_nodes(network, enr, distances).await, BeaconEndpoint::GetEnr(node_id) => get_enr(network, node_id).await, - BeaconEndpoint::Gossip(content_key, content_value) => { - gossip(network, content_key, content_value, false).await + BeaconEndpoint::PutContent(content_key, content_value) => { + put_content(network, content_key, content_value, false).await } - BeaconEndpoint::TraceGossip(content_key, content_value) => { - gossip(network, content_key, content_value, true).await + BeaconEndpoint::TracePutContent(content_key, content_value) => { + put_content(network, content_key, content_value, true).await } BeaconEndpoint::LightClientStore => light_client_store(&network).await, BeaconEndpoint::LookupEnr(node_id) => lookup_enr(network, node_id).await, @@ -366,8 +366,8 @@ async fn find_nodes( } } -/// Constructs a JSON call for the Gossip method. -async fn gossip( +/// Constructs a JSON call for the PutContent method. +async fn put_content( network: Arc, content_key: BeaconContentKey, content_value: BeaconContentValue, @@ -378,13 +378,12 @@ async fn gossip( true => Ok(json!( network .overlay - .propagate_gossip_trace(content_key, data) + .propagate_put_content_trace(content_key, data) .await )), - false => Ok(network + false => Ok(json!(network .overlay - .propagate_gossip(vec![(content_key, data)]) - .into()), + .propagate_put_content(content_key, data))), } } diff --git a/trin-history/src/jsonrpc.rs b/trin-history/src/jsonrpc.rs index 33eaca208..47ce3bbd3 100644 --- a/trin-history/src/jsonrpc.rs +++ b/trin-history/src/jsonrpc.rs @@ -62,11 +62,11 @@ async fn complete_request(network: Arc, request: HistoryJsonRpcR } HistoryEndpoint::FindNodes(enr, distances) => find_nodes(network, enr, distances).await, HistoryEndpoint::GetEnr(node_id) => get_enr(network, node_id).await, - HistoryEndpoint::Gossip(content_key, content_value) => { - gossip(network, content_key, content_value).await + HistoryEndpoint::PutContent(content_key, content_value) => { + put_content(network, content_key, content_value).await } - HistoryEndpoint::TraceGossip(content_key, content_value) => { - trace_gossip(network, content_key, content_value).await + HistoryEndpoint::TracePutContent(content_key, content_value) => { + trace_put_content(network, content_key, content_value).await } HistoryEndpoint::LookupEnr(node_id) => lookup_enr(network, node_id).await, HistoryEndpoint::Offer(enr, content_items) => offer(network, enr, content_items).await, @@ -306,21 +306,20 @@ async fn find_nodes( } } -/// Constructs a JSON call for the Gossip method. -async fn gossip( +/// Constructs a JSON call for the PutContent method. +async fn put_content( network: Arc, content_key: HistoryContentKey, content_value: ethportal_api::HistoryContentValue, ) -> Result { let data = content_value.encode(); - Ok(network + Ok(json!(network .overlay - .propagate_gossip(vec![(content_key, data)]) - .into()) + .propagate_put_content(content_key, data))) } -/// Constructs a JSON call for the Gossip method, with tracing enabled. -async fn trace_gossip( +/// Constructs a JSON call for the PutContent method, with tracing enabled. +async fn trace_put_content( network: Arc, content_key: HistoryContentKey, content_value: ethportal_api::HistoryContentValue, @@ -329,7 +328,7 @@ async fn trace_gossip( Ok(json!( network .overlay - .propagate_gossip_trace(content_key, data) + .propagate_put_content_trace(content_key, data) .await )) } diff --git a/trin-state/src/jsonrpc.rs b/trin-state/src/jsonrpc.rs index 1e058bdd0..035173069 100644 --- a/trin-state/src/jsonrpc.rs +++ b/trin-state/src/jsonrpc.rs @@ -65,8 +65,8 @@ impl StateRequestHandler { StateEndpoint::TraceOffer(enr, content_key, content_value) => { trace_offer(network, enr, content_key, content_value).await } - StateEndpoint::Gossip(content_key, content_value) => { - gossip( + StateEndpoint::PutContent(content_key, content_value) => { + put_content( network, content_key, content_value, @@ -74,8 +74,8 @@ impl StateRequestHandler { ) .await } - StateEndpoint::TraceGossip(content_key, content_value) => { - gossip( + StateEndpoint::TracePutContent(content_key, content_value) => { + put_content( network, content_key, content_value, @@ -341,7 +341,7 @@ async fn trace_offer( ) } -async fn gossip( +async fn put_content( network: Arc, content_key: StateContentKey, content_value: StateContentValue, @@ -351,14 +351,14 @@ async fn gossip( Ok(json!( network .overlay - .propagate_gossip_trace(content_key, content_value.encode()) + .propagate_put_content_trace(content_key, content_value.encode()) .await )) } else { - Ok(network - .overlay - .propagate_gossip(vec![(content_key, content_value.encode())]) - .into()) + Ok(json!(network.overlay.propagate_put_content( + content_key, + content_value.encode(), + ))) } } From 990cce0b8405893cf42e0541402e4985ccfc0ebf Mon Sep 17 00:00:00 2001 From: Kolby Moroz Liebl <31669092+KolbyML@users.noreply.github.com> Date: Wed, 1 Jan 2025 20:41:28 -0700 Subject: [PATCH 2/2] fix: resolve PR concerns --- ethportal-api/src/types/portal.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ethportal-api/src/types/portal.rs b/ethportal-api/src/types/portal.rs index 98ed0231f..60b62b151 100644 --- a/ethportal-api/src/types/portal.rs +++ b/ethportal-api/src/types/portal.rs @@ -71,9 +71,9 @@ pub struct AcceptInfo { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PutContentInfo { - // Indicates how many peers the content was gossiped to + /// Indicates how many peers the content was gossiped to pub peer_count: u32, - // Indicates whether the content was stored locally or not + /// Indicates whether the content was stored locally or not pub stored_locally: bool, } @@ -81,11 +81,11 @@ pub struct PutContentInfo { #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TracePutContentInfo { - // List of all ENRs that were offered the content + /// List of all ENRs that were offered the content pub offered: Vec, - // List of all ENRs that accepted the offer + /// List of all ENRs that accepted the offer pub accepted: Vec, - // List of all ENRs to whom the content was successfully transferred + /// List of all ENRs to whom the content was successfully transferred pub transferred: Vec, }