X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannelmanager.rs;h=8eb91ea5dc6e28b469dfb7967d84b450ff38fbeb;hb=af5c6e8186d1e8297f4a828901fae589d5cfcc76;hp=f4f9ef881bd0164edcf87454905644df723b93b8;hpb=456323886b9f5b67af3b07d9b3094cdc6d29d1cb;p=rust-lightning diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index f4f9ef88..8eb91ea5 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -4,7 +4,6 @@ use bitcoin::blockdata::constants::genesis_block; use bitcoin::network::constants::Network; use bitcoin::network::serialize::BitcoinHash; use bitcoin::util::hash::Sha256dHash; -use bitcoin::util::uint::Uint256; use secp256k1::key::{SecretKey,PublicKey}; use secp256k1::{Secp256k1,Message}; @@ -28,10 +27,11 @@ use crypto::digest::Digest; use crypto::symmetriccipher::SynchronousStreamCipher; use crypto::chacha20::ChaCha20; -use std::sync::{Mutex,MutexGuard,Arc}; +use std::{ptr, mem}; use std::collections::HashMap; use std::collections::hash_map; -use std::{ptr, mem}; +use std::sync::{Mutex,MutexGuard,Arc}; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{Instant,Duration}; mod channel_held_info { @@ -111,16 +111,16 @@ enum PendingOutboundHTLC { const MIN_HTLC_RELAY_HOLDING_CELL_MILLIS: u32 = 50; struct ChannelHolder { - by_id: HashMap, - short_to_id: HashMap, + by_id: HashMap<[u8; 32], Channel>, + short_to_id: HashMap, next_forward: Instant, /// short channel id -> forward infos. Key of 0 means payments received forward_htlcs: HashMap>, claimable_htlcs: HashMap<[u8; 32], PendingOutboundHTLC>, } struct MutChannelHolder<'a> { - by_id: &'a mut HashMap, - short_to_id: &'a mut HashMap, + by_id: &'a mut HashMap<[u8; 32], Channel>, + short_to_id: &'a mut HashMap, next_forward: &'a mut Instant, /// short channel id -> forward infos. Key of 0 means payments received forward_htlcs: &'a mut HashMap>, @@ -152,6 +152,7 @@ pub struct ChannelManager { announce_channels_publicly: bool, fee_proportional_millionths: u32, + latest_block_height: AtomicUsize, //TODO: Compile-time assert this is at least 32-bits long secp_ctx: Secp256k1, channel_state: Mutex, @@ -187,7 +188,7 @@ pub struct ChannelDetails { /// thereafter this is the txid of the funding transaction xor the funding transaction output). /// Note that this means this value is *not* persistent - it can change once during the /// lifetime of the channel. - pub channel_id: Uint256, + pub channel_id: [u8; 32], /// The position of the funding transaction in the chain. None if the funding transaction has /// not yet been confirmed and the channel fully opened. pub short_channel_id: Option, @@ -215,6 +216,7 @@ impl ChannelManager { announce_channels_publicly, fee_proportional_millionths, + latest_block_height: AtomicUsize::new(0), //TODO: Get an init value (generally need to replay recent chain on chain_monitor registration) secp_ctx, channel_state: Mutex::new(ChannelHolder{ @@ -294,11 +296,31 @@ impl ChannelManager { res } + /// Gets the list of usable channels, in random order. Useful as an argument to + /// Router::get_route to ensure non-announced channels are used. + pub fn list_usable_channels(&self) -> Vec { + let channel_state = self.channel_state.lock().unwrap(); + let mut res = Vec::with_capacity(channel_state.by_id.len()); + for (channel_id, channel) in channel_state.by_id.iter() { + if channel.is_usable() { + res.push(ChannelDetails { + channel_id: (*channel_id).clone(), + short_channel_id: channel.get_short_channel_id(), + remote_network_id: channel.get_their_node_id(), + channel_value_satoshis: channel.get_value_satoshis(), + user_id: channel.get_user_id(), + }); + } + } + res + } + /// Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs /// will be accepted on the given channel, and after additional timeout/the closing of all /// pending HTLCs, the channel will be closed on chain. - pub fn close_channel(&self, channel_id: &Uint256) -> Result { - let (res, chan_option) = { + /// May generate a SendShutdown event on success, which should be relayed. + pub fn close_channel(&self, channel_id: &[u8; 32]) -> Result<(), HandleError> { + let (res, node_id, chan_option) = { let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = channel_state_lock.borrow_parts(); match channel_state.by_id.entry(channel_id.clone()) { @@ -308,8 +330,8 @@ impl ChannelManager { if let Some(short_id) = chan_entry.get().get_short_channel_id() { channel_state.short_to_id.remove(&short_id); } - (res, Some(chan_entry.remove_entry().1)) - } else { (res, None) } + (res, chan_entry.get().get_their_node_id(), Some(chan_entry.remove_entry().1)) + } else { (res, chan_entry.get().get_their_node_id(), None) } }, hash_map::Entry::Vacant(_) => return Err(HandleError{err: "No such channel", action: None}) } @@ -318,15 +340,24 @@ impl ChannelManager { // unknown_next_peer...I dunno who that is anymore.... self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &payment_hash, HTLCFailReason::Reason { failure_code: 0x4000 | 10, data: Vec::new() }); } - if let Some(chan) = chan_option { + let chan_update = if let Some(chan) = chan_option { if let Ok(update) = self.get_channel_update(&chan) { - let mut events = self.pending_events.lock().unwrap(); - events.push(events::Event::BroadcastChannelUpdate { - msg: update - }); - } + Some(update) + } else { None } + } else { None }; + + let mut events = self.pending_events.lock().unwrap(); + if let Some(update) = chan_update { + events.push(events::Event::BroadcastChannelUpdate { + msg: update + }); } - Ok(res.0) + events.push(events::Event::SendShutdown { + node_id, + msg: res.0 + }); + + Ok(()) } #[inline] @@ -418,9 +449,9 @@ impl ChannelManager { } /// returns the hop data, as well as the first-hop value_msat and CLTV value we should send. - fn build_onion_payloads(route: &Route) -> Result<(Vec, u64, u32), HandleError> { + fn build_onion_payloads(route: &Route, starting_htlc_offset: u32) -> Result<(Vec, u64, u32), HandleError> { let mut cur_value_msat = 0u64; - let mut cur_cltv = 0u32; + let mut cur_cltv = starting_htlc_offset; let mut last_short_channel_id = 0; let mut res: Vec = Vec::with_capacity(route.hops.len()); internal_traits::test_no_dealloc::(None); @@ -431,7 +462,7 @@ impl ChannelManager { // exactly as it should be (and the next hop isn't trying to probe to find out if we're // the intended recipient). let value_msat = if cur_value_msat == 0 { hop.fee_msat } else { cur_value_msat }; - let cltv = if cur_cltv == 0 { hop.cltv_expiry_delta } else { cur_cltv }; + let cltv = if cur_cltv == starting_htlc_offset { hop.cltv_expiry_delta + starting_htlc_offset } else { cur_cltv }; res[idx] = msgs::OnionHopData { realm: 0, data: msgs::OnionRealm0HopData { @@ -474,7 +505,7 @@ impl ChannelManager { } const ZERO:[u8; 21*65] = [0; 21*65]; - fn construct_onion_packet(mut payloads: Vec, onion_keys: Vec, associated_data: Vec) -> Result { + fn construct_onion_packet(mut payloads: Vec, onion_keys: Vec, associated_data: &[u8; 32]) -> Result { let mut buf = Vec::with_capacity(21*65); buf.resize(21*65, 0); @@ -624,11 +655,11 @@ impl ChannelManager { session_key })); - let associated_data = Vec::new(); //TODO: What to put here? + let cur_height = self.latest_block_height.load(Ordering::Acquire) as u32 + 1; let onion_keys = ChannelManager::construct_onion_keys(&self.secp_ctx, &route, &session_priv)?; - let (onion_payloads, htlc_msat, htlc_cltv) = ChannelManager::build_onion_payloads(&route)?; - let onion_packet = ChannelManager::construct_onion_packet(onion_payloads, onion_keys, associated_data)?; + let (onion_payloads, htlc_msat, htlc_cltv) = ChannelManager::build_onion_payloads(&route, cur_height)?; + let onion_packet = ChannelManager::construct_onion_packet(onion_payloads, onion_keys, &payment_hash)?; let (first_hop_node_id, (update_add, commitment_signed, chan_monitor)) = { let mut channel_state = self.channel_state.lock().unwrap(); @@ -676,19 +707,33 @@ impl ChannelManager { /// Call this upon creation of a funding transaction for the given channel. /// Panics if a funding transaction has already been provided for this channel. - pub fn funding_transaction_generated(&self, temporary_channel_id: &Uint256, funding_txo: OutPoint) { + pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint) { + macro_rules! add_pending_event { + ($event: expr) => { + { + let mut pending_events = self.pending_events.lock().unwrap(); + pending_events.push($event); + } + } + } + let (chan, msg, chan_monitor) = { let mut channel_state = self.channel_state.lock().unwrap(); - match channel_state.by_id.remove(&temporary_channel_id) { + match channel_state.by_id.remove(temporary_channel_id) { Some(mut chan) => { match chan.get_outbound_funding_created(funding_txo) { Ok(funding_msg) => { (chan, funding_msg.0, funding_msg.1) }, - Err(_e) => { - //TODO: Push e to pendingevents + Err(e) => { + mem::drop(channel_state); + add_pending_event!(events::Event::DisconnectPeer { + node_id: chan.get_their_node_id(), + msg: if let Some(msgs::ErrorAction::DisconnectPeer { msg } ) = e.action { msg } else { None }, + }); + return; - } + }, } }, None => return @@ -697,13 +742,10 @@ impl ChannelManager { if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { unimplemented!(); // maybe remove from claimable_htlcs? } - { - let mut pending_events = self.pending_events.lock().unwrap(); - pending_events.push(events::Event::SendFundingCreated { - node_id: chan.get_their_node_id(), - msg: msg, - }); - } + add_pending_event!(events::Event::SendFundingCreated { + node_id: chan.get_their_node_id(), + msg: msg, + }); let mut channel_state = self.channel_state.lock().unwrap(); channel_state.by_id.insert(chan.channel_id(), chan); @@ -724,7 +766,10 @@ impl ChannelManager { })) } - pub fn process_pending_htlc_forward(&self) { + /// Processes HTLCs which are pending waiting on random forward delay. + /// Should only really ever be called in response to an PendingHTLCsForwardable event. + /// Will likely generate further events. + pub fn process_pending_htlc_forwards(&self) { let mut new_events = Vec::new(); let mut failed_forwards = Vec::new(); { @@ -1083,6 +1128,7 @@ impl ChainListener for ChannelManager { for funding_locked in new_events.drain(..) { pending_events.push(funding_locked); } + self.latest_block_height.store(height as usize, Ordering::Release); } /// We force-close the channel without letting our counterparty participate in the shutdown @@ -1104,6 +1150,7 @@ impl ChainListener for ChannelManager { true } }); + self.latest_block_height.fetch_sub(1, Ordering::AcqRel); } } @@ -1329,8 +1376,6 @@ impl ChannelMessageHandler for ChannelManager { let shared_secret = SharedSecret::new(&self.secp_ctx, &msg.onion_routing_packet.public_key, &self.our_network_key); let (rho, mu) = ChannelManager::gen_rho_mu_from_shared_secret(&shared_secret); - let associated_data = Vec::new(); //TODO: What to put here? - macro_rules! get_onion_hash { () => { { @@ -1370,7 +1415,7 @@ impl ChannelMessageHandler for ChannelManager { let mut hmac = Hmac::new(Sha256::new(), &mu); hmac.input(&msg.onion_routing_packet.hop_data); - hmac.input(&associated_data[..]); + hmac.input(&msg.payment_hash); if hmac.result() != MacResult::new(&msg.onion_routing_packet.hmac) { return_err!("HMAC Check failed", 0x8000 | 0x4000 | 5, &get_onion_hash!()); } @@ -1391,6 +1436,8 @@ impl ChannelMessageHandler for ChannelManager { } }; + //TODO: Check that msg.cltv_expiry is within acceptable bounds! + let mut pending_forward_info = if next_hop_data.hmac == [0; 32] { // OUR PAYMENT! if next_hop_data.data.amt_to_forward != msg.amount_msat { @@ -1838,7 +1885,6 @@ mod tests { use bitcoin::util::misc::hex_bytes; use bitcoin::util::hash::Sha256dHash; - use bitcoin::util::uint::Uint256; use bitcoin::blockdata::block::{Block, BlockHeader}; use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::network::constants::Network; @@ -1979,7 +2025,7 @@ mod tests { }, ); - let packet = ChannelManager::construct_onion_packet(payloads, onion_keys, hex_bytes("4242424242424242424242424242424242424242424242424242424242424242").unwrap()).unwrap(); + let packet = ChannelManager::construct_onion_packet(payloads, onion_keys, &[0x42; 32]).unwrap(); // Just check the final packet encoding, as it includes all the per-hop vectors in it // anyway... assert_eq!(packet.encode(), hex_bytes("0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619e5f14350c2a76fc232b5e46d421e9615471ab9e0bc887beff8c95fdb878f7b3a716a996c7845c93d90e4ecbb9bde4ece2f69425c99e4bc820e44485455f135edc0d10f7d61ab590531cf08000179a333a347f8b4072f216400406bdf3bf038659793d4a1fd7b246979e3150a0a4cb052c9ec69acf0f48c3d39cd55675fe717cb7d80ce721caad69320c3a469a202f1e468c67eaf7a7cd8226d0fd32f7b48084dca885d56047694762b67021713ca673929c163ec36e04e40ca8e1c6d17569419d3039d9a1ec866abe044a9ad635778b961fc0776dc832b3a451bd5d35072d2269cf9b040f6b7a7dad84fb114ed413b1426cb96ceaf83825665ed5a1d002c1687f92465b49ed4c7f0218ff8c6c7dd7221d589c65b3b9aaa71a41484b122846c7c7b57e02e679ea8469b70e14fe4f70fee4d87b910cf144be6fe48eef24da475c0b0bcc6565ae82cd3f4e3b24c76eaa5616c6111343306ab35c1fe5ca4a77c0e314ed7dba39d6f1e0de791719c241a939cc493bea2bae1c1e932679ea94d29084278513c77b899cc98059d06a27d171b0dbdf6bee13ddc4fc17a0c4d2827d488436b57baa167544138ca2e64a11b43ac8a06cd0c2fba2d4d900ed2d9205305e2d7383cc98dacb078133de5f6fb6bed2ef26ba92cea28aafc3b9948dd9ae5559e8bd6920b8cea462aa445ca6a95e0e7ba52961b181c79e73bd581821df2b10173727a810c92b83b5ba4a0403eb710d2ca10689a35bec6c3a708e9e92f7d78ff3c5d9989574b00c6736f84c199256e76e19e78f0c98a9d580b4a658c84fc8f2096c2fbea8f5f8c59d0fdacb3be2802ef802abbecb3aba4acaac69a0e965abd8981e9896b1f6ef9d60f7a164b371af869fd0e48073742825e9434fc54da837e120266d53302954843538ea7c6c3dbfb4ff3b2fdbe244437f2a153ccf7bdb4c92aa08102d4f3cff2ae5ef86fab4653595e6a5837fa2f3e29f27a9cde5966843fb847a4a61f1e76c281fe8bb2b0a181d096100db5a1a5ce7a910238251a43ca556712eaadea167fb4d7d75825e440f3ecd782036d7574df8bceacb397abefc5f5254d2722215c53ff54af8299aaaad642c6d72a14d27882d9bbd539e1cc7a527526ba89b8c037ad09120e98ab042d3e8652b31ae0e478516bfaf88efca9f3676ffe99d2819dcaeb7610a626695f53117665d267d3f7abebd6bbd6733f645c72c389f03855bdf1e4b8075b516569b118233a0f0971d24b83113c0b096f5216a207ca99a7cddc81c130923fe3d91e7508c9ac5f2e914ff5dccab9e558566fa14efb34ac98d878580814b94b73acbfde9072f30b881f7f0fff42d4045d1ace6322d86a97d164aa84d93a60498065cc7c20e636f5862dc81531a88c60305a2e59a985be327a6902e4bed986dbf4a0b50c217af0ea7fdf9ab37f9ea1a1aaa72f54cf40154ea9b269f1a7c09f9f43245109431a175d50e2db0132337baa0ef97eed0fcf20489da36b79a1172faccc2f7ded7c60e00694282d93359c4682135642bc81f433574aa8ef0c97b4ade7ca372c5ffc23c7eddd839bab4e0f14d6df15c9dbeab176bec8b5701cf054eb3072f6dadc98f88819042bf10c407516ee58bce33fbe3b3d86a54255e577db4598e30a135361528c101683a5fcde7e8ba53f3456254be8f45fe3a56120ae96ea3773631fcb3873aa3abd91bcff00bd38bd43697a2e789e00da6077482e7b1b1a677b5afae4c54e6cbdf7377b694eb7d7a5b913476a5be923322d3de06060fd5e819635232a2cf4f0731da13b8546d1d6d4f8d75b9fce6c2341a71b0ea6f780df54bfdb0dd5cd9855179f602f9172307c7268724c3618e6817abd793adc214a0dc0bc616816632f27ea336fb56dfd").unwrap()); @@ -2030,7 +2076,7 @@ mod tests { } static mut CHAN_COUNT: u32 = 0; - fn create_chan_between_nodes(node_a: &Node, node_b: &Node) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, Uint256, Transaction) { + fn create_chan_between_nodes(node_a: &Node, node_b: &Node) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) { node_a.node.create_channel(node_b.node.get_our_node_id(), 100000, 42).unwrap(); let events_1 = node_a.node.get_and_clear_pending_events(); @@ -2158,7 +2204,7 @@ mod tests { ((*announcement).clone(), (*as_update).clone(), (*bs_update).clone(), channel_id, tx) } - fn create_announced_chan_between_nodes(nodes: &Vec, a: usize, b: usize) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, Uint256, Transaction) { + fn create_announced_chan_between_nodes(nodes: &Vec, a: usize, b: usize) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) { let chan_announcement = create_chan_between_nodes(&nodes[a], &nodes[b]); for node in nodes { assert!(node.router.handle_channel_announcement(&chan_announcement.0).unwrap()); @@ -2168,12 +2214,22 @@ mod tests { (chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4) } - fn close_channel(outbound_node: &Node, inbound_node: &Node, channel_id: &Uint256, funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate) { + fn close_channel(outbound_node: &Node, inbound_node: &Node, channel_id: &[u8; 32], funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate) { let (node_a, broadcaster_a) = if close_inbound_first { (&inbound_node.node, &inbound_node.tx_broadcaster) } else { (&outbound_node.node, &outbound_node.tx_broadcaster) }; let (node_b, broadcaster_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster) } else { (&inbound_node.node, &inbound_node.tx_broadcaster) }; let (tx_a, tx_b); - let shutdown_a = node_a.close_channel(channel_id).unwrap(); + node_a.close_channel(channel_id).unwrap(); + let events_1 = node_a.get_and_clear_pending_events(); + assert_eq!(events_1.len(), 1); + let shutdown_a = match events_1[0] { + Event::SendShutdown { ref node_id, ref msg } => { + assert_eq!(node_id, &node_b.get_our_node_id()); + msg.clone() + }, + _ => panic!("Unexpected event"), + }; + let (shutdown_b, mut closing_signed_b) = node_b.handle_shutdown(&node_a.get_our_node_id(), &shutdown_a).unwrap(); if !close_inbound_first { assert!(closing_signed_b.is_none()); @@ -2205,18 +2261,18 @@ mod tests { funding_tx_map.insert(funding_tx.txid(), funding_tx); tx_a.verify(&funding_tx_map).unwrap(); - let events_1 = node_a.get_and_clear_pending_events(); - assert_eq!(events_1.len(), 1); - let as_update = match events_1[0] { + let events_2 = node_a.get_and_clear_pending_events(); + assert_eq!(events_2.len(), 1); + let as_update = match events_2[0] { Event::BroadcastChannelUpdate { ref msg } => { msg.clone() }, _ => panic!("Unexpected event"), }; - let events_2 = node_b.get_and_clear_pending_events(); - assert_eq!(events_2.len(), 1); - let bs_update = match events_2[0] { + let events_3 = node_b.get_and_clear_pending_events(); + assert_eq!(events_3.len(), 1); + let bs_update = match events_3[0] { Event::BroadcastChannelUpdate { ref msg } => { msg.clone() }, @@ -2306,7 +2362,7 @@ mod tests { }; node.node.channel_state.lock().unwrap().next_forward = Instant::now(); - node.node.process_pending_htlc_forward(); + node.node.process_pending_htlc_forwards(); let mut events_2 = node.node.get_and_clear_pending_events(); assert_eq!(events_2.len(), 1); @@ -2418,7 +2474,7 @@ mod tests { const TEST_FINAL_CLTV: u32 = 32; fn route_payment(origin_node: &Node, expected_route: &[&Node], recv_value: u64) -> ([u8; 32], [u8; 32]) { - let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), &Vec::new(), recv_value, TEST_FINAL_CLTV).unwrap(); + let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), None, &Vec::new(), recv_value, TEST_FINAL_CLTV).unwrap(); assert_eq!(route.hops.len(), expected_route.len()); for (node, hop) in expected_route.iter().zip(route.hops.iter()) { assert_eq!(hop.pubkey, node.node.get_our_node_id()); @@ -2428,7 +2484,7 @@ mod tests { } fn route_over_limit(origin_node: &Node, expected_route: &[&Node], recv_value: u64) { - let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), &Vec::new(), recv_value, TEST_FINAL_CLTV).unwrap(); + let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), None, &Vec::new(), recv_value, TEST_FINAL_CLTV).unwrap(); assert_eq!(route.hops.len(), expected_route.len()); for (node, hop) in expected_route.iter().zip(route.hops.iter()) { assert_eq!(hop.pubkey, node.node.get_our_node_id()); @@ -2542,7 +2598,7 @@ mod tests { let secp_ctx = Secp256k1::new(); for _ in 0..node_count { - let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_vbyte: 1 }); + let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }); let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new()); let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())}); let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone())); @@ -2679,7 +2735,7 @@ mod tests { #[derive(PartialEq)] enum HTLCType { NONE, TIMEOUT, SUCCESS } - fn test_txn_broadcast(node: &Node, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, Uint256, Transaction), commitment_tx: Option, has_htlc_tx: HTLCType) -> Vec { + fn test_txn_broadcast(node: &Node, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction), commitment_tx: Option, has_htlc_tx: HTLCType) -> Vec { let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap(); assert!(node_txn.len() >= if commitment_tx.is_some() { 0 } else { 1 } + if has_htlc_tx == HTLCType::NONE { 0 } else { 1 }); @@ -2863,7 +2919,7 @@ mod tests { { let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[3].chain_monitor.block_connected_checked(&header, 1, &Vec::new()[..], &[0; 0]); - for i in 2..TEST_FINAL_CLTV - 5 { + for i in 2..TEST_FINAL_CLTV - 3 { header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[3].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]); } @@ -2875,7 +2931,7 @@ mod tests { header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[4].chain_monitor.block_connected_checked(&header, 1, &Vec::new()[..], &[0; 0]); - for i in 2..TEST_FINAL_CLTV - 5 { + for i in 2..TEST_FINAL_CLTV - 3 { header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[4].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]); }