X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=fuzz%2Fsrc%2Ffull_stack.rs;h=10328cdce812d2992f8d53f18c1102bea7cde444;hb=65efd92c4a931b3b3622c84c6055bc015152fde0;hp=d07def30ff987176305faa2a76367b6b073b5fa0;hpb=33b9ba558c6b651e8d282052867e701f1543cec6;p=rust-lightning diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index d07def30..10328cdc 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -13,19 +13,22 @@ //! or payments to send/ways to handle events generated. //! This test has been very useful, though due to its complexity good starting inputs are critical. +use bitcoin::amount::Amount; use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::blockdata::script::{Builder, ScriptBuf}; use bitcoin::blockdata::opcodes; use bitcoin::blockdata::locktime::absolute::LockTime; use bitcoin::consensus::encode::deserialize; -use bitcoin::network::constants::Network; +use bitcoin::network::Network; +use bitcoin::transaction::Version; +use bitcoin::WPubkeyHash; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::Hash as _; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256d::Hash as Sha256dHash; -use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash}; +use bitcoin::hash_types::{Txid, BlockHash}; use lightning::blinded_path::BlindedPath; use lightning::blinded_path::payment::ReceiveTlvs; @@ -37,7 +40,8 @@ use lightning::chain::transaction::OutPoint; use lightning::sign::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider}; use lightning::events::Event; use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; -use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentId, RecipientOnionFields, Retry, InterceptId}; +use lightning::ln::channel_state::ChannelDetails; +use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentId, RecipientOnionFields, Retry, InterceptId}; use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,IgnoringMessageHandler}; use lightning::ln::msgs::{self, DecodeError}; use lightning::ln::script::ShutdownScript; @@ -67,8 +71,8 @@ use std::cell::RefCell; use std::convert::TryInto; use std::cmp; use std::sync::{Arc, Mutex}; -use std::sync::atomic::{AtomicU64,AtomicUsize,Ordering}; -use bitcoin::bech32::u5; +use std::sync::atomic::{AtomicU64,AtomicUsize,AtomicBool,Ordering}; +use bech32::u5; #[inline] pub fn slice_to_be16(v: &[u8]) -> u16 { @@ -94,6 +98,7 @@ pub fn slice_to_be24(v: &[u8]) -> u32 { struct InputData { data: Vec, read_pos: AtomicUsize, + halt_fee_est_reads: AtomicBool, } impl InputData { fn get_slice(&self, len: usize) -> Option<&[u8]> { @@ -120,6 +125,9 @@ struct FuzzEstimator { } impl FeeEstimator for FuzzEstimator { fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u32 { + if self.input.halt_fee_est_reads.load(Ordering::Acquire) { + return 253; + } //TODO: We should actually be testing at least much more than 64k... match self.input.get_slice(2) { Some(slice) => cmp::max(slice_to_be16(slice) as u32, 253), @@ -216,6 +224,7 @@ struct MoneyLossDetector<'a> { height: usize, max_height: usize, blocks_connected: u32, + error_message: String, } impl<'a> MoneyLossDetector<'a> { pub fn new(peers: &'a RefCell<[bool; 256]>, @@ -234,6 +243,7 @@ impl<'a> MoneyLossDetector<'a> { height: 0, max_height: 0, blocks_connected: 0, + error_message: "Channel force-closed".to_string(), } } @@ -288,7 +298,7 @@ impl<'a> Drop for MoneyLossDetector<'a> { } // Force all channels onto the chain (and time out claim txn) - self.manager.force_close_all_channels_broadcasting_latest_txn(); + self.manager.force_close_all_channels_broadcasting_latest_txn(self.error_message.to_string()); } } } @@ -349,7 +359,7 @@ impl NodeSigner for KeyProvider { } fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result { - let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?; + let msg_hash = Message::from_digest(Sha256dHash::hash(&msg.encode()[..]).to_byte_array()); let secp_ctx = Secp256k1::signing_only(); Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret)) } @@ -440,6 +450,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { let input = Arc::new(InputData { data: data.to_vec(), read_pos: AtomicUsize::new(0), + halt_fee_est_reads: AtomicBool::new(false), }); let fee_est = Arc::new(FuzzEstimator { input: input.clone(), @@ -650,11 +661,11 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { } }, 10 => { - let mut tx = Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + let mut tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; let mut channels = Vec::new(); for funding_generation in pending_funding_generation.drain(..) { let txout = TxOut { - value: funding_generation.2, script_pubkey: funding_generation.3, + value: Amount::from_sat(funding_generation.2), script_pubkey: funding_generation.3, }; if !tx.output.contains(&txout) { tx.output.push(txout); @@ -664,7 +675,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { // Once we switch to V2 channel opens we should be able to drop this entirely as // channel_ids no longer change when we set the funding tx. 'search_loop: loop { - if tx.version > 0xff { + if tx.version.0 > 0xff { break; } let funding_txid = tx.txid(); @@ -672,15 +683,15 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { let outpoint = OutPoint { txid: funding_txid, index: 0 }; for chan in channelmanager.list_channels() { if chan.channel_id == ChannelId::v1_from_funding_outpoint(outpoint) { - tx.version += 1; + tx.version = Version(tx.version.0 + 1); continue 'search_loop; } } break; } - tx.version += 1; + tx.version = Version(tx.version.0 + 1); } - if tx.version <= 0xff && !channels.is_empty() { + if tx.version.0 <= 0xff && !channels.is_empty() { let chans = channels.iter().map(|(a, b)| (a, b)).collect::>(); if let Err(e) = channelmanager.batch_funding_transaction_generated(&chans, tx.clone()) { // It's possible the channel has been closed in the mean time, but any other @@ -697,10 +708,12 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { 11 => { let mut txn = broadcast.txn_broadcasted.lock().unwrap().split_off(0); if !txn.is_empty() { + input.halt_fee_est_reads.store(true, Ordering::Release); loss_detector.connect_block(&txn[..]); for _ in 2..100 { loss_detector.connect_block(&[]); } + input.halt_fee_est_reads.store(false, Ordering::Release); } for tx in txn.drain(..) { loss_detector.funding_txn.push(tx); @@ -713,11 +726,11 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { } else { let txres: Result = deserialize(get_slice!(txlen)); if let Ok(tx) = txres { - let mut output_val = 0; + let mut output_val = Amount::ZERO; for out in tx.output.iter() { - if out.value > 21_000_000_0000_0000 { return; } + if out.value > Amount::MAX_MONEY { return; } output_val += out.value; - if output_val > 21_000_000_0000_0000 { return; } + if output_val > Amount::MAX_MONEY { return; } } loss_detector.connect_block(&[tx]); } else { @@ -731,9 +744,10 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { 14 => { let mut channels = channelmanager.list_channels(); let channel_id = get_slice!(1)[0] as usize; + let error_message = "Channel force-closed"; if channel_id >= channels.len() { return; } channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) }); - channelmanager.force_close_broadcasting_latest_txn(&channels[channel_id].channel_id, &channels[channel_id].counterparty.node_id).unwrap(); + channelmanager.force_close_broadcasting_latest_txn(&channels[channel_id].channel_id, &channels[channel_id].counterparty.node_id, error_message.to_string()).unwrap(); }, // 15, 16, 17, 18 is above 19 => { @@ -856,7 +870,7 @@ mod tests { // our network key ext_from_hex("0100000000000000000000000000000000000000000000000000000000000000", &mut test); // config - ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff0001000000", &mut test); + ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff000100000000", &mut test); // new outbound connection with id 0 ext_from_hex("00", &mut test); @@ -907,19 +921,32 @@ mod tests { ext_from_hex("0c005e", &mut test); // the funding transaction ext_from_hex("020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae0000000000000000000000000000000000000000000000000000000000000000000000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // connect a block with no transactions, one per line ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // by now client should have sent a channel_ready (CHECK 3: SendChannelReady to 03000000 for chan 3d000000) // inbound read from peer id 0 of len 18 @@ -1289,21 +1316,28 @@ mod tests { ext_from_hex("0c007d", &mut test); // the commitment transaction for channel 3f00000000000000000000000000000000000000000000000000000000000000 ext_from_hex("02000000013a000000000000000000000000000000000000000000000000000000000000000000000000000000800258020000000000002200204b0000000000000000000000000000000000000000000000000000000000000014c0000000000000160014280000000000000000000000000000000000000005000020", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // // connect a block with one transaction of len 94 ext_from_hex("0c005e", &mut test); // the HTLC timeout transaction ext_from_hex("0200000001730000000000000000000000000000000000000000000000000000000000000000000000000000000001a701000000000000220020b20000000000000000000000000000000000000000000000000000000000000000000000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // connect a block with no transactions ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // connect a block with no transactions ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // connect a block with no transactions ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // connect a block with no transactions ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // connect a block with no transactions ext_from_hex("0c0000", &mut test); + ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection // process the now-pending HTLC forward ext_from_hex("07", &mut test); @@ -1349,7 +1383,7 @@ mod tests { // our network key ext_from_hex("0100000000000000000000000000000000000000000000000000000000000000", &mut test); // config - ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff0001000000", &mut test); + ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff000100000000", &mut test); // new outbound connection with id 0 ext_from_hex("00", &mut test);