Merge pull request #18 from TheBlueMatt/2018-04-fuzzing-expansion
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Mon, 2 Apr 2018 22:27:23 +0000 (18:27 -0400)
committerGitHub <noreply@github.com>
Mon, 2 Apr 2018 22:27:23 +0000 (18:27 -0400)
 Expand full_stack_target from uselessly-large to laughably-large

README.md
fuzz/Cargo.toml
fuzz/fuzz_targets/channel_target.rs
fuzz/fuzz_targets/full_stack_target.rs
fuzz/fuzz_targets/peer_crypt_target.rs
src/ln/channel.rs
src/ln/channelmanager.rs
src/ln/msgs.rs
src/ln/peer_handler.rs
src/util/mod.rs
src/util/rng.rs

index 877ccc3bcf6150d506d3146144eda78711159b54..24a76c2276dab03433a68f3d689c634d167c425f 100644 (file)
--- a/README.md
+++ b/README.md
@@ -27,17 +27,13 @@ Assorted random TODOs:
    a timer. By default we should provide an implementation of this which uses
    some newfangled rusty promise-y library, but should generally ensure a
    client can simply integrate this into whatever existing timer interface
-   they use.
-
- * Networking...having a simple bytes-in-bytes-out interface which does message
-   handling and calls our encryption layer is probably the right approach. We
-   should then also probably use the same promise-y library we use for timers
-   to do socket selection and reading/writing.
+   they use. (This is partially complete, but the events stuff needs to also
+   exist in Channel, which has a few inline TODOs to set up timers).
 
  * Figure out how to expose when-to-connect and who-to-connect-to.
 
  * Implement when-to-connect and who-to-connect-to based on route/node rumoring
-   and channelmanager state.
+   and channelmanager state (and some concept of available value in wallet).
 
  * Some kind of serialization format for on-disk storage of things like
    channels, channelmonitors, routing db, etc.
@@ -50,8 +46,6 @@ Assorted random TODOs:
 
  * All the random TODOs and unimplemented!()s across the codebase.
 
- * BOLT 11 (invoice/address creation/generation) implementation
-
  * Type-ify our somewhat random usage of Uint256/[u8; 32]. Use Sha256dHash
    where appropriate, create our own types for everything else.
 
index 7ed7533a33d0dd499a704dfd979ba6ea3d31a0a6..39f805d44ee404280547a32a3bfc12225f8f3c4f 100644 (file)
@@ -15,6 +15,7 @@ honggfuzz_fuzz = ["honggfuzz"]
 lightning = { path = "..", features = ["fuzztarget"] }
 bitcoin = { git = "https://github.com/rust-bitcoin/rust-bitcoin", features = ["fuzztarget"] }
 secp256k1 = { version = "0.9", features = ["fuzztarget"] }
+rust-crypto = "0.2"
 honggfuzz = { version = "0.5", optional = true }
 afl = { version = "0.3", optional = true }
 
index d07b342da9436116ca9f7a613104e6221f4956c1..b643996105e81cd33621405bf0a77a070214989c 100644 (file)
@@ -3,7 +3,7 @@ extern crate lightning;
 extern crate secp256k1;
 
 use bitcoin::blockdata::block::BlockHeader;
-use bitcoin::blockdata::transaction::Transaction;
+use bitcoin::blockdata::transaction::{Transaction, TxOut};
 use bitcoin::util::hash::Sha256dHash;
 use bitcoin::network::serialize::{serialize, BitcoinHash};
 
@@ -12,6 +12,7 @@ use lightning::ln::channelmanager::PendingForwardHTLCInfo;
 use lightning::ln::msgs;
 use lightning::ln::msgs::MsgDecodable;
 use lightning::chain::chaininterface::{FeeEstimator, ConfirmationTarget};
+use lightning::util::reset_rng_state;
 
 use secp256k1::key::PublicKey;
 use secp256k1::Secp256k1;
