From 3c24a137b1088ca75d549b4355dc18980fad1a44 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 7 Mar 2024 14:37:58 -0800 Subject: [PATCH] Don't consume readers with FixedLengthReader We can't always assume that we're done reading after using a FixedLengthReader. In some cases, we may need to read a set of length-prefixed objects one at a time, and we'd like to do so without incurring an additional allocation by reading a number of bytes first to then deserialize them. --- lightning/src/crypto/streams.rs | 2 +- lightning/src/events/mod.rs | 32 ++++++++++++++++---------------- lightning/src/util/ser.rs | 12 ++++++------ lightning/src/util/ser_macros.rs | 4 ++-- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lightning/src/crypto/streams.rs b/lightning/src/crypto/streams.rs index 14921a386..e8217b8d9 100644 --- a/lightning/src/crypto/streams.rs +++ b/lightning/src/crypto/streams.rs @@ -151,7 +151,7 @@ mod tests { let writeable_len = $obj.serialized_length() as u64 + 16; let write_adapter = ChaChaPolyWriteAdapter::new(rho, &$obj); let encrypted_writeable_bytes = write_adapter.encode(); - let encrypted_writeable = &encrypted_writeable_bytes[..]; + let encrypted_writeable = &mut &encrypted_writeable_bytes[..]; // Now deserialize the object back and make sure it matches the original. let mut rd = FixedLengthReader::new(encrypted_writeable, writeable_len); diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index d4fa90c6a..f849dcc2f 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -1294,7 +1294,7 @@ impl MaybeReadable for Event { // Note that we do not write a length-prefixed TLV for FundingGenerationReady events. 0u8 => Ok(None), 1u8 => { - let f = || { + let mut f = || { let mut payment_hash = PaymentHash([0; 32]); let mut payment_preimage = None; let mut payment_secret = None; @@ -1342,7 +1342,7 @@ impl MaybeReadable for Event { f() }, 2u8 => { - let f = || { + let mut f = || { let mut payment_preimage = PaymentPreimage([0; 32]); let mut payment_hash = None; let mut payment_id = None; @@ -1366,7 +1366,7 @@ impl MaybeReadable for Event { f() }, 3u8 => { - let f = || { + let mut f = || { #[cfg(test)] let error_code = Readable::read(reader)?; #[cfg(test)] @@ -1409,7 +1409,7 @@ impl MaybeReadable for Event { }, 4u8 => Ok(None), 5u8 => { - let f = || { + let mut f = || { let mut outputs = WithoutLength(Vec::new()); let mut channel_id: Option = None; read_tlv_fields!(reader, { @@ -1445,7 +1445,7 @@ impl MaybeReadable for Event { })) }, 7u8 => { - let f = || { + let mut f = || { let mut prev_channel_id = None; let mut next_channel_id = None; let mut prev_user_channel_id = None; @@ -1473,7 +1473,7 @@ impl MaybeReadable for Event { f() }, 9u8 => { - let f = || { + let mut f = || { let mut channel_id = ChannelId::new_zero(); let mut reason = UpgradableRequired(None); let mut user_channel_id_low_opt: Option = None; @@ -1503,7 +1503,7 @@ impl MaybeReadable for Event { f() }, 11u8 => { - let f = || { + let mut f = || { let mut channel_id = ChannelId::new_zero(); let mut transaction = Transaction{ version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; read_tlv_fields!(reader, { @@ -1515,7 +1515,7 @@ impl MaybeReadable for Event { f() }, 13u8 => { - let f = || { + let mut f = || { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), (2, payment_hash, option), @@ -1531,7 +1531,7 @@ impl MaybeReadable for Event { f() }, 15u8 => { - let f = || { + let mut f = || { let mut payment_hash = PaymentHash([0; 32]); let mut payment_id = PaymentId([0; 32]); let mut reason = None; @@ -1553,7 +1553,7 @@ impl MaybeReadable for Event { Ok(None) }, 19u8 => { - let f = || { + let mut f = || { let mut payment_hash = PaymentHash([0; 32]); let mut purpose = UpgradableRequired(None); let mut amount_msat = 0; @@ -1580,7 +1580,7 @@ impl MaybeReadable for Event { f() }, 21u8 => { - let f = || { + let mut f = || { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), (2, payment_hash, required), @@ -1596,7 +1596,7 @@ impl MaybeReadable for Event { f() }, 23u8 => { - let f = || { + let mut f = || { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), (2, payment_hash, required), @@ -1614,7 +1614,7 @@ impl MaybeReadable for Event { f() }, 25u8 => { - let f = || { + let mut f = || { let mut prev_channel_id = ChannelId::new_zero(); let mut failed_next_destination_opt = UpgradableRequired(None); read_tlv_fields!(reader, { @@ -1630,7 +1630,7 @@ impl MaybeReadable for Event { }, 27u8 => Ok(None), 29u8 => { - let f = || { + let mut f = || { let mut channel_id = ChannelId::new_zero(); let mut user_channel_id: u128 = 0; let mut counterparty_node_id = RequiredWrapper(None); @@ -1652,7 +1652,7 @@ impl MaybeReadable for Event { f() }, 31u8 => { - let f = || { + let mut f = || { let mut channel_id = ChannelId::new_zero(); let mut user_channel_id: u128 = 0; let mut former_temporary_channel_id = None; @@ -1680,7 +1680,7 @@ impl MaybeReadable for Event { f() }, 33u8 => { - let f = || { + let mut f = || { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), }); diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 0611e6ffb..f333fa2ba 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -108,14 +108,14 @@ impl Writer for LengthCalculatingWriter { /// forward to ensure we always consume exactly the fixed length specified. /// /// This is not exported to bindings users as manual TLV building is not currently supported in bindings -pub struct FixedLengthReader { - read: R, +pub struct FixedLengthReader<'a, R: Read> { + read: &'a mut R, bytes_read: u64, total_bytes: u64, } -impl FixedLengthReader { +impl<'a, R: Read> FixedLengthReader<'a, R> { /// Returns a new [`FixedLengthReader`]. - pub fn new(read: R, total_bytes: u64) -> Self { + pub fn new(read: &'a mut R, total_bytes: u64) -> Self { Self { read, bytes_read: 0, total_bytes } } @@ -136,7 +136,7 @@ impl FixedLengthReader { } } } -impl Read for FixedLengthReader { +impl<'a, R: Read> Read for FixedLengthReader<'a, R> { #[inline] fn read(&mut self, dest: &mut [u8]) -> Result { if self.total_bytes == self.bytes_read { @@ -154,7 +154,7 @@ impl Read for FixedLengthReader { } } -impl LengthRead for FixedLengthReader { +impl<'a, R: Read> LengthRead for FixedLengthReader<'a, R> { #[inline] fn total_bytes(&self) -> u64 { self.total_bytes diff --git a/lightning/src/util/ser_macros.rs b/lightning/src/util/ser_macros.rs index 84d9f7a18..dce160a7c 100644 --- a/lightning/src/util/ser_macros.rs +++ b/lightning/src/util/ser_macros.rs @@ -1033,7 +1033,7 @@ macro_rules! impl_writeable_tlv_based_enum { $($variant_id => { // Because read_tlv_fields creates a labeled loop, we cannot call it twice // in the same function body. Instead, we define a closure and call it. - let f = || { + let mut f = || { $crate::_init_and_read_len_prefixed_tlv_fields!(reader, { $(($type, $field, $fieldty)),* }); @@ -1087,7 +1087,7 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable { $($variant_id => { // Because read_tlv_fields creates a labeled loop, we cannot call it twice // in the same function body. Instead, we define a closure and call it. - let f = || { + let mut f = || { $crate::_init_and_read_len_prefixed_tlv_fields!(reader, { $(($type, $field, $fieldty)),* }); -- 2.39.5