mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 23:08:36 +01:00
Merge pull request #985 from TheBlueMatt/2021-06-auto-chan-fee-updates
Automatically Update fees on outbound channels
This commit is contained in:
commit
a369f9e64e
9 changed files with 674 additions and 219 deletions
|
@ -5,5 +5,5 @@ echo Testing $(git log -1 --oneline)
|
|||
cargo check
|
||||
cargo doc
|
||||
cargo doc --document-private-items
|
||||
cd fuzz && cargo check --features=stdin_fuzz
|
||||
cd fuzz && RUSTFLAGS="--cfg=fuzzing" cargo check --features=stdin_fuzz
|
||||
cd ../lightning && cargo check --no-default-features --features=no-std
|
||||
|
|
|
@ -37,6 +37,7 @@ use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget,
|
|||
use lightning::chain::keysinterface::{KeysInterface, InMemorySigner};
|
||||
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
|
||||
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs};
|
||||
use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
|
||||
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
|
||||
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init};
|
||||
use lightning::ln::script::ShutdownScript;
|
||||
|
@ -58,16 +59,27 @@ use bitcoin::secp256k1::recovery::RecoverableSignature;
|
|||
use bitcoin::secp256k1::Secp256k1;
|
||||
|
||||
use std::mem;
|
||||
use std::cmp::Ordering;
|
||||
use std::cmp::{self, Ordering};
|
||||
use std::collections::{HashSet, hash_map, HashMap};
|
||||
use std::sync::{Arc,Mutex};
|
||||
use std::sync::atomic;
|
||||
use std::io::Cursor;
|
||||
|
||||
struct FuzzEstimator {}
|
||||
const MAX_FEE: u32 = 10_000;
|
||||
struct FuzzEstimator {
|
||||
ret_val: atomic::AtomicU32,
|
||||
}
|
||||
impl FeeEstimator for FuzzEstimator {
|
||||
fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u32 {
|
||||
253
|
||||
fn get_est_sat_per_1000_weight(&self, conf_target: ConfirmationTarget) -> u32 {
|
||||
// We force-close channels if our counterparty sends us a feerate which is a small multiple
|
||||
// of our HighPriority fee estimate or smaller than our Background fee estimate. Thus, we
|
||||
// always return a HighPriority feerate here which is >= the maximum Normal feerate and a
|
||||
// Background feerate which is <= the minimum Normal feerate.
|
||||
match conf_target {
|
||||
ConfirmationTarget::HighPriority => MAX_FEE,
|
||||
ConfirmationTarget::Background => 253,
|
||||
ConfirmationTarget::Normal => cmp::min(self.ret_val.load(atomic::Ordering::Acquire), MAX_FEE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +144,7 @@ impl chain::Watch<EnforcingSigner> for TestChainMonitor {
|
|||
};
|
||||
let deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor<EnforcingSigner>)>::
|
||||
read(&mut Cursor::new(&map_entry.get().1), &*self.keys).unwrap().1;
|
||||
deserialized_monitor.update_monitor(&update, &&TestBroadcaster{}, &&FuzzEstimator{}, &self.logger).unwrap();
|
||||
deserialized_monitor.update_monitor(&update, &&TestBroadcaster{}, &&FuzzEstimator { ret_val: atomic::AtomicU32::new(253) }, &self.logger).unwrap();
|
||||
let mut ser = VecWriter(Vec::new());
|
||||
deserialized_monitor.write(&mut ser).unwrap();
|
||||
map_entry.insert((update.update_id, ser.0));
|
||||
|
@ -334,14 +346,13 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
|
|||
|
||||
#[inline]
|
||||
pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
||||
let fee_est = Arc::new(FuzzEstimator{});
|
||||
let broadcast = Arc::new(TestBroadcaster{});
|
||||
|
||||
macro_rules! make_node {
|
||||
($node_id: expr) => { {
|
||||
($node_id: expr, $fee_estimator: expr) => { {
|
||||
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
|
||||
let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU32::new(0), revoked_commitments: Mutex::new(HashMap::new()) });
|
||||
let monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), fee_est.clone(), Arc::new(TestPersister{}), Arc::clone(&keys_manager)));
|
||||
let monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), $fee_estimator.clone(), Arc::new(TestPersister{}), Arc::clone(&keys_manager)));
|
||||
|
||||
let mut config = UserConfig::default();
|
||||
config.channel_options.forwarding_fee_proportional_millionths = 0;
|
||||
|
@ -351,16 +362,16 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
network,
|
||||
best_block: BestBlock::from_genesis(network),
|
||||
};
|
||||
(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params),
|
||||
(ChannelManager::new($fee_estimator.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params),
|
||||
monitor, keys_manager)
|
||||
} }
|
||||
}
|
||||
|
||||
macro_rules! reload_node {
|
||||
($ser: expr, $node_id: expr, $old_monitors: expr, $keys_manager: expr) => { {
|
||||
($ser: expr, $node_id: expr, $old_monitors: expr, $keys_manager: expr, $fee_estimator: expr) => { {
|
||||
let keys_manager = Arc::clone(& $keys_manager);
|
||||
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
|
||||
let chain_monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), fee_est.clone(), Arc::new(TestPersister{}), Arc::clone(& $keys_manager)));
|
||||
let chain_monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), $fee_estimator.clone(), Arc::new(TestPersister{}), Arc::clone(& $keys_manager)));
|
||||
|
||||
let mut config = UserConfig::default();
|
||||
config.channel_options.forwarding_fee_proportional_millionths = 0;
|
||||
|
@ -379,7 +390,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
|
||||
let read_args = ChannelManagerReadArgs {
|
||||
keys_manager,
|
||||
fee_estimator: fee_est.clone(),
|
||||
fee_estimator: $fee_estimator.clone(),
|
||||
chain_monitor: chain_monitor.clone(),
|
||||
tx_broadcaster: broadcast.clone(),
|
||||
logger,
|
||||
|
@ -497,11 +508,18 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
} }
|
||||
}
|
||||
|
||||
let fee_est_a = Arc::new(FuzzEstimator { ret_val: atomic::AtomicU32::new(253) });
|
||||
let mut last_htlc_clear_fee_a = 253;
|
||||
let fee_est_b = Arc::new(FuzzEstimator { ret_val: atomic::AtomicU32::new(253) });
|
||||
let mut last_htlc_clear_fee_b = 253;
|
||||
let fee_est_c = Arc::new(FuzzEstimator { ret_val: atomic::AtomicU32::new(253) });
|
||||
let mut last_htlc_clear_fee_c = 253;
|
||||
|
||||
// 3 nodes is enough to hit all the possible cases, notably unknown-source-unknown-dest
|
||||
// forwarding.
|
||||
let (node_a, mut monitor_a, keys_manager_a) = make_node!(0);
|
||||
let (node_b, mut monitor_b, keys_manager_b) = make_node!(1);
|
||||
let (node_c, mut monitor_c, keys_manager_c) = make_node!(2);
|
||||
let (node_a, mut monitor_a, keys_manager_a) = make_node!(0, fee_est_a);
|
||||
let (node_b, mut monitor_b, keys_manager_b) = make_node!(1, fee_est_b);
|
||||
let (node_c, mut monitor_c, keys_manager_c) = make_node!(2, fee_est_c);
|
||||
|
||||
let mut nodes = [node_a, node_b, node_c];
|
||||
|
||||
|
@ -637,10 +655,10 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
had_events = true;
|
||||
match event {
|
||||
events::MessageSendEvent::UpdateHTLCs { node_id, updates: CommitmentUpdate { update_add_htlcs, update_fail_htlcs, update_fulfill_htlcs, update_fail_malformed_htlcs, update_fee, commitment_signed } } => {
|
||||
for dest in nodes.iter() {
|
||||
for (idx, dest) in nodes.iter().enumerate() {
|
||||
if dest.get_our_node_id() == node_id {
|
||||
assert!(update_fee.is_none());
|
||||
for update_add in update_add_htlcs.iter() {
|
||||
out.locked_write(format!("Delivering update_add_htlc to node {}.\n", idx).as_bytes());
|
||||
if !$corrupt_forward {
|
||||
dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), update_add);
|
||||
} else {
|
||||
|
@ -655,14 +673,21 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
}
|
||||
}
|
||||
for update_fulfill in update_fulfill_htlcs.iter() {
|
||||
out.locked_write(format!("Delivering update_fulfill_htlc to node {}.\n", idx).as_bytes());
|
||||
dest.handle_update_fulfill_htlc(&nodes[$node].get_our_node_id(), update_fulfill);
|
||||
}
|
||||
for update_fail in update_fail_htlcs.iter() {
|
||||
out.locked_write(format!("Delivering update_fail_htlc to node {}.\n", idx).as_bytes());
|
||||
dest.handle_update_fail_htlc(&nodes[$node].get_our_node_id(), update_fail);
|
||||
}
|
||||
for update_fail_malformed in update_fail_malformed_htlcs.iter() {
|
||||
out.locked_write(format!("Delivering update_fail_malformed_htlc to node {}.\n", idx).as_bytes());
|
||||
dest.handle_update_fail_malformed_htlc(&nodes[$node].get_our_node_id(), update_fail_malformed);
|
||||
}
|
||||
if let Some(msg) = update_fee {
|
||||
out.locked_write(format!("Delivering update_fee to node {}.\n", idx).as_bytes());
|
||||
dest.handle_update_fee(&nodes[$node].get_our_node_id(), &msg);
|
||||
}
|
||||
let processed_change = !update_add_htlcs.is_empty() || !update_fulfill_htlcs.is_empty() ||
|
||||
!update_fail_htlcs.is_empty() || !update_fail_malformed_htlcs.is_empty();
|
||||
if $limit_events != ProcessMessages::AllMessages && processed_change {
|
||||
|
@ -677,21 +702,24 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
} });
|
||||
break;
|
||||
}
|
||||
out.locked_write(format!("Delivering commitment_signed to node {}.\n", idx).as_bytes());
|
||||
dest.handle_commitment_signed(&nodes[$node].get_our_node_id(), &commitment_signed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
events::MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
|
||||
for dest in nodes.iter() {
|
||||
for (idx, dest) in nodes.iter().enumerate() {
|
||||
if dest.get_our_node_id() == *node_id {
|
||||
out.locked_write(format!("Delivering revoke_and_ack to node {}.\n", idx).as_bytes());
|
||||
dest.handle_revoke_and_ack(&nodes[$node].get_our_node_id(), msg);
|
||||
}
|
||||
}
|
||||
},
|
||||
events::MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } => {
|
||||
for dest in nodes.iter() {
|
||||
for (idx, dest) in nodes.iter().enumerate() {
|
||||
if dest.get_our_node_id() == *node_id {
|
||||
out.locked_write(format!("Delivering channel_reestablish to node {}.\n", idx).as_bytes());
|
||||
dest.handle_channel_reestablish(&nodes[$node].get_our_node_id(), msg);
|
||||
}
|
||||
}
|
||||
|
@ -824,7 +852,9 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
} }
|
||||
}
|
||||
|
||||
match get_slice!(1)[0] {
|
||||
let v = get_slice!(1)[0];
|
||||
out.locked_write(format!("READ A BYTE! HANDLING INPUT {:x}...........\n", v).as_bytes());
|
||||
match v {
|
||||
// In general, we keep related message groups close together in binary form, allowing
|
||||
// bit-twiddling mutations to have similar effects. This is probably overkill, but no
|
||||
// harm in doing so.
|
||||
|
@ -928,7 +958,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
node_a_ser.0.clear();
|
||||
nodes[0].write(&mut node_a_ser).unwrap();
|
||||
}
|
||||
let (new_node_a, new_monitor_a) = reload_node!(node_a_ser, 0, monitor_a, keys_manager_a);
|
||||
let (new_node_a, new_monitor_a) = reload_node!(node_a_ser, 0, monitor_a, keys_manager_a, fee_est_a);
|
||||
nodes[0] = new_node_a;
|
||||
monitor_a = new_monitor_a;
|
||||
},
|
||||
|
@ -947,7 +977,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
bc_events.clear();
|
||||
cb_events.clear();
|
||||
}
|
||||
let (new_node_b, new_monitor_b) = reload_node!(node_b_ser, 1, monitor_b, keys_manager_b);
|
||||
let (new_node_b, new_monitor_b) = reload_node!(node_b_ser, 1, monitor_b, keys_manager_b, fee_est_b);
|
||||
nodes[1] = new_node_b;
|
||||
monitor_b = new_monitor_b;
|
||||
},
|
||||
|
@ -961,7 +991,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
node_c_ser.0.clear();
|
||||
nodes[2].write(&mut node_c_ser).unwrap();
|
||||
}
|
||||
let (new_node_c, new_monitor_c) = reload_node!(node_c_ser, 2, monitor_c, keys_manager_c);
|
||||
let (new_node_c, new_monitor_c) = reload_node!(node_c_ser, 2, monitor_c, keys_manager_c, fee_est_c);
|
||||
nodes[2] = new_node_c;
|
||||
monitor_c = new_monitor_c;
|
||||
},
|
||||
|
@ -1023,6 +1053,33 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
0x6c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1, &mut payment_id); },
|
||||
0x6d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id); },
|
||||
|
||||
0x80 => {
|
||||
let max_feerate = last_htlc_clear_fee_a * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
|
||||
if fee_est_a.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
|
||||
fee_est_a.ret_val.store(max_feerate, atomic::Ordering::Release);
|
||||
}
|
||||
nodes[0].maybe_update_chan_fees();
|
||||
},
|
||||
0x81 => { fee_est_a.ret_val.store(253, atomic::Ordering::Release); nodes[0].maybe_update_chan_fees(); },
|
||||
|
||||
0x84 => {
|
||||
let max_feerate = last_htlc_clear_fee_b * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
|
||||
if fee_est_b.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
|
||||
fee_est_b.ret_val.store(max_feerate, atomic::Ordering::Release);
|
||||
}
|
||||
nodes[1].maybe_update_chan_fees();
|
||||
},
|
||||
0x85 => { fee_est_b.ret_val.store(253, atomic::Ordering::Release); nodes[1].maybe_update_chan_fees(); },
|
||||
|
||||
0x88 => {
|
||||
let max_feerate = last_htlc_clear_fee_c * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
|
||||
if fee_est_c.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
|
||||
fee_est_c.ret_val.store(max_feerate, atomic::Ordering::Release);
|
||||
}
|
||||
nodes[2].maybe_update_chan_fees();
|
||||
},
|
||||
0x89 => { fee_est_c.ret_val.store(253, atomic::Ordering::Release); nodes[2].maybe_update_chan_fees(); },
|
||||
|
||||
0xff => {
|
||||
// Test that no channel is in a stuck state where neither party can send funds even
|
||||
// after we resolve all pending events.
|
||||
|
@ -1078,6 +1135,10 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
|||
assert!(
|
||||
send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id) ||
|
||||
send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id));
|
||||
|
||||
last_htlc_clear_fee_a = fee_est_a.ret_val.load(atomic::Ordering::Acquire);
|
||||
last_htlc_clear_fee_b = fee_est_b.ret_val.load(atomic::Ordering::Acquire);
|
||||
last_htlc_clear_fee_c = fee_est_c.ret_val.load(atomic::Ordering::Acquire);
|
||||
},
|
||||
_ => test_return!(),
|
||||
}
|
||||
|
|
|
@ -140,6 +140,9 @@ impl BackgroundProcessor {
|
|||
let stop_thread = Arc::new(AtomicBool::new(false));
|
||||
let stop_thread_clone = stop_thread.clone();
|
||||
let handle = thread::spawn(move || -> Result<(), std::io::Error> {
|
||||
log_trace!(logger, "Calling ChannelManager's timer_tick_occurred on startup");
|
||||
channel_manager.timer_tick_occurred();
|
||||
|
||||
let mut last_freshness_call = Instant::now();
|
||||
let mut last_ping_call = Instant::now();
|
||||
loop {
|
||||
|
|
|
@ -23,6 +23,7 @@ pub trait BroadcasterInterface {
|
|||
|
||||
/// An enum that represents the speed at which we want a transaction to confirm used for feerate
|
||||
/// estimation.
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ConfirmationTarget {
|
||||
/// We are happy with this transaction confirming slowly when feerate drops some.
|
||||
Background,
|
||||
|
|
|
@ -2054,6 +2054,195 @@ fn test_path_paused_mpp() {
|
|||
claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pending_update_fee_ack_on_reconnect() {
|
||||
// In early versions of our automated fee update patch, nodes did not correctly use the
|
||||
// previous channel feerate after sending an undelivered revoke_and_ack when re-sending an
|
||||
// undelivered commitment_signed.
|
||||
//
|
||||
// B sends A new HTLC + CS, not delivered
|
||||
// A sends B update_fee + CS
|
||||
// B receives the CS and sends RAA, previously causing B to lock in the new feerate
|
||||
// reconnect
|
||||
// B resends initial CS, using the original fee
|
||||
|
||||
let chanmon_cfgs = create_chanmon_cfgs(2);
|
||||
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);
|
||||
|
||||
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
|
||||
send_payment(&nodes[0], &[&nodes[1]], 100_000_00);
|
||||
|
||||
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[0]);
|
||||
let route = get_route(&nodes[1].node.get_our_node_id(), &nodes[1].net_graph_msg_handler.network_graph.read().unwrap(),
|
||||
&nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1_000_000, TEST_FINAL_CLTV, nodes[1].logger).unwrap();
|
||||
nodes[1].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
let bs_initial_send_msgs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
|
||||
// bs_initial_send_msgs are not delivered until they are re-generated after reconnect
|
||||
|
||||
{
|
||||
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
|
||||
*feerate_lock *= 2;
|
||||
}
|
||||
nodes[0].node.timer_tick_occurred();
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
let as_update_fee_msgs = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
|
||||
assert!(as_update_fee_msgs.update_fee.is_some());
|
||||
|
||||
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), as_update_fee_msgs.update_fee.as_ref().unwrap());
|
||||
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_update_fee_msgs.commitment_signed);
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
let bs_first_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
|
||||
// bs_first_raa is not delivered until it is re-generated after reconnect
|
||||
|
||||
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);
|
||||
|
||||
nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known() });
|
||||
let as_connect_msg = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
|
||||
nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known() });
|
||||
let bs_connect_msg = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
|
||||
|
||||
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_connect_msg);
|
||||
let bs_resend_msgs = nodes[1].node.get_and_clear_pending_msg_events();
|
||||
assert_eq!(bs_resend_msgs.len(), 3);
|
||||
if let MessageSendEvent::UpdateHTLCs { ref updates, .. } = bs_resend_msgs[0] {
|
||||
assert_eq!(*updates, bs_initial_send_msgs);
|
||||
} else { panic!(); }
|
||||
if let MessageSendEvent::SendRevokeAndACK { ref msg, .. } = bs_resend_msgs[1] {
|
||||
assert_eq!(*msg, bs_first_raa);
|
||||
} else { panic!(); }
|
||||
if let MessageSendEvent::SendChannelUpdate { .. } = bs_resend_msgs[2] { } else { panic!(); }
|
||||
|
||||
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_connect_msg);
|
||||
get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
|
||||
|
||||
nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &bs_initial_send_msgs.update_add_htlcs[0]);
|
||||
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_initial_send_msgs.commitment_signed);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()));
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
let bs_second_cs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()).commitment_signed;
|
||||
|
||||
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_first_raa);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()).commitment_signed);
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
let bs_third_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
|
||||
|
||||
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_cs);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
|
||||
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()));
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
|
||||
expect_pending_htlcs_forwardable!(nodes[0]);
|
||||
expect_payment_received!(nodes[0], payment_hash, payment_secret, 1_000_000);
|
||||
|
||||
claim_payment(&nodes[1], &[&nodes[0]], payment_preimage);
|
||||
}
|
||||
|
||||
fn do_update_fee_resend_test(deliver_update: bool, parallel_updates: bool) {
|
||||
// In early versions we did not handle resending of update_fee on reconnect correctly. The
|
||||
// chanmon_consistency fuzz target, of course, immediately found it, but we test a few cases
|
||||
// explicitly here.
|
||||
let chanmon_cfgs = create_chanmon_cfgs(2);
|
||||
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);
|
||||
|
||||
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
|
||||
send_payment(&nodes[0], &[&nodes[1]], 1000);
|
||||
|
||||
{
|
||||
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 update_msgs = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
|
||||
assert!(update_msgs.update_fee.is_some());
|
||||
if deliver_update {
|
||||
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msgs.update_fee.as_ref().unwrap());
|
||||
}
|
||||
|
||||
if parallel_updates {
|
||||
{
|
||||
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
|
||||
*feerate_lock += 20;
|
||||
}
|
||||
nodes[0].node.timer_tick_occurred();
|
||||
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known() });
|
||||
let as_connect_msg = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
|
||||
nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known() });
|
||||
let bs_connect_msg = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
|
||||
|
||||
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_connect_msg);
|
||||
get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
|
||||
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
|
||||
|
||||
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_connect_msg);
|
||||
let mut as_reconnect_msgs = nodes[0].node.get_and_clear_pending_msg_events();
|
||||
assert_eq!(as_reconnect_msgs.len(), 2);
|
||||
if let MessageSendEvent::SendChannelUpdate { .. } = as_reconnect_msgs.pop().unwrap() {} else { panic!(); }
|
||||
let update_msgs = if let MessageSendEvent::UpdateHTLCs { updates, .. } = as_reconnect_msgs.pop().unwrap()
|
||||
{ updates } else { panic!(); };
|
||||
assert!(update_msgs.update_fee.is_some());
|
||||
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msgs.update_fee.as_ref().unwrap());
|
||||
if parallel_updates {
|
||||
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &update_msgs.commitment_signed);
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
let (bs_first_raa, bs_first_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
|
||||
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_first_raa);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
let as_second_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
|
||||
|
||||
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_first_cs);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
let as_first_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
|
||||
|
||||
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), as_second_update.update_fee.as_ref().unwrap());
|
||||
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_second_update.commitment_signed);
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
let bs_second_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
|
||||
|
||||
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_first_raa);
|
||||
let bs_second_cs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
|
||||
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_raa);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
|
||||
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_cs.commitment_signed);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
|
||||
|
||||
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_second_raa);
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
} else {
|
||||
commitment_signed_dance!(nodes[1], nodes[0], update_msgs.commitment_signed, false);
|
||||
}
|
||||
|
||||
send_payment(&nodes[0], &[&nodes[1]], 1000);
|
||||
}
|
||||
#[test]
|
||||
fn update_fee_resend_test() {
|
||||
do_update_fee_resend_test(false, false);
|
||||
do_update_fee_resend_test(true, false);
|
||||
do_update_fee_resend_test(false, true);
|
||||
do_update_fee_resend_test(true, true);
|
||||
}
|
||||
|
||||
fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) {
|
||||
// Tests that, when we serialize a channel with AddHTLC entries in the holding cell, we
|
||||
// properly free them on reconnect. We previously failed such HTLCs upon serialization, but
|
||||
|
|
|
@ -63,6 +63,21 @@ pub struct ChannelValueStat {
|
|||
pub counterparty_dust_limit_msat: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum FeeUpdateState {
|
||||
// Inbound states mirroring InboundHTLCState
|
||||
RemoteAnnounced,
|
||||
AwaitingRemoteRevokeToAnnounce,
|
||||
// Note that we do not have a AwaitingAnnouncedRemoteRevoke variant here as it is universally
|
||||
// handled the same as `Committed`, with the only exception in `InboundHTLCState` being the
|
||||
// distinction of when we allow ourselves to forward the HTLC. Because we aren't "forwarding"
|
||||
// the fee update anywhere, we can simply consider the fee update `Committed` immediately
|
||||
// instead of setting it to AwaitingAnnouncedRemoteRevoke.
|
||||
|
||||
// Outbound state can only be `LocalAnnounced` or `Committed`
|
||||
Outbound,
|
||||
}
|
||||
|
||||
enum InboundHTLCRemovalReason {
|
||||
FailRelay(msgs::OnionErrorPacket),
|
||||
FailMalformed(([u8; 32], u16)),
|
||||
|
@ -341,6 +356,22 @@ pub enum UpdateFulfillCommitFetch {
|
|||
DuplicateClaim {},
|
||||
}
|
||||
|
||||
/// If the majority of the channels funds are to the fundee and the initiator holds only just
|
||||
/// enough funds to cover their reserve value, channels are at risk of getting "stuck". Because the
|
||||
/// initiator controls the feerate, if they then go to increase the channel fee, they may have no
|
||||
/// balance but the fundee is unable to send a payment as the increase in fee more than drains
|
||||
/// their reserve value. Thus, neither side can send a new HTLC and the channel becomes useless.
|
||||
/// Thus, before sending an HTLC when we are the initiator, we check that the feerate can increase
|
||||
/// by this multiple without hitting this case, before sending.
|
||||
/// This multiple is effectively the maximum feerate "jump" we expect until more HTLCs flow over
|
||||
/// the channel. Sadly, there isn't really a good number for this - if we expect to have no new
|
||||
/// HTLCs for days we may need this to suffice for feerate increases across days, but that may
|
||||
/// leave the channel less usable as we hold a bigger reserve.
|
||||
#[cfg(fuzzing)]
|
||||
pub const FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE: u64 = 2;
|
||||
#[cfg(not(fuzzing))]
|
||||
const FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE: u64 = 2;
|
||||
|
||||
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
|
||||
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
|
||||
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
|
||||
|
@ -404,7 +435,7 @@ pub(super) struct Channel<Signer: Sign> {
|
|||
// revoke_and_ack is received and new commitment_signed is generated to be
|
||||
// sent to the funder. Otherwise, the pending value is removed when receiving
|
||||
// commitment_signed.
|
||||
pending_update_fee: Option<u32>,
|
||||
pending_update_fee: Option<(u32, FeeUpdateState)>,
|
||||
// update_fee() during ChannelState::AwaitingRemoteRevoke is hold in
|
||||
// holdina_cell_update_fee then moved to pending_udpate_fee when revoke_and_ack
|
||||
// is received. holding_cell_update_fee is updated when there are additional
|
||||
|
@ -719,7 +750,12 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
if feerate_per_kw < lower_limit {
|
||||
return Err(ChannelError::Close(format!("Peer's feerate much too low. Actual: {}. Our expected lower limit: {}", feerate_per_kw, lower_limit)));
|
||||
}
|
||||
let upper_limit = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64 * 2;
|
||||
// We only bound the fee updates on the upper side to prevent completely absurd feerates,
|
||||
// always accepting up to 25 sat/vByte or 10x our fee estimator's "High Priority" fee.
|
||||
// We generally don't care too much if they set the feerate to something very high, but it
|
||||
// could result in the channel being useless due to everything being dust.
|
||||
let upper_limit = cmp::max(250 * 25,
|
||||
fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64 * 10);
|
||||
if feerate_per_kw as u64 > upper_limit {
|
||||
return Err(ChannelError::Close(format!("Peer's feerate much too high. Actual: {}. Our expected upper limit: {}", feerate_per_kw, upper_limit)));
|
||||
}
|
||||
|
@ -987,10 +1023,10 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
/// which peer generated this transaction and "to whom" this transaction flows.
|
||||
/// Returns (the transaction info, the number of HTLC outputs which were present in the
|
||||
/// transaction, the list of HTLCs which were not ignored when building the transaction).
|
||||
/// Note that below-dust HTLCs are included in the third return value, but not the second, and
|
||||
/// sources are provided only for outbound HTLCs in the third return value.
|
||||
/// Note that below-dust HTLCs are included in the fourth return value, but not the third, and
|
||||
/// sources are provided only for outbound HTLCs in the fourth return value.
|
||||
#[inline]
|
||||
fn build_commitment_transaction<L: Deref>(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u32, logger: &L) -> (CommitmentTransaction, usize, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>) where L::Target: Logger {
|
||||
fn build_commitment_transaction<L: Deref>(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, logger: &L) -> (CommitmentTransaction, u32, usize, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>) where L::Target: Logger {
|
||||
let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::new();
|
||||
let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
|
||||
let mut included_non_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(num_htlcs);
|
||||
|
@ -1000,6 +1036,19 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
let mut local_htlc_total_msat = 0;
|
||||
let mut value_to_self_msat_offset = 0;
|
||||
|
||||
let mut feerate_per_kw = self.feerate_per_kw;
|
||||
if let Some((feerate, update_state)) = self.pending_update_fee {
|
||||
if match update_state {
|
||||
// Note that these match the inclusion criteria when scanning
|
||||
// pending_inbound_htlcs below.
|
||||
FeeUpdateState::RemoteAnnounced => { debug_assert!(!self.is_outbound()); !generated_by_local },
|
||||
FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { debug_assert!(!self.is_outbound()); !generated_by_local },
|
||||
FeeUpdateState::Outbound => { assert!(self.is_outbound()); generated_by_local },
|
||||
} {
|
||||
feerate_per_kw = feerate;
|
||||
}
|
||||
}
|
||||
|
||||
log_trace!(logger, "Building commitment transaction number {} (really {} xor {}) for channel {} for {}, generated by {} with fee {}...",
|
||||
commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number),
|
||||
get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound()),
|
||||
|
@ -1160,7 +1209,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
htlcs_included.sort_unstable_by_key(|h| h.0.transaction_output_index.unwrap());
|
||||
htlcs_included.append(&mut included_dust_htlcs);
|
||||
|
||||
(tx, num_nondust_htlcs, htlcs_included)
|
||||
(tx, feerate_per_kw, num_nondust_htlcs, htlcs_included)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1213,6 +1262,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
|
||||
assert!(self.pending_inbound_htlcs.is_empty());
|
||||
assert!(self.pending_outbound_htlcs.is_empty());
|
||||
assert!(self.pending_update_fee.is_none());
|
||||
let mut txouts: Vec<(TxOut, ())> = Vec::new();
|
||||
|
||||
let mut total_fee_satoshis = proposed_total_fee_satoshis;
|
||||
|
@ -1638,7 +1688,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
let funding_script = self.get_funding_redeemscript();
|
||||
|
||||
let keys = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number)?;
|
||||
let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, false, self.feerate_per_kw, logger).0;
|
||||
let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, false, logger).0;
|
||||
{
|
||||
let trusted_tx = initial_commitment_tx.trust();
|
||||
let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
|
||||
|
@ -1652,7 +1702,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
}
|
||||
|
||||
let counterparty_keys = self.build_remote_transaction_keys()?;
|
||||
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, self.feerate_per_kw, logger).0;
|
||||
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).0;
|
||||
|
||||
let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
|
||||
let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
|
||||
|
@ -1760,7 +1810,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
let funding_script = self.get_funding_redeemscript();
|
||||
|
||||
let counterparty_keys = self.build_remote_transaction_keys()?;
|
||||
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, self.feerate_per_kw, logger).0;
|
||||
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).0;
|
||||
let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
|
||||
let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
|
||||
|
||||
|
@ -1768,7 +1818,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
log_bytes!(self.channel_id()), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction));
|
||||
|
||||
let holder_signer = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number)?;
|
||||
let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &holder_signer, true, false, self.feerate_per_kw, logger).0;
|
||||
let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &holder_signer, true, false, logger).0;
|
||||
{
|
||||
let trusted_tx = initial_commitment_tx.trust();
|
||||
let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
|
||||
|
@ -2339,16 +2389,8 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
|
||||
let keys = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number).map_err(|e| (None, e))?;
|
||||
|
||||
let mut update_fee = false;
|
||||
let feerate_per_kw = if !self.is_outbound() && self.pending_update_fee.is_some() {
|
||||
update_fee = true;
|
||||
self.pending_update_fee.unwrap()
|
||||
} else {
|
||||
self.feerate_per_kw
|
||||
};
|
||||
|
||||
let (num_htlcs, mut htlcs_cloned, commitment_tx, commitment_txid) = {
|
||||
let commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, false, feerate_per_kw, logger);
|
||||
let (num_htlcs, mut htlcs_cloned, commitment_tx, commitment_txid, feerate_per_kw) = {
|
||||
let commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, false, logger);
|
||||
let commitment_txid = {
|
||||
let trusted_tx = commitment_tx.0.trust();
|
||||
let bitcoin_tx = trusted_tx.built_transaction();
|
||||
|
@ -2363,12 +2405,17 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
}
|
||||
bitcoin_tx.txid
|
||||
};
|
||||
let htlcs_cloned: Vec<_> = commitment_tx.2.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
|
||||
(commitment_tx.1, htlcs_cloned, commitment_tx.0, commitment_txid)
|
||||
let htlcs_cloned: Vec<_> = commitment_tx.3.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
|
||||
(commitment_tx.2, htlcs_cloned, commitment_tx.0, commitment_txid, commitment_tx.1)
|
||||
};
|
||||
|
||||
// If our counterparty updated the channel fee in this commitment transaction, check that
|
||||
// they can actually afford the new fee now.
|
||||
let update_fee = if let Some((_, update_state)) = self.pending_update_fee {
|
||||
update_state == FeeUpdateState::RemoteAnnounced
|
||||
} else { false };
|
||||
if update_fee { debug_assert!(!self.is_outbound()); }
|
||||
let total_fee = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
|
||||
//If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction
|
||||
if update_fee {
|
||||
let counterparty_reserve_we_require = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis);
|
||||
if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + counterparty_reserve_we_require {
|
||||
|
@ -2432,16 +2479,10 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
|
||||
// Update state now that we've passed all the can-fail calls...
|
||||
let mut need_commitment = false;
|
||||
if !self.is_outbound() {
|
||||
if let Some(fee_update) = self.pending_update_fee {
|
||||
self.feerate_per_kw = fee_update;
|
||||
// We later use the presence of pending_update_fee to indicate we should generate a
|
||||
// commitment_signed upon receipt of revoke_and_ack, so we can only set it to None
|
||||
// if we're not awaiting a revoke (ie will send a commitment_signed now).
|
||||
if (self.channel_state & ChannelState::AwaitingRemoteRevoke as u32) == 0 {
|
||||
need_commitment = true;
|
||||
self.pending_update_fee = None;
|
||||
}
|
||||
if let &mut Some((_, ref mut update_state)) = &mut self.pending_update_fee {
|
||||
if *update_state == FeeUpdateState::RemoteAnnounced {
|
||||
*update_state = FeeUpdateState::AwaitingRemoteRevokeToAnnounce;
|
||||
need_commitment = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2622,8 +2663,9 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
if update_add_htlcs.is_empty() && update_fulfill_htlcs.is_empty() && update_fail_htlcs.is_empty() && self.holding_cell_update_fee.is_none() {
|
||||
return Ok((None, htlcs_to_fail));
|
||||
}
|
||||
let update_fee = if let Some(feerate) = self.holding_cell_update_fee {
|
||||
self.pending_update_fee = self.holding_cell_update_fee.take();
|
||||
let update_fee = if let Some(feerate) = self.holding_cell_update_fee.take() {
|
||||
assert!(self.is_outbound());
|
||||
self.pending_update_fee = Some((feerate, FeeUpdateState::Outbound));
|
||||
Some(msgs::UpdateFee {
|
||||
channel_id: self.channel_id,
|
||||
feerate_per_kw: feerate as u32,
|
||||
|
@ -2807,21 +2849,22 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
}
|
||||
self.value_to_self_msat = (self.value_to_self_msat as i64 + value_to_self_msat_diff) as u64;
|
||||
|
||||
if self.is_outbound() {
|
||||
if let Some(feerate) = self.pending_update_fee.take() {
|
||||
self.feerate_per_kw = feerate;
|
||||
}
|
||||
} else {
|
||||
if let Some(feerate) = self.pending_update_fee {
|
||||
// Because a node cannot send two commitment_signeds in a row without getting a
|
||||
// revoke_and_ack from us (as it would otherwise not know the per_commitment_point
|
||||
// it should use to create keys with) and because a node can't send a
|
||||
// commitment_signed without changes, checking if the feerate is equal to the
|
||||
// pending feerate update is sufficient to detect require_commitment.
|
||||
if feerate == self.feerate_per_kw {
|
||||
require_commitment = true;
|
||||
if let Some((feerate, update_state)) = self.pending_update_fee {
|
||||
match update_state {
|
||||
FeeUpdateState::Outbound => {
|
||||
debug_assert!(self.is_outbound());
|
||||
log_trace!(logger, " ...promoting outbound fee update {} to Committed", feerate);
|
||||
self.feerate_per_kw = feerate;
|
||||
self.pending_update_fee = None;
|
||||
}
|
||||
},
|
||||
FeeUpdateState::RemoteAnnounced => { debug_assert!(!self.is_outbound()); },
|
||||
FeeUpdateState::AwaitingRemoteRevokeToAnnounce => {
|
||||
debug_assert!(!self.is_outbound());
|
||||
log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce fee update {} to Committed", feerate);
|
||||
require_commitment = true;
|
||||
self.feerate_per_kw = feerate;
|
||||
self.pending_update_fee = None;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2905,13 +2948,13 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
panic!("Cannot update fee while peer is disconnected/we're awaiting a monitor update (ChannelManager should have caught this)");
|
||||
}
|
||||
|
||||
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
|
||||
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::MonitorUpdateFailed as u32)) != 0 {
|
||||
self.holding_cell_update_fee = Some(feerate_per_kw);
|
||||
return None;
|
||||
}
|
||||
|
||||
debug_assert!(self.pending_update_fee.is_none());
|
||||
self.pending_update_fee = Some(feerate_per_kw);
|
||||
self.pending_update_fee = Some((feerate_per_kw, FeeUpdateState::Outbound));
|
||||
|
||||
Some(msgs::UpdateFee {
|
||||
channel_id: self.channel_id,
|
||||
|
@ -2972,6 +3015,13 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
});
|
||||
self.next_counterparty_htlc_id -= inbound_drop_count;
|
||||
|
||||
if let Some((_, update_state)) = self.pending_update_fee {
|
||||
if update_state == FeeUpdateState::RemoteAnnounced {
|
||||
debug_assert!(!self.is_outbound());
|
||||
self.pending_update_fee = None;
|
||||
}
|
||||
}
|
||||
|
||||
for htlc in self.pending_outbound_htlcs.iter_mut() {
|
||||
if let OutboundHTLCState::RemoteRemoved(_) = htlc.state {
|
||||
// They sent us an update to remove this but haven't yet sent the corresponding
|
||||
|
@ -3066,8 +3116,27 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
return Err(ChannelError::Close("Peer sent update_fee when we needed a channel_reestablish".to_owned()));
|
||||
}
|
||||
Channel::<Signer>::check_remote_fee(fee_estimator, msg.feerate_per_kw)?;
|
||||
self.pending_update_fee = Some(msg.feerate_per_kw);
|
||||
let feerate_over_dust_buffer = msg.feerate_per_kw > self.get_dust_buffer_feerate();
|
||||
|
||||
self.pending_update_fee = Some((msg.feerate_per_kw, FeeUpdateState::RemoteAnnounced));
|
||||
self.update_time_counter += 1;
|
||||
// If the feerate has increased over the previous dust buffer (note that
|
||||
// `get_dust_buffer_feerate` considers the `pending_update_fee` status), check that we
|
||||
// won't be pushed over our dust exposure limit by the feerate increase.
|
||||
if feerate_over_dust_buffer {
|
||||
let inbound_stats = self.get_inbound_pending_htlc_stats();
|
||||
let outbound_stats = self.get_outbound_pending_htlc_stats();
|
||||
let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
|
||||
let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
|
||||
if holder_tx_dust_exposure > self.get_max_dust_htlc_exposure_msat() {
|
||||
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)",
|
||||
msg.feerate_per_kw, holder_tx_dust_exposure)));
|
||||
}
|
||||
if counterparty_tx_dust_exposure > self.get_max_dust_htlc_exposure_msat() {
|
||||
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our counterparty's transactions (totaling {} msat)",
|
||||
msg.feerate_per_kw, counterparty_tx_dust_exposure)));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -3129,11 +3198,18 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
}
|
||||
}
|
||||
|
||||
log_trace!(logger, "Regenerated latest commitment update in channel {} with {} update_adds, {} update_fulfills, {} update_fails, and {} update_fail_malformeds",
|
||||
log_bytes!(self.channel_id()), update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len(), update_fail_malformed_htlcs.len());
|
||||
let update_fee = if self.is_outbound() && self.pending_update_fee.is_some() {
|
||||
Some(msgs::UpdateFee {
|
||||
channel_id: self.channel_id(),
|
||||
feerate_per_kw: self.pending_update_fee.unwrap().0,
|
||||
})
|
||||
} else { None };
|
||||
|
||||
log_trace!(logger, "Regenerated latest commitment update in channel {} with{} {} update_adds, {} update_fulfills, {} update_fails, and {} update_fail_malformeds",
|
||||
log_bytes!(self.channel_id()), if update_fee.is_some() { " update_fee," } else { "" },
|
||||
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len(), update_fail_malformed_htlcs.len());
|
||||
msgs::CommitmentUpdate {
|
||||
update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs,
|
||||
update_fee: None,
|
||||
update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs, update_fee,
|
||||
commitment_signed: self.send_commitment_no_state_update(logger).expect("It looks like we failed to re-generate a commitment_signed we had previously sent?").0,
|
||||
}
|
||||
}
|
||||
|
@ -3622,7 +3698,6 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
self.config.max_dust_htlc_exposure_msat
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn get_feerate(&self) -> u32 {
|
||||
self.feerate_per_kw
|
||||
}
|
||||
|
@ -3633,7 +3708,11 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
// whichever is higher. This ensures that we aren't suddenly exposed to significantly
|
||||
// more dust balance if the feerate increases when we have several HTLCs pending
|
||||
// which are near the dust limit.
|
||||
cmp::max(2530, self.feerate_per_kw * 1250 / 1000)
|
||||
let mut feerate_per_kw = self.feerate_per_kw;
|
||||
if let Some((feerate, _)) = self.pending_update_fee {
|
||||
feerate_per_kw = cmp::max(feerate_per_kw, feerate);
|
||||
}
|
||||
cmp::max(2530, feerate_per_kw * 1250 / 1000)
|
||||
}
|
||||
|
||||
pub fn get_cur_holder_commitment_transaction_number(&self) -> u64 {
|
||||
|
@ -4034,7 +4113,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
/// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created)
|
||||
fn get_outbound_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
|
||||
let counterparty_keys = self.build_remote_transaction_keys()?;
|
||||
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, self.feerate_per_kw, logger).0;
|
||||
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).0;
|
||||
Ok(self.holder_signer.sign_counterparty_commitment(&counterparty_initial_commitment_tx, &self.secp_ctx)
|
||||
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0)
|
||||
}
|
||||
|
@ -4327,7 +4406,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
// `2 *` and extra HTLC are for the fee spike buffer.
|
||||
let commit_tx_fee_msat = if self.is_outbound() {
|
||||
let htlc_candidate = HTLCCandidate::new(amount_msat, HTLCInitiator::LocalOffered);
|
||||
2 * self.next_local_commit_tx_fee_msat(htlc_candidate, Some(()))
|
||||
FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * self.next_local_commit_tx_fee_msat(htlc_candidate, Some(()))
|
||||
} else { 0 };
|
||||
if pending_value_to_self_msat - amount_msat < commit_tx_fee_msat {
|
||||
return Err(ChannelError::Ignore(format!("Cannot send value that would not leave enough to pay for fees. Pending value to self: {}. local_commit_tx_fee {}", pending_value_to_self_msat, commit_tx_fee_msat)));
|
||||
|
@ -4391,7 +4470,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
if (self.channel_state & (ChannelState::MonitorUpdateFailed as u32)) == (ChannelState::MonitorUpdateFailed as u32) {
|
||||
panic!("Cannot create commitment tx while awaiting monitor update unfreeze, as send_htlc will have returned an Err so a send_commitment precondition has been violated");
|
||||
}
|
||||
let mut have_updates = self.pending_update_fee.is_some();
|
||||
let mut have_updates = self.is_outbound() && self.pending_update_fee.is_some();
|
||||
for htlc in self.pending_outbound_htlcs.iter() {
|
||||
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
|
||||
have_updates = true;
|
||||
|
@ -4411,6 +4490,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
}
|
||||
/// Only fails in case of bad keys
|
||||
fn send_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> Result<(msgs::CommitmentSigned, ChannelMonitorUpdate), ChannelError> where L::Target: Logger {
|
||||
log_trace!(logger, "Updating HTLC state for a newly-sent commitment_signed...");
|
||||
// We can upgrade the status of some HTLCs that are waiting on a commitment, even if we
|
||||
// fail to generate this, we still are at least at a position where upgrading their status
|
||||
// is acceptable.
|
||||
|
@ -4419,6 +4499,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
Some(InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info.clone()))
|
||||
} else { None };
|
||||
if let Some(state) = new_state {
|
||||
log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to AwaitingAnnouncedRemoteRevoke", log_bytes!(htlc.payment_hash.0));
|
||||
htlc.state = state;
|
||||
}
|
||||
}
|
||||
|
@ -4426,9 +4507,18 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
if let Some(fail_reason) = if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut fail_reason) = &mut htlc.state {
|
||||
Some(fail_reason.take())
|
||||
} else { None } {
|
||||
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", log_bytes!(htlc.payment_hash.0));
|
||||
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(fail_reason);
|
||||
}
|
||||
}
|
||||
if let Some((feerate, update_state)) = self.pending_update_fee {
|
||||
if update_state == FeeUpdateState::AwaitingRemoteRevokeToAnnounce {
|
||||
debug_assert!(!self.is_outbound());
|
||||
log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce fee update {} to Committed", feerate);
|
||||
self.feerate_per_kw = feerate;
|
||||
self.pending_update_fee = None;
|
||||
}
|
||||
}
|
||||
self.resend_order = RAACommitmentOrder::RevokeAndACKFirst;
|
||||
|
||||
let (res, counterparty_commitment_txid, htlcs) = match self.send_commitment_no_state_update(logger) {
|
||||
|
@ -4458,15 +4548,9 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
/// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation
|
||||
/// when we shouldn't change HTLC/channel state.
|
||||
fn send_commitment_no_state_update<L: Deref>(&self, logger: &L) -> Result<(msgs::CommitmentSigned, (Txid, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> where L::Target: Logger {
|
||||
let mut feerate_per_kw = self.feerate_per_kw;
|
||||
if let Some(feerate) = self.pending_update_fee {
|
||||
if self.is_outbound() {
|
||||
feerate_per_kw = feerate;
|
||||
}
|
||||
}
|
||||
|
||||
let counterparty_keys = self.build_remote_transaction_keys()?;
|
||||
let counterparty_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, feerate_per_kw, logger);
|
||||
let counterparty_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger);
|
||||
let feerate_per_kw = counterparty_commitment_tx.1;
|
||||
let counterparty_commitment_txid = counterparty_commitment_tx.0.trust().txid();
|
||||
let (signature, htlc_signatures);
|
||||
|
||||
|
@ -4481,7 +4565,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
&& info.next_holder_htlc_id == self.next_holder_htlc_id
|
||||
&& info.next_counterparty_htlc_id == self.next_counterparty_htlc_id
|
||||
&& info.feerate == self.feerate_per_kw {
|
||||
let actual_fee = self.commit_tx_fee_msat(counterparty_commitment_tx.1);
|
||||
let actual_fee = self.commit_tx_fee_msat(counterparty_commitment_tx.2);
|
||||
assert_eq!(actual_fee, info.fee);
|
||||
}
|
||||
}
|
||||
|
@ -4489,8 +4573,8 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
}
|
||||
|
||||
{
|
||||
let mut htlcs = Vec::with_capacity(counterparty_commitment_tx.2.len());
|
||||
for &(ref htlc, _) in counterparty_commitment_tx.2.iter() {
|
||||
let mut htlcs = Vec::with_capacity(counterparty_commitment_tx.3.len());
|
||||
for &(ref htlc, _) in counterparty_commitment_tx.3.iter() {
|
||||
htlcs.push(htlc);
|
||||
}
|
||||
|
||||
|
@ -4517,7 +4601,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
channel_id: self.channel_id,
|
||||
signature,
|
||||
htlc_signatures,
|
||||
}, (counterparty_commitment_txid, counterparty_commitment_tx.2)))
|
||||
}, (counterparty_commitment_txid, counterparty_commitment_tx.3)))
|
||||
}
|
||||
|
||||
/// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
|
||||
|
@ -4858,7 +4942,14 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
|
|||
fail_reason.write(writer)?;
|
||||
}
|
||||
|
||||
self.pending_update_fee.write(writer)?;
|
||||
if self.is_outbound() {
|
||||
self.pending_update_fee.map(|(a, _)| a).write(writer)?;
|
||||
} else if let Some((feerate, FeeUpdateState::AwaitingRemoteRevokeToAnnounce)) = self.pending_update_fee {
|
||||
// As for inbound HTLCs, if the update was only announced and never committed, drop it.
|
||||
Some(feerate).write(writer)?;
|
||||
} else {
|
||||
None::<u32>.write(writer)?;
|
||||
}
|
||||
self.holding_cell_update_fee.write(writer)?;
|
||||
|
||||
self.next_holder_htlc_id.write(writer)?;
|
||||
|
@ -5073,7 +5164,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
|
|||
monitor_pending_failures.push((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?));
|
||||
}
|
||||
|
||||
let pending_update_fee = Readable::read(reader)?;
|
||||
let pending_update_fee_value: Option<u32> = Readable::read(reader)?;
|
||||
|
||||
let holding_cell_update_fee = Readable::read(reader)?;
|
||||
|
||||
let next_holder_htlc_id = Readable::read(reader)?;
|
||||
|
@ -5125,7 +5217,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
|
|||
_ => return Err(DecodeError::InvalidValue),
|
||||
};
|
||||
|
||||
let channel_parameters = Readable::read(reader)?;
|
||||
let channel_parameters: ChannelTransactionParameters = Readable::read(reader)?;
|
||||
let funding_transaction = Readable::read(reader)?;
|
||||
|
||||
let counterparty_cur_commitment_point = Readable::read(reader)?;
|
||||
|
@ -5148,6 +5240,16 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
|
|||
}
|
||||
}
|
||||
|
||||
let pending_update_fee = if let Some(feerate) = pending_update_fee_value {
|
||||
Some((feerate, if channel_parameters.is_outbound_from_holder {
|
||||
FeeUpdateState::Outbound
|
||||
} else {
|
||||
FeeUpdateState::AwaitingRemoteRevokeToAnnounce
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut announcement_sigs = None;
|
||||
read_tlv_fields!(reader, {
|
||||
(0, announcement_sigs, option),
|
||||
|
@ -5686,9 +5788,9 @@ mod tests {
|
|||
$( { $htlc_idx: expr, $counterparty_htlc_sig_hex: expr, $htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
|
||||
} ) => { {
|
||||
let (commitment_tx, htlcs): (_, Vec<HTLCOutputInCommitment>) = {
|
||||
let mut res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw, &logger);
|
||||
let mut res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, &logger);
|
||||
|
||||
let htlcs = res.2.drain(..)
|
||||
let htlcs = res.3.drain(..)
|
||||
.filter_map(|(htlc, _)| if htlc.transaction_output_index.is_some() { Some(htlc) } else { None })
|
||||
.collect();
|
||||
(res.0, htlcs)
|
||||
|
|
|
@ -37,7 +37,7 @@ use bitcoin::secp256k1;
|
|||
|
||||
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
|
||||
|
@ -71,7 +71,6 @@ use core::time::Duration;
|
|||
#[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:
|
||||
//
|
||||
|
@ -2561,46 +2560,151 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
|
|||
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)
|
||||
}
|
||||
|
||||
#[cfg(fuzzing)]
|
||||
/// In chanmon_consistency we want to sometimes do the channel fee updates done in
|
||||
/// timer_tick_occurred, but we can't generate the disabled channel updates as it considers
|
||||
/// these a fuzz failure (as they usually indicate a channel force-close, which is exactly what
|
||||
/// it wants to detect). Thus, we have a variant exposed here for its benefit.
|
||||
pub fn maybe_update_chan_fees(&self) {
|
||||
PersistenceNotifierGuard::optionally_notify(&self.total_consistency_lock, &self.persistence_notifier, || {
|
||||
let mut should_persist = NotifyOption::SkipPersist;
|
||||
|
||||
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| {
|
||||
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);
|
||||
}
|
||||
retain_channel
|
||||
});
|
||||
}
|
||||
|
||||
should_persist
|
||||
});
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -3728,62 +3832,6 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
|
|||
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();
|
||||
|
|
|
@ -130,9 +130,8 @@ fn test_async_inbound_update_fee() {
|
|||
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);
|
||||
|
@ -155,7 +154,11 @@ fn test_async_inbound_update_fee() {
|
|||
// (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();
|
||||
|
@ -245,15 +248,18 @@ fn test_update_fee_unordered_raa() {
|
|||
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();
|
||||
|
@ -300,8 +306,7 @@ fn test_multi_flight_update_fee() {
|
|||
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 ->
|
||||
|
@ -323,8 +328,13 @@ fn test_multi_flight_update_fee() {
|
|||
// 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();
|
||||
|
@ -344,7 +354,11 @@ fn test_multi_flight_update_fee() {
|
|||
|
||||
// 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());
|
||||
|
||||
|
@ -536,11 +550,13 @@ fn test_update_fee_vanilla() {
|
|||
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();
|
||||
|
@ -582,7 +598,11 @@ fn test_update_fee_that_funder_cannot_afford() {
|
|||
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());
|
||||
|
||||
|
@ -605,7 +625,11 @@ fn test_update_fee_that_funder_cannot_afford() {
|
|||
|
||||
//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());
|
||||
|
@ -628,14 +652,16 @@ fn test_update_fee_with_fundee_update_add_htlc() {
|
|||
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();
|
||||
|
@ -743,8 +769,13 @@ fn test_update_fee() {
|
|||
// 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();
|
||||
|
@ -768,7 +799,11 @@ fn test_update_fee() {
|
|||
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);
|
||||
|
@ -6256,7 +6291,11 @@ fn test_fail_holding_cell_htlc_upon_free() {
|
|||
|
||||
// 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();
|
||||
|
@ -6330,7 +6369,11 @@ fn test_free_and_fail_holding_cell_htlcs() {
|
|||
|
||||
// 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();
|
||||
|
@ -6458,7 +6501,11 @@ fn test_fail_holding_cell_htlc_upon_free_multihop() {
|
|||
|
||||
// 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();
|
||||
|
|
|
@ -34,7 +34,11 @@ pub mod peer_channel_encryptor;
|
|||
#[cfg(not(feature = "fuzztarget"))]
|
||||
pub(crate) mod peer_channel_encryptor;
|
||||
|
||||
#[cfg(feature = "fuzztarget")]
|
||||
pub mod channel;
|
||||
#[cfg(not(feature = "fuzztarget"))]
|
||||
mod channel;
|
||||
|
||||
mod onion_utils;
|
||||
mod wire;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue