Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement ping extensions #1616

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions bin/trin/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use ethportal_api::{
network::Subnetwork,
portal_wire::{NetworkSpec, MAINNET},
},
version::FULL_VERSION,
version::{APP_NAME, FULL_VERSION},
};
use portalnet::{
bootnodes::Bootnodes,
Expand All @@ -33,7 +33,6 @@ const DEFAULT_SUBNETWORKS: &str = "history";
pub const DEFAULT_STORAGE_CAPACITY_MB: &str = "1000";
pub const DEFAULT_WEB3_TRANSPORT: &str = "ipc";

const APP_NAME: &str = "trin";
#[derive(Parser, Debug, PartialEq, Clone)]
#[command(name = APP_NAME,
author = "https://github.com/ethereum/trin/graphs/contributors",
Expand Down
1 change: 1 addition & 0 deletions crates/ethportal-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ ethereum_serde_utils.workspace = true
ethereum_ssz.workspace = true
ethereum_ssz_derive.workspace = true
hex.workspace = true
itertools.workspace = true
jsonrpsee = { workspace = true, features = ["async-client", "client", "macros", "server"]}
keccak-hash.workspace = true
lazy_static.workspace = true
Expand Down
4 changes: 3 additions & 1 deletion crates/ethportal-api/src/types/distance.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::{fmt, ops::Deref};

use alloy::primitives::U256;
use ssz_derive::{Decode, Encode};

pub type DataRadius = U256;

/// Represents a distance between two keys in the DHT key space.
#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Debug, Encode, Decode)]
#[ssz(struct_behaviour = "transparent")]
pub struct Distance(U256);

impl fmt::Display for Distance {
Expand Down
1 change: 1 addition & 0 deletions crates/ethportal-api/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod execution;
pub mod jsonrpc;
pub mod network;
pub mod node_id;
pub mod ping_extensions;
pub mod portal;
pub mod portal_wire;
pub mod query_trace;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use ssz::Decode;
use ssz_derive::{Decode, Encode};
use ssz_types::{
typenum::{
bit::{B0, B1},
UInt, UTerm,
},
VariableList,
};

use crate::types::portal_wire::CustomPayload;

// 1100 in binary is 10001001100
pub type U1100 = UInt<
UInt<
UInt<
UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B1>, B0>, B0>, B1>,
B1,
>,
B0,
>,
B0,
>;

#[derive(PartialEq, Debug, Encode, Decode)]
pub struct CustomPayloadExtensionsFormat {
pub r#type: u16,
pub payload: VariableList<u8, U1100>,
}

impl TryFrom<CustomPayload> for CustomPayloadExtensionsFormat {
type Error = anyhow::Error;

fn try_from(value: CustomPayload) -> Result<Self, Self::Error> {
CustomPayloadExtensionsFormat::from_ssz_bytes(&value.payload)
.map_err(|e| anyhow::anyhow!("Failed to decode CustomPayloadExtensionsFormat: {:?}", e))
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit use the var inside the string. though, this is the kind of nit I would expect clippy to pick up? seems like the rule is enabled https://github.com/ethereum/trin/blob/master/crates/ethportal-api/src/lib.rs#L5C1-L5C40 ... maybe clippy's structure isn't compatible/needs updating with the new crates/ layout?

also another nit importanyhow::anyhow at the top rather than importing it here

}
}

#[derive(PartialEq, Debug, Clone, Copy, Eq)]
pub enum Extensions {
Capabilities,
BasicRadius,
HistoryRadius,
Error,
}

impl TryFrom<u16> for Extensions {
type Error = ExtensionError;

fn try_from(value: u16) -> Result<Self, ExtensionError> {
match value {
0 => Ok(Extensions::Capabilities),
1 => Ok(Extensions::BasicRadius),
2 => Ok(Extensions::HistoryRadius),
65535 => Ok(Extensions::Error),
_ => Err(ExtensionError::NonSupportedExtension(value)),
}
}
}

impl From<Extensions> for u16 {
fn from(value: Extensions) -> u16 {
match value {
Extensions::Capabilities => 0,
Extensions::BasicRadius => 1,
Extensions::HistoryRadius => 2,
Extensions::Error => 65535,
}
}
}

#[derive(Debug)]
pub enum ExtensionError {
NonSupportedExtension(u16),
}
74 changes: 74 additions & 0 deletions crates/ethportal-api/src/types/ping_extensions/decode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use anyhow::bail;
use ssz::Decode;

use super::{
custom_payload_format::{CustomPayloadExtensionsFormat, Extensions},
extensions::{
type_0::ClientInfoRadiusCapabilities, type_1::BasicRadius, type_2::HistoryRadius,
type_65535::PingError,
},
};
use crate::types::portal_wire::CustomPayload;

#[derive(Debug, Clone)]
pub enum DecodedExtension {
Capabilities(ClientInfoRadiusCapabilities),
BasicRadius(BasicRadius),
HistoryRadius(HistoryRadius),
Error(PingError),
}

impl From<DecodedExtension> for Extensions {
fn from(value: DecodedExtension) -> Self {
match value {
DecodedExtension::Capabilities(_) => Extensions::Capabilities,
DecodedExtension::BasicRadius(_) => Extensions::BasicRadius,
DecodedExtension::HistoryRadius(_) => Extensions::HistoryRadius,
DecodedExtension::Error(_) => Extensions::Error,
}
}
}

impl TryFrom<CustomPayload> for DecodedExtension {
type Error = anyhow::Error;

fn try_from(value: CustomPayload) -> Result<Self, anyhow::Error> {
let Ok(ping_custom_payload): anyhow::Result<CustomPayloadExtensionsFormat> =
value.try_into()
else {
bail!("Failed to decode CustomPayloadExtensionsFormat");
};

let Ok(extension_type) = Extensions::try_from(ping_custom_payload.r#type) else {
bail!("Failed to decode extension type");
};

match extension_type {
Extensions::Capabilities => {
let capabilities =
ClientInfoRadiusCapabilities::from_ssz_bytes(&ping_custom_payload.payload)
.map_err(|err| {
anyhow::anyhow!(
Copy link
Collaborator

Choose a reason for hiding this comment

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

same with the anyhow import in this file

"Failed to decode ClientInfoRadiusCapabilities: {err:?}"
)
})?;
Ok(DecodedExtension::Capabilities(capabilities))
}
Extensions::BasicRadius => {
let basic_radius = BasicRadius::from_ssz_bytes(&ping_custom_payload.payload)
.map_err(|err| anyhow::anyhow!("Failed to decode BasicRadius: {err:?}"))?;
Ok(DecodedExtension::BasicRadius(basic_radius))
}
Extensions::HistoryRadius => {
let history_radius = HistoryRadius::from_ssz_bytes(&ping_custom_payload.payload)
.map_err(|err| anyhow::anyhow!("Failed to decode HistoryRadius: {err:?}"))?;
Ok(DecodedExtension::HistoryRadius(history_radius))
}
Extensions::Error => {
let error = PingError::from_ssz_bytes(&ping_custom_payload.payload)
.map_err(|err| anyhow::anyhow!("Failed to decode PingError: {err:?}"))?;
Ok(DecodedExtension::Error(error))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod type_0;
pub mod type_1;
pub mod type_2;
pub mod type_65535;
Loading