Skip to content

Commit b80d3d9

Browse files
committed
Change Option<T> serialization format to include length
This is a cheap way to fix an error in Router serialization roundtrip due to us calling read_to_end during the read of channel/node announcement/updates. During normal message reading, we only have limited bytes to read (specifically the message buffer) so this is fine, however when we read them inside Router, we have more data from other fields of the Router available as well. Thus, we end up reading the entire rest of the Router into one message field, and failing to deserialize. Because such fields are always stored in Option<>s, we can simply use a LengthLimitingStream in the Option<> serialization format and make only the correct number of bytes available. By using a variable-length integer for the new field, we avoid wasting space compared to the existing serialization format.
1 parent 32ca8ec commit b80d3d9

File tree

3 files changed

+29
-59
lines changed

3 files changed

+29
-59
lines changed

lightning/src/ln/channel.rs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3883,18 +3883,6 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
38833883
}
38843884
}
38853885

3886-
macro_rules! write_option {
3887-
($thing: expr) => {
3888-
match &$thing {
3889-
&None => 0u8.write(writer)?,
3890-
&Some(ref v) => {
3891-
1u8.write(writer)?;
3892-
v.write(writer)?;
3893-
},
3894-
}
3895-
}
3896-
}
3897-
38983886
(self.pending_outbound_htlcs.len() as u64).write(writer)?;
38993887
for htlc in self.pending_outbound_htlcs.iter() {
39003888
htlc.htlc_id.write(writer)?;
@@ -3912,15 +3900,15 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
39123900
},
39133901
&OutboundHTLCState::RemoteRemoved(ref fail_reason) => {
39143902
2u8.write(writer)?;
3915-
write_option!(*fail_reason);
3903+
fail_reason.write(writer)?;
39163904
},
39173905
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref fail_reason) => {
39183906
3u8.write(writer)?;
3919-
write_option!(*fail_reason);
3907+
fail_reason.write(writer)?;
39203908
},
39213909
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref fail_reason) => {
39223910
4u8.write(writer)?;
3923-
write_option!(*fail_reason);
3911+
fail_reason.write(writer)?;
39243912
},
39253913
}
39263914
}
@@ -3971,8 +3959,8 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
39713959
fail_reason.write(writer)?;
39723960
}
39733961

3974-
write_option!(self.pending_update_fee);
3975-
write_option!(self.holding_cell_update_fee);
3962+
self.pending_update_fee.write(writer)?;
3963+
self.holding_cell_update_fee.write(writer)?;
39763964

39773965
self.next_local_htlc_id.write(writer)?;
39783966
(self.next_remote_htlc_id - dropped_inbound_htlcs).write(writer)?;
@@ -3989,9 +3977,9 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
39893977
None => 0u8.write(writer)?,
39903978
}
39913979

3992-
write_option!(self.funding_txo);
3993-
write_option!(self.funding_tx_confirmed_in);
3994-
write_option!(self.short_channel_id);
3980+
self.funding_txo.write(writer)?;
3981+
self.funding_tx_confirmed_in.write(writer)?;
3982+
self.short_channel_id.write(writer)?;
39953983

39963984
self.last_block_connected.write(writer)?;
39973985
self.funding_tx_confirmations.write(writer)?;
@@ -4007,13 +3995,13 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
40073995
self.their_max_accepted_htlcs.write(writer)?;
40083996
self.minimum_depth.write(writer)?;
40093997

4010-
write_option!(self.their_pubkeys);
4011-
write_option!(self.their_cur_commitment_point);
3998+
self.their_pubkeys.write(writer)?;
3999+
self.their_cur_commitment_point.write(writer)?;
40124000

4013-
write_option!(self.their_prev_commitment_point);
4001+
self.their_prev_commitment_point.write(writer)?;
40144002
self.their_node_id.write(writer)?;
40154003

4016-
write_option!(self.their_shutdown_scriptpubkey);
4004+
self.their_shutdown_scriptpubkey.write(writer)?;
40174005

40184006
self.commitment_secrets.write(writer)?;
40194007

