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

Conversation

KolbyML
Copy link
Member

@KolbyML KolbyML commented Dec 27, 2024

What was wrong?

implements ethereum/portal-network-specs#348

How was it fixed?

by implementing it

@KolbyML KolbyML changed the title Implement ping extensions feat: implement ping extensions Dec 27, 2024
@KolbyML KolbyML force-pushed the implement-ping-extensions branch 3 times, most recently from 5febe0e to efd0328 Compare December 28, 2024 09:45
@KolbyML KolbyML force-pushed the implement-ping-extensions branch 4 times, most recently from 6b46f62 to d416970 Compare January 8, 2025 13:21
@KolbyML KolbyML marked this pull request as ready for review January 8, 2025 13:44
@KolbyML KolbyML self-assigned this Jan 8, 2025
Copy link
Collaborator

@njgheorghita njgheorghita left a comment

Choose a reason for hiding this comment

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

First pass, mostly thoughts on layout / docstrings. IIUC this is a breaking change, right? If so, what's the rollout plan?

assert_eq!(client_info, decoded);
}

#[test]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems like you could use rstest for these fail cases, and just add inline comments to the individual cases explaining why they should fail

}
}

impl From<BasicRadius> for CustomPayload {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems like a fairly simple type, but I still feel like we should have some pass/fail test cases for type_1 & type_2 * type_65535

Copy link
Member Author

Choose a reason for hiding this comment

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

I added a few test cases let me know if you want any specific test I didn't think of

pub mod decode;
pub mod extensions;

use ssz::Decode;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Idk... this is a bit of a nitpick, bc I'm pretty sure we're not consistent with this throughout the codebase, but personally i'm not a fan of having logic/defining types inside the mod.rs file. Imo, it makes navigation more difficult. eg. when the logic is in a specified module, then I know exactly where to go to see the source.

Same comment applies to your file change -> overlay/service/mod.rs. I'd rather see that logic in a named module

Copy link
Member Author

@KolbyML KolbyML Jan 10, 2025

Choose a reason for hiding this comment

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

Same comment applies to your file change -> overlay/service/mod.rs. I'd rather see that logic in a named module

I can move the impl out of mod, but I think the struct must stay in mod or the impl wouldn't be able to access the structs private with doing pub to all them

I think the struct has to go in mod yeah

Copy link
Member Author

@KolbyML KolbyML Jan 10, 2025

Choose a reason for hiding this comment

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

So to split the impl across files, I think the struct must be in the mod, or it becomes very messy and asks me to make the struct's contents public.

If you have an idea which works where we could cleanly do this let me know

let parts: Vec<&str> = string.split('/').collect();

if parts.len() != 4 {
bail!("Invalid client info string: should have 4 /'s {}", string);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would also include how many parts were actually found in the string (parts.len())

use ethportal_api::types::ping_extensions::Extensions;

pub trait PingExtension {
fn is_supported(&self, extension: Extensions) -> bool;
Copy link
Collaborator

Choose a reason for hiding this comment

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

docstring this and & raw_extensions


/// Returns the newest extension that is supported by both clients, used for extended ping
/// responses.
fn newest_commonly_supported_base_extension(
Copy link
Collaborator

Choose a reason for hiding this comment

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

nitpick latest_mutually_supported_base_extension

types::node::Node,
};

impl<
Copy link
Collaborator

Choose a reason for hiding this comment

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

Docstring

@KolbyML
Copy link
Member Author

KolbyML commented Jan 9, 2025

this is a breaking change, right?

Yes

If so, what's the rollout plan?

Currently our protocol doesn't have a way to deal with this, hopefully we define something in the specification soon!

So I think it is shipping breaking code, and I really want a defined way for shipping breaking change to the network 😭

@KolbyML
Copy link
Member Author

KolbyML commented Jan 10, 2025

@njgheorghita ready for another review

@KolbyML KolbyML force-pushed the implement-ping-extensions branch from 596bde7 to 259dcaa Compare January 13, 2025 18:43
@KolbyML KolbyML force-pushed the implement-ping-extensions branch from 259dcaa to d12c90a Compare January 13, 2025 18:53
Copy link
Collaborator

@njgheorghita njgheorghita left a comment

Choose a reason for hiding this comment

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

Looks good! Mostly nits. Though, I'd say this is blocked for merging until we get at least fluffy (and probably ultralight as well, since it sounds like they're not that far away) up to spec, and then we'll coordinate the release together


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

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

portal_wire::CustomPayload,
};

/// Used to response to pings which the node can't handle
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit Used to respond to ...

extensions: &[Extensions],
) -> Option<Extensions>;

/// Returns the extensions by there u16 type id that are supported by the clients subnetwork.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit Returns the extensions by their u16...

)
.await;
let command_tx =
OverlayService::<TContentKey, TMetric, TValidator, TStore, TPingExtensions>::spawn(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Jeez, this probably needs some refactoring at some point

protocol = %self.protocol,
request.source = %source,
request.discv5.id = %request_id,
"Received invalid Ping message, Error's should only be received from pong",
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit Errors...

@@ -9,10 +9,10 @@ use discv5::enr::{CombinedKey, Enr, NodeId};
use ethportal_api::{
types::network::Network,
utils::bytes::{hex_decode, hex_encode},
version::APP_NAME,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmmm. While you're at it... git grep -i '\"trin\"' reveals quite a few other places in the codebase where we just hardcode "trin", it could be a quick / worthwhile refactor to update those as well in a future pr, but it's nothing urgent / important.

types::node::Node,
};

/// Implementation of the `OverlayService` for handing Ping and Pong Extension's.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit handling & Extensions

warn!(
protocol = %self.protocol,
request.dest = %node_id,
"Base extension wasn't implemented: {extension:?}, sending Capabilities instead this is a bug",
Copy link
Collaborator

Choose a reason for hiding this comment

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

... sending Capabilities instead. This is a bug!

let _ = self.command_tx.send(OverlayCommand::Request(request));
}

fn handle_capabilities(
Copy link
Collaborator

Choose a reason for hiding this comment

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

In general, I feel like there's some room for improvement in how this file is organized. It just seems a bit spaghetti-y to me. It's not a blocker for this pr, and tbh I don't have any good ideas off the top of my head (our overlay service is so spaghetti-y already that maybe there aren't any great options). But at the very least it seems like the last 3 methods in this file don't use the self attribute, so maybe they would be better off somewhere else? IDK, leaving it up to you to evaluate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants