use chain::transaction::OutPoint;
use chain::chaininterface::{ChainListener, ChainWatchInterfaceUtil};
-use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor, KeysManager};
-use chain::keysinterface;
+use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor};
use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT};
use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
use ln::router::{Route, RouteHop};
use ln::msgs;
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, LocalFeatures, ErrorAction};
+use util::enforcing_trait_impls::EnforcingChannelKeys;
use util::test_utils;
use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
use util::errors::APIError;
// Instantiate channel parameters where we push the maximum msats given our
// funding satoshis
let channel_value_sat = 31337; // same as funding satoshis
- let channel_reserve_satoshis = Channel::get_our_channel_reserve_satoshis(channel_value_sat);
+ let channel_reserve_satoshis = Channel::<EnforcingChannelKeys>::get_our_channel_reserve_satoshis(channel_value_sat);
let push_msat = (channel_value_sat - channel_reserve_satoshis) * 1000;
// Have node0 initiate a channel to node1 with aforementioned parameters
let _ = nodes[0].router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id : as_chan.get_short_channel_id().unwrap(), is_permanent: false } );
- let as_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &as_chan.get_local_keys().funding_key);
- let bs_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &bs_chan.get_local_keys().funding_key);
+ let as_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &as_chan.get_local_keys().inner.funding_key);
+ let bs_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &bs_chan.get_local_keys().inner.funding_key);
let as_network_key = nodes[0].node.get_our_node_id();
let bs_network_key = nodes[1].node.get_our_node_id();
macro_rules! sign_msg {
($unsigned_msg: expr) => {
let msghash = Message::from_slice(&Sha256dHash::hash(&$unsigned_msg.encode()[..])[..]).unwrap();
- let as_bitcoin_sig = secp_ctx.sign(&msghash, &as_chan.get_local_keys().funding_key);
- let bs_bitcoin_sig = secp_ctx.sign(&msghash, &bs_chan.get_local_keys().funding_key);
+ let as_bitcoin_sig = secp_ctx.sign(&msghash, &as_chan.get_local_keys().inner.funding_key);
+ let bs_bitcoin_sig = secp_ctx.sign(&msghash, &bs_chan.get_local_keys().inner.funding_key);
let as_node_sig = secp_ctx.sign(&msghash, &nodes[0].keys_manager.get_node_secret());
let bs_node_sig = secp_ctx.sign(&msghash, &nodes[1].keys_manager.get_node_secret());
chan_announcement = msgs::ChannelAnnouncement {
let (_, nodes_0_deserialized) = {
let mut channel_monitors = HashMap::new();
channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor);
- <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+ <(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
default_config: config,
keys_manager,
fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
let (_, nodes_0_deserialized) = {
let mut channel_monitors = HashMap::new();
channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor);
- <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+ <(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
default_config: UserConfig::default(),
keys_manager,
fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
let mut nodes_0_read = &nodes_0_serialized[..];
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
- let (_, nodes_0_deserialized) = <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+ let (_, nodes_0_deserialized) = <(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
default_config: UserConfig::default(),
keys_manager,
fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
let nodes = create_network(2, &cfgs);
// We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_outbound()
- let keys_manager: Arc<KeysInterface> = Arc::new(KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new()), 10, 20));
+ let keys_manager: Arc<KeysInterface<ChanKeySigner = EnforcingChannelKeys>> = Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
if let Err(error) = Channel::new_outbound(&test_utils::TestFeeEstimator { sat_per_kw: 253 }, &keys_manager, nodes[1].node.get_our_node_id(), 1000000, 1000000, 0, Arc::new(test_utils::TestLogger::new()), &low_our_to_self_config) {
match error {
APIError::APIMisuseError { err } => { assert_eq!(err, "Configured with an unreasonable our_to_self_delay putting user funds at risks"); },
let monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone(), feeest.clone()));
let mut channel_monitors = HashMap::new();
channel_monitors.insert(OutPoint { txid: chan.3.txid(), index: 0 }, &chan_monitor);
- let node_state_0 = <(Sha256dHash, ChannelManager)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs {
- keys_manager: Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger), 42, 21)),
+ let node_state_0 = <(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs {
+ keys_manager: Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger))),
fee_estimator: feeest.clone(),
monitor: monitor.clone(),
logger: Arc::clone(&logger),
let header_132 = connect_blocks(&nodes[0].block_notifier, 3, 129, true, header_129.bitcoin_hash());
let node_txn = {
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(node_txn.len(), 3); //2 last tx : bumped claiming txn on Revoked HTLCs Txn, there is no bumped commitment tx as it's empty of claiming outpoints
+ assert_eq!(node_txn.len(), 5); // 2 bumped penalty txn on offered/received HTLC outputs of revoked commitment tx + 1 penalty tx on to_local of revoked commitment tx + 2 bumped penalty tx on revoked HTLC txn
+
+ check_spends!(node_txn[0], revoked_local_txn[0].clone());
+ check_spends!(node_txn[1], revoked_local_txn[0].clone());
let mut penalty_local = ::std::usize::MAX;
let mut penalty_offered = ::std::usize::MAX;
let mut penalty_received = ::std::usize::MAX;
- for (i, tx) in node_txn.iter().enumerate() {
- if tx.input[0].previous_output.txid == revoked_local_txn[0].txid() {
- penalty_local = i;
- } else if tx.input[0].previous_output.txid == revoked_htlc_txn[offered].txid() {
- penalty_offered = i;
- } else if tx.input[0].previous_output.txid == revoked_htlc_txn[received].txid() {
- penalty_received = i;
+ {
+ let iter_txn = node_txn[2..].iter();
+ for (i, tx) in iter_txn.enumerate() {
+ if tx.input[0].previous_output.txid == revoked_local_txn[0].txid() {
+ penalty_local = 2 + i;
+ } else if tx.input[0].previous_output.txid == revoked_htlc_txn[offered].txid() {
+ penalty_offered = 2+ i;
+ } else if tx.input[0].previous_output.txid == revoked_htlc_txn[received].txid() {
+ penalty_received = 2 + i;
+ }
}
}
check_spends!(node_txn[penalty_local], revoked_local_txn[0].clone());
let fee = revoked_htlc_txn[received].output[0].value - node_txn[penalty_received].output[0].value;
let new_feerate = fee * 1000 / node_txn[penalty_received].get_weight() as u64;
assert!(new_feerate * 100 > feerate_2 * 125);
- let txn = vec![node_txn[0].clone(), node_txn[1].clone(), node_txn[2].clone()];
+ let txn = vec![node_txn[2].clone(), node_txn[3].clone(), node_txn[4].clone()];
node_txn.clear();
txn
};
node_txn.clear();
}
}
+
+#[test]
+fn test_bump_txn_sanitize_tracking_maps() {
+ // Sanitizing pendning_claim_request and claimable_outpoints used to be buggy,
+ // verify we clean then right after expiration of ANTI_REORG_DELAY.
+
+ let nodes = create_network(2, &[None, None]);
+
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, LocalFeatures::new(), LocalFeatures::new());
+ // Lock HTLC in both directions
+ let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0;
+ route_payment(&nodes[1], &vec!(&nodes[0])[..], 9_000_000).0;
+
+ let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
+ assert_eq!(revoked_local_txn[0].input.len(), 1);
+ assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
+
+ // Revoke local commitment tx
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 9_000_000);
+
+ // Broadcast set of revoked txn on A
+ let header_128 = connect_blocks(&nodes[0].block_notifier, 128, 0, false, Default::default());
+ let header_129 = BlockHeader { version: 0x20000000, prev_blockhash: header_128, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[0].block_notifier.block_connected(&Block { header: header_129, txdata: vec![revoked_local_txn[0].clone()] }, 129);
+ check_closed_broadcast!(nodes[0]);
+ let penalty_txn = {
+ let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(node_txn.len(), 7);
+ check_spends!(node_txn[0], revoked_local_txn[0].clone());
+ check_spends!(node_txn[1], revoked_local_txn[0].clone());
+ check_spends!(node_txn[2], revoked_local_txn[0].clone());
+ let penalty_txn = vec![node_txn[0].clone(), node_txn[1].clone(), node_txn[2].clone()];
+ node_txn.clear();
+ penalty_txn
+ };
+ let header_130 = BlockHeader { version: 0x20000000, prev_blockhash: header_129.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[0].block_notifier.block_connected(&Block { header: header_130, txdata: penalty_txn }, 130);
+ connect_blocks(&nodes[0].block_notifier, 5, 130, false, header_130.bitcoin_hash());
+ {
+ let monitors = nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap();
+ if let Some(monitor) = monitors.get(&OutPoint::new(chan.3.txid(), 0)) {
+ assert!(monitor.pending_claim_requests.is_empty());
+ assert!(monitor.claimable_outpoints.is_empty());
+ }
+ }
+}