lightning/src/ln/channelmonitor.rs

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -489,11 +489,7 @@ impl Writeable for InputMaterial {
489489
script.write(writer)?;
490490
pubkey.write(writer)?;
491491
writer.write_all(&key[..])?;
492-
if *is_htlc {
493-
writer.write_all(&[0; 1])?;
494-
} else {
495-
writer.write_all(&[1; 1])?;
496-
}
492+
is_htlc.write(writer)?;
497493
writer.write_all(&byte_utils::be64_to_array(*amount))?;
498494
},
499495
&InputMaterial::RemoteHTLC { ref script, ref key, ref preimage, ref amount, ref locktime } => {
@@ -524,11 +520,7 @@ impl Readable for InputMaterial {
524520
let script = Readable::read(reader)?;
525521
let pubkey = Readable::read(reader)?;
526522
let key = Readable::read(reader)?;
527-
let is_htlc = match <u8 as Readable>::read(reader)? {
528-
0 => true,
529-
1 => false,
530-
_ => return Err(DecodeError::InvalidValue),
531-
};
523+
let is_htlc = Readable::read(reader)?;
532524
let amount = Readable::read(reader)?;
533525
InputMaterial::Revoked {
534526
script,
@@ -698,13 +690,7 @@ impl Writeable for ChannelMonitorUpdateStep {
698690
(htlc_outputs.len() as u64).write(w)?;
699691
for &(ref output, ref source) in htlc_outputs.iter() {
700692
output.write(w)?;
701-
match source {
702-
&None => 0u8.write(w)?,
703-
&Some(ref s) => {
704-
1u8.write(w)?;
705-
s.write(w)?;
706-
},
707-
}
693+
source.as_ref().map(|b| b.as_ref()).write(w)?;
708694
}
709695
},
710696
&ChannelMonitorUpdateStep::PaymentPreimage { ref payment_preimage } => {
@@ -973,18 +959,6 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
973959
// Set in initial Channel-object creation, so should always be set by now:
974960
U48(self.commitment_transaction_number_obscure_factor).write(writer)?;
975961

976-
macro_rules! write_option {
977-
($thing: expr) => {
978-
match $thing {
979-
&Some(ref t) => {
980-
1u8.write(writer)?;
981-
t.write(writer)?;
982-
},
983-
&None => 0u8.write(writer)?,
984-
}
985-
}
986-
}
987-
988962
match self.key_storage {
989963
Storage::Local { ref keys, ref funding_key, ref revocation_base_key, ref htlc_base_key, ref delayed_payment_base_key, ref payment_base_key, ref shutdown_pubkey, ref funding_info, ref current_remote_commitment_txid, ref prev_remote_commitment_txid } => {
990964
writer.write_all(&[0; 1])?;
@@ -1055,7 +1029,7 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
10551029
writer.write_all(&byte_utils::be64_to_array(htlc_infos.len() as u64))?;
10561030
for &(ref htlc_output, ref htlc_source) in htlc_infos.iter() {
10571031
serialize_htlc_in_commitment!(htlc_output);
1058-
write_option!(htlc_source);
1032+
htlc_source.as_ref().map(|b| b.as_ref()).write(writer)?;
10591033
}
10601034
}
10611035

@@ -1098,7 +1072,7 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
10981072
} else {
10991073
0u8.write(writer)?;
11001074
}
1101-
write_option!(htlc_source);
1075+
htlc_source.write(writer)?;
11021076
}
11031077
}
11041078
}

lightning/src/util/ser.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ pub trait Writeable {
172172
}
173173
}
174174

175+
impl<'a, T: Writeable> Writeable for &'a T {
176+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> { (*self).write(writer) }
177+
}
178+
175179
/// A trait that various rust-lightning types implement allowing them to be read in from a Read
176180
pub trait Readable
177181
where Self: Sized
@@ -592,7 +596,9 @@ impl<T: Writeable> Writeable for Option<T> {
592596
match *self {
593597
None => 0u8.write(w)?,
594598
Some(ref data) => {
595-
1u8.write(w)?;
599+
let mut len_calc = LengthCalculatingWriter(0);
600+
data.write(&mut len_calc).expect("No in-memory data may fail to serialize");
601+
BigSize(len_calc.0 as u64 + 1).write(w)?;
596602
data.write(w)?;
597603
}
598604
}
@@ -603,10 +609,12 @@ impl<T: Writeable> Writeable for Option<T> {
603609
impl<T: Readable> Readable for Option<T>
604610
{
605611
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
606-
match <u8 as Readable>::read(r)? {
612+
match BigSize::read(r)?.0 {
607613
0 => Ok(None),
608-
1 => Ok(Some(Readable::read(r)?)),
609-
_ => return Err(DecodeError::InvalidValue),
614+
len => {
615+
let mut reader = FixedLengthReader::new(r, len - 1);
616+
Ok(Some(Readable::read(&mut reader)?))
617+
}
610618
}
611619
}
612620
}

0 commit comments

Comments
 (0)