Skip to content

Commit 1b1dcb8

Browse files
committed
Add size_hint in ser and call size_hint in all message serializers
1 parent ec5a4c8 commit 1b1dcb8

File tree

3 files changed

+99
-27
lines changed

3 files changed

+99
-27
lines changed

src/ln/msgs.rs

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,7 +1704,10 @@ impl MsgDecodable for ErrorMessage {
17041704
}
17051705
}
17061706

1707-
impl_writeable!(AcceptChannel, {
1707+
impl_writeable_len_match!(AcceptChannel, {
1708+
{AcceptChannel{ shutdown_scriptpubkey: Some(ref script), ..}, 270 + 2 + script.len()},
1709+
{_, 270}
1710+
}, {
17081711
temporary_channel_id,
17091712
dust_limit_satoshis,
17101713
max_htlc_value_in_flight_msat,
@@ -1722,7 +1725,7 @@ impl_writeable!(AcceptChannel, {
17221725
shutdown_scriptpubkey
17231726
});
17241727

1725-
impl_writeable!(AnnouncementSignatures, {
1728+
impl_writeable!(AnnouncementSignatures, 32+8+64*2, {
17261729
channel_id,
17271730
short_channel_id,
17281731
node_signature,
@@ -1731,6 +1734,7 @@ impl_writeable!(AnnouncementSignatures, {
17311734

17321735
impl<W: Writer> Writeable<W> for ChannelReestablish {
17331736
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
1737+
w.size_hint(if self.data_loss_protect.is_some() { 32+2*8+33+32 } else { 32+2*8 });
17341738
self.channel_id.write(w)?;
17351739
self.next_local_commitment_number.write(w)?;
17361740
self.next_remote_commitment_number.write(w)?;
@@ -1763,55 +1767,68 @@ impl<R: Read> Readable<R> for ChannelReestablish{
17631767
}
17641768
}
17651769

1766-
impl_writeable!(ClosingSigned, {
1770+
impl_writeable!(ClosingSigned, 32+8+64, {
17671771
channel_id,
17681772
fee_satoshis,
17691773
signature
17701774
});
17711775

1772-
impl_writeable!(CommitmentSigned, {
1776+
impl_writeable_len_match!(CommitmentSigned, {
1777+
{ CommitmentSigned { ref htlc_signatures, .. }, 32+64+2+htlc_signatures.len()*64 }
1778+
}, {
17731779
channel_id,
17741780
signature,
17751781
htlc_signatures
17761782
});
17771783

1778-
impl_writeable!(DecodedOnionErrorPacket, {
1784+
impl_writeable_len_match!(DecodedOnionErrorPacket, {
1785+
{ DecodedOnionErrorPacket { ref failuremsg, ref pad, .. }, 32 + 4 + failuremsg.len() + pad.len() }
1786+
}, {
17791787
hmac,
17801788
failuremsg,
17811789
pad
17821790
});
17831791

1784-
impl_writeable!(FundingCreated, {
1792+
impl_writeable!(FundingCreated, 32+32+2+64, {
17851793
temporary_channel_id,
17861794
funding_txid,
17871795
funding_output_index,
17881796
signature
17891797
});
17901798

1791-
impl_writeable!(FundingSigned, {
1799+
impl_writeable!(FundingSigned, 32+64, {
17921800
channel_id,
17931801
signature
17941802
});
17951803

1796-
impl_writeable!(FundingLocked, {
1804+
impl_writeable!(FundingLocked, 32+33, {
17971805
channel_id,
17981806
next_per_commitment_point
17991807
});
18001808

1801-
impl_writeable!(GlobalFeatures, {
1809+
impl_writeable_len_match!(GlobalFeatures, {
1810+
{ GlobalFeatures { ref flags }, flags.len() + 2 }
1811+
}, {
18021812
flags
18031813
});
18041814

1805-
impl_writeable!(LocalFeatures, {
1815+
impl_writeable_len_match!(LocalFeatures, {
1816+
{ LocalFeatures { ref flags }, flags.len() + 2 }
1817+
}, {
18061818
flags
18071819
});
18081820

1809-
impl_writeable!(Init, {
1821+
impl_writeable_len_match!(Init, {
1822+
{ Init { ref global_features, ref local_features }, global_features.flags.len() + local_features.flags.len() + 4 }
1823+
}, {
18101824
global_features,
18111825
local_features
18121826
});
18131827

1814-
impl_writeable!(OpenChannel, {
1828+
impl_writeable_len_match!(OpenChannel, {
1829+
{ OpenChannel { shutdown_scriptpubkey: Some(ref script), .. }, 319 + 2 + script.len() },
1830+
{ OpenChannel { shutdown_scriptpubkey: None, .. }, 319 }
1831+
}, {
18151832
chain_hash,
18161833
temporary_channel_id,
18171834
funding_satoshis,
@@ -1833,47 +1850,54 @@ impl_writeable!(OpenChannel, {
18331850
shutdown_scriptpubkey
18341851
});
18351852

1836-
impl_writeable!(RevokeAndACK, {
1853+
impl_writeable!(RevokeAndACK, 32+32+33, {
18371854
channel_id,
18381855
per_commitment_secret,
18391856
next_per_commitment_point
18401857
});
18411858

1842-
impl_writeable!(Shutdown, {
1859+
impl_writeable_len_match!(Shutdown, {
1860+
{ Shutdown { ref scriptpubkey, .. }, 32 + 2 + scriptpubkey.len() }
1861+
}, {
18431862
channel_id,
18441863
scriptpubkey
18451864
});
18461865

1847-
impl_writeable!(UpdateFailHTLC, {
1866+
impl_writeable_len_match!(UpdateFailHTLC, {
1867+
{ UpdateFailHTLC { ref reason, .. }, 32 + 10 + reason.data.len() }
1868+
}, {
18481869
channel_id,
18491870
htlc_id,
18501871
reason
18511872
});
18521873

1853-
impl_writeable!(UpdateFailMalformedHTLC, {
1874+
impl_writeable!(UpdateFailMalformedHTLC, 32+8+32+2, {
18541875
channel_id,
18551876
htlc_id,
18561877
sha256_of_onion,
18571878
failure_code
18581879
});
18591880

1860-
impl_writeable!(UpdateFee, {
1881+
impl_writeable!(UpdateFee, 32+4, {
18611882
channel_id,
18621883
feerate_per_kw
18631884
});
18641885

1865-
impl_writeable!(UpdateFulfillHTLC, {
1886+
impl_writeable!(UpdateFulfillHTLC, 32+8+32, {
18661887
channel_id,
18671888
htlc_id,
18681889
payment_preimage
18691890
});
18701891

1871-
impl_writeable!(OnionErrorPacket, {
1892+
impl_writeable_len_match!(OnionErrorPacket, {
1893+
{ OnionErrorPacket { ref data, .. }, 2 + data.len() }
1894+
}, {
18721895
data
18731896
});
18741897

18751898
impl<W: Writer> Writeable<W> for OnionPacket {
18761899
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
1900+
w.size_hint(1 + 33 + 20*65 + 32);
18771901
self.version.write(w)?;
18781902
match self.public_key {
18791903
Ok(pubkey) => pubkey.write(w)?,
@@ -1900,7 +1924,7 @@ impl<R: Read> Readable<R> for OnionPacket {
19001924
}
19011925
}
19021926

1903-
impl_writeable!(UpdateAddHTLC, {
1927+
impl_writeable!(UpdateAddHTLC, 32+8+8+32+4+1366, {
19041928
channel_id,
19051929
htlc_id,
19061930
amount_msat,
@@ -1911,6 +1935,7 @@ impl_writeable!(UpdateAddHTLC, {
19111935

19121936
impl<W: Writer> Writeable<W> for OnionRealm0HopData {
19131937
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
1938+
w.size_hint(32);
19141939
self.short_channel_id.write(w)?;
19151940
self.amt_to_forward.write(w)?;
19161941
self.outgoing_cltv_value.write(w)?;
@@ -1935,6 +1960,7 @@ impl<R: Read> Readable<R> for OnionRealm0HopData {
19351960

19361961
impl<W: Writer> Writeable<W> for OnionHopData {
19371962
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
1963+
w.size_hint(65);
19381964
self.realm.write(w)?;
19391965
self.data.write(w)?;
19401966
self.hmac.write(w)?;
@@ -1960,6 +1986,7 @@ impl<R: Read> Readable<R> for OnionHopData {
19601986

19611987
impl<W: Writer> Writeable<W> for Ping {
19621988
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
1989+
w.size_hint(self.byteslen as usize + 4);
19631990
self.ponglen.write(w)?;
19641991
vec![0u8; self.byteslen as usize].write(w)?; // size-unchecked write
19651992
Ok(())
@@ -1981,6 +2008,7 @@ impl<R: Read> Readable<R> for Ping {
19812008

19822009
impl<W: Writer> Writeable<W> for Pong {
19832010
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
2011+
w.size_hint(self.byteslen as usize + 2);
19842012
vec![0u8; self.byteslen as usize].write(w)?; // size-unchecked write
19852013
Ok(())
19862014
}
@@ -2000,6 +2028,7 @@ impl<R: Read> Readable<R> for Pong {
20002028

20012029
impl<W: Writer> Writeable<W> for UnsignedChannelAnnouncement {
20022030
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
2031+
w.size_hint(2 + 2*32 + 4*33 + self.features.flags.len() + self.excess_data.len());
20032032
self.features.write(w)?;
20042033
self.chain_hash.write(w)?;
20052034
self.short_channel_id.write(w)?;
@@ -2037,7 +2066,10 @@ impl<R: Read> Readable<R> for UnsignedChannelAnnouncement {
20372066
}
20382067
}
20392068

2040-
impl_writeable!(ChannelAnnouncement,{
2069+
impl_writeable_len_match!(ChannelAnnouncement, {
2070+
{ ChannelAnnouncement { contents: UnsignedChannelAnnouncement {ref features, ref excess_data, ..}, .. },
2071+
2 + 2*32 + 4*33 + features.flags.len() + excess_data.len() + 4*64 }
2072+
}, {
20412073
node_signature_1,
20422074
node_signature_2,
20432075
bitcoin_signature_1,
@@ -2047,6 +2079,7 @@ impl_writeable!(ChannelAnnouncement,{
20472079

20482080
impl<W: Writer> Writeable<W> for UnsignedChannelUpdate {
20492081
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
2082+
w.size_hint(64 + self.excess_data.len());
20502083
self.chain_hash.write(w)?;
20512084
self.short_channel_id.write(w)?;
20522085
self.timestamp.write(w)?;
@@ -2080,15 +2113,20 @@ impl<R: Read> Readable<R> for UnsignedChannelUpdate {
20802113
}
20812114
}
20822115

2083-
impl_writeable!(ChannelUpdate, {
2116+
impl_writeable_len_match!(ChannelUpdate, {
2117+
{ ChannelUpdate { contents: UnsignedChannelUpdate {ref excess_data, ..}, .. },
2118+
64 + excess_data.len() + 64 }
2119+
}, {
20842120
signature,
20852121
contents
20862122
});
20872123

20882124
impl<W: Writer> Writeable<W> for ErrorMessage {
20892125
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
2126+
w.size_hint(32 + 2 + self.data.len());
20902127
self.channel_id.write(w)?;
2091-
self.data.as_bytes().to_vec().write(w)?; // write with size prefix
2128+
(self.data.len() as u16).write(w)?;
2129+
w.write_all(self.data.as_bytes())?;
20922130
Ok(())
20932131
}
20942132
}
@@ -2113,6 +2151,7 @@ impl<R: Read> Readable<R> for ErrorMessage {
21132151

21142152
impl<W: Writer> Writeable<W> for UnsignedNodeAnnouncement {
21152153
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
2154+
w.size_hint(64 + 76 + self.features.flags.len() + self.addresses.len()*38 + self.excess_address_data.len() + self.excess_data.len());
21162155
self.features.write(w)?;
21172156
self.timestamp.write(w)?;
21182157
self.node_id.write(w)?;
@@ -2279,7 +2318,10 @@ impl<R: Read> Readable<R> for UnsignedNodeAnnouncement {
22792318
}
22802319
}
22812320

2282-
impl_writeable!(NodeAnnouncement, {
2321+
impl_writeable_len_match!(NodeAnnouncement, {
2322+
{ NodeAnnouncement { contents: UnsignedNodeAnnouncement { ref features, ref addresses, ref excess_address_data, ref excess_data, ..}, .. },
2323+
64 + 76 + features.flags.len() + addresses.len()*38 + excess_address_data.len() + excess_data.len() }
2324+
}, {
22832325
signature,
22842326
contents
22852327
});

src/util/ser.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,25 @@ use util::byte_utils::{be64_to_array, be32_to_array, be16_to_array, slice_to_be1
1414

1515
const MAX_BUF_SIZE: usize = 64 * 1024;
1616

17-
/// A trait that is similar to std::io::Write.
18-
/// An impl is provided for any type that also impls std::io::Write.
17+
/// A trait that is similar to std::io::Write but has one extra function which can be used to size
18+
/// buffers being written into.
19+
/// An impl is provided for any type that also impls std::io::Write which simply ignores size
20+
/// hints.
1921
pub trait Writer {
2022
/// Writes the given buf out. See std::io::Write::write_all for more
2123
fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error>;
24+
/// Hints that data of the given size is about the be written. This may not always be called
25+
/// prior to data being written and may be safely ignored.
26+
fn size_hint(&mut self, size: usize);
2227
}
2328

2429
impl<W: ::std::io::Write> Writer for W {
30+
#[inline]
2531
fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
2632
<Self as ::std::io::Write>::write_all(self, buf)
2733
}
34+
#[inline]
35+
fn size_hint(&mut self, _size: usize) { }
2836
}
2937

3038
/// A trait that various rust-lightning types implement allowing them to be written out to a Writer

src/util/ser_macros.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,29 @@
11
macro_rules! impl_writeable {
2-
($st:ident, {$($field:ident),*}) => {
2+
($st:ident, $len: expr, {$($field:ident),*}) => {
33
impl<W: Writer> Writeable<W> for $st {
44
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
5+
w.size_hint($len);
6+
$( self.$field.write(w)?; )*
7+
Ok(())
8+
}
9+
}
10+
11+
impl<R: Read> Readable<R> for $st {
12+
fn read(r: &mut R) -> Result<Self, DecodeError> {
13+
Ok(Self {
14+
$($field: Readable::read(r)?),*
15+
})
16+
}
17+
}
18+
}
19+
}
20+
macro_rules! impl_writeable_len_match {
21+
($st:ident, {$({$m: pat, $l: expr}),*}, {$($field:ident),*}) => {
22+
impl<W: Writer> Writeable<W> for $st {
23+
fn write(&self, w: &mut W) -> Result<(), DecodeError> {
24+
w.size_hint(match *self {
25+
$($m => $l,)*
26+
});
527
$( self.$field.write(w)?; )*
628
Ok(())
729
}

0 commit comments

Comments
 (0)