use util::scid_utils;
use util::test_utils;
use util::test_utils::{panicking, TestChainMonitor};
-use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose};
+use util::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose};
use util::errors::APIError;
use util::config::UserConfig;
use util::ser::{ReadableArgs, Writeable};
use alloc::rc::Rc;
use sync::{Arc, Mutex};
use core::mem;
+use core::iter::repeat;
+use bitcoin::{PackedLockTime, TxMerkleNode};
pub const CHAN_CONFIRM_DEPTH: u32 = 10;
connect_blocks(node, conf_height - first_connect_height);
}
let mut block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: conf_height, bits: 42, nonce: 42 },
+ header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: conf_height, bits: 42, nonce: 42 },
txdata: Vec::new(),
};
for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count
- block.txdata.push(Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() });
+ block.txdata.push(Transaction { version: 0, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() });
}
block.txdata.push(tx.clone());
connect_block(node, &block);
let height = node.best_block_info().1 + 1;
let mut block = Block {
- header: BlockHeader { version: 0x2000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: height, bits: 42, nonce: 42 },
+ header: BlockHeader { version: 0x2000000, prev_blockhash: node.best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: height, bits: 42, nonce: 42 },
txdata: vec![],
};
assert!(depth >= 1);
let prev_blockhash = block.header.block_hash();
do_connect_block(node, block, skip_intermediaries);
block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash, merkle_root: Default::default(), time: height + i, bits: 42, nonce: 42 },
+ header: BlockHeader { version: 0x20000000, prev_blockhash, merkle_root: TxMerkleNode::all_zeros(), time: height + i, bits: 42, nonce: 42 },
txdata: vec![],
};
}
);
let mut chan_progress = 0;
loop {
- let orig_announcements = self.gossip_sync.get_next_channel_announcements(chan_progress, 255);
- let deserialized_announcements = gossip_sync.get_next_channel_announcements(chan_progress, 255);
+ let orig_announcements = self.gossip_sync.get_next_channel_announcement(chan_progress);
+ let deserialized_announcements = gossip_sync.get_next_channel_announcement(chan_progress);
assert!(orig_announcements == deserialized_announcements);
- chan_progress = match orig_announcements.last() {
+ chan_progress = match orig_announcements {
Some(announcement) => announcement.0.contents.short_channel_id + 1,
None => break,
};
}
let mut node_progress = None;
loop {
- let orig_announcements = self.gossip_sync.get_next_node_announcements(node_progress.as_ref(), 255);
- let deserialized_announcements = gossip_sync.get_next_node_announcements(node_progress.as_ref(), 255);
+ let orig_announcements = self.gossip_sync.get_next_node_announcement(node_progress.as_ref());
+ let deserialized_announcements = gossip_sync.get_next_node_announcement(node_progress.as_ref());
assert!(orig_announcements == deserialized_announcements);
- node_progress = match orig_announcements.last() {
+ node_progress = match orig_announcements {
Some(announcement) => Some(announcement.contents.node_id),
None => break,
};
}
}
+ let broadcaster = test_utils::TestBroadcaster {
+ txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()),
+ blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())),
+ };
+
// Before using all the new monitors to check the watch outpoints, use the full set of
// them to ensure we can write and reload our ChannelManager.
{
keys_manager: self.keys_manager,
fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
chain_monitor: self.chain_monitor,
- tx_broadcaster: &test_utils::TestBroadcaster {
- txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()),
- blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())),
- },
+ tx_broadcaster: &broadcaster,
logger: &self.logger,
channel_monitors,
}).unwrap();
}
let persister = test_utils::TestPersister::new();
- let broadcaster = test_utils::TestBroadcaster {
- txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()),
- blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())),
- };
let chain_source = test_utils::TestChainSource::new(Network::Testnet);
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chain_source), &broadcaster, &self.logger, &feeest, &persister, &self.keys_manager);
for deserialized_monitor in deserialized_monitors.drain(..) {
assert_eq!(*channel_value_satoshis, expected_chan_value);
assert_eq!(user_channel_id, expected_user_chan_id);
- let tx = Transaction { version: chan_id as i32, lock_time: 0, input: Vec::new(), output: vec![TxOut {
+ let tx = Transaction { version: chan_id as i32, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: vec![TxOut {
value: *channel_value_satoshis, script_pubkey: output_script.clone(),
}]};
let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 };
{
$(
for outp in $spends_txn.output.iter() {
- assert!(outp.value >= outp.script_pubkey.dust_value().as_sat(), "Input tx output didn't meet dust limit");
+ assert!(outp.value >= outp.script_pubkey.dust_value().to_sat(), "Input tx output didn't meet dust limit");
}
)*
for outp in $tx.output.iter() {
- assert!(outp.value >= outp.script_pubkey.dust_value().as_sat(), "Spending tx output didn't meet dust limit");
+ assert!(outp.value >= outp.script_pubkey.dust_value().to_sat(), "Spending tx output didn't meet dust limit");
}
let get_output = |out_point: &bitcoin::blockdata::transaction::OutPoint| {
$(
{
commitment_signed_dance!($node_a, $node_b, $commitment_signed, $fail_backwards, true);
if $fail_backwards {
- $crate::expect_pending_htlcs_forwardable!($node_a);
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed!($node_a, vec![$crate::util::events::HTLCDestination::NextHopChannel{ node_id: Some($node_b.node.get_our_node_id()), channel_id: $commitment_signed.channel_id }]);
check_added_monitors!($node_a, 1);
let channel_state = $node_a.node.channel_state.lock().unwrap();
}
#[macro_export]
-/// Clears (and ignores) a PendingHTLCsForwardable event
-macro_rules! expect_pending_htlcs_forwardable_ignore {
- ($node: expr) => {{
+macro_rules! expect_pending_htlcs_forwardable_conditions {
+ ($node: expr, $expected_failures: expr) => {{
+ let expected_failures = $expected_failures;
let events = $node.node.get_and_clear_pending_events();
- assert_eq!(events.len(), 1);
match events[0] {
$crate::util::events::Event::PendingHTLCsForwardable { .. } => { },
_ => panic!("Unexpected event"),
};
+
+ let count = expected_failures.len() + 1;
+ assert_eq!(events.len(), count);
+
+ if expected_failures.len() > 0 {
+ expect_htlc_handling_failed_destinations!(events, expected_failures)
+ }
+ }}
+}
+
+#[macro_export]
+macro_rules! expect_htlc_handling_failed_destinations {
+ ($events: expr, $expected_failures: expr) => {{
+ for event in $events {
+ match event {
+ $crate::util::events::Event::PendingHTLCsForwardable { .. } => { },
+ $crate::util::events::Event::HTLCHandlingFailed { ref failed_next_destination, .. } => {
+ assert!($expected_failures.contains(&failed_next_destination))
+ },
+ _ => panic!("Unexpected destination"),
+ }
+ }
}}
}
+#[macro_export]
+/// Clears (and ignores) a PendingHTLCsForwardable event
+macro_rules! expect_pending_htlcs_forwardable_ignore {
+ ($node: expr) => {{
+ expect_pending_htlcs_forwardable_conditions!($node, vec![]);
+ }};
+}
+
+#[macro_export]
+/// Clears (and ignores) PendingHTLCsForwardable and HTLCHandlingFailed events
+macro_rules! expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore {
+ ($node: expr, $expected_failures: expr) => {{
+ expect_pending_htlcs_forwardable_conditions!($node, $expected_failures);
+ }};
+}
+
#[macro_export]
/// Handles a PendingHTLCsForwardable event
macro_rules! expect_pending_htlcs_forwardable {
($node: expr) => {{
- $crate::expect_pending_htlcs_forwardable_ignore!($node);
+ expect_pending_htlcs_forwardable_ignore!($node);
+ $node.node.process_pending_htlc_forwards();
+
+ // Ensure process_pending_htlc_forwards is idempotent.
+ $node.node.process_pending_htlc_forwards();
+ }};
+}
+
+#[macro_export]
+/// Handles a PendingHTLCsForwardable and HTLCHandlingFailed event
+macro_rules! expect_pending_htlcs_forwardable_and_htlc_handling_failed {
+ ($node: expr, $expected_failures: expr) => {{
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!($node, $expected_failures);
$node.node.process_pending_htlc_forwards();
// Ensure process_pending_htlc_forwards is idempotent.
};
}
-pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>(
- node: &'a Node<'b, 'c, 'd>, expected_payment_hash: PaymentHash, expected_rejected_by_dest: bool,
- conditions: PaymentFailedConditions<'e>
+pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
+ node: &'a Node<'b, 'c, 'd>, payment_failed_event: Event, expected_payment_hash: PaymentHash,
+ expected_rejected_by_dest: bool, conditions: PaymentFailedConditions<'e>
) {
- let mut events = node.node.get_and_clear_pending_events();
- assert_eq!(events.len(), 1);
- let expected_payment_id = match events.pop().unwrap() {
+ let expected_payment_id = match payment_failed_event {
Event::PaymentPathFailed { payment_hash, rejected_by_dest, path, retry, payment_id, network_update, short_channel_id,
#[cfg(test)]
error_code,
}
}
+pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>(
+ node: &'a Node<'b, 'c, 'd>, expected_payment_hash: PaymentHash, expected_rejected_by_dest: bool,
+ conditions: PaymentFailedConditions<'e>
+) {
+ let mut events = node.node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ expect_payment_failed_conditions_event(node, events.pop().unwrap(), expected_payment_hash, expected_rejected_by_dest, conditions);
+}
+
pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_paths: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret) -> PaymentId {
let payment_id = origin_node.node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(origin_node, expected_paths.len());
assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id());
}
expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash);
- expect_pending_htlcs_forwardable!(expected_paths[0].last().unwrap());
+ let expected_destinations: Vec<HTLCDestination> = repeat(HTLCDestination::FailedPayment { payment_hash: our_payment_hash }).take(expected_paths.len()).collect();
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed!(expected_paths[0].last().unwrap(), expected_destinations);
pass_failed_payment_back(origin_node, expected_paths, skip_last, our_payment_hash);
}
node.node.handle_update_fail_htlc(&prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0);
commitment_signed_dance!(node, prev_node, next_msgs.as_ref().unwrap().1, update_next_node);
if !update_next_node {
- expect_pending_htlcs_forwardable!(node);
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed!(node, vec![HTLCDestination::NextHopChannel { node_id: Some(prev_node.node.get_our_node_id()), channel_id: next_msgs.as_ref().unwrap().0.channel_id }]);
}
}
let events = node.node.get_and_clear_pending_msg_events();
if tx.input.len() == 1 && tx.input[0].previous_output.txid == res[0].txid() {
check_spends!(tx, res[0]);
if has_htlc_tx == HTLCType::TIMEOUT {
- assert!(tx.lock_time != 0);
+ assert!(tx.lock_time.0 != 0);
} else {
- assert!(tx.lock_time == 0);
+ assert!(tx.lock_time.0 == 0);
}
res.push(tx.clone());
false