Skip to content

Commit 16fdd33

Browse files
Implement LengthLimitedRead for &[u8]
We want to slowly phase out the use of Cursor in the codebase, which means we want to be able to call LengthLimitedRead::read(&mut &slice_of_bytes[..]) instead of wrapping the slice in a Cursor. However, this breaks the current LengthLimitedRead::total_bytes method because the underlying Read implementation for slice advances the slice as it is read, so slice.len() can't be used to get the total bytes after any part of the struct is read. Therefore here we also switch the ::total_bytes method to ::remaining_bytes, which seems like a more sensible method anyway since the reader is being consumed.
1 parent f5fc13b commit 16fdd33

File tree

4 files changed

+17
-8
lines changed

4 files changed

+17
-8
lines changed

lightning/src/crypto/streams.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ impl<T: Readable> LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter<T> {
6060
// Self::readable. LengthLimitedRead must be used instead of std::io::Read because we need the
6161
// total length to separate out the tag at the end.
6262
fn read<R: LengthLimitedRead>(r: &mut R, secret: [u8; 32]) -> Result<Self, DecodeError> {
63-
if r.total_bytes() < 16 {
63+
if r.remaining_bytes() < 16 {
6464
return Err(DecodeError::InvalidValue);
6565
}
6666

6767
let mut chacha = ChaCha20Poly1305RFC::new(&secret, &[0; 12], &[]);
68-
let decrypted_len = r.total_bytes() - 16;
68+
let decrypted_len = r.remaining_bytes() - 16;
6969
let s = FixedLengthReader::new(r, decrypted_len);
7070
let mut chacha_stream = ChaChaPolyReader { chacha: &mut chacha, read: s };
7171
let readable: T = Readable::read(&mut chacha_stream)?;

lightning/src/ln/msgs.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2324,10 +2324,11 @@ impl Writeable for TrampolineOnionPacket {
23242324

23252325
impl LengthReadable for TrampolineOnionPacket {
23262326
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
2327+
let hop_data_len = r.remaining_bytes().saturating_sub(66); // 1 (version) + 33 (pubkey) + 32 (HMAC) = 66
2328+
23272329
let version = Readable::read(r)?;
23282330
let public_key = Readable::read(r)?;
23292331

2330-
let hop_data_len = r.total_bytes().saturating_sub(66); // 1 (version) + 33 (pubkey) + 32 (HMAC) = 66
23312332
let mut rd = FixedLengthReader::new(r, hop_data_len);
23322333
let hop_data = WithoutLength::<Vec<u8>>::read(&mut rd)?.0;
23332334

lightning/src/onion_message/packet.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,12 @@ impl Writeable for Packet {
8585
impl LengthReadable for Packet {
8686
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
8787
const READ_BUFFER_SIZE: usize = 4096;
88+
let hop_data_len = r.remaining_bytes().saturating_sub(66) as usize; // 1 (version) + 33 (pubkey) + 32 (HMAC) = 66
8889

8990
let version = Readable::read(r)?;
9091
let public_key = Readable::read(r)?;
9192

9293
let mut hop_data = Vec::new();
93-
let hop_data_len = r.total_bytes().saturating_sub(66) as usize; // 1 (version) + 33 (pubkey) + 32 (HMAC) = 66
9494
let mut read_idx = 0;
9595
while read_idx < hop_data_len {
9696
let mut read_buffer = [0; READ_BUFFER_SIZE];

lightning/src/util/ser.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ impl<'a, R: Read> Read for FixedLengthReader<'a, R> {
228228

229229
impl<'a, R: Read> LengthLimitedRead for FixedLengthReader<'a, R> {
230230
#[inline]
231-
fn total_bytes(&self) -> u64 {
232-
self.total_bytes
231+
fn remaining_bytes(&self) -> u64 {
232+
self.total_bytes.saturating_sub(self.bytes_read)
233233
}
234234
}
235235

@@ -348,8 +348,16 @@ where
348348
/// that the object being read will only consume a fixed number of bytes from the underlying
349349
/// [`io::Read`], see [`FixedLengthReader`] for an example.
350350
pub trait LengthLimitedRead: Read {
351-
/// The total number of bytes available to be read.
352-
fn total_bytes(&self) -> u64;
351+
/// The number of bytes remaining to be read.
352+
fn remaining_bytes(&self) -> u64;
353+
}
354+
355+
impl LengthLimitedRead for &[u8] {
356+
fn remaining_bytes(&self) -> u64 {
357+
// The underlying `Read` implementation for slice updates the slice to point to the yet unread
358+
// part.
359+
self.len() as u64
360+
}
353361
}
354362

355363
/// Similar to [`LengthReadable`]. Useful when an additional set of arguments is required to

0 commit comments

Comments
 (0)