Skip to content

Implement Readable for LengthReadable #3579

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

Merged
merged 4 commits into from
Feb 7, 2025

Conversation

arik-so
Copy link
Contributor

@arik-so arik-so commented Jan 30, 2025

Inbound Trampoline entrypoint packets will contain inner onions, which only implement LengthReadable. Until now, we never had to decode LengthReadable-only structs in TLV streams, so this issue never surfaced before, but going forward, this will allow us to parse inbound Trampoline data.

@@ -395,7 +395,7 @@ macro_rules! _decode_tlv {
$field = f.0;
}};
($outer_reader: expr, $reader: expr, $field: ident, option) => {{
$field = Some($crate::util::ser::Readable::read(&mut $reader)?);
$field = Some($crate::util::ser::LengthReadable::read(&mut $reader)?);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

it might be prudent to change the one line line 388, too

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yea, probably should use it for all TLV value reads.

@arik-so arik-so force-pushed the length_readable_serde branch 2 times, most recently from 58c565c to c92c81b Compare January 30, 2025 21:23
Copy link

codecov bot commented Jan 30, 2025

Codecov Report

Attention: Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.

Project coverage is 88.84%. Comparing base (31b32c5) to head (c92c81b).
Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/msgs.rs 60.00% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3579      +/-   ##
==========================================
+ Coverage   88.53%   88.84%   +0.31%     
==========================================
  Files         149      149              
  Lines      114567   116432    +1865     
  Branches   114567   116432    +1865     
==========================================
+ Hits       101428   103448    +2020     
+ Misses      10645    10514     -131     
+ Partials     2494     2470      -24     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -363,14 +363,21 @@ where

/// A trait that various higher-level LDK types implement allowing them to be read in
/// from a [`Read`], requiring the implementer to provide the total length of the read.
pub(crate) trait LengthReadable
Copy link
Collaborator

Choose a reason for hiding this comment

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

Probably could update the docs since its now pub

@arik-so arik-so force-pushed the length_readable_serde branch from c92c81b to 21acd71 Compare January 31, 2025 21:48
@TheBlueMatt
Copy link
Collaborator

Feel free to squash.

Copy link
Member

Choose a reason for hiding this comment

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

Hello!
I was reviewing this and noticed that the rule at line 454 doesn’t use LengthReadable. I was curious—why is that the case?

($outer_reader: expr, $reader: expr, $field: ident, (option, encoding: ($fieldty: ty, $encoding: ident))) => {{
		$field = {
			let field: $encoding<$fieldty> = ser::Readable::read(&mut $reader)?;
			Some(field.0)
		};
	}};

Would love to understand it. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I think this is the last missing one

Copy link
Contributor Author

Choose a reason for hiding this comment

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

CI is currently running with it added

Copy link
Contributor Author

Choose a reason for hiding this comment

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

squashed

@arik-so arik-so force-pushed the length_readable_serde branch from 4fc2a9d to 9189640 Compare February 4, 2025 21:42
@arik-so arik-so requested a review from TheBlueMatt February 5, 2025 01:03
Copy link
Member

@shaavan shaavan left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

/// A trait that various higher-level LDK types implement allowing them to be read in
/// from a [`Read`], requiring the implementer to provide the total length of the read.
pub(crate) trait LengthReadable
/// A trait that various LDK types implement allowing them to be read in from a [`Read`], requiring
Copy link
Collaborator

Choose a reason for hiding this comment

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

Were you gonna remove the weird reference to "various LDK types" implementing this? Its a public trait - anything can implement it now (and only a few LDK types actually implement it)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no more weird references

/// from a [`Read`], requiring the implementer to provide the total length of the read.
pub(crate) trait LengthReadable
/// A trait that various LDK types implement allowing them to be read in from a [`Read`], requiring
/// the implementer to provide the total length of the read.
Copy link
Collaborator

Choose a reason for hiding this comment

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

The implementer isn't providing the total length of the read, the implementer is relying on having the length of the buffer available when being read - the implementer is the struct being deserialized.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

rephrased

impl<T: Readable> LengthReadable for T {
#[inline]
fn read<R: Read>(reader: &mut R) -> Result<T, DecodeError> {
Readable::read(reader)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this fail if the expected length wasn't read?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

given that without resorting to assert_eq, it would produce pretty ubiquitous overhead, we agreed not to

In this commit we rename this method to `read_from_fixed_length_buffer`
to avoid ambiguities with `Readable`.
@@ -2854,7 +2854,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
let mut keysend_preimage: Option<PaymentPreimage> = None;
let mut custom_tlvs = Vec::new();

let tlv_len = BigSize::read(r)?;
let tlv_len = <BigSize as Readable>::read(r)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this can be reverted since the trait method was renamed, some other changes in this commit may also be unnecessary now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fair point. Reverted

@arik-so arik-so force-pushed the length_readable_serde branch from 8f21227 to a86e58e Compare February 6, 2025 19:41
@@ -1964,7 +1964,7 @@ impl LengthReadable for TrampolineOnionPacket {

let hop_data_len = r.total_bytes().saturating_sub(66); // 1 (version) + 33 (pubkey) + 32 (HMAC) = 66
let mut rd = FixedLengthReader::new(r, hop_data_len);
let hop_data = WithoutLength::<Vec<u8>>::read(&mut rd)?.0;
let hop_data = WithoutLength::<Vec<u8>>::read_from_fixed_length_buffer(&mut rd)?.0;
Copy link
Contributor

Choose a reason for hiding this comment

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

This should either go in a separate commit or the commit message should be updated for why we need this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's actually not even necessary any longer, dropped

Inbound Trampoline entrypoint packets will contain inner onions, which
only implement LengthReadable. Until now, we never had to decode
LengthReadable-only structs in TLV streams, so this issue never
surfaced before, but going forward, this will allow us to parse inbound
Trampoline data.
A followup commit will require that LengthReadable be accessible from
outside the lightning crate, as it will be the default trait referenced
for TLV stream decoding.
Previously, our deserialization macros used the `Readable` trait by
default. Now that `LengthReadable` is public and all `Readable` types
also implement it, we can use `LengthReadable` instead.
@arik-so arik-so force-pushed the length_readable_serde branch from a86e58e to 9dbe358 Compare February 6, 2025 20:45
@arik-so arik-so merged commit 8e90841 into lightningdevkit:main Feb 7, 2025
24 of 25 checks passed
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.

4 participants