X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannelmanager.rs;h=ddd6b2f214afbf54910e7a6ba38a2de383484e17;hb=dfbcacfe0ef446234d0d40400fc818908311da7b;hp=a650c89bb44668149cb305a4c0f4b35d307ad279;hpb=3c44d6beca2d5c3c50a8454d072ef54f735d5000;p=rust-lightning diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index a650c89b..ddd6b2f2 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -12,8 +12,7 @@ use bitcoin::blockdata::block::BlockHeader; use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::constants::genesis_block; use bitcoin::network::constants::Network; -use bitcoin::network::serialize::BitcoinHash; -use bitcoin::util::hash::Sha256dHash; +use bitcoin::util::hash::{BitcoinHash, Sha256dHash}; use secp256k1::key::{SecretKey,PublicKey}; use secp256k1::{Secp256k1,Message}; @@ -405,6 +404,38 @@ pub struct ChannelDetails { pub user_id: u64, } +macro_rules! handle_error { + ($self: ident, $internal: expr, $their_node_id: expr) => { + match $internal { + Ok(msg) => Ok(msg), + Err(MsgHandleErrInternal { err, needs_channel_force_close }) => { + if needs_channel_force_close { + match &err.action { + &Some(msgs::ErrorAction::DisconnectPeer { msg: Some(ref msg) }) => { + if msg.channel_id == [0; 32] { + $self.peer_disconnected(&$their_node_id, true); + } else { + $self.force_close_channel(&msg.channel_id); + } + }, + &Some(msgs::ErrorAction::DisconnectPeer { msg: None }) => {}, + &Some(msgs::ErrorAction::IgnoreError) => {}, + &Some(msgs::ErrorAction::SendErrorMessage { ref msg }) => { + if msg.channel_id == [0; 32] { + $self.peer_disconnected(&$their_node_id, true); + } else { + $self.force_close_channel(&msg.channel_id); + } + }, + &None => {}, + } + } + Err(err) + }, + } + } +} + impl ChannelManager { /// Constructs a new ChannelManager to hold several channels and route between them. /// @@ -1204,7 +1235,17 @@ impl ChannelManager { route: route.clone(), session_priv: session_priv.clone(), first_hop_htlc_msat: htlc_msat, - }, onion_packet).map_err(|he| APIError::ChannelUnavailable{err: he.err})? + }, onion_packet).map_err(|he| + match he { + ChannelError::Close(err) => { + // TODO: We need to close the channel here, but for that to be safe we have + // to do all channel closure inside the channel_state lock which is a + // somewhat-larger refactor, so we leave that for later. + APIError::ChannelUnavailable { err } + }, + ChannelError::Ignore(err) => APIError::ChannelUnavailable { err }, + } + )? }; match res { Some((update_add, commitment_signed, chan_monitor)) => { @@ -1244,24 +1285,30 @@ impl ChannelManager { let _ = self.total_consistency_lock.read().unwrap(); let (chan, msg, chan_monitor) = { - let mut channel_state = self.channel_state.lock().unwrap(); - 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) => { - log_error!(self, "Got bad signatures: {}!", e.err); - channel_state.pending_msg_events.push(events::MessageSendEvent::HandleError { - node_id: chan.get_their_node_id(), - action: e.action, - }); - return; - }, - } + let (res, chan) = { + let mut channel_state = self.channel_state.lock().unwrap(); + match channel_state.by_id.remove(temporary_channel_id) { + Some(mut chan) => { + (chan.get_outbound_funding_created(funding_txo) + .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, chan.channel_id())) + , chan) + }, + None => return + } + }; + match handle_error!(self, res, chan.get_their_node_id()) { + Ok(funding_msg) => { + (chan, funding_msg.0, funding_msg.1) + }, + Err(e) => { + log_error!(self, "Got bad signatures: {}!", e.err); + let mut channel_state = self.channel_state.lock().unwrap(); + channel_state.pending_msg_events.push(events::MessageSendEvent::HandleError { + node_id: chan.get_their_node_id(), + action: e.action, + }); + return; }, - None => return } }; // Because we have exclusive ownership of the channel here we can release the channel_state @@ -1373,9 +1420,7 @@ impl ChannelManager { let (commitment_msg, monitor) = match forward_chan.send_commitment() { Ok(res) => res, Err(e) => { - if let &Some(msgs::ErrorAction::DisconnectPeer{msg: Some(ref _err_msg)}) = &e.action { - } else if let &Some(msgs::ErrorAction::SendErrorMessage{msg: ref _err_msg}) = &e.action { - } else { + if let ChannelError::Ignore(_) = e { panic!("Stated return value requirements in send_commitment() were not met"); } //TODO: Handle...this is bad! @@ -1746,7 +1791,7 @@ impl ChannelManager { (chan.remove(), funding_msg, monitor_update) }, Err(e) => { - return Err(e).map_err(|e| MsgHandleErrInternal::from_maybe_close(e)) + return Err(e).map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.temporary_channel_id)) } } }, @@ -1784,7 +1829,7 @@ impl ChannelManager { //TODO: here and below MsgHandleErrInternal, #153 case return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id)); } - let chan_monitor = chan.funding_signed(&msg).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?; + let chan_monitor = chan.funding_signed(&msg).map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?; if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { unimplemented!(); } @@ -1943,10 +1988,20 @@ impl ChannelManager { // but if we've sent a shutdown and they haven't acknowledged it yet, we just // want to reject the new HTLC and fail it backwards instead of forwarding. if let PendingHTLCStatus::Forward(PendingForwardHTLCInfo { incoming_shared_secret, .. }) = pending_forward_info { + let chan_update = self.get_channel_update(chan); pending_forward_info = PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { channel_id: msg.channel_id, htlc_id: msg.htlc_id, - reason: ChannelManager::build_first_hop_failure_packet(&incoming_shared_secret, 0x1000|20, &self.get_channel_update(chan).unwrap().encode_with_len()[..]), + reason: if let Ok(update) = chan_update { + ChannelManager::build_first_hop_failure_packet(&incoming_shared_secret, 0x1000|20, &update.encode_with_len()[..]) + } else { + // This can only happen if the channel isn't in the fully-funded + // state yet, implying our counterparty is trying to route payments + // over the channel back to themselves (cause no one else should + // know the short_id is a lightning channel yet). We should have no + // problem just calling this unknown_next_peer + ChannelManager::build_first_hop_failure_packet(&incoming_shared_secret, 0x4000|10, &[]) + }, })); } } @@ -2214,7 +2269,8 @@ impl ChannelManager { //TODO: here and below MsgHandleErrInternal, #153 case return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id)); } - let (revoke_and_ack, commitment_signed, closing_signed, chan_monitor) = chan.commitment_signed(&msg, &*self.fee_estimator).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?; + let (revoke_and_ack, commitment_signed, closing_signed, chan_monitor) = chan.commitment_signed(&msg, &*self.fee_estimator) + .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?; if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { unimplemented!(); } @@ -2290,7 +2346,8 @@ impl ChannelManager { //TODO: here and below MsgHandleErrInternal, #153 case return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id)); } - let (commitment_update, pending_forwards, pending_failures, closing_signed, chan_monitor) = chan.revoke_and_ack(&msg, &*self.fee_estimator).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?; + let (commitment_update, pending_forwards, pending_failures, closing_signed, chan_monitor) = chan.revoke_and_ack(&msg, &*self.fee_estimator) + .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?; if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { unimplemented!(); } @@ -2456,7 +2513,16 @@ impl ChannelManager { if !chan.is_live() { return Err(APIError::ChannelUnavailable{err: "Channel is either not yet fully established or peer is currently disconnected"}); } - if let Some((update_fee, commitment_signed, chan_monitor)) = chan.send_update_fee_and_commit(feerate_per_kw).map_err(|e| APIError::APIMisuseError{err: e.err})? { + if let Some((update_fee, commitment_signed, chan_monitor)) = chan.send_update_fee_and_commit(feerate_per_kw) + .map_err(|e| match e { + ChannelError::Ignore(err) => APIError::APIMisuseError{err}, + ChannelError::Close(err) => { + // TODO: We need to close the channel here, but for that to be safe we have + // to do all channel closure inside the channel_state lock which is a + // somewhat-larger refactor, so we leave that for later. + APIError::APIMisuseError{err} + }, + })? { if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { unimplemented!(); } @@ -2609,38 +2675,6 @@ impl ChainListener for ChannelManager { } } -macro_rules! handle_error { - ($self: ident, $internal: expr, $their_node_id: expr) => { - match $internal { - Ok(msg) => Ok(msg), - Err(MsgHandleErrInternal { err, needs_channel_force_close }) => { - if needs_channel_force_close { - match &err.action { - &Some(msgs::ErrorAction::DisconnectPeer { msg: Some(ref msg) }) => { - if msg.channel_id == [0; 32] { - $self.peer_disconnected(&$their_node_id, true); - } else { - $self.force_close_channel(&msg.channel_id); - } - }, - &Some(msgs::ErrorAction::DisconnectPeer { msg: None }) => {}, - &Some(msgs::ErrorAction::IgnoreError) => {}, - &Some(msgs::ErrorAction::SendErrorMessage { ref msg }) => { - if msg.channel_id == [0; 32] { - $self.peer_disconnected(&$their_node_id, true); - } else { - $self.force_close_channel(&msg.channel_id); - } - }, - &None => {}, - } - } - Err(err) - }, - } - } -} - impl ChannelMessageHandler for ChannelManager { //TODO: Handle errors and close channel (or so) fn handle_open_channel(&self, their_node_id: &PublicKey, msg: &msgs::OpenChannel) -> Result<(), HandleError> { @@ -3210,8 +3244,9 @@ mod tests { use chain::chaininterface; use chain::transaction::OutPoint; use chain::chaininterface::{ChainListener, ChainWatchInterface}; - use chain::keysinterface::KeysInterface; + use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor}; use chain::keysinterface; + use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC}; use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,OnionKeys,PaymentFailReason,RAACommitmentOrder}; use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, CLTV_CLAIM_BUFFER, HTLC_FAIL_TIMEOUT_BLOCKS, ManyChannelMonitor}; use ln::router::{Route, RouteHop, Router}; @@ -3224,13 +3259,16 @@ mod tests { use util::ser::{Writeable, Writer, ReadableArgs}; use util::config::UserConfig; - use bitcoin::util::hash::Sha256dHash; + use bitcoin::util::hash::{BitcoinHash, Sha256dHash}; + use bitcoin::util::bip143; + use bitcoin::util::address::Address; + use bitcoin::util::bip32::{ChildNumber, ExtendedPubKey, ExtendedPrivKey}; use bitcoin::blockdata::block::{Block, BlockHeader}; - use bitcoin::blockdata::transaction::{Transaction, TxOut}; + use bitcoin::blockdata::transaction::{Transaction, TxOut, TxIn, SigHashType}; + use bitcoin::blockdata::script::{Builder, Script}; + use bitcoin::blockdata::opcodes; use bitcoin::blockdata::constants::genesis_block; use bitcoin::network::constants::Network; - use bitcoin::network::serialize::serialize; - use bitcoin::network::serialize::BitcoinHash; use hex; @@ -3501,6 +3539,17 @@ mod tests { } } + macro_rules! get_feerate { + ($node: expr, $channel_id: expr) => { + { + let chan_lock = $node.node.channel_state.lock().unwrap(); + let chan = chan_lock.by_id.get(&$channel_id).unwrap(); + chan.get_feerate() + } + } + } + + fn create_chan_between_nodes_with_value_init(node_a: &Node, node_b: &Node, channel_value: u64, push_msat: u64) -> Transaction { node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42).unwrap(); node_b.node.handle_open_channel(&node_a.node.get_our_node_id(), &get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id())).unwrap(); @@ -3520,7 +3569,7 @@ mod tests { 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 = OutPoint::new(Sha256dHash::from_data(&serialize(&tx).unwrap()[..]), 0); + funding_output = OutPoint::new(tx.txid(), 0); node_a.node.funding_transaction_generated(&temporary_channel_id, funding_output); let mut added_monitors = node_a.chan_monitor.added_monitors.lock().unwrap(); @@ -3670,7 +3719,7 @@ mod tests { } } - fn close_channel(outbound_node: &Node, inbound_node: &Node, channel_id: &[u8; 32], 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, Transaction) { let (node_a, broadcaster_a, struct_a) = if close_inbound_first { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) } else { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) }; 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); @@ -3733,7 +3782,7 @@ mod tests { assert_eq!(tx_a, tx_b); check_spends!(tx_a, funding_tx); - (as_update, bs_update) + (as_update, bs_update, tx_a) } struct SendEvent { @@ -4134,14 +4183,6 @@ mod tests { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); let channel_id = chan.2; - macro_rules! get_feerate { - ($node: expr) => {{ - let chan_lock = $node.node.channel_state.lock().unwrap(); - let chan = chan_lock.by_id.get(&channel_id).unwrap(); - chan.get_feerate() - }} - } - // balancing send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); @@ -4163,7 +4204,7 @@ mod tests { // (6) RAA is delivered -> // First nodes[0] generates an update_fee - nodes[0].node.update_fee(channel_id, get_feerate!(nodes[0]) + 20).unwrap(); + nodes[0].node.update_fee(channel_id, get_feerate!(nodes[0], channel_id) + 20).unwrap(); check_added_monitors!(nodes[0], 1); let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); @@ -4252,19 +4293,11 @@ mod tests { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); let channel_id = chan.2; - macro_rules! get_feerate { - ($node: expr) => {{ - let chan_lock = $node.node.channel_state.lock().unwrap(); - let chan = chan_lock.by_id.get(&channel_id).unwrap(); - chan.get_feerate() - }} - } - // balancing send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); // First nodes[0] generates an update_fee - nodes[0].node.update_fee(channel_id, get_feerate!(nodes[0]) + 20).unwrap(); + nodes[0].node.update_fee(channel_id, get_feerate!(nodes[0], channel_id) + 20).unwrap(); check_added_monitors!(nodes[0], 1); let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); @@ -4310,14 +4343,6 @@ mod tests { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); let channel_id = chan.2; - macro_rules! get_feerate { - ($node: expr) => {{ - let chan_lock = $node.node.channel_state.lock().unwrap(); - let chan = chan_lock.by_id.get(&channel_id).unwrap(); - chan.get_feerate() - }} - } - // A B // update_fee/commitment_signed -> // .- send (1) RAA and (2) commitment_signed @@ -4338,7 +4363,7 @@ mod tests { // revoke_and_ack -> // First nodes[0] generates an update_fee - let initial_feerate = get_feerate!(nodes[0]); + let initial_feerate = get_feerate!(nodes[0], channel_id); nodes[0].node.update_fee(channel_id, initial_feerate + 20).unwrap(); check_added_monitors!(nodes[0], 1); @@ -4422,16 +4447,8 @@ mod tests { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); let channel_id = chan.2; - macro_rules! get_feerate { - ($node: expr) => {{ - let chan_lock = $node.node.channel_state.lock().unwrap(); - let chan = chan_lock.by_id.get(&channel_id).unwrap(); - chan.get_feerate() - }} - } - - let feerate = get_feerate!(nodes[0]); - nodes[0].node.update_fee(channel_id, feerate+20).unwrap(); + let feerate = get_feerate!(nodes[0], channel_id); + nodes[0].node.update_fee(channel_id, feerate+25).unwrap(); check_added_monitors!(nodes[0], 1); let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); @@ -4462,24 +4479,69 @@ mod tests { check_added_monitors!(nodes[1], 1); } + #[test] + fn test_update_fee_that_funder_cannot_afford() { + let nodes = create_network(2); + let channel_value = 1888; + let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, 700000); + let channel_id = chan.2; + + let feerate = 260; + nodes[0].node.update_fee(channel_id, feerate).unwrap(); + check_added_monitors!(nodes[0], 1); + let update_msg = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + + nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), &update_msg.update_fee.unwrap()).unwrap(); + + commitment_signed_dance!(nodes[1], nodes[0], update_msg.commitment_signed, false); + + //Confirm that the new fee based on the last local commitment txn is what we expected based on the feerate of 260 set above. + //This value results in a fee that is exactly what the funder can afford (277 sat + 1000 sat channel reserve) + { + let chan_lock = nodes[1].node.channel_state.lock().unwrap(); + let chan = chan_lock.by_id.get(&channel_id).unwrap(); + + //We made sure neither party's funds are below the dust limit so -2 non-HTLC txns from number of outputs + let num_htlcs = chan.last_local_commitment_txn[0].output.len() - 2; + let total_fee: u64 = feerate * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let mut actual_fee = chan.last_local_commitment_txn[0].output.iter().fold(0, |acc, output| acc + output.value); + actual_fee = channel_value - actual_fee; + assert_eq!(total_fee, actual_fee); + } //drop the mutex + + //Add 2 to the previous fee rate to the final fee increases by 1 (with no HTLCs the fee is essentially + //fee_rate*(724/1000) so the increment of 1*0.724 is rounded back down) + nodes[0].node.update_fee(channel_id, feerate+2).unwrap(); + check_added_monitors!(nodes[0], 1); + + let update2_msg = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + + nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), &update2_msg.update_fee.unwrap()).unwrap(); + + //While producing the commitment_signed response after handling a received update_fee request the + //check to see if the funder, who sent the update_fee request, can afford the new fee (funder_balance >= fee+channel_reserve) + //Should produce and error. + let err = nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &update2_msg.commitment_signed).unwrap_err(); + + assert!(match err.err { + "Funding remote cannot afford proposed new fee" => true, + _ => false, + }); + + //clear the message we could not handle + nodes[1].node.get_and_clear_pending_msg_events(); + } + #[test] fn test_update_fee_with_fundee_update_add_htlc() { let mut nodes = create_network(2); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); let channel_id = chan.2; - macro_rules! get_feerate { - ($node: expr) => {{ - let chan_lock = $node.node.channel_state.lock().unwrap(); - let chan = chan_lock.by_id.get(&channel_id).unwrap(); - chan.get_feerate() - }} - } - // balancing send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); - let feerate = get_feerate!(nodes[0]); + let feerate = get_feerate!(nodes[0], channel_id); nodes[0].node.update_fee(channel_id, feerate+20).unwrap(); check_added_monitors!(nodes[0], 1); @@ -4577,14 +4639,6 @@ mod tests { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); let channel_id = chan.2; - macro_rules! get_feerate { - ($node: expr) => {{ - let chan_lock = $node.node.channel_state.lock().unwrap(); - let chan = chan_lock.by_id.get(&channel_id).unwrap(); - chan.get_feerate() - }} - } - // A B // (1) update_fee/commitment_signed -> // <- (2) revoke_and_ack @@ -4600,7 +4654,7 @@ mod tests { // revoke_and_ack -> // Create and deliver (1)... - let feerate = get_feerate!(nodes[0]); + let feerate = get_feerate!(nodes[0], channel_id); nodes[0].node.update_fee(channel_id, feerate+20).unwrap(); check_added_monitors!(nodes[0], 1); @@ -4674,8 +4728,8 @@ mod tests { check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - assert_eq!(get_feerate!(nodes[0]), feerate + 30); - assert_eq!(get_feerate!(nodes[1]), feerate + 30); + assert_eq!(get_feerate!(nodes[0], channel_id), feerate + 30); + assert_eq!(get_feerate!(nodes[1], channel_id), feerate + 30); close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true); } @@ -5315,8 +5369,7 @@ mod tests { }} } - #[test] - fn channel_reserve_test() { + fn do_channel_reserve_test(test_recv: bool) { use util::rng; use std::sync::atomic::Ordering; use ln::msgs::HandleError; @@ -5473,9 +5526,23 @@ mod tests { onion_routing_packet: onion_packet, }; - let err = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &msg).err().unwrap(); - match err { - HandleError{err, .. } => assert_eq!(err, "Remote HTLC add would put them over their reserve value"), + if test_recv { + let err = nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &msg).err().unwrap(); + match err { + HandleError{err, .. } => assert_eq!(err, "Remote HTLC add would put them over their reserve value"), + } + // If we send a garbage message, the channel should get closed, making the rest of this test case fail. + /*assert_eq!(nodes[1].node.list_channels().len(), 1); + assert_eq!(nodes[1].node.list_channels().len(), 1); + let channel_close_broadcast = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(channel_close_broadcast.len(), 1); + match channel_close_broadcast[0] { + MessageSendEvent::BroadcastChannelUpdate { ref msg } => { + assert_eq!(msg.contents.flags & 2, 2); + }, + _ => panic!("Unexpected event"), + }*/ + return; } } @@ -5583,6 +5650,12 @@ mod tests { assert_eq!(stat2.value_to_self_msat, stat22.value_to_self_msat + recv_value_1 + recv_value_21 + recv_value_22); } + #[test] + fn channel_reserve_test() { + do_channel_reserve_test(false); + do_channel_reserve_test(true); + } + #[test] fn channel_monitor_network_test() { // Simple test which builds a network of ChannelManagers, connects them to each other, and @@ -6212,7 +6285,7 @@ mod tests { /// pending_htlc_adds includes both the holding cell and in-flight update_add_htlcs, whereas /// for claims/fails they are separated out. - fn reconnect_nodes(node_a: &Node, node_b: &Node, pre_all_htlcs: bool, pending_htlc_adds: (i64, i64), pending_htlc_claims: (usize, usize), pending_cell_htlc_claims: (usize, usize), pending_cell_htlc_fails: (usize, usize), pending_raa: (bool, bool)) { + fn reconnect_nodes(node_a: &Node, node_b: &Node, send_funding_locked: (bool, bool), pending_htlc_adds: (i64, i64), pending_htlc_claims: (usize, usize), pending_cell_htlc_claims: (usize, usize), pending_cell_htlc_fails: (usize, usize), pending_raa: (bool, bool)) { node_a.node.peer_connected(&node_b.node.get_our_node_id()); let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b); node_b.node.peer_connected(&node_a.node.get_our_node_id()); @@ -6245,7 +6318,7 @@ mod tests { (pending_htlc_adds.1 == 0 && pending_htlc_claims.1 == 0 && pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0)); for chan_msgs in resp_1.drain(..) { - if pre_all_htlcs { + if send_funding_locked.0 { node_a.node.handle_funding_locked(&node_b.node.get_our_node_id(), &chan_msgs.0.unwrap()).unwrap(); let announcement_event = node_a.node.get_and_clear_pending_msg_events(); if !announcement_event.is_empty() { @@ -6302,7 +6375,7 @@ mod tests { } for chan_msgs in resp_2.drain(..) { - if pre_all_htlcs { + if send_funding_locked.1 { node_b.node.handle_funding_locked(&node_a.node.get_our_node_id(), &chan_msgs.0.unwrap()).unwrap(); let announcement_event = node_b.node.get_and_clear_pending_msg_events(); if !announcement_event.is_empty() { @@ -6366,7 +6439,7 @@ mod tests { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - reconnect_nodes(&nodes[0], &nodes[1], true, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0; let payment_hash_2 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1; @@ -6375,7 +6448,7 @@ mod tests { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0; let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0; @@ -6388,7 +6461,7 @@ mod tests { claim_payment_along_route(&nodes[0], &vec!(&nodes[1], &nodes[2]), true, payment_preimage_3); fail_payment_along_route(&nodes[0], &[&nodes[1], &nodes[2]], true, payment_hash_5); - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (1, 0), (1, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (1, 0), (1, 0), (false, false)); { let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); @@ -6469,19 +6542,19 @@ mod tests { if messages_delivered < 3 { // Even if the funding_locked messages get exchanged, as long as nothing further was // received on either side, both sides will need to resend them. - reconnect_nodes(&nodes[0], &nodes[1], true, (0, 1), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 1), (0, 0), (0, 0), (0, 0), (false, false)); } else if messages_delivered == 3 { // nodes[0] still wants its RAA + commitment_signed - reconnect_nodes(&nodes[0], &nodes[1], false, (-1, 0), (0, 0), (0, 0), (0, 0), (true, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (-1, 0), (0, 0), (0, 0), (0, 0), (true, false)); } else if messages_delivered == 4 { // nodes[0] still wants its commitment_signed - reconnect_nodes(&nodes[0], &nodes[1], false, (-1, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (-1, 0), (0, 0), (0, 0), (0, 0), (false, false)); } else if messages_delivered == 5 { // nodes[1] still wants its final RAA - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, true)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, true)); } else if messages_delivered == 6 { // Everything was delivered... - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); } let events_1 = nodes[1].node.get_and_clear_pending_events(); @@ -6493,7 +6566,7 @@ mod tests { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); nodes[1].node.channel_state.lock().unwrap().next_forward = Instant::now(); nodes[1].node.process_pending_htlc_forwards(); @@ -6567,7 +6640,7 @@ mod tests { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); if messages_delivered < 2 { - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (1, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (1, 0), (0, 0), (0, 0), (false, false)); //TODO: Deduplicate PaymentSent events, then enable this if: //if messages_delivered < 1 { let events_4 = nodes[0].node.get_and_clear_pending_events(); @@ -6581,21 +6654,21 @@ mod tests { //} } else if messages_delivered == 2 { // nodes[0] still wants its RAA + commitment_signed - reconnect_nodes(&nodes[0], &nodes[1], false, (0, -1), (0, 0), (0, 0), (0, 0), (false, true)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, -1), (0, 0), (0, 0), (0, 0), (false, true)); } else if messages_delivered == 3 { // nodes[0] still wants its commitment_signed - reconnect_nodes(&nodes[0], &nodes[1], false, (0, -1), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, -1), (0, 0), (0, 0), (0, 0), (false, false)); } else if messages_delivered == 4 { // nodes[1] still wants its final RAA - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (true, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (true, false)); } else if messages_delivered == 5 { // Everything was delivered... - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); } nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); // Channel should still work fine... let payment_preimage_2 = send_along_route(&nodes[0], route, &[&nodes[1]], 1000000).0; @@ -6636,20 +6709,28 @@ mod tests { _ => panic!("Unexpected event"), } + reconnect_nodes(&nodes[0], &nodes[1], (false, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + + nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); + nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); + confirm_transaction(&nodes[1].chain_monitor, &tx, tx.version); let events_2 = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(events_2.len(), 1); + assert_eq!(events_2.len(), 2); match events_2[0] { MessageSendEvent::SendFundingLocked { ref node_id, msg: _ } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); }, _ => panic!("Unexpected event"), } + match events_2[1] { + MessageSendEvent::SendAnnouncementSignatures { ref node_id, msg: _ } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + }, + _ => panic!("Unexpected event"), + } - reconnect_nodes(&nodes[0], &nodes[1], true, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); - nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); - nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - reconnect_nodes(&nodes[0], &nodes[1], true, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); // TODO: We shouldn't need to manually pass list_usable_chanels here once we support // rebroadcasting announcement_signatures upon reconnect. @@ -6852,7 +6933,7 @@ mod tests { if disconnect { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - reconnect_nodes(&nodes[0], &nodes[1], true, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); } *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(()); @@ -6893,7 +6974,7 @@ mod tests { if disconnect { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); } // ...and make sure we can force-close a TemporaryFailure channel with a PermanentFailure @@ -7453,7 +7534,7 @@ mod tests { nodes[0].node = Arc::new(nodes_0_deserialized); check_added_monitors!(nodes[0], 1); - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); fail_payment(&nodes[0], &[&nodes[1]], our_payment_hash); claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage); @@ -7523,8 +7604,8 @@ mod tests { nodes[0].node = Arc::new(nodes_0_deserialized); // nodes[1] and nodes[2] have no lost state with nodes[0]... - reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); - reconnect_nodes(&nodes[0], &nodes[2], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[2], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); //... and we can even still claim the payment! claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage); @@ -7535,4 +7616,467 @@ mod tests { assert_eq!(msg.channel_id, channel_id); } else { panic!("Unexpected result"); } } + + macro_rules! check_dynamic_output_p2wsh { + ($node: expr) => { + { + let events = $node.chan_monitor.simple_monitor.get_and_clear_pending_events(); + let mut txn = Vec::new(); + for event in events { + match event { + Event::SpendableOutputs { ref outputs } => { + for outp in outputs { + match *outp { + SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref key, ref witness_script, ref to_self_delay, ref output } => { + let input = TxIn { + previous_output: outpoint.clone(), + script_sig: Script::new(), + sequence: *to_self_delay as u32, + witness: Vec::new(), + }; + let outp = TxOut { + script_pubkey: Builder::new().push_opcode(opcodes::All::OP_RETURN).into_script(), + value: output.value, + }; + let mut spend_tx = Transaction { + version: 2, + lock_time: 0, + input: vec![input], + output: vec![outp], + }; + let secp_ctx = Secp256k1::new(); + let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], witness_script, output.value)[..]).unwrap(); + let local_delaysig = secp_ctx.sign(&sighash, key); + spend_tx.input[0].witness.push(local_delaysig.serialize_der(&secp_ctx).to_vec()); + spend_tx.input[0].witness[0].push(SigHashType::All as u8); + spend_tx.input[0].witness.push(vec!(0)); + spend_tx.input[0].witness.push(witness_script.clone().into_bytes()); + txn.push(spend_tx); + }, + _ => panic!("Unexpected event"), + } + } + }, + _ => panic!("Unexpected event"), + }; + } + txn + } + } + } + + macro_rules! check_dynamic_output_p2wpkh { + ($node: expr) => { + { + let events = $node.chan_monitor.simple_monitor.get_and_clear_pending_events(); + let mut txn = Vec::new(); + for event in events { + match event { + Event::SpendableOutputs { ref outputs } => { + for outp in outputs { + match *outp { + SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => { + let input = TxIn { + previous_output: outpoint.clone(), + script_sig: Script::new(), + sequence: 0, + witness: Vec::new(), + }; + let outp = TxOut { + script_pubkey: Builder::new().push_opcode(opcodes::All::OP_RETURN).into_script(), + value: output.value, + }; + let mut spend_tx = Transaction { + version: 2, + lock_time: 0, + input: vec![input], + output: vec![outp], + }; + let secp_ctx = Secp256k1::new(); + let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &key); + let witness_script = Address::p2pkh(&remotepubkey, Network::Testnet).script_pubkey(); + let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap(); + let remotesig = secp_ctx.sign(&sighash, key); + spend_tx.input[0].witness.push(remotesig.serialize_der(&secp_ctx).to_vec()); + spend_tx.input[0].witness[0].push(SigHashType::All as u8); + spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec()); + txn.push(spend_tx); + }, + _ => panic!("Unexpected event"), + } + } + }, + _ => panic!("Unexpected event"), + }; + } + txn + } + } + } + + macro_rules! check_static_output { + ($event: expr, $node: expr, $event_idx: expr, $output_idx: expr, $der_idx: expr, $idx_node: expr) => { + match $event[$event_idx] { + Event::SpendableOutputs { ref outputs } => { + match outputs[$output_idx] { + SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output } => { + let secp_ctx = Secp256k1::new(); + let input = TxIn { + previous_output: outpoint.clone(), + script_sig: Script::new(), + sequence: 0, + witness: Vec::new(), + }; + let outp = TxOut { + script_pubkey: Builder::new().push_opcode(opcodes::All::OP_RETURN).into_script(), + value: output.value, + }; + let mut spend_tx = Transaction { + version: 2, + lock_time: 0, + input: vec![input], + output: vec![outp.clone()], + }; + let secret = { + match ExtendedPrivKey::new_master(&secp_ctx, Network::Testnet, &$node[$idx_node].node_seed) { + Ok(master_key) => { + match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx($der_idx)) { + Ok(key) => key, + Err(_) => panic!("Your RNG is busted"), + } + } + Err(_) => panic!("Your rng is busted"), + } + }; + let pubkey = ExtendedPubKey::from_private(&secp_ctx, &secret).public_key; + let witness_script = Address::p2pkh(&pubkey, Network::Testnet).script_pubkey(); + let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap(); + let sig = secp_ctx.sign(&sighash, &secret.secret_key); + spend_tx.input[0].witness.push(sig.serialize_der(&secp_ctx).to_vec()); + spend_tx.input[0].witness[0].push(SigHashType::All as u8); + spend_tx.input[0].witness.push(pubkey.serialize().to_vec()); + spend_tx + }, + _ => panic!("Unexpected event !"), + } + }, + _ => panic!("Unexpected event !"), + }; + } + } + + #[test] + fn test_claim_sizeable_push_msat() { + // Incidentally test SpendableOutput event generation due to detection of to_local output on commitment tx + let nodes = create_network(2); + + let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000); + nodes[1].node.force_close_channel(&chan.2); + let events = nodes[1].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn.len(), 1); + check_spends!(node_txn[0], chan.3.clone()); + assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening + + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 0); + let spend_txn = check_dynamic_output_p2wsh!(nodes[1]); + assert_eq!(spend_txn.len(), 1); + check_spends!(spend_txn[0], node_txn[0].clone()); + } + + #[test] + fn test_claim_on_remote_sizeable_push_msat() { + // Same test as precedent, just test on remote commitment tx, as per_commitment_point registration changes following you're funder/fundee and + // to_remote output is encumbered by a P2WPKH + + let nodes = create_network(2); + + let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000); + nodes[0].node.force_close_channel(&chan.2); + let events = nodes[0].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn.len(), 1); + check_spends!(node_txn[0], chan.3.clone()); + assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening + + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 0); + let events = nodes[1].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + let spend_txn = check_dynamic_output_p2wpkh!(nodes[1]); + assert_eq!(spend_txn.len(), 2); + assert_eq!(spend_txn[0], spend_txn[1]); + check_spends!(spend_txn[0], node_txn[0].clone()); + } + + #[test] + fn test_static_spendable_outputs_preimage_tx() { + let nodes = create_network(2); + + // Create some initial channels + let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); + + let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + + let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone(); + assert_eq!(commitment_tx[0].input.len(), 1); + assert_eq!(commitment_tx[0].input[0].previous_output.txid, chan_1.3.txid()); + + // Settle A's commitment tx on B's chain + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + assert!(nodes[1].node.claim_funds(payment_preimage)); + check_added_monitors!(nodes[1], 1); + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()] }, 1); + let events = nodes[1].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::UpdateHTLCs { .. } => {}, + _ => panic!("Unexpected event"), + } + match events[1] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexepected event"), + } + + // Check B's monitor was able to send back output descriptor event for preimage tx on A's commitment tx + let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); // ChannelManager : 1 (local commitment tx), ChannelMonitor: 2 (1 preimage tx) * 2 (block-rescan) + check_spends!(node_txn[0], commitment_tx[0].clone()); + assert_eq!(node_txn[0], node_txn[2]); + assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), 133); + check_spends!(node_txn[1], chan_1.3.clone()); + + let events = nodes[1].chan_monitor.simple_monitor.get_and_clear_pending_events(); + let spend_tx = check_static_output!(events, nodes, 0, 0, 1, 1); + check_spends!(spend_tx, node_txn[0].clone()); + } + + #[test] + fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() { + let nodes = create_network(2); + + // Create some initial channels + let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); + + let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.last_local_commitment_txn.clone(); + assert_eq!(revoked_local_txn[0].input.len(), 1); + assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid()); + + claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + let events = nodes[1].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn.len(), 3); + assert_eq!(node_txn.pop().unwrap(), node_txn[0]); + assert_eq!(node_txn[0].input.len(), 2); + check_spends!(node_txn[0], revoked_local_txn[0].clone()); + + let events = nodes[1].chan_monitor.simple_monitor.get_and_clear_pending_events(); + let spend_tx = check_static_output!(events, nodes, 0, 0, 1, 1); + check_spends!(spend_tx, node_txn[0].clone()); + } + + #[test] + fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() { + let nodes = create_network(2); + + // Create some initial channels + let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); + + let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone(); + assert_eq!(revoked_local_txn[0].input.len(), 1); + assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid()); + + claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + // A will generate HTLC-Timeout from revoked commitment tx + nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + let events = nodes[0].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(revoked_htlc_txn.len(), 2); + assert_eq!(revoked_htlc_txn[0].input.len(), 1); + assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), 133); + check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone()); + + // B will generate justice tx from A's revoked commitment/HTLC tx + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1); + let events = nodes[1].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + + let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn.len(), 4); + assert_eq!(node_txn[3].input.len(), 1); + check_spends!(node_txn[3], revoked_htlc_txn[0].clone()); + + let events = nodes[1].chan_monitor.simple_monitor.get_and_clear_pending_events(); + // Check B's ChannelMonitor was able to generate the right spendable output descriptor + let spend_tx = check_static_output!(events, nodes, 1, 1, 1, 1); + check_spends!(spend_tx, node_txn[3].clone()); + } + + #[test] + fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() { + let nodes = create_network(2); + + // Create some initial channels + let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); + + let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone(); + assert_eq!(revoked_local_txn[0].input.len(), 1); + assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid()); + + claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + // B will generate HTLC-Success from revoked commitment tx + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + let events = nodes[1].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); + + assert_eq!(revoked_htlc_txn.len(), 2); + assert_eq!(revoked_htlc_txn[0].input.len(), 1); + assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), 138); + check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone()); + + // A will generate justice tx from B's revoked commitment/HTLC tx + nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1); + let events = nodes[0].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + + let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn.len(), 4); + assert_eq!(node_txn[3].input.len(), 1); + check_spends!(node_txn[3], revoked_htlc_txn[0].clone()); + + let events = nodes[0].chan_monitor.simple_monitor.get_and_clear_pending_events(); + // Check A's ChannelMonitor was able to generate the right spendable output descriptor + let spend_tx = check_static_output!(events, nodes, 1, 2, 1, 0); + check_spends!(spend_tx, node_txn[3].clone()); + } + + #[test] + fn test_dynamic_spendable_outputs_local_htlc_success_tx() { + let nodes = create_network(2); + + // Create some initial channels + let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); + + let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000).0; + let local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone(); + assert_eq!(local_txn[0].input.len(), 1); + check_spends!(local_txn[0], chan_1.3.clone()); + + // Give B knowledge of preimage to be able to generate a local HTLC-Success Tx + nodes[1].node.claim_funds(payment_preimage); + check_added_monitors!(nodes[1], 1); + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![local_txn[0].clone()] }, 1); + let events = nodes[1].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::UpdateHTLCs { .. } => {}, + _ => panic!("Unexpected event"), + } + match events[1] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexepected event"), + } + let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn[0].input.len(), 1); + assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), 138); + check_spends!(node_txn[0], local_txn[0].clone()); + + // Verify that B is able to spend its own HTLC-Success tx thanks to spendable output event given back by its ChannelMonitor + let spend_txn = check_dynamic_output_p2wsh!(nodes[1]); + assert_eq!(spend_txn.len(), 1); + check_spends!(spend_txn[0], node_txn[0].clone()); + } + + #[test] + fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() { + let nodes = create_network(2); + + // Create some initial channels + let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); + + route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000).0; + let local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone(); + assert_eq!(local_txn[0].input.len(), 1); + check_spends!(local_txn[0], chan_1.3.clone()); + + // Timeout HTLC on A's chain and so it can generate a HTLC-Timeout tx + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![local_txn[0].clone()] }, 200); + let events = nodes[0].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexepected event"), + } + let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn[0].input.len(), 1); + assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), 133); + check_spends!(node_txn[0], local_txn[0].clone()); + + // Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor + let spend_txn = check_dynamic_output_p2wsh!(nodes[0]); + assert_eq!(spend_txn.len(), 4); + assert_eq!(spend_txn[0], spend_txn[2]); + assert_eq!(spend_txn[1], spend_txn[3]); + check_spends!(spend_txn[0], local_txn[0].clone()); + check_spends!(spend_txn[1], node_txn[0].clone()); + } + + #[test] + fn test_static_output_closing_tx() { + let nodes = create_network(2); + + let chan = create_announced_chan_between_nodes(&nodes, 0, 1); + + send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); + let closing_tx = close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true).2; + + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![closing_tx.clone()] }, 1); + let events = nodes[0].chan_monitor.simple_monitor.get_and_clear_pending_events(); + let spend_tx = check_static_output!(events, nodes, 0, 0, 2, 0); + check_spends!(spend_tx, closing_tx.clone()); + + nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![closing_tx.clone()] }, 1); + let events = nodes[1].chan_monitor.simple_monitor.get_and_clear_pending_events(); + let spend_tx = check_static_output!(events, nodes, 0, 0, 2, 1); + check_spends!(spend_tx, closing_tx); + } }