//! nodes for functional tests.
use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch, chainmonitor::Persist};
-use crate::sign::EntropySource;
use crate::chain::channelmonitor::ChannelMonitor;
use crate::chain::transaction::OutPoint;
use crate::events::{ClaimedHTLC, ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, PaymentFailureReason};
use crate::events::bump_transaction::{BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource};
use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::channelmanager::{AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, PaymentId, MIN_CLTV_EXPIRY_DELTA};
-use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate};
-use crate::routing::router::{self, PaymentParameters, Route, RouteParameters};
use crate::ln::features::InitFeatures;
use crate::ln::msgs;
-use crate::ln::msgs::{ChannelMessageHandler,RoutingMessageHandler};
-use crate::util::test_channel_signer::TestChannelSigner;
+use crate::ln::msgs::{ChannelMessageHandler, OnionMessageHandler, RoutingMessageHandler};
+use crate::ln::peer_handler::IgnoringMessageHandler;
+use crate::onion_message::messenger::OnionMessenger;
+use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate};
+use crate::routing::router::{self, PaymentParameters, Route, RouteParameters};
+use crate::sign::{EntropySource, RandomBytes};
+use crate::util::config::{UserConfig, MaxDustHTLCExposure};
+use crate::util::errors::APIError;
+#[cfg(test)]
+use crate::util::logger::Logger;
use crate::util::scid_utils;
+use crate::util::test_channel_signer::TestChannelSigner;
use crate::util::test_utils;
use crate::util::test_utils::{panicking, TestChainMonitor, TestScorer, TestKeysInterface};
-use crate::util::errors::APIError;
-use crate::util::config::{UserConfig, MaxDustHTLCExposure};
use crate::util::ser::{ReadableArgs, Writeable};
-#[cfg(test)]
-use crate::util::logger::Logger;
-use bitcoin::blockdata::block::{Block, BlockHeader};
-use bitcoin::blockdata::transaction::{Transaction, TxOut};
-use bitcoin::hash_types::BlockHash;
+use bitcoin::blockdata::block::{Block, Header, Version};
+use bitcoin::blockdata::locktime::absolute::LockTime;
+use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
+use bitcoin::hash_types::{BlockHash, TxMerkleNode};
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::Hash as _;
use bitcoin::network::constants::Network;
+use bitcoin::pow::CompactTarget;
use bitcoin::secp256k1::{PublicKey, SecretKey};
+use alloc::rc::Rc;
+use core::cell::RefCell;
+use core::iter::repeat;
+use core::mem;
+use core::ops::Deref;
use crate::io;
use crate::prelude::*;
-use core::cell::RefCell;
-use alloc::rc::Rc;
use crate::sync::{Arc, Mutex, LockTestExt, RwLock};
-use core::mem;
-use core::iter::repeat;
-use bitcoin::{PackedLockTime, TxIn, TxMerkleNode};
pub const CHAN_CONFIRM_DEPTH: u32 = 10;
pub fn mine_transaction_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
let height = node.best_block_info().1 + 1;
let mut block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: height, bits: 42, nonce: 42 },
+ header: Header {
+ version: Version::NO_SOFT_FORK_SIGNALLING,
+ prev_blockhash: node.best_block_hash(),
+ merkle_root: TxMerkleNode::all_zeros(),
+ time: height,
+ bits: CompactTarget::from_consensus(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: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() });
+ block.txdata.push(Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() });
}
block.txdata.push((*tx).clone());
do_connect_block_without_consistency_checks(node, block, false);
}
let mut 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
- txdata.push(Transaction { version: 0, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() });
+ txdata.push(Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() });
}
for tx in txn {
txdata.push((*tx).clone());
}
}
-pub fn create_dummy_header(prev_blockhash: BlockHash, time: u32) -> BlockHeader {
- BlockHeader {
- version: 0x2000_0000,
+pub fn create_dummy_header(prev_blockhash: BlockHash, time: u32) -> Header {
+ Header {
+ version: Version::NO_SOFT_FORK_SIGNALLING,
prev_blockhash,
merkle_root: TxMerkleNode::all_zeros(),
time,
- bits: 42,
+ bits: CompactTarget::from_consensus(42),
nonce: 42,
}
}
fn call_claimable_balances<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) {
// Ensure `get_claimable_balances`' self-tests never panic
- for funding_outpoint in node.chain_monitor.chain_monitor.list_monitors() {
+ for (funding_outpoint, _channel_id) in node.chain_monitor.chain_monitor.list_monitors() {
node.chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances();
}
}
pub tx_broadcaster: &'a test_utils::TestBroadcaster,
pub fee_estimator: &'a test_utils::TestFeeEstimator,
pub router: test_utils::TestRouter<'a>,
+ pub message_router: test_utils::TestMessageRouter<'a>,
pub chain_monitor: test_utils::TestChainMonitor<'a>,
pub keys_manager: &'a test_utils::TestKeysInterface,
pub logger: &'a test_utils::TestLogger,
&'chan_mon_cfg test_utils::TestLogger,
>;
+type TestOnionMessenger<'chan_man, 'node_cfg, 'chan_mon_cfg> = OnionMessenger<
+ DedicatedEntropy,
+ &'node_cfg test_utils::TestKeysInterface,
+ &'chan_mon_cfg test_utils::TestLogger,
+ &'node_cfg test_utils::TestMessageRouter<'chan_mon_cfg>,
+ &'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>,
+ IgnoringMessageHandler,
+>;
+
+/// For use with [`OnionMessenger`] otherwise `test_restored_packages_retry` will fail. This is
+/// because that test uses older serialized data produced by calling [`EntropySource`] in a specific
+/// manner. Using the same [`EntropySource`] with [`OnionMessenger`] would introduce another call,
+/// causing the produced data to no longer match.
+pub struct DedicatedEntropy(RandomBytes);
+
+impl Deref for DedicatedEntropy {
+ type Target = RandomBytes;
+ fn deref(&self) -> &Self::Target { &self.0 }
+}
+
pub struct Node<'chan_man, 'node_cfg: 'chan_man, 'chan_mon_cfg: 'node_cfg> {
pub chain_source: &'chan_mon_cfg test_utils::TestChainSource,
pub tx_broadcaster: &'chan_mon_cfg test_utils::TestBroadcaster,
pub chain_monitor: &'node_cfg test_utils::TestChainMonitor<'chan_mon_cfg>,
pub keys_manager: &'chan_mon_cfg test_utils::TestKeysInterface,
pub node: &'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>,
+ pub onion_messenger: TestOnionMessenger<'chan_man, 'node_cfg, 'chan_mon_cfg>,
pub network_graph: &'node_cfg NetworkGraph<&'chan_mon_cfg test_utils::TestLogger>,
pub gossip_sync: P2PGossipSync<&'node_cfg NetworkGraph<&'chan_mon_cfg test_utils::TestLogger>, &'chan_mon_cfg test_utils::TestChainSource, &'chan_mon_cfg test_utils::TestLogger>,
pub node_seed: [u8; 32],
&'chan_mon_cfg test_utils::TestLogger,
>,
}
+
+impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
+ pub fn init_features(&self, peer_node_id: &PublicKey) -> InitFeatures {
+ self.override_init_features.borrow().clone()
+ .unwrap_or_else(|| self.node.init_features() | self.onion_messenger.provided_init_features(peer_node_id))
+ }
+}
+
#[cfg(feature = "std")]
impl<'a, 'b, 'c> std::panic::UnwindSafe for Node<'a, 'b, 'c> {}
#[cfg(feature = "std")]
pub fn best_block_info(&self) -> (BlockHash, u32) {
self.blocks.lock().unwrap().last().map(|(a, b)| (a.block_hash(), *b)).unwrap()
}
- pub fn get_block_header(&self, height: u32) -> BlockHeader {
+ pub fn get_block_header(&self, height: u32) -> Header {
self.blocks.lock().unwrap()[height as usize].0.header
}
/// Changes the channel signer's availability for the specified peer and channel.
let feeest = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) };
let mut deserialized_monitors = Vec::new();
{
- for outpoint in self.chain_monitor.chain_monitor.list_monitors() {
+ for (outpoint, _channel_id) in self.chain_monitor.chain_monitor.list_monitors() {
let mut w = test_utils::TestVecWriter(Vec::new());
self.chain_monitor.chain_monitor.get_monitor(outpoint).unwrap().write(&mut w).unwrap();
let (_, deserialized_monitor) = <(BlockHash, ChannelMonitor<TestChannelSigner>)>::read(
node_signer: self.keys_manager,
signer_provider: self.keys_manager,
fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
- router: &test_utils::TestRouter::new(Arc::new(network_graph), &scorer),
+ router: &test_utils::TestRouter::new(Arc::new(network_graph), &self.logger, &scorer),
chain_monitor: self.chain_monitor,
tx_broadcaster: &broadcaster,
logger: &self.logger,
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(..) {
- if chain_monitor.watch_channel(deserialized_monitor.get_funding_txo().0, deserialized_monitor) != Ok(ChannelMonitorUpdateStatus::Completed) {
+ let funding_outpoint = deserialized_monitor.get_funding_txo().0;
+ if chain_monitor.watch_channel(funding_outpoint, deserialized_monitor) != Ok(ChannelMonitorUpdateStatus::Completed) {
panic!();
}
}
_ => panic!(),
}
},
- _ => panic!(),
+ &Err(PaymentSendFailure::PathParameterError(ref result)) if !$all_failed => {
+ assert_eq!(result.len(), 1);
+ match result[0] {
+ Err($type) => { $check },
+ _ => panic!(),
+ }
+ },
+ _ => {panic!()},
}
}
}
assert!(node_read.is_empty());
for monitor in monitors_read.drain(..) {
- assert_eq!(node.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor),
+ let funding_outpoint = monitor.get_funding_txo().0;
+ assert_eq!(node.chain_monitor.watch_channel(funding_outpoint, monitor),
Ok(ChannelMonitorUpdateStatus::Completed));
check_added_monitors!(node, 1);
}
$new_channelmanager = _reload_node(&$node, $new_config, &chanman_encoded, $monitors_encoded);
$node.node = &$new_channelmanager;
+ $node.onion_messenger.set_offers_handler(&$new_channelmanager);
};
($node: expr, $chanman_encoded: expr, $monitors_encoded: expr, $persister: ident, $new_chain_monitor: ident, $new_channelmanager: ident) => {
reload_node!($node, $crate::util::config::UserConfig::default(), $chanman_encoded, $monitors_encoded, $persister, $new_chain_monitor, $new_channelmanager);
Vec::new()
};
- let tx = Transaction { version: chan_id as i32, lock_time: PackedLockTime::ZERO, input, output: vec![TxOut {
+ let tx = Transaction { version: chan_id as i32, lock_time: LockTime::ZERO, input, output: vec![TxOut {
value: *channel_value_satoshis, script_pubkey: output_script.clone(),
}]};
let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 };
(tx, as_channel_ready.channel_id)
}
-pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> Transaction {
+pub fn exchange_open_accept_chan<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> ChannelId {
let create_chan_id = node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None).unwrap();
let open_channel_msg = get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id());
assert_eq!(open_channel_msg.temporary_channel_id, create_chan_id);
node_a.node.handle_accept_channel(&node_b.node.get_our_node_id(), &accept_channel_msg);
assert_ne!(node_b.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 0);
+ create_chan_id
+}
+
+pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> Transaction {
+ let create_chan_id = exchange_open_accept_chan(node_a, node_b, channel_value, push_msat);
sign_funding_transaction(node_a, node_b, channel_value, create_chan_id)
}
for output in tx.output.iter() {
total_value_out += output.value;
}
- let min_fee = (tx.weight() as u64 + 3) / 4; // One sat per vbyte (ie per weight/4, rounded up)
+ let min_fee = (tx.weight().to_wu() as u64 + 3) / 4; // One sat per vbyte (ie per weight/4, rounded up)
// Input amount - output amount = fee, so check that out + min_fee is smaller than input
assert!(total_value_out + min_fee <= total_value_in);
tx.verify(get_output).unwrap();
pub counterparty_node_id: Option<PublicKey>,
pub discard_funding: bool,
pub reason: Option<ClosureReason>,
+ pub channel_funding_txo: Option<OutPoint>,
+ pub user_channel_id: Option<u128>,
+}
+
+impl ExpectedCloseEvent {
+ pub fn from_id_reason(channel_id: ChannelId, discard_funding: bool, reason: ClosureReason) -> Self {
+ Self {
+ channel_capacity_sats: None,
+ channel_id: Some(channel_id),
+ counterparty_node_id: None,
+ discard_funding,
+ reason: Some(reason),
+ channel_funding_txo: None,
+ user_channel_id: None,
+ }
+ }
}
/// Check that multiple channel closing events have been issued.
reason,
counterparty_node_id,
channel_capacity_sats,
+ channel_funding_txo,
+ user_channel_id,
..
} if (
expected_event.channel_id.map(|expected| *channel_id == expected).unwrap_or(true) &&
expected_event.reason.as_ref().map(|expected| reason == expected).unwrap_or(true) &&
- expected_event.counterparty_node_id.map(|expected| *counterparty_node_id == Some(expected)).unwrap_or(true) &&
- expected_event.channel_capacity_sats.map(|expected| *channel_capacity_sats == Some(expected)).unwrap_or(true)
+ expected_event.
+ counterparty_node_id.map(|expected| *counterparty_node_id == Some(expected)).unwrap_or(true) &&
+ expected_event.channel_capacity_sats
+ .map(|expected| *channel_capacity_sats == Some(expected)).unwrap_or(true) &&
+ expected_event.channel_funding_txo
+ .map(|expected| *channel_funding_txo == Some(expected)).unwrap_or(true) &&
+ expected_event.user_channel_id
+ .map(|expected| *user_channel_id == expected).unwrap_or(true)
)
)));
}
counterparty_node_id: Some(*node_id),
discard_funding: is_check_discard_funding,
reason: Some(expected_reason.clone()),
+ channel_funding_txo: None,
+ user_channel_id: None,
}).collect::<Vec<_>>();
check_closed_events(node, expected_close_events.as_slice());
}
let mut payment_count = recipient.network_payment_count.borrow_mut();
let payment_preimage = PaymentPreimage([*payment_count; 32]);
*payment_count += 1;
- let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
+ let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array());
let payment_secret = recipient.node.create_inbound_payment_for_hash(payment_hash, min_value_msat, 7200, min_final_cltv_expiry_delta).unwrap();
(payment_preimage, payment_hash, payment_secret)
}
)
}
+/// Like `get_route` above, but adds a random CLTV offset to the final hop.
+pub fn find_route(send_node: &Node, route_params: &RouteParameters) -> Result<Route, msgs::LightningError> {
+ let scorer = TestScorer::new();
+ let keys_manager = TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
+ let random_seed_bytes = keys_manager.get_secure_random_bytes();
+ router::find_route(
+ &send_node.node.get_our_node_id(), route_params, &send_node.network_graph,
+ Some(&send_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
+ send_node.logger, &scorer, &Default::default(), &random_seed_bytes
+ )
+}
+
/// Gets a route from the given sender to the node described in `payment_params`.
///
/// Don't use this, use the identically-named function instead.
) {
let events = node.node().get_and_clear_pending_events();
let expected_payment_hash = PaymentHash(
- bitcoin::hashes::sha256::Hash::hash(&expected_payment_preimage.0).into_inner());
+ bitcoin::hashes::sha256::Hash::hash(&expected_payment_preimage.0).to_byte_array());
if expect_per_path_claims {
assert!(events.len() > 1);
} else {
pub fn expect_payment_forwarded<CM: AChannelManager, H: NodeHolder<CM=CM>>(
event: Event, node: &H, prev_node: &H, next_node: &H, expected_fee: Option<u64>,
- upstream_force_closed: bool, downstream_force_closed: bool
+ expected_extra_fees_msat: Option<u64>, upstream_force_closed: bool,
+ downstream_force_closed: bool
) {
match event {
Event::PaymentForwarded {
- fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id,
- outbound_amount_forwarded_msat: _
+ total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id,
+ outbound_amount_forwarded_msat: _, skimmed_fee_msat
} => {
- assert_eq!(fee_earned_msat, expected_fee);
+ assert_eq!(total_fee_earned_msat, expected_fee);
+
+ // Check that the (knowingly) withheld amount is always less or equal to the expected
+ // overpaid amount.
+ assert!(skimmed_fee_msat == expected_extra_fees_msat);
if !upstream_force_closed {
// Is the event prev_channel_id in one of the channels between the two nodes?
assert!(node.node().list_channels().iter().any(|x| x.counterparty.node_id == prev_node.node().get_our_node_id() && x.channel_id == prev_channel_id.unwrap()));
}
}
+#[macro_export]
macro_rules! expect_payment_forwarded {
($node: expr, $prev_node: expr, $next_node: expr, $expected_fee: expr, $upstream_force_closed: expr, $downstream_force_closed: expr) => {
let mut events = $node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
$crate::ln::functional_test_utils::expect_payment_forwarded(
- events.pop().unwrap(), &$node, &$prev_node, &$next_node, $expected_fee,
- $upstream_force_closed, $downstream_force_closed);
+ events.pop().unwrap(), &$node, &$prev_node, &$next_node, $expected_fee, None,
+ $upstream_force_closed, $downstream_force_closed
+ );
}
}
origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool,
our_payment_preimage: PaymentPreimage
) -> u64 {
- let extra_fees = vec![0; expected_paths.len()];
- do_claim_payment_along_route_with_extra_penultimate_hop_fees(origin_node, expected_paths,
- &extra_fees[..], skip_last, our_payment_preimage)
-}
-
-pub fn do_claim_payment_along_route_with_extra_penultimate_hop_fees<'a, 'b, 'c>(
- origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], expected_extra_fees:
- &[u32], skip_last: bool, our_payment_preimage: PaymentPreimage
-) -> u64 {
- assert_eq!(expected_paths.len(), expected_extra_fees.len());
for path in expected_paths.iter() {
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.claim_funds(our_payment_preimage);
- pass_claimed_payment_along_route(origin_node, expected_paths, expected_extra_fees, skip_last, our_payment_preimage)
+ pass_claimed_payment_along_route(
+ ClaimAlongRouteArgs::new(origin_node, expected_paths, our_payment_preimage)
+ .skip_last(skip_last)
+ )
}
-pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], expected_extra_fees: &[u32], skip_last: bool, our_payment_preimage: PaymentPreimage) -> u64 {
+pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
+ pub origin_node: &'a Node<'b, 'c, 'd>,
+ pub expected_paths: &'a [&'a [&'a Node<'b, 'c, 'd>]],
+ pub expected_extra_fees: Vec<u32>,
+ pub expected_min_htlc_overpay: Vec<u32>,
+ pub skip_last: bool,
+ pub payment_preimage: PaymentPreimage,
+}
+
+impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
+ pub fn new(
+ origin_node: &'a Node<'b, 'c, 'd>, expected_paths: &'a [&'a [&'a Node<'b, 'c, 'd>]],
+ payment_preimage: PaymentPreimage,
+ ) -> Self {
+ Self {
+ origin_node, expected_paths, expected_extra_fees: vec![0; expected_paths.len()],
+ expected_min_htlc_overpay: vec![0; expected_paths.len()], skip_last: false, payment_preimage,
+ }
+ }
+ pub fn skip_last(mut self, skip_last: bool) -> Self {
+ self.skip_last = skip_last;
+ self
+ }
+ pub fn with_expected_extra_fees(mut self, extra_fees: Vec<u32>) -> Self {
+ self.expected_extra_fees = extra_fees;
+ self
+ }
+ pub fn with_expected_min_htlc_overpay(mut self, extra_fees: Vec<u32>) -> Self {
+ self.expected_min_htlc_overpay = extra_fees;
+ self
+ }
+}
+
+pub fn pass_claimed_payment_along_route<'a, 'b, 'c, 'd>(args: ClaimAlongRouteArgs) -> u64 {
+ let ClaimAlongRouteArgs {
+ origin_node, expected_paths, expected_extra_fees, expected_min_htlc_overpay, skip_last,
+ payment_preimage: our_payment_preimage
+ } = args;
let claim_event = expected_paths[0].last().unwrap().node.get_and_clear_pending_events();
assert_eq!(claim_event.len(), 1);
match claim_event[0] {
channel.context().config().forwarding_fee_base_msat
}
};
- if $idx == 1 { fee += expected_extra_fees[i]; }
- expect_payment_forwarded!(*$node, $next_node, $prev_node, Some(fee as u64), false, false);
+
+ let mut expected_extra_fee = None;
+ if $idx == 1 {
+ fee += expected_extra_fees[i];
+ fee += expected_min_htlc_overpay[i];
+ expected_extra_fee = if expected_extra_fees[i] > 0 { Some(expected_extra_fees[i] as u64) } else { None };
+ }
+ let mut events = $node.node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ expect_payment_forwarded(events.pop().unwrap(), *$node, $next_node, $prev_node,
+ Some(fee as u64), expected_extra_fee, false, false);
expected_total_fee_msat += fee as u64;
check_added_monitors!($node, 1);
let new_next_msgs = if $new_msgs {
logger: &chanmon_cfgs[i].logger,
tx_broadcaster: &chanmon_cfgs[i].tx_broadcaster,
fee_estimator: &chanmon_cfgs[i].fee_estimator,
- router: test_utils::TestRouter::new(network_graph.clone(), &chanmon_cfgs[i].scorer),
+ router: test_utils::TestRouter::new(network_graph.clone(), &chanmon_cfgs[i].logger, &chanmon_cfgs[i].scorer),
+ message_router: test_utils::TestMessageRouter::new(network_graph.clone()),
chain_monitor,
keys_manager: &chanmon_cfgs[i].keys_manager,
node_seed: seed,
let connect_style = Rc::new(RefCell::new(ConnectStyle::random_style()));
for i in 0..node_count {
+ let dedicated_entropy = DedicatedEntropy(RandomBytes::new([i as u8; 32]));
+ let onion_messenger = OnionMessenger::new(
+ dedicated_entropy, cfgs[i].keys_manager, cfgs[i].logger, &cfgs[i].message_router,
+ &chan_mgrs[i], IgnoringMessageHandler {},
+ );
let gossip_sync = P2PGossipSync::new(cfgs[i].network_graph.as_ref(), None, cfgs[i].logger);
let wallet_source = Arc::new(test_utils::TestWalletSource::new(SecretKey::from_slice(&[i as u8 + 1; 32]).unwrap()));
nodes.push(Node{
fee_estimator: cfgs[i].fee_estimator, router: &cfgs[i].router,
chain_monitor: &cfgs[i].chain_monitor, keys_manager: &cfgs[i].keys_manager,
node: &chan_mgrs[i], network_graph: cfgs[i].network_graph.as_ref(), gossip_sync,
- node_seed: cfgs[i].node_seed, network_chan_count: chan_count.clone(),
+ node_seed: cfgs[i].node_seed, onion_messenger, network_chan_count: chan_count.clone(),
network_payment_count: payment_count.clone(), logger: cfgs[i].logger,
blocks: Arc::clone(&cfgs[i].tx_broadcaster.blocks),
connect_style: Rc::clone(&connect_style),
for i in 0..node_count {
for j in (i+1)..node_count {
- nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &msgs::Init {
- features: nodes[j].override_init_features.borrow().clone().unwrap_or_else(|| nodes[j].node.init_features()),
+ let node_id_i = nodes[i].node.get_our_node_id();
+ let node_id_j = nodes[j].node.get_our_node_id();
+
+ let init_i = msgs::Init {
+ features: nodes[i].init_features(&node_id_j),
networks: None,
remote_network_address: None,
- }, true).unwrap();
- nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &msgs::Init {
- features: nodes[i].override_init_features.borrow().clone().unwrap_or_else(|| nodes[i].node.init_features()),
+ };
+ let init_j = msgs::Init {
+ features: nodes[j].init_features(&node_id_i),
networks: None,
remote_network_address: None,
- }, false).unwrap();
+ };
+
+ nodes[i].node.peer_connected(&node_id_j, &init_j, true).unwrap();
+ nodes[j].node.peer_connected(&node_id_i, &init_i, false).unwrap();
+ nodes[i].onion_messenger.peer_connected(&node_id_j, &init_j, true).unwrap();
+ nodes[j].onion_messenger.peer_connected(&node_id_i, &init_i, false).unwrap();
}
}
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 != 0);
+ assert_ne!(tx.lock_time, LockTime::ZERO);
} else {
- assert!(tx.lock_time.0 == 0);
+ assert_eq!(tx.lock_time, LockTime::ZERO);
}
res.push(tx.clone());
false
// Compose the batch funding transaction and give it to the ChannelManager.
let tx = Transaction {
version: 2,
- lock_time: PackedLockTime::ZERO,
+ lock_time: LockTime::ZERO,
input: Vec::new(),
output: tx_outs,
};