From 0c1f47807a772a69e2a11d0752f54291505ad002 Mon Sep 17 00:00:00 2001 From: Savil Srivastava Date: Fri, 20 Jul 2018 17:24:14 -0700 Subject: [PATCH] [msgs::ChannelReestablish] implement encoding and decoding Summary: Implementing these, taking inspiration from the surrounding code since i'm a rust n00b. Test Plan: ``` cargo build cargo test channel_reestablish ``` output: ``` running 3 tests test ln::msgs::tests::encoding_channel_reestablish_with_secret ... ok test ln::msgs::tests::decode_channel_reestablish_bad_length ... ok test ln::msgs::tests::encoding_channel_reestablish_no_secret ... ok test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 14 filtered out ``` --- fuzz/Cargo.toml | 4 + fuzz/fuzz_targets/msg_targets/gen_target.sh | 2 +- .../msg_channel_reestablish_target.rs | 48 ++++++++++ src/ln/msgs.rs | 96 ++++++++++++++++++- 4 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 077aacfaf..53724f356 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -110,3 +110,7 @@ path = "fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs" [[bin]] name = "msg_update_fail_htlc_target" path = "fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs" + +[[bin]] +name = "msg_channel_reestablish_target" +path = "fuzz_targets/msg_targets/msg_channel_reestablish_target.rs" diff --git a/fuzz/fuzz_targets/msg_targets/gen_target.sh b/fuzz/fuzz_targets/msg_targets/gen_target.sh index a74319f4f..4a5dc2fc5 100755 --- a/fuzz/fuzz_targets/msg_targets/gen_target.sh +++ b/fuzz/fuzz_targets/msg_targets/gen_target.sh @@ -1,4 +1,4 @@ -for target in CommitmentSigned FundingCreated FundingLocked FundingSigned OpenChannel RevokeAndACK Shutdown UpdateAddHTLC UpdateFailHTLC UpdateFailMalformedHTLC UpdateFee UpdateFulfillHTLC AcceptChannel ClosingSigned; do +for target in CommitmentSigned FundingCreated FundingLocked FundingSigned OpenChannel RevokeAndACK Shutdown UpdateAddHTLC UpdateFailHTLC UpdateFailMalformedHTLC UpdateFee UpdateFulfillHTLC AcceptChannel ClosingSigned ChannelReestablish; do tn=$(echo $target | sed 's/\([a-z0-9]\)\([A-Z]\)/\1_\2/g') fn=msg_$(echo $tn | tr '[:upper:]' '[:lower:]')_target.rs cat msg_target_template.txt | sed s/MSG_TARGET/$target/ > $fn diff --git a/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs b/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs new file mode 100644 index 000000000..dc9c2acd1 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs @@ -0,0 +1,48 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + test_msg!(msgs::ChannelReestablish, data); +} + +#[cfg(feature = "afl")] +extern crate afl; +#[cfg(feature = "afl")] +fn main() { + afl::read_stdio_bytes(|data| { + do_test(&data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(test)] +mod tests { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/src/ln/msgs.rs b/src/ln/msgs.rs index a36202e46..a10a50e22 100644 --- a/src/ln/msgs.rs +++ b/src/ln/msgs.rs @@ -1101,13 +1101,50 @@ impl MsgEncodable for UpdateFee { } impl MsgDecodable for ChannelReestablish { - fn decode(_v: &[u8]) -> Result { - unimplemented!(); + fn decode(v: &[u8]) -> Result { + if v.len() < 32+2*8+33 { + return Err(DecodeError::WrongLength); + } + + let your_last_per_commitment_secret = if v.len() > 32+2*8+33 { + if v.len() < 32+2*8+33 + 32 { + return Err(DecodeError::WrongLength); + } + let mut inner_array = [0; 32]; + inner_array.copy_from_slice(&v[48..48+32]); + Some(inner_array) + } else { None }; + + let option_size = match &your_last_per_commitment_secret { + &Some(ref _ary) => 32, + &None => 0, + }; + Ok(Self { + channel_id: deserialize(&v[0..32]).unwrap(), + next_local_commitment_number: byte_utils::slice_to_be64(&v[32..40]), + next_remote_commitment_number: byte_utils::slice_to_be64(&v[40..48]), + your_last_per_commitment_secret: your_last_per_commitment_secret, + my_current_per_commitment_point: { + let ctx = Secp256k1::without_caps(); + secp_pubkey!(&ctx, &v[48+option_size..48+option_size+33]) + } + }) } } impl MsgEncodable for ChannelReestablish { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(if self.your_last_per_commitment_secret.is_some() { 32+2*3+33 + 32 } else { 32+2*8+33 }); + + res.extend_from_slice(&serialize(&self.channel_id).unwrap()[..]); + res.extend_from_slice(&byte_utils::be64_to_array(self.next_local_commitment_number)); + res.extend_from_slice(&byte_utils::be64_to_array(self.next_remote_commitment_number)); + + if let &Some(ref ary) = &self.your_last_per_commitment_secret { + res.extend_from_slice(&ary[..]); + } + + res.extend_from_slice(&self.my_current_per_commitment_point.serialize()); + res } } @@ -1562,3 +1599,56 @@ impl MsgEncodable for OnionErrorPacket { res } } + +#[cfg(test)] +mod tests { + use bitcoin::util::misc::hex_bytes; + use ln::msgs::MsgEncodable; + use ln::msgs; + use secp256k1::key::{PublicKey,SecretKey}; + use secp256k1::Secp256k1; + + #[test] + fn encoding_channel_reestablish_no_secret() { + let public_key = { + let secp_ctx = Secp256k1::new(); + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()).unwrap() + }; + + let cr = msgs::ChannelReestablish { + channel_id: [4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0], + next_local_commitment_number: 3, + next_remote_commitment_number: 4, + your_last_per_commitment_secret: None, + my_current_per_commitment_point: public_key, + }; + + let encoded_value = cr.encode(); + assert_eq!( + encoded_value, + vec![4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 3, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143] + ); + } + + #[test] + fn encoding_channel_reestablish_with_secret() { + let public_key = { + let secp_ctx = Secp256k1::new(); + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()).unwrap() + }; + + let cr = msgs::ChannelReestablish { + channel_id: [4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0], + next_local_commitment_number: 3, + next_remote_commitment_number: 4, + your_last_per_commitment_secret: Some([9; 32]), + my_current_per_commitment_point: public_key, + }; + + let encoded_value = cr.encode(); + assert_eq!( + encoded_value, + vec![4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143] + ); + } +} -- 2.39.5