X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannelmanager.rs;h=d4548ce621a516fca6ba5fdcb1b5a87213373f16;hb=6b3cc8bb4dd645f6afaa00afe6a4e02d8ff8e2db;hp=bd649ac0ad937362a0e58a095e696110ea703dfb;hpb=321534020e021e440e7b1effb05a7ae5ca725bbd;p=rust-lightning diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index bd649ac0..d4548ce6 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -36,16 +36,31 @@ use std::sync::{Mutex,MutexGuard,Arc}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{Instant,Duration}; +/// We hold various information about HTLC relay in the HTLC objects in Channel itself: +/// +/// Upon receipt of an HTLC from a peer, we'll give it a PendingHTLCStatus indicating if it should +/// forward the HTLC with information it will give back to us when it does so, or if it should Fail +/// the HTLC with the relevant message for the Channel to handle giving to the remote peer. +/// +/// When a Channel forwards an HTLC to its peer, it will give us back the PendingForwardHTLCInfo +/// which we will use to construct an outbound HTLC, with a relevant HTLCSource::PreviousHopData +/// filled in to indicate where it came from (which we can use to either fail-backwards or fulfill +/// the HTLC backwards along the relevant path). +/// Alternatively, we can fill an outbound HTLC with a HTLCSource::OutboundRoute indicating this is +/// our payment, which we can use to decode errors or inform the user that the payment was sent. mod channel_held_info { use ln::msgs; + use ln::router::Route; + use secp256k1::key::SecretKey; + use secp256k1::ecdh::SharedSecret; /// Stores the info we will need to send when we want to forward an HTLC onwards #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug pub struct PendingForwardHTLCInfo { pub(super) onion_packet: Option, + pub(super) incoming_shared_secret: SharedSecret, pub(super) payment_hash: [u8; 32], pub(super) short_channel_id: u64, - pub(super) prev_short_channel_id: u64, pub(super) amt_to_forward: u64, pub(super) outgoing_cltv_value: u32, } @@ -66,17 +81,47 @@ mod channel_held_info { #[cfg(feature = "fuzztarget")] impl PendingHTLCStatus { pub fn dummy() -> Self { + let secp_ctx = ::secp256k1::Secp256k1::signing_only(); PendingHTLCStatus::Forward(PendingForwardHTLCInfo { onion_packet: None, + incoming_shared_secret: SharedSecret::new(&secp_ctx, + &::secp256k1::key::PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &[1; 32]).unwrap()), + &SecretKey::from_slice(&secp_ctx, &[1; 32]).unwrap()), payment_hash: [0; 32], short_channel_id: 0, - prev_short_channel_id: 0, amt_to_forward: 0, outgoing_cltv_value: 0, }) } } + /// Tracks the inbound corresponding to an outbound HTLC + #[derive(Clone)] + pub struct HTLCPreviousHopData { + pub(super) short_channel_id: u64, + pub(super) htlc_id: u64, + pub(super) incoming_packet_shared_secret: SharedSecret, + } + + /// Tracks the inbound corresponding to an outbound HTLC + #[derive(Clone)] + pub enum HTLCSource { + PreviousHopData(HTLCPreviousHopData), + OutboundRoute { + route: Route, + session_priv: SecretKey, + }, + } + #[cfg(any(test, feature = "fuzztarget"))] + impl HTLCSource { + pub fn dummy() -> Self { + HTLCSource::OutboundRoute { + route: Route { hops: Vec::new() }, + session_priv: SecretKey::from_slice(&::secp256k1::Secp256k1::without_caps(), &[1; 32]).unwrap(), + } + } + } + #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug pub enum HTLCFailReason { ErrorPacket { @@ -102,24 +147,6 @@ pub use self::channel_held_info::*; #[cfg(not(feature = "fuzztarget"))] pub(crate) use self::channel_held_info::*; -enum PendingOutboundHTLC { - IntermediaryHopData { - source_short_channel_id: u64, - incoming_packet_shared_secret: SharedSecret, - }, - OutboundRoute { - route: Route, - session_priv: SecretKey, - }, - /// Used for channel rebalancing - CycledRoute { - source_short_channel_id: u64, - incoming_packet_shared_secret: SharedSecret, - route: Route, - session_priv: SecretKey, - } -} - struct MsgHandleErrInternal { err: msgs::HandleError, needs_channel_force_close: bool, @@ -171,6 +198,12 @@ impl MsgHandleErrInternal { /// probably increase this significantly. const MIN_HTLC_RELAY_HOLDING_CELL_MILLIS: u32 = 50; +struct HTLCForwardInfo { + prev_short_channel_id: u64, + prev_htlc_id: u64, + forward_info: PendingForwardHTLCInfo, +} + struct ChannelHolder { by_id: HashMap<[u8; 32], Channel>, short_to_id: HashMap, @@ -179,18 +212,18 @@ struct ChannelHolder { /// Note that while this is held in the same mutex as the channels themselves, no consistency /// guarantees are made about there existing a channel with the short id here, nor the short /// ids in the PendingForwardHTLCInfo! - forward_htlcs: HashMap>, + forward_htlcs: HashMap>, /// Note that while this is held in the same mutex as the channels themselves, no consistency /// guarantees are made about the channels given here actually existing anymore by the time you /// go to read them! - claimable_htlcs: HashMap<[u8; 32], PendingOutboundHTLC>, + claimable_htlcs: HashMap<[u8; 32], Vec>, } struct MutChannelHolder<'a> { by_id: &'a mut HashMap<[u8; 32], Channel>, short_to_id: &'a mut HashMap, next_forward: &'a mut Instant, - forward_htlcs: &'a mut HashMap>, - claimable_htlcs: &'a mut HashMap<[u8; 32], PendingOutboundHTLC>, + forward_htlcs: &'a mut HashMap>, + claimable_htlcs: &'a mut HashMap<[u8; 32], Vec>, } impl ChannelHolder { fn borrow_parts(&mut self) -> MutChannelHolder { @@ -392,7 +425,7 @@ impl ChannelManager { /// pending HTLCs, the channel will be closed on chain. /// 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 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()) { @@ -408,9 +441,9 @@ impl ChannelManager { hash_map::Entry::Vacant(_) => return Err(HandleError{err: "No such channel", action: None}) } }; - for payment_hash in res.1 { + for htlc_source in res.1.drain(..) { // 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() }); + self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source.0, &htlc_source.1, HTLCFailReason::Reason { failure_code: 0x4000 | 10, data: Vec::new() }); } let chan_update = if let Some(chan) = chan_option { if let Ok(update) = self.get_channel_update(&chan) { @@ -433,11 +466,11 @@ impl ChannelManager { } #[inline] - fn finish_force_close_channel(&self, shutdown_res: (Vec, Vec<[u8; 32]>)) { - let (local_txn, failed_htlcs) = shutdown_res; - for payment_hash in failed_htlcs { + fn finish_force_close_channel(&self, shutdown_res: (Vec, Vec<(HTLCSource, [u8; 32])>)) { + let (local_txn, mut failed_htlcs) = shutdown_res; + for htlc_source in failed_htlcs.drain(..) { // 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() }); + self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source.0, &htlc_source.1, HTLCFailReason::Reason { failure_code: 0x4000 | 10, data: Vec::new() }); } for tx in local_txn { self.tx_broadcaster.broadcast_transaction(&tx); @@ -722,7 +755,7 @@ impl ChannelManager { ChannelManager::encrypt_failure_packet(shared_secret, &failure_packet.encode()[..]) } - fn decode_update_add_htlc_onion(&self, msg: &msgs::UpdateAddHTLC) -> (PendingHTLCStatus, Option, MutexGuard) { + fn decode_update_add_htlc_onion(&self, msg: &msgs::UpdateAddHTLC) -> (PendingHTLCStatus, MutexGuard) { macro_rules! get_onion_hash { () => { { @@ -742,7 +775,7 @@ impl ChannelManager { htlc_id: msg.htlc_id, sha256_of_onion: get_onion_hash!(), failure_code: 0x8000 | 0x4000 | 6, - })), None, self.channel_state.lock().unwrap()); + })), self.channel_state.lock().unwrap()); } let shared_secret = SharedSecret::new(&self.secp_ctx, &msg.onion_routing_packet.public_key.unwrap(), &self.our_network_key); @@ -760,7 +793,7 @@ impl ChannelManager { channel_id: msg.channel_id, htlc_id: msg.htlc_id, reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, $err_code, $data), - })), Some(shared_secret), channel_state.unwrap()); + })), channel_state.unwrap()); } } } @@ -818,7 +851,7 @@ impl ChannelManager { onion_packet: None, payment_hash: msg.payment_hash.clone(), short_channel_id: 0, - prev_short_channel_id: 0, + incoming_shared_secret: shared_secret.clone(), amt_to_forward: next_hop_data.data.amt_to_forward, outgoing_cltv_value: next_hop_data.data.outgoing_cltv_value, }) @@ -858,7 +891,7 @@ impl ChannelManager { onion_packet: Some(outgoing_packet), payment_hash: msg.payment_hash.clone(), short_channel_id: next_hop_data.data.short_channel_id, - prev_short_channel_id: 0, + incoming_shared_secret: shared_secret.clone(), amt_to_forward: next_hop_data.data.amt_to_forward, outgoing_cltv_value: next_hop_data.data.outgoing_cltv_value, }) @@ -896,7 +929,7 @@ impl ChannelManager { } } - (pending_forward_info, Some(shared_secret), channel_state.unwrap()) + (pending_forward_info, channel_state.unwrap()) } /// only fails if the channel does not yet have an assigned short_id @@ -975,26 +1008,22 @@ impl ChannelManager { Some(id) => id.clone() }; - let claimable_htlc_entry = channel_state.claimable_htlcs.entry(payment_hash.clone()); - if let hash_map::Entry::Occupied(_) = claimable_htlc_entry { - return Err(HandleError{err: "Already had pending HTLC with the same payment_hash", action: None}); - } - let res = { let chan = channel_state.by_id.get_mut(&id).unwrap(); if chan.get_their_node_id() != route.hops.first().unwrap().pubkey { return Err(HandleError{err: "Node ID mismatch on first hop!", action: None}); } - chan.send_htlc_and_commit(htlc_msat, payment_hash, htlc_cltv, onion_packet)? + if !chan.is_live() { + return Err(HandleError{err: "Peer for first hop currently disconnected!", action: None}); + } + chan.send_htlc_and_commit(htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute { + route: route.clone(), + session_priv: session_priv.clone(), + }, onion_packet)? }; let first_hop_node_id = route.hops.first().unwrap().pubkey; - claimable_htlc_entry.or_insert(PendingOutboundHTLC::OutboundRoute { - route, - session_priv, - }); - match res { Some(msgs) => (first_hop_node_id, msgs), None => return Ok(()), @@ -1002,7 +1031,7 @@ 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? + unimplemented!(); } let mut events = self.pending_events.lock().unwrap(); @@ -1057,7 +1086,7 @@ impl ChannelManager { } }; // Release channel lock for install_watch_outpoint call, if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { - unimplemented!(); // maybe remove from claimable_htlcs? + unimplemented!(); } add_pending_event!(events::Event::SendFundingCreated { node_id: chan.get_their_node_id(), @@ -1107,14 +1136,19 @@ impl ChannelManager { return; } - for (short_chan_id, pending_forwards) in channel_state.forward_htlcs.drain() { + for (short_chan_id, mut pending_forwards) in channel_state.forward_htlcs.drain() { if short_chan_id != 0 { let forward_chan_id = match channel_state.short_to_id.get(&short_chan_id) { Some(chan_id) => chan_id.clone(), None => { failed_forwards.reserve(pending_forwards.len()); - for forward_info in pending_forwards { - failed_forwards.push((forward_info.payment_hash, 0x4000 | 10, None)); + for HTLCForwardInfo { prev_short_channel_id, prev_htlc_id, forward_info } in pending_forwards.drain(..) { + let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { + short_channel_id: prev_short_channel_id, + htlc_id: prev_htlc_id, + incoming_packet_shared_secret: forward_info.incoming_shared_secret, + }); + failed_forwards.push((htlc_source, forward_info.payment_hash, 0x4000 | 10, None)); } continue; } @@ -1122,11 +1156,16 @@ impl ChannelManager { let forward_chan = &mut channel_state.by_id.get_mut(&forward_chan_id).unwrap(); let mut add_htlc_msgs = Vec::new(); - for forward_info in pending_forwards { - match forward_chan.send_htlc(forward_info.amt_to_forward, forward_info.payment_hash, forward_info.outgoing_cltv_value, forward_info.onion_packet.unwrap()) { + for HTLCForwardInfo { prev_short_channel_id, prev_htlc_id, forward_info } in pending_forwards.drain(..) { + let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { + short_channel_id: prev_short_channel_id, + htlc_id: prev_htlc_id, + incoming_packet_shared_secret: forward_info.incoming_shared_secret, + }); + match forward_chan.send_htlc(forward_info.amt_to_forward, forward_info.payment_hash, forward_info.outgoing_cltv_value, htlc_source.clone(), forward_info.onion_packet.unwrap()) { Err(_e) => { let chan_update = self.get_channel_update(forward_chan).unwrap(); - failed_forwards.push((forward_info.payment_hash, 0x1000 | 7, Some(chan_update))); + failed_forwards.push((htlc_source, forward_info.payment_hash, 0x1000 | 7, Some(chan_update))); continue; }, Ok(update_add) => { @@ -1171,7 +1210,16 @@ impl ChannelManager { })); } } else { - for forward_info in pending_forwards { + for HTLCForwardInfo { prev_short_channel_id, prev_htlc_id, forward_info } in pending_forwards.drain(..) { + let prev_hop_data = HTLCPreviousHopData { + short_channel_id: prev_short_channel_id, + htlc_id: prev_htlc_id, + incoming_packet_shared_secret: forward_info.incoming_shared_secret, + }; + match channel_state.claimable_htlcs.entry(forward_info.payment_hash) { + hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(prev_hop_data), + hash_map::Entry::Vacant(mut entry) => { entry.insert(vec![prev_hop_data]); }, + }; new_events.push((None, events::Event::PaymentReceived { payment_hash: forward_info.payment_hash, amt: forward_info.amt_to_forward, @@ -1181,10 +1229,10 @@ impl ChannelManager { } } - for failed_forward in failed_forwards.drain(..) { - match failed_forward.2 { - None => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &failed_forward.0, HTLCFailReason::Reason { failure_code: failed_forward.1, data: Vec::new() }), - Some(chan_update) => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &failed_forward.0, HTLCFailReason::Reason { failure_code: failed_forward.1, data: chan_update.encode_with_len() }), + for (htlc_source, payment_hash, failure_code, update) in failed_forwards.drain(..) { + match update { + None => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, HTLCFailReason::Reason { failure_code, data: Vec::new() }), + Some(chan_update) => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, HTLCFailReason::Reason { failure_code, data: chan_update.encode_with_len() }), }; } @@ -1208,7 +1256,15 @@ impl ChannelManager { /// Indicates that the preimage for payment_hash is unknown after a PaymentReceived event. pub fn fail_htlc_backwards(&self, payment_hash: &[u8; 32]) -> bool { - self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), payment_hash, HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: Vec::new() }) + let mut channel_state = Some(self.channel_state.lock().unwrap()); + let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(payment_hash); + if let Some(mut sources) = removed_source { + for htlc_with_hash in sources.drain(..) { + if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); } + self.fail_htlc_backwards_internal(channel_state.take().unwrap(), HTLCSource::PreviousHopData(htlc_with_hash), payment_hash, HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: Vec::new() }); + } + true + } else { false } } /// Fails an HTLC backwards to the sender of it to us. @@ -1217,37 +1273,17 @@ impl ChannelManager { /// to fail and take the channel_state lock for each iteration (as we take ownership and may /// drop it). In other words, no assumptions are made that entries in claimable_htlcs point to /// still-available channels. - fn fail_htlc_backwards_internal(&self, mut channel_state: MutexGuard, payment_hash: &[u8; 32], onion_error: HTLCFailReason) -> bool { - let mut pending_htlc = { - match channel_state.claimable_htlcs.remove(payment_hash) { - Some(pending_htlc) => pending_htlc, - None => return false, - } - }; - - match pending_htlc { - PendingOutboundHTLC::CycledRoute { source_short_channel_id, incoming_packet_shared_secret, route, session_priv } => { - channel_state.claimable_htlcs.insert(payment_hash.clone(), PendingOutboundHTLC::OutboundRoute { - route, - session_priv, - }); - pending_htlc = PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret }; - }, - _ => {} - } - - match pending_htlc { - PendingOutboundHTLC::CycledRoute { .. } => unreachable!(), - PendingOutboundHTLC::OutboundRoute { .. } => { + fn fail_htlc_backwards_internal(&self, mut channel_state: MutexGuard, source: HTLCSource, payment_hash: &[u8; 32], onion_error: HTLCFailReason) { + match source { + HTLCSource::OutboundRoute { .. } => { mem::drop(channel_state); let mut pending_events = self.pending_events.lock().unwrap(); pending_events.push(events::Event::PaymentFailed { payment_hash: payment_hash.clone() }); - false }, - PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret } => { + HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id, htlc_id, incoming_packet_shared_secret }) => { let err_packet = match onion_error { HTLCFailReason::Reason { failure_code, data } => { let packet = ChannelManager::build_failure_packet(&incoming_packet_shared_secret, failure_code, &data[..]).encode(); @@ -1259,17 +1295,17 @@ impl ChannelManager { }; let (node_id, fail_msgs) = { - let chan_id = match channel_state.short_to_id.get(&source_short_channel_id) { + let chan_id = match channel_state.short_to_id.get(&short_channel_id) { Some(chan_id) => chan_id.clone(), - None => return false + None => return }; let chan = channel_state.by_id.get_mut(&chan_id).unwrap(); - match chan.get_update_fail_htlc_and_commit(payment_hash, err_packet) { + match chan.get_update_fail_htlc_and_commit(htlc_id, err_packet) { Ok(msg) => (chan.get_their_node_id(), msg), Err(_e) => { //TODO: Do something with e? - return false; + return; }, } }; @@ -1296,8 +1332,6 @@ impl ChannelManager { }, None => {}, } - - true }, } } @@ -1307,69 +1341,51 @@ impl ChannelManager { /// should probably kick the net layer to go send messages if this returns true! /// May panic if called except in response to a PaymentReceived event. pub fn claim_funds(&self, payment_preimage: [u8; 32]) -> bool { - self.claim_funds_internal(payment_preimage, true) - } - fn claim_funds_internal(&self, payment_preimage: [u8; 32], from_user: bool) -> bool { let mut sha = Sha256::new(); sha.input(&payment_preimage); let mut payment_hash = [0; 32]; sha.result(&mut payment_hash); - let mut channel_state = self.channel_state.lock().unwrap(); - let mut pending_htlc = { - match channel_state.claimable_htlcs.remove(&payment_hash) { - Some(pending_htlc) => pending_htlc, - None => return false, + let mut channel_state = Some(self.channel_state.lock().unwrap()); + let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&payment_hash); + if let Some(mut sources) = removed_source { + for htlc_with_hash in sources.drain(..) { + if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); } + self.claim_funds_internal(channel_state.take().unwrap(), HTLCSource::PreviousHopData(htlc_with_hash), payment_preimage); } - }; - - match pending_htlc { - PendingOutboundHTLC::CycledRoute { source_short_channel_id, incoming_packet_shared_secret, route, session_priv } => { - if from_user { // This was the end hop back to us - pending_htlc = PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret }; - channel_state.claimable_htlcs.insert(payment_hash, PendingOutboundHTLC::OutboundRoute { route, session_priv }); - } else { // This came from the first upstream node - // Bank error in our favor! Maybe we should tell the user this somehow??? - pending_htlc = PendingOutboundHTLC::OutboundRoute { route, session_priv }; - channel_state.claimable_htlcs.insert(payment_hash, PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret }); - } - }, - _ => {}, - } - - match pending_htlc { - PendingOutboundHTLC::CycledRoute { .. } => unreachable!(), - PendingOutboundHTLC::OutboundRoute { .. } => { - if from_user { - panic!("Called claim_funds with a preimage for an outgoing payment. There is nothing we can do with this, and something is seriously wrong if you knew this..."); - } + true + } else { false } + } + fn claim_funds_internal(&self, mut channel_state: MutexGuard, source: HTLCSource, payment_preimage: [u8; 32]) { + match source { + HTLCSource::OutboundRoute { .. } => { mem::drop(channel_state); let mut pending_events = self.pending_events.lock().unwrap(); pending_events.push(events::Event::PaymentSent { payment_preimage }); - false }, - PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, .. } => { + HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id, htlc_id, .. }) => { + //TODO: Delay the claimed_funds relaying just like we do outbound relay! let (node_id, fulfill_msgs) = { - let chan_id = match channel_state.short_to_id.get(&source_short_channel_id) { + let chan_id = match channel_state.short_to_id.get(&short_channel_id) { Some(chan_id) => chan_id.clone(), None => { // TODO: There is probably a channel manager somewhere that needs to // learn the preimage as the channel already hit the chain and that's // why its missing. - return false + return } }; let chan = channel_state.by_id.get_mut(&chan_id).unwrap(); - match chan.get_update_fulfill_htlc_and_commit(payment_preimage) { + match chan.get_update_fulfill_htlc_and_commit(htlc_id, payment_preimage) { Ok(msg) => (chan.get_their_node_id(), msg), Err(_e) => { // TODO: There is probably a channel manager somewhere that needs to // learn the preimage as the channel may be about to hit the chain. //TODO: Do something with e? - return false; + return }, } }; @@ -1394,7 +1410,6 @@ impl ChannelManager { } }); } - true }, } } @@ -1553,7 +1568,7 @@ impl ChannelManager { } fn internal_shutdown(&self, their_node_id: &PublicKey, msg: &msgs::Shutdown) -> Result<(Option, Option), MsgHandleErrInternal> { - let (res, chan_option) = { + let (mut res, chan_option) = { let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = channel_state_lock.borrow_parts(); @@ -1574,9 +1589,9 @@ impl ChannelManager { hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id)) } }; - for payment_hash in res.2 { + for htlc_source in res.2.drain(..) { // 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() }); + self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source.0, &htlc_source.1, HTLCFailReason::Reason { failure_code: 0x4000 | 10, data: Vec::new() }); } if let Some(chan) = chan_option { if let Ok(update) = self.get_channel_update(&chan) { @@ -1639,84 +1654,214 @@ impl ChannelManager { //encrypted with the same key. Its not immediately obvious how to usefully exploit that, //but we should prevent it anyway. - let (mut pending_forward_info, shared_secret, mut channel_state_lock) = self.decode_update_add_htlc_onion(msg); + let (pending_forward_info, mut channel_state_lock) = self.decode_update_add_htlc_onion(msg); let channel_state = channel_state_lock.borrow_parts(); - let claimable_htlcs_entry = channel_state.claimable_htlcs.entry(msg.payment_hash.clone()); - - // We dont correctly handle payments that route through us twice on their way to their - // destination. That's OK since those nodes are probably busted or trying to do network - // mapping through repeated loops. In either case, we want them to stop talking to us, so - // we send permanent_node_failure. - let mut will_forward = false; - if let PendingHTLCStatus::Forward(PendingForwardHTLCInfo { short_channel_id, .. }) = pending_forward_info { - if let &hash_map::Entry::Occupied(ref e) = &claimable_htlcs_entry { - let mut acceptable_cycle = false; - if let &PendingOutboundHTLC::OutboundRoute { .. } = e.get() { - acceptable_cycle = short_channel_id == 0; + match channel_state.by_id.get_mut(&msg.channel_id) { + Some(chan) => { + if chan.get_their_node_id() != *their_node_id { + //TODO: here MsgHandleErrInternal, #153 case + return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id)); } - if !acceptable_cycle { - log_info!(self, "Failed to accept incoming HTLC: Payment looped through us twice"); - 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(&shared_secret.unwrap(), 0x4000 | 0x2000 | 2, &[0;0]), - })); - } else { - will_forward = true; + if !chan.is_usable() { + return Err(MsgHandleErrInternal::from_no_close(HandleError{err: "Channel not yet available for receiving HTLCs", action: Some(msgs::ErrorAction::IgnoreError)})); } - } else { - will_forward = true; - } + chan.update_add_htlc(&msg, pending_forward_info).map_err(|e| MsgHandleErrInternal::from_maybe_close(e)) + }, + None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id)) } + } - let (source_short_channel_id, res) = match channel_state.by_id.get_mut(&msg.channel_id) { + fn internal_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> { + let mut channel_state = self.channel_state.lock().unwrap(); + let htlc_source = match channel_state.by_id.get_mut(&msg.channel_id) { Some(chan) => { if chan.get_their_node_id() != *their_node_id { - //TODO: here MsgHandleErrInternal, #153 case + //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)); } - if !chan.is_usable() { - return Err(MsgHandleErrInternal::from_no_close(HandleError{err: "Channel not yet available for receiving HTLCs", action: Some(msgs::ErrorAction::IgnoreError)})); + chan.update_fulfill_htlc(&msg).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?.clone() + }, + None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id)) + }; + self.claim_funds_internal(channel_state, htlc_source, msg.payment_preimage.clone()); + Ok(()) + } + + fn internal_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result, MsgHandleErrInternal> { + let mut channel_state = self.channel_state.lock().unwrap(); + let htlc_source = match channel_state.by_id.get_mut(&msg.channel_id) { + Some(chan) => { + if chan.get_their_node_id() != *their_node_id { + //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 short_channel_id = chan.get_short_channel_id().unwrap(); - if let PendingHTLCStatus::Forward(ref mut forward_info) = pending_forward_info { - forward_info.prev_short_channel_id = short_channel_id; + chan.update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() }).map_err(|e| MsgHandleErrInternal::from_maybe_close(e)) + }, + None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id)) + }?; + + match htlc_source { + &HTLCSource::OutboundRoute { ref route, ref session_priv, .. } => { + // Handle packed channel/node updates for passing back for the route handler + let mut packet_decrypted = msg.reason.data.clone(); + let mut res = None; + Self::construct_onion_keys_callback(&self.secp_ctx, &route, &session_priv, |shared_secret, _, _, route_hop| { + if res.is_some() { return; } + + let ammag = ChannelManager::gen_ammag_from_shared_secret(&shared_secret); + + let mut decryption_tmp = Vec::with_capacity(packet_decrypted.len()); + decryption_tmp.resize(packet_decrypted.len(), 0); + let mut chacha = ChaCha20::new(&ammag, &[0u8; 8]); + chacha.process(&packet_decrypted, &mut decryption_tmp[..]); + packet_decrypted = decryption_tmp; + + if let Ok(err_packet) = msgs::DecodedOnionErrorPacket::decode(&packet_decrypted) { + if err_packet.failuremsg.len() >= 2 { + let um = ChannelManager::gen_um_from_shared_secret(&shared_secret); + + let mut hmac = Hmac::new(Sha256::new(), &um); + hmac.input(&err_packet.encode()[32..]); + let mut calc_tag = [0u8; 32]; + hmac.raw_result(&mut calc_tag); + if crypto::util::fixed_time_eq(&calc_tag, &err_packet.hmac) { + const UNKNOWN_CHAN: u16 = 0x4000|10; + const TEMP_CHAN_FAILURE: u16 = 0x4000|7; + match byte_utils::slice_to_be16(&err_packet.failuremsg[0..2]) { + TEMP_CHAN_FAILURE => { + if err_packet.failuremsg.len() >= 4 { + let update_len = byte_utils::slice_to_be16(&err_packet.failuremsg[2..4]) as usize; + if err_packet.failuremsg.len() >= 4 + update_len { + if let Ok(chan_update) = msgs::ChannelUpdate::decode(&err_packet.failuremsg[4..4 + update_len]) { + res = Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage { + msg: chan_update, + }); + } + } + } + }, + UNKNOWN_CHAN => { + // No such next-hop. We know this came from the + // current node as the HMAC validated. + res = Some(msgs::HTLCFailChannelUpdate::ChannelClosed { + short_channel_id: route_hop.short_channel_id + }); + }, + _ => {}, //TODO: Enumerate all of these! + } + } + } + } + }).unwrap(); + Ok(res) + }, + _ => { Ok(None) }, + } + } + + fn internal_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), MsgHandleErrInternal> { + let mut channel_state = self.channel_state.lock().unwrap(); + match channel_state.by_id.get_mut(&msg.channel_id) { + Some(chan) => { + if chan.get_their_node_id() != *their_node_id { + //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)); } - (short_channel_id, chan.update_add_htlc(&msg, pending_forward_info).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?) + chan.update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() }).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?; + Ok(()) }, None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id)) + } + } + + fn internal_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option), MsgHandleErrInternal> { + let (revoke_and_ack, commitment_signed, chan_monitor) = { + let mut channel_state = self.channel_state.lock().unwrap(); + match channel_state.by_id.get_mut(&msg.channel_id) { + Some(chan) => { + if chan.get_their_node_id() != *their_node_id { + //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)); + } + chan.commitment_signed(&msg).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))? + }, + None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id)) + } }; + if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { + unimplemented!(); + } - if will_forward { - match claimable_htlcs_entry { - hash_map::Entry::Occupied(mut e) => { - let outbound_route = e.get_mut(); - let (route, session_priv) = match outbound_route { - &mut PendingOutboundHTLC::OutboundRoute { ref route, ref session_priv } => { - (route.clone(), session_priv.clone()) - }, - _ => unreachable!(), - }; - *outbound_route = PendingOutboundHTLC::CycledRoute { - source_short_channel_id, - incoming_packet_shared_secret: shared_secret.unwrap(), - route, - session_priv, - }; + Ok((revoke_and_ack, commitment_signed)) + } + + fn internal_revoke_and_ack(&self, their_node_id: &PublicKey, msg: &msgs::RevokeAndACK) -> Result, MsgHandleErrInternal> { + let ((res, mut pending_forwards, mut pending_failures, chan_monitor), short_channel_id) = { + let mut channel_state = self.channel_state.lock().unwrap(); + match channel_state.by_id.get_mut(&msg.channel_id) { + Some(chan) => { + if chan.get_their_node_id() != *their_node_id { + //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)); + } + (chan.revoke_and_ack(&msg).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?, chan.get_short_channel_id().expect("RAA should only work on a short-id-available channel")) }, - hash_map::Entry::Vacant(e) => { - e.insert(PendingOutboundHTLC::IntermediaryHopData { - source_short_channel_id, - incoming_packet_shared_secret: shared_secret.unwrap(), - }); + None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id)) + } + }; + if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { + unimplemented!(); + } + for failure in pending_failures.drain(..) { + self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), failure.0, &failure.1, failure.2); + } + + let mut forward_event = None; + if !pending_forwards.is_empty() { + let mut channel_state = self.channel_state.lock().unwrap(); + if channel_state.forward_htlcs.is_empty() { + forward_event = Some(Instant::now() + Duration::from_millis(((rng::rand_f32() * 4.0 + 1.0) * MIN_HTLC_RELAY_HOLDING_CELL_MILLIS as f32) as u64)); + channel_state.next_forward = forward_event.unwrap(); + } + for (forward_info, prev_htlc_id) in pending_forwards.drain(..) { + match channel_state.forward_htlcs.entry(forward_info.short_channel_id) { + hash_map::Entry::Occupied(mut entry) => { + entry.get_mut().push(HTLCForwardInfo { prev_short_channel_id: short_channel_id, prev_htlc_id, forward_info }); + }, + hash_map::Entry::Vacant(entry) => { + entry.insert(vec!(HTLCForwardInfo { prev_short_channel_id: short_channel_id, prev_htlc_id, forward_info })); + } } } } + match forward_event { + Some(time) => { + let mut pending_events = self.pending_events.lock().unwrap(); + pending_events.push(events::Event::PendingHTLCsForwardable { + time_forwardable: time + }); + } + None => {}, + } Ok(res) } + fn internal_update_fee(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFee) -> Result<(), MsgHandleErrInternal> { + let mut channel_state = self.channel_state.lock().unwrap(); + match channel_state.by_id.get_mut(&msg.channel_id) { + Some(chan) => { + if chan.get_their_node_id() != *their_node_id { + //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)); + } + chan.update_fee(&*self.fee_estimator, &msg).map_err(|e| MsgHandleErrInternal::from_maybe_close(e)) + }, + None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id)) + } + } + fn internal_announcement_signatures(&self, their_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures) -> Result<(), MsgHandleErrInternal> { let (chan_announcement, chan_update) = { let mut channel_state = self.channel_state.lock().unwrap(); @@ -1951,193 +2096,27 @@ impl ChannelMessageHandler for ChannelManager { } fn handle_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), HandleError> { - //TODO: Delay the claimed_funds relaying just like we do outbound relay! - // Claim funds first, cause we don't really care if the channel we received the message on - // is broken, we may have enough info to get our own money! - self.claim_funds_internal(msg.payment_preimage.clone(), false); - - let mut channel_state = self.channel_state.lock().unwrap(); - match channel_state.by_id.get_mut(&msg.channel_id) { - Some(chan) => { - if chan.get_their_node_id() != *their_node_id { - return Err(HandleError{err: "Got a message for a channel from the wrong node!", action: None}) - } - chan.update_fulfill_htlc(&msg) - }, - None => return Err(HandleError{err: "Failed to find corresponding channel", action: None}) - } + handle_error!(self, self.internal_update_fulfill_htlc(their_node_id, msg), their_node_id) } fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result, HandleError> { - let mut channel_state = self.channel_state.lock().unwrap(); - let payment_hash = match channel_state.by_id.get_mut(&msg.channel_id) { - Some(chan) => { - if chan.get_their_node_id() != *their_node_id { - return Err(HandleError{err: "Got a message for a channel from the wrong node!", action: None}) - } - chan.update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() }) - }, - None => return Err(HandleError{err: "Failed to find corresponding channel", action: None}) - }?; - - if let Some(pending_htlc) = channel_state.claimable_htlcs.get(&payment_hash) { - match pending_htlc { - &PendingOutboundHTLC::OutboundRoute { ref route, ref session_priv } => { - // Handle packed channel/node updates for passing back for the route handler - let mut packet_decrypted = msg.reason.data.clone(); - let mut res = None; - Self::construct_onion_keys_callback(&self.secp_ctx, &route, &session_priv, |shared_secret, _, _, route_hop| { - if res.is_some() { return; } - - let ammag = ChannelManager::gen_ammag_from_shared_secret(&shared_secret); - - let mut decryption_tmp = Vec::with_capacity(packet_decrypted.len()); - decryption_tmp.resize(packet_decrypted.len(), 0); - let mut chacha = ChaCha20::new(&ammag, &[0u8; 8]); - chacha.process(&packet_decrypted, &mut decryption_tmp[..]); - packet_decrypted = decryption_tmp; - - if let Ok(err_packet) = msgs::DecodedOnionErrorPacket::decode(&packet_decrypted) { - if err_packet.failuremsg.len() >= 2 { - let um = ChannelManager::gen_um_from_shared_secret(&shared_secret); - - let mut hmac = Hmac::new(Sha256::new(), &um); - hmac.input(&err_packet.encode()[32..]); - let mut calc_tag = [0u8; 32]; - hmac.raw_result(&mut calc_tag); - if crypto::util::fixed_time_eq(&calc_tag, &err_packet.hmac) { - const UNKNOWN_CHAN: u16 = 0x4000|10; - const TEMP_CHAN_FAILURE: u16 = 0x4000|7; - match byte_utils::slice_to_be16(&err_packet.failuremsg[0..2]) { - TEMP_CHAN_FAILURE => { - if err_packet.failuremsg.len() >= 4 { - let update_len = byte_utils::slice_to_be16(&err_packet.failuremsg[2..4]) as usize; - if err_packet.failuremsg.len() >= 4 + update_len { - if let Ok(chan_update) = msgs::ChannelUpdate::decode(&err_packet.failuremsg[4..4 + update_len]) { - res = Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage { - msg: chan_update, - }); - } - } - } - }, - UNKNOWN_CHAN => { - // No such next-hop. We know this came from the - // current node as the HMAC validated. - res = Some(msgs::HTLCFailChannelUpdate::ChannelClosed { - short_channel_id: route_hop.short_channel_id - }); - }, - _ => {}, //TODO: Enumerate all of these! - } - } - } - } - }).unwrap(); - Ok(res) - }, - _ => { Ok(None) }, - } - } else { - Ok(None) - } + handle_error!(self, self.internal_update_fail_htlc(their_node_id, msg), their_node_id) } fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), HandleError> { - let mut channel_state = self.channel_state.lock().unwrap(); - match channel_state.by_id.get_mut(&msg.channel_id) { - Some(chan) => { - if chan.get_their_node_id() != *their_node_id { - return Err(HandleError{err: "Got a message for a channel from the wrong node!", action: None}) - } - chan.update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() }) - }, - None => return Err(HandleError{err: "Failed to find corresponding channel", action: None}) - } + handle_error!(self, self.internal_update_fail_malformed_htlc(their_node_id, msg), their_node_id) } fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option), HandleError> { - let (revoke_and_ack, commitment_signed, chan_monitor) = { - let mut channel_state = self.channel_state.lock().unwrap(); - match channel_state.by_id.get_mut(&msg.channel_id) { - Some(chan) => { - if chan.get_their_node_id() != *their_node_id { - return Err(HandleError{err: "Got a message for a channel from the wrong node!", action: None}) - } - chan.commitment_signed(&msg)? - }, - None => return Err(HandleError{err: "Failed to find corresponding channel", action: None}) - } - }; - if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { - unimplemented!(); - } - - Ok((revoke_and_ack, commitment_signed)) + handle_error!(self, self.internal_commitment_signed(their_node_id, msg), their_node_id) } fn handle_revoke_and_ack(&self, their_node_id: &PublicKey, msg: &msgs::RevokeAndACK) -> Result, HandleError> { - let (res, mut pending_forwards, mut pending_failures, chan_monitor) = { - let mut channel_state = self.channel_state.lock().unwrap(); - match channel_state.by_id.get_mut(&msg.channel_id) { - Some(chan) => { - if chan.get_their_node_id() != *their_node_id { - return Err(HandleError{err: "Got a message for a channel from the wrong node!", action: None}) - } - chan.revoke_and_ack(&msg)? - }, - None => return Err(HandleError{err: "Failed to find corresponding channel", action: None}) - } - }; - if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) { - unimplemented!(); - } - for failure in pending_failures.drain(..) { - self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &failure.0, failure.1); - } - - let mut forward_event = None; - if !pending_forwards.is_empty() { - let mut channel_state = self.channel_state.lock().unwrap(); - if channel_state.forward_htlcs.is_empty() { - forward_event = Some(Instant::now() + Duration::from_millis(((rng::rand_f32() * 4.0 + 1.0) * MIN_HTLC_RELAY_HOLDING_CELL_MILLIS as f32) as u64)); - channel_state.next_forward = forward_event.unwrap(); - } - for forward_info in pending_forwards.drain(..) { - match channel_state.forward_htlcs.entry(forward_info.short_channel_id) { - hash_map::Entry::Occupied(mut entry) => { - entry.get_mut().push(forward_info); - }, - hash_map::Entry::Vacant(entry) => { - entry.insert(vec!(forward_info)); - } - } - } - } - match forward_event { - Some(time) => { - let mut pending_events = self.pending_events.lock().unwrap(); - pending_events.push(events::Event::PendingHTLCsForwardable { - time_forwardable: time - }); - } - None => {}, - } - - Ok(res) + handle_error!(self, self.internal_revoke_and_ack(their_node_id, msg), their_node_id) } fn handle_update_fee(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFee) -> Result<(), HandleError> { - let mut channel_state = self.channel_state.lock().unwrap(); - match channel_state.by_id.get_mut(&msg.channel_id) { - Some(chan) => { - if chan.get_their_node_id() != *their_node_id { - return Err(HandleError{err: "Got a message for a channel from the wrong node!", action: None}) - } - chan.update_fee(&*self.fee_estimator, &msg) - }, - None => return Err(HandleError{err: "Failed to find corresponding channel", action: None}) - } + handle_error!(self, self.internal_update_fee(their_node_id, msg), their_node_id) } fn handle_announcement_signatures(&self, their_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures) -> Result<(), HandleError> { @@ -2233,8 +2212,10 @@ mod tests { use rand::{thread_rng,Rng}; + use std::cell::RefCell; use std::collections::HashMap; use std::default::Default; + use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::time::Instant; use std::mem; @@ -2405,9 +2386,10 @@ mod tests { chan_monitor: Arc, node: Arc, router: Router, + network_payment_count: Rc>, + network_chan_count: Rc>, } - static mut CHAN_COUNT: u32 = 0; 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, 10001, 42).unwrap(); @@ -2423,7 +2405,7 @@ mod tests { node_a.node.handle_accept_channel(&node_b.node.get_our_node_id(), &accept_chan).unwrap(); - let chan_id = unsafe { CHAN_COUNT }; + let chan_id = *node_a.network_chan_count.borrow(); let tx; let funding_output; @@ -2529,9 +2511,7 @@ mod tests { _ => panic!("Unexpected event"), }; - unsafe { - CHAN_COUNT += 1; - } + *node_a.network_chan_count.borrow_mut() += 1; ((*announcement).clone(), (*as_update).clone(), (*bs_update).clone(), channel_id, tx) } @@ -2633,10 +2613,9 @@ mod tests { } } - static mut PAYMENT_COUNT: u8 = 0; fn send_along_route(origin_node: &Node, route: Route, expected_route: &[&Node], recv_value: u64) -> ([u8; 32], [u8; 32]) { - let our_payment_preimage = unsafe { [PAYMENT_COUNT; 32] }; - unsafe { PAYMENT_COUNT += 1 }; + let our_payment_preimage = [*origin_node.network_payment_count.borrow(); 32]; + *origin_node.network_payment_count.borrow_mut() += 1; let our_payment_hash = { let mut sha = Sha256::new(); sha.input(&our_payment_preimage[..]); @@ -2828,8 +2807,8 @@ mod tests { assert_eq!(hop.pubkey, node.node.get_our_node_id()); } - let our_payment_preimage = unsafe { [PAYMENT_COUNT; 32] }; - unsafe { PAYMENT_COUNT += 1 }; + let our_payment_preimage = [*origin_node.network_payment_count.borrow(); 32]; + *origin_node.network_payment_count.borrow_mut() += 1; let our_payment_hash = { let mut sha = Sha256::new(); sha.input(&our_payment_preimage[..]); @@ -2940,6 +2919,9 @@ mod tests { let secp_ctx = Secp256k1::new(); let logger: Arc = Arc::new(test_utils::TestLogger::new()); + let chan_count = Rc::new(RefCell::new(0)); + let payment_count = Rc::new(RefCell::new(0)); + for _ in 0..node_count { let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }); let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger))); @@ -2952,7 +2934,10 @@ mod tests { }; let node = ChannelManager::new(node_id.clone(), 0, true, Network::Testnet, feeest.clone(), chan_monitor.clone(), chain_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger)).unwrap(); let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id), chain_monitor.clone(), Arc::clone(&logger)); - nodes.push(Node { chain_monitor, tx_broadcaster, chan_monitor, node, router }); + nodes.push(Node { chain_monitor, tx_broadcaster, chan_monitor, node, router, + network_payment_count: payment_count.clone(), + network_chan_count: chan_count.clone(), + }); } nodes @@ -3307,7 +3292,8 @@ mod tests { nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); { let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); - assert_eq!(node_txn.len(), 2); + assert_eq!(node_txn.len(), 3); + assert_eq!(node_txn.pop().unwrap(), node_txn[0]); // An outpoint registration will result in a 2nd block_connected assert_eq!(node_txn[0].input.len(), 1); let mut funding_tx_map = HashMap::new();