@@ -89,6 +90,8 @@ impl<'a> FeeEstimator for FuzzEstimator<'a> {
 
 #[inline]
 pub fn do_test(data: &[u8]) {
+       reset_rng_state();
+
        let input = InputData {
                data,
                read_pos: AtomicUsize::new(0),
@@ -163,11 +166,11 @@ pub fn do_test(data: &[u8]) {
 
        let their_pubkey = get_pubkey!();
 
-       let tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
-       let funding_output = (Sha256dHash::from_data(&serialize(&tx).unwrap()[..]), 0);
+       let mut tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
 
        let mut channel = if get_slice!(1)[0] != 0 {
-               let mut chan = Channel::new_outbound(&fee_est, their_pubkey, slice_to_be24(get_slice!(3)), get_slice!(1)[0] == 0, slice_to_be64(get_slice!(8)));
+               let chan_value = slice_to_be24(get_slice!(3));
+               let mut chan = Channel::new_outbound(&fee_est, their_pubkey, chan_value, get_slice!(1)[0] == 0, slice_to_be64(get_slice!(8)));
                chan.get_open_channel(Sha256dHash::from(get_slice!(32)), &fee_est).unwrap();
                let accept_chan = if get_slice!(1)[0] == 0 {
                        decode_msg_with_len16!(msgs::AcceptChannel, 270, 1)
@@ -175,6 +178,10 @@ pub fn do_test(data: &[u8]) {
                        decode_msg!(msgs::AcceptChannel, 270)
                };
                return_err!(chan.accept_channel(&accept_chan));
+
+               tx.output.push(TxOut{ value: chan_value, script_pubkey: chan.get_funding_redeemscript().to_v0_p2wsh() });
+               let funding_output = (Sha256dHash::from_data(&serialize(&tx).unwrap()[..]), 0);
+
                chan.get_outbound_funding_created(funding_output.0.clone(), funding_output.1).unwrap();
                let funding_signed = decode_msg!(msgs::FundingSigned, 32+64);
                return_err!(chan.funding_signed(&funding_signed));
@@ -190,6 +197,10 @@ pub fn do_test(data: &[u8]) {
                        Err(_) => return,
                };
                chan.get_accept_channel().unwrap();
+
+               tx.output.push(TxOut{ value: open_chan.funding_satoshis, script_pubkey: chan.get_funding_redeemscript().to_v0_p2wsh() });
+               let funding_output = (Sha256dHash::from_data(&serialize(&tx).unwrap()[..]), 0);
+
                let mut funding_created = decode_msg!(msgs::FundingCreated, 32+32+2+64);
                funding_created.funding_txid = funding_output.0.clone();
                funding_created.funding_output_index = funding_output.1;
index c7ad6d49dc11b20af90fb54876c32eec16b93088..e36f64206359e1b541a2ba5fc36e0a665acdfd4f 100644 (file)
@@ -1,20 +1,31 @@
 extern crate bitcoin;
+extern crate crypto;
 extern crate lightning;
 extern crate secp256k1;
 
-use bitcoin::blockdata::transaction::Transaction;
+use bitcoin::blockdata::block::BlockHeader;
+use bitcoin::blockdata::transaction::{Transaction, TxOut};
+use bitcoin::blockdata::script::Script;
 use bitcoin::network::constants::Network;
+use bitcoin::network::serialize::{serialize, BitcoinHash};
 use bitcoin::util::hash::Sha256dHash;
+use bitcoin::util::uint::Uint256;
 
-use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,FeeEstimator,ChainWatchInterfaceUtil};
+use crypto::sha2::Sha256;
+use crypto::digest::Digest;
+
+use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil};
 use lightning::ln::{channelmonitor,msgs};
 use lightning::ln::channelmanager::ChannelManager;
 use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
 use lightning::ln::router::Router;
+use lightning::util::events::{EventsProvider,Event};
+use lightning::util::reset_rng_state;
 
 use secp256k1::key::{PublicKey,SecretKey};
 use secp256k1::Secp256k1;
 
+use std::collections::HashMap;
 use std::sync::Arc;
 use std::sync::atomic::{AtomicUsize,Ordering};
 
@@ -24,6 +35,13 @@ pub fn slice_to_be16(v: &[u8]) -> u16 {
        ((v[1] as u16) << 8*0)
 }
 
+#[inline]
+pub fn slice_to_be24(v: &[u8]) -> u32 {
+       ((v[0] as u32) << 8*2) |
+       ((v[1] as u32) << 8*1) |
+       ((v[2] as u32) << 8*0)
+}
+
 #[inline]
 pub fn slice_to_be32(v: &[u8]) -> u32 {
        ((v[0] as u32) << 8*3) |
@@ -32,6 +50,20 @@ pub fn slice_to_be32(v: &[u8]) -> u32 {
        ((v[3] as u32) << 8*0)
 }
 
+#[inline]
+pub fn be64_to_array(u: u64) -> [u8; 8] {
+       let mut v = [0; 8];
+       v[0] = ((u >> 8*7) & 0xff) as u8;
+       v[1] = ((u >> 8*6) & 0xff) as u8;
+       v[2] = ((u >> 8*5) & 0xff) as u8;
+       v[3] = ((u >> 8*4) & 0xff) as u8;
+       v[4] = ((u >> 8*3) & 0xff) as u8;
+       v[5] = ((u >> 8*2) & 0xff) as u8;
+       v[6] = ((u >> 8*1) & 0xff) as u8;
+       v[7] = ((u >> 8*0) & 0xff) as u8;
+       v
+}
+
 struct InputData {
        data: Vec<u8>,
        read_pos: AtomicUsize,
@@ -44,13 +76,6 @@ impl InputData {
                }
                Some(&self.data[old_pos..old_pos + len])
        }
-       fn get_slice_nonadvancing(&self, len: usize) -> Option<&[u8]> {
-               let old_pos = self.read_pos.load(Ordering::Acquire);
-               if self.data.len() < old_pos + len {
-                       return None;
-               }
-               Some(&self.data[old_pos..old_pos + len])
-       }
 }
 
 struct FuzzEstimator {
@@ -92,6 +117,8 @@ impl SocketDescriptor for Peer {
 
 #[inline]
 pub fn do_test(data: &[u8]) {
+       reset_rng_state();
+
        let input = Arc::new(InputData {
                data: data.to_vec(),
                read_pos: AtomicUsize::new(0),
@@ -137,6 +164,12 @@ pub fn do_test(data: &[u8]) {
        }, our_network_key);
 
        let mut peers = [false; 256];
+       let mut should_forward = false;
+       let mut payments_received = Vec::new();
+       let mut payments_sent = 0;
+       let mut pending_funding_generation: Vec<(Uint256, u64, Script)> = Vec::new();
+       let mut pending_funding_signatures = HashMap::new();
+       let mut pending_funding_relay = Vec::new();
 
        loop {
                match get_slice!(1)[0] {
@@ -178,8 +211,122 @@ pub fn do_test(data: &[u8]) {
                                        Err(_) => { peers[peer_id as usize] = false; }
                                }
                        },
+                       4 => {
+                               let value = slice_to_be24(get_slice!(3)) as u64;
+                               let route = match router.get_route(&get_pubkey!(), &Vec::new(), value, 42) {
+                                       Ok(route) => route,
+                                       Err(_) => return,
+                               };
+                               let mut payment_hash = [0; 32];
+                               payment_hash[0..8].copy_from_slice(&be64_to_array(payments_sent));
+                               let mut sha = Sha256::new();
+                               sha.input(&payment_hash);
+                               sha.result(&mut payment_hash);
+                               for i in 1..32 { payment_hash[i] = 0; }
+                               payments_sent += 1;
+                               match channelmanager.send_payment(route, payment_hash) {
+                                       Ok(_) => {},
+                                       Err(_) => return,
+                               }
+                       },
+                       5 => {
+                               let peer_id = get_slice!(1)[0];
+                               if !peers[peer_id as usize] { return; }
+                               let their_key = get_pubkey!();
+                               let chan_value = slice_to_be24(get_slice!(3)) as u64;
+                               if channelmanager.create_channel(their_key, chan_value, 0).is_err() { return; }
+                       },
+                       6 => {
+                               let mut channels = channelmanager.list_channels();
+                               let channel_id = get_slice!(1)[0] as usize;
+                               if channel_id >= channels.len() { return; }
+                               channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) });
+                               if channelmanager.close_channel(&channels[channel_id].channel_id).is_err() { return; }
+                       },
+                       7 => {
+                               if should_forward {
+                                       channelmanager.process_pending_htlc_forward();
+                                       handler.process_events();
+                                       should_forward = false;
+                               }
+                       },
+                       8 => {
+                               for payment in payments_received.drain(..) {
+                                       let mut payment_preimage = None;
+                                       for i in 0..payments_sent {
+                                               let mut payment_hash = [0; 32];
+                                               payment_hash[0..8].copy_from_slice(&be64_to_array(i));
+                                               let mut sha = Sha256::new();
+                                               sha.input(&payment_hash);
+                                               sha.result(&mut payment_hash);
+                                               for i in 1..32 { payment_hash[i] = 0; }
+                                               if payment_hash == payment {
+                                                       payment_hash = [0; 32];
+                                                       payment_hash[0..8].copy_from_slice(&be64_to_array(i));
+                                                       payment_preimage = Some(payment_hash);
+                                                       break;
+                                               }
+                                       }
+                                       channelmanager.claim_funds(payment_preimage.unwrap());
+                               }
+                       },
+                       9 => {
+                               for payment in payments_received.drain(..) {
+                                       channelmanager.fail_htlc_backwards(&payment);
+                               }
+                       },
+                       10 => {
+                               for funding_generation in  pending_funding_generation.drain(..) {
+                                       let mut tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: vec![TxOut {
+                                                       value: funding_generation.1, script_pubkey: funding_generation.2,
+                                               }] };
+                                       let funding_output = (Sha256dHash::from_data(&serialize(&tx).unwrap()[..]), 0);
+                                       channelmanager.funding_transaction_generated(&funding_generation.0, funding_output.clone());
+                                       pending_funding_signatures.insert(funding_output, tx);
+                               }
+                       },
+                       11 => {
+                               if !pending_funding_relay.is_empty() {
+                                       let mut txn = Vec::with_capacity(pending_funding_relay.len());
+                                       let mut txn_idxs = Vec::with_capacity(pending_funding_relay.len());
+                                       for (idx, tx) in pending_funding_relay.iter().enumerate() {
+                                               txn.push(tx);
+                                               txn_idxs.push(idx as u32 + 1);
+                                       }
+
+                                       let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+                                       channelmanager.block_connected(&header, 1, &txn[..], &txn_idxs[..]);
+                                       txn.clear();
+                                       txn_idxs.clear();
+                                       for i in 2..100 {
+                                               header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+                                               channelmanager.block_connected(&header, i, &txn[..], &txn_idxs[..]);
+                                       }
+                               }
+                               pending_funding_relay.clear();
+                       },
                        _ => return,
                }
+               for event in handler.get_and_clear_pending_events() {
+                       match event {
+                               Event::FundingGenerationReady { temporary_channel_id, channel_value_satoshis, output_script, .. } => {
+                                       pending_funding_generation.push((temporary_channel_id, channel_value_satoshis, output_script));
+                               },
+                               Event::FundingBroadcastSafe { funding_txo, .. } => {
+                                       pending_funding_relay.push(pending_funding_signatures.remove(&funding_txo).unwrap());
+                               },
+                               Event::PaymentReceived { payment_hash, .. } => {
+                                       payments_received.push(payment_hash);
+                               },
+                               Event::PaymentSent {..} => {},
+                               Event::PaymentFailed {..} => {},
+
+                               Event::PendingHTLCsForwardable {..} => {
+                                       should_forward = true;
+                               },
+                               _ => panic!("Unknown event"),
+                       }
+               }
        }
 }
 
index b7287fb9be542852e3362fab44c44d110146d4b7..06d00c2ecfbe9a7abc7e7239b5d2166dc16a907e 100644 (file)
@@ -2,6 +2,7 @@ extern crate lightning;
 extern crate secp256k1;
 
 use lightning::ln::peer_channel_encryptor::PeerChannelEncryptor;
+use lightning::util::reset_rng_state;
 
 use secp256k1::key::{PublicKey,SecretKey};
 use secp256k1::Secp256k1;
@@ -14,6 +15,8 @@ fn slice_to_be16(v: &[u8]) -> u16 {
 
 #[inline]
 pub fn do_test(data: &[u8]) {
+       reset_rng_state();
+
        let mut read_pos = 0;
        macro_rules! get_slice {
                ($len: expr) => {
index c9c9e41430d014ba6d6d62ee9d21c4a1a6bde230..61fb8a3e05ed4bd794bd3848be5a3afe5204f457 100644 (file)
@@ -1639,10 +1639,16 @@ impl Channel {
                if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 {
                        for (ref tx, index_in_block) in txn_matched.iter().zip(indexes_of_txn_matched) {
                                if tx.txid() == self.channel_monitor.get_funding_txo().unwrap().0 {
-                                       self.funding_tx_confirmations = 1;
-                                       self.short_channel_id = Some(((height as u64)          << (5*8)) |
-                                                                    ((*index_in_block as u64) << (2*8)) |
-                                                                    ((self.channel_monitor.get_funding_txo().unwrap().1 as u64) << (2*8)));
+                                       let txo_idx = self.channel_monitor.get_funding_txo().unwrap().1 as usize;
+                                       if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() ||
+                                               tx.output[txo_idx].value != self.channel_value_satoshis {
+                                               self.channel_state = ChannelState::ShutdownComplete as u32;
+                                       } else {
+                                               self.funding_tx_confirmations = 1;
+                                               self.short_channel_id = Some(((height as u64)          << (5*8)) |
+                                                                            ((*index_in_block as u64) << (2*8)) |
+                                                                            ((self.channel_monitor.get_funding_txo().unwrap().1 as u64) << (2*8)));
+                                       }
                                }
                        }
                }
index ff78a27df58b3243979758af8ba8889e36b63e01..43e0d59f4faa357a5bddab02906844bb4b7f700d 100644 (file)
@@ -906,6 +906,7 @@ impl ChainListener for ChannelManager {
                                        },
                                        None => {}
                                }
+                               //TODO: Check if channel was closed (or disabled) here
                        }
                        for to_insert in short_to_ids_to_insert {
                                channel_state.short_to_id.insert(to_insert.0, to_insert.1);
@@ -1496,7 +1497,7 @@ mod tests {
        use bitcoin::util::hash::Sha256dHash;
        use bitcoin::util::uint::Uint256;
        use bitcoin::blockdata::block::BlockHeader;
-       use bitcoin::blockdata::transaction::Transaction;
+       use bitcoin::blockdata::transaction::{Transaction, TxOut};
        use bitcoin::network::constants::Network;
        use bitcoin::network::serialize::serialize;
        use bitcoin::network::serialize::BitcoinHash;
@@ -1680,16 +1681,21 @@ mod tests {
                node_a.handle_accept_channel(&node_b.get_our_node_id(), &accept_chan).unwrap();
 
                let chan_id = unsafe { CHAN_COUNT };
-               let tx = Transaction { version: chan_id as u32, lock_time: 0, input: Vec::new(), output: Vec::new() };
-               let funding_output = (Sha256dHash::from_data(&serialize(&tx).unwrap()[..]), chan_id);
+               let tx;
+               let funding_output;
 
                let events_1 = node_a.get_and_clear_pending_events();
                assert_eq!(events_1.len(), 1);
                match events_1[0] {
-                       Event::FundingGenerationReady { ref temporary_channel_id, ref channel_value_satoshis, output_script: _, user_channel_id } => {
+                       Event::FundingGenerationReady { ref temporary_channel_id, ref channel_value_satoshis, ref output_script, user_channel_id } => {
                                assert_eq!(*channel_value_satoshis, 100000);
                                assert_eq!(user_channel_id, 42);
 
+                               tx = Transaction { version: chan_id as u32, lock_time: 0, input: Vec::new(), output: vec![TxOut {
+                                       value: *channel_value_satoshis, script_pubkey: output_script.clone(),
+                               }]};
+                               funding_output = (Sha256dHash::from_data(&serialize(&tx).unwrap()[..]), 0);
+
                                node_a.funding_transaction_generated(&temporary_channel_id, funding_output.clone());
                                //TODO: Check that we got added to chan_monitor_a!
                        },
index c7310ac9d5d4a2c1e13b368c761ef8ef7204b3af..312fea206e44d5702f02e4065e7d260f034381bf 100644 (file)
@@ -2,7 +2,7 @@ use secp256k1::key::PublicKey;
 use secp256k1::{Secp256k1, Signature};
 use bitcoin::util::uint::Uint256;
 use bitcoin::util::hash::Sha256dHash;
-use bitcoin::network::serialize::deserialize;
+use bitcoin::network::serialize::{deserialize,serialize};
 use bitcoin::blockdata::script::Script;
 
 use std::error::Error;
@@ -473,7 +473,7 @@ impl MsgDecodable for LocalFeatures {
                let len = byte_utils::slice_to_be16(&v[0..2]) as usize;
                if v.len() < len + 2 { return Err(DecodeError::WrongLength); }
                let mut flags = Vec::with_capacity(len);
-               flags.extend_from_slice(&v[2..]);
+               flags.extend_from_slice(&v[2..2 + len]);
                Ok(Self {
                        flags: flags
                })
@@ -495,7 +495,7 @@ impl MsgDecodable for GlobalFeatures {
                let len = byte_utils::slice_to_be16(&v[0..2]) as usize;
                if v.len() < len + 2 { return Err(DecodeError::WrongLength); }
                let mut flags = Vec::with_capacity(len);
-               flags.extend_from_slice(&v[2..]);
+               flags.extend_from_slice(&v[2..2 + len]);
                Ok(Self {
                        flags: flags
                })
@@ -619,7 +619,29 @@ impl MsgDecodable for AcceptChannel {
 }
 impl MsgEncodable for AcceptChannel {
        fn encode(&self) -> Vec<u8> {
-               unimplemented!();
+               let mut res = match &self.shutdown_scriptpubkey {
+                       &Some(ref script) => Vec::with_capacity(270 + 2 + script.len()),
+                       &None => Vec::with_capacity(270),
+               };
+               res.extend_from_slice(&serialize(&self.temporary_channel_id).unwrap()[..]);
+               res.extend_from_slice(&byte_utils::be64_to_array(self.dust_limit_satoshis));
+               res.extend_from_slice(&byte_utils::be64_to_array(self.max_htlc_value_in_flight_msat));
+               res.extend_from_slice(&byte_utils::be64_to_array(self.channel_reserve_satoshis));
+               res.extend_from_slice(&byte_utils::be64_to_array(self.htlc_minimum_msat));
+               res.extend_from_slice(&byte_utils::be32_to_array(self.minimum_depth));
+               res.extend_from_slice(&byte_utils::be16_to_array(self.to_self_delay));
+               res.extend_from_slice(&byte_utils::be16_to_array(self.max_accepted_htlcs));
+               res.extend_from_slice(&self.funding_pubkey.serialize());
+               res.extend_from_slice(&self.revocation_basepoint.serialize());
+               res.extend_from_slice(&self.payment_basepoint.serialize());
+               res.extend_from_slice(&self.delayed_payment_basepoint.serialize());
+               res.extend_from_slice(&self.htlc_basepoint.serialize());
+               res.extend_from_slice(&self.first_per_commitment_point.serialize());
+               if let &Some(ref script) = &self.shutdown_scriptpubkey {
+                       res.extend_from_slice(&byte_utils::be16_to_array(script.len() as u16));
+                       res.extend_from_slice(&script[..]);
+               }
+               res
        }
 }
 
@@ -639,7 +661,13 @@ impl MsgDecodable for FundingCreated {
 }
 impl MsgEncodable for FundingCreated {
        fn encode(&self) -> Vec<u8> {
-               unimplemented!();
+               let mut res = Vec::with_capacity(32+32+2+64);
+               res.extend_from_slice(&serialize(&self.temporary_channel_id).unwrap()[..]);
+               res.extend_from_slice(&serialize(&self.funding_txid).unwrap()[..]);
+               res.extend_from_slice(&byte_utils::be16_to_array(self.funding_output_index));
+               let secp_ctx = Secp256k1::without_caps();
+               res.extend_from_slice(&self.signature.serialize_compact(&secp_ctx));
+               res
        }
 }
 
@@ -675,7 +703,10 @@ impl MsgDecodable for FundingLocked {
 }
 impl MsgEncodable for FundingLocked {
        fn encode(&self) -> Vec<u8> {
-               unimplemented!();
+               let mut res = Vec::with_capacity(32+33);
+               res.extend_from_slice(&serialize(&self.channel_id).unwrap());
+               res.extend_from_slice(&self.next_per_commitment_point.serialize());
+               res
        }
 }
 
@@ -893,7 +924,13 @@ impl MsgDecodable for AnnouncementSignatures {
 }
 impl MsgEncodable for AnnouncementSignatures {
        fn encode(&self) -> Vec<u8> {
-               unimplemented!();
+               let mut res = Vec::with_capacity(32+8+64*2);
+               res.extend_from_slice(&serialize(&self.channel_id).unwrap());
+               res.extend_from_slice(&byte_utils::be64_to_array(self.short_channel_id));
+               let secp_ctx = Secp256k1::without_caps();
+               res.extend_from_slice(&self.node_signature.serialize_compact(&secp_ctx));
+               res.extend_from_slice(&self.bitcoin_signature.serialize_compact(&secp_ctx));
+               res
        }
 }
 
index a6992eae4ff1fcf62dab20875407e2741dcebec5..173467dfce88bac83f6bb1593bc85fd62ccd39b3 100644 (file)
@@ -279,6 +279,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                        let act_three = try_potential_handleerror!(peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..], &self.our_node_secret)).to_vec();
                                                                        peer.pending_outbound_buffer.push_back(act_three);
                                                                        peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes
+                                                                       peer.pending_read_is_header = true;
 
                                                                        insert_node_id = Some(peer.their_node_id.unwrap());
                                                                        encode_and_send_msg!(msgs::Init {
@@ -317,7 +318,9 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                                                if msg.local_features.requires_unknown_bits() {
                                                                                                        return Err(PeerHandleError{});
                                                                                                }
-                                                                                               //TODO: Store features!
+                                                                                               //TODO: Store features (and check that we've
+                                                                                               //received Init prior to any other messages)!
+                                                                                               //TODO: Respond to Init with Init if we're inbound.
                                                                                        },
                                                                                        17 => {
                                                                                                // Error msg
index b7578bce407caca84ef77d675edcb4ac8135208e..a39d288488d0a18e984296e106e358dedbab82cf 100644 (file)
@@ -7,5 +7,8 @@ pub(crate) mod internal_traits;
 pub(crate) mod rng;
 pub(crate) mod sha2;
 
+#[cfg(feature = "fuzztarget")]
+pub use self::rng::reset_rng_state;
+
 #[cfg(test)]
 pub(crate) mod test_utils;
index f0d4492521b82d090c33c3f570dff9472e6c767d..818528b8e13e9f35c333c18769ea12dce4543b93 100644 (file)
@@ -24,19 +24,32 @@ pub use self::real_rng::*;
 #[cfg(feature = "fuzztarget")]
 mod fuzzy_rng {
        use bitcoin::util::uint::Uint256;
+       use util::byte_utils;
+
+       static mut RNG_ITER: u64 = 0;
 
        pub fn fill_bytes(data: &mut [u8]) {
-               for i in 0..data.len() {
-                       data[i] = 0x42;
+               let rng = unsafe { RNG_ITER += 1; RNG_ITER -1 };
+               for i in 0..data.len() / 8 {
+                       data[i*8..(i+1)*8].copy_from_slice(&byte_utils::be64_to_array(rng));
                }
+               let rem = data.len() % 8;
+               let off = data.len() - rem;
+               data[off..].copy_from_slice(&byte_utils::be64_to_array(rng)[0..rem]);
        }
 
        pub fn rand_uint256() -> Uint256 {
-               Uint256([0xdeadbeef, 0x1badcafe, 0xbadbeef, 0xdeadcafe])
+               let rng = unsafe { RNG_ITER += 1; RNG_ITER - 1 };
+               Uint256([rng, rng, rng, rng])
        }
 
        pub fn rand_f32() -> f32 {
-               0.42
+               let rng = unsafe { RNG_ITER += 1; RNG_ITER - 1 };
+               f64::from_bits(rng) as f32
+       }
+
+       pub fn reset_rng_state() {
+               unsafe { RNG_ITER = 0; }
        }
 }
 #[cfg(feature = "fuzztarget")]