use chain;
use chain::{Confirm, Watch, BestBlock};
-use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
+use chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, ChannelMonitorUpdateErr, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent, CLOSED_CHANNEL_UPDATE_ID};
use chain::transaction::{OutPoint, TransactionData};
// Since this struct is returned in `list_channels` methods, expose it here in case users want to
#[cfg(any(test, feature = "allow_wallclock_use"))]
use std::time::Instant;
use core::ops::Deref;
-use bitcoin::hashes::hex::ToHex;
// We hold various information about HTLC relay in the HTLC objects in Channel itself:
//
self.process_background_events();
}
- /// If a peer is disconnected we mark any channels with that peer as 'disabled'.
- /// After some time, if channels are still disabled we need to broadcast a ChannelUpdate
- /// to inform the network about the uselessness of these channels.
+ fn update_channel_fee(&self, short_to_id: &mut HashMap<u64, [u8; 32]>, pending_msg_events: &mut Vec<events::MessageSendEvent>, chan_id: &[u8; 32], chan: &mut Channel<Signer>, new_feerate: u32) -> (bool, NotifyOption, Result<(), MsgHandleErrInternal>) {
+ if !chan.is_outbound() { return (true, NotifyOption::SkipPersist, Ok(())); }
+ // If the feerate has decreased by less than half, don't bother
+ if new_feerate <= chan.get_feerate() && new_feerate * 2 > chan.get_feerate() {
+ log_trace!(self.logger, "Channel {} does not qualify for a feerate change from {} to {}.",
+ log_bytes!(chan_id[..]), chan.get_feerate(), new_feerate);
+ return (true, NotifyOption::SkipPersist, Ok(()));
+ }
+ if !chan.is_live() {
+ log_trace!(self.logger, "Channel {} does not qualify for a feerate change from {} to {} as it cannot currently be updated (probably the peer is disconnected).",
+ log_bytes!(chan_id[..]), chan.get_feerate(), new_feerate);
+ return (true, NotifyOption::SkipPersist, Ok(()));
+ }
+ log_trace!(self.logger, "Channel {} qualifies for a feerate change from {} to {}.",
+ log_bytes!(chan_id[..]), chan.get_feerate(), new_feerate);
+
+ let mut retain_channel = true;
+ let res = match chan.send_update_fee_and_commit(new_feerate, &self.logger) {
+ Ok(res) => Ok(res),
+ Err(e) => {
+ let (drop, res) = convert_chan_err!(self, e, short_to_id, chan, chan_id);
+ if drop { retain_channel = false; }
+ Err(res)
+ }
+ };
+ let ret_err = match res {
+ Ok(Some((update_fee, commitment_signed, monitor_update))) => {
+ if let Err(e) = self.chain_monitor.update_channel(chan.get_funding_txo().unwrap(), monitor_update) {
+ let (res, drop) = handle_monitor_err!(self, e, short_to_id, chan, RAACommitmentOrder::CommitmentFirst, false, true, Vec::new(), Vec::new(), chan_id);
+ if drop { retain_channel = false; }
+ res
+ } else {
+ pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
+ node_id: chan.get_counterparty_node_id(),
+ updates: msgs::CommitmentUpdate {
+ update_add_htlcs: Vec::new(),
+ update_fulfill_htlcs: Vec::new(),
+ update_fail_htlcs: Vec::new(),
+ update_fail_malformed_htlcs: Vec::new(),
+ update_fee: Some(update_fee),
+ commitment_signed,
+ },
+ });
+ Ok(())
+ }
+ },
+ Ok(None) => Ok(()),
+ Err(e) => Err(e),
+ };
+ (retain_channel, NotifyOption::DoPersist, ret_err)
+ }
+
+ /// Performs actions which should happen on startup and roughly once per minute thereafter.
///
- /// This method handles all the details, and must be called roughly once per minute.
+ /// This currently includes:
+ /// * Increasing or decreasing the on-chain feerate estimates for our outbound channels,
+ /// * Broadcasting `ChannelUpdate` messages if we've been disconnected from our peer for more
+ /// than a minute, informing the network that they should no longer attempt to route over
+ /// the channel.
///
- /// Note that in some rare cases this may generate a `chain::Watch::update_channel` call.
+ /// Note that this may cause reentrancy through `chain::Watch::update_channel` calls or feerate
+ /// estimate fetches.
pub fn timer_tick_occurred(&self) {
PersistenceNotifierGuard::optionally_notify(&self.total_consistency_lock, &self.persistence_notifier, || {
let mut should_persist = NotifyOption::SkipPersist;
if self.process_background_events() { should_persist = NotifyOption::DoPersist; }
- let mut channel_state_lock = self.channel_state.lock().unwrap();
- let channel_state = &mut *channel_state_lock;
- for (_, chan) in channel_state.by_id.iter_mut() {
- match chan.channel_update_status() {
- ChannelUpdateStatus::Enabled if !chan.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::DisabledStaged),
- ChannelUpdateStatus::Disabled if chan.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::EnabledStaged),
- ChannelUpdateStatus::DisabledStaged if chan.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::Enabled),
- ChannelUpdateStatus::EnabledStaged if !chan.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::Disabled),
- ChannelUpdateStatus::DisabledStaged if !chan.is_live() => {
- if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
- channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
- msg: update
- });
- }
- should_persist = NotifyOption::DoPersist;
- chan.set_channel_update_status(ChannelUpdateStatus::Disabled);
- },
- ChannelUpdateStatus::EnabledStaged if chan.is_live() => {
- if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
- channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
- msg: update
- });
- }
- should_persist = NotifyOption::DoPersist;
- chan.set_channel_update_status(ChannelUpdateStatus::Enabled);
- },
- _ => {},
- }
+ let new_feerate = self.fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
+
+ let mut handle_errors = Vec::new();
+ {
+ let mut channel_state_lock = self.channel_state.lock().unwrap();
+ let channel_state = &mut *channel_state_lock;
+ let pending_msg_events = &mut channel_state.pending_msg_events;
+ let short_to_id = &mut channel_state.short_to_id;
+ channel_state.by_id.retain(|chan_id, chan| {
+ match chan.channel_update_status() {
+ ChannelUpdateStatus::Enabled if !chan.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::DisabledStaged),
+ ChannelUpdateStatus::Disabled if chan.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::EnabledStaged),
+ ChannelUpdateStatus::DisabledStaged if chan.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::Enabled),
+ ChannelUpdateStatus::EnabledStaged if !chan.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::Disabled),
+ ChannelUpdateStatus::DisabledStaged if !chan.is_live() => {
+ if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
+ pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
+ msg: update
+ });
+ }
+ should_persist = NotifyOption::DoPersist;
+ chan.set_channel_update_status(ChannelUpdateStatus::Disabled);
+ },
+ ChannelUpdateStatus::EnabledStaged if chan.is_live() => {
+ if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
+ pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
+ msg: update
+ });
+ }
+ should_persist = NotifyOption::DoPersist;
+ chan.set_channel_update_status(ChannelUpdateStatus::Enabled);
+ },
+ _ => {},
+ }
+
+ let counterparty_node_id = chan.get_counterparty_node_id();
+ let (retain_channel, chan_needs_persist, err) = self.update_channel_fee(short_to_id, pending_msg_events, chan_id, chan, new_feerate);
+ if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; }
+ if err.is_err() {
+ handle_errors.push((err, counterparty_node_id));
+ }
+ retain_channel
+ });
+ }
+
+ for (err, counterparty_node_id) in handle_errors.drain(..) {
+ let _ = handle_error!(self, err, counterparty_node_id);
}
should_persist
Ok(())
}
- /// Begin Update fee process. Allowed only on an outbound channel.
- /// If successful, will generate a UpdateHTLCs event, so you should probably poll
- /// PeerManager::process_events afterwards.
- /// Note: This API is likely to change!
- /// (C-not exported) Cause its doc(hidden) anyway
- #[doc(hidden)]
- pub fn update_fee(&self, channel_id: [u8;32], feerate_per_kw: u32) -> Result<(), APIError> {
- let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
- let counterparty_node_id;
- let err: Result<(), _> = loop {
- let mut channel_state_lock = self.channel_state.lock().unwrap();
- let channel_state = &mut *channel_state_lock;
-
- match channel_state.by_id.entry(channel_id) {
- hash_map::Entry::Vacant(_) => return Err(APIError::APIMisuseError{err: format!("Failed to find corresponding channel for id {}", channel_id.to_hex())}),
- hash_map::Entry::Occupied(mut chan) => {
- if !chan.get().is_outbound() {
- return Err(APIError::APIMisuseError{err: "update_fee cannot be sent for an inbound channel".to_owned()});
- }
- if chan.get().is_awaiting_monitor_update() {
- return Err(APIError::MonitorUpdateFailed);
- }
- if !chan.get().is_live() {
- return Err(APIError::ChannelUnavailable{err: "Channel is either not yet fully established or peer is currently disconnected".to_owned()});
- }
- counterparty_node_id = chan.get().get_counterparty_node_id();
- if let Some((update_fee, commitment_signed, monitor_update)) =
- break_chan_entry!(self, chan.get_mut().send_update_fee_and_commit(feerate_per_kw, &self.logger), channel_state, chan)
- {
- if let Err(_e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
- unimplemented!();
- }
- log_debug!(self.logger, "Updating fee resulted in a commitment_signed for channel {}", log_bytes!(chan.get().channel_id()));
- channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
- node_id: chan.get().get_counterparty_node_id(),
- updates: msgs::CommitmentUpdate {
- update_add_htlcs: Vec::new(),
- update_fulfill_htlcs: Vec::new(),
- update_fail_htlcs: Vec::new(),
- update_fail_malformed_htlcs: Vec::new(),
- update_fee: Some(update_fee),
- commitment_signed,
- },
- });
- }
- },
- }
- return Ok(())
- };
-
- match handle_error!(self, err, counterparty_node_id) {
- Ok(_) => unreachable!(),
- Err(e) => { Err(APIError::APIMisuseError { err: e.err })}
- }
- }
-
/// Process pending events from the `chain::Watch`, returning whether any events were processed.
fn process_pending_monitor_events(&self) -> bool {
let mut failed_channels = Vec::new();
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let channel_id = chan.2;
// balancing
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
// (6) RAA is delivered ->
// First nodes[0] generates an update_fee
- nodes[0].node.update_fee(channel_id, get_feerate!(nodes[0], channel_id) + 20).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock += 20;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let channel_id = chan.2;
+ create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
// 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], channel_id) + 20).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock += 20;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let channel_id = chan.2;
+ create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
// A B
// update_fee/commitment_signed ->
// revoke_and_ack ->
// First nodes[0] generates an update_fee
- let initial_feerate = get_feerate!(nodes[0], channel_id);
- nodes[0].node.update_fee(channel_id, initial_feerate + 20).unwrap();
+ let initial_feerate;
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ initial_feerate = *feerate_lock;
+ *feerate_lock = initial_feerate + 20;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
// nodes[0] is awaiting a revoke from nodes[1] before it will create a new commitment
// transaction:
- nodes[0].node.update_fee(channel_id, initial_feerate + 40).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock = initial_feerate + 40;
+ }
+ nodes[0].node.timer_tick_occurred();
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
- let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let channel_id = chan.2;
+ create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let feerate = get_feerate!(nodes[0], channel_id);
- nodes[0].node.update_fee(channel_id, feerate+25).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock += 25;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
let channel_id = chan.2;
let feerate = 260;
- nodes[0].node.update_fee(channel_id, feerate).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock = feerate;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let update_msg = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
//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();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock = feerate + 2;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let update2_msg = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let channel_id = chan.2;
let logger = test_utils::TestLogger::new();
// balancing
send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
- let feerate = get_feerate!(nodes[0], channel_id);
- nodes[0].node.update_fee(channel_id, feerate+20).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock += 20;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
// revoke_and_ack ->
// Create and deliver (1)...
- let feerate = get_feerate!(nodes[0], channel_id);
- nodes[0].node.update_fee(channel_id, feerate+20).unwrap();
+ let feerate;
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ feerate = *feerate_lock;
+ *feerate_lock = feerate + 20;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
check_added_monitors!(nodes[0], 1);
// Create and deliver (4)...
- nodes[0].node.update_fee(channel_id, feerate+30).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock = feerate + 30;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events_0.len(), 1);
// First nodes[0] generates an update_fee, setting the channel's
// pending_update_fee.
- nodes[0].node.update_fee(chan.2, get_feerate!(nodes[0], chan.2) + 20).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock += 20;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events = nodes[0].node.get_and_clear_pending_msg_events();
// First nodes[0] generates an update_fee, setting the channel's
// pending_update_fee.
- nodes[0].node.update_fee(chan.2, get_feerate!(nodes[0], chan.2) + 200).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock += 200;
+ }
+ nodes[0].node.timer_tick_occurred();
check_added_monitors!(nodes[0], 1);
let events = nodes[0].node.get_and_clear_pending_msg_events();
// First nodes[1] generates an update_fee, setting the channel's
// pending_update_fee.
- nodes[1].node.update_fee(chan_1_2.2, get_feerate!(nodes[1], chan_1_2.2) + 20).unwrap();
+ {
+ let mut feerate_lock = chanmon_cfgs[1].fee_estimator.sat_per_kw.lock().unwrap();
+ *feerate_lock += 20;
+ }
+ nodes[1].node.timer_tick_occurred();
check_added_monitors!(nodes[1], 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();