Skip to content

Commit 377824f

Browse files
committed
Add WithoutLength wrapper
When serializing variable-length types as part of a TLV stream, the length does not need to be serialized as it is already encoded in TLV records. Add a WithoutLength wrapper for this encoding. Replace VecReadWrapper and VecWriteWrapper with this single type to avoid redundant encoders.
1 parent 6b6bf13 commit 377824f

File tree

5 files changed

+50
-47
lines changed

5 files changed

+50
-47
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6523,7 +6523,7 @@ impl Writeable for HTLCSource {
65236523
(1, payment_id_opt, option),
65246524
(2, first_hop_htlc_msat, required),
65256525
(3, payment_secret, option),
6526-
(4, path, vec_type),
6526+
(4, *path, vec_type),
65276527
(5, payment_params, option),
65286528
});
65296529
}

lightning/src/onion_message/packet.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,15 @@ impl<T: CustomOnionMessageContents> Writeable for (Payload<T>, [u8; 32]) {
164164
match &self.0 {
165165
Payload::Forward(ForwardControlTlvs::Blinded(encrypted_bytes)) => {
166166
encode_varint_length_prefixed_tlv!(w, {
167-
(4, encrypted_bytes, vec_type)
167+
(4, *encrypted_bytes, vec_type)
168168
})
169169
},
170170
Payload::Receive {
171171
control_tlvs: ReceiveControlTlvs::Blinded(encrypted_bytes), reply_path, message,
172172
} => {
173173
encode_varint_length_prefixed_tlv!(w, {
174174
(2, reply_path, option),
175-
(4, encrypted_bytes, vec_type),
175+
(4, *encrypted_bytes, vec_type),
176176
(message.tlv_type(), message, required)
177177
})
178178
},

lightning/src/util/events.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::ln::msgs;
2323
use crate::ln::msgs::DecodeError;
2424
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
2525
use crate::routing::gossip::NetworkUpdate;
26-
use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
26+
use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, WithoutLength};
2727
use crate::routing::router::{RouteHop, RouteParameters};
2828

2929
use bitcoin::{PackedLockTime, Transaction, OutPoint};
@@ -756,7 +756,7 @@ impl Writeable for Event {
756756
(1, network_update, option),
757757
(2, payment_failed_permanently, required),
758758
(3, all_paths_failed, required),
759-
(5, path, vec_type),
759+
(5, *path, vec_type),
760760
(7, short_channel_id, option),
761761
(9, retry, option),
762762
(11, payment_id, option),
@@ -770,7 +770,7 @@ impl Writeable for Event {
770770
&Event::SpendableOutputs { ref outputs } => {
771771
5u8.write(writer)?;
772772
write_tlv_fields!(writer, {
773-
(0, VecWriteWrapper(outputs), required),
773+
(0, WithoutLength(outputs), required),
774774
});
775775
},
776776
&Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id } => {
@@ -802,7 +802,7 @@ impl Writeable for Event {
802802
write_tlv_fields!(writer, {
803803
(0, payment_id, required),
804804
(2, payment_hash, option),
805-
(4, path, vec_type)
805+
(4, *path, vec_type)
806806
})
807807
},
808808
&Event::PaymentFailed { ref payment_id, ref payment_hash } => {
@@ -830,15 +830,15 @@ impl Writeable for Event {
830830
write_tlv_fields!(writer, {
831831
(0, payment_id, required),
832832
(2, payment_hash, required),
833-
(4, path, vec_type)
833+
(4, *path, vec_type)
834834
})
835835
},
836836
&Event::ProbeFailed { ref payment_id, ref payment_hash, ref path, ref short_channel_id } => {
837837
23u8.write(writer)?;
838838
write_tlv_fields!(writer, {
839839
(0, payment_id, required),
840840
(2, payment_hash, required),
841-
(4, path, vec_type),
841+
(4, *path, vec_type),
842842
(6, short_channel_id, option),
843843
})
844844
},
@@ -969,7 +969,7 @@ impl MaybeReadable for Event {
969969
4u8 => Ok(None),
970970
5u8 => {
971971
let f = || {
972-
let mut outputs = VecReadWrapper(Vec::new());
972+
let mut outputs = WithoutLength(Vec::new());
973973
read_tlv_fields!(reader, {
974974
(0, outputs, required),
975975
});

lightning/src/util/ser.rs

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -283,39 +283,6 @@ impl<T: Readable> From<T> for OptionDeserWrapper<T> {
283283
fn from(t: T) -> OptionDeserWrapper<T> { OptionDeserWrapper(Some(t)) }
284284
}
285285

286-
/// Wrapper to write each element of a Vec with no length prefix
287-
pub(crate) struct VecWriteWrapper<'a, T: Writeable>(pub &'a Vec<T>);
288-
impl<'a, T: Writeable> Writeable for VecWriteWrapper<'a, T> {
289-
#[inline]
290-
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
291-
for ref v in self.0.iter() {
292-
v.write(writer)?;
293-
}
294-
Ok(())
295-
}
296-
}
297-
298-
/// Wrapper to read elements from a given stream until it reaches the end of the stream.
299-
pub(crate) struct VecReadWrapper<T>(pub Vec<T>);
300-
impl<T: MaybeReadable> Readable for VecReadWrapper<T> {
301-
#[inline]
302-
fn read<R: Read>(mut reader: &mut R) -> Result<Self, DecodeError> {
303-
let mut values = Vec::new();
304-
loop {
305-
let mut track_read = ReadTrackingReader::new(&mut reader);
306-
match MaybeReadable::read(&mut track_read) {
307-
Ok(Some(v)) => { values.push(v); },
308-
Ok(None) => { },
309-
// If we failed to read any bytes at all, we reached the end of our TLV
310-
// stream and have simply exhausted all entries.
311-
Err(ref e) if e == &DecodeError::ShortRead && !track_read.have_read => break,
312-
Err(e) => return Err(e),
313-
}
314-
}
315-
Ok(Self(values))
316-
}
317-
}
318-
319286
pub(crate) struct U48(pub u64);
320287
impl Writeable for U48 {
321288
#[inline]
@@ -547,6 +514,42 @@ impl Readable for [u16; 8] {
547514
}
548515
}
549516

517+
/// For variable-length values within TLV record where the length is encoded as part of the record.
518+
/// Used to prevent encoding the length twice.
519+
pub(crate) struct WithoutLength<T>(pub T);
520+
521+
impl<'a, T: Writeable> Writeable for WithoutLength<&'a Vec<T>> {
522+
#[inline]
523+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
524+
for ref v in self.0.iter() {
525+
v.write(writer)?;
526+
}
527+
Ok(())
528+
}
529+
}
530+
531+
impl<T: MaybeReadable> Readable for WithoutLength<Vec<T>> {
532+
#[inline]
533+
fn read<R: Read>(mut reader: &mut R) -> Result<Self, DecodeError> {
534+
let mut values = Vec::new();
535+
loop {
536+
let mut track_read = ReadTrackingReader::new(&mut reader);
537+
match MaybeReadable::read(&mut track_read) {
538+
Ok(Some(v)) => { values.push(v); },
539+
Ok(None) => { },
540+
// If we failed to read any bytes at all, we reached the end of our TLV
541+
// stream and have simply exhausted all entries.
542+
Err(ref e) if e == &DecodeError::ShortRead && !track_read.have_read => break,
543+
Err(e) => return Err(e),
544+
}
545+
}
546+
Ok(Self(values))
547+
}
548+
}
549+
impl<'a, T> From<&'a Vec<T>> for WithoutLength<&'a Vec<T>> {
550+
fn from(v: &'a Vec<T>) -> Self { Self(v) }
551+
}
552+
550553
// HashMap
551554
impl<K, V> Writeable for HashMap<K, V>
552555
where K: Writeable + Eq + Hash,

lightning/src/util/ser_macros.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ macro_rules! encode_tlv {
1717
$field.write($stream)?;
1818
};
1919
($stream: expr, $type: expr, $field: expr, vec_type) => {
20-
encode_tlv!($stream, $type, $crate::util::ser::VecWriteWrapper(&$field), required);
20+
encode_tlv!($stream, $type, $crate::util::ser::WithoutLength(&$field), required);
2121
};
2222
($stream: expr, $optional_type: expr, $optional_field: expr, option) => {
2323
if let Some(ref field) = $optional_field {
@@ -66,7 +66,7 @@ macro_rules! get_varint_length_prefixed_tlv_length {
6666
$len.0 += field_len;
6767
};
6868
($len: expr, $type: expr, $field: expr, vec_type) => {
69-
get_varint_length_prefixed_tlv_length!($len, $type, $crate::util::ser::VecWriteWrapper(&$field), required);
69+
get_varint_length_prefixed_tlv_length!($len, $type, $crate::util::ser::WithoutLength(&$field), required);
7070
};
7171
($len: expr, $optional_type: expr, $optional_field: expr, option) => {
7272
if let Some(ref field) = $optional_field {
@@ -160,7 +160,7 @@ macro_rules! decode_tlv {
160160
$field = $crate::util::ser::Readable::read(&mut $reader)?;
161161
}};
162162
($reader: expr, $field: ident, vec_type) => {{
163-
let f: $crate::util::ser::VecReadWrapper<_> = $crate::util::ser::Readable::read(&mut $reader)?;
163+
let f: $crate::util::ser::WithoutLength<Vec<_>> = $crate::util::ser::Readable::read(&mut $reader)?;
164164
$field = Some(f.0);
165165
}};
166166
($reader: expr, $field: ident, option) => {{
@@ -453,7 +453,7 @@ macro_rules! _impl_writeable_tlv_based_enum_common {
453453
let id: u8 = $variant_id;
454454
id.write(writer)?;
455455
write_tlv_fields!(writer, {
456-
$(($type, $field, $fieldty)),*
456+
$(($type, *$field, $fieldty)),*
457457
});
458458
}),*
459459
$($st::$tuple_variant_name (ref field) => {

0 commit comments

Comments
 (0)