X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=fuzz%2Fsrc%2Ffull_stack.rs;h=10328cdce812d2992f8d53f18c1102bea7cde444;hb=65efd92c4a931b3b3622c84c6055bc015152fde0;hp=89212e5837073342a4a7f569411b07badc5fe247;hpb=3096061bef7e04444dd6c0b4f2331d06a6d8969c;p=rust-lightning diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 89212e58..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,16 +744,17 @@ 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 => { - let mut list = loss_detector.handler.get_peer_node_ids(); - list.sort_by_key(|v| v.0); - if let Some((id, _)) = list.get(0) { - loss_detector.handler.disconnect_by_node_id(*id); + let mut list = loss_detector.handler.list_peers(); + list.sort_by_key(|v| v.counterparty_node_id); + if let Some(peer_details) = list.get(0) { + loss_detector.handler.disconnect_by_node_id(peer_details.counterparty_node_id); } }, 20 => loss_detector.handler.disconnect_all_peers(), @@ -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 @@ -971,6 +998,8 @@ mod tests { // create the funding transaction (client should send funding_created now) ext_from_hex("0a", &mut test); + // Two feerate requests to check the dust exposure on the initial commitment tx + ext_from_hex("00fd00fd", &mut test); // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1019,6 +1048,9 @@ mod tests { // end of update_add_htlc from 0 to 1 via client and mac ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ab00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test); + // Two feerate requests to check dust exposure + ext_from_hex("00fd00fd", &mut test); + // inbound read from peer id 0 of len 18 ext_from_hex("030012", &mut test); // message header indicating message length 100 @@ -1040,6 +1072,8 @@ mod tests { // process the now-pending HTLC forward ext_from_hex("07", &mut test); + // Two feerate requests to check dust exposure + ext_from_hex("00fd00fd", &mut test); // client now sends id 1 update_add_htlc and commitment_signed (CHECK 7: UpdateHTLCs event for node 03020000 with 1 HTLCs for channel 3f000000) // we respond with commitment_signed then revoke_and_ack (a weird, but valid, order) @@ -1115,6 +1149,9 @@ mod tests { // end of update_add_htlc from 0 to 1 via client and mac ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ab00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test); + // Two feerate requests to check dust exposure + ext_from_hex("00fd00fd", &mut test); + // now respond to the update_fulfill_htlc+commitment_signed messages the client sent to peer 0 // inbound read from peer id 0 of len 18 ext_from_hex("030012", &mut test); @@ -1146,6 +1183,10 @@ mod tests { // process the now-pending HTLC forward ext_from_hex("07", &mut test); + + // Two feerate requests to check dust exposure + ext_from_hex("00fd00fd", &mut test); + // client now sends id 1 update_add_htlc and commitment_signed (CHECK 7 duplicate) // we respond with revoke_and_ack, then commitment_signed, then update_fail_htlc @@ -1243,6 +1284,9 @@ mod tests { // end of update_add_htlc from 0 to 1 via client and mac ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 5300000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test); + // Two feerate requests to check dust exposure + ext_from_hex("00fd00fd", &mut test); + // inbound read from peer id 0 of len 18 ext_from_hex("030012", &mut test); // message header indicating message length 164 @@ -1264,27 +1308,36 @@ mod tests { // process the now-pending HTLC forward ext_from_hex("07", &mut test); + // Two feerate requests to check dust exposure + ext_from_hex("00fd00fd", &mut test); // client now sends id 1 update_add_htlc and commitment_signed (CHECK 7 duplicate) // connect a block with one transaction of len 125 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); @@ -1330,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);