-
Notifications
You must be signed in to change notification settings - Fork 872
TLV PoC #6082
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
TLV PoC #6082
Conversation
27c106d to
da79d4a
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6082 +/- ##
=======================================
Coverage 82.9% 82.9%
=======================================
Files 842 843 +1
Lines 377680 377751 +71
=======================================
+ Hits 313116 313195 +79
+ Misses 64564 64556 -8 🚀 New features to boost your workflow:
|
gregcusack
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks goooooood! just a few thoughts. also i think the walking the packet concern is kind of a moot point since we have to do that anyway for sockets: Vec<SocketEntry>. also thank you for refreshing my macro game.
| extensions: Vec<Extension>, | ||
| extensions: Vec<TlvRecord>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh this is nice. so rollout strategy here is switch to Vec<TlvRecord> and leave empty until everyone adopts. since those not updated will fail to accept/deser ContactInfo with non-empty vecs here. and then we can start populating extensions with TlvRecords.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, pretty much. At that point any client can do whatever they want with Extensions as long as we do not get conflicting tags.
| pub(crate) fn parse<'a, T: TryFrom<&'a TlvRecord>>(entries: &'a [TlvRecord]) -> Vec<T> { | ||
| entries.iter().filter_map(|v| T::try_from(v).ok()).collect() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may not be a huge deal since its a sender issue but if there are multiple TlvRecords with the same typ we just keep the last one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why that would be the case. It will skip invalid entries, but will happily produce as many identical TLVs as there are in the original entries slice. Granted, the Vec allocation here is grotesque, but its a PoC =)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ya turns out i can't read lol. ignore
gossip/src/tlv.rs
Outdated
| $( | ||
| $typ => Ok(Self::$variant(bincode::deserialize::<$inner>(&value.bytes)?)), | ||
| )* | ||
| _ => Err(bincode::Error::custom("Invalid type")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe would be nice to differentiate between invalid type and some other decode failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how that would work to be honest, can you elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well the code kind of differentiates already. since if the type is valid we just return some bincode::Error::<error> and if the type is invalid then we get bincode::Error::custom("invalid type").
but from a caller error handling/clarity/debugging perspective it may be nice to provide a way to match on the error rather than having to do match err.kind() { ... } and possibly have to do string matching.
we could wrap the error in some TlvDecodeError like:
pub enum TlvDecodeError {
#[error("Unknown type: {0}")]
UnknownType(u8),
#[error("Malformed payload: {0}")]
MalformedPayload(#[from] bincode::Error),
}
or change the error string to 'invalid tlv type" so we don't get crossed up with someone in the future defining a bincode error with "invalid type".
won't die on this hill. but would just clean/clear up error messages and handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah good idea, I'll put that in. Thanks!
gossip/src/contact_info.rs
Outdated
| // The Extension enum for optional features in gossip | ||
| define_tlv_enum! (pub(crate) enum Extension { | ||
| 1=>SupportSenderSignatures(u8), | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be nice to add a more detailed comment here about how to add a new tlv type:
/// TLV features in ContactInfo
///
/// On the wire each record is: [type: u8][len of vec][bytes vec]
/// Unknown types are ignored by tlv::parse, so new types can be added without breaking legacy code
///
/// Always add new TLV records to the end of this enum
/// Never reorder or reuse a type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 78a0053
gossip/src/tlv.rs
Outdated
| // Make sure legacy recover works correctly | ||
| let legacy: Vec<ExtensionLegacy> = crate::tlv::parse(&tlv_vec); | ||
| assert!(matches!(legacy[0], ExtensionLegacy::Test(42))); | ||
| assert_eq!(legacy.len(), 1, "Legacy parser should only recover ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Legacy parse should only recover ... what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 78a0053
Co-authored-by: Greg Cusack <[email protected]>
|
TLVs seem like a good fit for the extensions vec. Have you considered something more standard like protobufs? That way we can define types in a platform-agnostic matter (and share definitions in a centralized repo) |
|
@ravyu-jump my main motivation was based on the fact that bincode is used nearly everywhere in solana networking stack, so it is a "devil we know", and Firedancer already has relevant implementation details sorted out (and for Zig there is a libraray that does the job). So the concern with protobuf is that it is a fairly complex format, and bringing that into the network-facing part of the clients would make the attack surface larger. Transitioning gossip entirely to protobuf instead of bincode could be an interesting proposition though, as protobuf has a far smoother mechanism for protocol evolution over time (aside from the advantages you have mentioned w.r.t. cross-language compatbility). We should definitely discuss this more and see if such change is justified (and whether protobuf is even a good option for that or we should go with something fancier like capnproto). |
gregcusack
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks mostly good. just would add clearer error handling as discussed here: #6082 (comment)
gregcusack
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
* TLV PoC for Gossip extensions --------- Co-authored-by: Greg Cusack <[email protected]>
* TLV PoC for Gossip extensions --------- Co-authored-by: Greg Cusack <[email protected]>
Problem
Gossip Extensions mechanism is effectively dead, TLV could allow us to make it do what it was supposed to
Summary of Changes