-
Notifications
You must be signed in to change notification settings - Fork 412
Implement serialize/deserialize for Router #271
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
Implement serialize/deserialize for Router #271
Conversation
47358b8
to
ad45d92
Compare
@@ -382,7 +382,81 @@ impl NetAddress { | |||
} | |||
} | |||
|
|||
#[derive(Clone)] | |||
impl Writeable for NetAddress { |
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.
Can you adapt the UnsignedNodeAnnouncement write/read to use these as well?
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.
Updated
ad45d92
to
216edbb
Compare
Damn seems cc dependencies break on 1.22 and 1.29 |
Looks like this accidentally changed the serialization of some messages resulting in a router_target failure: ---- tests::duplicate_crash stdout ---- |
Sorry, stupid question, from where do you get this specific debug output ? I mean I only get crash in hfuzz_workspace/router_target/ with HONGGFUZZ.REPORT.TXT ? |
If you put the failing test's hex in the duplicate_crash test case in fuzz_targets/router_target.rs and run cargo test from the fuzz/ directory you should get a failing test just like any other cargo test. |
Thanks got the same debug! |
216edbb
to
0026aec
Compare
excess_byte = byte; | ||
break; | ||
}, | ||
Err(DecodeError::ShortRead) => return Err(DecodeError::BadLengthDescriptor), |
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.
There, as serialization is implemented for NetAddress now, a ShortRead bring back by deserialization field failure should be translated as a BadLengthDescriptor as address descriptor isn't accurate seems to me (or we can change msg_node_announcement_target constraints)
src/ln/msgs.rs
Outdated
port, | ||
}) | ||
} | ||
_ => return Err(DecodeError::UnknownVersion { byte }), |
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.
Doesn't InvalidValue make more sense here?
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.
To me InvalidValue is data that is syntaxically incorrect at the protocol level, there address descriptor is may be right we just don't support it.
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.
We use InvalidValue mostly to track non-0/1 for bool values, which seems kinda equivalent here - the type byte isnt a "version" so much as something analogous to a 2 for a bool
src/ln/router.rs
Outdated
let fee_proportional_millionths = Readable::read(reader)?; | ||
let last_update_message = match <u8 as Readable<R>>::read(reader)? { | ||
0 => None, | ||
1 => Some(msgs::ChannelUpdate::read(reader)?), |
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 we should just implement Readable/Writeable for Option<T : Readable/Writeable>? There's a bunch of places that would simplify things.
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.
Hey right working on it
0f97f11
to
605b5d2
Compare
Still WIP, need to dissociate between None field and optional field (e,g option_shutdown_upfront_script), should do it with an enum |
270e387
to
e3f46f3
Compare
Rebased, and fix 1.22 build should be good now |
src/ln/msgs.rs
Outdated
port, | ||
}) | ||
} | ||
_ => return Err(DecodeError::InvalidValue { byte: Some(byte) }), |
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.
Hmm, now that I think about it more I'm rather unconvinced of this approach. If, eg, at some point we check the ed25519_pubkey is valid in OnionV3 or the ports are non-0 we may want to return an InvalidValue but not have extra bytes. Maybe it makes sense to return a Result<enum { Ok(NetAddress), UnknownType(u8) }, DecodeError>? This would also make this patch much smaller, which is nice (especially when the "byte" field in InvalidValue only sometimes makes sense, hence it being an Option).
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.
Added a NetAddess::Unknown { descriptor }, cleaner than an enum, Agree, cleaner and better do not touch InvalidValue so let it free to be return for an invalid ed25519_pubkey, zero ports or constrained fields in future addresses.
src/ln/msgs.rs
Outdated
#[derive(Clone)] | ||
pub enum OptionalField<T> { | ||
/// Optional field is included in message | ||
Present { |
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.
Why not just Present(T)?
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.
Thanks, still learning to be a good rustacean
e3f46f3
to
2fdff3a
Compare
fuzz/fuzz_targets/router_target.rs
Outdated
@@ -125,9 +125,9 @@ pub fn do_test(data: &[u8]) { | |||
match <($MsgType)>::read(&mut reader) { | |||
Ok(msg) => msg, | |||
Err(e) => match e { | |||
msgs::DecodeError::UnknownVersion => return, | |||
msgs::DecodeError::UnknownVersion { .. } => return, |
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.
nit: stale.
@@ -191,7 +190,7 @@ pub struct OpenChannel { | |||
pub(crate) htlc_basepoint: PublicKey, | |||
pub(crate) first_per_commitment_point: PublicKey, | |||
pub(crate) channel_flags: u8, | |||
pub(crate) shutdown_scriptpubkey: Option<Script>, | |||
pub(crate) shutdown_scriptpubkey: OptionalField<Script>, |
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 believe you need a similar hunk in ChannelReestablish.
src/ln/msgs.rs
Outdated
@@ -372,6 +371,12 @@ pub enum NetAddress { | |||
/// The port on which the node is listenting | |||
port: u16, | |||
}, | |||
/// An unsupported address. | |||
/// At deserialization, we retrieve first byte of it if needed by caller. | |||
Unknown { |
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.
Hmmm, the panics introduced in get_id/len are kinda annoying. A user may deserialize a NetAddress and then try to reserialize it and get a panic. It may be easier to get a higher-level enum that selects between an unknown byte and a NetAddress for the deserialization.
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.
But an enum doesn't fit into Readable trait signature so seems to me here we are constrained between extending NetAddress enum type with UnknownAddress (but gross because of panic) or adding an UnknownAddressDescriptor with byte field in DecodeError ?
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.
Hmm? We can implement Readable for NetAddressReadEnum instead of for NetAddress and just map it properly in the message thats calling it.
2fdff3a
to
58d3b14
Compare
src/ln/router.rs
Outdated
self.htlc_minimum_msat.write(writer)?; | ||
self.fee_base_msat.write(writer)?; | ||
self.fee_proportional_millionths.write(writer)?; | ||
match &self.last_update_message { |
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.
Once you add the writer for Option, cant this switch to the impl_writeable!?
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.
There updated with impl_writeable_len_match
self.features.write(writer)?; | ||
self.one_to_two.write(writer)?; | ||
self.two_to_one.write(writer)?; | ||
match &self.announcement_message { |
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.
Same here - can we use impl_writeable?
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.
And there not, I mean due to DirectionalChannelInfo having itself optional field and announcement_msg being optional we have a good chunk of pattern to cover, so if macro goal is to be hygienic I'm not sure it's reached there.
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.
Err, would actually prefer imple_writeable!(.., 0, {}) for both as otherwise we give a wrong length descriptor.
Extend route_test to check if serialize/deserialize of NetworkMap works. Add PartialEq traits on some Router's structs. Modify also UnsignedNodeAnnouncement serialization
Add OptionalField in OpenChannel, AcceptChannel ChannelReestablish to avoid serialization implementation conflicts
58d3b14
to
54874f1
Compare
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.
Will take as #298 with the following few comments fixed and the commit order swapped as the first commit did not compile on its own.
break; | ||
}, | ||
Err(DecodeError::ShortRead) => return Err(DecodeError::BadLengthDescriptor), | ||
_ => unreachable!(), |
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.
We could hit at least DecodeError::Io if the user is streaming the message in to be deserialized live.
self.features.write(writer)?; | ||
self.one_to_two.write(writer)?; | ||
self.two_to_one.write(writer)?; | ||
match &self.announcement_message { |
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.
Err, would actually prefer imple_writeable!(.., 0, {}) for both as otherwise we give a wrong length descriptor.
impl<R: ::std::io::Read> Readable<R> for NodeInfo { | ||
fn read(reader: &mut R) -> Result<NodeInfo, DecodeError> { | ||
let channels_count: u64 = Readable::read(reader)?; | ||
let mut channels = Vec::with_capacity(channels_count as usize); |
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.
Careful with_capacity()ing a u64 - this will result in corruption causing a crash instead of returning an Err.
@@ -518,6 +592,16 @@ pub enum HTLCFailChannelUpdate { | |||
} | |||
} | |||
|
|||
/// Messages could have optional fields to use with extended features | |||
/// Due to serialization issues, we encapsulate it in enum |
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 speciy what those "serialization issues" are.
Will add a test and maybe more docs
Part of #57